diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-08-22 13:23:03 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-08-22 13:23:03 +0000 |
commit | 180ca1d87d2bf69d9dbb0acb76422e9ae15f930c (patch) | |
tree | b14651206aaec8e03fdfdce9e04433068fa62648 /src/exec.c | |
parent | 708a28a2f5bd2384e4c254a47d069ec4d9ef697e (diff) | |
download | wydawca-180ca1d87d2bf69d9dbb0acb76422e9ae15f930c.tar.gz wydawca-180ca1d87d2bf69d9dbb0acb76422e9ae15f930c.tar.bz2 |
Implement all directives
git-svn-id: file:///svnroot/wydawca/trunk@284 6bb4bd81-ecc2-4fd4-a2d4-9571d19c0d33
Diffstat (limited to 'src/exec.c')
-rw-r--r-- | src/exec.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/src/exec.c b/src/exec.c new file mode 100644 index 0000000..1f9e27a --- /dev/null +++ b/src/exec.c @@ -0,0 +1,155 @@ +/* wydawca - FTP release synchronisation daemon + Copyright (C) 2007 Sergey Poznyakoff + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or (at your + option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "wydawca.h" +#include "save-cwd.h" +#include <gpgme.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> + +static FILE * +start_prog (int argc, const char **argv, pid_t *ppid) +{ + int p[2]; + FILE *fp; + pid_t pid; + int i; + + pipe (p); + switch (pid = fork ()) + { + case 0: + /* Child process */ + + if (p[1] != 1) + dup2 (p[1], 1); + if (p[1] != 1) + dup2 (p[1], 2); + close (p[0]); + + /* Close unneded descripitors */ + for (i = getmaxfd (); i > 2; i--) + close (i); + + execvp (argv[0], (char**) argv); + logmsg (LOG_CRIT, "cannot run %s: %s", argv[0], strerror (errno)); + exit (1); + + 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; +} + +void +log_output (int prio, const char *prog, FILE *fp) +{ + size_t size = 0; + char *buf = NULL; + + logmsg (prio, "%s output follows:", prog); + while (getline (&buf, &size, fp) > 0) + logmsg (prio, "%s", buf); + logmsg (prio, "end of %s output", prog); + free (buf); +} + +enum exec_result +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); + } + 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; +} |