summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorhobbs <hobbs>2004-07-02 23:31:27 (GMT)
committerhobbs <hobbs>2004-07-02 23:31:27 (GMT)
commit2ab4506f34cae724a01ece9dc1c650e5a9b674e9 (patch)
tree2ab62cdf50305b836821c87186431bcd137a4c73 /generic
parent1aa82f9d198e68705e1f5a9fd2ff6525e45fb0f4 (diff)
downloadtcl-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.c51
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.