From: Carl Worth Date: Thu, 8 Dec 2005 23:42:28 +0000 (+0000) Subject: 2005-12-08 Carl Worth X-Git-Url: https://git.cworth.org/git?p=ttt;a=commitdiff_plain;h=95898262b4ce4a2a3d36f70a4e6cc8188decc142 2005-12-08 Carl Worth * src/ttt-args.h: * src/ttt-args.c: (ttt_args_help), (ttt_args_parse): Add -d,--detach and --pid-file=FILE options for running the server as a daemon. * src/ttt-server.c: (ttt_server_statistics), (ttt_server_verify_username), (_detach_and_write_child_pid_to), (main): Add support for detaching and writing out the child PID to a file. * src/x.h: * src/x.c: (xfopen), (xdup2): Two new x-functions. --- diff --git a/ChangeLog b/ChangeLog index bc97e1b..640a333 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2005-12-08 Carl Worth + + * src/ttt-args.h: + * src/ttt-args.c: (ttt_args_help), (ttt_args_parse): Add + -d,--detach and --pid-file=FILE options for running the server as + a daemon. + + * src/ttt-server.c: (ttt_server_statistics), + (ttt_server_verify_username), (_detach_and_write_child_pid_to), + (main): Add support for detaching and writing out the child PID to + a file. + + * src/x.h: + * src/x.c: (xfopen), (xdup2): Two new x-functions. + +2005-12-08 Carl Worth + + * src/ttt-args.c: (ttt_args_help), (ttt_args_parse): + * src/ttt-args.h: + * src/ttt-server.c: (ttt_server_statistics), + (ttt_server_verify_username), (_detach_and_write_child_pid_to), + (main): + * src/x.c: (xfopen), (xdup2): + * src/x.h: + 2005-12-08 Bryan Worth * src/ttt-curses-client.c: Multiple improvements! Username taken from USER environment variable and stored as diff --git a/src/ttt-args.c b/src/ttt-args.c index 54cc0db..f367716 100644 --- a/src/ttt-args.c +++ b/src/ttt-args.c @@ -48,16 +48,19 @@ static char TTT_ARGS_PROGRAM_ARGDOC[] = ""; enum { TTT_ARGS_VAL_LOG_FILE = 256, + TTT_ARGS_VAL_PID_FILE, TTT_ARGS_VAL_HELP, - TTT_ARGS_VAL_VERSION + TTT_ARGS_VAL_VERSION, }; -static char ttt_args_optstring[] = "h:p:"; +static char ttt_args_optstring[] = "dh:p:"; static struct option ttt_args_options[] = { /* name, has_arg, flag, val */ {"host", 1, 0, 'h'}, {"port", 1, 0, 'p'}, + {"detach", 0, 0, 'd'}, {"log-file", 1, 0, TTT_ARGS_VAL_LOG_FILE}, + {"pid-file", 1, 0, TTT_ARGS_VAL_PID_FILE}, {"help", 0, 0, TTT_ARGS_VAL_HELP}, {"version", 0, 0, TTT_ARGS_VAL_VERSION}, { 0 } @@ -71,14 +74,20 @@ ttt_args_help (const char *argv0) puts (""); printf ("Options that are common to both client and server:\n"); puts (""); - printf (" -h HOST, --host=HOST\tHost to connect/bind to\n"); - printf (" -p PORT, --port=PORT\tPort to connect/bind to\n"); + printf (" -h HOST, --host=HOST\tHost to connect/bind to [%s]\n", + TTT_ARGS_HOST_DEFAULT); + printf (" -p PORT, --port=PORT\tPort to connect/bind to [%s]\n", + TTT_ARGS_PORT_DEFAULT); printf (" --help\tGive this help list\n"); printf (" --version\tPrint program version\n"); puts (""); printf ("Options that are specific to the server:\n"); puts (""); - printf (" --log-file=FILE\tFile to use for logging\n"); + printf (" --log-file=FILE\tFile to use for logging [stderr]\n"); + printf (" -d, --detach\tDetach and daemonize\n"); + printf (" --pid-file=FILE\tFile in which to save PID (if -d given)\n" + " \t[%s]\n", + TTT_ARGS_PID_FILE_DEFAULT); } #if 0 @@ -101,6 +110,8 @@ ttt_args_parse(ttt_args_t *args, int argc, char *argv[]) args->host = TTT_ARGS_HOST_DEFAULT; args->port = TTT_ARGS_PORT_DEFAULT; args->log_file = TTT_ARGS_LOG_FILE_DEFAULT; + args->detach = FALSE; + args->pid_file = TTT_ARGS_PID_FILE_DEFAULT; while (1) { c = getopt_long (argc, argv, ttt_args_optstring, ttt_args_options, NULL); @@ -117,6 +128,12 @@ ttt_args_parse(ttt_args_t *args, int argc, char *argv[]) case TTT_ARGS_VAL_LOG_FILE: args->log_file = optarg; break; + case 'd': + args->detach = TRUE; + break; + case TTT_ARGS_VAL_PID_FILE: + args->pid_file = optarg; + break; case TTT_ARGS_VAL_VERSION: printf ("%s\n", VERSION); exit (0); diff --git a/src/ttt-args.h b/src/ttt-args.h index 7c18acd..5a1b3cf 100644 --- a/src/ttt-args.h +++ b/src/ttt-args.h @@ -22,20 +22,21 @@ #ifndef TTT_ARGS_H #define TTT_ARGS_H -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +#include "ttt.h" #define TTT_ARGS_HOST_DEFAULT "localhost" #define TTT_ARGS_PORT_DEFAULT "5334" /* NULL means to just log to stderr. */ #define TTT_ARGS_LOG_FILE_DEFAULT NULL +#define TTT_ARGS_PID_FILE_DEFAULT "/var/run/ttt-server.pid" typedef struct ttt_args { char *host; char *port; char *log_file; + ttt_bool_t detach; + char *pid_file; } ttt_args_t; int diff --git a/src/ttt-server.c b/src/ttt-server.c index c94d3d2..34159b5 100644 --- a/src/ttt-server.c +++ b/src/ttt-server.c @@ -162,7 +162,7 @@ ttt_error_t ttt_server_statistics (ttt_server_t *server, const char *username, char **response) { ttt_bool_t usernamefound = FALSE; - char *client_username; + const char *client_username; int client_num_wins; int i; @@ -193,7 +193,7 @@ ttt_error_t ttt_server_verify_username (ttt_server_t *server, const char *username) { ttt_bool_t usernamefound = FALSE; - char *client_username; + const char *client_username; int i; pthread_mutex_lock (&server->mutex); @@ -248,6 +248,35 @@ _ttt_server_accept (void *closure, int client_socket) ttt_client_new (server, client_socket); } +static void +_detach_and_write_child_pid_to (const char *filename) +{ + pid_t pid; + + /* Use the Unix double-fork trick to detach completely. See + * setsid(2) for some details as to why two forks are + * needed. */ + pid = xfork (); + if (pid) { + /* First parent just exits */ + exit (0); + } + + chdir ("/"); + setsid (); + + pid = xfork (); + if (pid) { + /* Second parent exits after writing pid */ + FILE *file = xfopen (filename, "w"); + fprintf (file, "%d\n", pid); + fclose (file); + exit (0); + } + + /* Final, detached child returns. */ +} + int main (int argc, char **argv) { @@ -257,12 +286,34 @@ main (int argc, char **argv) ttt_args_parse (&args, argc, argv); - if (args.log_file) - xfreopen (args.log_file, "a", stderr); + if (args.log_file || args.detach) { + FILE *log_file; + /* In the detach case, we force redirection to a log file. */ + if (args.log_file == NULL) + args.log_file = "/var/log/ttt-server.log"; + log_file = fopen (args.log_file, "a"); + if (log_file == NULL) { + printf ("Warning: Failed to open log file %s: %s.\n", + args.log_file, strerror (errno)); + printf ("Logging will be disabled.\n"); + xdup2 (1, 2); + } else { + xdup2 (fileno (log_file), 2); + } + } + + if (args.detach) + _detach_and_write_child_pid_to (args.pid_file); socket = ttt_socket_create_server (args.host, args.port); - printf (WELCOME_MESSAGE, args.host, args.port, args.host, args.port); + if (args.detach) + printf ("Server started listening on %s:%s\n", args.host, args.port); + else + printf (WELCOME_MESSAGE, args.host, args.port, args.host, args.port); + + fclose (stdout); + fclose (stdin); ttt_server_init (&server, args.host, args.port); diff --git a/src/x.c b/src/x.c index a95fedf..c35f4c8 100644 --- a/src/x.c +++ b/src/x.c @@ -117,6 +117,22 @@ xrealloc (void *ptr, size_t size) return ret; } +FILE * +xfopen (const char *path, const char *mode) +{ + FILE *ret; + + ret = fopen (path, mode); + + if (ret == NULL) { + fprintf (stderr, "Error: fopen of %s failed: %s. Aborting.\n", + path, strerror (errno)); + exit (1); + } + + return ret; +} + FILE * xfdopen (int filedes, const char *mode) { @@ -134,14 +150,14 @@ xfdopen (int filedes, const char *mode) } void -xfreopen (const char *path, const char *mode, FILE *stream) +xdup2 (int oldfd, int newfd) { - FILE *ret; + int ret; - ret = freopen (path, mode, stream); - if (ret == NULL) { - fprintf (stderr, "Error: freopen of %s failed: %s. Aborting.\n", - path, strerror (errno)); + ret = dup2 (oldfd, newfd); + if (ret == -1) { + printf ("Error: dup2 failed: %s. Aborting.\n", + strerror (errno)); exit (1); } } diff --git a/src/x.h b/src/x.h index 3b7f208..64a18a2 100644 --- a/src/x.h +++ b/src/x.h @@ -45,11 +45,14 @@ xcalloc (size_t nmemb, size_t size); void * xrealloc (void *ptr, size_t size); +FILE * +xfopen (const char *path, const char *mode); + FILE * xfdopen (int filedes, const char *mode); void -xfreopen (const char *path, const char *mode, FILE *stream); +xdup2 (int oldfd, int newfd); char * xstrdup (const char *s);