sigset_t fset;
sigset_t eset;
static struct child *findchild __P((int));static void delchild __P((struct child *));static int file_pid __P((FILE *));static int handle_spool_locks __P((int));FILE *Fopen(file, mode)	char *file, *mode;{	FILE *fp;	if ((fp = fopen(file, mode)) != NULL) {		register_file(fp, 0, 0);		(void)fcntl(fileno(fp), F_SETFD, 1);	}	return(fp);}FILE *Fdopen(fd, mode)	int fd;	char *mode;{	FILE *fp;	if ((fp = fdopen(fd, mode)) != NULL) {		register_file(fp, 0, 0);		(void)fcntl(fileno(fp), F_SETFD, 1);	}	return(fp);}intFclose(fp)	FILE *fp;{	unregister_file(fp);	return(fclose(fp));}FILE *Popen(cmd, mode)	char *cmd;	char *mode;{	int p[2];	int myside, hisside, fd0, fd1;	int pid;	sigset_t nset;	FILE *fp;	if (pipe(p) < 0)		return(NULL);	(void)fcntl(p[READ], F_SETFD, 1);	(void)fcntl(p[WRITE], F_SETFD, 1);	if (*mode == 'r') {		myside = p[READ];		fd0 = -1;		hisside = fd1 = p[WRITE];	} else {		myside = p[WRITE];		hisside = fd0 = p[READ];		fd1 = -1;	}	sigemptyset(&nset);	if ((pid = start_command(cmd, &nset, fd0, fd1, NULL, NULL, NULL)) < 0) {		(void)close(p[READ]);		(void)close(p[WRITE]);		return(NULL);	}	(void)close(hisside);	if ((fp = fdopen(myside, mode)) != NULL)		register_file(fp, 1, pid);	return(fp);}intPclose(ptr)	FILE *ptr;{	int i;	sigset_t nset, oset;	i = file_pid(ptr);	unregister_file(ptr);	(void)fclose(ptr);	sigemptyset(&nset);	sigaddset(&nset, SIGINT);	sigaddset(&nset, SIGHUP);	sigprocmask(SIG_BLOCK, &nset, &oset);	i = wait_child(i);	sigprocmask(SIG_SETMASK, &oset, NULL);	return(i);}voidclose_all_files(){	while (fp_head)		if (fp_head->pipe)			(void)Pclose(fp_head->fp);		else			(void)Fclose(fp_head->fp);}voidregister_file(fp, pipe, pid)	FILE *fp;	int pipe, pid;{	struct fp *fpp;	if ((fpp = (struct fp *)malloc(sizeof(*fpp))) == NULL)		panic("Out of memory");	fpp->fp = fp;	fpp->pipe = pipe;	fpp->pid = pid;	fpp->link = fp_head;	fp_head = fpp;}voidunregister_file(fp)	FILE *fp;{	struct fp **pp, *p;	for (pp = &fp_head; (p = *pp) != NULL; pp = &p->link)		if (p->fp == fp) {			*pp = p->link;			(void)free(p);			return;		}	panic("Invalid file pointer");}static intfile_pid(fp)	FILE *fp;{	struct fp *p;	for (p = fp_head; p; p = p->link)		if (p->fp == fp)			return(p->pid);	panic("Invalid file pointer");	/*NOTREACHED*/}/* * Run a command without a shell, with optional arguments and splicing * of stdin and stdout.  The command name can be a sequence of words. * Signals must be handled by the caller. * "Mask" contains the signals to ignore in the new process. * SIGINT is enabled unless it's in the mask. *//*VARARGS4*/intrun_command(cmd, mask, infd, outfd, a0, a1, a2)	char *cmd;	sigset_t *mask;	int infd, outfd;	char *a0, *a1, *a2;{	int pid;	if ((pid = start_command(cmd, mask, infd, outfd, a0, a1, a2)) < 0)		return(-1);	return(wait_command(pid));}/*VARARGS4*/intstart_command(cmd, mask, infd, outfd, a0, a1, a2)	char *cmd;	sigset_t *mask;	int infd, outfd;	char *a0, *a1, *a2;{	int pid;	if ((pid = vfork()) < 0) {		warn("fork");		return(-1);	}	if (pid == 0) {		char *argv[100];		int i = getrawlist(cmd, argv, sizeof(argv)/ sizeof(*argv));		if ((argv[i++] = a0) != NULL &&		    (argv[i++] = a1) != NULL &&		    (argv[i++] = a2) != NULL)			argv[i] = NULL;		prepare_child(mask, infd, outfd);		execvp(argv[0], argv);		warn(argv[0]);		_exit(1);	}	return(pid);}voidprepare_child(nset, infd, outfd)	sigset_t *nset;	int infd, outfd;{	int i;	sigset_t fset;	/*	 * All file descriptors other than 0, 1, and 2 are supposed to be	 * close-on-exec.	 */	if (infd >= 0)		dup2(infd, 0);	if (outfd >= 0)		dup2(outfd, 1);	if (nset == NULL)		return;	if (nset != NULL) {		for (i = 1; i < NSIG; i++)			if (sigismember(nset, i))				(void)signal(i, SIG_IGN);	}	if (nset == NULL || !sigismember(nset, SIGINT))		(void)signal(SIGINT, SIG_DFL);	sigfillset(&fset);	(void)sigprocmask(SIG_UNBLOCK, &fset, NULL);}intwait_command(pid)	int pid;{	if (wait_child(pid) < 0) {		puts("Fatal error in process.");		return(-1);	}	return(0);}static struct child *findchild(pid)	int pid;{	register struct child **cpp;	for (cpp = &child; *cpp != NULL && (*cpp)->pid != pid;	     cpp = &(*cpp)->link)			;	if (*cpp == NULL) {		*cpp = (struct child *)malloc(sizeof(struct child));		(*cpp)->pid = pid;		(*cpp)->done = (*cpp)->free = 0;		(*cpp)->link = NULL;	}	return(*cpp);}