xref: /csrg-svn/lib/libc/gen/popen.c (revision 36302)
122101Smckusick /*
235451Sbostic  * Copyright (c) 1988 The Regents of the University of California.
335451Sbostic  * All rights reserved.
435451Sbostic  *
535458Sbostic  * This code is derived from software written by Ken Arnold and
635458Sbostic  * published in UNIX Review, Vol. 6, No. 8.
735451Sbostic  *
835451Sbostic  * Redistribution and use in source and binary forms are permitted
935451Sbostic  * provided that the above copyright notice and this paragraph are
1035451Sbostic  * duplicated in all such forms and that any documentation,
1135451Sbostic  * advertising materials, and other materials related to such
1235451Sbostic  * distribution and use acknowledge that the software was developed
1335451Sbostic  * by the University of California, Berkeley.  The name of the
1435451Sbostic  * University may not be used to endorse or promote products derived
1535451Sbostic  * from this software without specific prior written permission.
1635451Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1735451Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1835451Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1922101Smckusick  */
2016676Ssam 
2126575Sdonn #if defined(LIBC_SCCS) && !defined(lint)
22*36302Skarels static char sccsid[] = "@(#)popen.c	5.8 (Berkeley) 12/06/88";
2335451Sbostic #endif /* LIBC_SCCS and not lint */
2422101Smckusick 
2535458Sbostic #include <sys/param.h>
2635458Sbostic #include <sys/signal.h>
2735458Sbostic #include <sys/wait.h>
282024Swnj #include <stdio.h>
2916676Ssam 
30*36302Skarels static pid_t *pids;
3135458Sbostic static int fds;
322024Swnj 
332024Swnj FILE *
3435451Sbostic popen(program, type)
3535458Sbostic 	char *program, *type;
362024Swnj {
3735458Sbostic 	FILE *iop;
3835451Sbostic 	int pdes[2], pid;
3935458Sbostic 	char *malloc();
402024Swnj 
4135458Sbostic 	if (*type != 'r' && *type != 'w' || type[1])
4235458Sbostic 		return(NULL);
4335458Sbostic 
44*36302Skarels 	if (pids == NULL) {
4535458Sbostic 		if ((fds = getdtablesize()) <= 0)
4635458Sbostic 			return(NULL);
47*36302Skarels 		if ((pids = (pid_t *)malloc((u_int)(fds * sizeof(int)))) == NULL)
4835458Sbostic 			return(NULL);
49*36302Skarels 		bzero((char *)pids, fds * sizeof(pid_t));
5035458Sbostic 	}
5135451Sbostic 	if (pipe(pdes) < 0)
5235458Sbostic 		return(NULL);
53*36302Skarels 	switch (pid = vfork()) {
5435458Sbostic 	case -1:			/* error */
5535458Sbostic 		(void)close(pdes[0]);
5635458Sbostic 		(void)close(pdes[1]);
5735458Sbostic 		return(NULL);
5835458Sbostic 		/* NOTREACHED */
5935458Sbostic 	case 0:				/* child */
6035451Sbostic 		if (*type == 'r') {
6135458Sbostic 			if (pdes[1] != 1) {
6235458Sbostic 				dup2(pdes[1], 1);
6335458Sbostic 				(void)close(pdes[1]);
6435458Sbostic 			}
6535458Sbostic 			(void)close(pdes[0]);
6635458Sbostic 		} else {
6735458Sbostic 			if (pdes[0] != 0) {
6835458Sbostic 				dup2(pdes[0], 0);
6935458Sbostic 				(void)close(pdes[0]);
7035458Sbostic 			}
7135458Sbostic 			(void)close(pdes[1]);
7214718Ssam 		}
7335451Sbostic 		execl("/bin/sh", "sh", "-c", program, NULL);
7435458Sbostic 		_exit(127);
7535451Sbostic 		/* NOTREACHED */
762024Swnj 	}
7735458Sbostic 	/* parent; assume fdopen can't fail...  */
7835458Sbostic 	if (*type == 'r') {
7935458Sbostic 		iop = fdopen(pdes[0], type);
8035458Sbostic 		(void)close(pdes[1]);
8135458Sbostic 	} else {
8235458Sbostic 		iop = fdopen(pdes[1], type);
8335458Sbostic 		(void)close(pdes[0]);
8415073Skarels 	}
8535458Sbostic 	pids[fileno(iop)] = pid;
8635458Sbostic 	return(iop);
872024Swnj }
882024Swnj 
8935451Sbostic pclose(iop)
9035458Sbostic 	FILE *iop;
912024Swnj {
9235458Sbostic 	register int fdes;
93*36302Skarels 	int omask;
9435458Sbostic 	int stat_loc;
9535458Sbostic 	pid_t waitpid();
962024Swnj 
9735458Sbostic 	/*
9835458Sbostic 	 * pclose returns -1 if stream is not associated with a
9935458Sbostic 	 * `popened' command, or, if already `pclosed'.
10035458Sbostic 	 */
101*36302Skarels 	if (pids == NULL || pids[fdes = fileno(iop)] == 0)
10235458Sbostic 		return(-1);
10335458Sbostic 	(void)fclose(iop);
10435458Sbostic 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
10535458Sbostic 	stat_loc = waitpid(pids[fdes], &stat_loc, 0) == -1 ?
10635458Sbostic 	    -1 : WEXITSTATUS(stat_loc);
10735458Sbostic 	(void)sigsetmask(omask);
10835458Sbostic 	pids[fdes] = 0;
10935458Sbostic 	return(stat_loc);
1102024Swnj }
111