X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=daemon.c;h=20cdc6ae605a99f56f35bf41f0abeff7d508936d;hp=478b0f47acc94d3098cc17576599032f007b43ca;hb=fc8dfbb416ff07cca08fbf4e13efcaa25e17cc54;hpb=642445e95fea1c548c79f80ad3b5d6f30ba572f3 diff --git a/daemon.c b/daemon.c index 478b0f47..20cdc6ae 100644 --- a/daemon.c +++ b/daemon.c @@ -54,12 +54,12 @@ static void daemon_set_default_log_colors(void) color_parse_or_die(default_log_colors[i], me->log_colors[i]); } -/* +/** * Set the color for one loglevel. * - * arg must be of the form "ll:[fg [bg]] [attr]". + * \param arg Must be of the form "ll:[fg [bg]] [attr]". */ -static void daemon_set_log_color_or_die(char const *arg) +void daemon_set_log_color_or_die(const char *arg) { char *p = strchr(arg, ':'); int ret, ll; @@ -74,7 +74,7 @@ static void daemon_set_log_color_or_die(char const *arg) color_parse_or_die(p, me->log_colors[ll]); return; err: - PARA_EMERG_LOG("%s: color syntax error\n", arg); + PARA_EMERG_LOG("%s: invalid color argument\n", arg); exit(EXIT_FAILURE); } @@ -85,36 +85,31 @@ err: * \param color_arg_auto The value for automatic color detection. * \param color_arg_no The value to disable colored log messages. * \param logfile_given In auto mode colors are disabled if this value is true. - * \param log_color_argv Color specifiers given to --log-color. - * \param argc Number of color specifiers in \a log_color_argv. * - * If \a color_arg equals \a color_arg_no, color mode is disabled, i.e., calls - * to \a para_log() will not produce colored output. If \a color_arg == \a - * color_arg_auto, the function autodetects whether to activate colors. - * Otherwise color mode is enabled. + * If color_arg equals color_arg_no, color mode is disabled. That is, calls to + * para_log() will not produce colored output. If color_arg equals + * color_arg_auto, the function detects automatically whether to activate + * colors. Otherwise color mode is enabled. + * + * If color mode is to be enabled, the default colors are set for each + * loglevel. They can be overwritten by calling daemon_set_log_color_or_die(). * - * If color mode is to be enabled, the strings in \a log_color_argv are parsed - * and the color scheme is updated accordingly. For each loglevel, the default - * colors apply if there is no log_color_argv for this loglevel. + * \return Whether colors have been enabled by the function. */ -void daemon_init_colors_or_die(int color_arg, int color_arg_auto, - int color_arg_no, bool logfile_given, char **log_color_argv, - int argc) +bool daemon_init_colors_or_die(int color_arg, int color_arg_auto, + int color_arg_no, bool logfile_given) { - int i; - if (color_arg == color_arg_no) - return; + return false; if (color_arg == color_arg_auto) { if (logfile_given) - return; + return false; if (!isatty(STDERR_FILENO)) - return; + return false; } daemon_set_flag(DF_COLOR_LOG); daemon_set_default_log_colors(); - for (i = 0; i < argc; i++) - daemon_set_log_color_or_die(log_color_argv[i]); + return true; } /** @@ -122,7 +117,7 @@ void daemon_init_colors_or_die(int color_arg, int color_arg_auto, * * \param logfile_name The full path of the logfile. */ -void daemon_set_logfile(char *logfile_name) +void daemon_set_logfile(const char *logfile_name) { free(me->logfile_name); me->logfile_name = NULL; @@ -135,7 +130,7 @@ void daemon_set_logfile(char *logfile_name) * * \param loglevel The smallest level that should be logged. */ -void daemon_set_loglevel(char *loglevel) +void daemon_set_loglevel(const char *loglevel) { int ret = get_loglevel_by_name(loglevel); @@ -160,10 +155,6 @@ static bool daemon_test_flag(unsigned flag) return me->flags & flag; } -static void dummy_sighandler(__a_unused int s) -{ -} - /** * Do the usual stuff to become a daemon. * @@ -171,30 +162,42 @@ static void dummy_sighandler(__a_unused int s) * * Fork, become session leader, cd to /, and dup fd 0, 1, 2 to /dev/null. If \a * parent_waits is false, the parent process terminates immediately. - * Otherwise, it calls pause() to sleep until it receives \p SIGTERM or \p - * SIGCHLD and exits successfully thereafter. This behaviour is useful if the - * daemon process should not detach from the console until the child process - * has completed its setup. + * Otherwise, a pipe is created prior to the fork() and the parent tries to + * read a single byte from the reading end of the pipe. The child is supposed + * to write to the writing end of the pipe after it completed its setup + * procedure successfully. This behaviour is useful to let the parent process + * die with an error if the child process aborts early, since in this case the + * read() will return non-positive. + * + * \return This function either succeeds or calls exit(3). If parent_waits is + * true, the return value is the file descriptor of the writing end of the + * pipe. Otherwise the function returns zero. * * \sa fork(2), setsid(2), dup(2), pause(2). */ -void daemonize(bool parent_waits) +int daemonize(bool parent_waits) { pid_t pid; - int null; + int null, pipe_fd[2]; - PARA_INFO_LOG("daemonizing\n"); + if (parent_waits && pipe(pipe_fd) < 0) + goto err; + PARA_INFO_LOG("subsequent log messages go to %s\n", me->logfile_name? + me->logfile_name : "/dev/null"); pid = fork(); if (pid < 0) goto err; - if (pid) { + if (pid) { /* parent exits */ if (parent_waits) { - signal(SIGTERM, dummy_sighandler); - signal(SIGCHLD, dummy_sighandler); - pause(); + char c; + close(pipe_fd[1]); + exit(read(pipe_fd[0], &c, 1) <= 0? + EXIT_FAILURE : EXIT_SUCCESS); } - exit(EXIT_SUCCESS); /* parent exits */ + exit(EXIT_SUCCESS); } + if (parent_waits) + close(pipe_fd[0]); /* become session leader */ if (setsid() < 0) goto err; @@ -210,7 +213,7 @@ void daemonize(bool parent_waits) if (dup2(null, STDERR_FILENO) < 0) goto err; close(null); - return; + return parent_waits? pipe_fd[1] : 0; err: PARA_EMERG_LOG("fatal: %s\n", strerror(errno)); exit(EXIT_FAILURE);