[comp.lang.c] redirecting a child process output to a file

wei@hpctdls.HP.COM (Bill Ives) (06/19/89)

    To redirect a child's stdout to a file in the way you
    described does not work because the child process does
    not parse the ">" out of the command line.  When the
    redirection operators are used they are used on the DOS
    command line  --- where DOS ( namely command.com ) parses
    them out and determines that redirection is to be done. The
    same thing works for pipes "|".  Since the command.com shell
    does this parsing and redirection you may invoke it with the
    child process name and args following like:
    
    c:\command.com  child.exe > outfile.dat

    You should get the command.com specification out of your environment
    by looking at the "COMSPEC=" environment variable.

    You could also do the redirection yourself by using DOS functions
    DOS_DUP_HANDLE, DOS_CLOSE  ....  The idea in using these is to do
    the same thing the command shell does when it sees the ">" operator.
    The basic algorithm for doing this is:

    duplicate your stdout and save the duplicate in a temp variable
    open the child's stdout file
    close your stdout handle so the that it may be attached to the
       file opened above.
    use DOS_DUP again to attach the opened file to the stdout

    your stdout is now the file that was opened.

    invoke the child -- it will inherit the stdout that
         is attached to the file.

    restore your own stdout by closing stdout and duping the
       temp handle saved in the first step.  Your stdout will
       then be restored.

bga@bgalli.eds.com (Billy G. Allie) (06/20/89)

In article <8430@techunix.BITNET>, buzy@techunix.BITNET (boaz binnun) writes:
> I need to redirect the output of a child process to a file,
> I am working with Turbo C, what  I did was :
> 
> 	char *args[] = { "child.exe", "argument", ">", "filename", NULL };
> 	spawnl(P_WAIT,args[0],args[0],args[1],args[2],args[3],args[4]);
> 
> and it didnt work,does anyone know why ?

The redirection of the standard input and output files using the '>' and '<'
characters is a function the shell (command.com in this case).  Executing a
program with spawn or exec with the redirection character(s) in the
argument list will not cause redirection (unless the program is command.com
or the prgram has been written to recognize the redirection characters as
such).  To redirect the output of a child process to a file you can do one
of two things:

1.   Use the system function, which will use command.com to execute the
     program and set up the redirection.  For example:

     system("child argument >filename");

     The disadvantage to this method is that another copy of command.com
     must be loaded into memory in addition to the child program.  Also,
     there is a bug in command.com that prevents the exit code from the
     child process from returning correctly.  The advantages are that it
     is easy to use and even pipes can be set up in this manner.

2.   Set up the file redirection yourself before spawning the child
     process.  This can be done as follows:

     int oldstdout, newstdout;
	...
     oldstdout = dup(2);	/* Save the original stdout handle	    */
     newstdout = open("filename", O_CREAT|O_TRUNC|O_WRONLY); /* open output */
     dup2(newstdout, 2);	/* Make the new file the standard output    */
     close(newstdout);		/* Close the (now) un-needed file handle    */
     spawnl(P_WAIT, "child.exe", "child", "argument"); /* Execute the child */
     dup2(oldstdout, 2);	/* Restore the original stdout handle	    */
     close(oldstdout);		/* Close the un-needed file handle	    */

     Please note that I did not include any code to check the return
     values of the dup, dup2, close, open and spawnl function calls.
     Those checks will have to be added for the code sequence to be
     truly useful.

     The disadvantage of this method is that it is harder to set up.
     The advantages are it can be used to redirect any of the 5 standard
     devices used in the MS-DOS environment (stdin, stdout, stderr,
     stdaux and stdprn) and it does not require any additional processes
     to be loaded (i.e. command.com).

I hope this helps you with your problem.
-- 
____	   | Billy G. Allie	| Internet..: bga@bgalli.eds.com
|  /|	   | 7436 Hartwell	| UUCP......: uunet!{mcf|edsews}!bgalli!bga
|-/-|----- | Dearborn, MI 48126	| Compuserve: 76337,2061
|/  |LLIE  | (313) 582-1540	| Genie.....: BGALLIE

chris@mimsy.UUCP (Chris Torek) (06/21/89)

In various articles various people write about:
	fork
	exec
	spawn
	/bin/sh
	command.com
	sockets
	interrupt handlers
	device drivers
and so forth.  Unfortunately, they do it in comp.lang.c, although
the only relation these things have to C is that they can be programmed
in C, or called from C programs.  But so can databases, operating
systems, USENET news, UUCP, kermit, and so forth; and these are *not*
discussed in comp.lang.c (or at least not anywhere near as often).

The latter is how things should be.  Please try to keep IBM-PC
specific articles in IBM-PC specific newsgroups; and try to keep
Unix-specific articles in Unix-specific newsgroups.  Those of you
who read this via INFO-C on the Internet, please use one of the
other INFO-* lists.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

buzy@techunix.BITNET (boaz binnun) (07/22/89)

I need to redirect the output of a child process to a file,
I am working with Turbo C,

what  I did was :

char *args[] = { "child.exe",
                 "argument",
                 ">",
                 "filename",
                 NULL   };

and than :

spawnl(P_WAIT,args[0],args[0],args[1],args[2],args[3],args[4]);

and it didnt work,does anyone know why ?

Many thanks


Boaz Bin-nun  buzy@techunix.bitnet or buzy@techunix.technion.ac.il

dik@cwi.nl (Dik T. Winter) (07/22/89)

In article <8430@.........BITNET> ....%.........bitnet@jade.berkeley.edu (.... ......) writes:
 > I need to redirect the output of a child process to a file,
 > I am working with Turbo C,
 > 
Matt Crawford can say Aaaaarrrrrggggghhhhh again.
-- 
dik t. winter, cwi, amsterdam, nederland
INTERNET   : dik@cwi.nl
BITNET/EARN: dik@mcvax

wei@hpctdls.HP.COM (Bill Ives) (08/03/89)

    The reason your redirection technic does not work is because
    the '>' operator is a DOS command shell ( among other shells )
    operator... Thus, your command works at the command prompt because
    command.com parses it out and sets up the redirection before
    starting the process ... As it stands now, your spawn command will
    pass the > charater as a command line parameter to the process which
    could look for it-- bad way to do this though.  To do this without
    the shell you will have to set up redirection yourself -- look up
    Dos Dup Handle and Dos Close Handle for information about this...
    If you have access to older ket notes this technic has been covered
    in excessive detail-- I have covered it at least three times myself.
    Email me if you can't figure it out and I'll send you an example..
 
    Bill Ives
    HP CTD

    #include <std-disclaimer> /* I could never speak for HP */

jamespw@mqcomp.oz (Warlow) (08/07/89)

In article <8430@techunix.BITNET> buzy%techunix.bitnet@jade.berkeley.edu (boaz binnun) writes:
>I need to redirect the output of a child process to a file, ...
>what  I did was :
>
>char *args[] = { "child.exe", "argument", ">", "filename", NULL   };
>
>and than:
>
>spawnl(P_WAIT,args[0],args[0],args[1],args[2],args[3],args[4]);

This won't work because the indirection operator > is interpreted by the
shell, NOT by C. spawnl doesn't invoke the shell so the file child.exe
sees the argument '>', which will probably frighten it. If you *really*
want to use indirection, something like
	system("child.exe argument > filename");
will do the trick (but it's awful); otherwise, use fork to explicitly
reset stdout yourself:
	if (fork() == 0) {
		/* child process */
		stdout = freopen("filename", "w", stdout);
		execl(args[0],args[0],args[1],args[4]);
	}
or some such.