Skip to content
Permalink
Browse files

Added dup2popen which "should" do exactly what popen does but combining

STDERR and STDOUT.  Not heavilly tested but should compile.

git-svn-id: https://svn.macports.org/repository/macports/trunk/base@201 d073be05-634f-4543-b044-5fe20cf6d1d6
  • Loading branch information
David Leimbach
David Leimbach committed Aug 19, 2002
1 parent 72b2732 commit 2672227b723dab74e2c970ee4f6546c3cf4842ba
Showing with 114 additions and 1 deletion.
  1. +114 −1 Tcl/port1.0/Pextlib.c
@@ -5,6 +5,15 @@
#include <dirent.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <signal.h>
#include <unistd.h>
#include <paths.h>

#include <crt_externs.h>

#include <tcl.h>

#define BUFSIZ 1024
@@ -28,11 +37,113 @@ static int ui_info(Tcl_Interp *interp, char *mesg) {
return (Tcl_EvalEx(interp, script, scriptlen - 1, 0));
}

#define environ *(_NSGetEnviron())
static struct pid {
struct pid *next;
FILE *fp;
pid_t pid;
} *pidlist;

FILE *
dup2popen (command, type) /*stderr and stdout together in the output*/
const char * command, *type;
{
struct pid *cur;
FILE *iop;
int pdes[2], pid, twoway;
char *argv[4];
struct pid *p;

if (strchr(type, '+')) {
twoway = 1;
type = "r+";
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
return (NULL);
} else {
twoway = 0;
if ((*type != 'r' && *type != 'w') || type[1])
return (NULL);
}
if (pipe(pdes) < 0)
return (NULL);

if ((cur = malloc(sizeof(struct pid))) == NULL) {
(void)close(pdes[0]);
(void)close(pdes[1]);
return (NULL);
}

argv[0] = "sh";
argv[1] = "-c";
argv[2] = (char *)command;
argv[3] = NULL;

switch (pid = vfork()) {
case -1: /* Error. */
(void)close(pdes[0]);
(void)close(pdes[1]);
free(cur);
return (NULL);
/* NOTREACHED */
case 0: /* Child. */
if (*type == 'r') {
/*
* The _dup2() to STDIN_FILENO is repeated to avoid
* writing to pdes[1], which might corrupt the
* parent's copy. This isn't good enough in
* general, since the _exit() is no return, so
* the compiler is free to corrupt all the local
* variables.
*/
(void)close(pdes[0]);
if (pdes[1] != STDOUT_FILENO) {
(void)dup2(pdes[1], STDOUT_FILENO);
(void)close(pdes[1]);
if (twoway)
(void)dup2(STDOUT_FILENO, STDIN_FILENO);
} else if (twoway && (pdes[1] != STDIN_FILENO))
(void)dup2(pdes[1], STDIN_FILENO);
} else {
if (pdes[0] != STDIN_FILENO) {
(void)dup2(pdes[0], STDIN_FILENO);
(void)close(pdes[0]);
}
(void)close(pdes[1]);
}
for (p = pidlist; p; p = p->next) {
(void)close(fileno(p->fp));
}
(void)dup2(STDOUT_FILENO,STDERR_FILENO);
execve(_PATH_BSHELL, argv, environ);
_exit(127);
/* NOTREACHED */
}

/* Parent; assume fdopen can't fail. */
if (*type == 'r') {
iop = fdopen(pdes[0], type);
(void)close(pdes[1]);
} else {
iop = fdopen(pdes[1], type);
(void)close(pdes[0]);
}

/* Link into list of file descriptors. */
cur->fp = iop;
cur->pid = pid;
cur->next = pidlist;
pidlist = cur;

return (iop);
}


int SystemCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
char buf[BUFSIZ];
char *cmdstring, *p;
FILE *pipe;

int i, cmdlen, cmdlenavail;
cmdlen = cmdlenavail = BUFSIZ;
p = cmdstring = NULL;
@@ -94,7 +205,9 @@ int SystemCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONS
}
}

pipe = popen(cmdstring, "r");
/*pipe = popen(cmdstring, "r");*/
pipe = dup2popen(cmdstring, "r");
/*Gutted the popen code...*/
if (p != NULL)
free(cmdstring);

0 comments on commit 2672227

Please sign in to comment.
You can’t perform that action at this time.