diff options
author | hobbs <hobbs> | 2004-07-02 23:31:27 (GMT) |
---|---|---|
committer | hobbs <hobbs> | 2004-07-02 23:31:27 (GMT) |
commit | 2ab4506f34cae724a01ece9dc1c650e5a9b674e9 (patch) | |
tree | 2ab62cdf50305b836821c87186431bcd137a4c73 /generic | |
parent | 1aa82f9d198e68705e1f5a9fd2ff6525e45fb0f4 (diff) | |
download | tcl-2ab4506f34cae724a01ece9dc1c650e5a9b674e9.zip tcl-2ab4506f34cae724a01ece9dc1c650e5a9b674e9.tar.gz tcl-2ab4506f34cae724a01ece9dc1c650e5a9b674e9.tar.bz2 |
* generic/tclPipe.c (TclCreatePipeline): applied TIP #202 patch
* doc/exec.n, tests/exec.test: that adds 2>@1 as a
special case redirection of stderr to the result output.
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclPipe.c | 51 |
1 files changed, 36 insertions, 15 deletions
diff --git a/generic/tclPipe.c b/generic/tclPipe.c index 99a89e1..681d18b 100644 --- a/generic/tclPipe.c +++ b/generic/tclPipe.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclPipe.c,v 1.8 2004/04/06 22:25:54 dgp Exp $ + * RCS: @(#) $Id: tclPipe.c,v 1.9 2004/07/02 23:31:29 hobbs Exp $ */ #include "tclInt.h" @@ -67,13 +67,13 @@ static TclFile FileForRedirect(interp, spec, atOK, arg, nextArg, flags, skipPtr, closePtr, releasePtr) Tcl_Interp *interp; /* Intepreter to use for error reporting. */ - CONST char *spec; /* Points to character just after + CONST char *spec; /* Points to character just after * redirection character. */ - CONST char *arg; /* Pointer to entire argument containing - * spec: used for error reporting. */ int atOK; /* Non-zero means that '@' notation can be * used to specify a channel, zero means that * it isn't. */ + CONST char *arg; /* Pointer to entire argument containing + * spec: used for error reporting. */ CONST char *nextArg; /* Next argument in argc/argv array, if needed * for file name or channel name. May be * NULL. */ @@ -106,9 +106,9 @@ FileForRedirect(interp, spec, atOK, arg, nextArg, flags, skipPtr, closePtr, } file = TclpMakeFile(chan, writing ? TCL_WRITABLE : TCL_READABLE); if (file == NULL) { - Tcl_AppendResult(interp, "channel \"", Tcl_GetChannelName(chan), - "\" wasn't opened for ", - ((writing) ? "writing" : "reading"), (char *) NULL); + Tcl_AppendResult(interp, "channel \"", Tcl_GetChannelName(chan), + "\" wasn't opened for ", + ((writing) ? "writing" : "reading"), (char *) NULL); return NULL; } *releasePtr = 1; @@ -507,7 +507,7 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr, * closed when cleaning up. */ int errorRelease = 0; CONST char *p; - int skip, lastBar, lastArg, i, j, atOK, flags, errorToOutput; + int skip, lastBar, lastArg, i, j, atOK, flags, errorToOutput = 0; Tcl_DString execBuffer; TclFile pipeIn; TclFile curInFile, curOutFile, curErrFile; @@ -546,7 +546,8 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr, lastBar = -1; cmdCount = 1; for (i = 0; i < argc; i++) { - skip = 0; + errorToOutput = 0; + skip = 0; p = argv[i]; switch (*p++) { case '|': @@ -600,7 +601,6 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr, case '>': atOK = 1; flags = O_WRONLY | O_CREAT | O_TRUNC; - errorToOutput = 0; if (*p == '>') { p++; atOK = 0; @@ -674,10 +674,26 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr, errorRelease = 0; TclpReleaseFile(errorFile); } - errorFile = FileForRedirect(interp, p, atOK, argv[i], - argv[i + 1], flags, &skip, &errorClose, &errorRelease); - if (errorFile == NULL) { - goto error; + if (atOK && p[0] == '@' && p[1] == '1' && p[2] == '\0') { + /* + * Special case handling of 2>@1 to redirect stderr to the + * exec/open output pipe as well. This is meant for the end + * of the command string, otherwise use |& between commands. + */ + if (i != argc - 1) { + Tcl_AppendResult(interp, "must specify \"", argv[i], + "\" as last word in command", (char *) NULL); + goto error; + } + errorFile = outputFile; + errorToOutput = 2; + skip = 1; + } else { + errorFile = FileForRedirect(interp, p, atOK, argv[i], + argv[i + 1], flags, &skip, &errorClose, &errorRelease); + if (errorFile == NULL) { + goto error; + } } break; } @@ -764,7 +780,12 @@ TclCreatePipeline(interp, argc, argv, pidArrayPtr, inPipePtr, } if (errorFile == NULL) { - if (errFilePtr != NULL) { + if (errorToOutput == 2) { + /* + * Handle 2>@1 special case at end of cmd line + */ + errorFile = outputFile; + } else if (errFilePtr != NULL) { /* * Set up the standard error output sink for the pipeline, if * requested. Use a temporary file which is opened, then deleted. |