diff --git a/Makefile b/Makefile
index ce25268..2778a73 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ EXT=dylib
SERVER=plugin_manager.o ini.o http_server.o plugins/dictionary.o plugins/utils.o
SERVERLIB=-lpthread -ldl
#-lsocket
-PLUGINS= dummy.$(EXT) fileman.$(EXT) pluginsman.$(EXT)
+PLUGINS= dummy.$(EXT) fileman.$(EXT) pluginsman.$(EXT) wterm.$(EXT)
PLUGINSDEP = plugins/plugin.o plugins/dbhelper.o plugins/dictionary.o plugins/utils.o plugins/list.o
PLUGINLIBS = -lsqlite3
diff --git a/build/htdocs/index.html b/build/htdocs/index.html
index 9be0adc..de4872c 100644
--- a/build/htdocs/index.html
+++ b/build/htdocs/index.html
@@ -1,12 +1,14 @@
-
+
+
+
diff --git a/build/htdocs/scripts/camviewer.js b/build/htdocs/scripts/camviewer.js
index 8369770..be73550 100644
--- a/build/htdocs/scripts/camviewer.js
+++ b/build/htdocs/scripts/camviewer.js
@@ -1,3 +1,4 @@
+
var picam_config = {
name: 'picam_layout',
toolbar:{
diff --git a/build/htdocs/scripts/sidebar.js b/build/htdocs/scripts/sidebar.js
index e42cdf1..ef93fec 100644
--- a/build/htdocs/scripts/sidebar.js
+++ b/build/htdocs/scripts/sidebar.js
@@ -14,7 +14,8 @@ var sidebar_config = {
text: 'Plugins',
icon: 'fa-cogs'
},
- { id: 'level-fman', text: 'File manager', icon: 'fa-folder-open' }
+ { id: 'level-fman', text: 'File manager', icon: 'fa-folder-open' },
+ { id: 'level-wterm', text: 'Terminal', icon: 'fa-wrench' }
]
},
{
@@ -47,6 +48,9 @@ var sidebar_config = {
case 'level-picam':
w2ui.layout.content('main', w2ui.picam_layout);
break;
+ case 'level-wterm':
+ w2ui.layout.content('main', w2ui.wterm_layout);
+ break;
default: //do nothing
w2ui.layout.content('main',"Empty page");
console.log('Event: ' + event.type + ' Target: ' + event.target);
diff --git a/build/htdocs/scripts/wterm.js b/build/htdocs/scripts/wterm.js
new file mode 100644
index 0000000..3dbfcbb
--- /dev/null
+++ b/build/htdocs/scripts/wterm.js
@@ -0,0 +1,245 @@
+/*! terminal.js v2.0 | (c) 2014 Erik Österberg | https://github.com/eosterberg/terminaljs */
+
+var Terminal = (function () {
+ // PROMPT_TYPE
+ var PROMPT_INPUT = 1, PROMPT_PASSWORD = 2, PROMPT_CONFIRM = 3
+
+ var fireCursorInterval = function (inputField, terminalObj) {
+ var cursor = terminalObj._cursor
+ setTimeout(function () {
+ if (inputField.parentElement && terminalObj._shouldBlinkCursor) {
+ cursor.style.visibility = cursor.style.visibility === 'visible' ? 'hidden' : 'visible'
+ fireCursorInterval(inputField, terminalObj)
+ } else {
+ cursor.style.visibility = 'visible'
+ }
+ }, 500)
+ }
+
+ var firstPrompt = true;
+ promptInput = function (terminalObj, message, PROMPT_TYPE, callback) {
+ var shouldDisplayInput = (PROMPT_TYPE === PROMPT_INPUT)
+ var inputField = document.createElement('input')
+
+ inputField.style.position = 'absolute'
+ inputField.style.zIndex = '-100'
+ inputField.style.outline = 'none'
+ inputField.style.border = 'none'
+ inputField.style.opacity = '0'
+ inputField.style.fontSize = '0.2em'
+
+ terminalObj._inputLine.textContent = ''
+ terminalObj._input.style.display = 'block'
+ terminalObj.html.appendChild(inputField)
+ fireCursorInterval(inputField, terminalObj)
+
+ if (message.length) terminalObj.msg(PROMPT_TYPE === PROMPT_CONFIRM ? message + ' (y/n)' : message)
+
+ inputField.onblur = function () {
+ terminalObj._cursor.style.display = 'none'
+ }
+
+ inputField.onfocus = function () {
+ inputField.value = terminalObj._inputLine.textContent
+ terminalObj._cursor.style.display = 'inline'
+ }
+
+ terminalObj.html.onclick = function () {
+ inputField.focus()
+ }
+
+ inputField.onkeydown = function (e) {
+ if (e.which === 37 || e.which === 39 || e.which === 38 || e.which === 40 || e.which === 9) {
+ e.preventDefault()
+ } else if (shouldDisplayInput && e.which !== 13) {
+ setTimeout(function () {
+ terminalObj._inputLine.textContent = inputField.value
+ }, 1)
+ }
+ }
+ inputField.onkeyup = function (e) {
+ if (PROMPT_TYPE === PROMPT_CONFIRM || e.which === 13) {
+ terminalObj._input.style.display = 'none'
+ var inputValue = inputField.value
+ if (shouldDisplayInput) terminalObj._print(message+inputValue,"wterm_input_div")
+ terminalObj.html.removeChild(inputField)
+ if (typeof(callback) === 'function') {
+ if (PROMPT_TYPE === PROMPT_CONFIRM) {
+ callback(inputValue.toUpperCase()[0] === 'Y' ? true : false)
+ } else callback(inputValue)
+ }
+ }
+ }
+ if (firstPrompt) {
+ firstPrompt = false
+ setTimeout(function () { inputField.focus() }, 50)
+ } else {
+ inputField.focus()
+ }
+ }
+
+ var terminalBeep
+
+ var TerminalConstructor = function (id) {
+ if (!terminalBeep) {
+ terminalBeep = document.createElement('audio')
+ var source = '' + source + 'ogg" type="audio/ogg">'
+ terminalBeep.volume = 0.05
+ }
+
+ this.html = document.createElement('div')
+ this.html.className = 'Terminal'
+ if (typeof(id) === 'string') { this.html.id = id }
+
+ this._innerWindow = document.createElement('div')
+ this._output = document.createElement('p')
+ this._inputLine = document.createElement('span') //the span element where the users input is put
+ this._cursor = document.createElement('span')
+ this._input = document.createElement('p') //the full element administering the user input, including cursor
+ this._input.className = "wterm_input_p"
+ this._cursor.className = "wterm_cursor"
+ //this._output.className = "wterm_output_p"
+ this._input.appendChild(document.createElement('span'));
+ this._shouldBlinkCursor = true
+
+ this.beep = function () {
+ terminalBeep.load()
+ terminalBeep.play()
+ }
+ this.msg = function (message) {
+ this._input.firstChild.textContent = message
+ }
+ this._print = function(msg,cls)
+ {
+ var newLine = document.createElement('div')
+ newLine.className = cls
+ newLine.textContent = msg
+ this._output.appendChild(newLine)
+ }
+ this.print = function (message) {
+ this._print(message,"wterm_output_div")
+ }
+
+ this.input = function (message, callback) {
+ promptInput(this, message, PROMPT_INPUT, callback)
+ }
+
+ this.password = function (message, callback) {
+ promptInput(this, message, PROMPT_PASSWORD, callback)
+ }
+
+ this.confirm = function (message, callback) {
+ promptInput(this, message, PROMPT_CONFIRM, callback)
+ }
+
+ this.clear = function () {
+ this._output.innerHTML = ''
+ }
+
+ this.sleep = function (milliseconds, callback) {
+ setTimeout(callback, milliseconds)
+ }
+
+ this.setTextSize = function (size) {
+ this._output.style.fontSize = size
+ this._input.style.fontSize = size
+ }
+
+ this.setTextColor = function (col) {
+ this.html.style.color = col
+ this._cursor.style.background = col
+ }
+
+ this.setBackgroundColor = function (col) {
+ this.html.style.background = col
+ }
+
+ this.setWidth = function (width) {
+ this.html.style.width = width
+ }
+
+ this.setHeight = function (height) {
+ this.html.style.height = height
+ }
+
+ this.blinkingCursor = function (bool) {
+ bool = bool.toString().toUpperCase()
+ this._shouldBlinkCursor = (bool === 'TRUE' || bool === '1' || bool === 'YES')
+ }
+
+ this._input.appendChild(this._inputLine)
+ this._input.appendChild(this._cursor)
+ this._innerWindow.appendChild(this._output)
+ this._innerWindow.appendChild(this._input)
+ this.html.appendChild(this._innerWindow)
+
+ this.setBackgroundColor('black')
+ this.setTextColor('white')
+ this.setTextSize('1em')
+ this.setWidth('100%')
+ this.setHeight('100%')
+
+ this.html.style.fontFamily = 'Monaco, Courier'
+ this.html.style.margin = '0'
+ this._innerWindow.style.padding = '10px'
+ this._input.style.margin = '0'
+ this._output.style.margin = '0'
+ this._cursor.style.background = '#00cc00'
+ this._cursor.innerHTML = 'C' //put something in the cursor..
+ this._cursor.style.display = 'none' //then hide it
+ this._input.style.display = 'none'
+ }
+
+ return TerminalConstructor
+}());
+var wtermobj;
+
+var wterm_config = {
+ name: 'wterm_layout',
+ panels: [
+ {
+ type: 'main',
+ style: 'padding: 0px;',
+ content: ''
+ }
+ ],
+ onRefresh:function(event)
+ {
+ if($("#wterm_input") )
+ {
+ wtermobj = new Terminal();
+ wtermobj.setTextSize(11);
+ var nest_callback = function(data)
+ {
+ if(data.length>0)
+ {
+ //send to server
+ var webtty = new EventSource('/wterm?cmd='+data);
+ webtty.onmessage = function (e) {
+ wtermobj.print(e.data);
+ var par = $("#wterm");
+ par.animate({
+ scrollTop: par.get(0).scrollHeight
+ }, 0);
+ };
+ webtty.onerror = function(e)
+ {
+ // finish the command
+ webtty.close();
+ wtermobj.input("antd> ",nest_callback);
+ }
+ }
+ else
+ {
+ wtermobj.input("antd> ",nest_callback);
+ }
+ };
+ $("#wterm").html(wtermobj.html);
+ $("#wterm").parent().css("overflow","hidden");
+ $("#wterm").parent().css("background-color","black");
+ wtermobj.input("antd> ",nest_callback);
+ }
+ }
+}
+$().w2layout(wterm_config);
diff --git a/build/htdocs/style/site.css b/build/htdocs/style/site.css
new file mode 100644
index 0000000..ba6325d
--- /dev/null
+++ b/build/htdocs/style/site.css
@@ -0,0 +1,21 @@
+#wterm {
+ width:100%;
+ height: 100%;
+ background-color:black;
+ position:absolute;
+ overflow:auto;
+}
+.wterm_output_div{
+ padding-left:15px;
+}
+.wterm_input_div
+{
+ color:#00cc00;
+}
+.wterm_input_p{
+ color:#00cc00;
+}
+.wterm_cursor{
+ color:#00cc00;
+ background-color:#00cc00;
+}
\ No newline at end of file
diff --git a/build/httpd b/build/httpd
index c679977..1cdc37f 100755
Binary files a/build/httpd and b/build/httpd differ
diff --git a/build/plugins/dummy.dylib b/build/plugins/dummy.dylib
index 9294138..6ac1b7d 100755
Binary files a/build/plugins/dummy.dylib and b/build/plugins/dummy.dylib differ
diff --git a/build/plugins/fileman.dylib b/build/plugins/fileman.dylib
index 8100897..846c316 100755
Binary files a/build/plugins/fileman.dylib and b/build/plugins/fileman.dylib differ
diff --git a/build/plugins/pluginsman.dylib b/build/plugins/pluginsman.dylib
index 1c53b48..208c682 100755
Binary files a/build/plugins/pluginsman.dylib and b/build/plugins/pluginsman.dylib differ
diff --git a/build/plugins/wterm.dylib b/build/plugins/wterm.dylib
new file mode 100755
index 0000000..b534109
Binary files /dev/null and b/build/plugins/wterm.dylib differ
diff --git a/plugins/wterm/wterm.c b/plugins/wterm/wterm.c
new file mode 100644
index 0000000..2692e03
--- /dev/null
+++ b/plugins/wterm/wterm.c
@@ -0,0 +1,88 @@
+#include
+#include
+#include
+#include
+#include
+#include "../plugin.h"
+
+void init();
+call __init__ = init;
+
+void init()
+{
+
+}
+void pexit()
+{
+
+}
+
+int read_buf(int fd, char*buf,int size)
+{
+ int i = 0;
+ char c = '\0';
+ int n;
+ while ((i < size - 1) && (c != '\n'))
+ {
+ n = read(fd, &c, 1);
+ if (n > 0)
+ {
+ buf[i] = c;
+ i++;
+ }
+ else if(n == -1) return n;
+ else
+ c = '\n';
+ }
+ buf[i] = '\0';
+ return i;
+}
+void execute(int client, const char* m, dictionary rq)
+{
+ textstream(client);
+ int filedes[2];
+ char* code = R_STR(rq, "cmd");
+ if(!code) return;
+ if(pipe(filedes) == -1)
+ {
+ perror("pipe");
+ return;
+ }
+ pid_t pid = fork();
+ if(pid == -1)
+ {
+ perror("folk");
+ return;
+ } else if(pid == 0)
+ {
+ while ((dup2(filedes[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {}
+ close(filedes[1]);
+ close(filedes[0]);
+ // executecomand
+ system(code);
+ //perror("execl");
+ _exit(1);
+ }
+ close(filedes[1]);
+ char buffer[1024];
+ while (1) {
+ ssize_t count = read_buf(filedes[0],buffer, sizeof(buffer));
+ if (count == -1) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ perror("read");
+ return;
+ }
+ } else if (count == 0) {
+ break;
+ } else {
+ __t(client,"data:%s\n",buffer);
+ //handle_child_process_output(buffer, count);
+ }
+ }
+ close(filedes[0]);
+ wait(0);
+ free(code);
+ printf("Child process exit\n");
+}
\ No newline at end of file