allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (02/04/89)
Posting-number: Volume 6, Issue 31 Submitted-by: bobg+@andrew.cmu.edu Archive-name: redir This is redir, a simple Unix program for csh(1) users who are tired of being sneered at by their sh(1)-using brothers because their shell can't separate stdout from stderr. Redir will exec a program you name, redirecting the standard output and/or the standard error (or neither) according to redir's options. Previously, the only good way of separating stdout from stderr in csh was something like (command > stdout-destination) >& stderr-destination which stinks. Suppose you wanted to pipe command A through command B, collecting the stderr of A in A.err and the stderr of B in B.err, while displaying the stdout of B? What would you do then, huh? Probably something awful that looks like this: (A | (B > /dev/tyy) >& B.err) >& A.err I'm not even sure that would work. I am sure that this works: redir -e A.err A | redir -e B.err B Well, here it is. ----- Not this line ----- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: README Makefile redir.c redir.doc # Wrapped by bobg@ephrata.andrew.cmu.edu on Sun Jan 29 19:02:42 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f README -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"README\" else echo shar: Extracting \"README\" \(893 characters\) sed "s/^X//" >README <<'END_OF_README' XRedir is a simple utility which remedies a problem in csh(1); Xnamely, that you can't redirect stdout and stderr separately, Xas you can in sh(1), unless you want to do something ugly like X X (command > stdout) >& stderr X XRedir will execute the command you name, with stdout and Xstderr redirected according to the options you supply to redir. XThe file redir.doc gives the usage of this program. X XTo compile this program, type "make redir". To install this Xprogram on your system, modify the Makefile so that the Xvariables BIN and DOC are defined to be the pathnames Xof the directories to hold the binary file "redir" and the Xdocumentation file "redir.doc," respectively, then type X"make install". X XThis software exists in the public domain. Absolutely no Xrestrictions on its usage, modification or distribution Xexist. No guarantees are made concerning the proper Xfunctioning of this software. END_OF_README if test 893 -ne `wc -c <README`; then echo shar: \"README\" unpacked with wrong size! fi # end of overwriting check fi if test -f Makefile -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Makefile\" else echo shar: Extracting \"Makefile\" \(350 characters\) sed "s/^X//" >Makefile <<'END_OF_Makefile' XOPTIMIZE = -O XDEBUG = XINCLUDES = XPROFILE = XLIBS = XCFLAGS = $(OPTIMIZE) $(DEBUG) $(INCLUDES) $(PROFILE) XCC = cc XBIN = XDOC = X XTARGET = redir X Xredir: redir.c X $(CC) $(CFLAGS) -o redir redir.c X Xtest: $(TARGET) X Xinstall: $(TARGET) X cp $(TARGET) $(BIN) X -strip $(BIN)/$(TARGET) X cp redir.doc $(DOC) X Xclean: X -rm -f *.BAK *.CKP *.o a.out gmon.out $(TARGET) END_OF_Makefile if test 350 -ne `wc -c <Makefile`; then echo shar: \"Makefile\" unpacked with wrong size! fi # end of overwriting check fi if test -f redir.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"redir.c\" else echo shar: Extracting \"redir.c\" \(3851 characters\) sed "s/^X//" >redir.c <<'END_OF_redir.c' X/* redir X * a program to execute a command, redirecting stdout and stderr separately, X * a feature available in sh but not csh. X * X * THIS SOFTWARE EXISTS IN THE PUBLIC DOMAIN. ABSOLUTELY NO X * RESTRICTIONS ON ITS USAGE, MODIFICATION OR DISTRIBUTION X * EXIST. NO GUARANTEES ARE MADE CONCERNING THE PROPER X * FUNCTIONING OF THIS SOFTWARE. X * X * Usage: X * X * redir [options] command-words... X * X * where options are X * -o file X * to redirect stdout to file "file," without clobbering "file" if it exists X * -e file X * to redirect stderr to file "file," without clobbering "file" if it exists X * -O file X * to redirect stdout to file "file," clobbering "file" if it exists X * -E file X * to redirect stderr to file "file," clobbering "file" if it exists X * -a X * the following redirection option is to append to the named file, as in: X * redir -O foo.log -ae foo.err command command-arg1 command-arg2 ... X * (stdout (destructively) to foo.log, stderr appended to foo.err. X * The -a option doesn't care if the named file exists or not. This option X * must be used twice if you want stdout and stderr both to be appended X * to their respective files; X * redir -ao foo.log -ae foo.err command ... X */ X X#include <stdio.h> X#include <sys/file.h> X X#define USAGESTRING ("Usage: %s [-[a][oeOE] file] ... command-words\n") X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X extern int optind; X extern char *optarg; X char *stderrfile = NULL, *stdoutfile = NULL; X int rstderr = 0, rstdout = 0, cstderr = 0, cstdout = 0, astderr = 0, astdout = 0, appendopt = 0, c, fd; X X while ((c = getopt(argc, argv, "ao:e:O:E:")) != EOF) { X switch (c) { X case 'a': X if (appendopt) { X fprintf(stderr, USAGESTRING, argv[0]); X exit(1); X } X ++appendopt; X break; X case 'e': X if (rstderr) { X fprintf(stderr, USAGESTRING, argv[0]); X exit(1); X } X ++rstderr; X stderrfile = optarg; X if (appendopt) { X appendopt = 0; X ++astderr; X } X break; X case 'o': X if (rstdout) { X fprintf(stderr, USAGESTRING, argv[0]); X exit(1); X } X ++rstdout; X stdoutfile = optarg; X if (appendopt) { X appendopt = 0; X ++astdout; X } X break; X case 'E': X if (rstderr) { X fprintf(stderr, USAGESTRING, argv[0]); X exit(1); X } X ++rstderr; X ++cstderr; X stderrfile = optarg; X if (appendopt) { X appendopt = 0; X ++astderr; X } X break; X case 'O': X if (rstdout) { X fprintf(stderr, USAGESTRING, argv[0]); X exit(1); X } X ++rstdout; X ++cstdout; X stdoutfile = optarg; X if (appendopt) { X appendopt = 0; X ++astdout; X } X break; X default: X fprintf(stderr, USAGESTRING, argv[0]); X exit(1); X break; X } X } X if (rstdout) { X if ((fd = open(stdoutfile, (astdout ? X (O_WRONLY | O_APPEND | O_CREAT) : X (cstdout ? X (O_WRONLY | O_CREAT | O_TRUNC) : X (O_WRONLY | O_CREAT | O_EXCL))), X 0644)) < 0) { X fprintf(stderr, X "%s: couldn't open destination %s for standard output\n", X argv[0], stdoutfile); X exit(2); X } X if (dup2(fd, 1) < 0) { X fprintf(stderr, X "%s: couldn't open destination %s for standard output\n", X argv[0], stdoutfile); X exit(2); X } X close(fd); X } X if (rstderr) { X if ((fd = open(stderrfile, (astderr ? X (O_WRONLY | O_APPEND | O_CREAT) : X (cstderr ? X (O_WRONLY | O_CREAT | O_TRUNC) : X (O_WRONLY | O_CREAT | O_EXCL))), X 0644)) < 0) { X fprintf(stderr, X "%s: couldn't open destination %s for standard error\n", X argv[0], stderrfile); X exit(2); X } X if (dup2(fd, 2) < 0) { X fprintf(stderr, X "%s: couldn't open destination %s for standard error\n", X argv[0], stderrfile); X exit(2); X } X close(fd); X } X execvp(argv[optind], argv + optind); X} END_OF_redir.c if test 3851 -ne `wc -c <redir.c`; then echo shar: \"redir.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f redir.doc -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"redir.doc\" else echo shar: Extracting \"redir.doc\" \(1658 characters\) sed "s/^X//" >redir.doc <<'END_OF_redir.doc' XREDIR(1) X XNAME Xredir - redirect standard output and/or standard error (diagnostic output) X XSYNOPSIS Xredir [-[a][oeOE] file] ... command arg1 arg2 ... X XDESCRIPTION XRedir executes the named command with the given arguments, Xredirecting the standard output and/or standard input according Xto the options given. This program exists to remedy a serious Xdeficiency in csh(1), namely that csh does not allow stdout Xand stderr to be redirected separately. The options are: X X-o file Redirect the standard output of the named command X to the file "file", only if "file" does not yet exist. X-O file Redirect the standard output of the named command X to the file "file", clobbering the existing X version of "file" if it exists. X-e Redirect the standard error (diagnostic output) of the X named command to file "file", only if "file" does not yet exist. X-E Redirect the standard error (diagnostic output) of the X named command to the file "file", clobbering the existing X version of "file" if it exists. X-ao file Append the standard output of the named command X to the file "file", whether or not "file" exists. X-ae file Append the standard error (diagnostic output) of the X named command to the file "file", whether or not "file" exists. X X-aO and -aE are synonyms for -ao and -ae. X XEXAMPLE XThe following example demonstrates a means for piping the output Xof sed through ctags and then into awk; errors from ctags will be Xplaced in the file "errors": X X% ... | sed -f sed-script | redir -e errors ctags -x | awk -f awk-script | ... X XAUTHOR XBob Glickstein X Information Technology Center X Carnegie Mellon University X Pittsburgh, PA X 22-Jan-89 X ARPAnet: bobg@andrew.cmu.edu END_OF_redir.doc if test 1658 -ne `wc -c <redir.doc`; then echo shar: \"redir.doc\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of shell archive. exit 0