errbuf = Tcl_NewStringObj(NULL, 0); for (fline = pos; pos < fline + CBUFSIZ; pos++) { if (circbuf[pos % CBUFSIZ].len == 0) continue;   Tcl_AppendToObj(errbuf, circbuf[pos % CBUFSIZ].line, circbuf[pos % CBUFSIZ].len);   Tcl_AppendToObj(errbuf, "\n", 1); free(circbuf[pos % CBUFSIZ].line); }
int SystemCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]){	char *buf;	struct linebuf circbuf[CBUFSIZ];	size_t linelen;	char *args[4];	char *cmdstring;	FILE *pdes;	int fdset[2], nullfd;	int fline, pos, ret;	pid_t pid;	Tcl_Obj *errbuf;	Tcl_Obj *tcl_result;#if defined(__APPLE__)	char **environ;	environ = *_NSGetEnviron();#endif	if (objc != 2) {		Tcl_WrongNumArgs(interp, 1, objv, "command");		return TCL_ERROR;	}	cmdstring = Tcl_GetString(objv[1]);	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.	 */	pid = fork();	if (pid == -1)		return TCL_ERROR;	if (pid == 0) {		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);		/* XXX dropping the controlling terminal */		if (setsid() == -1)			_exit(1);		/* XXX ugly string constants */		args[0] = "sh";		args[1] = "-c";		args[2] = cmdstring;		args[3] = NULL;		execve("/bin/sh", args, environ);		_exit(1);	}	close(fdset[1]);	pdes = fdopen(fdset[0], "r");	/* read from simulated popen() pipe */	pos = 0;	bzero(circbuf, sizeof(circbuf));	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) {			for (fline = pos; pos < fline + CBUFSIZ; pos++) {				if (circbuf[pos % CBUFSIZ].len != 0)					free(circbuf[pos % CBUFSIZ].line);			}			return TCL_ERROR;		}		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;		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;		}	}	fclose(pdes);	/* Copy the contents of the circular buffer to errbuf */	errbuf = Tcl_NewStringObj(NULL, 0);	for (fline = pos; pos < fline + CBUFSIZ; pos++) {		if (circbuf[pos % CBUFSIZ].len == 0)			break;		Tcl_AppendToObj(errbuf, circbuf[pos % CBUFSIZ].line, circbuf[pos % CBUFSIZ].len);		free(circbuf[pos % CBUFSIZ].line);	}	if (wait(&ret) != pid)		return TCL_ERROR;	if (WIFEXITED(ret)) {		if (WEXITSTATUS(ret) == 0)			return TCL_OK;		else {			/* set errorCode [list CHILDSTATUS <pid> <code>] */			Tcl_Obj* errorCode = Tcl_NewListObj(0, NULL);			Tcl_ListObjAppendElement(interp, errorCode, Tcl_NewStringObj("CHILDSTATUS", -1));			Tcl_ListObjAppendElement(interp, errorCode, Tcl_NewIntObj(pid));			Tcl_ListObjAppendElement(interp, errorCode, Tcl_NewIntObj(WEXITSTATUS(ret)));			Tcl_SetObjErrorCode(interp, errorCode);			/* set result */			tcl_result = Tcl_NewStringObj("shell command \"", -1);			Tcl_AppendToObj(tcl_result, cmdstring, -1);			Tcl_AppendToObj(tcl_result, "\" returned error ", -1);			Tcl_AppendObjToObj(tcl_result, Tcl_NewIntObj(WEXITSTATUS(ret)));			Tcl_AppendToObj(tcl_result, "\nCommand output: ", -1);			Tcl_AppendObjToObj(tcl_result, errbuf);			Tcl_SetObjResult(interp, tcl_result);			return TCL_ERROR;		}	} else		return TCL_ERROR;}