Process Control/Pipe Tutorial
From EDM2
This is a short tutorial on spawning a background process, and reading its standard output through a pipe.
- All examples have been compiled with Open Watcom.
The following is a simple program that spawn a subprocess, and reads its standard 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; }