#include <sys/wait.h>
#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.
+
+<Senji> So, close on exec only closes if exec isn't going to return then?
+<Diziet> 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'.
+<Senji> Diz - I would rather have a coherant error message than 'child failed'
+<Diziet> 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.
+<Diziet> It should exit calling _exit.
+*/
+
/* Process handling - subprocesses, signals, etc. */
static bool_t signal_handling=False;
struct child {
pid_t pid;
- string_t desc;
+ cstring_t desc;
process_callback_fn *cb;
void *cst;
bool_t finished;
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;
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) {
}
}
-int sys_cmd(const char *path, char *arg, ...)
+int sys_cmd(const char *path, const char *arg, ...)
{
va_list ap;
int rv;
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(). */
+ args[0]=(char *)arg;
i=1;
while ((args[i++]=va_arg(ap,char *)));
execvp(path,args);
static void signal_handler(int signum)
{
+ int saved_errno;
uint8_t thing=0;
sigaddset(&pending,signum);
+ /* XXX the write() may set errno, which can make the main program fail.
+ However, signal handlers aren't allowed to modify anything which
+ is not of type sig_atomic_t. The world is broken. */
+ /* I have decided to save and restore errno anyway; on most
+ architectures on which secnet can run modifications to errno
+ will be atomic, and it seems to be the lesser of the two
+ evils. */
+ saved_errno=errno;
write(spw,&thing,1); /* We don't care if this fails (i.e. the pipe
is full) because the service routine will
spot the pending signal anyway */
+ errno=saved_errno;
}
static void register_signal_handler(struct signotify *s)