diff options
Diffstat (limited to 'src/exec.c')
-rw-r--r-- | src/exec.c | 253 |
1 files changed, 122 insertions, 131 deletions
@@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2009-2011 Sergey Poznyakoff + Copyright (C) 2007, 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -23,150 +23,141 @@ /* Execute a program from ARGC/ARGV. Return PID in PPID. Return FILE connected to the program's stdout and stderr. */ static FILE * -start_prog (int argc, const char **argv, pid_t *ppid) +start_prog(int argc, const char **argv, pid_t * ppid) { - int p[2]; - FILE *fp; - pid_t pid; - int i; - - if (pipe (p)) - { - logmsg (LOG_CRIT, "pipe: %s", strerror (errno)); - return NULL; - } - - switch (pid = fork ()) - { - case 0: - /* Child process */ - - if (p[1] != 1 && dup2 (p[1], 1) == -1) - { - logmsg (LOG_CRIT, "dup2: %s", strerror (errno)); - _exit (EX_UNAVAILABLE); + int p[2]; + FILE *fp; + pid_t pid; + int i; + + if (pipe(p)) { + logmsg(LOG_CRIT, "pipe: %s", strerror(errno)); + return NULL; } - - if (p[1] != 1 && dup2 (p[1], 2) == -1) - { - logmsg (LOG_CRIT, "dup2: %s", strerror (errno)); - _exit (EX_UNAVAILABLE); + + switch (pid = fork()) { + case 0: + /* Child process */ + + if (p[1] != 1 && dup2(p[1], 1) == -1) { + logmsg(LOG_CRIT, "dup2: %s", strerror(errno)); + _exit(EX_UNAVAILABLE); + } + + if (p[1] != 1 && dup2(p[1], 2) == -1) { + logmsg(LOG_CRIT, "dup2: %s", strerror(errno)); + _exit(EX_UNAVAILABLE); + } + + close(p[0]); + + /* Close unneded descripitors */ + for (i = getdtablesize(); i > 2; i--) + close(i); + + execvp(argv[0], (char **)argv); + logmsg(LOG_CRIT, _("cannot run %s: %s"), argv[0], + strerror(errno)); + exit(EX_UNAVAILABLE); + + case -1: + logmsg(LOG_CRIT, _("cannot run `%s': fork failed: %s"), + argv[0], strerror(errno)); + return NULL; + + default: + /* Master process */ + close(p[1]); + fp = fdopen(p[0], "r"); + if (!fp) + logmsg(LOG_ERR, _("cannot fdopen: %s"), + strerror(errno)); + *ppid = pid; } - - close (p[0]); - - /* Close unneded descripitors */ - for (i = getdtablesize (); i > 2; i--) - close (i); - - execvp (argv[0], (char**) argv); - logmsg (LOG_CRIT, _("cannot run %s: %s"), argv[0], strerror (errno)); - exit (EX_UNAVAILABLE); - - case -1: - logmsg (LOG_CRIT, _("cannot run `%s': fork failed: %s"), - argv[0], strerror (errno)); - return NULL; - - default: - /* Master process */ - close (p[1]); - fp = fdopen (p[0], "r"); - if (!fp) - logmsg (LOG_ERR, _("cannot fdopen: %s"), strerror (errno)); - *ppid = pid; - } - return fp; + return fp; } /* Log everything read from FP as the output from the program PROG, using syslog priority PRIO. */ void -log_output (int prio, const char *prog, FILE *fp) +log_output(int prio, const char *prog, FILE * fp) { - size_t size = 0; - char *buf = NULL; - - logmsg (prio, _("%s output follows:"), prog); - while (grecs_getline (&buf, &size, fp) > 0) - logmsg (prio, "%s", buf); - logmsg (prio, _("end of %s output"), prog); - free (buf); + size_t size = 0; + char *buf = NULL; + + logmsg(prio, _("%s output follows:"), prog); + while (grecs_getline(&buf, &size, fp) > 0) + logmsg(prio, "%s", buf); + logmsg(prio, _("end of %s output"), prog); + free(buf); } /* Execute ARGC/ARGV. Return the exit code in RETCODE. */ enum exec_result -wydawca_exec (int argc, const char **argv, int *retcode) +wydawca_exec(int argc, const char **argv, int *retcode) { - FILE *fp; - pid_t pid, npid; - int status; - int i; - enum exec_result res; - - fp = start_prog (5, argv, &pid); - if (!fp) - { - logmsg (LOG_CRIT, _("cannot start %s"), argv[0]); - return exec_error; - } - - for (i = 0; i < 5 && (npid = waitpid (pid, &status, WNOHANG)) == 0; i++) - sleep (1); - - switch (npid) - { - case -1: - logmsg (LOG_CRIT, _("cannot execute %s: waitpid failed: %s"), - argv[0], strerror (errno)); - fclose (fp); - return exec_error; - - case 0: - logmsg (LOG_CRIT, - _("cannot execute %s: the process did not respond " - "within 5 seconds: %s"), - argv[0], strerror (errno)); - kill (pid, SIGKILL); - fclose (fp); - return exec_error; - - default: - break; - } - - if (WIFEXITED (status)) - { - int rc = WEXITSTATUS (status); - if (rc) - { - res = exec_fail; - logmsg (LOG_ERR, _("command %s returned %d"), argv[0], rc); - log_output (LOG_ERR, argv[0], fp); + FILE *fp; + pid_t pid, npid; + int status; + int i; + enum exec_result res; + + fp = start_prog(5, argv, &pid); + if (!fp) { + logmsg(LOG_CRIT, _("cannot start %s"), argv[0]); + return exec_error; } - else - { - res = exec_success; - if (debug_level > 1) - log_output (LOG_DEBUG, argv[0], fp); + + for (i = 0; i < 5 && (npid = waitpid(pid, &status, WNOHANG)) == 0; i++) + sleep(1); + + switch (npid) { + case -1: + logmsg(LOG_CRIT, _("cannot execute %s: waitpid failed: %s"), + argv[0], strerror(errno)); + fclose(fp); + return exec_error; + + case 0: + logmsg(LOG_CRIT, + _("cannot execute %s: the process did not respond " + "within 5 seconds: %s"), argv[0], strerror(errno)); + kill(pid, SIGKILL); + fclose(fp); + return exec_error; + + default: + break; } - if (retcode) - *retcode = rc; - } - else - { - res = exec_error; - if (WIFSIGNALED (status)) - logmsg (LOG_ERR, _("%s terminated on signal %d"), - argv[0], WTERMSIG (status)); - else if (WIFSTOPPED (status)) - logmsg (LOG_ERR, _("%s stopped on signal %d"), - argv[0], WTERMSIG (status)); - else - logmsg (LOG_ERR, _("%s terminated with unrecognized status"), - argv[0]); - } - fclose (fp); - - return res; + + if (WIFEXITED(status)) { + int rc = WEXITSTATUS(status); + if (rc) { + res = exec_fail; + logmsg(LOG_ERR, _("command %s returned %d"), argv[0], + rc); + log_output(LOG_ERR, argv[0], fp); + } else { + res = exec_success; + if (debug_level > 1) + log_output(LOG_DEBUG, argv[0], fp); + } + if (retcode) + *retcode = rc; + } else { + res = exec_error; + if (WIFSIGNALED(status)) + logmsg(LOG_ERR, _("%s terminated on signal %d"), + argv[0], WTERMSIG(status)); + else if (WIFSTOPPED(status)) + logmsg(LOG_ERR, _("%s stopped on signal %d"), + argv[0], WTERMSIG(status)); + else + logmsg(LOG_ERR, + _("%s terminated with unrecognized status"), + argv[0]); + } + fclose(fp); + + return res; } |