From 52d3e9c8fe49b0805b6d07b08773d16848293ddd Mon Sep 17 00:00:00 2001 From: Christopher Ramey Date: Sat, 7 Mar 2015 19:17:57 +0000 Subject: [PATCH] Added proper daemonization, bumped version number --- src/wstationd.c | 192 ++++++++++++++++++++++++++++++++++++++---------- src/wstationd.h | 2 +- 2 files changed, 154 insertions(+), 40 deletions(-) diff --git a/src/wstationd.c b/src/wstationd.c index 762dfe5..8f29b1a 100644 --- a/src/wstationd.c +++ b/src/wstationd.c @@ -6,14 +6,17 @@ #include #include #include +#include #include #include #include +#include #include #include #include #include #include +#include #include "wstationd.h" @@ -31,7 +34,9 @@ #define TIMEOUT 30 -static char* exec_name; +static char exec_name[MAXPATHLEN]; + +static int daemonize = 1; struct connection { @@ -48,6 +53,7 @@ static int write_connection(struct connection *); static void print_help() { fprintf(stdout, "usage: %s [-p port] [-b addr] directory\n", exec_name); + fprintf(stdout, " -d, --nodaemon Do not detach and daemonize\n"); fprintf(stdout, " -p, --port Port to listen on (default: 10800)\n"); fprintf(stdout, " -b, --bind
Address to bind to (default: 0.0.0.0)\n"); fprintf(stdout, " -h, --help Print this message and exit\n"); @@ -58,6 +64,7 @@ static void print_help() int main(int argc, char* argv[]) { const struct option longopts[] = { + { "nodaemon", required_argument, NULL, 'd' }, { "port", required_argument, NULL, 'p' }, { "bind", required_argument, NULL, 'b' }, { "version", no_argument, NULL, 'v' }, @@ -72,13 +79,20 @@ int main(int argc, char* argv[]) struct connection* conns[SLOTLIMIT]; memset(conns, 0, sizeof(struct connection*) * SLOTLIMIT); - struct pollfd fds[SLOTLIMIT+1]; - memset(&fds, 0, sizeof(struct pollfd) * (SLOTLIMIT + 1)); - exec_name = basename(argv[0]); + if(basename_r(argv[0], exec_name) == NULL){ + fprintf(stderr, "%s: cannot get basename - %s\n", + exec_name, strerror(errno) + ); + goto shutdown_error; + } - for(int ch; (ch = getopt_long(argc, argv, "l:b:p:vh0", longopts, NULL)) != -1;){ + for(int ch; (ch = getopt_long(argc, argv, "l:b:p:dvh0", longopts, NULL)) != -1;){ switch(ch){ + case 'd': + daemonize = 0; + break; + case 'p': port = (int)strtol(optarg, NULL, 10); if(port < 1 || port > 65535){ @@ -120,14 +134,58 @@ int main(int argc, char* argv[]) print_help(); goto shutdown_error; } - + + // Daemonize if requested + if(daemonize){ + pid_t pid = fork(); + + // Fork failure + if(pid == -1){ + fprintf(stderr, "%s: cannot fork - %s\n", + exec_name, strerror(errno) + ); + goto shutdown_error; + } + + // Fork success, exit parent process + if(pid > 0){ exit(EXIT_SUCCESS); } + + // create new session for daemon + if(setsid() == -1){ + fprintf(stderr, "%s: cannot setsid - %s\n", + exec_name, strerror(errno) + ); + goto shutdown_error; + } + + // Ensure that standard descriptors are + // unavailable after fork() and setsid() + int fd = open("/dev/null", O_RDWR, 0); + if(fd != -1){ + dup2(fd, fileno(stdin)); + dup2(fd, fileno(stdout)); + dup2(fd, fileno(stderr)); + } + + // Open syslog + openlog(exec_name, LOG_PID, LOG_DAEMON); + } + + // Change default mask + umask(133); // Establish the socket sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd == -1){ - fprintf(stderr, "%s: cannot open socket - %s\n", - exec_name, strerror(errno) - ); + if(daemonize){ + syslog(LOG_ERR, "cannot open socket - %s", + strerror(errno) + ); + } else { + fprintf(stderr, "%s: cannot open socket - %s\n", + exec_name, strerror(errno) + ); + } goto shutdown_error; } @@ -144,32 +202,51 @@ int main(int argc, char* argv[]) // Bind our socket to the specified address and port if(bind(sockfd, (struct sockaddr*)&sock, sizeof(sock)) < 0){ - fprintf(stderr, "%s: cannot bind - %s\n", - exec_name, strerror(errno) - ); + if(daemonize){ + syslog(LOG_ERR, "cannot bind - %s", + strerror(errno) + ); + } else { + fprintf(stderr, "%s: cannot bind - %s\n", + exec_name, strerror(errno) + ); + } goto shutdown_error; } // Listen on port if(listen(sockfd, 10) != 0){ - fprintf(stderr, "%s: cannot listen - %s\n", - exec_name, strerror(errno) - ); + if(daemonize){ + syslog(LOG_ERR, "cannot listen - %s", + strerror(errno) + ); + } else { + fprintf(stderr, "%s: cannot listen - %s\n", + exec_name, strerror(errno) + ); + } goto shutdown_error; } + struct pollfd fds[SLOTLIMIT+1]; + memset(&fds, 0, sizeof(struct pollfd) * (SLOTLIMIT + 1)); + // Add sockfd fds[0].fd = sockfd; fds[0].events = POLLIN; fds[0].revents = 0; while(1){ - int r = poll(fds, (SLOTLIMIT + 1), 1000); - - if(r == -1){ - fprintf(stderr, "%s: socket poll error - %s\n", - exec_name, strerror(errno) - ); + if(poll(fds, (SLOTLIMIT + 1), 1000) == -1){ + if(daemonize){ + syslog(LOG_ERR, "socket poll error - %s", + strerror(errno) + ); + } else { + fprintf(stderr, "%s: socket poll error - %s\n", + exec_name, strerror(errno) + ); + } goto shutdown_error; } @@ -238,26 +315,44 @@ int main(int argc, char* argv[]) int fd = accept(sockfd, (struct sockaddr*)&client, &client_sz); if(fd == -1){ - fprintf(stderr, "%s: accept failed - %s\n", - exec_name, strerror(errno) - ); + if(daemonize){ + syslog(LOG_ERR, "accept failed - %s", + strerror(errno) + ); + } else { + fprintf(stderr, "%s: accept failed - %s\n", + exec_name, strerror(errno) + ); + } continue; } // Get current flags before setting nonblock if((flags = fcntl(fd, F_GETFL)) == -1){ - fprintf(stderr, "%s: cannot get connection flags - %s\n", - exec_name, strerror(errno) - ); + if(daemonize){ + syslog(LOG_ERR, "cannot get connection flags - %s", + strerror(errno) + ); + } else { + fprintf(stderr, "%s: cannot get connection flags - %s\n", + exec_name, strerror(errno) + ); + } close(fd); continue; } // Set nonblocking on socket if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1){ - fprintf(stderr, "%s: cannot set connection flags - %s\n", - exec_name, strerror(errno) - ); + if(daemonize){ + syslog(LOG_ERR, "cannot set connection flags - %s", + strerror(errno) + ); + } else { + fprintf(stderr, "%s: cannot set connection flags - %s\n", + exec_name, strerror(errno) + ); + } close(fd); continue; } @@ -265,7 +360,11 @@ int main(int argc, char* argv[]) // Allocate memory for the connection's state. conns[slotfirst - 1] = malloc(sizeof(struct connection)); if(conns[slotfirst - 1] == NULL){ - fprintf(stderr, "%s: out of memory\n", exec_name); + if(daemonize){ + syslog(LOG_ERR, "out of memory"); + } else { + fprintf(stderr, "%s: out of memory\n", exec_name); + } close(fd); continue; } @@ -296,6 +395,7 @@ int main(int argc, char* argv[]) shutdown_error: if(sockfd > 0) close(sockfd); + for(int i = 0; i < SLOTLIMIT; i++){ if(conns[i] != NULL) free(conns[i]); } return 1; } @@ -305,8 +405,9 @@ static int write_connection(struct connection *conn) // Build a filename for the file we're writing based // on the time and the source IP address char timebuff[20]; - struct tm* timeptr = localtime(&conn->tv.tv_sec); - strftime(&timebuff[0], 20, "%Y%m%d%H%M%S", timeptr); + struct tm timeptr; + localtime_r(&conn->tv.tv_sec, &timeptr); + strftime(&timebuff[0], 20, "%Y%m%d%H%M%S", &timeptr); char fnbuff[50]; snprintf(&fnbuff[0], 50, "%s.%ld-%s.dat", @@ -316,16 +417,29 @@ static int write_connection(struct connection *conn) int ofd; if((ofd = open(fnbuff, O_WRONLY | O_CREAT, 0644)) == -1){ - fprintf(stderr, "%s: cannot open - %s\n", - exec_name, strerror(errno) - ); + if(daemonize){ + syslog(LOG_ERR, "cannot open %s - %s", + fnbuff, strerror(errno) + ); + } else { + fprintf(stderr, "%s: cannot open %s - %s\n", + exec_name, fnbuff, strerror(errno) + ); + } return 1; } + // Write out the buffer if(write(ofd, conn->buff, conn->len) == -1){ - fprintf(stderr, "%s: file write error - %s\n", - exec_name, strerror(errno) - ); + if(daemonize){ + syslog(LOG_ERR, "write error on %s - %s", + fnbuff, strerror(errno) + ); + } else { + fprintf(stderr, "%s: write error on %s - %s\n", + exec_name, fnbuff, strerror(errno) + ); + } close(ofd); return 1; } diff --git a/src/wstationd.h b/src/wstationd.h index 36bbb31..bc0d1b1 100644 --- a/src/wstationd.h +++ b/src/wstationd.h @@ -1 +1 @@ -#define VERSION "0.7.0" +#define VERSION "1.0.0"