Index: filed.1 ================================================================== --- filed.1 +++ filed.1 @@ -4,10 +4,11 @@ filed \- serve files over HTTP .SH SYNOPSIS .ll +10 .B filed .RB [{ \-h | \-\-help }] +.RB [{ \-d | \-\-daemon }] .RB [{ \-b | \-\-bind } .IR address ] .RB [{ \-p | \-\-port } .IR port ] .RB [{ \-t | \-\-threads } @@ -27,10 +28,15 @@ .SH OPTIONS .TP .B -h (or --help) Prints detailed usage information +.TP +.B -d (or --daemon) +Instructs filed to become a daemon after initializing +the listening TCP socket and log files. + .TP .B -b (or --bind) Specifies the address to listen for incoming HTTP requests on. Index: filed.c ================================================================== --- filed.c +++ filed.c @@ -2,10 +2,11 @@ #include #include #include #include #include +#include #include #include #include #include #include @@ -686,10 +687,11 @@ } fprintf(output, "Usage: filed []\n"); fprintf(output, " Options:\n"); fprintf(output, " -h, --help\n"); + fprintf(output, " -d, --daemon\n"); fprintf(output, " -b
, --bind
\n"); fprintf(output, " -p , --port \n"); fprintf(output, " -t , --threads \n"); fprintf(output, " -c , --cache \n"); fprintf(output, " -u , --user \n"); @@ -697,10 +699,13 @@ if (long_help) { fprintf(output, "\n"); fprintf(output, " Usage:\n"); fprintf(output, " -h (or --help) prints this usage information\n"); + fprintf(output, "\n"); + fprintf(output, " -d (or --daemon) instructs filed to become a daemon after initializing\n"); + fprintf(output, " the listening TCP socket and log files.\n"); fprintf(output, "\n"); fprintf(output, " -b (or --bind) specifies the address to listen for incoming HTTP\n"); fprintf(output, " requests on. The default value is \"%s\".\n", BIND_ADDR); fprintf(output, "\n"); fprintf(output, " -p (or --port) specifies the TCP port number to listen for incoming HTTP\n"); @@ -769,20 +774,82 @@ *user_id = user_id_check; return(0); } + +/* Daemonize */ +static int filed_daemonize(void) { + pid_t setsid_ret, fork_ret; + int chdir_ret, dup2_ret; + int fd_in, fd_out; + + chdir_ret = chdir("/"); + if (chdir_ret != 0) { + return(1); + } + + fork_ret = fork(); + if (fork_ret < 0) { + return(1); + } + + if (fork_ret > 0) { + /* Parent */ + waitpid(fork_ret, NULL, 0); + + exit(EXIT_SUCCESS); + } + + /* Child */ + if (fork() != 0) { + /* Child */ + exit(EXIT_SUCCESS); + } + + /* Grand child */ + setsid_ret = setsid(); + if (setsid_ret == ((pid_t) -1)) { + return(1); + } + + fd_in = open("/dev/null", O_RDONLY); + fd_out = open("/dev/null", O_WRONLY); + if (fd_in < 0 || fd_out < 0) { + return(1); + } + + dup2_ret = dup2(fd_in, STDIN_FILENO); + if (dup2_ret != STDIN_FILENO) { + return(1); + } + + dup2_ret = dup2(fd_out, STDOUT_FILENO); + if (dup2_ret != STDOUT_FILENO) { + return(1); + } + + dup2_ret = dup2(fd_out, STDERR_FILENO); + if (dup2_ret != STDERR_FILENO) { + return(1); + } + + close(fd_in); + close(fd_out); + + return(0); +} /* Run process */ int main(int argc, char **argv) { - struct option options[8]; + struct option options[9]; const char *bind_addr = BIND_ADDR, *newroot = NULL; uid_t user = 0; int port = PORT, thread_count = THREAD_COUNT; int cache_size = CACHE_SIZE; int init_ret, chroot_ret, setuid_ret, lookup_ret, chdir_ret; - int setuid_enabled = 0; + int setuid_enabled = 0, daemon_enabled = 0; int ch; int fd; /* Process arguments */ filed_getopt_long_setopt(&options[0], "port", required_argument, 'p'); @@ -790,12 +857,13 @@ filed_getopt_long_setopt(&options[2], "cache", required_argument, 'c'); filed_getopt_long_setopt(&options[3], "bind", required_argument, 'b'); filed_getopt_long_setopt(&options[4], "user", required_argument, 'u'); filed_getopt_long_setopt(&options[5], "root", required_argument, 'r'); filed_getopt_long_setopt(&options[6], "help", no_argument, 'h'); - filed_getopt_long_setopt(&options[7], NULL, 0, 0); - while ((ch = getopt_long(argc, argv, "p:t:c:b:u:r:h", options, NULL)) != -1) { + filed_getopt_long_setopt(&options[7], "daemon", no_argument, 'd'); + filed_getopt_long_setopt(&options[8], NULL, 0, 0); + while ((ch = getopt_long(argc, argv, "p:t:c:b:u:r:hd", options, NULL)) != -1) { switch(ch) { case 'p': port = atoi(optarg); break; case 't': @@ -817,10 +885,13 @@ } break; case 'r': newroot = strdup(optarg); break; + case 'd': + daemon_enabled = 1; + break; case '?': case ':': filed_print_help(stderr, 0, NULL); return(1); @@ -865,11 +936,13 @@ return(1); } } /* Become a daemon */ - /* XXX:TODO: Become a daemon */ + if (daemon_enabled) { + filed_daemonize(); + } /* Initialize */ init_ret = filed_init(cache_size); if (init_ret != 0) { perror("filed_init");