| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 | /* * Modified     3/03/2001       Manuel Novoa III * * Added check for legal mode arg. * Call fdopen and check return value before forking. * Reduced code size by using variables pr and pnr instead of array refs. */#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>#include <errno.h>FILE *popen (const char *command, const char *mode){	FILE *fp;	int pipe_fd[2];	int pid, reading;	int pr, pnr;	reading = (mode[0] == 'r');	if ((!reading && (mode[0] != 'w')) || mode[1]) {		__set_errno(EINVAL);			/* Invalid mode arg. */	} else if (pipe(pipe_fd) == 0) {		pr = pipe_fd[reading];		pnr = pipe_fd[1-reading];		if ((fp = fdopen(pnr, mode)) != NULL) {			if ((pid = vfork()) == 0) {	/* vfork -- child */				close(pnr);				close(reading);				if (pr != reading) {					dup2(pr, reading);					close(pr);				}				execl("/bin/sh", "sh", "-c", command, (char *) 0);				_exit(255);		/* execl failed! */			} else {			/* vfork -- parent or failed */				close(pr);				if (pid > 0) {	/* vfork -- parent */					return fp;				} else {		/* vfork -- failed! */					fclose(fp);				}			}		} else {				/* fdopen failed */			close(pr);			close(pnr);		}	}	return NULL;}int pclose(FILE *fd){	int waitstat;	if (fclose(fd) != 0) {		return EOF;	}	wait(&waitstat);	return waitstat;}
 |