Changeset 201 for trunk/base


Ignore:
Timestamp:
Aug 19, 2002, 2:38:55 AM (22 years ago)
Author:
leimy
Message:

Added dup2popen which "should" do exactly what popen does but combining
STDERR and STDOUT. Not heavilly tested but should compile.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/base/Tcl/port1.0/Pextlib.c

    r195 r201  
    66#include <sys/file.h>
    77#include <sys/types.h>
     8#include <sys/param.h>
     9#include <sys/wait.h>
     10#include <sys/socket.h>
     11#include <signal.h>
     12#include <unistd.h>
     13#include <paths.h>
     14
     15#include <crt_externs.h>
     16
    817#include <tcl.h>
    918
     
    2938}
    3039
     40#define environ *(_NSGetEnviron())
     41static struct pid {
     42        struct pid *next;
     43        FILE *fp;
     44        pid_t pid;
     45} *pidlist;
     46
     47FILE *
     48dup2popen (command, type) /*stderr and stdout together in the output*/
     49        const char * command, *type;
     50{
     51        struct pid *cur;
     52        FILE *iop;
     53        int pdes[2], pid, twoway;
     54        char *argv[4];
     55        struct pid *p;
     56
     57        if (strchr(type, '+')) {
     58                twoway = 1;
     59                type = "r+";
     60                if (socketpair(AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
     61                        return (NULL);
     62        } else  {
     63                twoway = 0;
     64                if ((*type != 'r' && *type != 'w') || type[1])
     65                        return (NULL);
     66        }
     67        if (pipe(pdes) < 0)
     68                return (NULL);
     69
     70        if ((cur = malloc(sizeof(struct pid))) == NULL) {
     71                (void)close(pdes[0]);
     72                (void)close(pdes[1]);
     73                return (NULL);
     74        }
     75
     76        argv[0] = "sh";
     77        argv[1] = "-c";
     78        argv[2] = (char *)command;
     79        argv[3] = NULL;
     80
     81        switch (pid = vfork()) {
     82        case -1:                        /* Error. */
     83                (void)close(pdes[0]);
     84                (void)close(pdes[1]);
     85                free(cur);
     86                return (NULL);
     87                /* NOTREACHED */
     88        case 0:                         /* Child. */
     89                if (*type == 'r') {
     90                        /*
     91                         * The _dup2() to STDIN_FILENO is repeated to avoid
     92                         * writing to pdes[1], which might corrupt the
     93                         * parent's copy.  This isn't good enough in
     94                         * general, since the _exit() is no return, so
     95                         * the compiler is free to corrupt all the local
     96                         * variables.
     97                         */
     98                        (void)close(pdes[0]);
     99                        if (pdes[1] != STDOUT_FILENO) {
     100                                (void)dup2(pdes[1], STDOUT_FILENO);
     101                                (void)close(pdes[1]);
     102                                if (twoway)
     103                                        (void)dup2(STDOUT_FILENO, STDIN_FILENO);
     104                        } else if (twoway && (pdes[1] != STDIN_FILENO))
     105                                (void)dup2(pdes[1], STDIN_FILENO);
     106                } else {
     107                        if (pdes[0] != STDIN_FILENO) {
     108                                (void)dup2(pdes[0], STDIN_FILENO);
     109                                (void)close(pdes[0]);
     110                        }
     111                        (void)close(pdes[1]);
     112                        }
     113                for (p = pidlist; p; p = p->next) {
     114                        (void)close(fileno(p->fp));
     115                }
     116                (void)dup2(STDOUT_FILENO,STDERR_FILENO);
     117                execve(_PATH_BSHELL, argv, environ);
     118                _exit(127);
     119                /* NOTREACHED */
     120        }
     121
     122        /* Parent; assume fdopen can't fail. */
     123        if (*type == 'r') {
     124                iop = fdopen(pdes[0], type);
     125                (void)close(pdes[1]);
     126        } else {
     127                iop = fdopen(pdes[1], type);
     128                (void)close(pdes[0]);
     129        }
     130
     131        /* Link into list of file descriptors. */
     132        cur->fp = iop;
     133        cur->pid =  pid;
     134        cur->next = pidlist;
     135        pidlist = cur;
     136
     137        return (iop);
     138}
     139
     140
    31141int SystemCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
    32142{
     
    34144        char *cmdstring, *p;
    35145        FILE *pipe;
     146       
    36147        int i, cmdlen, cmdlenavail;
    37148        cmdlen = cmdlenavail = BUFSIZ;
     
    95206        }
    96207
    97         pipe = popen(cmdstring, "r");
     208        /*pipe = popen(cmdstring, "r");*/
     209        pipe = dup2popen(cmdstring, "r");
     210        /*Gutted the popen code...*/
    98211        if (p != NULL)
    99212                free(cmdstring);
Note: See TracChangeset for help on using the changeset viewer.