popen.c

Go to the documentation of this file.
00001 /*
00002  * popen - open a pipe
00003  */
00004 /* $Header: /opt/proj/minix/cvsroot/src/lib/other/popen.c,v 1.1.1.1 2005/04/21 14:56:27 beng Exp $ */
00005 
00006 #include        <sys/types.h>
00007 #include        <limits.h>
00008 #include        <errno.h>
00009 #include        <signal.h>
00010 #include        <stdio.h>
00011 
00012 #if     defined(__BSD4_2)
00013 union wait {
00014         int     w_status;
00015 };
00016 typedef union wait wait_arg;
00017 #else
00018 typedef int wait_arg;
00019 #endif  /* __BSD4_2 */
00020 
00021 #include        "../stdio/loc_incl.h"
00022 
00023 #ifdef _ANSI
00024 int _close(int d);
00025 int _dup2(int oldd, int newd);          /* not present in System 5 */
00026 int _execl(const char *name, const char *_arg, ... );
00027 pid_t _fork(void);
00028 int _pipe(int fildes[2]);
00029 pid_t _wait(wait_arg *status);
00030 void _exit(int status);
00031 #endif
00032 
00033 static int pids[OPEN_MAX];
00034 
00035 FILE *
00036 popen(command, type)
00037 _CONST char *command;
00038 _CONST char *type;
00039 {
00040         int piped[2];
00041         int Xtype = *type == 'r' ? 0 : *type == 'w' ? 1 : 2;
00042         int pid;
00043 
00044         if (Xtype == 2 ||
00045             _pipe(piped) < 0 ||
00046             (pid = _fork()) < 0) return 0;
00047         
00048         if (pid == 0) {
00049                 /* child */
00050                 register int *p;
00051 
00052                 for (p = pids; p < &pids[OPEN_MAX]; p++) {
00053                         if (*p) _close((int)(p - pids));
00054                 }
00055                 _close(piped[Xtype]);
00056                 _dup2(piped[!Xtype], !Xtype);
00057                 _close(piped[!Xtype]);
00058                 _execl("/bin/sh", "sh", "-c", command, (char *) 0);
00059                 _exit(127);     /* like system() ??? */
00060         }
00061 
00062         pids[piped[Xtype]] = pid;
00063         _close(piped[!Xtype]);
00064         return fdopen(piped[Xtype], type);
00065 }
00066 
00067 #if     defined(__BSD4_2)
00068 #define ret_val status.w_status
00069 #else
00070 #define ret_val status
00071 #endif
00072 
00073 int
00074 pclose(stream)
00075 FILE *stream;
00076 {
00077         int fd = fileno(stream);
00078         wait_arg status;
00079         int wret;
00080 
00081 #ifdef _ANSI
00082         void (*intsave)(int) = signal(SIGINT, SIG_IGN);
00083         void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN);
00084 #else
00085         void (*intsave)() = signal(SIGINT, SIG_IGN);
00086         void (*quitsave)() = signal(SIGQUIT, SIG_IGN);
00087 #endif
00088         fclose(stream);
00089         while ((wret = _wait(&status)) != -1) {
00090                 if (wret == pids[fd]) break;
00091         }
00092         if (wret == -1) ret_val = -1;
00093         signal(SIGINT, intsave);
00094         signal(SIGQUIT, quitsave);
00095         pids[fd] = 0;
00096         return ret_val;
00097 }
00098 
00099 #if     defined(__USG)
00100 int _dup(int fildes);
00101 
00102 static int
00103 _dup2(oldd, newd)
00104 int oldd, newd;
00105 {
00106         int i = 0, fd, tmp;
00107         int fdbuf[_NFILES];
00108 
00109         /* ignore the error on the close() */
00110         tmp = errno; (void) _close(newd); errno = tmp;
00111         while ((fd = _dup(oldd)) != newd) {
00112                 if (fd == -1) break;
00113                 fdbuf[i++] = fd;
00114         }
00115         tmp = errno;
00116         while (--i >= 0) {
00117                 _close(fdbuf[i]);
00118         }
00119         errno = tmp;
00120         return -(fd == -1);
00121 }
00122 #endif  /* __USG */

Generated on Fri Apr 14 22:57:25 2006 for minix by  doxygen 1.4.6