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:
zodiac@gmail.com 2010-09-11 19:32:30 +00:00
parent 61b40ad475
commit bdf1ba75bd
9 changed files with 99 additions and 22 deletions

View file

@ -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>
* Added an optional on-screen keyboard. Must be activated by the

View file

@ -153,7 +153,7 @@
#define STDC_HEADERS 1
/* Most recent revision number in the version control system */
#define VCS_REVISION "222"
#define VCS_REVISION "223"
/* Version number of package */
#define VERSION "2.10"

2
configure vendored
View file

@ -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
VCS_REVISION=222
VCS_REVISION=223
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
AC_INIT(shellinabox, 2.10, markus@shellinabox.com)
VCS_REVISION=222
VCS_REVISION=223
AC_SUBST(VCS_REVISION)
AC_DEFINE_UNQUOTED(VCS_REVISION, "${VCS_REVISION}",
[Most recent revision number in the version control system])

View file

@ -2384,7 +2384,7 @@ VT100.prototype.toggleCursorBlinking = 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" +
"For more information check http://shellinabox.com");
};

View file

@ -358,7 +358,7 @@ ShellInABox.prototype.extendContextMenu = function(entries, actions) {
};
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" +
"For more information check http://shellinabox.com" +
(typeof serverSupportsSSL != 'undefined' && serverSupportsSSL ?

View file

@ -52,6 +52,8 @@
#include <limits.h>
#include <locale.h>
#include <poll.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@ -94,6 +96,9 @@ static char *cgiSessionKey;
static int cgiSessions;
static char *cssStyleSheet;
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 const char *hexDigit = "0123456789ABCDEF";
@ -757,6 +762,7 @@ static void usage(void) {
" --localhost-only only listen on 127.0.0.1\n"
" --no-beep suppress all audio output\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"
" -s, --service=SERVICE define one or more services\n"
"%s"
@ -822,6 +828,13 @@ static void destroyExternalFileHashEntry(void *arg, char *key, char *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[]) {
int hasSSL = serverSupportsSSL();
if (!hasSSL) {
@ -829,7 +842,6 @@ static void parseArgs(int argc, char * const argv[]) {
}
int demonize = 0;
int cgi = 0;
const char *pidfile = NULL;
int verbosity = MSG_DEFAULT;
externalFiles = newHashMap(destroyExternalFileHashEntry, NULL);
HashMap *serviceTable = newHashMap(destroyServiceHashEntry, NULL);
@ -855,6 +867,7 @@ static void parseArgs(int argc, char * const argv[]) {
{ "localhost-only", 0, 0, 0 },
{ "no-beep", 0, 0, 0 },
{ "numeric", 0, 0, 'n' },
{ "pidfile", 1, 0, 0 },
{ "port", 1, 0, 'p' },
{ "service", 1, 0, 's' },
{ "disable-ssl", 0, 0, 't' },
@ -894,7 +907,7 @@ static void parseArgs(int argc, char * const argv[]) {
fatal("Only one pidfile can be given");
}
if (optarg && *optarg) {
pidfile = strdup(optarg);
check(pidfile = strdup(optarg));
}
} else if (!idx--) {
// Certificate
@ -957,6 +970,9 @@ static void parseArgs(int argc, char * const argv[]) {
if (demonize) {
fatal("CGI and background operations are mutually exclusive");
}
if (pidfile) {
fatal("CGI operation and --pidfile= are mutually exclusive");
}
if (port) {
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));
memcpy(path, optarg, ptr - optarg);
path[ptr - optarg] = '\000';
file = strdup(ptr + 1);
check(file = strdup(ptr + 1));
if (getRefFromHashMap(externalFiles, path)) {
fatal("Duplicate static-file definition for \"%s\".", path);
}
@ -1022,6 +1038,18 @@ static void parseArgs(int argc, char * const argv[]) {
} else if (!idx--) {
// Numeric
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--) {
// Port
if (port) {
@ -1138,6 +1166,7 @@ static void parseArgs(int argc, char * const argv[]) {
_exit(0);
}
setsid();
}
if (pidfile) {
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
@ -1149,10 +1178,11 @@ static void parseArgs(int argc, char * const argv[]) {
char buf[40];
NOINTR(write(fd, buf, snprintf(buf, 40, "%d", (int)getpid())));
check(!NOINTR(close(fd)));
}
}
}
} else {
free((char *)pidfile);
pidfile = NULL;
}
}
}
static void removeLimits() {
@ -1278,7 +1308,20 @@ int main(int argc, char * const argv[]) {
iterateOverHashMap(externalFiles, registerExternalFiles, server);
// Start the 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
deleteServer(server);
@ -1290,6 +1333,27 @@ int main(int argc, char * const argv[]) {
free(services);
free(certificateDir);
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");
_exit(0);
}

View file

@ -1,6 +1,6 @@
'\" t
.\" 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
.\" 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
.\" http://shellinabox.com
.\"
.TH SHELLINABOXD 1 "Dec 03, 2009"
.TH SHELLINABOXD 1 "Sep 11, 2010"
.SH NAME
shellinaboxd \- publish command line shell through AJAX interface
.SH SYNOPSIS
@ -65,6 +65,7 @@ shellinaboxd \- publish command line shell through AJAX interface
[\ \fB--localhost-only\fP\ ]
[\ \fB--no-beep\fP\ ]
[\ \fB-n\fP\ | \fB--numeric\fP\ ]
[\ \fB--pidfile=\fP\fIpidfile\fP\ ]
[\ \fB-p\fP\ | \fB--port=\fP\fIport\fP\ ]
[\ \fB-s\fP\ | \fB--service=\fP\fIservice\fP\ ]
#ifdef HAVE_OPENSSL
@ -188,7 +189,8 @@ should be configured to pass through the firewall.
The
.B --cgi
option is mutually exclusive with the
.B --background
.BR --background ,
.B --pidfile
and
.B --port
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
to request logging of numeric IP addresses, instead.
.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
Unless overridden by this option, the web server listens on port 4200
for incoming HTTP and HTTPS requests.
@ -798,7 +806,7 @@ and
.B --user
options should be used to change to a dedicated user.
.SH AUTHOR
Copyright (C) 2008-2009 by Markus Gutschke
Copyright (C) 2008-2010 by Markus Gutschke
.RI < "markus@shellinabox.com" >.
.P
This program is free software; you can redistribute it and/or modify

View file

@ -2384,7 +2384,7 @@ VT100.prototype.toggleCursorBlinking = 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" +
"For more information check http://shellinabox.com");
};