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

📄 tclunixpipe.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  * tclUnixPipe.c -- * *	This file implements the UNIX-specific exec pipeline functions, *	the "pipe" channel driver, and the "pid" Tcl command. * * 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. * * RCS: @(#) $Id: tclUnixPipe.c,v 1.23 2003/02/21 14:15:58 das Exp $ */#include "tclInt.h"#include "tclPort.h"#ifdef USE_VFORK#define fork vfork#endif/* * The following macros convert between TclFile's and fd's.  The conversion * simple involves shifting fd's up by one to ensure that no valid fd is ever * the same as NULL. */#define MakeFile(fd) ((TclFile)(((int)fd)+1))#define GetFd(file) (((int)file)-1)/* * This structure describes per-instance state of a pipe based channel. */typedef struct PipeState {    Tcl_Channel channel;/* Channel associated with this file. */    TclFile inFile;	/* Output from pipe. */    TclFile outFile;	/* Input to pipe. */    TclFile errorFile;	/* Error output from pipe. */    int numPids;	/* How many processes are attached to this pipe? */    Tcl_Pid *pidPtr;	/* The process IDs themselves. Allocated by                         * the creator of the pipe. */    int isNonBlocking;	/* Nonzero when the pipe is in nonblocking mode.                         * Used to decide whether to wait for the children                         * at close time. */} PipeState;/* * Declarations for local procedures defined in this file: */static int	PipeBlockModeProc _ANSI_ARGS_((ClientData instanceData,		    int mode));static int	PipeCloseProc _ANSI_ARGS_((ClientData instanceData,		    Tcl_Interp *interp));static int	PipeGetHandleProc _ANSI_ARGS_((ClientData instanceData,		    int direction, ClientData *handlePtr));static int	PipeInputProc _ANSI_ARGS_((ClientData instanceData,		    char *buf, int toRead, int *errorCode));static int	PipeOutputProc _ANSI_ARGS_((		    ClientData instanceData, CONST char *buf, int toWrite,		    int *errorCode));static void	PipeWatchProc _ANSI_ARGS_((ClientData instanceData, int mask));static void	RestoreSignals _ANSI_ARGS_((void));static int	SetupStdFile _ANSI_ARGS_((TclFile file, int type));/* * This structure describes the channel type structure for command pipe * based IO: */static Tcl_ChannelType pipeChannelType = {    "pipe",			/* Type name. */    TCL_CHANNEL_VERSION_2,	/* v2 channel */    PipeCloseProc,		/* Close proc. */    PipeInputProc,		/* Input proc. */    PipeOutputProc,		/* Output proc. */    NULL,			/* Seek proc. */    NULL,			/* Set option proc. */    NULL,			/* Get option proc. */    PipeWatchProc,		/* Initialize notifier. */    PipeGetHandleProc,		/* Get OS handles out of channel. */    NULL,			/* close2proc. */    PipeBlockModeProc,		/* Set blocking or non-blocking mode.*/    NULL,			/* flush proc. */    NULL,			/* handler proc. */};/* *---------------------------------------------------------------------- * * TclpMakeFile -- * *	Make a TclFile from a channel. * * Results: *	Returns a new TclFile or NULL on failure. * * Side effects: *	None. * *---------------------------------------------------------------------- */TclFileTclpMakeFile(channel, direction)    Tcl_Channel channel;	/* Channel to get file from. */    int direction;		/* Either TCL_READABLE or TCL_WRITABLE. */{    ClientData data;    if (Tcl_GetChannelHandle(channel, direction, (ClientData *) &data)	    == TCL_OK) {	return MakeFile((int)data);    } else {	return (TclFile) NULL;    }}/* *---------------------------------------------------------------------- * * TclpOpenFile -- * *	Open a file for use in a pipeline.   * * Results: *	Returns a new TclFile handle or NULL on failure. * * Side effects: *	May cause a file to be created on the file system. * *---------------------------------------------------------------------- */TclFileTclpOpenFile(fname, mode)    CONST char *fname;		/* The name of the file to open. */    int mode;			/* In what mode to open the file? */{    int fd;    CONST char *native;    Tcl_DString ds;    native = Tcl_UtfToExternalDString(NULL, fname, -1, &ds);    fd = TclOSopen(native, mode, 0666);			/* INTL: Native. */    Tcl_DStringFree(&ds);    if (fd != -1) {        fcntl(fd, F_SETFD, FD_CLOEXEC);	/*	 * If the file is being opened for writing, seek to the end	 * so we can append to any data already in the file.	 */	if (mode & O_WRONLY) {	    TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_END);	}	/*	 * Increment the fd so it can't be 0, which would conflict with	 * the NULL return for errors.	 */	return MakeFile(fd);    }    return NULL;}/* *---------------------------------------------------------------------- * * TclpCreateTempFile -- * *	This function creates a temporary file initialized with an *	optional string, and returns a file handle with the file pointer *	at the beginning of the file. * * Results: *	A handle to a file. * * Side effects: *	None. * *---------------------------------------------------------------------- */TclFileTclpCreateTempFile(contents)    CONST char *contents;	/* String to write into temp file, or 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, P_tmpdir);				/* 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);    unlink(fileName);					/* INTL: Native. */    if (contents != NULL) {	native = Tcl_UtfToExternalDString(NULL, contents, -1, &dstring);	if (write(fd, native, strlen(native)) == -1) {	    close(fd);	    Tcl_DStringFree(&dstring);	    return NULL;	}	Tcl_DStringFree(&dstring);	TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_SET);    }    return MakeFile(fd);}/* *---------------------------------------------------------------------- * * TclpTempFileName -- * *	This function returns unique filename. * * Results: *	Returns a valid Tcl_Obj* with refCount 0, or NULL on failure. * * Side effects: *	None. * *---------------------------------------------------------------------- */Tcl_Obj* TclpTempFileName(){    char fileName[L_tmpnam + 9];    Tcl_Obj *result = NULL;    int fd;    /*     * We should also check against making more then TMP_MAX of these.     */    strcpy(fileName, P_tmpdir);		/* 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);    unlink(fileName);			/* INTL: Native. */    result = TclpNativeToNormalized((ClientData) fileName);    close (fd);    return result;}/* *---------------------------------------------------------------------- * * TclpCreatePipe -- * *      Creates a pipe - simply calls the pipe() function. * * Results: *      Returns 1 on success, 0 on failure.  * * Side effects: *      Creates a pipe. * *---------------------------------------------------------------------- */intTclpCreatePipe(readPipe, writePipe)    TclFile *readPipe;		/* Location to store file handle for				 * read side of pipe. */    TclFile *writePipe;		/* Location to store file handle for				 * write side of pipe. */{    int pipeIds[2];    if (pipe(pipeIds) != 0) {	return 0;    }    fcntl(pipeIds[0], F_SETFD, FD_CLOEXEC);    fcntl(pipeIds[1], F_SETFD, FD_CLOEXEC);    *readPipe = MakeFile(pipeIds[0]);    *writePipe = MakeFile(pipeIds[1]);    return 1;}/* *---------------------------------------------------------------------- * * TclpCloseFile -- * *	Implements a mechanism to close a UNIX file. * * Results: *	Returns 0 on success, or -1 on error, setting errno. * * Side effects: *	The file is closed. * *---------------------------------------------------------------------- */intTclpCloseFile(file)    TclFile file;	/* The file to close. */{    int fd = GetFd(file);    /*     * Refuse to close the fds for stdin, stdout and stderr.     */        if ((fd == 0) || (fd == 1) || (fd == 2)) {        return 0;    }        Tcl_DeleteFileHandler(fd);    return close(fd);}/* *--------------------------------------------------------------------------- * * TclpCreateProcess -- * *	Create a child process that has the specified files as its  *	standard input, output, and error.  The child process runs *	asynchronously and runs with the same environment variables *	as the creating process. * *	The path is searched to find the specified executable.   * * Results: *	The return value is TCL_ERROR and an error message is left in *	the interp's result if there was a problem creating the child  *	process.  Otherwise, the return value is TCL_OK and *pidPtr is *	filled with the process id of the child process. *  * Side effects: *	A process is created. *	 *--------------------------------------------------------------------------- */    /* ARGSUSED */intTclpCreateProcess(interp, argc, argv, inputFile, outputFile, errorFile, 	pidPtr)    Tcl_Interp *interp;		/* Interpreter in which to leave errors that				 * occurred when creating the child process.				 * Error messages from the child process				 * itself are sent to errorFile. */    int argc;			/* Number of arguments in following array. */    CONST char **argv;		/* Array of argument strings in UTF-8.				 * argv[0] contains the name of the executable				 * translated using Tcl_TranslateFileName				 * call).  Additional arguments have not been				 * converted. */    TclFile inputFile;		/* If non-NULL, gives the file to use as				 * input for the child process.  If inputFile				 * file is not readable or is NULL, the child				 * will receive no standard input. */    TclFile outputFile;		/* If non-NULL, gives the file that				 * receives output from the child process.  If				 * 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 writeable or is NULL,				 * errors from the child will be discarded.				 * errorFile may be the same as outputFile. */    Tcl_Pid *pidPtr;		/* If this procedure is successful, pidPtr				 * is filled with the process id of the child				 * process. */{    TclFile errPipeIn, errPipeOut;    int joinThisError, count, status, fd;    char errSpace[200 + TCL_INTEGER_SPACE];    Tcl_DString *dsArray;    char **newArgv;    int pid, i;        errPipeIn = NULL;    errPipeOut = NULL;    pid = -1;    /*     * Create a pipe that the child can use to return error     * information if anything goes wrong.     */    if (TclpCreatePipe(&errPipeIn, &errPipeOut) == 0) {	Tcl_AppendResult(interp, "couldn't create pipe: ",		Tcl_PosixError(interp), (char *) NULL);	goto error;

⌨️ 快捷键说明

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