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

📄 tclpipe.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 2 页
字号:
     * arguments and remove them from the argument list in the pipeline.     * Count the number of distinct processes (it's the number of "|"     * arguments plus one) but don't remove the "|" arguments because      * they'll be used in the second pass to seperate the individual      * child processes.  Cannot start the child processes in this pass      * because the redirection symbols may appear anywhere in the      * command line -- e.g., the '<' that specifies the input to the      * entire pipe may appear at the very end of the argument list.     */    lastBar = -1;    cmdCount = 1;    for (i = 0; i < argc; i++) {        skip = 0;	p = argv[i];	switch (*p++) {	case '|':	    if (*p == '&') {		p++;	    }	    if (*p == '\0') {		if ((i == (lastBar + 1)) || (i == (argc - 1))) {		    Tcl_SetResult(interp,			    "illegal use of | or |& in command",			    TCL_STATIC);		    goto error;		}	    }	    lastBar = i;	    cmdCount++;	    break;	case '<':	    if (inputClose != 0) {		inputClose = 0;		TclpCloseFile(inputFile);	    }	    if (inputRelease != 0) {		inputRelease = 0;		TclpReleaseFile(inputFile);	    }	    if (*p == '<') {		inputFile = NULL;		inputLiteral = p + 1;		skip = 1;		if (*inputLiteral == '\0') {		    inputLiteral = argv[i + 1];		    if (inputLiteral == NULL) {			Tcl_AppendResult(interp, "can't specify \"", argv[i],				"\" as last word in command", (char *) NULL);			goto error;		    }		    skip = 2;		}	    } else {		inputLiteral = NULL;		inputFile = FileForRedirect(interp, p, 1, argv[i], 			argv[i + 1], O_RDONLY, &skip, &inputClose, &inputRelease);		if (inputFile == NULL) {		    goto error;		}	    }	    break;	case '>':	    atOK = 1;	    flags = O_WRONLY | O_CREAT | O_TRUNC;	    errorToOutput = 0;	    if (*p == '>') {		p++;		atOK = 0;		flags = O_WRONLY | O_CREAT;	    }	    if (*p == '&') {		if (errorClose != 0) {		    errorClose = 0;		    TclpCloseFile(errorFile);		}		errorToOutput = 1;		p++;	    }	    /*	     * Close the old output file, but only if the error file is	     * not also using it.	     */	    if (outputClose != 0) {		outputClose = 0;		if (errorFile == outputFile) {		    errorClose = 1;		} else {		    TclpCloseFile(outputFile);		}	    }	    if (outputRelease != 0) {		outputRelease = 0;		if (errorFile == outputFile) {		    errorRelease = 1;		} else {		    TclpReleaseFile(outputFile);		}	    }	    outputFile = FileForRedirect(interp, p, atOK, argv[i], 		    argv[i + 1], flags, &skip, &outputClose, &outputRelease);	    if (outputFile == NULL) {		goto error;	    }	    if (errorToOutput) {		if (errorClose != 0) {		    errorClose = 0;		    TclpCloseFile(errorFile);		}		if (errorRelease != 0) {		    errorRelease = 0;		    TclpReleaseFile(errorFile);		}		errorFile = outputFile;	    }	    break;	case '2':	    if (*p != '>') {		break;	    }	    p++;	    atOK = 1;	    flags = O_WRONLY | O_CREAT | O_TRUNC;	    if (*p == '>') {		p++;		atOK = 0;		flags = O_WRONLY | O_CREAT;	    }	    if (errorClose != 0) {		errorClose = 0;		TclpCloseFile(errorFile);	    }	    if (errorRelease != 0) {		errorRelease = 0;		TclpReleaseFile(errorFile);	    }	    errorFile = FileForRedirect(interp, p, atOK, argv[i], 		    argv[i + 1], flags, &skip, &errorClose, &errorRelease);	    if (errorFile == NULL) {		goto error;	    }	    break;	}	if (skip != 0) {	    for (j = i + skip; j < argc; j++) {		argv[j - skip] = argv[j];	    }	    argc -= skip;	    i -= 1;	}    }    if (inputFile == NULL) {	if (inputLiteral != NULL) {	    /*	     * The input for the first process is immediate data coming from	     * Tcl.  Create a temporary file for it and put the data into the	     * file.	     */	    inputFile = TclpCreateTempFile(inputLiteral, NULL);	    if (inputFile == NULL) {		Tcl_AppendResult(interp,			"couldn't create input file for command: ",			Tcl_PosixError(interp), (char *) NULL);		goto error;	    }	    inputClose = 1;	} else if (inPipePtr != NULL) {	    /*	     * The input for the first process in the pipeline is to	     * come from a pipe that can be written from by the caller.	     */	    if (TclpCreatePipe(&inputFile, inPipePtr) == 0) {		Tcl_AppendResult(interp, 			"couldn't create input pipe for command: ",			Tcl_PosixError(interp), (char *) NULL);		goto error;	    }	    inputClose = 1;	} else {	    /*	     * The input for the first process comes from stdin.	     */	    channel = Tcl_GetStdChannel(TCL_STDIN);	    if (channel != NULL) {		inputFile = TclpMakeFile(channel, TCL_READABLE);		if (inputFile != NULL) {		    inputRelease = 1;		}	    }	}    }    if (outputFile == NULL) {	if (outPipePtr != NULL) {	    /*	     * Output from the last process in the pipeline is to go to a	     * pipe that can be read by the caller.	     */	    if (TclpCreatePipe(outPipePtr, &outputFile) == 0) {		Tcl_AppendResult(interp, 			"couldn't create output pipe for command: ",			Tcl_PosixError(interp), (char *) NULL);		goto error;	    }	    outputClose = 1;	} else {	    /*	     * The output for the last process goes to stdout.	     */	    channel = Tcl_GetStdChannel(TCL_STDOUT);	    if (channel) {		outputFile = TclpMakeFile(channel, TCL_WRITABLE);		if (outputFile != NULL) {		    outputRelease = 1;		}	    }	}    }    if (errorFile == NULL) {	if (errFilePtr != NULL) {	    /*	     * Set up the standard error output sink for the pipeline, if	     * requested.  Use a temporary file which is opened, then deleted.	     * Could potentially just use pipe, but if it filled up it could	     * cause the pipeline to deadlock:  we'd be waiting for processes	     * to complete before reading stderr, and processes couldn't 	     * complete because stderr was backed up.	     */	    errorFile = TclpCreateTempFile(NULL, NULL);	    if (errorFile == NULL) {		Tcl_AppendResult(interp,			"couldn't create error file for command: ",			Tcl_PosixError(interp), (char *) NULL);		goto error;	    }	    *errFilePtr = errorFile;	} else {	    /*	     * Errors from the pipeline go to stderr.	     */	    channel = Tcl_GetStdChannel(TCL_STDERR);	    if (channel) {		errorFile = TclpMakeFile(channel, TCL_WRITABLE);		if (errorFile != NULL) {		    errorRelease = 1;		}	    }	}    }	    /*     * Scan through the argc array, creating a process for each     * group of arguments between the "|" characters.     */    Tcl_ReapDetachedProcs();    pidPtr = (Tcl_Pid *) ckalloc((unsigned) (cmdCount * sizeof(Tcl_Pid)));    curInFile = inputFile;    for (i = 0; i < argc; i = lastArg + 1) { 	int joinThisError;	Tcl_Pid pid;	/*	 * Convert the program name into native form. 	 */	argv[i] = Tcl_TranslateFileName(interp, argv[i], &execBuffer);	if (argv[i] == NULL) {	    goto error;	}	/*	 * Find the end of the current segment of the pipeline.	 */	joinThisError = 0;	for (lastArg = i; lastArg < argc; lastArg++) {	    if (argv[lastArg][0] == '|') { 		if (argv[lastArg][1] == '\0') { 		    break;		}		if ((argv[lastArg][1] == '&') && (argv[lastArg][2] == '\0')) {		    joinThisError = 1;		    break;		}	    }	}	argv[lastArg] = NULL;	/*	 * If this is the last segment, use the specified outputFile.	 * Otherwise create an intermediate pipe.  pipeIn will become the	 * curInFile for the next segment of the pipe.	 */	if (lastArg == argc) { 	    curOutFile = outputFile;	} else {	    if (TclpCreatePipe(&pipeIn, &curOutFile) == 0) {		Tcl_AppendResult(interp, "couldn't create pipe: ",			Tcl_PosixError(interp), (char *) NULL);		goto error;	    }	}	if (joinThisError != 0) {	    curErrFile = curOutFile;	} else {	    curErrFile = errorFile;	}	if (TclpCreateProcess(interp, lastArg - i, argv + i,		curInFile, curOutFile, curErrFile, &pid) != TCL_OK) {	    goto error;	}	Tcl_DStringFree(&execBuffer);	pidPtr[numPids] = pid;	numPids++;	/*	 * Close off our copies of file descriptors that were set up for	 * this child, then set up the input for the next child.	 */	if ((curInFile != NULL) && (curInFile != inputFile)) {	    TclpCloseFile(curInFile);	}	curInFile = pipeIn;	pipeIn = NULL;	if ((curOutFile != NULL) && (curOutFile != outputFile)) {	    TclpCloseFile(curOutFile);	}	curOutFile = NULL;    }    *pidArrayPtr = pidPtr;    /*     * All done.  Cleanup open files lying around and then return.     */cleanup:    Tcl_DStringFree(&execBuffer);    if (inputClose) {	TclpCloseFile(inputFile);    } else if (inputRelease) {	TclpReleaseFile(inputFile);    }    if (outputClose) {	TclpCloseFile(outputFile);    } else if (outputRelease) {	TclpReleaseFile(outputFile);    }    if (errorClose) {	TclpCloseFile(errorFile);    } else if (errorRelease) {	TclpReleaseFile(errorFile);    }    return numPids;    /*     * An error occurred.  There could have been extra files open, such     * as pipes between children.  Clean them all up.  Detach any child     * processes that have been created.     */error:    if (pipeIn != NULL) {	TclpCloseFile(pipeIn);    }    if ((curOutFile != NULL) && (curOutFile != outputFile)) {	TclpCloseFile(curOutFile);    }    if ((curInFile != NULL) && (curInFile != inputFile)) {	TclpCloseFile(curInFile);    }    if ((inPipePtr != NULL) && (*inPipePtr != NULL)) {	TclpCloseFile(*inPipePtr);	*inPipePtr = NULL;    }    if ((outPipePtr != NULL) && (*outPipePtr != NULL)) {	TclpCloseFile(*outPipePtr);	*outPipePtr = NULL;    }    if ((errFilePtr != NULL) && (*errFilePtr != NULL)) {	TclpCloseFile(*errFilePtr);	*errFilePtr = NULL;    }    if (pidPtr != NULL) {	for (i = 0; i < numPids; i++) {	    if (pidPtr[i] != (Tcl_Pid) -1) {		Tcl_DetachPids(1, &pidPtr[i]);	    }	}	ckfree((char *) pidPtr);    }    numPids = -1;    goto cleanup;}/* *---------------------------------------------------------------------- * * Tcl_OpenCommandChannel -- * *	Opens an I/O channel to one or more subprocesses specified *	by argc and argv.  The flags argument determines the *	disposition of the stdio handles.  If the TCL_STDIN flag is *	set then the standard input for the first subprocess will *	be tied to the channel:  writing to the channel will provide *	input to the subprocess.  If TCL_STDIN is not set, then *	standard input for the first subprocess will be the same as *	this application's standard input.  If TCL_STDOUT is set then *	standard output from the last subprocess can be read from the *	channel;  otherwise it goes to this application's standard *	output.  If TCL_STDERR is set, standard error output for all *	subprocesses is returned to the channel and results in an error *	when the channel is closed;  otherwise it goes to this *	application's standard error.  If TCL_ENFORCE_MODE is not set, *	then argc and argv can redirect the stdio handles to override *	TCL_STDIN, TCL_STDOUT, and TCL_STDERR;  if it is set, then it  *	is an error for argc and argv to override stdio channels for *	which TCL_STDIN, TCL_STDOUT, and TCL_STDERR have been set. * * Results: *	A new command channel, or NULL on failure with an error *	message left in interp. * * Side effects: *	Creates processes, opens pipes. * *---------------------------------------------------------------------- */Tcl_ChannelTcl_OpenCommandChannel(interp, argc, argv, flags)    Tcl_Interp *interp;		/* Interpreter for error reporting. Can                                 * NOT be NULL. */    int argc;			/* How many arguments. */    char **argv;		/* Array of arguments for command pipe. */    int flags;			/* Or'ed combination of TCL_STDIN, TCL_STDOUT,				 * TCL_STDERR, and TCL_ENFORCE_MODE. */{    TclFile *inPipePtr, *outPipePtr, *errFilePtr;    TclFile inPipe, outPipe, errFile;    int numPids;    Tcl_Pid *pidPtr;    Tcl_Channel channel;    inPipe = outPipe = errFile = NULL;    inPipePtr = (flags & TCL_STDIN) ? &inPipe : NULL;    outPipePtr = (flags & TCL_STDOUT) ? &outPipe : NULL;    errFilePtr = (flags & TCL_STDERR) ? &errFile : NULL;        numPids = TclCreatePipeline(interp, argc, argv, &pidPtr, inPipePtr,            outPipePtr, errFilePtr);    if (numPids < 0) {	goto error;    }    /*     * Verify that the pipes that were created satisfy the     * readable/writable constraints.      */    if (flags & TCL_ENFORCE_MODE) {	if ((flags & TCL_STDOUT) && (outPipe == NULL)) {	    Tcl_AppendResult(interp, "can't read output from command:",		    " standard output was redirected", (char *) NULL);	    goto error;	}	if ((flags & TCL_STDIN) && (inPipe == NULL)) {	    Tcl_AppendResult(interp, "can't write input to command:",		    " standard input was redirected", (char *) NULL);	    goto error;	}    }        channel = TclpCreateCommandChannel(outPipe, inPipe, errFile,	    numPids, pidPtr);    if (channel == (Tcl_Channel) NULL) {        Tcl_AppendResult(interp, "pipe for command could not be created",                (char *) NULL);	goto error;    }    return channel;error:    if (numPids > 0) {	Tcl_DetachPids(numPids, pidPtr);	ckfree((char *) pidPtr);    }    if (inPipe != NULL) {	TclpCloseFile(inPipe);    }    if (outPipe != NULL) {	TclpCloseFile(outPipe);    }    if (errFile != NULL) {	TclpCloseFile(errFile);    }    return NULL;}

⌨️ 快捷键说明

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