Revision: 104692 https://trac.macports.org/changeset/104692 Author: raimue@macports.org Date: 2013-03-31 14:43:13 -0700 (Sun, 31 Mar 2013) Log Message: ----------- pextlib1.0/system.c: Add new argument -nodup to system command to avoid redirection of stdin/stdout/stderr. Modified Paths: -------------- branches/new-help-system/base/src/pextlib1.0/system.c Modified: branches/new-help-system/base/src/pextlib1.0/system.c =================================================================== --- branches/new-help-system/base/src/pextlib1.0/system.c 2013-03-31 21:26:08 UTC (rev 104691) +++ branches/new-help-system/base/src/pextlib1.0/system.c 2013-03-31 21:43:13 UTC (rev 104692) @@ -102,7 +102,7 @@ return 1; } -/* usage: system ?-notty? ?-nice value? ?-W path? command */ +/* usage: system ?-notty? ?-nodup? ?-nice value? ?-W path? command */ int SystemCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { char *buf; @@ -117,6 +117,7 @@ int fdset[2], nullfd; int fline, pos, ret; int osetsid = 0; + int odup = 1; /* redirect stdin/stdout/stderr by default */ int oniceval = INT_MAX; /* magic value indicating no change */ const char *path = NULL; pid_t pid; @@ -136,6 +137,8 @@ char *arg = Tcl_GetString(objv[i]); if (strcmp(arg, "-notty") == 0) { osetsid = 1; + } else if (strcmp(arg, "-nodup") == 0) { + odup = 0; } else if (strcmp(arg, "-nice") == 0) { i++; if (Tcl_GetIntFromObj(interp, objv[i], &oniceval) != TCL_OK) { @@ -163,9 +166,11 @@ * Fork a child to run the command, in a popen() like fashion - * popen() itself is not used because stderr is also desired. */ - if (pipe(fdset) != 0) { - Tcl_SetResult(interp, strerror(errno), TCL_STATIC); - return TCL_ERROR; + if (odup) { + if (pipe(fdset) != 0) { + Tcl_SetResult(interp, strerror(errno), TCL_STATIC); + return TCL_ERROR; + } } pid = fork(); @@ -175,13 +180,15 @@ return TCL_ERROR; break; case 0: /* child */ - close(fdset[0]); + if (odup) { + close(fdset[0]); - if ((nullfd = open(_PATH_DEVNULL, O_RDONLY)) == -1) - _exit(1); - dup2(nullfd, STDIN_FILENO); - dup2(fdset[1], STDOUT_FILENO); - dup2(fdset[1], STDERR_FILENO); + if ((nullfd = open(_PATH_DEVNULL, O_RDONLY)) == -1) + _exit(1); + dup2(nullfd, STDIN_FILENO); + dup2(fdset[1], STDOUT_FILENO); + dup2(fdset[1], STDERR_FILENO); + } /* drop the controlling terminal if requested */ if (osetsid) { if (setsid() == -1) @@ -231,58 +238,60 @@ break; } - close(fdset[1]); + if (odup) { + close(fdset[1]); - /* read from simulated popen() pipe */ - read_failed = 0; - pos = 0; - memset(circbuf, 0, sizeof(circbuf)); - pdes = fdopen(fdset[0], "r"); - if (pdes) { - while ((buf = fgetln(pdes, &linelen)) != NULL) { - char *sbuf; - int slen; - - /* - * Allocate enough space to insert a terminating - * '\0' if the line is not terminated with a '\n' - */ - if (buf[linelen - 1] == '\n') - slen = linelen; - else - slen = linelen + 1; - - if (circbuf[pos].len == 0) - sbuf = malloc(slen); - else { - sbuf = realloc(circbuf[pos].line, slen); + /* read from simulated popen() pipe */ + read_failed = 0; + pos = 0; + memset(circbuf, 0, sizeof(circbuf)); + pdes = fdopen(fdset[0], "r"); + if (pdes) { + while ((buf = fgetln(pdes, &linelen)) != NULL) { + char *sbuf; + int slen; + + /* + * Allocate enough space to insert a terminating + * '\0' if the line is not terminated with a '\n' + */ + if (buf[linelen - 1] == '\n') + slen = linelen; + else + slen = linelen + 1; + + if (circbuf[pos].len == 0) + sbuf = malloc(slen); + else { + sbuf = realloc(circbuf[pos].line, slen); + } + + if (sbuf == NULL) { + read_failed = 1; + break; + } + + memcpy(sbuf, buf, linelen); + /* terminate line with '\0',replacing '\n' if it exists */ + sbuf[slen - 1] = '\0'; + + circbuf[pos].line = sbuf; + circbuf[pos].len = slen; + + if (pos++ == CBUFSIZ - 1) { + pos = 0; + } + + if (ui_info(interp, sbuf) != TCL_OK) { + read_failed = 1; + break; + } } - - if (sbuf == NULL) { - read_failed = 1; - break; - } - - memcpy(sbuf, buf, linelen); - /* terminate line with '\0',replacing '\n' if it exists */ - sbuf[slen - 1] = '\0'; - - circbuf[pos].line = sbuf; - circbuf[pos].len = slen; - - if (pos++ == CBUFSIZ - 1) { - pos = 0; - } - - if (ui_info(interp, sbuf) != TCL_OK) { - read_failed = 1; - break; - } + fclose(pdes); + } else { + read_failed = 1; + Tcl_SetResult(interp, strerror(errno), TCL_STATIC); } - fclose(pdes); - } else { - read_failed = 1; - Tcl_SetResult(interp, strerror(errno), TCL_STATIC); } status = TCL_ERROR; @@ -319,11 +328,13 @@ } } - /* Cleanup. */ - close(fdset[0]); - for (fline = 0; fline < CBUFSIZ; fline++) { - if (circbuf[fline].len != 0) { - free(circbuf[fline].line); + if (odup) { + /* Cleanup. */ + close(fdset[0]); + for (fline = 0; fline < CBUFSIZ; fline++) { + if (circbuf[fline].len != 0) { + free(circbuf[fline].line); + } } }