/* -*- linux-c -*-
 *
 * spawn.c
 *
 *  Fork-and-wait routine
 *
 */

#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>

#include "automount.h"

/* Used by subprocesses to avoid carrying over the main daemon's rather
   weird signalling environment */
void reset_signals(void)
{
	struct sigaction sa;
	sigset_t allsignals;
	int i;

	sigfillset(&allsignals);
	sigprocmask(SIG_BLOCK, &allsignals, NULL);

	sa.sa_handler = SIG_DFL;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	for ( i = 1 ; i < NSIG ; i++ )
		sigaction(i, &sa, NULL);

	sigprocmask(SIG_UNBLOCK, &allsignals, NULL);
}

int spawnl(char *prog, ...) {
	va_list arg;
	pid_t f;
	int status;
	int argc;
	char **argv, **p;
	sigset_t allsignals, oldsig;
	
	va_start(arg,prog);
	for ( argc = 1 ; va_arg(arg,char *) ; argc++ ); 
	va_end(arg);

	if ( !(argv = alloca(sizeof(char *) * argc)) )
		return -1;

	va_start(arg,prog);
	p = argv;
	while ((*p++ = va_arg(arg,char *)));
	va_end(arg);

	sigfillset(&allsignals);
	sigprocmask(SIG_BLOCK, &allsignals, &oldsig);

	f = fork();
	if ( f == 0 ) {
		reset_signals();
		execv(prog, argv);
		_exit(255);	/* execv() failed */
	} else {
		sigprocmask(SIG_SETMASK, &oldsig, NULL);
		if ( f < 0 || waitpid(f, &status, 0) != f )
			return -1; /* waitpid() failed */
		else
			return status;
	}
}
