home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 11 Util
/
11-Util.zip
/
doscall.zip
/
doscall.c
next >
Wrap
C/C++ Source or Header
|
2000-10-15
|
6KB
|
176 lines
/* 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 );
}