diff options
Diffstat (limited to 'unix/tclUnixPipe.c')
| -rw-r--r-- | unix/tclUnixPipe.c | 497 |
1 files changed, 192 insertions, 305 deletions
diff --git a/unix/tclUnixPipe.c b/unix/tclUnixPipe.c index 70a5d5d..d0a5e53 100644 --- a/unix/tclUnixPipe.c +++ b/unix/tclUnixPipe.c @@ -4,8 +4,8 @@ * This file implements the UNIX-specific exec pipeline functions, the * "pipe" channel driver, and the "pid" Tcl command. * - * Copyright © 1991-1994 The Regents of the University of California. - * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright (c) 1991-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -13,19 +13,18 @@ #include "tclInt.h" -#ifdef HAVE_POSIX_SPAWNP -# if defined(HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2) \ - && defined(HAVE_POSIX_SPAWNATTR_SETFLAGS) \ - && !defined(HAVE_VFORK) -# include <unistd.h> -# include <spawn.h> -# else -# undef HAVE_POSIX_SPAWNP -# endif +#ifdef USE_VFORK +#define fork vfork #endif -#ifdef HAVE_VFORK -#define fork vfork +/* + * Fallback temporary file location the temporary file generation code. Can be + * overridden at compile time for when it is known that temp files can't be + * written to /tmp (hello, iOS!). + */ + +#ifndef TCL_TEMPORARY_FILE_DIRECTORY +#define TCL_TEMPORARY_FILE_DIRECTORY "/tmp" #endif /* @@ -41,7 +40,7 @@ * This structure describes per-instance state of a pipe based channel. */ -typedef struct { +typedef struct PipeState { Tcl_Channel channel; /* Channel associated with this file. */ TclFile inFile; /* Output from pipe. */ TclFile outFile; /* Input to pipe. */ @@ -59,16 +58,17 @@ typedef struct { * Declarations for local functions defined in this file: */ -static int PipeBlockModeProc(void *instanceData, int mode); -static int PipeClose2Proc(void *instanceData, - Tcl_Interp *interp, int flags); -static int PipeGetHandleProc(void *instanceData, - int direction, void **handlePtr); -static int PipeInputProc(void *instanceData, char *buf, +static const char * DefaultTempDir(void); +static int PipeBlockModeProc(ClientData instanceData, int mode); +static int PipeCloseProc(ClientData instanceData, + Tcl_Interp *interp); +static int PipeGetHandleProc(ClientData instanceData, + int direction, ClientData *handlePtr); +static int PipeInputProc(ClientData instanceData, char *buf, int toRead, int *errorCode); -static int PipeOutputProc(void *instanceData, +static int PipeOutputProc(ClientData instanceData, const char *buf, int toWrite, int *errorCode); -static void PipeWatchProc(void *instanceData, int mask); +static void PipeWatchProc(ClientData instanceData, int mask); static void RestoreSignals(void); static int SetupStdFile(TclFile file, int type); @@ -77,10 +77,10 @@ static int SetupStdFile(TclFile file, int type); * I/O: */ -static const Tcl_ChannelType pipeChannelType = { +static Tcl_ChannelType pipeChannelType = { "pipe", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - TCL_CLOSE2PROC, /* Close proc. */ + PipeCloseProc, /* Close proc. */ PipeInputProc, /* Input proc. */ PipeOutputProc, /* Output proc. */ NULL, /* Seek proc. */ @@ -88,7 +88,7 @@ static const Tcl_ChannelType pipeChannelType = { NULL, /* Get option proc. */ PipeWatchProc, /* Initialize notifier. */ PipeGetHandleProc, /* Get OS handles out of channel. */ - PipeClose2Proc, /* close2proc. */ + NULL, /* close2proc. */ PipeBlockModeProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ @@ -118,13 +118,14 @@ TclpMakeFile( Tcl_Channel channel, /* Channel to get file from. */ int direction) /* Either TCL_READABLE or TCL_WRITABLE. */ { - void *data; + ClientData data; - if (Tcl_GetChannelHandle(channel, direction, &data) != TCL_OK) { - return NULL; + if (Tcl_GetChannelHandle(channel, direction, + (ClientData *) &data) == TCL_OK) { + return MakeFile(PTR2INT(data)); + } else { + return (TclFile) NULL; } - - return MakeFile(PTR2INT(data)); } /* @@ -152,7 +153,7 @@ TclpOpenFile( const char *native; Tcl_DString ds; - native = Tcl_UtfToExternalDString(NULL, fname, TCL_INDEX_NONE, &ds); + native = Tcl_UtfToExternalDString(NULL, fname, -1, &ds); fd = TclOSopen(native, mode, 0666); /* INTL: Native. */ Tcl_DStringFree(&ds); if (fd != -1) { @@ -164,7 +165,7 @@ TclpOpenFile( */ if ((mode & O_WRONLY) && !(mode & O_APPEND)) { - TclOSseek(fd, 0, SEEK_END); + TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_END); } /* @@ -199,24 +200,36 @@ TclFile TclpCreateTempFile( const char *contents) /* String to write into temp file, or NULL. */ { - int fd = TclUnixOpenTemporaryFile(NULL, NULL, NULL, NULL); + char fileName[L_tmpnam + 9]; + const char *native; + Tcl_DString dstring; + int fd; + + /* + * We should also check against making more then TMP_MAX of these. + */ + strcpy(fileName, DefaultTempDir()); /* INTL: Native. */ + if (fileName[strlen(fileName) - 1] != '/') { + strcat(fileName, "/"); /* INTL: Native. */ + } + strcat(fileName, "tclXXXXXX"); + fd = mkstemp(fileName); /* INTL: Native. */ if (fd == -1) { return NULL; } fcntl(fd, F_SETFD, FD_CLOEXEC); - if (contents != NULL) { - Tcl_DString dstring; - char *native; + unlink(fileName); /* INTL: Native. */ - native = Tcl_UtfToExternalDString(NULL, contents, TCL_INDEX_NONE, &dstring); + if (contents != NULL) { + native = Tcl_UtfToExternalDString(NULL, contents, -1, &dstring); if (write(fd, native, Tcl_DStringLength(&dstring)) == -1) { close(fd); Tcl_DStringFree(&dstring); return NULL; } Tcl_DStringFree(&dstring); - TclOSseek(fd, 0, SEEK_SET); + TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_SET); } return MakeFile(fd); } @@ -240,56 +253,67 @@ TclpCreateTempFile( Tcl_Obj * TclpTempFileName(void) { - Tcl_Obj *retVal, *nameObj; + char fileName[L_tmpnam + 9]; + Tcl_Obj *result = NULL; int fd; - TclNewObj(nameObj); - Tcl_IncrRefCount(nameObj); - fd = TclUnixOpenTemporaryFile(NULL, NULL, NULL, nameObj); + /* + * We should also check against making more then TMP_MAX of these. + */ + + strcpy(fileName, DefaultTempDir()); /* INTL: Native. */ + if (fileName[strlen(fileName) - 1] != '/') { + strcat(fileName, "/"); /* INTL: Native. */ + } + strcat(fileName, "tclXXXXXX"); + fd = mkstemp(fileName); /* INTL: Native. */ if (fd == -1) { - Tcl_DecrRefCount(nameObj); return NULL; } - fcntl(fd, F_SETFD, FD_CLOEXEC); - TclpObjDeleteFile(nameObj); + unlink(fileName); /* INTL: Native. */ + + result = TclpNativeToNormalized((ClientData) fileName); close(fd); - retVal = Tcl_DuplicateObj(nameObj); - Tcl_DecrRefCount(nameObj); - return retVal; + return result; } /* - *---------------------------------------------------------------------------- - * - * TclpTempFileNameForLibrary -- - * - * Constructs a file name in the native file system where a dynamically - * loaded library may be placed. + *---------------------------------------------------------------------- * - * Results: - * Returns the constructed file name. If an error occurs, returns NULL - * and leaves an error message in the interpreter result. + * DefaultTempDir -- * - * On Unix, it works to load a shared object from a file of any name, so this - * function is merely a thin wrapper around TclpTempFileName(). + * Helper that does *part* of what tempnam() does. * - *---------------------------------------------------------------------------- + *---------------------------------------------------------------------- */ -Tcl_Obj * -TclpTempFileNameForLibrary( - Tcl_Interp *interp, /* Tcl interpreter. */ - TCL_UNUSED(Tcl_Obj *) /*path*/) +static const char * +DefaultTempDir(void) { - Tcl_Obj *retval = TclpTempFileName(); + const char *dir; + struct stat buf; + + dir = getenv("TMPDIR"); + if (dir && dir[0] && stat(dir, &buf) == 0 && S_ISDIR(buf.st_mode) + && access(dir, W_OK)) { + return dir; + } - if (retval == NULL) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "couldn't create temporary file: %s", - Tcl_PosixError(interp))); +#ifdef P_tmpdir + dir = P_tmpdir; + if (stat(dir, &buf) == 0 && S_ISDIR(buf.st_mode) && access(dir, W_OK)) { + return dir; } - return retval; +#endif + + /* + * Assume that the default location ("/tmp" if not overridden) is always + * an existing writable directory; we've no recovery mechanism if it + * isn't. + */ + + return TCL_TEMPORARY_FILE_DIRECTORY; } /* @@ -386,6 +410,7 @@ TclpCloseFile( *--------------------------------------------------------------------------- */ + /* ARGSUSED */ int TclpCreateProcess( Tcl_Interp *interp, /* Interpreter in which to leave errors that @@ -404,12 +429,12 @@ TclpCreateProcess( * receive no standard input. */ TclFile outputFile, /* If non-NULL, gives the file that receives * output from the child process. If - * outputFile file is not writable or is + * outputFile file is not writeable or is * NULL, output from the child will be * discarded. */ TclFile errorFile, /* If non-NULL, gives the file that receives * errors from the child process. If errorFile - * file is not writable or is NULL, errors + * file is not writeable or is NULL, errors * from the child will be discarded. errorFile * may be the same as outputFile. */ Tcl_Pid *pidPtr) /* If this function is successful, pidPtr is @@ -421,12 +446,7 @@ TclpCreateProcess( char errSpace[200 + TCL_INTEGER_SPACE]; Tcl_DString *dsArray; char **newArgv; - int pid; - int i; -#if defined(HAVE_POSIX_SPAWNP) - int childErrno; - static int use_spawn = -1; -#endif + int pid, i; errPipeIn = NULL; errPipeOut = NULL; @@ -438,8 +458,8 @@ TclpCreateProcess( */ if (TclpCreatePipe(&errPipeIn, &errPipeOut) == 0) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "couldn't create pipe: %s", Tcl_PosixError(interp))); + Tcl_AppendResult(interp, "couldn't create pipe: ", + Tcl_PosixError(interp), NULL); goto error; } @@ -448,99 +468,34 @@ TclpCreateProcess( * deallocated later */ - dsArray = (Tcl_DString *)TclStackAlloc(interp, argc * sizeof(Tcl_DString)); - newArgv = (char **)TclStackAlloc(interp, (argc+1) * sizeof(char *)); + dsArray = (Tcl_DString *) + TclStackAlloc(interp, argc * sizeof(Tcl_DString)); + newArgv = (char **) TclStackAlloc(interp, (argc+1) * sizeof(char *)); newArgv[argc] = NULL; for (i = 0; i < argc; i++) { - newArgv[i] = Tcl_UtfToExternalDString(NULL, argv[i], TCL_INDEX_NONE, &dsArray[i]); + newArgv[i] = Tcl_UtfToExternalDString(NULL, argv[i], -1, &dsArray[i]); } -#if defined(HAVE_VFORK) || defined(HAVE_POSIX_SPAWNP) +#ifdef USE_VFORK /* * After vfork(), do not call code in the child that changes global state, * because it is using the parent's memory space at that point and writes - * might corrupt the parent: so ensure standard channels are initialized - * in the parent, otherwise SetupStdFile() might initialize them in the - * child. + * might corrupt the parent: so ensure standard channels are initialized in + * the parent, otherwise SetupStdFile() might initialize them in the child. */ if (!inputFile) { Tcl_GetStdChannel(TCL_STDIN); } if (!outputFile) { - Tcl_GetStdChannel(TCL_STDOUT); + Tcl_GetStdChannel(TCL_STDOUT); } if (!errorFile) { - Tcl_GetStdChannel(TCL_STDERR); + Tcl_GetStdChannel(TCL_STDERR); } #endif -#ifdef HAVE_POSIX_SPAWNP -#ifdef _CS_GNU_LIBC_VERSION - if (use_spawn < 0) { - char conf[32], *p; - int major = 0, minor = 0; - - use_spawn = 0; - memset(conf, 0, sizeof(conf)); - confstr(_CS_GNU_LIBC_VERSION, conf, sizeof(conf)); - p = strchr(conf, ' '); /* skip "glibc" */ - if (p != NULL) { - ++p; - if (sscanf(p, "%d.%d", &major, &minor) > 1) { - if ((major > 2) || ((major == 2) && (minor >= 24))) { - use_spawn = 1; - } - } - } - } -#endif - status = -1; - if (use_spawn) { - posix_spawn_file_actions_t actions; - posix_spawnattr_t attr; - sigset_t sigs; - - posix_spawn_file_actions_init(&actions); - posix_spawnattr_init(&attr); - sigfillset(&sigs); - sigdelset(&sigs, SIGKILL); - sigdelset(&sigs, SIGSTOP); - - posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF -#ifdef POSIX_SPAWN_USEVFORK - | POSIX_SPAWN_USEVFORK -#endif - ); - posix_spawnattr_setsigdefault(&attr, &sigs); - - posix_spawn_file_actions_adddup2(&actions, GetFd(inputFile), 0); - posix_spawn_file_actions_adddup2(&actions, GetFd(outputFile), 1); - posix_spawn_file_actions_adddup2(&actions, GetFd(errorFile), 2); - - status = posix_spawnp(&pid, newArgv[0], &actions, &attr, - newArgv, environ); - childErrno = errno; - posix_spawn_file_actions_destroy(&actions); - posix_spawnattr_destroy(&attr); - - /* - * Fork semantics: - * - pid == 0: child process - * - pid == -1: error - * - pid > 0: parent process - * - * Mimic fork semantics to minimize changes below, - * but retry with fork() as last ressort. - */ - } - if (status != 0) { - pid = fork(); - childErrno = errno; - } -#else pid = fork(); -#endif if (pid == 0) { size_t len; int joinThisError = errorFile && (errorFile == outputFile); @@ -556,8 +511,8 @@ TclpCreateProcess( || (!joinThisError && !SetupStdFile(errorFile, TCL_STDERR)) || (joinThisError && ((dup2(1,2) == -1) || (fcntl(2, F_SETFD, 0) != 0)))) { - snprintf(errSpace, sizeof(errSpace), - "%dforked process couldn't set up input/output", errno); + sprintf(errSpace, + "%dforked process couldn't set up input/output: ", errno); len = strlen(errSpace); if (len != (size_t) write(fd, errSpace, len)) { Tcl_Panic("TclpCreateProcess: unable to write to errPipeOut"); @@ -571,11 +526,11 @@ TclpCreateProcess( RestoreSignals(); execvp(newArgv[0], newArgv); /* INTL: Native. */ - snprintf(errSpace, sizeof(errSpace), "%dcouldn't execute \"%.150s\"", errno, argv[0]); + sprintf(errSpace, "%dcouldn't execute \"%.150s\": ", errno, argv[0]); len = strlen(errSpace); - if (len != (size_t) write(fd, errSpace, len)) { + if (len != (size_t) write(fd, errSpace, len)) { Tcl_Panic("TclpCreateProcess: unable to write to errPipeOut"); - } + } _exit(1); } @@ -590,11 +545,8 @@ TclpCreateProcess( TclStackFree(interp, dsArray); if (pid == -1) { -#ifdef HAVE_POSIX_SPAWNP - errno = childErrno; -#endif - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "couldn't fork child process: %s", Tcl_PosixError(interp))); + Tcl_AppendResult(interp, "couldn't fork child process: ", + Tcl_PosixError(interp), NULL); goto error; } @@ -608,14 +560,12 @@ TclpCreateProcess( errPipeOut = NULL; fd = GetFd(errPipeIn); - count = read(fd, errSpace, sizeof(errSpace) - 1); + count = read(fd, errSpace, (size_t) (sizeof(errSpace) - 1)); if (count > 0) { char *end; - errSpace[count] = 0; errno = strtol(errSpace, &end, 10); - Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s: %s", - end, Tcl_PosixError(interp))); + Tcl_AppendResult(interp, end, Tcl_PosixError(interp), NULL); goto error; } @@ -632,7 +582,7 @@ TclpCreateProcess( * here, since this is the error case. [Bug: 6148] */ - Tcl_WaitPid((Tcl_Pid)INT2PTR(pid), &status, 0); + Tcl_WaitPid((Tcl_Pid) INT2PTR(pid), &status, 0); } if (errPipeIn) { @@ -828,7 +778,7 @@ TclpCreateCommandChannel( { char channelName[16 + TCL_INTEGER_SPACE]; int channelId; - PipeState *statePtr = (PipeState *)ckalloc(sizeof(PipeState)); + PipeState *statePtr = (PipeState *) ckalloc((unsigned) sizeof(PipeState)); int mode; statePtr->inFile = readFile; @@ -866,58 +816,15 @@ TclpCreateCommandChannel( * natural to use "pipe%d". */ - snprintf(channelName, sizeof(channelName), "file%d", channelId); + sprintf(channelName, "file%d", channelId); statePtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName, - statePtr, mode); + (ClientData) statePtr, mode); return statePtr->channel; } /* *---------------------------------------------------------------------- * - * Tcl_CreatePipe -- - * - * System dependent interface to create a pipe for the [chan pipe] - * command. Stolen from TclX. - * - * Results: - * TCL_OK or TCL_ERROR. - * - * Side effects: - * Registers two channels. - * - *---------------------------------------------------------------------- - */ - -int -Tcl_CreatePipe( - Tcl_Interp *interp, /* Errors returned in result. */ - Tcl_Channel *rchan, /* Returned read side. */ - Tcl_Channel *wchan, /* Returned write side. */ - TCL_UNUSED(int) /*flags*/) /* Reserved for future use. */ -{ - int fileNums[2]; - - if (pipe(fileNums) < 0) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf("pipe creation failed: %s", - Tcl_PosixError(interp))); - return TCL_ERROR; - } - - fcntl(fileNums[0], F_SETFD, FD_CLOEXEC); - fcntl(fileNums[1], F_SETFD, FD_CLOEXEC); - - *rchan = Tcl_MakeFileChannel(INT2PTR(fileNums[0]), TCL_READABLE); - Tcl_RegisterChannel(interp, *rchan); - *wchan = Tcl_MakeFileChannel(INT2PTR(fileNums[1]), TCL_WRITABLE); - Tcl_RegisterChannel(interp, *wchan); - - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * * TclGetAndDetachPids -- * * This function is invoked in the generic implementation of a @@ -941,8 +848,8 @@ TclGetAndDetachPids( { PipeState *pipePtr; const Tcl_ChannelType *chanTypePtr; - Tcl_Obj *pidsObj; int i; + char buf[TCL_INTEGER_SPACE]; /* * Punt if the channel is not a command channel. @@ -953,16 +860,14 @@ TclGetAndDetachPids( return; } - pipePtr = (PipeState *)Tcl_GetChannelInstanceData(chan); - TclNewObj(pidsObj); + pipePtr = (PipeState *) Tcl_GetChannelInstanceData(chan); for (i = 0; i < pipePtr->numPids; i++) { - Tcl_ListObjAppendElement(NULL, pidsObj, Tcl_NewWideIntObj( - PTR2INT(pipePtr->pidPtr[i]))); - Tcl_DetachPids(1, &pipePtr->pidPtr[i]); + TclFormatInt(buf, (long) TclpGetPid(pipePtr->pidPtr[i])); + Tcl_AppendElement(interp, buf); + Tcl_DetachPids(1, &(pipePtr->pidPtr[i])); } - Tcl_SetObjResult(interp, pidsObj); if (pipePtr->numPids > 0) { - ckfree(pipePtr->pidPtr); + ckfree((char *) pipePtr->pidPtr); pipePtr->numPids = 0; } } @@ -984,22 +889,25 @@ TclGetAndDetachPids( *---------------------------------------------------------------------- */ + /* ARGSUSED */ static int PipeBlockModeProc( - void *instanceData, /* Pipe state. */ + ClientData instanceData, /* Pipe state. */ int mode) /* The mode to set. Can be one of * TCL_MODE_BLOCKING or * TCL_MODE_NONBLOCKING. */ { - PipeState *psPtr = (PipeState *)instanceData; + PipeState *psPtr = instanceData; - if (psPtr->inFile - && TclUnixSetBlockingMode(GetFd(psPtr->inFile), mode) < 0) { - return errno; + if (psPtr->inFile) { + if (TclUnixSetBlockingMode(GetFd(psPtr->inFile), mode) < 0) { + return errno; + } } - if (psPtr->outFile - && TclUnixSetBlockingMode(GetFd(psPtr->outFile), mode) < 0) { - return errno; + if (psPtr->outFile) { + if (TclUnixSetBlockingMode(GetFd(psPtr->outFile), mode) < 0) { + return errno; + } } psPtr->isNonBlocking = (mode == TCL_MODE_NONBLOCKING); @@ -1010,10 +918,11 @@ PipeBlockModeProc( /* *---------------------------------------------------------------------- * - * PipeClose2Proc + * PipeCloseProc -- * * This function is invoked by the generic IO level to perform - * pipeline-type-specific half or full-close. + * channel-type-specific cleanup when a command pipeline channel is + * closed. * * Results: * 0 on success, errno otherwise. @@ -1024,43 +933,30 @@ PipeBlockModeProc( *---------------------------------------------------------------------- */ + /* ARGSUSED */ static int -PipeClose2Proc( - void *instanceData, /* The pipe to close. */ - Tcl_Interp *interp, /* For error reporting. */ - int flags) /* Flags that indicate which side to close. */ +PipeCloseProc( + ClientData instanceData, /* The pipe to close. */ + Tcl_Interp *interp) /* For error reporting. */ { - PipeState *pipePtr = (PipeState *)instanceData; + PipeState *pipePtr; Tcl_Channel errChan; int errorCode, result; errorCode = 0; result = 0; - - if (((!flags) || (flags & TCL_CLOSE_READ)) && (pipePtr->inFile != NULL)) { + pipePtr = (PipeState *) instanceData; + if (pipePtr->inFile) { if (TclpCloseFile(pipePtr->inFile) < 0) { errorCode = errno; - } else { - pipePtr->inFile = NULL; } } - if (((!flags) || (flags & TCL_CLOSE_WRITE)) && (pipePtr->outFile != NULL) - && (errorCode == 0)) { - if (TclpCloseFile(pipePtr->outFile) < 0) { + if (pipePtr->outFile) { + if ((TclpCloseFile(pipePtr->outFile) < 0) && (errorCode == 0)) { errorCode = errno; - } else { - pipePtr->outFile = NULL; } } - /* - * If half-closing, stop here. - */ - - if (flags) { - return errorCode; - } - if (pipePtr->isNonBlocking || TclInExit()) { /* * If the channel is non-blocking or Tcl is being cleaned up, just @@ -1082,8 +978,7 @@ PipeClose2Proc( if (pipePtr->errorFile) { errChan = Tcl_MakeFileChannel( - INT2PTR(GetFd(pipePtr->errorFile)), - TCL_READABLE); + (ClientData) INT2PTR(GetFd(pipePtr->errorFile)), TCL_READABLE); } else { errChan = NULL; } @@ -1092,9 +987,9 @@ PipeClose2Proc( } if (pipePtr->numPids != 0) { - ckfree(pipePtr->pidPtr); + ckfree((char *) pipePtr->pidPtr); } - ckfree(pipePtr); + ckfree((char *) pipePtr); if (errorCode == 0) { return result; } @@ -1121,13 +1016,13 @@ PipeClose2Proc( static int PipeInputProc( - void *instanceData, /* Pipe state. */ + ClientData instanceData, /* Pipe state. */ char *buf, /* Where to store data read. */ int toRead, /* How much space is available in the * buffer? */ int *errorCodePtr) /* Where to store error code. */ { - PipeState *psPtr = (PipeState *)instanceData; + PipeState *psPtr = (PipeState *) instanceData; int bytesRead; /* How many bytes were actually read from the * input device? */ @@ -1142,14 +1037,15 @@ PipeInputProc( */ do { - bytesRead = read(GetFd(psPtr->inFile), buf, toRead); + bytesRead = read(GetFd(psPtr->inFile), buf, (size_t) toRead); } while ((bytesRead < 0) && (errno == EINTR)); if (bytesRead < 0) { *errorCodePtr = errno; return -1; + } else { + return bytesRead; } - return bytesRead; } /* @@ -1172,12 +1068,12 @@ PipeInputProc( static int PipeOutputProc( - void *instanceData, /* Pipe state. */ + ClientData instanceData, /* Pipe state. */ const char *buf, /* The data buffer. */ int toWrite, /* How many bytes to write? */ int *errorCodePtr) /* Where to store error code. */ { - PipeState *psPtr = (PipeState *)instanceData; + PipeState *psPtr = (PipeState *) instanceData; int written; *errorCodePtr = 0; @@ -1188,14 +1084,15 @@ PipeOutputProc( */ do { - written = write(GetFd(psPtr->outFile), buf, toWrite); + written = write(GetFd(psPtr->outFile), buf, (size_t) toWrite); } while ((written < 0) && (errno == EINTR)); if (written < 0) { *errorCodePtr = errno; return -1; + } else { + return written; } - return written; } /* @@ -1215,35 +1112,22 @@ PipeOutputProc( *---------------------------------------------------------------------- */ -/* - * Bug ad5a57f2f271: Tcl_NotifyChannel is not a Tcl_FileProc, - * so do not pass it to directly to Tcl_CreateFileHandler. - * Instead, pass a wrapper which is a Tcl_FileProc. - */ -static void -PipeWatchNotifyChannelWrapper( - void *clientData, - int mask) -{ - Tcl_Channel channel = (Tcl_Channel)clientData; - Tcl_NotifyChannel(channel, mask); -} - static void PipeWatchProc( - void *instanceData, /* The pipe state. */ + ClientData instanceData, /* The pipe state. */ int mask) /* Events of interest; an OR-ed combination of * TCL_READABLE, TCL_WRITABLE and * TCL_EXCEPTION. */ { - PipeState *psPtr = (PipeState *)instanceData; + PipeState *psPtr = (PipeState *) instanceData; int newmask; if (psPtr->inFile) { newmask = mask & (TCL_READABLE | TCL_EXCEPTION); if (newmask) { - Tcl_CreateFileHandler(GetFd(psPtr->inFile), newmask, - PipeWatchNotifyChannelWrapper, psPtr->channel); + Tcl_CreateFileHandler(GetFd(psPtr->inFile), mask, + (Tcl_FileProc *) Tcl_NotifyChannel, + (ClientData) psPtr->channel); } else { Tcl_DeleteFileHandler(GetFd(psPtr->inFile)); } @@ -1251,8 +1135,9 @@ PipeWatchProc( if (psPtr->outFile) { newmask = mask & (TCL_WRITABLE | TCL_EXCEPTION); if (newmask) { - Tcl_CreateFileHandler(GetFd(psPtr->outFile), newmask, - PipeWatchNotifyChannelWrapper, psPtr->channel); + Tcl_CreateFileHandler(GetFd(psPtr->outFile), mask, + (Tcl_FileProc *) Tcl_NotifyChannel, + (ClientData) psPtr->channel); } else { Tcl_DeleteFileHandler(GetFd(psPtr->outFile)); } @@ -1279,18 +1164,18 @@ PipeWatchProc( static int PipeGetHandleProc( - void *instanceData, /* The pipe state. */ + ClientData instanceData, /* The pipe state. */ int direction, /* TCL_READABLE or TCL_WRITABLE */ - void **handlePtr) /* Where to store the handle. */ + ClientData *handlePtr) /* Where to store the handle. */ { - PipeState *psPtr = (PipeState *)instanceData; + PipeState *psPtr = (PipeState *) instanceData; if (direction == TCL_READABLE && psPtr->inFile) { - *handlePtr = INT2PTR(GetFd(psPtr->inFile)); + *handlePtr = (ClientData) INT2PTR(GetFd(psPtr->inFile)); return TCL_OK; } if (direction == TCL_WRITABLE && psPtr->outFile) { - *handlePtr = INT2PTR(GetFd(psPtr->outFile)); + *handlePtr = (ClientData) INT2PTR(GetFd(psPtr->outFile)); return TCL_OK; } return TCL_ERROR; @@ -1346,35 +1231,37 @@ Tcl_WaitPid( *---------------------------------------------------------------------- */ + /* ARGSUSED */ int Tcl_PidObjCmd( - TCL_UNUSED(void *), + ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const *objv) /* Argument strings. */ { - Tcl_Channel chan; - PipeState *pipePtr; - int i; - Tcl_Obj *resultPtr; - if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?channelId?"); return TCL_ERROR; } if (objc == 1) { - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(getpid())); + Tcl_SetObjResult(interp, Tcl_NewLongObj((long) getpid())); } else { /* * Get the channel and make sure that it refers to a pipe. */ + Tcl_Channel chan; + const Tcl_ChannelType *chanTypePtr; + PipeState *pipePtr; + int i; + Tcl_Obj *resultPtr, *longObjPtr; chan = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), NULL); - if (chan == NULL) { + if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } - if (Tcl_GetChannelType(chan) != &pipeChannelType) { + chanTypePtr = Tcl_GetChannelType(chan); + if (chanTypePtr != &pipeChannelType) { return TCL_OK; } @@ -1382,11 +1269,11 @@ Tcl_PidObjCmd( * Extract the process IDs from the pipe structure. */ - pipePtr = (PipeState *)Tcl_GetChannelInstanceData(chan); - TclNewObj(resultPtr); + pipePtr = (PipeState *) Tcl_GetChannelInstanceData(chan); + resultPtr = Tcl_NewObj(); for (i = 0; i < pipePtr->numPids; i++) { - Tcl_ListObjAppendElement(NULL, resultPtr, - Tcl_NewWideIntObj(PTR2INT(TclpGetPid(pipePtr->pidPtr[i])))); + longObjPtr = Tcl_NewLongObj((long) TclpGetPid(pipePtr->pidPtr[i])); + Tcl_ListObjAppendElement(NULL, resultPtr, longObjPtr); } Tcl_SetObjResult(interp, resultPtr); } |
