diff --git a/ChangeLog b/ChangeLog index efd7401..3e437c7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-12-03 Markus Gutschke + + * Allow retrieval of the user's default login shell from + /etc/passwd. + + * Allow the code to be built without support for the LOGIN + service, as calling /bin/login does not work well on Fedora. + 2009-12-02 Markus Gutschke * Added fallback code that dynamically computes the correct commandline diff --git a/Makefile.am b/Makefile.am index 93ab34f..3759202 100644 --- a/Makefile.am +++ b/Makefile.am @@ -196,12 +196,18 @@ ${top_srcdir}/demo/vt100.js: ${top_srcdir}/shellinabox/vt100.js shellinaboxd.1: shellinabox/shellinaboxd.man.in config.h @src="${top_srcdir}/shellinabox/shellinaboxd.man.in"; \ echo preprocess "$$src" '>'"$@"; \ + if sed -e 's/^#define \([^ ]*\).*/\1/' -e t -e d config.h | \ + grep 'HAVE_BIN_LOGIN' >/dev/null 2>&1; then \ + sed -e '/^#ifndef *HAVE_BIN_LOGIN$$/,/^#endif$$/d' "$$src"; \ + else \ + sed -e '/^#ifdef *HAVE_BIN_LOGIN$$/,/^#endif$$/d' "$$src"; \ + fi | \ if [ `sed -e 's/^#define \([^ ]*\).*/\1/' -e t -e d config.h | \ egrep 'HAVE_OPENSSL_BIO_H|HAVE_OPENSSL_ERR_H|HAVE_OPENSSL_SSL_H'|\ wc -l` -eq 3 ]; then \ - sed -e '/^#ifndef *HAVE_OPENSSL$$/,/^#endif$$/d' "$$src"; \ + sed -e '/^#ifndef *HAVE_OPENSSL$$/,/^#endif$$/d'; \ else \ - sed -e '/^#ifdef *HAVE_OPENSSL$$/,/^#endif$$/d' "$$src"; \ + sed -e '/^#ifdef *HAVE_OPENSSL$$/,/^#endif$$/d'; \ fi | \ if sed -e 's/^#define \([^ ]*\).*/\1/' -e t -e d config.h | \ grep 'HAVE_SECURITY_PAM_APPL_H' >/dev/null 2>&1; then \ diff --git a/Makefile.in b/Makefile.in index 322bd58..7ad48c0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1209,12 +1209,18 @@ ${top_srcdir}/demo/vt100.js: ${top_srcdir}/shellinabox/vt100.js shellinaboxd.1: shellinabox/shellinaboxd.man.in config.h @src="${top_srcdir}/shellinabox/shellinaboxd.man.in"; \ echo preprocess "$$src" '>'"$@"; \ + if sed -e 's/^#define \([^ ]*\).*/\1/' -e t -e d config.h | \ + grep 'HAVE_BIN_LOGIN' >/dev/null 2>&1; then \ + sed -e '/^#ifndef *HAVE_BIN_LOGIN$$/,/^#endif$$/d' "$$src"; \ + else \ + sed -e '/^#ifdef *HAVE_BIN_LOGIN$$/,/^#endif$$/d' "$$src"; \ + fi | \ if [ `sed -e 's/^#define \([^ ]*\).*/\1/' -e t -e d config.h | \ egrep 'HAVE_OPENSSL_BIO_H|HAVE_OPENSSL_ERR_H|HAVE_OPENSSL_SSL_H'|\ wc -l` -eq 3 ]; then \ - sed -e '/^#ifndef *HAVE_OPENSSL$$/,/^#endif$$/d' "$$src"; \ + sed -e '/^#ifndef *HAVE_OPENSSL$$/,/^#endif$$/d'; \ else \ - sed -e '/^#ifdef *HAVE_OPENSSL$$/,/^#endif$$/d' "$$src"; \ + sed -e '/^#ifdef *HAVE_OPENSSL$$/,/^#endif$$/d'; \ fi | \ if sed -e 's/^#define \([^ ]*\).*/\1/' -e t -e d config.h | \ grep 'HAVE_SECURITY_PAM_APPL_H' >/dev/null 2>&1; then \ diff --git a/README.Fedora b/README.Fedora index decc5be..018bfc2 100644 --- a/README.Fedora +++ b/README.Fedora @@ -11,11 +11,16 @@ some tips on getting things working: you start the daemon as "root". To fix this problem, consider explicitly specifying a service definition. One of these two should work: - --service /:AUTH:HOME:/bin/bash + --service /:AUTH:HOME:SHELL or --service /:SSH The latter requires that you have a locally running "sshd" daemon. +- Alternatively, consider running "./configure --disable-login" before building + the daemon. This will completely remove support for the "LOGIN" service, and + shellinaboxd will instead use a default "SSH" service for both unprivileged + and for "root" users. + - On Fedora, PAM authentication does not work for shellinabox until you explicitly configure it. This means, using "AUTH" in the service definition will not allow you to log in. diff --git a/config.h b/config.h index 590cf1d..f893da3 100644 --- a/config.h +++ b/config.h @@ -1,11 +1,14 @@ /* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.ac by autoheader. */ +/* Set if you want support for calling /bin/login */ +#define HAVE_BIN_LOGIN 1 + /* Define to 1 if you have the header file. */ #define HAVE_DLFCN_H 1 /* Define to 1 if you have the `dlopen' function. */ -/* #undef HAVE_DLOPEN */ +#define HAVE_DLOPEN 1 /* Define to 1 if you have the `getgrgid_r' function. */ #define HAVE_GETGRGID_R 1 @@ -138,10 +141,10 @@ #define STDC_HEADERS 1 /* Most recent revision number in the version control system */ -#define VCS_REVISION "197" +#define VCS_REVISION "198" /* Version number of package */ #define VERSION "2.10" /* Define to empty if `const' does not conform to ANSI C. */ -#define const /**/ +/* #undef const */ diff --git a/config.h.in b/config.h.in index f4eecf4..692ce14 100644 --- a/config.h.in +++ b/config.h.in @@ -1,5 +1,8 @@ /* config.h.in. Generated from configure.ac by autoheader. */ +/* Set if you want support for calling /bin/login */ +#undef HAVE_BIN_LOGIN + /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H diff --git a/configure b/configure index 97374cf..d4c15af 100755 --- a/configure +++ b/configure @@ -861,6 +861,7 @@ with_pic enable_fast_install with_gnu_ld enable_libtool_lock +enable_login enable_ssl enable_pam enable_runtime_loading @@ -1500,6 +1501,11 @@ Optional Features: --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) + --disable-login on some systems (e.g. Fedora), calling /bin/login + does not work well. If you know that your system + suffers from this problem, set this option to + remove support for the LOGIN keyword in the + service description. --disable-ssl if available at built-time, support for SSL connections will be enabled. It can still be disabled at run-time, either on the daemon's @@ -2319,7 +2325,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu -VCS_REVISION=197 +VCS_REVISION=198 cat >>confdefs.h <<_ACEOF @@ -4470,13 +4476,13 @@ if test "${lt_cv_nm_interface+set}" = set; then : else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:4473: $ac_compile\"" >&5) + (eval echo "\"\$as_me:4479: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:4476: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:4482: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:4479: output\"" >&5) + (eval echo "\"\$as_me:4485: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -5682,7 +5688,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 5685 "configure"' > conftest.$ac_ext + echo '#line 5691 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -7208,11 +7214,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7211: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7217: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7215: \$? = $ac_status" >&5 + echo "$as_me:7221: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -7547,11 +7553,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7550: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7556: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7554: \$? = $ac_status" >&5 + echo "$as_me:7560: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -7652,11 +7658,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7655: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7661: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7659: \$? = $ac_status" >&5 + echo "$as_me:7665: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -7707,11 +7713,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7710: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7716: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:7714: \$? = $ac_status" >&5 + echo "$as_me:7720: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -10090,7 +10096,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 10093 "configure" +#line 10099 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -10186,7 +10192,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 10189 "configure" +#line 10195 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -10680,6 +10686,17 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext +# Check whether --enable-login was given. +if test "${enable_login+set}" = set; then : + enableval=$enable_login; +fi + +if test "x$enable_login" != xno; then + +$as_echo "#define HAVE_BIN_LOGIN 1" >>confdefs.h + +fi + # Check whether --enable-ssl was given. if test "${enable_ssl+set}" = set; then : enableval=$enable_ssl; diff --git a/configure.ac b/configure.ac index 0b9e533..8dff904 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.10, markus@shellinabox.com) -VCS_REVISION=197 +VCS_REVISION=198 AC_SUBST(VCS_REVISION) AC_DEFINE_UNQUOTED(VCS_REVISION, "${VCS_REVISION}", [Most recent revision number in the version control system]) @@ -55,6 +55,19 @@ AC_TRY_LINK([#include [AC_DEFINE(HAVE_SIGWAIT, 1, Define to 1 if you have a working sigwait)]) +dnl On some systems, calling /bin/login does not work. Disable the LOGIN +dnl feature, if the user tells us that it does not do the right thing. +AC_ARG_ENABLE(login, + [ --disable-login on some systems (e.g. Fedora), calling /bin/login + does not work well. If you know that your system + suffers from this problem, set this option to + remove support for the LOGIN keyword in the + service description.]) +if test "x$enable_login" != xno; then + AC_DEFINE(HAVE_BIN_LOGIN, 1, + Set if you want support for calling /bin/login) +fi + dnl We automatically detect SSL support, but allow users to disable it AC_ARG_ENABLE(ssl, [ --disable-ssl if available at built-time, support for SSL diff --git a/demo/vt100.js b/demo/vt100.js index ff48872..96bdb46 100644 --- a/demo/vt100.js +++ b/demo/vt100.js @@ -1955,7 +1955,7 @@ VT100.prototype.toggleBell = function() { }; VT100.prototype.about = function() { - alert("VT100 Terminal Emulator " + "2.10 (revision 197)" + + alert("VT100 Terminal Emulator " + "2.10 (revision 198)" + "\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 fb8a133..0bb2214 100644 --- a/shellinabox/launcher.c +++ b/shellinabox/launcher.c @@ -727,29 +727,34 @@ static const struct passwd *getPWEnt(uid_t uid) { struct passwd pwbuf, *pw; char *buf; #ifdef _SC_GETPW_R_SIZE_MAX - int len = sysconf(_SC_GETPW_R_SIZE_MAX); + int len = sysconf(_SC_GETPW_R_SIZE_MAX); if (len <= 0) { - len = 4096; + len = 4096; } #else - int len = 4096; + int len = 4096; #endif - check(buf = malloc(len)); + check(buf = malloc(len)); check(!getpwuid_r(uid, &pwbuf, buf, len, &pw) && pw); + if (!pw->pw_name ) pw->pw_name = ""; + if (!pw->pw_passwd) pw->pw_passwd = ""; + if (!pw->pw_gecos ) pw->pw_gecos = ""; + if (!pw->pw_dir ) pw->pw_dir = ""; + if (!pw->pw_shell ) pw->pw_shell = ""; struct passwd *passwd; - check(passwd = calloc(sizeof(struct passwd) + - strlen(pw->pw_name) + - strlen(pw->pw_passwd) + - strlen(pw->pw_gecos) + - strlen(pw->pw_dir) + - strlen(pw->pw_shell) + 5, 1)); - passwd->pw_uid = pw->pw_uid; - passwd->pw_gid = pw->pw_gid; - strncat(passwd->pw_shell = strrchr( - strncat(passwd->pw_dir = strrchr( - strncat(passwd->pw_gecos = strrchr( - strncat(passwd->pw_passwd = strrchr( - strncat(passwd->pw_name = (char *)(passwd + 1), + check(passwd = calloc(sizeof(struct passwd) + + strlen(pw->pw_name) + + strlen(pw->pw_passwd) + + strlen(pw->pw_gecos) + + strlen(pw->pw_dir) + + strlen(pw->pw_shell) + 5, 1)); + passwd->pw_uid = pw->pw_uid; + passwd->pw_gid = pw->pw_gid; + strncat(passwd->pw_shell = strrchr( + strncat(passwd->pw_dir = strrchr( + strncat(passwd->pw_gecos = strrchr( + strncat(passwd->pw_passwd = strrchr( + strncat(passwd->pw_name = (char *)(passwd + 1), pw->pw_name, strlen(pw->pw_name)), '\000') + 1, pw->pw_passwd, strlen(pw->pw_passwd)), '\000') + 1, pw->pw_gecos, strlen(pw->pw_gecos)), '\000') + 1, @@ -946,6 +951,12 @@ static pam_handle_t *internalLogin(struct Service *service, struct Utmp *utmp, free((void *)fqdn); free((void *)hostname); + if (service->useDefaultShell) { + check(!service->cmdline); + service->cmdline = strdup(*pw->pw_shell ? + pw->pw_shell : "/bin/sh"); + } + if (restricted && (service->uid != restricted || service->gid != pw->pw_gid)) { puts("\nAccess denied!"); @@ -1226,8 +1237,19 @@ static void execService(int width, int height, struct Service *service, extern char **environ; environ = environment; - char *cmd = strrchr(argv[0], '/'); - execvp(cmd ? cmd + 1: argv[0], argv); + char *cmd = strdup(argv[0]); + char *slash = strrchr(argv[0], '/'); + if (slash) { + memmove(argv[0], slash + 1, strlen(slash)); + } + if (service->useDefaultShell) { + int len = strlen(argv[0]); + check(argv[0] = realloc(argv[0], len + 2)); + memmove(argv[0] + 1, argv[0], len); + argv[0][0] = '-'; + argv[0][len + 1] = '\000'; + } + execvp(cmd, argv); } void setWindowSize(int pty, int width, int height) { diff --git a/shellinabox/service.c b/shellinabox/service.c index 96ba7f4..ca05faf 100644 --- a/shellinabox/service.c +++ b/shellinabox/service.c @@ -83,6 +83,7 @@ void initService(struct Service *service, const char *arg) { } arg = ptr + 1; +#ifdef HAVE_BIN_LOGIN // The next part of the argument is either the word 'LOGIN' or the // application definition. if (!strcmp(arg, "LOGIN")) { @@ -93,6 +94,7 @@ void initService(struct Service *service, const char *arg) { service->useLogin = 1; service->useHomeDir = 0; service->authUser = 0; + service->useDefaultShell = 0; service->uid = 0; service->gid = 0; check(service->user = strdup("root")); @@ -100,10 +102,13 @@ void initService(struct Service *service, const char *arg) { check(service->cwd = strdup("/")); check(service->cmdline = strdup( "/bin/login -p -h ${peer}")); - } else if (!strcmp(arg, "SSH") || !strncmp(arg, "SSH:", 4)) { + } else +#endif + if (!strcmp(arg, "SSH") || !strncmp(arg, "SSH:", 4)) { service->useLogin = 0; service->useHomeDir = 0; service->authUser = 2; + service->useDefaultShell = 0; service->uid = -1; service->gid = -1; service->user = NULL; @@ -204,7 +209,13 @@ void initService(struct Service *service, const char *arg) { if (!*arg) { goto error; } - check(service->cmdline = strdup(arg)); + if (!strcmp(arg, "SHELL")) { + service->useDefaultShell = 1; + service->cmdline = NULL; + } else { + service->useDefaultShell = 0; + check(service->cmdline = strdup(arg)); + } } free(desc); } diff --git a/shellinabox/service.h b/shellinabox/service.h index 2518da3..24a4281 100644 --- a/shellinabox/service.h +++ b/shellinabox/service.h @@ -54,6 +54,7 @@ struct Service { int useLogin; int useHomeDir; int authUser; + int useDefaultShell; int uid; int gid; const char *user; diff --git a/shellinabox/shell_in_a_box.js b/shellinabox/shell_in_a_box.js index 23d826d..fb8fdcc 100644 --- a/shellinabox/shell_in_a_box.js +++ b/shellinabox/shell_in_a_box.js @@ -358,7 +358,7 @@ ShellInABox.prototype.extendContextMenu = function(entries, actions) { }; ShellInABox.prototype.about = function() { - alert("Shell In A Box version " + "2.10 (revision 197)" + + alert("Shell In A Box version " + "2.10 (revision 198)" + "\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 dcf05ff..a107882 100644 --- a/shellinabox/shellinaboxd.c +++ b/shellinabox/shellinaboxd.c @@ -765,10 +765,15 @@ static void usage(void) { "be made available\n" "through the web interface:\n" " SERVICE := ':' APP\n" - " APP := 'LOGIN' | 'SSH' [ : ] | " - "USER ':' CWD ':' \n" + " APP := " +#ifdef HAVE_BIN_LOGIN + "'LOGIN' | " +#endif + "'SSH' [ : ] | " + "USER ':' CWD ':' CMD\n" " USER := %s ':' \n" " CWD := 'HOME' | \n" + " CMD := 'SHELL' | \n" "\n" " supports variable expansion:\n" " ${columns} - number of columns\n" @@ -1096,8 +1101,14 @@ static void parseArgs(int argc, char * const argv[]) { // If the user did not register any services, provide the default service if (!getHashmapSize(serviceTable)) { - addToHashMap(serviceTable, "/", (char *)newService(geteuid() ? ":SSH" : - ":LOGIN")); + addToHashMap(serviceTable, "/", + (char *)newService( +#ifdef HAVE_BIN_LOGIN + geteuid() ? ":SSH" : ":LOGIN" +#else + ":SSH" +#endif + )); } enumerateServices(serviceTable); deleteHashMap(serviceTable); diff --git a/shellinabox/shellinaboxd.man.in b/shellinabox/shellinaboxd.man.in index 18b647d..9dbe40a 100644 --- a/shellinabox/shellinaboxd.man.in +++ b/shellinabox/shellinaboxd.man.in @@ -44,7 +44,7 @@ .\" The most up-to-date version of this program is always available from .\" http://shellinabox.com .\" -.TH SHELLINABOXD 1 "Nov 21, 2009" +.TH SHELLINABOXD 1 "Dec 03, 2009" .SH NAME shellinaboxd \- publish command line shell through AJAX interface .SH SYNOPSIS @@ -330,6 +330,7 @@ One or more services can be registered on different URL paths: \fISERVICE\fP := ':' \fIAPPLICATION\fP .in +#ifdef HAVE_BIN_LOGIN There is a pre-defined \fIapplication\fP, 'LOGIN', which causes the daemon to invoke .B /bin/login @@ -343,12 +344,34 @@ was defined. Starting requires .B root privileges. +#endif -There is another pre-defined \fIapplication\fP, 'SSH'. Instead of invoking +There is +#ifdef HAVE_BIN_LOGIN +another +#endif +#ifndef HAVE_BIN_LOGIN +a +#endif +pre-defined \fIapplication\fP, 'SSH'. +#ifdef HAVE_BIN_LOGIN +Instead of invoking .BR /bin/login , -it calls +it +#endif +#ifndef HAVE_BIN_LOGIN +It +#endif +calls .BR ssh . -This is the default option for unprivileged users, if no +This is the default +#ifdef HAVE_BIN_LOGIN +option for unprivileged users, +#endif +#ifndef HAVE_BIN_LOGIN +option, +#endif +if no .B --service was defined. This operation is available to both privileged and regular users. If the optional \fIhost\fP parameter is omitted, @@ -359,7 +382,12 @@ connects to Alternatively, an \fIapplication\fP can be specified by providing a \fIuser\fP description, a working directory, and a command line: .in +4 -\fIAPPLICATION\fP := 'LOGIN' | 'SSH' [ ':' ] | \fIUSER\fP ':' \fICWD\fP ':' +#ifdef HAVE_BIN_LOGIN +\fIAPPLICATION\fP := 'LOGIN' | 'SSH' [ ':' ] | \fIUSER\fP ':' \fICWD\fP ':' \fICMD\fP +#endif +#ifndef HAVE_BIN_LOGIN +\fIAPPLICATION\fP := 'SSH' [ ':' ] | \fIUSER\fP ':' \fICWD\fP ':' \fICMD\fP +#endif #ifdef HAVE_PAM .in @@ -383,6 +411,14 @@ can be the user's home directory: \fICWD\fP := 'HOME' : .in +The command that +.B shellinaboxd +executes can either be specified as the 'SHELL' keyword, denoting the user's +default login shell, or an arbitrary command line: +.in +4 +\fICMD\fP := 'SHELL' : +.in + The supports expansion of variables of the form ${VAR}. Supported variables are: .RS diff --git a/shellinabox/vt100.js b/shellinabox/vt100.js index ff48872..96bdb46 100644 --- a/shellinabox/vt100.js +++ b/shellinabox/vt100.js @@ -1955,7 +1955,7 @@ VT100.prototype.toggleBell = function() { }; VT100.prototype.about = function() { - alert("VT100 Terminal Emulator " + "2.10 (revision 197)" + + alert("VT100 Terminal Emulator " + "2.10 (revision 198)" + "\nCopyright 2008-2009 by Markus Gutschke\n" + "For more information check http://shellinabox.com"); };