Added --pidfile= option that can be used even if running in the foreground.
git-svn-id: https://shellinabox.googlecode.com/svn/trunk@223 0da03de8-d603-11dd-86c2-0f8696b7b6f9
This commit is contained in:
parent
61b40ad475
commit
bdf1ba75bd
9 changed files with 99 additions and 22 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2010-09-11 Markus Gutschke <markus@shellinabox.com>
|
||||||
|
|
||||||
|
* Added --pidfile= option that can be used even if running in the
|
||||||
|
foreground.
|
||||||
|
|
||||||
2010-09-04 Markus Gutschke <markus@shellinabox.com>
|
2010-09-04 Markus Gutschke <markus@shellinabox.com>
|
||||||
|
|
||||||
* Added an optional on-screen keyboard. Must be activated by the
|
* Added an optional on-screen keyboard. Must be activated by the
|
||||||
|
|
2
config.h
2
config.h
|
@ -153,7 +153,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 "222"
|
#define VCS_REVISION "223"
|
||||||
|
|
||||||
/* Version number of package */
|
/* Version number of package */
|
||||||
#define VERSION "2.10"
|
#define VERSION "2.10"
|
||||||
|
|
2
configure
vendored
2
configure
vendored
|
@ -2328,7 +2328,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=222
|
VCS_REVISION=223
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
|
|
@ -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.10, markus@shellinabox.com)
|
AC_INIT(shellinabox, 2.10, markus@shellinabox.com)
|
||||||
VCS_REVISION=222
|
VCS_REVISION=223
|
||||||
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])
|
||||||
|
|
|
@ -2384,7 +2384,7 @@ VT100.prototype.toggleCursorBlinking = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
VT100.prototype.about = function() {
|
VT100.prototype.about = function() {
|
||||||
alert("VT100 Terminal Emulator " + "2.10 (revision 222)" +
|
alert("VT100 Terminal Emulator " + "2.10 (revision 223)" +
|
||||||
"\nCopyright 2008-2010 by Markus Gutschke\n" +
|
"\nCopyright 2008-2010 by Markus Gutschke\n" +
|
||||||
"For more information check http://shellinabox.com");
|
"For more information check http://shellinabox.com");
|
||||||
};
|
};
|
||||||
|
|
|
@ -358,7 +358,7 @@ ShellInABox.prototype.extendContextMenu = function(entries, actions) {
|
||||||
};
|
};
|
||||||
|
|
||||||
ShellInABox.prototype.about = function() {
|
ShellInABox.prototype.about = function() {
|
||||||
alert("Shell In A Box version " + "2.10 (revision 222)" +
|
alert("Shell In A Box version " + "2.10 (revision 223)" +
|
||||||
"\nCopyright 2008-2010 by Markus Gutschke\n" +
|
"\nCopyright 2008-2010 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 ?
|
||||||
|
|
|
@ -52,6 +52,8 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -94,6 +96,9 @@ static char *cgiSessionKey;
|
||||||
static int cgiSessions;
|
static int cgiSessions;
|
||||||
static char *cssStyleSheet;
|
static char *cssStyleSheet;
|
||||||
static struct UserCSS *userCSSList;
|
static struct UserCSS *userCSSList;
|
||||||
|
static const char *pidfile;
|
||||||
|
static sigjmp_buf jmpenv;
|
||||||
|
static volatile int exiting;
|
||||||
|
|
||||||
static char *jsonEscape(const char *buf, int len) {
|
static char *jsonEscape(const char *buf, int len) {
|
||||||
static const char *hexDigit = "0123456789ABCDEF";
|
static const char *hexDigit = "0123456789ABCDEF";
|
||||||
|
@ -757,6 +762,7 @@ static void usage(void) {
|
||||||
" --localhost-only only listen on 127.0.0.1\n"
|
" --localhost-only only listen on 127.0.0.1\n"
|
||||||
" --no-beep suppress all audio output\n"
|
" --no-beep suppress all audio output\n"
|
||||||
" -n, --numeric do not resolve hostnames\n"
|
" -n, --numeric do not resolve hostnames\n"
|
||||||
|
" --pidfile=PIDFILE publish pid of daemon process\n"
|
||||||
" -p, --port=PORT select a port (default: %d)\n"
|
" -p, --port=PORT select a port (default: %d)\n"
|
||||||
" -s, --service=SERVICE define one or more services\n"
|
" -s, --service=SERVICE define one or more services\n"
|
||||||
"%s"
|
"%s"
|
||||||
|
@ -822,6 +828,13 @@ static void destroyExternalFileHashEntry(void *arg, char *key, char *value) {
|
||||||
free(value);
|
free(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sigHandler(int signo, siginfo_t *info, void *context) {
|
||||||
|
if (exiting++) {
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
siglongjmp(jmpenv, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static void parseArgs(int argc, char * const argv[]) {
|
static void parseArgs(int argc, char * const argv[]) {
|
||||||
int hasSSL = serverSupportsSSL();
|
int hasSSL = serverSupportsSSL();
|
||||||
if (!hasSSL) {
|
if (!hasSSL) {
|
||||||
|
@ -829,7 +842,6 @@ static void parseArgs(int argc, char * const argv[]) {
|
||||||
}
|
}
|
||||||
int demonize = 0;
|
int demonize = 0;
|
||||||
int cgi = 0;
|
int cgi = 0;
|
||||||
const char *pidfile = NULL;
|
|
||||||
int verbosity = MSG_DEFAULT;
|
int verbosity = MSG_DEFAULT;
|
||||||
externalFiles = newHashMap(destroyExternalFileHashEntry, NULL);
|
externalFiles = newHashMap(destroyExternalFileHashEntry, NULL);
|
||||||
HashMap *serviceTable = newHashMap(destroyServiceHashEntry, NULL);
|
HashMap *serviceTable = newHashMap(destroyServiceHashEntry, NULL);
|
||||||
|
@ -855,6 +867,7 @@ static void parseArgs(int argc, char * const argv[]) {
|
||||||
{ "localhost-only", 0, 0, 0 },
|
{ "localhost-only", 0, 0, 0 },
|
||||||
{ "no-beep", 0, 0, 0 },
|
{ "no-beep", 0, 0, 0 },
|
||||||
{ "numeric", 0, 0, 'n' },
|
{ "numeric", 0, 0, 'n' },
|
||||||
|
{ "pidfile", 1, 0, 0 },
|
||||||
{ "port", 1, 0, 'p' },
|
{ "port", 1, 0, 'p' },
|
||||||
{ "service", 1, 0, 's' },
|
{ "service", 1, 0, 's' },
|
||||||
{ "disable-ssl", 0, 0, 't' },
|
{ "disable-ssl", 0, 0, 't' },
|
||||||
|
@ -894,7 +907,7 @@ static void parseArgs(int argc, char * const argv[]) {
|
||||||
fatal("Only one pidfile can be given");
|
fatal("Only one pidfile can be given");
|
||||||
}
|
}
|
||||||
if (optarg && *optarg) {
|
if (optarg && *optarg) {
|
||||||
pidfile = strdup(optarg);
|
check(pidfile = strdup(optarg));
|
||||||
}
|
}
|
||||||
} else if (!idx--) {
|
} else if (!idx--) {
|
||||||
// Certificate
|
// Certificate
|
||||||
|
@ -957,6 +970,9 @@ static void parseArgs(int argc, char * const argv[]) {
|
||||||
if (demonize) {
|
if (demonize) {
|
||||||
fatal("CGI and background operations are mutually exclusive");
|
fatal("CGI and background operations are mutually exclusive");
|
||||||
}
|
}
|
||||||
|
if (pidfile) {
|
||||||
|
fatal("CGI operation and --pidfile= are mutually exclusive");
|
||||||
|
}
|
||||||
if (port) {
|
if (port) {
|
||||||
fatal("Cannot specify a port for CGI operation");
|
fatal("Cannot specify a port for CGI operation");
|
||||||
}
|
}
|
||||||
|
@ -987,7 +1003,7 @@ static void parseArgs(int argc, char * const argv[]) {
|
||||||
check(path = malloc(ptr - optarg + 1));
|
check(path = malloc(ptr - optarg + 1));
|
||||||
memcpy(path, optarg, ptr - optarg);
|
memcpy(path, optarg, ptr - optarg);
|
||||||
path[ptr - optarg] = '\000';
|
path[ptr - optarg] = '\000';
|
||||||
file = strdup(ptr + 1);
|
check(file = strdup(ptr + 1));
|
||||||
if (getRefFromHashMap(externalFiles, path)) {
|
if (getRefFromHashMap(externalFiles, path)) {
|
||||||
fatal("Duplicate static-file definition for \"%s\".", path);
|
fatal("Duplicate static-file definition for \"%s\".", path);
|
||||||
}
|
}
|
||||||
|
@ -1022,6 +1038,18 @@ static void parseArgs(int argc, char * const argv[]) {
|
||||||
} else if (!idx--) {
|
} else if (!idx--) {
|
||||||
// Numeric
|
// Numeric
|
||||||
numericHosts = 1;
|
numericHosts = 1;
|
||||||
|
} else if (!idx--) {
|
||||||
|
// Pidfile
|
||||||
|
if (cgi) {
|
||||||
|
fatal("CGI operation and --pidfile= are mutually exclusive");
|
||||||
|
}
|
||||||
|
if (!optarg || !*optarg) {
|
||||||
|
fatal("Must specify a filename for --pidfile= option");
|
||||||
|
}
|
||||||
|
if (pidfile) {
|
||||||
|
fatal("Only one pidfile can be given");
|
||||||
|
}
|
||||||
|
check(pidfile = strdup(optarg));
|
||||||
} else if (!idx--) {
|
} else if (!idx--) {
|
||||||
// Port
|
// Port
|
||||||
if (port) {
|
if (port) {
|
||||||
|
@ -1138,21 +1166,23 @@ static void parseArgs(int argc, char * const argv[]) {
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
setsid();
|
setsid();
|
||||||
if (pidfile) {
|
}
|
||||||
|
if (pidfile) {
|
||||||
#ifndef O_LARGEFILE
|
#ifndef O_LARGEFILE
|
||||||
#define O_LARGEFILE 0
|
#define O_LARGEFILE 0
|
||||||
#endif
|
#endif
|
||||||
int fd = NOINTR(open(pidfile,
|
int fd = NOINTR(open(pidfile,
|
||||||
O_WRONLY|O_TRUNC|O_LARGEFILE|O_CREAT,
|
O_WRONLY|O_TRUNC|O_LARGEFILE|O_CREAT,
|
||||||
0644));
|
0644));
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
char buf[40];
|
char buf[40];
|
||||||
NOINTR(write(fd, buf, snprintf(buf, 40, "%d", (int)getpid())));
|
NOINTR(write(fd, buf, snprintf(buf, 40, "%d", (int)getpid())));
|
||||||
check(!NOINTR(close(fd)));
|
check(!NOINTR(close(fd)));
|
||||||
}
|
} else {
|
||||||
|
free((char *)pidfile);
|
||||||
|
pidfile = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free((char *)pidfile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void removeLimits() {
|
static void removeLimits() {
|
||||||
|
@ -1278,7 +1308,20 @@ int main(int argc, char * const argv[]) {
|
||||||
iterateOverHashMap(externalFiles, registerExternalFiles, server);
|
iterateOverHashMap(externalFiles, registerExternalFiles, server);
|
||||||
|
|
||||||
// Start the server
|
// Start the server
|
||||||
serverLoop(server);
|
if (!sigsetjmp(jmpenv, 1)) {
|
||||||
|
// Clean up upon orderly shut down. Do _not_ cleanup if we die
|
||||||
|
// unexpectedly, as we cannot guarantee if we are still in a valid
|
||||||
|
// static. This means, we should never catch SIGABRT.
|
||||||
|
static const int signals[] = { SIGHUP, SIGINT, SIGQUIT, SIGTERM };
|
||||||
|
struct sigaction sa;
|
||||||
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
sa.sa_sigaction = sigHandler;
|
||||||
|
sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
|
||||||
|
for (int i = 0; i < sizeof(signals)/sizeof(*signals); ++i) {
|
||||||
|
sigaction(signals[i], &sa, NULL);
|
||||||
|
}
|
||||||
|
serverLoop(server);
|
||||||
|
}
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
deleteServer(server);
|
deleteServer(server);
|
||||||
|
@ -1290,6 +1333,27 @@ int main(int argc, char * const argv[]) {
|
||||||
free(services);
|
free(services);
|
||||||
free(certificateDir);
|
free(certificateDir);
|
||||||
free(cgiSessionKey);
|
free(cgiSessionKey);
|
||||||
|
if (pidfile) {
|
||||||
|
// As a convenience, remove the pidfile, if it is still the version that
|
||||||
|
// we wrote. In general, pidfiles are not expected to be incredibly
|
||||||
|
// reliable, as there is no way to properly deal with multiple programs
|
||||||
|
// accessing the same pidfile. But we at least make a best effort to be
|
||||||
|
// good citizens.
|
||||||
|
char buf[40];
|
||||||
|
int fd = open(pidfile, O_RDONLY);
|
||||||
|
if (fd >= 0) {
|
||||||
|
ssize_t sz;
|
||||||
|
NOINTR(sz = read(fd, buf, sizeof(buf)-1));
|
||||||
|
NOINTR(close(fd));
|
||||||
|
if (sz > 0) {
|
||||||
|
buf[sz] = '\000';
|
||||||
|
if (atoi(buf) == getpid()) {
|
||||||
|
unlink(pidfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free((char *)pidfile);
|
||||||
|
}
|
||||||
info("Done");
|
info("Done");
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
'\" t
|
'\" t
|
||||||
.\" shellinaboxd.man -- Make command line applications available as AJAX web applications
|
.\" shellinaboxd.man -- Make command line applications available as AJAX web applications
|
||||||
.\" Copyright (C) 2008-2009 Markus Gutschke <markus@shellinabox.com>
|
.\" Copyright (C) 2008-2010 Markus Gutschke <markus@shellinabox.com>
|
||||||
.\"
|
.\"
|
||||||
.\" This program is free software; you can redistribute it and/or modify
|
.\" This program is free software; you can redistribute it and/or modify
|
||||||
.\" it under the terms of the GNU General Public License version 2 as
|
.\" it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
.\" The most up-to-date version of this program is always available from
|
.\" The most up-to-date version of this program is always available from
|
||||||
.\" http://shellinabox.com
|
.\" http://shellinabox.com
|
||||||
.\"
|
.\"
|
||||||
.TH SHELLINABOXD 1 "Dec 03, 2009"
|
.TH SHELLINABOXD 1 "Sep 11, 2010"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
shellinaboxd \- publish command line shell through AJAX interface
|
shellinaboxd \- publish command line shell through AJAX interface
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
@ -65,6 +65,7 @@ shellinaboxd \- publish command line shell through AJAX interface
|
||||||
[\ \fB--localhost-only\fP\ ]
|
[\ \fB--localhost-only\fP\ ]
|
||||||
[\ \fB--no-beep\fP\ ]
|
[\ \fB--no-beep\fP\ ]
|
||||||
[\ \fB-n\fP\ | \fB--numeric\fP\ ]
|
[\ \fB-n\fP\ | \fB--numeric\fP\ ]
|
||||||
|
[\ \fB--pidfile=\fP\fIpidfile\fP\ ]
|
||||||
[\ \fB-p\fP\ | \fB--port=\fP\fIport\fP\ ]
|
[\ \fB-p\fP\ | \fB--port=\fP\fIport\fP\ ]
|
||||||
[\ \fB-s\fP\ | \fB--service=\fP\fIservice\fP\ ]
|
[\ \fB-s\fP\ | \fB--service=\fP\fIservice\fP\ ]
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
|
@ -188,7 +189,8 @@ should be configured to pass through the firewall.
|
||||||
The
|
The
|
||||||
.B --cgi
|
.B --cgi
|
||||||
option is mutually exclusive with the
|
option is mutually exclusive with the
|
||||||
.B --background
|
.BR --background ,
|
||||||
|
.B --pidfile
|
||||||
and
|
and
|
||||||
.B --port
|
.B --port
|
||||||
options.
|
options.
|
||||||
|
@ -312,6 +314,12 @@ By default, host names of peers get resolved
|
||||||
before logging them. As DNS look-ups can be expensive, it is possible
|
before logging them. As DNS look-ups can be expensive, it is possible
|
||||||
to request logging of numeric IP addresses, instead.
|
to request logging of numeric IP addresses, instead.
|
||||||
.TP
|
.TP
|
||||||
|
\fB--pidfile=\fP\fIpidfile\fP
|
||||||
|
The
|
||||||
|
.B shellinaboxd
|
||||||
|
daemon can be configured to store its process identifier in
|
||||||
|
.IR pidfile .
|
||||||
|
.TP
|
||||||
\fB-p\fP\ |\ \fB--port=\fP\fIport\fP
|
\fB-p\fP\ |\ \fB--port=\fP\fIport\fP
|
||||||
Unless overridden by this option, the web server listens on port 4200
|
Unless overridden by this option, the web server listens on port 4200
|
||||||
for incoming HTTP and HTTPS requests.
|
for incoming HTTP and HTTPS requests.
|
||||||
|
@ -798,7 +806,7 @@ and
|
||||||
.B --user
|
.B --user
|
||||||
options should be used to change to a dedicated user.
|
options should be used to change to a dedicated user.
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
Copyright (C) 2008-2009 by Markus Gutschke
|
Copyright (C) 2008-2010 by Markus Gutschke
|
||||||
.RI < "markus@shellinabox.com" >.
|
.RI < "markus@shellinabox.com" >.
|
||||||
.P
|
.P
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
|
|
@ -2384,7 +2384,7 @@ VT100.prototype.toggleCursorBlinking = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
VT100.prototype.about = function() {
|
VT100.prototype.about = function() {
|
||||||
alert("VT100 Terminal Emulator " + "2.10 (revision 222)" +
|
alert("VT100 Terminal Emulator " + "2.10 (revision 223)" +
|
||||||
"\nCopyright 2008-2010 by Markus Gutschke\n" +
|
"\nCopyright 2008-2010 by Markus Gutschke\n" +
|
||||||
"For more information check http://shellinabox.com");
|
"For more information check http://shellinabox.com");
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue