diff --git a/README.md b/README.md new file mode 100644 index 0000000..1bc8416 --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ + +shellinabox +=========== + +This is unofficial fork of project **shellinabox**. Fork was created because +original project is not maintained anymore and we cannot contact original +repository owners. + +Our aim is to continue with maintanince of shellinabox project. + +If you have any questions, issues or patches, please fell free to submit pull +request or report an issue. You can also drop an email to original project +[issue #261](https://code.google.com/p/shellinabox/issues/detail?id=261) discusion +from where this fork started. + + +About shellinabox +----------------- + +Shell In A Box implements a web server that can export arbitrary command line +tools to a web based terminal emulator. This emulator is accessible to any +JavaScript and CSS enabled web browser and does not require any additional +browser plugins. + +More information: + +* [Official site](https://code.google.com/p/shellinabox) +* [Official wiki](https://code.google.com/p/shellinabox/wiki/shellinaboxd_man) + diff --git a/shellinabox/launcher.c b/shellinabox/launcher.c index 69e29e6..835969e 100644 --- a/shellinabox/launcher.c +++ b/shellinabox/launcher.c @@ -520,6 +520,7 @@ int launchChild(int service, struct Session *session, const char *url) { ssize_t len = sizeof(struct LaunchRequest) + strlen(u) + 1; check(request = calloc(len, 1)); request->service = service; + request->terminate = -1; request->width = session->width; request->height = session->height; strncat(request->peerName, httpGetPeerName(session->http), @@ -547,6 +548,7 @@ int launchChild(int service, struct Session *session, const char *url) { return -1; } check(bytes == sizeof(pid)); + check(session->pid = pid); struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); check(cmsg); check(cmsg->cmsg_level == SOL_SOCKET); @@ -555,6 +557,34 @@ int launchChild(int service, struct Session *session, const char *url) { return pid; } +int terminateChild(struct Session *session) { + if (launcher < 0) { + errno = EINVAL; + return -1; + } + + if (session->pid < 1) { + debug("Child pid for termination not valid!"); + return -1; + } + + // Send terminate request to launcher process + struct LaunchRequest *request; + ssize_t len = sizeof(struct LaunchRequest); + check(request = calloc(len, 1)); + request->terminate = session->pid; + if (NOINTR(write(launcher, request, len)) != len) { + debug("Child %d termination request failed!", request->terminate); + free(request); + return -1; + } + + free(request); + session->pid = 0; + session->cleanup = 0; + return 0; +} + struct Utmp { const char pid[32]; int pty; @@ -1616,7 +1646,7 @@ static void launcherDaemon(int fd) { int status; pid_t pid; while (NOINTR(pid = waitpid(-1, &status, WNOHANG)) > 0) { - debug("Child %d exited with exit code %d\n", pid, WEXITSTATUS(status)); + debug("Child %d exited with exit code %d", pid, WEXITSTATUS(status)); if (WIFEXITED(status) || WIFSIGNALED(status)) { char key[32]; snprintf(&key[0], sizeof(key), "%d", pid); @@ -1627,6 +1657,21 @@ static void launcherDaemon(int fd) { continue; } + // Check if we received terminate request from parent process and + // try to terminate child, if child is still running + if (request.terminate > 0) { + errno = 0; + NOINTR(pid = waitpid(request.terminate, &status, WNOHANG)); + if (pid == 0 && errno == 0) { + if (kill(request.terminate, SIGTERM) == 0) { + debug("Terminating child %d (kill)", request.terminate); + } else { + debug("Terminating child failed [%s]", strerror(errno)); + } + } + continue; + } + char *url; check(url = calloc(request.urlLength + 1, 1)); readURL: @@ -1637,7 +1682,7 @@ static void launcherDaemon(int fd) { break; } while (NOINTR(pid = waitpid(-1, &status, WNOHANG)) > 0) { - debug("Child %d exited with exit code %d\n", pid, WEXITSTATUS(status)); + debug("Child %d exited with exit code %d", pid, WEXITSTATUS(status)); if (WIFEXITED(status) || WIFSIGNALED(status)) { char key[32]; snprintf(&key[0], sizeof(key), "%d", pid); @@ -1682,6 +1727,7 @@ static void launcherDaemon(int fd) { childProcesses = newHashMap(destroyUtmpHashEntry, NULL); } addToHashMap(childProcesses, utmp->pid, (char *)utmp); + debug("Child %d launched", pid); } else { int fds[2]; if (!pipe(fds)) { diff --git a/shellinabox/launcher.h b/shellinabox/launcher.h index 945bccc..2d7d145 100644 --- a/shellinabox/launcher.h +++ b/shellinabox/launcher.h @@ -52,15 +52,17 @@ struct LaunchRequest { - int service; - int width, height; - char peerName[128]; - int urlLength; - char url[0]; + int service; + int width, height; + pid_t terminate; + char peerName[128]; + int urlLength; + char url[0]; }; int supportsPAM(void); int launchChild(int service, struct Session *session, const char *url); +int terminateChild(struct Session *session); void setWindowSize(int pty, int width, int height); int forkLauncher(void); void terminateLauncher(void); diff --git a/shellinabox/session.c b/shellinabox/session.c index f18203f..25f5513 100644 --- a/shellinabox/session.c +++ b/shellinabox/session.c @@ -121,6 +121,8 @@ void initSession(struct Session *session, const char *sessionKey, session->height = 0; session->buffered = NULL; session->len = 0; + session->pid = 0; + session->cleanup = 0; } struct Session *newSession(const char *sessionKey, Server *server, URL *url, diff --git a/shellinabox/session.h b/shellinabox/session.h index bd54963..11d2281 100644 --- a/shellinabox/session.h +++ b/shellinabox/session.h @@ -63,6 +63,8 @@ struct Session { int height; char *buffered; int len; + pid_t pid; + int cleanup; }; void addToGraveyard(struct Session *session); diff --git a/shellinabox/shellinaboxd.c b/shellinabox/shellinaboxd.c index d0d787b..ba734e1 100644 --- a/shellinabox/shellinaboxd.c +++ b/shellinabox/shellinaboxd.c @@ -274,8 +274,11 @@ static int completePendingRequest(struct Session *session, } static void sessionDone(void *arg) { - debug("Child terminated"); struct Session *session = (struct Session *)arg; + debug("Session %s done", session->sessionKey); + if (session->cleanup) { + terminateChild(session); + } session->done = 1; addToGraveyard(session); completePendingRequest(session, "", 0, INT_MAX); @@ -301,6 +304,7 @@ static int handleSession(struct ServerConnection *connection, void *arg, if (bytes || timedOut) { if (!session->http && timedOut) { debug("Timeout. Closing session."); + session->cleanup = 1; return 0; } check(!session->done); diff --git a/shellinabox/vt100.jspp b/shellinabox/vt100.jspp index dc97181..e514692 100755 --- a/shellinabox/vt100.jspp +++ b/shellinabox/vt100.jspp @@ -3089,6 +3089,7 @@ VT100.prototype.keyUp = function(event) { asciiKey || event.keyCode == 50 || event.keyCode >= 96 && event.keyCode <= 105; + // Not used ??? var normalKey = alphNumKey || event.keyCode == 59 || event.keyCode == 61 || @@ -3279,7 +3280,6 @@ VT100.prototype.lf = function(count) { this.scrollRegion(0, this.top + 1, this.terminalWidth, this.bottom - this.top - 1, 0, -1, this.color, this.style); - offset = undefined; } else if (this.cursorY < this.terminalHeight - 1) { this.gotoXY(this.cursorX, this.cursorY + 1); } @@ -3723,7 +3723,7 @@ VT100.prototype.csiJ = function(number) { default: return; } - needWrap = false; + this.needWrap = false; }; VT100.prototype.csiK = function(number) { @@ -3744,7 +3744,7 @@ VT100.prototype.csiK = function(number) { default: return; } - needWrap = false; + this.needWrap = false; }; VT100.prototype.csiL = function(number) { @@ -3761,7 +3761,7 @@ VT100.prototype.csiL = function(number) { this.scrollRegion(0, this.cursorY, this.terminalWidth, this.bottom - this.cursorY - number, 0, number, this.color, this.style); - needWrap = false; + this.needWrap = false; }; VT100.prototype.csiM = function(number) { @@ -3773,12 +3773,12 @@ VT100.prototype.csiM = function(number) { number = 1; } if (number > this.bottom - this.cursorY) { - number = bottom - cursorY; + number = this.bottom - this.cursorY; } this.scrollRegion(0, this.cursorY + number, this.terminalWidth, this.bottom - this.cursorY - number, 0, -number, this.color, this.style); - needWrap = false; + this.needWrap = false; }; VT100.prototype.csim = function() { @@ -3839,7 +3839,7 @@ VT100.prototype.csiP = function(number) { this.scrollRegion(this.cursorX + number, this.cursorY, this.terminalWidth - this.cursorX - number, 1, -number, 0, this.color, this.style); - needWrap = false; + this.needWrap = false; }; VT100.prototype.csiX = function(number) { @@ -3852,7 +3852,7 @@ VT100.prototype.csiX = function(number) { } this.clearRegion(this.cursorX, this.cursorY, number, 1, this.color, this.style); - needWrap = false; + this.needWrap = false; }; VT100.prototype.settermCommand = function() {