home *** CD-ROM | disk | FTP | other *** search
- /* get stdout, stderr, and rc from DOS session - theory: */
- /* 1: OS/2 side creates two unique inbound named pipes */
- /* 2: OS/2 side creates a start thread and waits for connect */
- /* 3: start thread starts DOS session and terminates */
- /* 4: DOS session opens named pipes as stdout and stderr */
- /* 5: DOS session spawns whatever DOS program and arguments */
- /* 6: OS/2 side copies pipe input to OS/2 stdout and stderr */
- /* 7: DOS program dies, DOS session gets return code */
- /* 8: DOS session writes NUL + rc to stderr and terminates */
- /* 9: OS/2 side finds rc and uses it as its return code */
- /* 0: any OS/2 errors reported on stderr before termination, */
- /* any DOS spawn errno reported via pipe with error message */
-
- #include <stddef.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <process.h>
- #include <io.h>
- #include <fcntl.h>
- #define INCL_NOPMAPI
- #define INCL_BASE
- #include <os2.h>
-
- #define STK 8192
- #define NPL 8192
- #ifndef UNUSED
- #define UNUSED(x) (void)(x)
- #endif
- #define EMSG( x ) emsg( x, __LINE__ )
-
- static char PName[] = "\\PIPE\\12345678.DC?";
- static char OsMsg[ 132 ];
- static char Stack[ STK *3 ]; /* schild, reader+writer */
- static char RBuff[ NPL ], WBuff[ NPL ];
- static STARTDATA Start;
- static HPIPE pipe[ 3 ];
- static char * name;
-
- /* ------------------------------------------------------------- */
-
- int emsg( char *msg, int line )
- {
- fprintf( stderr, "\n%s (%s %d)\n", name, __FILE__, line );
- if ( msg ) fprintf( stderr, "\t%s\n", msg );
- if ( errno ) fprintf( stderr, "\t%s\n", strerror( errno ));
- return EXIT_FAILURE;
- }
- /* ------------------------------------------------------------- */
-
- char * SysMsg( APIRET rc ) /* many error codes not */
- { /* decoded in OSO001.MSG */
- ULONG ulen = 0; /* e.g. 294, 309, ... */
-
- if ( DosGetMessage( 0, 0, OsMsg, sizeof OsMsg,
- rc, "OSO001.msg", &ulen ))
- sprintf( OsMsg, "system error code %d", rc );
- return OsMsg;
- }
- /* ------------------------------------------------------------- */
-
- void schild( void *arg )
- {
- APIRET rc; int n = 0;
- ULONG x; UNUSED( arg );
-
- Start.Length = 32; /* more requires PM (?) */
- Start.PgmName = name; /* start own DOS stub */
- Start.PgmInputs = PName;
- Start.Related = SSF_RELATED_CHILD;
- Start.FgBg = SSF_FGBG_BACK;
- Start.InheritOpt = SSF_INHERTOPT_PARENT;
- Start.SessionType = SSF_TYPE_VDM;
-
- while ( n < 3 ) /* check handles 0, 1, 2 */
- if ( DosQueryNPHState( pipe[ n ], &x ))
- DosSleep( 0 ); /* if not yet ready wait */
- else ++n;
-
- rc = DosStartSession( &Start, &x, (PID *) &x );
- if ( rc ) DosExit( EXIT_PROCESS, EMSG( SysMsg( rc )));
- }
- /* ------------------------------------------------------------- */
-
- void reader( void *arg )
- {
- int in = 1 + strlen( RBuff );
- APIRET rc = DosConnectNPipe( pipe[ 0 ] );
- ULONG uw; ; UNUSED( arg );
-
- if ( ! rc ) rc = DosWrite( pipe[ 0 ], &in, 2, &uw );
- if ( ! rc ) rc = DosWrite( pipe[ 0 ], RBuff, in, &uw );
- if ( rc ) DosExit( EXIT_PROCESS, EMSG( SysMsg( rc )));
-
- if ( ! isatty( 0 )) while ( ! rc )
- {
- in = read( 0, RBuff, sizeof RBuff );
- if ( in <= 0 ) break;
- rc = DosWrite( pipe[ 0 ], RBuff, in, &uw );
- }
-
- DosClose( pipe[ 0 ] ); close( 0 );
- }
- /* ------------------------------------------------------------- */
-
- void writer( void *arg )
- {
- APIRET rc = DosConnectNPipe( pipe[ 1 ]);
- ULONG uw = 1; UNUSED( arg );
-
- while ( ! rc && uw )
- {
- rc = DosRead( pipe[ 1 ], WBuff, sizeof WBuff, &uw );
- if ( ! rc && uw != write( 1, WBuff, uw ))
- DosExit( EXIT_PROCESS, EMSG( "output lost" ));
- }
- if ( rc ) DosExit( EXIT_PROCESS, EMSG( SysMsg( rc )));
- }
- /* ------------------------------------------------------------- */
-
- int rundos( TID w )
- {
- APIRET rc = DosConnectNPipe( pipe[ 2 ]);
- ULONG uw; /* ex[ 0 ] = 0 if DOS rc */
- char ex[ 3 ]; memset( ex, 11, 3 );
-
- while ( ! rc )
- {
- rc = DosRead( pipe[ 2 ], ex +2, 1, &uw );
- if ( rc || ! uw ) break;
- if ( ! memchr( ex, 0, 3 )) fputc( ex[ 2 ], stderr );
- memmove( ex, ex +1, 2 );
- }
- if ( rc ) return EMSG( SysMsg( rc ));
-
- DosWaitThread( &w, DCWW_WAIT ); /* drain writer() thread */
- if ( ex[ 0 ]) /* char DOS rc after NUL */
- return EMSG( "DOS return code lost" );
- else return (int)(signed char) ex[ 1 ];
- }
- /* ------------------------------------------------------------- */
-
- int main( int argc, char * argv[] )
- {
- APIRET rc; TID s, r, w; int n;
-
- name = argv[ 0 ];
-
- sprintf( Stack, "%8.8x", getpid());
- memcpy( PName + 6, Stack, 8 );
-
- if ( argc < 2 )
- return EMSG( "specify DOS program" );
- if ( sizeof RBuff <= strlen( getcmd( Stack )))
- return EMSG( "too many arguments" );
- strcpy( RBuff, Stack );
-
- for ( n = 0; n < 3; ++n )
- {
- PName[ 17 ] = n + '0';
- if ( n )
- rc = DosCreateNPipe( PName, &pipe[ n ],
- NP_ACCESS_INBOUND , 1, NPL, 0, 1 );
- else rc = DosCreateNPipe( PName, &pipe[ n ],
- NP_ACCESS_OUTBOUND, 1, 0, NPL, 1 );
- if ( rc ) return EMSG( SysMsg( rc ));
- }
-
- r = _beginthread( reader, Stack + 0 * STK, STK, NULL );
- w = _beginthread( writer, Stack + 1 * STK, STK, NULL );
- s = _beginthread( schild, Stack + 2 * STK, STK, NULL );
- if ( r == -1 || w == -1 || s == -1 )
- return EMSG( SysMsg( _doserrno ));
- else return rundos( w );
- }
-