123 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * popen - open a pipe
 | |
|  */
 | |
| /* $Header$ */
 | |
| 
 | |
| #include	<sys/types.h>
 | |
| #include	<limits.h>
 | |
| #include	<errno.h>
 | |
| #include	<signal.h>
 | |
| #include	<stdio.h>
 | |
| 
 | |
| #if	defined(__BSD4_2)
 | |
| union wait {
 | |
| 	int	w_status;
 | |
| };
 | |
| typedef union wait wait_arg;
 | |
| #else
 | |
| typedef int wait_arg;
 | |
| #endif	/* __BSD4_2 */
 | |
| 
 | |
| #include	"../stdio/loc_incl.h"
 | |
| 
 | |
| #ifdef _ANSI
 | |
| int _close(int d);
 | |
| int _dup2(int oldd, int newd);		/* not present in System 5 */
 | |
| int _execl(const char *name, const char *_arg, ... );
 | |
| pid_t _fork(void);
 | |
| int _pipe(int fildes[2]);
 | |
| pid_t _wait(wait_arg *status);
 | |
| void _exit(int status);
 | |
| #endif
 | |
| 
 | |
| static int pids[OPEN_MAX];
 | |
| 
 | |
| FILE *
 | |
| popen(command, type)
 | |
| _CONST char *command;
 | |
| _CONST char *type;
 | |
| {
 | |
| 	int piped[2];
 | |
| 	int Xtype = *type == 'r' ? 0 : *type == 'w' ? 1 : 2;
 | |
| 	int pid;
 | |
| 
 | |
| 	if (Xtype == 2 ||
 | |
| 	    _pipe(piped) < 0 ||
 | |
| 	    (pid = _fork()) < 0) return 0;
 | |
| 	
 | |
| 	if (pid == 0) {
 | |
| 		/* child */
 | |
| 		register int *p;
 | |
| 
 | |
| 		for (p = pids; p < &pids[OPEN_MAX]; p++) {
 | |
| 			if (*p) _close((int)(p - pids));
 | |
| 		}
 | |
| 		_close(piped[Xtype]);
 | |
| 		_dup2(piped[!Xtype], !Xtype);
 | |
| 		_close(piped[!Xtype]);
 | |
| 		_execl("/bin/sh", "sh", "-c", command, (char *) 0);
 | |
| 		_exit(127);	/* like system() ??? */
 | |
| 	}
 | |
| 
 | |
| 	pids[piped[Xtype]] = pid;
 | |
| 	_close(piped[!Xtype]);
 | |
| 	return fdopen(piped[Xtype], type);
 | |
| }
 | |
| 
 | |
| #if	defined(__BSD4_2)
 | |
| #define	ret_val	status.w_status
 | |
| #else
 | |
| #define	ret_val	status
 | |
| #endif
 | |
| 
 | |
| int
 | |
| pclose(stream)
 | |
| FILE *stream;
 | |
| {
 | |
| 	int fd = fileno(stream);
 | |
| 	wait_arg status;
 | |
| 	int wret;
 | |
| 
 | |
| #ifdef _ANSI
 | |
| 	void (*intsave)(int) = signal(SIGINT, SIG_IGN);
 | |
| 	void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN);
 | |
| #else
 | |
| 	void (*intsave)() = signal(SIGINT, SIG_IGN);
 | |
| 	void (*quitsave)() = signal(SIGQUIT, SIG_IGN);
 | |
| #endif
 | |
| 	fclose(stream);
 | |
| 	while ((wret = _wait(&status)) != -1) {
 | |
| 		if (wret == pids[fd]) break;
 | |
| 	}
 | |
| 	if (wret == -1) ret_val = -1;
 | |
| 	signal(SIGINT, intsave);
 | |
| 	signal(SIGQUIT, quitsave);
 | |
| 	pids[fd] = 0;
 | |
| 	return ret_val;
 | |
| }
 | |
| 
 | |
| #if	defined(__USG)
 | |
| int _dup(int fildes);
 | |
| 
 | |
| static int
 | |
| _dup2(oldd, newd)
 | |
| int oldd, newd;
 | |
| {
 | |
| 	int i = 0, fd, tmp;
 | |
| 	int fdbuf[_NFILES];
 | |
| 
 | |
| 	/* ignore the error on the close() */
 | |
| 	tmp = errno; (void) _close(newd); errno = tmp;
 | |
| 	while ((fd = _dup(oldd)) != newd) {
 | |
| 		if (fd == -1) break;
 | |
| 		fdbuf[i++] = fd;
 | |
| 	}
 | |
| 	tmp = errno;
 | |
| 	while (--i >= 0) {
 | |
| 		_close(fdbuf[i]);
 | |
| 	}
 | |
| 	errno = tmp;
 | |
| 	return -(fd == -1);
 | |
| }
 | |
| #endif	/* __USG */
 | 
