Jump to content

Process Control/Pipe Tutorial: Difference between revisions

From EDM2
Created page with "By Johann Oskarsson This is a short tutorial on spawning a background process, and reading it's standard output through a pipe. * All examples have been com..."
 
mNo edit summary
Line 26: Line 26:
  int main( int argc, char *argv[] )
  int main( int argc, char *argv[] )
  {
  {
HFILE pipe1_in = 0, pipe1_out = 0;
        HFILE pipe1_in = 0, pipe1_out = 0;
DosCreatePipe( &pipe1_in, &pipe1_out, 50 );
        DosCreatePipe( &pipe1_in, &pipe1_out, 50 );
   
   
   
   
// And to prevent the child process from inheriting
        // And to prevent the child process from inheriting
// the read handle of the pipe.
        // the read handle of the pipe.
unsigned long int m;
        unsigned long int m;
DosQueryFHState( pipe1_in, &m );
        DosQueryFHState( pipe1_in, &m );
// bits 0-6, 8-11, 15 must be 0
        // bits 0-6, 8-11, 15 must be 0
// that is, only the following flags are legal
        // that is, only the following flags are legal
// in DosSetFHState()
        // in DosSetFHState()
unsigned long int mask = open_flags_write_through |
        unsigned long int mask = open_flags_write_through |
open_fail_on_error |
                open_fail_on_error |
open_flags_no_cache |
                open_flags_no_cache |
open_flags_no_inherit;
                open_flags_no_inherit;
m &= mask;  
        m &= mask;  
m |= open_flags_no_inherit;
        m |= open_flags_no_inherit;
DosSetFHState( pipe1_in, m );
        DosSetFHState( pipe1_in, m );


// Duplicate standard output
        // Duplicate standard output
HFILE mystdout = -1;
        HFILE mystdout = -1;
DosDupHandle( 1, &mystdout );
        DosDupHandle( 1, &mystdout );
// Close STDOUT since otherwise the subprocess will inherit it.
        // Close STDOUT since otherwise the subprocess will inherit it.
// After this, using printf will not work, but writing to
        // After this, using printf will not work, but writing to
// mystdout will have the same effeccts.
        // mystdout will have the same effeccts.
DosClose( 1 );
        DosClose( 1 );


// On second thought, the above DosClose() is probably redundant
        // On second thought, the above DosClose() is probably redundant
// since DosDupHandle will close it as well, but it doesn't hurt.
        // since DosDupHandle will close it as well, but it doesn't hurt.
        // Set STDOUT of child process
        HFILE childout = 1;
        DosDupHandle( pipe1_out, &childout );
        // Spawn process
        char buffer[25];
        RESULTCODES res;
        DosExecPgm( buffer, 25, EXEC_ASYNCRESULT, 0, 0, &res, "hello.exe" );


// Set STDOUT of child process
HFILE childout = 1;
DosDupHandle( pipe1_out, &childout );


// Spawn process
        // Read output of subprocess
char buffer[25];
        char rbuffer[100];
RESULTCODES res;
        ULONG bread = 0;
DosExecPgm( buffer, 25, EXEC_ASYNCRESULT, 0, 0,
        DosRead( pipe1_in, rbuffer, 100, &bread );
&res, "hello.exe" );
 
 
        // Print the output to STDOUT
 
        DosWrite( mystdout, rbuffer, bread, &bread );
// Read output of subprocess
char rbuffer[100];
        PID p;
ULONG bread = 0;
        // Wait for child process to terminate
DosRead( pipe1_in, rbuffer, 100, &bread );
        DosWaitChild( DCWA_PROCESS, DCWW_WAIT, &res, &p, res.codeTerminate );
 
// Print the output to STDOUT
DosWrite( mystdout, rbuffer, bread, &bread );
 
PID p;
// Wait for child process to terminate
DosWaitChild( DCWA_PROCESS, DCWW_WAIT,
&res, &p, res.codeTerminate );


// and return the exit code of the child
        // and return the exit code of the child
return res.codeResult;
        return res.codeResult;
   
   
  }
  }
      
      
[[Category:Languages Articles]]
[[Category:Languages Articles]]

Revision as of 15:14, 22 May 2012

By Johann Oskarsson

This is a short tutorial on spawning a background process, and reading it's standard output through a pipe.

The following is a simple program that spawn a subprocess, and reads its standad output, which it then writes out again. It does lack error checking and variable names could be better. It is also meant to be used with the classic "Hello, World" program that prints to STDOUT, not the VIO hello-world example. It does not matter what programming language is used to create it, only the executable has to be "HELLO.EXE". If you need to call the executable something else, you'll need to modify the DosExecPgm() call.

#define INCL_DOSQUEUES
#define INCL_DOSPROCESS
#define INCL_DOSFILEMGR
#include <os2.h>

// The reason I'm using my own constants, as opposed to the ones
// defined in os2.h, is that their definition seems to conflict
// with my use of the | operator.
const unsigned long int open_flags_dasd = 0x8000; // bit 15
const unsigned long int open_flags_write_through = 0x4000; //bit 14
const unsigned long int open_fail_on_error = 0x2000; // bit 13
const unsigned long int open_flags_no_cache = 0x1000; // bit 12

// ... irrelevant constants skipped ...

const unsigned long int open_flags_no_inherit = 0x0080; // bit 7

int main( int argc, char *argv[] )
{
       HFILE pipe1_in = 0, pipe1_out = 0;
       DosCreatePipe( &pipe1_in, &pipe1_out, 50 );


       // And to prevent the child process from inheriting
       // the read handle of the pipe.
       unsigned long int m;
       DosQueryFHState( pipe1_in, &m );
       // bits 0-6, 8-11, 15 must be 0
       // that is, only the following flags are legal
       // in DosSetFHState()
       unsigned long int mask = open_flags_write_through |
               open_fail_on_error |
               open_flags_no_cache |
               open_flags_no_inherit;
       m &= mask; 
       m |= open_flags_no_inherit;
       DosSetFHState( pipe1_in, m );


       // Duplicate standard output
       HFILE mystdout = -1;
       DosDupHandle( 1, &mystdout );
       // Close STDOUT since otherwise the subprocess will inherit it.
       // After this, using printf will not work, but writing to
       // mystdout will have the same effeccts.
       DosClose( 1 );
       // On second thought, the above DosClose() is probably redundant
       // since DosDupHandle will close it as well, but it doesn't hurt.

       // Set STDOUT of child process
       HFILE childout = 1;
       DosDupHandle( pipe1_out, &childout );

       // Spawn process
       char buffer[25];
       RESULTCODES res;
       DosExecPgm( buffer, 25, EXEC_ASYNCRESULT, 0, 0, &res, "hello.exe" );


       // Read output of subprocess
       char rbuffer[100];
       ULONG bread = 0;
       DosRead( pipe1_in, rbuffer, 100, &bread );
 
       // Print the output to STDOUT
       DosWrite( mystdout, rbuffer, bread, &bread );

       PID p;
       // Wait for child process to terminate
       DosWaitChild( DCWA_PROCESS, DCWW_WAIT, &res, &p, res.codeTerminate );
       // and return the exit code of the child
       return res.codeResult;

}