Logging and debuging

* Added prefixes to all log messages. Prefix should describe source of
  message, like "config", "http", "ssl", "server", etc... This should
  give users more info to figure out what went wrong or what is going
  on. Prefixes also make automatic processing easier.
* Usage is not displayed by default when given command line options are
  incorrect. This way it is easier to notice actual error.
This commit is contained in:
KLuka 2015-08-23 19:24:35 +02:00
parent d74e60b6a7
commit 6c9f98bf34
11 changed files with 149 additions and 141 deletions

View file

@ -88,7 +88,7 @@
static int httpPromoteToSSL(struct HttpConnection *http, const char *buf,
int len) {
if (http->ssl->enabled && !http->sslHndl) {
debug("SSL: switching to SSL (replaying %d+%d bytes)",
debug("[ssl] Switching to SSL (replaying %d+%d bytes)...",
http->partialLength, len);
if (http->partial && len > 0) {
check(http->partial = realloc(http->partial,
@ -143,7 +143,7 @@ static ssize_t httpRead(struct HttpConnection *http, char *buf, ssize_t len) {
// Shutdown SSL connection, if client initiated renegotiation.
if (http->ssl->renegotiationCount > 1) {
debug("SSL: connection shutdown due to client initiated renegotiation!");
debug("[ssl] Connection shutdown due to client initiated renegotiation!");
rc = 0;
errno = EINVAL;
}
@ -273,7 +273,7 @@ static int httpFinishCommand(struct HttpConnection *http) {
*lengthBuf = '\000';
strncat(lengthBuf, "-", sizeof(lengthBuf)-1);
}
info("%s - - %s \"%s %s %s\" %d %s",
info("[http] %s - - %s \"%s %s %s\" %d %s",
http->peerName, timeBuf, http->method, http->path, http->version,
http->code, lengthBuf);
}
@ -405,7 +405,7 @@ void initHttpConnection(struct HttpConnection *http, struct Server *server,
http->sslHndl = NULL;
http->lastError = 0;
if (logIsInfo()) {
debug("Accepted connection from %s:%d",
debug("[http] Accepted connection from %s:%d",
http->peerName ? http->peerName : "???", http->peerPort);
}
}
@ -426,7 +426,7 @@ void destroyHttpConnection(struct HttpConnection *http) {
}
httpSetState(http, COMMAND);
if (logIsInfo()) {
debug("Closing connection to %s:%d",
debug("[http] Closing connection to %s:%d",
http->peerName ? http->peerName : "???", http->peerPort);
}
httpShutdown(http, http->closed ? SHUT_WR : SHUT_RDWR);
@ -661,7 +661,7 @@ void httpTransfer(struct HttpConnection *http, char *msg, int len) {
31, 8, Z_DEFAULT_STRATEGY) == Z_OK) {
if (deflate(&strm, Z_FINISH) == Z_STREAM_END) {
// Compression was successful and resulted in reduction in size
debug("Compressed response from %d to %d", len, len-strm.avail_out);
debug("[http] Compressed response from %d to %d", len, len-strm.avail_out);
free(msg);
msg = compressed;
len -= strm.avail_out;
@ -757,7 +757,7 @@ void httpTransfer(struct HttpConnection *http, char *msg, int len) {
if (!http->isPartialReply) {
if (http->expecting < 0) {
// If we do not know the length of the content, close the connection.
debug("Closing previously suspended connection");
debug("[http] Closing previously suspended connection!");
httpCloseRead(http);
httpSetState(http, DISCARD_PAYLOAD);
} else if (http->expecting == 0) {
@ -786,7 +786,7 @@ void httpTransferPartialReply(struct HttpConnection *http, char *msg, int len){
static int httpHandleCommand(struct HttpConnection *http,
const struct Trie *handlers) {
debug("Handling \"%s\" \"%s\"", http->method, http->path);
debug("[http] Handling \"%s\" \"%s\"", http->method, http->path);
const char *contentLength = getFromHashMap(&http->header,
"content-length");
if (contentLength != NULL && *contentLength) {
@ -901,7 +901,7 @@ static int httpHandleCommand(struct HttpConnection *http,
protocol ? protocol : "",
protocol ? "\r\n" : "");
free(port);
debug("Switching to WebSockets");
debug("[http] Switching to WebSockets");
httpTransfer(http, response, strlen(response));
if (http->expecting < 0) {
http->expecting = 0;
@ -1158,7 +1158,7 @@ static int httpParseHeaders(struct HttpConnection *http,
}
value[j] = '\000';
if (getRefFromHashMap(&http->header, http->key)) {
debug("Dropping duplicate header \"%s\"", http->key);
debug("[http] Dropping duplicate header \"%s\"", http->key);
free(http->key);
free(value);
http->key = NULL;

View file

@ -309,19 +309,20 @@ void initServer(struct Server *server, int localhostOnly, int portMin,
+ strlen(unixDomainPath);
if (bind(server->serverFd, (struct sockaddr *)&serverAddr, servlen)) {
fatal("Failed to bind to unix socket! [%d: %s]", errno, strerror(errno));
fatal("[server] Failed to bind to unix socket! [%d: %s]",
errno, strerror(errno));
}
if (chown(unixDomainPath, unixDomainUser, unixDomainGroup)) {
fatal("Unable to change ownership on unix socket! [%d: %s]",
fatal("[server] Unable to change ownership on unix socket! [%d: %s]",
errno, strerror(errno));
}
if (chmod(unixDomainPath, unixDomainChmod)) {
fatal("Unable to change premission on unix socket! [%d: %s)",
fatal("[server] Unable to change permission on unix socket! [%d: %s]",
errno, strerror(errno));
}
check(!listen(server->serverFd, SOMAXCONN));
info("Listening on unix domain socket %s", unixDomainPath);
info("[server] Listening on unix domain socket %s...", unixDomainPath);
check(server->pollFds = malloc(sizeof(struct pollfd)));
server->pollFds->fd = server->serverFd;
server->pollFds->events = POLLIN;
@ -362,7 +363,7 @@ void initServer(struct Server *server, int localhostOnly, int portMin,
serverAddr.sin_port = 0;
}
if (!serverAddr.sin_port) {
fatal("Failed to find any available port");
fatal("[server] Failed to find any available port!");
}
}
@ -372,7 +373,7 @@ void initServer(struct Server *server, int localhostOnly, int portMin,
&socklen));
check(socklen == sizeof(serverAddr));
server->port = ntohs(serverAddr.sin_port);
info("Listening on port %d", server->port);
info("[server] Listening on port %d...", server->port);
check(server->pollFds = malloc(sizeof(struct pollfd)));
server->pollFds->fd = server->serverFd;
@ -386,7 +387,7 @@ void initServer(struct Server *server, int localhostOnly, int portMin,
void destroyServer(struct Server *server) {
if (server) {
if (server->serverFd >= 0) {
info("Shutting down server");
info("[server] Shutting down server");
NOINTR(close(server->serverFd));
}
for (int i = 0; i < server->numConnections; i++) {

View file

@ -327,7 +327,7 @@ static void loadSSL(void) {
};
for (unsigned i = 0; i < sizeof(symbols)/sizeof(symbols[0]); i++) {
if (!(*symbols[i].var = loadSymbol(path_libssl, symbols[i].fn))) {
debug("SSL: failed to load SSL support. Could not find \"%s\"",
debug("[ssl] Failed to load SSL support. Could not find \"%s\"!",
symbols[i].fn);
for (unsigned j = 0; j < sizeof(symbols)/sizeof(symbols[0]); j++) {
*symbols[j].var = NULL;
@ -342,7 +342,7 @@ static void loadSSL(void) {
SSL_library_init();
dcheck(!ERR_peek_error());
debug("SSL: loaded SSL suppport");
debug("[ssl] Loaded SSL suppport...");
}
#endif
@ -379,12 +379,12 @@ int serverSupportsSSL(void) {
#if defined(HAVE_OPENSSL)
static void sslGenerateCertificate(const char *certificate,
const char *serverName) {
debug("SSL: auto-generating missing certificate \"%s\" for \"%s\"",
info("[ssl] Auto-generating missing certificate \"%s\" for \"%s\"...",
certificate, serverName);
pid_t pid = fork();
if (pid == -1) {
warn("SSL: failed to generate self-signed certificate \"%s\"", certificate);
warn("[ssl] Failed to generate self-signed certificate \"%s\"!", certificate);
} else if (pid == 0) {
int fd = NOINTR(open("/dev/null", O_RDONLY));
check(fd != -1);
@ -401,14 +401,16 @@ static void sslGenerateCertificate(const char *certificate,
if (execlp("openssl", "openssl", "req", "-x509", "-nodes", "-days", "7300",
"-newkey", "rsa:2048", "-keyout", certificate, "-out", certificate,
"-subj", subject, (char *)NULL) < 0) {
warn("SSL: failed to generate self-signed certificate \"%s\"", certificate);
warn("[ssl] Failed to generate self-signed certificate \"%s\"!", certificate);
free(subject);
}
} else {
int status;
check(NOINTR(waitpid(pid, &status, 0)) == pid);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
warn("SSL: failed to generate self-signed certificate \"%s\"", certificate);
warn("[ssl] Failed to generate self-signed certificate \"%s\"!", certificate);
} else {
info("[ssl] Certificate succesfully generated.");
}
}
}
@ -657,7 +659,7 @@ static SSL_CTX *sslMakeContext(void) {
SSL_CTX_set_tmp_ecdh(context, ecKey);
EC_KEY_free(ecKey);
debug("SSL: support for PFS enabled...");
debug("[ssl] Support for PFS enabled...");
#endif
check(SSL_CTX_set_cipher_list(context,
@ -672,7 +674,7 @@ static SSL_CTX *sslMakeContext(void) {
SSL_CTX_set_info_callback(context, sslInfoCallback);
debug("SSL: server context succesfully initialized...");
debug("[ssl] Server context succesfully initialized...");
return context;
}
#endif
@ -689,7 +691,7 @@ static int sslSNICallback(SSL *sslHndl, int *al ATTR_UNUSED,
}
struct HttpConnection *http =
(struct HttpConnection *)SSL_get_app_data(sslHndl);
debug("SSL: received SNI callback for virtual host \"%s\" from \"%s:%d\"",
debug("[ssl] Received SNI callback for virtual host \"%s\" from \"%s:%d\"...",
name, httpGetPeerName(http), httpGetPort(http));
char *serverName;
check(serverName = malloc(strlen(name)+2));
@ -726,7 +728,7 @@ static int sslSNICallback(SSL *sslHndl, int *al ATTR_UNUSED,
// the default certificate, instead.
sslSetCertificateFromFile(context, certificate);
} else {
warn("SSL: could not find matching certificate \"%s\" for \"%s\"",
warn("[ssl] Could not find matching certificate \"%s\" for \"%s\"",
certificate, serverName + 1);
SSL_CTX_free(context);
context = ssl->sslContext;
@ -803,7 +805,7 @@ void sslSetCertificate(struct SSLSupport *ssl, const char *filename,
sslGenerateCertificate(defaultCertificate, he->h_name);
} else {
if (h_err) {
warn("SSL: error getting host information: \"%s\".", hstrerror(h_err));
warn("[ssl] Error getting host information: \"%s\".", hstrerror(h_err));
}
sslGenerateCertificate(defaultCertificate, hostname);
}
@ -812,7 +814,7 @@ void sslSetCertificate(struct SSLSupport *ssl, const char *filename,
}
}
if (sslSetCertificateFromFile(ssl->sslContext, defaultCertificate) < 0) {
fatal("SSL: cannot read valid certificate from \"%s\". "
fatal("[ssl] Cannot read valid certificate from \"%s\"! "
"Check file permissions and file format.", defaultCertificate);
}
valid_certificate:
@ -878,7 +880,7 @@ void sslSetCertificateFd(struct SSLSupport *ssl, int fd) {
ssl->sslContext = sslMakeContext();
char *filename = sslFdToFilename(fd);
if (!sslSetCertificateFromFd(ssl->sslContext, fd)) {
fatal("SSL: cannot read valid certificate from %s. Check file format.",
fatal("[ssl] Cannot read valid certificate from %s. Check file format.",
filename);
}
free(filename);
@ -1051,7 +1053,7 @@ void sslFreeHndl(SSL **sslHndl) {
// We do not know, how to fix this situation. Something must have
// changed in the OpenSSL internals. Either, this is a new bug, or
// somebody fixed the code in a way that we did not anticipate.
fatal("SSL: unexpected corruption of OpenSSL data structures");
fatal("[ssl] Unexpected corruption of OpenSSL data structures");
}
}
SSL_free(*sslHndl);

View file

@ -82,10 +82,10 @@ static char *urlUnescape(char *s) {
ch = (ch << 4) + c2 - (c2 > '9' ? 'A' - 10 : '0');
++u;
} else if (!warned++) {
warn("Malformed URL encoded data \"%s\"", r);
warn("[http] Malformed URL encoded data \"%s\"!", r);
}
} else if (!warned++) {
warn("Malformed URL encoded data \"%s\"", r);
warn("[http] Malformed URL encoded data \"%s\"!", r);
}
}
*s++ = ch;
@ -297,7 +297,7 @@ static void urlParsePostBody(struct URL *url,
urlParsePart(url, lastPart, ptr - lastPart);
} else {
if (ptr != buf) {
info("Ignoring prologue before \"multipart/form-data\"");
info("[http] Ignoring prologue before \"multipart/form-data\"!");
}
}
lastPart = part;
@ -307,18 +307,18 @@ static void urlParsePostBody(struct URL *url,
urlParsePart(url, lastPart, ptr - lastPart);
lastPart = NULL;
if (len > 0) {
info("Ignoring epilogue past end of \"multipart/"
"form-data\"");
info("[http] Ignoring epilogue past end of \"multipart/"
"form-data\"!");
}
}
}
}
}
if (lastPart) {
warn("Missing final \"boundary\" for \"multipart/form-data\"");
warn("[http] Missing final \"boundary\" for \"multipart/form-data\"!");
}
} else {
warn("Missing \"boundary\" information for \"multipart/form-data\"");
warn("[http] Missing \"boundary\" information for \"multipart/form-data\"!");
}
}
destroyHashMap(&contentType);

View file

@ -118,7 +118,7 @@ void fatal(const char *fmt, ...) {
debugMsg(MSG_QUIET, fmt, ap);
#ifdef HAVE_SYSLOG_H
vsyslog(LOG_CRIT, fmt, ap);
syslog(LOG_CRIT, "Aborting...");
syslog(LOG_CRIT, "[server] Aborting...");
#endif
va_end(ap);
_exit(1);

View file

@ -430,7 +430,7 @@ static void loadPAM(void) {
*symbols[i].var = (void *)my_misc_conv;
continue;
}
debug("Failed to load PAM support. Could not find \"%s\"",
debug("[server] Failed to load PAM support. Could not find \"%s\"!",
symbols[i].fn);
for (unsigned j = 0; j < sizeof(symbols)/sizeof(symbols[0]); j++) {
*symbols[j].var = NULL;
@ -438,7 +438,7 @@ static void loadPAM(void) {
return;
}
}
debug("Loaded PAM suppport");
debug("[server] Loaded PAM suppport");
}
#endif
@ -566,7 +566,7 @@ int terminateChild(struct Session *session) {
}
if (session->pid < 1) {
debug("Child pid for termination not valid!");
debug("[server] Child pid for termination not valid!");
return -1;
}
@ -576,7 +576,7 @@ int terminateChild(struct Session *session) {
check(request = calloc(len, 1));
request->terminate = session->pid;
if (NOINTR(write(launcher, request, len)) != len) {
debug("Child %d termination request failed!", request->terminate);
debug("[server] Child %d termination request failed!", request->terminate);
free(request);
return -1;
}
@ -850,7 +850,7 @@ static int forkPty(int *pty, int useLogin, struct Utmp **utmp,
ptyPath[5] = 't';
}
if ((slave = NOINTR(open(ptyPath, O_RDWR|O_NOCTTY))) >= 0) {
debug("Opened old-style pty: %s", ptyPath);
debug("[server] Opened old-style pty: %s", ptyPath);
goto success;
}
NOINTR(close(*pty));
@ -1672,7 +1672,7 @@ static void launcherDaemon(int fd) {
int len = read(fd, &request, sizeof(request));
if (len != sizeof(request) && errno != EINTR) {
if (len) {
debug("Failed to read launch request");
debug("[server] Failed to read launch request!");
}
break;
}
@ -1682,7 +1682,8 @@ static void launcherDaemon(int fd) {
int status;
pid_t pid;
while (NOINTR(pid = waitpid(-1, &status, WNOHANG)) > 0) {
debug("Child %d exited with exit code %d", pid, WEXITSTATUS(status));
debug("[server] Child %d exited with exit code %d.",
pid, WEXITSTATUS(status));
if (WIFEXITED(status) || WIFSIGNALED(status)) {
char key[32];
snprintf(&key[0], sizeof(key), "%d", pid);
@ -1700,9 +1701,9 @@ static void launcherDaemon(int fd) {
NOINTR(pid = waitpid(request.terminate, &status, WNOHANG));
if (pid == 0 && errno == 0) {
if (kill(request.terminate, SIGTERM) == 0) {
debug("Terminating child %d (kill)", request.terminate);
debug("[server] Terminating child %d! [kill]", request.terminate);
} else {
debug("Terminating child %d failed [%s]", request.terminate,
debug("[server] Terminating child %d failed! [%s]", request.terminate,
strerror(errno));
}
}
@ -1714,12 +1715,13 @@ static void launcherDaemon(int fd) {
readURL:
len = read(fd, url, request.urlLength + 1);
if (len != request.urlLength + 1 && errno != EINTR) {
debug("Failed to read URL");
debug("[server] Failed to read URL!");
free(url);
break;
}
while (NOINTR(pid = waitpid(-1, &status, WNOHANG)) > 0) {
debug("Child %d exited with exit code %d", pid, WEXITSTATUS(status));
debug("[server] Child %d exited with exit code %d.", pid,
WEXITSTATUS(status));
if (WIFEXITED(status) || WIFSIGNALED(status)) {
char key[32];
snprintf(&key[0], sizeof(key), "%d", pid);
@ -1776,7 +1778,7 @@ static void launcherDaemon(int fd) {
childProcesses = newHashMap(destroyUtmpHashEntry, NULL);
}
addToHashMap(childProcesses, utmp->pid, (char *)utmp);
debug("Child %d launched", pid);
debug("[server] Child %d launched", pid);
} else {
int fds[2];
if (!pipe(fds)) {
@ -1830,9 +1832,9 @@ int forkLauncher(void) {
lowerPrivileges();
closeAllFds((int []){ pair[1], 2 }, 2);
launcherDaemon(pair[1]);
fatal("exit() failed!");
fatal("[server] Launcher exit() failed!");
case -1:
fatal("fork() failed!");
fatal("[server] Launcher fork() failed!");
default:
NOINTR(close(pair[1]));
launcher = pair[0];

View file

@ -110,7 +110,7 @@ static void removeGroupPrivileges(int showError) {
if ((ru && runAsGroup != (int)rg) ||
setresgid(runAsGroup, runAsGroup, runAsGroup)) {
if (showError) {
fatal("Only privileged users can change their group memberships");
fatal("[server] Only privileged users can change their group membership!");
} else {
_exit(1);
}
@ -142,7 +142,7 @@ void lowerPrivileges(void) {
if (runAsUser >= 0) {
// Try to switch to the user-provided user id.
if (r && runAsUser != (int)r) {
fatal("Only privileged users can change their user id");
fatal("[server] Only privileged users can change their user id!");
}
check(!setresuid(runAsUser, runAsUser, -1));
} else {
@ -169,7 +169,7 @@ void dropPrivileges(void) {
// Try to switch to the user-provided user id.
if ((r && runAsUser != (int)r) ||
setresuid(runAsUser, runAsUser, runAsUser)) {
fatal("Only privileged users can change their user id.");
fatal("[server] Only privileged users can change their user id!");
}
} else {
if (r) {
@ -268,7 +268,7 @@ uid_t getUserId(const char *name) {
#endif
check(buf = malloc(len));
if (getpwnam_r(name, &pwbuf, buf, len, &pw) || !pw) {
fatal("Cannot look up user id \"%s\"", name);
fatal("[server] Cannot look up user id \"%s\"!", name);
}
uid_t uid = pw->pw_uid;
free(buf);
@ -402,16 +402,16 @@ gid_t getGroupId(const char *name) {
check(buf = realloc(buf, pw_len));
}
if (!getpwnam_r("nobody", &pwbuf, buf, pw_len, &pw) && pw) {
debug("Substituting \"nobody's\" primary group for \"nogroup\"");
debug("[server] Substituting \"nobody\"'s primary group for \"nogroup\"");
gid_t gid = pw->pw_gid;
free(buf);
return gid;
}
}
}
if(ret && errno == ERANGE) {
if (ret && errno == ERANGE) {
if ((gr_len + gr_baselen) < gr_len || (gr_len + gr_baselen) > gr_max) {
fatal("Cannot look up group \"%s\": buffer limit reached", name);
fatal("[server] Cannot look up group \"%s\"! [buffer limit reached]", name);
break;
}
// grow the buffer by 'gr_baselen' each time getgrnam_r fails
@ -420,7 +420,7 @@ gid_t getGroupId(const char *name) {
buf = temp;
continue;
}
fatal("Cannot look up group \"%s\"", name);
fatal("[server] Cannot look up group \"%s\"", name);
}
gid_t gid = gr->gr_gid;
free(buf);

View file

@ -78,7 +78,7 @@ void initService(struct Service *service, const char *arg) {
char *ptr;
if ((ptr = strchr(arg, ':')) == NULL) {
error:
fatal("Syntax error in service description \"%s\".", desc);
fatal("[config] Syntax error in service description \"%s\"!", desc);
}
service->id = -1;
check(service->path = malloc(ptr - arg + 2));
@ -95,8 +95,7 @@ void initService(struct Service *service, const char *arg) {
// application definition.
if (!strcmp(arg, "LOGIN")) {
if (geteuid()) {
fatal("Must be \"root\" to invoke \"/bin/login\". Maybe, change "
"--service definitions?");
fatal("[config] Must be \"root\" to invoke LOGIN service!");
}
service->useLogin = 1;
service->useHomeDir = 0;
@ -145,7 +144,7 @@ void initService(struct Service *service, const char *arg) {
(ch >= 'A' && ch <= 'Z') ||
(ch >= 'a' && ch <= 'z') ||
ch == '-' || ch == '.')) {
fatal("Invalid hostname \"%s\" in service definition", host);
fatal("[config] Invalid hostname \"%s\" in service definition!", host);
}
}
@ -210,7 +209,7 @@ void initService(struct Service *service, const char *arg) {
service->cwd = NULL;
} else {
if (*arg != '/') {
fatal("Working directories must have absolute paths");
fatal("[config] Working directories must have absolute paths!");
}
service->useHomeDir = 0;
check(service->cwd = strdup(arg));

View file

@ -224,7 +224,7 @@ struct Session *findSession(const char *sessionKey, const char *cgiSessionKey,
*sessionIsNew = 0;
} else if (!cgiSessionKey && sessionKey && *sessionKey) {
*sessionIsNew = 0;
debug("Failed to find session: %s", sessionKey);
debug("[server] Failed to find session: %s", sessionKey);
} else {
// First contact. Create session, now.
check(sessionKey = cgiSessionKey ? strdup(cgiSessionKey)
@ -232,7 +232,7 @@ struct Session *findSession(const char *sessionKey, const char *cgiSessionKey,
session = newSession(sessionKey, httpGetServer(http),
httpGetPeerName(http));
addToHashMap(sessions, sessionKey, (const char *)session);
debug("Creating a new session: %s", sessionKey);
debug("[server] Creating a new session: %s", sessionKey);
}
}
return session;

View file

@ -280,7 +280,7 @@ static int completePendingRequest(struct Session *session,
static void sessionDone(void *arg) {
struct Session *session = (struct Session *)arg;
debug("Session %s done", session->sessionKey);
debug("[server] Session %s done.", session->sessionKey);
if (session->cleanup) {
terminateChild(session);
}
@ -308,7 +308,7 @@ static int handleSession(struct ServerConnection *connection, void *arg,
int timedOut = serverGetTimeout(connection) < 0;
if (bytes || timedOut) {
if (!session->http && timedOut) {
debug("Timeout. Closing session.");
debug("[server] Timeout. Closing session!");
session->cleanup = 1;
return 0;
}
@ -332,7 +332,7 @@ static int invalidatePendingHttpSession(void *arg, const char *key,
char **value) {
struct Session *session = *(struct Session **)value;
if (session->http && session->http == (HttpConnection *)arg) {
debug("Clearing pending HTTP connection for session %s", key);
debug("[server] Clearing pending HTTP connection for session %s!", key);
session->http = NULL;
serverDeleteConnection(session->server, session->pty);
@ -367,7 +367,7 @@ static int dataHandler(HttpConnection *http, struct Service *service,
// Sanity check
if (!sessionIsNew && strcmp(session->peerName, httpGetPeerName(http))) {
error("Peername changed from %s to %s",
error("[server] Peername changed from %s to %s",
session->peerName, httpGetPeerName(http));
httpSendReply(http, 400, "Bad Request", NO_MSG);
return HTTP_DONE;
@ -418,7 +418,8 @@ static int dataHandler(HttpConnection *http, struct Service *service,
// Reset window dimensions of the pseudo TTY, if changed since last time set.
if (session->width > 0 && session->height > 0 &&
(session->width != oldWidth || session->height != oldHeight)) {
debug("Window size changed to %dx%d", session->width, session->height);
debug("[server] Window size changed to %dx%d", session->width,
session->height);
setWindowSize(session->pty, session->width, session->height);
}
@ -746,11 +747,11 @@ static int shellInABoxHttpHandler(HttpConnection *http, void *arg,
static int strtoint(const char *s, int minVal, int maxVal) {
char *ptr;
if (!*s) {
fatal("Missing numeric value.");
fatal("[config] Missing numeric value!");
}
long l = strtol(s, &ptr, 10);
if (*ptr || l < minVal || l > maxVal) {
fatal("Range error on numeric value \"%s\".", s);
fatal("[config] Range error on numeric value \"%s\"!", s);
}
return l;
}
@ -916,19 +917,20 @@ static void parseArgs(int argc, char * const argv[]) {
}
if (idx-- <= 0) {
// Help (or invalid argument)
usage();
if (idx < -1) {
fatal("Failed to parse command line");
fatal("[server] Failed to parse command line!");
} else {
usage();
}
exit(0);
} else if (!idx--) {
// Background
if (cgi) {
fatal("CGI and background operations are mutually exclusive");
fatal("[config] CGI and background operations are mutually exclusive!");
}
demonize = 1;
if (optarg && pidfile) {
fatal("Only one pidfile can be given");
fatal("[config] Only one pidfile can be given!");
}
if (optarg && *optarg) {
check(pidfile = strdup(optarg));
@ -936,55 +938,55 @@ static void parseArgs(int argc, char * const argv[]) {
} else if (!idx--) {
// Certificate
if (!hasSSL) {
warn("Ignoring certificate directory, as SSL support is unavailable");
warn("[config] Ignoring certificate directory, as SSL support is unavailable.");
}
if (certificateFd >= 0) {
fatal("Cannot set both a certificate directory and file handle");
fatal("[config] Cannot set both a certificate directory and file handle!");
}
if (certificateDir) {
fatal("Only one certificate directory can be selected");
fatal("[config] 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");
fatal("[config] Option --cert expects a directory name!");
}
check(certificateDir = strdup(optarg));
} else if (!idx--) {
// Certificate file descriptor
if (!hasSSL) {
warn("Ignoring certificate directory, as SSL support is unavailable");
warn("[config] Ignoring certificate directory, as SSL support is unavailable.");
}
if (certificateDir) {
fatal("Cannot set both a certificate directory and file handle");
fatal("[config] Cannot set both a certificate directory and file handle!");
}
if (certificateFd >= 0) {
fatal("Only one certificate file handle can be provided");
fatal("[config] Only one certificate file handle can be provided!");
}
if (!optarg || *optarg < '0' || *optarg > '9') {
fatal("Option \"--cert-fd\" expects a valid file handle.");
fatal("[config] Option --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");
fatal("[config] 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("Option \"--css\" expects a file name.");
fatal("[config] Option --css expects a file name!");
}
FILE *css = fopen(optarg, "r");
if (!css) {
fatal("Cannot read style sheet \"%s\"", optarg);
fatal("[config] 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, st.st_size, 1, css) != 1) {
fatal("Failed to read style sheet \"%s\"", optarg);
fatal("[config] Failed to read style sheet \"%s\"!", optarg);
}
newData[st.st_size]= '\000';
fclose(css);
@ -992,19 +994,19 @@ static void parseArgs(int argc, char * const argv[]) {
} else if (!idx--) {
// CGI
if (demonize) {
fatal("CGI and background operations are mutually exclusive");
fatal("[config] CGI and background operations are mutually exclusive!");
}
if (pidfile) {
fatal("CGI operation and --pidfile= are mutually exclusive");
fatal("[config] CGI operation and --pidfile are mutually exclusive!");
}
if (port) {
fatal("Cannot specify a port for CGI operation");
fatal("[config] Cannot specify a port for CGI operation!");
}
cgi = 1;
if (optarg && *optarg) {
char *ptr = strchr(optarg, '-');
if (!ptr) {
fatal("Syntax error in port range specification");
fatal("[config] Syntax error in port range specification!");
}
*ptr = '\000';
portMin = strtoint(optarg, 1, 65535);
@ -1014,40 +1016,41 @@ static void parseArgs(int argc, char * const argv[]) {
} else if (!idx--) {
// Debug
if (!logIsDefault() && !logIsDebug()) {
fatal("--debug is mutually exclusive with --quiet and --verbose.");
fatal("[config] Option --debug is mutually exclusive with --quiet and --verbose!");
}
verbosity = MSG_DEBUG;
logSetLogLevel(verbosity);
} else if (!idx--) {
// Static file
if (!optarg || !*optarg) {
fatal("Option \"--static-file\" expects an argument.");
fatal("[config] Option --static-file expects an argument!");
}
char *ptr, *path, *file;
if ((ptr = strchr(optarg, ':')) == NULL) {
fatal("Syntax error in static-file definition \"%s\".", optarg);
fatal("[config] Syntax error in static-file definition \"%s\"!",
optarg);
}
check(path = malloc(ptr - optarg + 1));
memcpy(path, optarg, ptr - optarg);
path[ptr - optarg] = '\000';
check(file = strdup(ptr + 1));
if (getRefFromHashMap(externalFiles, path)) {
fatal("Duplicate static-file definition for \"%s\".", path);
fatal("[config] Duplicate static-file definition for \"%s\"!", path);
}
addToHashMap(externalFiles, path, file);
} else if (!idx--) {
// Group
if (runAsGroup >= 0) {
fatal("Duplicate --group option.");
fatal("[config] Duplicate --group option.");
}
if (!optarg || !*optarg) {
fatal("Option \"--group\" expects a group name.");
fatal("[config] Option --group expects a group name.");
}
runAsGroup = parseGroupArg(optarg, NULL);
} else if (!idx--) {
// Linkify
if (!optarg || !*optarg) {
fatal("Option \"--linkify\" expects an argument.");
fatal("[config] Option --linkify expects an argument.");
}
if (!strcmp(optarg, "none")) {
linkifyURLs = 0;
@ -1056,8 +1059,8 @@ static void parseArgs(int argc, char * const argv[]) {
} else if (!strcmp(optarg, "aggressive")) {
linkifyURLs = 2;
} else {
fatal("Invalid argument for --linkify. Must be "
"\"none\", \"normal\", or \"aggressive\".");
fatal("[config] Invalid argument for --linkify. Must be \"none\", \"normal\", "
"or \"aggressive\".");
}
} else if (!idx--) {
// Localhost Only
@ -1071,71 +1074,70 @@ static void parseArgs(int argc, char * const argv[]) {
} else if (!idx--) {
// Messages origin
if (messagesOrigin) {
fatal("Duplicated \"--messages-origin\" option.");
fatal("[config] Duplicated --messages-origin option.");
}
if (!optarg || !*optarg) {
fatal("Option \"--messages-origin\" expects an argument.");
fatal("[config] Option --messages-origin expects an argument.");
}
check(messagesOrigin = strdup(optarg));
} else if (!idx--) {
// Pidfile
if (cgi) {
fatal("CGI operation and --pidfile= are mutually exclusive");
fatal("[config] CGI operation and --pidfile are mutually exclusive");
}
if (!optarg || !*optarg) {
fatal("Must specify a filename for --pidfile= option");
fatal("[config] Must specify a filename for --pidfile option");
}
if (pidfile) {
fatal("Only one pidfile can be given");
fatal("[config] Only one pidfile can be given");
}
check(pidfile = strdup(optarg));
} else if (!idx--) {
// Port
if (port) {
fatal("Duplicate --port option");
fatal("[config] Duplicate --port option!");
}
if (cgi) {
fatal("Cannot specifiy a port for CGI operation");
fatal("[config] Cannot specifiy a port for CGI operation");
}
if (!optarg || *optarg < '0' || *optarg > '9') {
fatal("Option \"--port\" expects a port number.");
fatal("[config] Option --port expects a port number.");
}
port = strtoint(optarg, 1, 65535);
} else if (!idx--) {
// Service
if (!optarg || !*optarg) {
fatal("Option \"--service\" expects an argument.");
fatal("[config] Option \"--service\" expects an argument.");
}
struct Service *service;
service = newService(optarg);
if (getRefFromHashMap(serviceTable, service->path)) {
fatal("Duplicate service description for \"%s\".", service->path);
fatal("[config] Duplicate service description for \"%s\".", service->path);
}
addToHashMap(serviceTable, service->path, (char *)service);
} else if (!idx--) {
// Disable SSL
if (!hasSSL) {
warn("Ignoring disable-ssl option, as SSL support is unavailable");
warn("[config] Ignoring disable-ssl option, as SSL support is unavailable.");
}
enableSSL = 0;
} else if (!idx--) {
// Disable SSL Menu
if (!hasSSL) {
warn("Ignoring disable-ssl-menu option, as SSL support is "
"unavailable");
warn("[config] Ignoring disable-ssl-menu option, as SSL support is unavailable.");
}
enableSSLMenu = 0;
} else if (!idx--) {
// Quiet
if (!logIsDefault() && !logIsQuiet()) {
fatal("--quiet is mutually exclusive with --debug and --verbose.");
fatal("[config] Option --quiet is mutually exclusive with --debug and --verbose!");
}
verbosity = MSG_QUIET;
logSetLogLevel(verbosity);
} else if (!idx--) {
// Unix domain only
if (!optarg || !*optarg) {
fatal("Option \"--unixdomain-only\" expects an argument.");
fatal("[config] Option --unixdomain-only expects an argument!");
}
char *ptr, *s, *tmp;
@ -1143,7 +1145,8 @@ static void parseArgs(int argc, char * const argv[]) {
s = optarg;
ptr = strchr(s, ':');
if (ptr == NULL || ptr == s || ptr - s >= UNIX_PATH_MAX) {
fatal("Syntax error in unixdomain-only path definition \"%s\".", optarg);
fatal("[config] Syntax error in unixdomain-only path definition \"%s\".",
optarg);
}
check(unixDomainPath = strndup(s, ptr - s));
@ -1151,7 +1154,8 @@ static void parseArgs(int argc, char * const argv[]) {
s = ptr + 1;
ptr = strchr(s, ':');
if (ptr == NULL || ptr == s) {
fatal("Syntax error in unixdomain-only user definition \"%s\".", optarg);
fatal("[config] Syntax error in unixdomain-only user definition \"%s\".",
optarg);
}
check(tmp = strndup(s, ptr - s));
unixDomainUser = parseUserArg(tmp, NULL);
@ -1161,7 +1165,8 @@ static void parseArgs(int argc, char * const argv[]) {
s = ptr + 1;
ptr = strchr(s, ':');
if (ptr == NULL || ptr == s) {
fatal("Syntax error in unixdomain-only group definition \"%s\".", optarg);
fatal("[config] Syntax error in unixdomain-only group definition \"%s\".",
optarg);
}
check(tmp = strndup(s, ptr - s));
unixDomainGroup = parseGroupArg(tmp, NULL);
@ -1170,29 +1175,31 @@ static void parseArgs(int argc, char * const argv[]) {
// Unix domain chmod
s = ptr + 1;
if (strlen(ptr) == 1) {
fatal("Syntax error in unixdomain-only chmod definition \"%s\".", optarg);
fatal("[config] Syntax error in unixdomain-only chmod definition \"%s\".",
optarg);
}
unixDomainChmod = strtol(s, NULL, 8);
} else if (!idx--) {
// User
if (runAsUser >= 0) {
fatal("Duplicate --user option.");
fatal("[config] Duplicate --user option.");
}
if (!optarg || !*optarg) {
fatal("Option \"--user\" expects a user name.");
fatal("[config] Option --user expects a user name.");
}
runAsUser = parseUserArg(optarg, NULL);
} else if (!idx--) {
// User CSS
if (!optarg || !*optarg) {
fatal("Option \"--user-css\" expects a list of styles sheets and labels");
fatal("[config] Option --user-css expects a list of styles sheets "
"and labels!");
}
parseUserCSS(&userCSSList, optarg);
} else if (!idx--) {
// Verbose
if (!logIsDefault() && (!logIsInfo() || logIsDebug())) {
fatal("--verbose is mutually exclusive with --debug and --quiet");
fatal("[config] Option --verbose is mutually exclusive with --debug and --quiet!");
}
verbosity = MSG_INFO;
logSetLogLevel(verbosity);
@ -1204,14 +1211,14 @@ static void parseArgs(int argc, char * const argv[]) {
}
if (optind != argc) {
usage();
fatal("Failed to parse command line");
fatal("[config] Failed to parse command line!");
}
char *buf = NULL;
check(argc >= 1);
for (int i = 0; i < argc; i++) {
buf = stringPrintf(buf, " %s", argv[i]);
}
info("Command line:%s", buf);
info("[server] Command line: %s", buf);
free(buf);
// If the user did not specify a port, use the default one
@ -1237,7 +1244,7 @@ static void parseArgs(int argc, char * const argv[]) {
if (cgi) {
for (int i = 0; i < numServices; i++) {
if (strcmp(services[i]->path, "/")) {
fatal("Non-root service URLs are incompatible with CGI operation");
fatal("[config] Non-root service URLs are incompatible with CGI operation");
}
}
check(cgiSessionKey = newSessionKey());
@ -1297,7 +1304,7 @@ static void setUpSSL(Server *server) {
} else if (certificateDir) {
char *tmp;
if (strchr(certificateDir, '%')) {
fatal("Invalid certificate directory name \"%s\".", certificateDir);
fatal("[ssl] Invalid certificate directory name \"%s\".", certificateDir);
}
check(tmp = stringPrintf(NULL, "%s/certificate%%s.pem", certificateDir));
serverSetCertificate(server, tmp, 1);
@ -1433,6 +1440,6 @@ int main(int argc, char * const argv[]) {
}
free((char *)pidfile);
}
info("Done");
info("[server] Done");
_exit(0);
}

View file

@ -80,7 +80,7 @@ static void readStylesheet(struct UserCSS *userCSS, const char *filename,
int fd = open(filename, O_RDONLY);
struct stat st;
if (fd < 0 || fstat(fd, &st)) {
fatal("Cannot access style sheet \"%s\"", filename);
fatal("[config] Cannot access style sheet \"%s\"!", filename);
}
FILE *fp;
check(fp = fdopen(fd, "r"));
@ -114,7 +114,7 @@ void initUserCSS(struct UserCSS *userCSS, const char *arg) {
for (;;) {
const char *colon = strchr(arg, ':');
if (!colon) {
fatal("Incomplete user CSS definition: \"%s\"", arg);
fatal("[config] Incomplete user CSS definition: \"%s\"!", arg);
}
check(userCSS->label = malloc(6*(colon - arg) + 1));
@ -153,15 +153,14 @@ void initUserCSS(struct UserCSS *userCSS, const char *arg) {
break;
case '+':
if (hasActiveMember) {
fatal("There can only be one active style option per group. Maybe "
"use ';' instead of ',' to start a new group.");
fatal("[config] Only one default active style allowed per group!");
}
hasActiveMember = 1;
userCSS->isActivated = 1;
break;
default:
fatal("Must indicate with '+' or '-' whether the style option is "
"active by default");
fatal("[config] Must indicate with '+' or '-' whether the style option "
"is active by default!");
}
readStylesheet(userCSS, filename + 1, (char **)&userCSS->style,
@ -188,9 +187,7 @@ void initUserCSS(struct UserCSS *userCSS, const char *arg) {
}
}
if (!hasActiveMember && numMembers > 1) {
fatal("Each group of style options must have exactly one style that is "
"active by\n"
"default.");
fatal("[config] Only one default active style allowed per group!");
}
}