[41655] trunk/base/src/pextlib1.0/Pextlib.c
toby at macports.org
toby at macports.org
Sat Nov 8 02:50:43 PST 2008
Revision: 41655
http://trac.macports.org/changeset/41655
Author: toby at macports.org
Date: 2008-11-08 02:50:42 -0800 (Sat, 08 Nov 2008)
Log Message:
-----------
SystemCmd:
- fix major leak (circbuf only freed when command exited non-zero)
- fix fd leak
- minor refactoring
Modified Paths:
--------------
trunk/base/src/pextlib1.0/Pextlib.c
Modified: trunk/base/src/pextlib1.0/Pextlib.c
===================================================================
--- trunk/base/src/pextlib1.0/Pextlib.c 2008-11-08 10:27:40 UTC (rev 41654)
+++ trunk/base/src/pextlib1.0/Pextlib.c 2008-11-08 10:50:42 UTC (rev 41655)
@@ -220,17 +220,16 @@
pid_t pid;
Tcl_Obj *errbuf;
Tcl_Obj *tcl_result;
+ int read_failed, status;
- if (objc != 2 && objc != 3) {
- Tcl_WrongNumArgs(interp, 1, objv, "command");
- return TCL_ERROR;
- }
-
- if (objc == 3) {
+ /* usage: system [-notty] command */
+ if (objc == 2) {
+ cmdstring = Tcl_GetString(objv[1]);
+ } else if (objc == 3) {
char *arg = Tcl_GetString(objv[1]);
cmdstring = Tcl_GetString(objv[2]);
- if (!strcmp(arg, "-notty")) {
+ if (strcmp(arg, "-notty") == 0) {
osetsid = 1;
} else {
tcl_result = Tcl_NewStringObj("bad option ", -1);
@@ -239,21 +238,26 @@
return TCL_ERROR;
}
} else {
- cmdstring = Tcl_GetString(objv[1]);
+ Tcl_WrongNumArgs(interp, 1, objv, "command");
+ return TCL_ERROR;
}
- if (pipe(fdset) == -1)
- return TCL_ERROR;
-
/*
* 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) {
+ return TCL_ERROR;
+ }
+
pid = fork();
- if (pid == -1)
+ switch (pid) {
+ case -1: /* error */
return TCL_ERROR;
- if (pid == 0) {
+ break;
+ case 0: /* child */
close(fdset[0]);
+
if ((nullfd = open(_PATH_DEVNULL, O_RDONLY)) == -1)
_exit(1);
dup2(nullfd, STDIN_FILENO);
@@ -271,13 +275,18 @@
args[3] = NULL;
execve("/bin/sh", args, environ);
_exit(1);
+ break;
+ default: /* parent */
+ break;
}
+
close(fdset[1]);
- pdes = fdopen(fdset[0], "r");
/* read from simulated popen() pipe */
+ read_failed = 0;
pos = 0;
bzero(circbuf, sizeof(circbuf));
+ pdes = fdopen(fdset[0], "r");
while ((buf = fgetln(pdes, &linelen)) != NULL) {
char *sbuf;
int slen;
@@ -298,11 +307,8 @@
}
if (sbuf == NULL) {
- for (fline = pos; pos < fline + CBUFSIZ; pos++) {
- if (circbuf[pos % CBUFSIZ].len != 0)
- free(circbuf[pos % CBUFSIZ].line);
- }
- return TCL_ERROR;
+ read_failed = 1;
+ break;
}
memcpy(sbuf, buf, linelen);
@@ -312,25 +318,24 @@
circbuf[pos].line = sbuf;
circbuf[pos].len = slen;
- if (pos++ == CBUFSIZ - 1)
+ if (pos++ == CBUFSIZ - 1) {
pos = 0;
- ret = ui_info(interp, sbuf);
- if (ret != TCL_OK) {
- for (fline = pos; pos < fline + CBUFSIZ; pos++) {
- if (circbuf[pos % CBUFSIZ].len != 0)
- free(circbuf[pos % CBUFSIZ].line);
- }
- return ret;
}
+
+ if (ui_info(interp, sbuf) != TCL_OK) {
+ read_failed = 1;
+ break;
+ }
}
fclose(pdes);
- if (wait(&ret) != pid)
- return TCL_ERROR;
- if (WIFEXITED(ret)) {
- if (WEXITSTATUS(ret) == 0)
- return TCL_OK;
- else {
+ status = TCL_ERROR;
+
+ if (wait(&ret) == pid && WIFEXITED(ret) && !read_failed) {
+ /* Normal exit, and reading from the pipe didn't fail. */
+ if (WEXITSTATUS(ret) == 0) {
+ status = TCL_OK;
+ } else {
/* Copy the contents of the circular buffer to errbuf */
Tcl_Obj* errorCode;
errbuf = Tcl_NewStringObj(NULL, 0);
@@ -344,7 +349,6 @@
/* Re-add previously stripped newline */
Tcl_AppendToObj(errbuf, "\n", 1);
- free(circbuf[pos % CBUFSIZ].line);
}
/* set errorCode [list CHILDSTATUS <pid> <code>] */
@@ -362,10 +366,18 @@
Tcl_AppendToObj(tcl_result, "\nCommand output: ", -1);
Tcl_AppendObjToObj(tcl_result, errbuf);
Tcl_SetObjResult(interp, tcl_result);
- return TCL_ERROR;
}
- } else
- return TCL_ERROR;
+ }
+
+ /* Cleanup. */
+ close(fdset[0]);
+ for (fline = 0; fline < CBUFSIZ; fline++) {
+ if (circbuf[fline].len != 0) {
+ free(circbuf[fline].line);
+ }
+ }
+
+ return status;
}
int SudoCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20081108/27aad727/attachment-0001.html>
More information about the macports-changes
mailing list