X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=secnet.git;a=blobdiff_plain;f=process.c;h=343be9b58bc59b0eac0330cf5e168e31d7608772;hp=0c6d44388dbad630b0db367585a449be41fa20b4;hb=0cf9c062e165da3e9444dfea93f25f198bb71a0e;hpb=ff05a229397c75142725f45cad191ce4a00625ce diff --git a/process.c b/process.c index 0c6d443..343be9b 100644 --- a/process.c +++ b/process.c @@ -1,27 +1,12 @@ +#define _GNU_SOURCE #include "secnet.h" #include #include #include #include +#include #include "process.h" -/* Advice about children from Peter: -Better way: before the fork, make a pipe. In the child close the -+reading end. Make the writing end close-on-exec. If the dup2 or exec fails, -+write the errno value. In the parent, close the writing end. Now you can read -+from it. If you get an errno value from the pipe, the process failed and you -+know why. If you get EOF, the exec succeeded. - - So, close on exec only closes if exec isn't going to return then? - qu: I wouldn't bother with all that with pipes. Remember that the -+runtime system can still make exec fail when it's `too late'. - Diz - I would rather have a coherant error message than 'child failed' - The child, if it fails to exec, should print a message to stderr -+(giving errno and what it was trying to execute, most likely), and exit -+nonzero. - It should exit calling _exit. -*/ - /* Process handling - subprocesses, signals, etc. */ static bool_t signal_handling=False; @@ -30,7 +15,7 @@ static sigset_t registered,pending; struct child { pid_t pid; - string_t desc; + cstring_t desc; process_callback_fn *cb; void *cst; bool_t finished; @@ -57,7 +42,7 @@ static void set_default_signals(void); their exit status using the callback function. We block SIGCHLD until signal processing has begun. */ pid_t makesubproc(process_entry_fn *entry, process_callback_fn *cb, - void *est, void *cst, string_t desc) + void *est, void *cst, cstring_t desc) { struct child *c; pid_t p; @@ -68,7 +53,7 @@ pid_t makesubproc(process_entry_fn *entry, process_callback_fn *cb, c->cst=cst; if (!signal_handling) { - fatal("makesubproc called before signal handling started\n"); + fatal("makesubproc called before signal handling started"); } p=fork(); if (p==0) { @@ -140,39 +125,63 @@ static void sigchld_handler(void *st, int signum) } } -int sys_cmd(const char *path, char *arg, ...) +int sys_cmd(const char *path, const char *arg, ...) { va_list ap; - int rv; + int rv, rc; pid_t c; - va_start(ap,arg); c=fork(); if (c) { /* Parent -> wait for child */ - waitpid(c,&rv,0); + do { + rc = waitpid(c,&rv,0); + } while(rc < 0 && errno == EINTR); + if (rc < 0) + fatal_perror("sys_cmd: waitpid for %s", path); + if (rc != c) /* OS has gone mad */ + fatal("sys_cmd: waitpid for %s returned wrong process ID!", + path); + if (rv) { + /* If the command failed reporting its exit status */ + if (WIFEXITED(rv)) + Message(M_ERR, "sys_cmd(%s,%s,...) exited with status %d\n", + path, arg, WEXITSTATUS(rv)); + else if(WIFSIGNALED(rv)) + Message(M_ERR, "sys_cmd(%s,%s,...) exited with signal %d (%s)%s\n", + path, arg, WTERMSIG(rv), strsignal(WTERMSIG(rv)), + WCOREDUMP(rv) ? " - core dumped" : ""); + else + Message(M_ERR, "sys_cmd(%s,%s,...) exited with wstat %#x", + path, arg, rv); + } } else if (c==0) { char *args[100]; int i; /* Child -> exec command */ - args[0]=arg; + /* Really we ought to strcpy() the arguments into the args array, + since the arguments are const char *. Since we'll exit anyway + if the execvp() fails this seems somewhat pointless, and + increases the chance of the child process failing before it + gets to exec(). */ + va_start(ap,arg); + args[0]=(char *)arg; /* program name */ i=1; while ((args[i++]=va_arg(ap,char *))); execvp(path,args); - exit(1); + fprintf(stderr, "sys_cmd(%s,%s,...): %s\n", path, arg, strerror(errno)); + _exit(1); } else { /* Error */ - fatal_perror("sys_cmd(%s,%s,...)"); + fatal_perror("sys_cmd(%s,%s,...)", path, arg); } - va_end(ap); return rv; } static beforepoll_fn signal_beforepoll; static int signal_beforepoll(void *st, struct pollfd *fds, int *nfds_io, - int *timeout_io, const struct timeval *tv_now, - uint64_t *now) + int *timeout_io) { if (*nfds_io<1) { *nfds_io=1; @@ -185,8 +194,7 @@ static int signal_beforepoll(void *st, struct pollfd *fds, int *nfds_io, } static afterpoll_fn signal_afterpoll; -static void signal_afterpoll(void *st, struct pollfd *fds, int nfds, - const struct timeval *tv, uint64_t *now) +static void signal_afterpoll(void *st, struct pollfd *fds, int nfds) { uint8_t buf[16]; struct signotify *n;