if ((pid = start_command(value("SHELL"), &nset, fd0, fd1, "-c", cmd, NULL)) < 0) {
if (strpbrk(cmd, "$&*(){}[]'\";\\|?<>~`")) pid = start_command(value("SHELL"), &nset, fd0, fd1, "-c", cmd, NULL); else pid = start_command(cmd, &nset, fd0, fd1, NULL); if (pid < 0) {
static struct child *findchild __P((int, 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];		hisside = fd0 = fd1 = p[WRITE];	} else {		myside = p[WRITE];		hisside = fd0 = p[READ];		fd1 = -1;	}	sigemptyset(&nset);	if ((pid = start_command(value("SHELL"), &nset, fd0, fd1,						"-c", cmd, 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)		errx(1, "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;		}	errx(1, "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);	errx(1, "Invalid file pointer");	/*NOTREACHED*/}/* * Run a command without a shell, with optional arguments and splicing * of stdin (-1 means none) and stdout.  The command name can be a sequence * of words. * Signals must be handled by the caller. * "nset" contains the signals to ignore in the new process. * SIGINT is enabled unless it's in "nset". */intstart_commandv(cmd, nset, infd, outfd, args)	char *cmd;	sigset_t *nset;	int infd, outfd;	va_list args;{	int pid;	if ((pid = fork()) < 0) {		warn("fork");		return(-1);	}	if (pid == 0) {		char *argv[100];		int i = getrawlist(cmd, argv, sizeof(argv)/ sizeof(*argv));		while ((argv[i++] = va_arg(args, char *)))			;		argv[i] = NULL;		prepare_child(nset, infd, outfd);		execvp(argv[0], argv);		warn("%s", argv[0]);		_exit(1);	}	return(pid);}int#ifdef __STDC__run_command(char *cmd, sigset_t *nset, int infd, int outfd, ...)#elserun_command(cmd, nset, infd, outfd, va_alist)	char *cmd;	sigset_t *nset;	int infd;	int outfd;	va_dcl#endif{	int pid;	va_list args;#ifdef __STDC__	va_start(args, outfd);#else	va_start(args);#endif	pid = start_commandv(cmd, nset, infd, outfd, args);	va_end(args);	if (pid < 0)		return(-1);	return(wait_command(pid));}int#ifdef __STDC__start_command(char *cmd, sigset_t *nset, int infd, int outfd, ...)#elsestart_command(cmd, nset, infd, outfd, va_alist)	char *cmd;	sigset_t *nset;	int infd;	int outfd;	va_dcl#endif{	va_list args;	int r;#ifdef __STDC__	va_start(args, outfd);#else	va_start(args);#endif	r = start_commandv(cmd, nset, infd, outfd, args);	va_end(args);	return(r);}voidprepare_child(nset, infd, outfd)	sigset_t *nset;	int infd, outfd;{	int i;	sigset_t eset;	/*	 * All file descriptors other than 0, 1, and 2 are supposed to be	 * close-on-exec.	 */	if (infd > 0) {		dup2(infd, 0);	} else if (infd != 0) {		/* we don't want the child stealing my stdin input */		close(0);		open(_PATH_DEVNULL, O_RDONLY, 0);	}	if (outfd >= 0 && outfd != 1)		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);	sigemptyset(&eset);	(void)sigprocmask(SIG_SETMASK, &eset, 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, dont_alloc)	int pid;	int dont_alloc;{	struct child **cpp;	for (cpp = &child; *cpp != NULL && (*cpp)->pid != pid;	     cpp = &(*cpp)->link)			;	if (*cpp == NULL) {		if (dont_alloc)			return(NULL);		if (child_freelist) {			*cpp = child_freelist;			child_freelist = (*cpp)->link;		} else			*cpp = (struct child *)malloc(sizeof(struct child));		(*cpp)->pid = pid;		(*cpp)->done = (*cpp)->free = 0;		(*cpp)->link = NULL;	}	return(*cpp);}