[comp.sys.ibm.pc] redirecting std[in,out,err] vs. the shell

randyn@microsoft.UUCP (Randy Nevin) (04/26/89)

stdin, stdout, and stderr are simply file pointers, and can be redirected on
dos or unix. there is nothing magic about them that prevents redirection. the
fact that the shell (sh or csh on unix, command.com on dos) does not do this
for you does not prohibit you from doing it yourself. below is the code to a
simple shell which redirects any of these file pointers before executing an
arbitrary command. "redirect -i myin -o myout -e myerr foo arg1 arg2" will
execute the dos command "foo arg1 arg2" with stdin redirected from file myin,
and stdout and stderr redirected to files myout and myerr, respectively. so
information is not lost, myout and myerr are opened for appending, rather
than overwriting. this works on dos or unix.

/*
** redirect -- feed line to shell with stdin/stdout/stderr redirected
**
** usage -- redirect [-i newin] [-o newout] [-e newerr] command
**
** executes command via the shell, but redirects stdin/stdout/stderr first.
** stdout/stderr are appended, not overwritten.
*/

#include <stdio.h>

extern char *strcat( char *, char * );
extern char *strcpy( char *, char * );
extern int system( char * );
extern void exit( int );
extern int errno;
char umsg[] = "usage: redirect [-i newin] [-o newout] [-e newerr] command\n";
char emsg[] = "can't redirect %s to %s\n";

void main ( int, char ** );
void main ( argc, argv )
	int argc;
	char **argv;
	{
	int result;
	char buf[5120];

	argc--;  argv++;
	if (!argc) {
		fprintf( stderr, umsg );
		exit( 0 );
		}
	while (**argv == '-') {
		if (*(*argv+1) == 'i') {
			argc--;  argv++;
			if (!freopen( *argv, "r", stdin )) {
				fprintf( stderr, emsg, "stdin", *argv );
				exit( 1 );
				}
			}
		else if (*(*argv+1) == 'o') {
			argc--;  argv++;
			if (!freopen( *argv, "a", stdout )) {
				fprintf( stderr, emsg, "stdout", *argv );
				exit( 1 );
				}
			}
		else if (*(*argv+1) == 'e') {
			argc--;  argv++;
			if (!freopen( *argv, "a", stderr )) {
				fprintf( stderr, emsg, "stderr", *argv );
				exit( 1 );
				}
			}
		else
			fprintf( stderr, "unknown option %c\n", *(*argv+1) );
		argc--;  argv++;
		}
	if (!argc) {
		fprintf( stderr, umsg );
		exit( 0 );
		}
	strcpy( buf, *argv++ );
	while (*argv)
		strcat( strcat( buf, " " ), *argv++ );
	if (result = system( buf ))
		fprintf( stderr, "exit code = %d, errno = %d\n", result,
			errno );
	exit( 0 );
	}

arpanet:  microsoft!randyn@beaver.cs.washington.edu
          or  microsoft!randyn@uunet.uu.net
uucp:     ..uw-beaver!microsoft!randyn  or  ..uunet!microsoft!randyn

bobmon@iuvax.cs.indiana.edu (RAMontante) (04/28/89)

randyn@microsoft.UUCP (Randy Nevin) <5608@microsoft.UUCP> :
-
-fact that the shell (sh or csh on unix, command.com on dos) does not do this
-for you does not prohibit you from doing it yourself. below is the code to a

Note, though, that sh, csh, tcsh (and any other shell, I expect) on unix
*do* support redirection.  COMMAND.COM does not support redirection of
stderr, although it does mimic the unix notion of redirection and piping
of stdin and stout.

Some (not all) of the scorn that MSDOS generates is caused by this
incomplete and inept mimicking of unix's behavior.  Thanks to Randy
for showing a workaround.