From 3e81b0123b4bbfedbdc1135a6a4305c347f91a3a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Aug 2003 16:41:59 +0000 Subject: Initial commit git-svn-id: file:///home/lennart/svn/public/aeswepd/trunk@3 022f378f-78c4-0310-b860-d162c87e6274 --- src/exec.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 src/exec.c (limited to 'src/exec.c') diff --git a/src/exec.c b/src/exec.c new file mode 100644 index 0000000..2e8b33b --- /dev/null +++ b/src/exec.c @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "exec.h" + +int log_exec(const char *dir, const char *prog, const char *arg) { + pid_t pid; + int p[2]; + unsigned n = 0; + static char buf[256]; + int sigfd, r; + fd_set fds; + + daemon_log(LOG_INFO, "Running '%s %s'", prog, arg); + + if (pipe(p) < 0) { + daemon_log(LOG_ERR, "pipe() failed: %s", strerror(errno)); + return -1; + } + + if ((pid = fork()) < 0) { + daemon_log(LOG_ERR, "fork() failed: %s", strerror(errno)); + return -1; + + } else if (pid == 0) { + dup2(p[1], 1); + dup2(p[1], 2); + + if (p[0] > 2) + close(p[0]); + + if (p[1] > 2) + close(p[1]); + + close(0); + open("/dev/null", O_RDONLY); + + umask(0022); // Set up a sane umask + + if (dir && chdir(dir) < 0) { + daemon_log(LOG_WARNING, "Failed to change to directory '%s'", dir); + chdir("/"); + } + + execl(prog, prog, arg, 0); + + daemon_log(LOG_ERR, "execl(%s) failed: %s\n", prog, strerror(errno)); + + _exit(EXIT_FAILURE); + } + + close(p[1]); + + FD_ZERO(&fds); + FD_SET(p[0], &fds); + FD_SET(sigfd = daemon_signal_fd(), &fds); + + n = 0; + + for (;;) { + fd_set qfds = fds; + + if (select(FD_SETSIZE, &qfds, NULL, NULL, NULL) < 0) { + + if (errno == EINTR) + continue; + + daemon_log(LOG_ERR, "select() failed: %s", strerror(errno)); + return -1; + } + + + if (FD_ISSET(p[0], &qfds)) { + char c; + + if (read(p[0], &c, 1) != 1) + break; + + buf[n] = c; + + if (c == '\n' || n >= sizeof(buf) - 2) { + if (c != '\n') n++; + buf[n] = 0; + + if (buf[0]) + daemon_log(LOG_INFO, "client: %s", buf); + + n = 0; + } else + n++; + } + + if (FD_ISSET(sigfd, &qfds)) { + int sig; + + if ((sig = daemon_signal_next()) < 0) { + daemon_log(LOG_ERR, "daemon_signal_next(): %s", strerror(errno)); + break; + } + + if (sig != SIGCHLD) { + daemon_log(LOG_WARNING, "Killing child."); + kill(pid, SIGTERM); + } + + break; + } + } + + if (n > 0) { + buf[n] = 0; + daemon_log(LOG_WARNING, "client: %s", buf); + } + + waitpid(pid, &r, 0); + + close(p[0]); + + if (!WIFEXITED(r) || WEXITSTATUS(r) != 0) { + daemon_log(LOG_ERR, "Program execution failed, return value is %i.", WEXITSTATUS(r)); + return -1; + } else { + daemon_log(LOG_INFO, "Program executed successfully."); + return 0; + } +} -- cgit