Redirect Output in the Middle of a Program??

Bruce bak at csd-v.UUCP
Wed Apr 27 12:46:29 AEST 1988


In article <2841 at cvl.umd.edu> liuqing at cvl.UUCP (Larry Liuqing Huang) writes:
>
>Is it possible for the C program or Shell to detect the line problem?

The following program (redir) will accomplish what you want.
It is called with the command you wish executed as arguments.
Say you want to call:

$ cmd arg_1 ... arg_n

then you execute the command:

$ redir cmd arg_1 ... arg_n

Included is a sample command (output) which produces plenty of output.
To demo redir build both executables via

$ make redir
$ make output

Then issue the following commands:

$ redir output
762

$ kill -1 1037              # Simulates a hangup and causes output redirection
                            # to file "newout".  Note that during this command
                            # output is streaming to the screen and you will
                            # not be able to see the command being typed.

$ ps                        # get the proc id of the output process.

   PID TTY      TIME COMMAND
    52 cons3    0:33 ksh
   762 cons3    3:07 redir [output]
   763 cons3    0:26 [output]
   773 cons3    0:01 ps

$ kill -15 763              # Simulate software termination of the output
                            # process.  This will cause redir to exit also.

$ head newdir               # print the first few lines of newdir (which will
                            # be pretty big by now).  Note that output should
                            # begin where the screen output left off.


The details of starting this program up on terminal lines and doing similar
redirection of standard error should be fairly straight forward.

The principles used here are explained very lucidly in Rochkind's
admirable book ADVANCED UNIX PROGRAMMING.

The following is redir.c:

#--- cut here ---#--- cut here ---#--- cut here ---#--- cut here ---*
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>


main( argc, argv, envp )
int argc ; char **argv, **envp;
    {
    int i, redir();
    int fpipe[2];
    char c;

    /*
    **      Set signal handler to redirect output on receipt of
    **      SIGHUP.
    */
    signal( SIGHUP, redir );

    /*
    **      Open a pipe for the child to write its standard output to.
    */      And the parent to read it's standard input from.

    if( pipe( fpipe ) == -1 )
        {
        perror( "redir: pipe" );
        exit( 1 );
        }

    switch( fork() )
        {
        case 0:                             /* child process */
        /*
        **      Now exec the child with args.
        */
        close( 1 );
        dup( fpipe[1] );            /* prepare pipe as child's stdout */
        close( fpipe[0] );
        close( fpipe[1] );
        execve( argv[1], &argv[1], envp );
        exit( 1 );

        default:                             /* parent process */
        close( 0 );
        dup( fpipe[0] );            /* prepare pipe as parent's stdin */
        close( fpipe[0] );
        close( fpipe[1] );

        /*
        **      Read child's standard output and write it to parent's
        **      standard output.  Note that initially this is the terminal
        **      but upon receipt of a hangup it will become the file newout
        **      ( see the signal handler below).
        */
        while( read( 0, &c, 1 ) ) write( 1, &c, 1 );

        /*
        **      Exit when the pipe is closed by the child.
        */
        exit( 0 );
        }
    }


int redir()                 /* Handle receipt of SIGHUP */
    {
    int fout;

    /*
    **      Create the output file newout.
    */
    if( ( fout = open( "newout", O_WRONLY | O_CREAT, 0666 ) ) < 0 )
        {
        perror( "redir: open" );
        exit( 1 );
        }

    /*
    **      Close stdout and dup the file just opened.
    **      Upon return from this signal handler, the new
    **      file will become the redirected stdoutput file.
    */
    close( 1 );
    if( dup( fout ) == -1 )
        {
        perror( "redir: dup" );
        exit( 2 );
        }
    }
#--- cut here ---#--- cut here ---#--- cut here ---#--- cut here ---*

This is output.c:
#--- cut here ---#--- cut here ---#--- cut here ---#--- cut here ---*

#include <stdio.h>

main()              /* Sample application to produce lots of output */
    {
    int i=0;
    while( 1 ) fprintf( stdout, "%d\n", i++ );
    }
-- 
  Bruce Kern                                 |  uunet!swlabs!csd-v!bak  
  Computer Systems Design                    |  1-203-270-0399          
  29 High Rock Rd., Sandy Hook, Ct. 06482    |  This space for rent.    



More information about the Comp.unix.wizards mailing list