⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclunixpipe.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 3 页
字号:
    if (psPtr->inFile) {        fd = GetFd(psPtr->inFile);        curStatus = fcntl(fd, F_GETFL);        if (mode == TCL_MODE_BLOCKING) {            curStatus &= (~(O_NONBLOCK));        } else {            curStatus |= O_NONBLOCK;        }        if (fcntl(fd, F_SETFL, curStatus) < 0) {            return errno;        }    }    if (psPtr->outFile) {        fd = GetFd(psPtr->outFile);        curStatus = fcntl(fd, F_GETFL);        if (mode == TCL_MODE_BLOCKING) {            curStatus &= (~(O_NONBLOCK));        } else {            curStatus |= O_NONBLOCK;        }        if (fcntl(fd, F_SETFL, curStatus) < 0) {            return errno;        }    }#endif	/* !FIONBIO */#ifdef	USE_FIONBIO    if (psPtr->inFile) {        fd = GetFd(psPtr->inFile);        if (mode == TCL_MODE_BLOCKING) {            curStatus = 0;        } else {            curStatus = 1;        }        if (ioctl(fd, (int) FIONBIO, &curStatus) < 0) {            return errno;        }    }    if (psPtr->outFile != NULL) {        fd = GetFd(psPtr->outFile);        if (mode == TCL_MODE_BLOCKING) {            curStatus = 0;        } else {            curStatus = 1;        }        if (ioctl(fd, (int) FIONBIO,  &curStatus) < 0) {            return errno;        }    }#endif	/* USE_FIONBIO */    psPtr->isNonBlocking = (mode == TCL_MODE_NONBLOCKING);    return 0;}/* *---------------------------------------------------------------------- * * PipeCloseProc -- * *	This procedure is invoked by the generic IO level to perform *	channel-type-specific cleanup when a command pipeline channel *	is closed. * * Results: *	0 on success, errno otherwise. * * Side effects: *	Closes the command pipeline channel. * *---------------------------------------------------------------------- */	/* ARGSUSED */static intPipeCloseProc(instanceData, interp)    ClientData instanceData;	/* The pipe to close. */    Tcl_Interp *interp;		/* For error reporting. */{    PipeState *pipePtr;    Tcl_Channel errChan;    int errorCode, result;    errorCode = 0;    result = 0;    pipePtr = (PipeState *) instanceData;    if (pipePtr->inFile) {	if (TclpCloseFile(pipePtr->inFile) < 0) {	    errorCode = errno;	}    }    if (pipePtr->outFile) {	if ((TclpCloseFile(pipePtr->outFile) < 0) && (errorCode == 0)) {	    errorCode = errno;	}    }    if (pipePtr->isNonBlocking || TclInExit()) {    	/*         * If the channel is non-blocking or Tcl is being cleaned up, just         * detach the children PIDs, reap them (important if we are in a         * dynamic load module), and discard the errorFile.         */                Tcl_DetachPids(pipePtr->numPids, pipePtr->pidPtr);        Tcl_ReapDetachedProcs();        if (pipePtr->errorFile) {	    TclpCloseFile(pipePtr->errorFile);        }    } else {        	/*         * Wrap the error file into a channel and give it to the cleanup         * routine.         */        if (pipePtr->errorFile) {	    errChan = Tcl_MakeFileChannel(		(ClientData) GetFd(pipePtr->errorFile), TCL_READABLE);        } else {            errChan = NULL;        }        result = TclCleanupChildren(interp, pipePtr->numPids, pipePtr->pidPtr,                errChan);    }    if (pipePtr->numPids != 0) {        ckfree((char *) pipePtr->pidPtr);    }    ckfree((char *) pipePtr);    if (errorCode == 0) {        return result;    }    return errorCode;}/* *---------------------------------------------------------------------- * * PipeInputProc -- * *	This procedure is invoked from the generic IO level to read *	input from a command pipeline based channel. * * Results: *	The number of bytes read is returned or -1 on error. An output *	argument contains a POSIX error code if an error occurs, or zero. * * Side effects: *	Reads input from the input device of the channel. * *---------------------------------------------------------------------- */static intPipeInputProc(instanceData, buf, toRead, errorCodePtr)    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;    int bytesRead;			/* How many bytes were actually                                         * read from the input device? */    *errorCodePtr = 0;        /*     * Assume there is always enough input available. This will block     * appropriately, and read will unblock as soon as a short read is     * possible, if the channel is in blocking mode. If the channel is     * nonblocking, the read will never block.     * Some OSes can throw an interrupt error, for which we should     * immediately retry. [Bug #415131]     */    do {	bytesRead = read (GetFd(psPtr->inFile), buf, (size_t) toRead);    } while ((bytesRead < 0) && (errno == EINTR));    if (bytesRead < 0) {	*errorCodePtr = errno;	return -1;    } else {	return bytesRead;    }}/* *---------------------------------------------------------------------- * * PipeOutputProc-- * *	This procedure is invoked from the generic IO level to write *	output to a command pipeline based channel. * * Results: *	The number of bytes written is returned or -1 on error. An *	output argument	contains a POSIX error code if an error occurred, *	or zero. * * Side effects: *	Writes output on the output device of the channel. * *---------------------------------------------------------------------- */static intPipeOutputProc(instanceData, buf, toWrite, errorCodePtr)    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;    int written;    *errorCodePtr = 0;    /*     * Some OSes can throw an interrupt error, for which we should     * immediately retry. [Bug #415131]     */    do {	written = write(GetFd(psPtr->outFile), buf, (size_t) toWrite);    } while ((written < 0) && (errno == EINTR));    if (written < 0) {	*errorCodePtr = errno;	return -1;    } else {	return written;    }}/* *---------------------------------------------------------------------- * * PipeWatchProc -- * *	Initialize the notifier to watch the fds from this channel. * * Results: *	None. * * Side effects: *	Sets up the notifier so that a future event on the channel will *	be seen by Tcl. * *---------------------------------------------------------------------- */static voidPipeWatchProc(instanceData, mask)    ClientData instanceData;		/* The pipe state. */    int mask;				/* Events of interest; an OR-ed                                         * combination of TCL_READABLE,                                         * TCL_WRITABEL and TCL_EXCEPTION. */{    PipeState *psPtr = (PipeState *) instanceData;    int newmask;    if (psPtr->inFile) {	newmask = mask & (TCL_READABLE | TCL_EXCEPTION);	if (newmask) {	    Tcl_CreateFileHandler(GetFd(psPtr->inFile), mask,		    (Tcl_FileProc *) Tcl_NotifyChannel,		    (ClientData) psPtr->channel);	} else {	    Tcl_DeleteFileHandler(GetFd(psPtr->inFile));	}    }    if (psPtr->outFile) {	newmask = mask & (TCL_WRITABLE | TCL_EXCEPTION);	if (newmask) {	    Tcl_CreateFileHandler(GetFd(psPtr->outFile), mask,		    (Tcl_FileProc *) Tcl_NotifyChannel,		    (ClientData) psPtr->channel);	} else {	    Tcl_DeleteFileHandler(GetFd(psPtr->outFile));	}    }}/* *---------------------------------------------------------------------- * * PipeGetHandleProc -- * *	Called from Tcl_GetChannelHandle to retrieve OS handles from *	inside a command pipeline based channel. * * Results: *	Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if *	there is no handle for the specified direction.  * * Side effects: *	None. * *---------------------------------------------------------------------- */static intPipeGetHandleProc(instanceData, direction, handlePtr)    ClientData instanceData;	/* The pipe state. */    int direction;		/* TCL_READABLE or TCL_WRITABLE */    ClientData *handlePtr;	/* Where to store the handle.  */{    PipeState *psPtr = (PipeState *) instanceData;    if (direction == TCL_READABLE && psPtr->inFile) {	*handlePtr = (ClientData) GetFd(psPtr->inFile);	return TCL_OK;    }    if (direction == TCL_WRITABLE && psPtr->outFile) {	*handlePtr = (ClientData) GetFd(psPtr->outFile);	return TCL_OK;    }    return TCL_ERROR;}/* *---------------------------------------------------------------------- * * Tcl_WaitPid -- * *	Implements the waitpid system call on Unix systems. * * Results: *	Result of calling waitpid. * * Side effects: *	Waits for a process to terminate. * *---------------------------------------------------------------------- */Tcl_PidTcl_WaitPid(pid, statPtr, options)    Tcl_Pid pid;    int *statPtr;    int options;{    int result;    pid_t real_pid;    real_pid = (pid_t) pid;    while (1) {	result = (int) waitpid(real_pid, statPtr, options);	if ((result != -1) || (errno != EINTR)) {	    return (Tcl_Pid) result;	}    }}/* *---------------------------------------------------------------------- * * Tcl_PidObjCmd -- * *	This procedure is invoked to process the "pid" Tcl command. *	See the user documentation for details on what it does. * * Results: *	A standard Tcl result. * * Side effects: *	See the user documentation. * *---------------------------------------------------------------------- */	/* ARGSUSED */intTcl_PidObjCmd(dummy, interp, objc, objv)    ClientData dummy;		/* Not used. */    Tcl_Interp *interp;		/* Current interpreter. */    int objc;			/* Number of arguments. */    Tcl_Obj *CONST *objv;	/* Argument strings. */{    Tcl_Channel chan;    Tcl_ChannelType *chanTypePtr;    PipeState *pipePtr;    int i;    Tcl_Obj *resultPtr, *longObjPtr;    if (objc > 2) {	Tcl_WrongNumArgs(interp, 1, objv, "?channelId?");	return TCL_ERROR;    }    if (objc == 1) {	Tcl_SetLongObj(Tcl_GetObjResult(interp), (long) getpid());    } else {        chan = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), NULL);        if (chan == (Tcl_Channel) NULL) {	    return TCL_ERROR;	}	chanTypePtr = Tcl_GetChannelType(chan);	if (chanTypePtr != &pipeChannelType) {	    return TCL_OK;	}        pipePtr = (PipeState *) Tcl_GetChannelInstanceData(chan);	resultPtr = Tcl_GetObjResult(interp);        for (i = 0; i < pipePtr->numPids; i++) {	    longObjPtr = Tcl_NewLongObj((long) TclpGetPid(pipePtr->pidPtr[i]));	    Tcl_ListObjAppendElement(NULL, resultPtr, longObjPtr);	}    }    return TCL_OK;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -