summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixPipe.c
diff options
context:
space:
mode:
Diffstat (limited to 'unix/tclUnixPipe.c')
-rw-r--r--unix/tclUnixPipe.c497
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);
}