Added a ${url} parameter that can be used in the service description

git-svn-id: https://shellinabox.googlecode.com/svn/trunk@174 0da03de8-d603-11dd-86c2-0f8696b7b6f9
This commit is contained in:
zodiac 2009-08-19 19:08:30 +00:00
parent dfe41ce244
commit 9b8e3af162
11 changed files with 85 additions and 23 deletions

View file

@ -1,3 +1,7 @@
2009-08-19 Markus Gutschke <markus@shellinabox.com>
* Added a ${url} parameter that can be used in the service description.
2009-08-11 Markus Gutschke <markus@shellinabox.com> 2009-08-11 Markus Gutschke <markus@shellinabox.com>
* Added support for user selectable style sheets. Included example * Added support for user selectable style sheets. Included example

View file

@ -138,7 +138,7 @@
#define STDC_HEADERS 1 #define STDC_HEADERS 1
/* Most recent revision number in the version control system */ /* Most recent revision number in the version control system */
#define VCS_REVISION "172" #define VCS_REVISION "174"
/* Version number of package */ /* Version number of package */
#define VERSION "2.9" #define VERSION "2.9"

2
configure vendored
View file

@ -2317,7 +2317,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_compiler_gnu=$ac_cv_c_compiler_gnu
VCS_REVISION=172 VCS_REVISION=174
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF

View file

@ -2,7 +2,7 @@ AC_PREREQ(2.57)
dnl This is the one location where the authoritative version number is stored dnl This is the one location where the authoritative version number is stored
AC_INIT(shellinabox, 2.9, markus@shellinabox.com) AC_INIT(shellinabox, 2.9, markus@shellinabox.com)
VCS_REVISION=172 VCS_REVISION=174
AC_SUBST(VCS_REVISION) AC_SUBST(VCS_REVISION)
AC_DEFINE_UNQUOTED(VCS_REVISION, "${VCS_REVISION}", AC_DEFINE_UNQUOTED(VCS_REVISION, "${VCS_REVISION}",
[Most recent revision number in the version control system]) [Most recent revision number in the version control system])

View file

@ -1892,7 +1892,7 @@ VT100.prototype.toggleBell = function() {
}; };
VT100.prototype.about = function() { VT100.prototype.about = function() {
alert("VT100 Terminal Emulator " + "2.9 (revision 172)" + alert("VT100 Terminal Emulator " + "2.9 (revision 174)" +
"\nCopyright 2008-2009 by Markus Gutschke\n" + "\nCopyright 2008-2009 by Markus Gutschke\n" +
"For more information check http://shellinabox.com"); "For more information check http://shellinabox.com");
}; };

View file

@ -401,21 +401,27 @@ static int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, size_t buflen,
} }
#endif #endif
int launchChild(int service, struct Session *session) { int launchChild(int service, struct Session *session, const char *url) {
if (launcher < 0) { if (launcher < 0) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
struct LaunchRequest request = { struct LaunchRequest *request;
.service = service, size_t len = sizeof(struct LaunchRequest) + strlen(url) + 1;
.width = session->width, check(request = calloc(len, 1));
.height = session->height }; request->service = service;
strncat(request.peerName, httpGetPeerName(session->http), request->width = session->width;
sizeof(request.peerName) - 1); request->height = session->height;
if (NOINTR(write(launcher, &request, sizeof(request))) != sizeof(request)) { strncat(request->peerName, httpGetPeerName(session->http),
sizeof(request->peerName) - 1);
request->urlLength = strlen(url);
memcpy(&request->url, url, request->urlLength);
if (NOINTR(write(launcher, request, len)) != len) {
free(request);
return -1; return -1;
} }
free(request);
pid_t pid; pid_t pid;
char cmsg_buf[CMSG_SPACE(sizeof(int))]; char cmsg_buf[CMSG_SPACE(sizeof(int))];
struct iovec iov = { 0 }; struct iovec iov = { 0 };
@ -1023,7 +1029,8 @@ static void destroyVariableHashEntry(void *arg, char *key, char *value) {
} }
static void execService(int width, int height, struct Service *service, static void execService(int width, int height, struct Service *service,
const char *peerName, char **environment) { const char *peerName, char **environment,
const char *url) {
// Create a hash table with all the variables that we can expand. This // Create a hash table with all the variables that we can expand. This
// includes all environment variables being passed to the child. // includes all environment variables being passed to the child.
HashMap *vars; HashMap *vars;
@ -1059,6 +1066,8 @@ static void execService(int width, int height, struct Service *service,
addToHashMap(vars, key, value); addToHashMap(vars, key, value);
check(key = strdup("uid")); check(key = strdup("uid"));
addToHashMap(vars, key, stringPrintf(NULL, "%d", service->uid)); addToHashMap(vars, key, stringPrintf(NULL, "%d", service->uid));
check(key = strdup("url"));
addToHashMap(vars, key, strdup(url));
enum { ENV, ARGS } state = ENV; enum { ENV, ARGS } state = ENV;
enum { NONE, SINGLE, DOUBLE enum { NONE, SINGLE, DOUBLE
@ -1110,11 +1119,26 @@ static void execService(int width, int height, struct Service *service,
if (ch) { if (ch) {
end++; end++;
} }
int incr = replLen - (end - ptr);
if (incr > 0) {
char *oldCmdline = cmdline;
check(cmdline = realloc(cmdline,
(end - cmdline) + strlen(end) +
incr + 1));
ptr += cmdline - oldCmdline;
end += cmdline - oldCmdline;
if (key) {
key += cmdline - oldCmdline;
}
if (value) {
value += cmdline - oldCmdline;
}
}
memmove(ptr + replLen, end, strlen(end) + 1); memmove(ptr + replLen, end, strlen(end) + 1);
if (repl) { if (repl) {
memcpy(ptr, repl, replLen); memcpy(ptr, repl, replLen);
} }
ptr += replLen; ptr += replLen - 1;
} }
break; break;
case '\\': case '\\':
@ -1168,7 +1192,7 @@ static void execService(int width, int height, struct Service *service,
} else { } else {
// Add entry to argv. // Add entry to argv.
state = ARGS; state = ARGS;
argv[argc++] = key; argv[argc++] = strdup(key);
check(argv = realloc(argv, (argc + 1)*sizeof(char *))); check(argv = realloc(argv, (argc + 1)*sizeof(char *)));
} }
} }
@ -1183,6 +1207,7 @@ static void execService(int width, int height, struct Service *service,
} }
} }
done: done:
free(cmdline);
argv[argc] = NULL; argv[argc] = NULL;
deleteHashMap(vars); deleteHashMap(vars);
check(argc); check(argc);
@ -1217,7 +1242,8 @@ void setWindowSize(int pty, int width, int height) {
} }
static void childProcess(struct Service *service, int width, int height, static void childProcess(struct Service *service, int width, int height,
struct Utmp *utmp, const char *peerName) { struct Utmp *utmp, const char *peerName,
const char *url) {
// Set initial window size // Set initial window size
setWindowSize(0, width, height); setWindowSize(0, width, height);
@ -1343,7 +1369,7 @@ static void childProcess(struct Service *service, int width, int height,
execle("/usr/bin/login", "login", "-p", "-h", peerName, execle("/usr/bin/login", "login", "-p", "-h", peerName,
(void *)0, environment); (void *)0, environment);
} else { } else {
execService(width, height, service, peerName, environment); execService(width, height, service, peerName, environment, url);
} }
_exit(1); _exit(1);
} }
@ -1363,6 +1389,9 @@ static void launcherDaemon(int fd) {
errno = 0; errno = 0;
int len = read(fd, &request, sizeof(request)); int len = read(fd, &request, sizeof(request));
if (len != sizeof(request) && errno != EINTR) { if (len != sizeof(request) && errno != EINTR) {
if (len) {
debug("Failed to read launch request");
}
break; break;
} }
@ -1381,6 +1410,26 @@ static void launcherDaemon(int fd) {
continue; continue;
} }
char *url;
check(url = calloc(request.urlLength + 1, 1));
readURL:
len = read(fd, url, request.urlLength + 1);
if (len != request.urlLength + 1 && errno != EINTR) {
debug("Failed to read URL");
free(url);
break;
}
while (NOINTR(pid = waitpid(-1, &status, WNOHANG)) > 0) {
if (WIFEXITED(pid) || WIFSIGNALED(pid)) {
char key[32];
snprintf(&key[0], sizeof(key), "%d", pid);
deleteFromHashMap(childProcesses, key);
}
}
if (len != request.urlLength + 1) {
goto readURL;
}
check(request.service >= 0); check(request.service >= 0);
check(request.service < numServices); check(request.service < numServices);
@ -1403,11 +1452,13 @@ static void launcherDaemon(int fd) {
services[request.service]->useLogin, services[request.service]->useLogin,
&utmp, request.peerName)) == 0) { &utmp, request.peerName)) == 0) {
childProcess(services[request.service], request.width, request.height, childProcess(services[request.service], request.width, request.height,
utmp, request.peerName); utmp, request.peerName, url);
free(url);
_exit(1); _exit(1);
} else { } else {
// Remember the utmp entry so that we can clean up when the child // Remember the utmp entry so that we can clean up when the child
// terminates. // terminates.
free(url);
if (pid > 0) { if (pid > 0) {
if (!childProcesses) { if (!childProcesses) {
childProcesses = newHashMap(destroyUtmpHashEntry, NULL); childProcesses = newHashMap(destroyUtmpHashEntry, NULL);

View file

@ -55,10 +55,12 @@ struct LaunchRequest {
int service; int service;
int width, height; int width, height;
char peerName[128]; char peerName[128];
int urlLength;
char url[0];
}; };
int supportsPAM(void); int supportsPAM(void);
int launchChild(int service, struct Session *session); int launchChild(int service, struct Session *session, const char *url);
void setWindowSize(int pty, int width, int height); void setWindowSize(int pty, int width, int height);
int forkLauncher(void); int forkLauncher(void);
void terminateLauncher(void); void terminateLauncher(void);

View file

@ -355,7 +355,7 @@ ShellInABox.prototype.extendContextMenu = function(entries, actions) {
}; };
ShellInABox.prototype.about = function() { ShellInABox.prototype.about = function() {
alert("Shell In A Box version " + "2.9 (revision 172)" + alert("Shell In A Box version " + "2.9 (revision 174)" +
"\nCopyright 2008-2009 by Markus Gutschke\n" + "\nCopyright 2008-2009 by Markus Gutschke\n" +
"For more information check http://shellinabox.com" + "For more information check http://shellinabox.com" +
(typeof serverSupportsSSL != 'undefined' && serverSupportsSSL ? (typeof serverSupportsSSL != 'undefined' && serverSupportsSSL ?

View file

@ -341,6 +341,7 @@ static int dataHandler(HttpConnection *http, struct Service *service,
const char *width = getFromHashMap(args, "width"); const char *width = getFromHashMap(args, "width");
const char *height = getFromHashMap(args, "height"); const char *height = getFromHashMap(args, "height");
const char *keys = getFromHashMap(args, "keys"); const char *keys = getFromHashMap(args, "keys");
const char *rootURL = getFromHashMap(args, "rooturl");
// Adjust window dimensions if provided by client // Adjust window dimensions if provided by client
if (width && height) { if (width && height) {
@ -362,7 +363,8 @@ static int dataHandler(HttpConnection *http, struct Service *service,
goto bad_new_session; goto bad_new_session;
} }
session->http = http; session->http = http;
if (launchChild(service->id, session) < 0) { if (launchChild(service->id, session,
rootURL && *rootURL ? rootURL : urlGetURL(url)) < 0) {
abandonSession(session); abandonSession(session);
httpSendReply(http, 500, "Internal Error", NO_MSG); httpSendReply(http, 500, "Internal Error", NO_MSG);
return HTTP_DONE; return HTTP_DONE;
@ -809,7 +811,7 @@ static void parseArgs(int argc, char * const argv[]) {
HashMap *serviceTable = newHashMap(destroyServiceHashEntry, NULL); HashMap *serviceTable = newHashMap(destroyServiceHashEntry, NULL);
extern char stylesStart[]; extern char stylesStart[];
extern char stylesEnd[]; extern char stylesEnd[];
check(cssStyleSheet = malloc(stylesEnd - stylesStart)); check(cssStyleSheet = malloc(stylesEnd - stylesStart + 1));
memcpy(cssStyleSheet, stylesStart, stylesEnd - stylesStart); memcpy(cssStyleSheet, stylesStart, stylesEnd - stylesStart);
cssStyleSheet[stylesEnd - stylesStart] = '\000'; cssStyleSheet[stylesEnd - stylesStart] = '\000';

View file

@ -403,6 +403,9 @@ name of remote peer.
.B ${uid} .B ${uid}
numeric user id. numeric user id.
.TP .TP
.B ${url}
the URL that serves the terminal session.
.TP
.B ${user} .B ${user}
user name. user name.
.P .P

View file

@ -1892,7 +1892,7 @@ VT100.prototype.toggleBell = function() {
}; };
VT100.prototype.about = function() { VT100.prototype.about = function() {
alert("VT100 Terminal Emulator " + "2.9 (revision 172)" + alert("VT100 Terminal Emulator " + "2.9 (revision 174)" +
"\nCopyright 2008-2009 by Markus Gutschke\n" + "\nCopyright 2008-2009 by Markus Gutschke\n" +
"For more information check http://shellinabox.com"); "For more information check http://shellinabox.com");
}; };