From 1f771613a2d9d6871ba09fcfae82d9fde1c6343c Mon Sep 17 00:00:00 2001 From: Markus Gutschke Date: Thu, 30 Jul 2009 17:40:54 +0000 Subject: [PATCH] - Added the --css command line option to make incremental changes to the style sheet without having to load a full replacement with the --static-file option. Added an example that enables white text on a black background. - Added Debian specific documentation to the manual page. --- ChangeLog | 9 ++++++ Makefile.am | 8 ++++- Makefile.in | 8 ++++- config.h | 2 +- configure | 2 +- configure.ac | 2 +- debian/docs | 1 + debian/rules | 2 +- demo/vt100.js | 2 +- shellinabox/launcher.c | 13 ++++---- shellinabox/shell_in_a_box.js | 2 +- shellinabox/shellinaboxd.c | 54 +++++++++++++++++++++++++++++--- shellinabox/shellinaboxd.man.in | 55 +++++++++++++++++++++++++++++++++ shellinabox/vt100.js | 2 +- shellinabox/white-on-black.css | 6 ++++ 15 files changed, 148 insertions(+), 20 deletions(-) create mode 100644 shellinabox/white-on-black.css diff --git a/ChangeLog b/ChangeLog index e1fe74a..62a56d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-07-30 Markus Gutschke + + * Added the --css command line option to make incremental changes + to the style sheet without having to load a full replacement with + the --static-file option. Added an example that enables white text + on a black background. + + * Added Debian specific documentation to the manual page. + 2009-07-29 Markus Gutschke * Allow unprivileged users to run the daemon. This requires diff --git a/Makefile.am b/Makefile.am index 45fa351..10182e7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,7 +15,8 @@ dist_doc_DATA = AUTHORS \ INSTALL \ NEWS \ README \ - TODO + TODO \ + shellinabox/white-on-black.css EXTRA_DIST = demo/beep.wav \ demo/favicon.ico \ demo/demo.html \ @@ -153,6 +154,11 @@ shellinaboxd.1: shellinabox/shellinaboxd.man.in config.h else \ sed -e '/^#ifdef *HAVE_PAM$$/,/^#endif$$/d'; \ fi | \ + if [ -n "${DPKGBUILD}" ]; then \ + sed -e '/^#ifndef *DPKGBUILD$$/,/^#endif$$/d'; \ + else \ + sed -e '/^#ifdef *DPKGBUILD$$/,/^#endif$$/d'; \ + fi | \ sed -e '/^#/d' >"$@" @out=`echo "$@" 2>/dev/null|sed -e 's/\.[^.]*$$/.ps/'`; \ man -Tps "./$@" >"$${out}" 2>/dev/null || rm -f "$${out}" diff --git a/Makefile.in b/Makefile.in index 2ae69fc..0c128bc 100644 --- a/Makefile.in +++ b/Makefile.in @@ -253,7 +253,8 @@ dist_doc_DATA = AUTHORS \ INSTALL \ NEWS \ README \ - TODO + TODO \ + shellinabox/white-on-black.css EXTRA_DIST = demo/beep.wav \ demo/favicon.ico \ @@ -1067,6 +1068,11 @@ shellinaboxd.1: shellinabox/shellinaboxd.man.in config.h else \ sed -e '/^#ifdef *HAVE_PAM$$/,/^#endif$$/d'; \ fi | \ + if [ -n "${DPKGBUILD}" ]; then \ + sed -e '/^#ifndef *DPKGBUILD$$/,/^#endif$$/d'; \ + else \ + sed -e '/^#ifdef *DPKGBUILD$$/,/^#endif$$/d'; \ + fi | \ sed -e '/^#/d' >"$@" @out=`echo "$@" 2>/dev/null|sed -e 's/\.[^.]*$$/.ps/'`; \ man -Tps "./$@" >"$${out}" 2>/dev/null || rm -f "$${out}" diff --git a/config.h b/config.h index fafda1f..e31c08b 100644 --- a/config.h +++ b/config.h @@ -135,7 +135,7 @@ #define STDC_HEADERS 1 /* Most recent revision number in the version control system */ -#define VCS_REVISION "157" +#define VCS_REVISION "158" /* Version number of package */ #define VERSION "2.9" diff --git a/configure b/configure index b33d439..1c48779 100755 --- a/configure +++ b/configure @@ -2037,7 +2037,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu -VCS_REVISION=157 +VCS_REVISION=158 cat >>confdefs.h <<_ACEOF diff --git a/configure.ac b/configure.ac index f86785a..c4ba524 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ(2.57) dnl This is the one location where the authoritative version number is stored AC_INIT(shellinabox, 2.9, markus@shellinabox.com) -VCS_REVISION=157 +VCS_REVISION=158 AC_SUBST(VCS_REVISION) AC_DEFINE_UNQUOTED(VCS_REVISION, "${VCS_REVISION}", [Most recent revision number in the version control system]) diff --git a/debian/docs b/debian/docs index 885f1b8..bc017c5 100644 --- a/debian/docs +++ b/debian/docs @@ -5,3 +5,4 @@ INSTALL NEWS README TODO +shellinabox/white-on-black.css diff --git a/debian/rules b/debian/rules index 695f140..f7841ff 100755 --- a/debian/rules +++ b/debian/rules @@ -46,7 +46,7 @@ build: build-stamp build-stamp: config.status dh_testdir @# Add here commands to compile the package. - $(MAKE) + $(MAKE) DPKGBUILD=true touch build-stamp diff --git a/demo/vt100.js b/demo/vt100.js index 2e9f4d4..80d9d86 100644 --- a/demo/vt100.js +++ b/demo/vt100.js @@ -1693,7 +1693,7 @@ VT100.prototype.toggleBell = function() { }; VT100.prototype.about = function() { - alert("VT100 Terminal Emulator " + "2.9 (revision 157)" + + alert("VT100 Terminal Emulator " + "2.9 (revision 158)" + "\nCopyright 2008-2009 by Markus Gutschke\n" + "For more information check http://shellinabox.com"); }; diff --git a/shellinabox/launcher.c b/shellinabox/launcher.c index 1386ae5..bccb580 100644 --- a/shellinabox/launcher.c +++ b/shellinabox/launcher.c @@ -772,6 +772,11 @@ static pam_handle_t *internalLogin(struct Service *service, struct Utmp *utmp, check(!uname(&uts)); hostname = uts.nodename; } + check(hostname = strdup(hostname)); + char *dot = strchr(hostname, '.'); + if (dot) { + *dot = '\000'; + } const struct passwd *pw; pam_handle_t *pam = NULL; @@ -786,12 +791,7 @@ static pam_handle_t *internalLogin(struct Service *service, struct Utmp *utmp, _exit(1); } free(prompt); - char *localhost = strstr(service->cmdline, "@localhost"); - if (localhost) { - memcpy(localhost+1, "%s", 3); - } - char *cmdline = stringPrintf(NULL, service->cmdline, user, - hostname); + char *cmdline = stringPrintf(NULL, service->cmdline, user); free(user); free((void *)service->cmdline); service->cmdline = cmdline; @@ -892,6 +892,7 @@ static pam_handle_t *internalLogin(struct Service *service, struct Utmp *utmp, pw = getPWEnt(service->uid); #endif } + free((void *)hostname); if (restricted && (service->uid != restricted || service->gid != pw->pw_gid)) { diff --git a/shellinabox/shell_in_a_box.js b/shellinabox/shell_in_a_box.js index b4f80b8..64fe952 100644 --- a/shellinabox/shell_in_a_box.js +++ b/shellinabox/shell_in_a_box.js @@ -355,7 +355,7 @@ ShellInABox.prototype.extendContextMenu = function(entries, actions) { }; ShellInABox.prototype.about = function() { - alert("Shell In A Box version " + "2.9 (revision 157)" + + alert("Shell In A Box version " + "2.9 (revision 158)" + "\nCopyright 2008-2009 by Markus Gutschke\n" + "For more information check http://shellinabox.com" + (typeof serverSupportsSSL != 'undefined' && serverSupportsSSL ? diff --git a/shellinabox/shellinaboxd.c b/shellinabox/shellinaboxd.c index abb2669..ef1af94 100644 --- a/shellinabox/shellinaboxd.c +++ b/shellinabox/shellinaboxd.c @@ -91,6 +91,7 @@ static HashMap *externalFiles; static Server *cgiServer; static char *cgiSessionKey; static int cgiSessions; +static char *cssStyleSheet; static char *jsonEscape(const char *buf, int len) { static const char *hexDigit = "0123456789ABCDEF"; @@ -548,9 +549,8 @@ static int shellInABoxHttpHandler(HttpConnection *http, void *arg, httpTransfer(http, response, headerLength + contentLength); } else if (pathInfoLength == 10 && !memcmp(pathInfo, "styles.css", 10)) { // Serve the style sheet. - extern char stylesStart[]; - extern char stylesEnd[]; - serveStaticFile(http, "text/css; charset=utf-8", stylesStart, stylesEnd); + serveStaticFile(http, "text/css; charset=utf-8", + cssStyleSheet, strrchr(cssStyleSheet, '\000')); } else { httpSendReply(http, 404, "File not found", NO_MSG); } @@ -589,6 +589,7 @@ static void usage(void) { "List of command line options:\n" " -b, --background[=PIDFILE] run in background\n" "%s" + " --css=FILE attach contents to CSS style sheet\n" " --cgi[=PORTMIN-PORTMAX] run as CGI\n" " -d, --debug enable debug mode\n" " -f, --static-file=URL:FILE serve static file from URL path\n" @@ -655,6 +656,12 @@ static void parseArgs(int argc, char * const argv[]) { int verbosity = MSG_DEFAULT; externalFiles = newHashMap(destroyExternalFileHashEntry, NULL); HashMap *serviceTable = newHashMap(destroyServiceHashEntry, NULL); + extern char stylesStart[]; + extern char stylesEnd[]; + check(cssStyleSheet = malloc(stylesEnd - stylesStart)); + memcpy(cssStyleSheet, stylesStart, stylesEnd - stylesStart); + cssStyleSheet[stylesEnd - stylesStart] = '\000'; + for (;;) { static const char optstring[] = "+hb::c:df:g:np:s:tqu:v"; static struct option options[] = { @@ -662,6 +669,7 @@ static void parseArgs(int argc, char * const argv[]) { { "background", 2, 0, 'b' }, { "cert", 1, 0, 'c' }, { "cert-fd", 1, 0, 0 }, + { "css", 1, 0, 0 }, { "cgi", 2, 0, 0 }, { "debug", 0, 0, 'd' }, { "static-file", 1, 0, 'f' }, @@ -707,7 +715,7 @@ static void parseArgs(int argc, char * const argv[]) { if (optarg && pidfile) { fatal("Only one pidfile can be given"); } - if (optarg) { + if (optarg && *optarg) { pidfile = strdup(optarg); } } else if (!idx--) { @@ -721,6 +729,10 @@ static void parseArgs(int argc, char * const argv[]) { if (certificateDir) { fatal("Only one certificate directory can be selected"); } + struct stat st; + if (!optarg || !*optarg || stat(optarg, &st) || !S_ISDIR(st.st_mode)) { + fatal("\"--cert\" expects a directory name"); + } check(certificateDir = strdup(optarg)); } else if (!idx--) { // Certificate file descriptor @@ -733,12 +745,35 @@ static void parseArgs(int argc, char * const argv[]) { if (certificateFd >= 0) { fatal("Only one certificate file handle can be provided"); } + if (!optarg || *optarg < '0' || *optarg > '9') { + fatal("\"--cert-fd\" expects a valid file handle"); + } int tmpFd = strtoint(optarg, 3, INT_MAX); certificateFd = dup(tmpFd); if (certificateFd < 0) { fatal("Invalid certificate file handle"); } check(!NOINTR(close(tmpFd))); + } else if (!idx--) { + // CSS + struct stat st; + if (!optarg || !*optarg || stat(optarg, &st) || !S_ISREG(st.st_mode)) { + fatal("\"--css\" expects a file name"); + } + FILE *css = fopen(optarg, "r"); + if (!css) { + fatal("Cannot read style sheet \"%s\"", optarg); + } else { + check(cssStyleSheet= realloc(cssStyleSheet, strlen(cssStyleSheet) + + st.st_size + 2)); + char *newData = strrchr(cssStyleSheet, '\000'); + *newData++ = '\n'; + if (fread(newData, 1, st.st_size, css) != st.st_size) { + fatal("Failed to read style sheet \"%s\"", optarg); + } + newData[st.st_size]= '\000'; + fclose(css); + } } else if (!idx--) { // CGI if (demonize) { @@ -748,7 +783,7 @@ static void parseArgs(int argc, char * const argv[]) { fatal("Cannot specify a port for CGI operation"); } cgi = 1; - if (optarg) { + if (optarg && *optarg) { char *ptr = strchr(optarg, '-'); if (!ptr) { fatal("Syntax error in port range specification"); @@ -784,6 +819,9 @@ static void parseArgs(int argc, char * const argv[]) { if (runAsGroup >= 0) { fatal("Duplicate --group option."); } + if (!optarg || !*optarg) { + fatal("\"--group\" expects a group name."); + } runAsGroup = parseGroup(optarg, NULL); } else if (!idx--) { // Linkify @@ -814,6 +852,9 @@ static void parseArgs(int argc, char * const argv[]) { if (cgi) { fatal("Cannot specifiy a port for CGI operation"); } + if (!optarg || *optarg < '0' || *optarg > '9') { + fatal("\"--port\" expects a port number."); + } port = strtoint(optarg, 1, 65535); } else if (!idx--) { // Service @@ -848,6 +889,9 @@ static void parseArgs(int argc, char * const argv[]) { if (runAsUser >= 0) { fatal("Duplicate --user option."); } + if (!optarg || !*optarg) { + fatal("\"--user\" expects a user name."); + } runAsUser = parseUser(optarg, NULL); } else if (!idx--) { // Verbose diff --git a/shellinabox/shellinaboxd.man.in b/shellinabox/shellinaboxd.man.in index ba3b0e4..4a41371 100644 --- a/shellinabox/shellinaboxd.man.in +++ b/shellinabox/shellinaboxd.man.in @@ -55,6 +55,7 @@ shellinaboxd \- publish command line shell through AJAX interface [\ \fB-c\fP\ | \fB--cert=\fP\fIcertdir\fP\ ] #endif [\ \fB--cert-fd=\fP\fIfd\fP\ ] +[\ \fB--css=\fP\fIfilename\fP\ ] [\ \fB--cgi\fP[\fB=\fP\fIportrange\fP]\ ] [\ \fB-d\fP\ | \fB--debug\fP\ ] [\ \fB-f\fP\ | \fB--static-file=\fP\fIurl\fP:\fIfile\fP\ ] @@ -158,6 +159,19 @@ support, it does offer an alternative solution for securely providing the private key data to the daemon. #endif .TP +\fB--css=\fP\fIfilename\fP +Sometimes, it is not necessary to replace the entire style sheet using the +.B --static-file +option. But instead a small incremental change should be made to the visual +appearance of the terminal. The +.B --css +option provides a means to append additional style rules to the end of +the default +.B styles.css +sheet. More than one +.B --css +option can be given on the same command line. +.TP \fB--cgi\fP[\fB=\fP\fIportrange\fP] Instead of running .B shellinaboxd @@ -540,6 +554,22 @@ terminal, publish a .B Wyse 60\*(Tm terminal. Again, this command should be run as .BR root . +.TP +#ifndef DPKGBUILD +.B shellinaboxd --css white-on-black.css +#endif +#ifdef DPKGBUILD +.B shellinaboxd --css /usr/share/doc/shellinabox/white-on-black.css +#endif +Loads the +.B white-on-black.css +style sheet +#ifndef DPKGBUILD +from the current directory +#endif +and appends it to the built-in +.B styles.css +sheet. This causes the terminal to render white text on a black background. .P .SH DIAGNOSTICS The daemon returns a non-zero exit code in case of failure. With the @@ -553,6 +583,31 @@ Common failure conditions are reusing a port that is already in use, lack of sufficient privileges to run a service, failure to find SSL/TLS certificates, and failure to write newly generated certificates to the certification directory. +#ifdef DPKGBUILD +.SH FILES +.TP 10 +.I /etc/default/shellinabox +The system-wide installation of +.B shellinaboxd +can be configured by editing this file. After making any changes, restart +the daemon with \fBsudo service shellinabox restart\fP. +.TP +.I /etc/init.d/shellinabox +This is the system-wide service definition. Usually, there is no need to +edit this file. +.TP +.I /var/lib/shellinabox +This directory contains the certificate files that +.B shellinaboxd +uses when serving encrypted SSL sessions. If suitable files do not exist, yet, +it tries to populate the directory with self-signed certificates the first +time a particular certificate is needed. Over time, it should contain +\fBcertificate.pem\fP, \fBcertificate-localhost.pem\fP, and +\fBcertificate-\fP\fIHOSTNAME\fP\fB.pem\fP. +.TP +.I /var/run/shellinaboxd.pid +This file is created any time the system-wide service gets started. +#endif .SH "SEE ALSO" .BR chmod (1), .BR last (1), diff --git a/shellinabox/vt100.js b/shellinabox/vt100.js index 2e9f4d4..80d9d86 100644 --- a/shellinabox/vt100.js +++ b/shellinabox/vt100.js @@ -1693,7 +1693,7 @@ VT100.prototype.toggleBell = function() { }; VT100.prototype.about = function() { - alert("VT100 Terminal Emulator " + "2.9 (revision 157)" + + alert("VT100 Terminal Emulator " + "2.9 (revision 158)" + "\nCopyright 2008-2009 by Markus Gutschke\n" + "For more information check http://shellinabox.com"); }; diff --git a/shellinabox/white-on-black.css b/shellinabox/white-on-black.css new file mode 100644 index 0000000..db2dcf8 --- /dev/null +++ b/shellinabox/white-on-black.css @@ -0,0 +1,6 @@ +#vt100 #scrollable { + color: white; + background-color: black; +} +#vt100 #ansi0 { background-color: #ffffff; } +#vt100 #ansi15 { background-color: #000000; } -- 2.45.2