batserv.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 221 行
C
221 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: OS/2 Spawn server for Viper (IDE).
*
****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <process.h>
#include <ctype.h>
#include <sys/types.h>
#include <direct.h>
#define INCL_DOSNMPIPES
#define INCL_DOSPROCESS
#define INCL_DOSFILEMGR
#define INCL_DOSERRORS
#define INCL_DOSEXCEPTIONS
#include <os2.h>
#include "batpipe.h"
HPIPE LnkHdl;
HPIPE RedirHdl;
char RedirName[ PREFIX_LEN + MAX_NAME + 1];
unsigned CmdStatus;
char *CmdProc;
unsigned ProcId;
static void RunCmd( char *cmd_name )
{
char cmd[MAX_TRANS+80];
RESULTCODES res;
UINT rc;
//NYI: spawning of DOS and PM programs
//DOS programs can be handled by quoting the redirection
//operators:
// prog 1^>out 2^>&1
sprintf( cmd, "%s%c/C %s 0<NUL 1>%s 2>&1%c", CmdProc, 0, cmd_name, RedirName, 0 );
rc = DosExecPgm( NULL, 0, /* don't care about fail name */
EXEC_ASYNCRESULT, /* execflags */
cmd, /* args */
NULL, /* inherit environment */
&res, /* result codes */
CmdProc ); /* pgmname */
if( rc == 0 ) {
ProcId = res.codeTerminate;
} else {
ProcId = 0;
}
}
static void SendStatus( unsigned long status )
{
struct {
unsigned char cmd;
unsigned long stat;
} buff;
ULONG dummy;
buff.cmd = LNK_STATUS;
buff.stat = status;
DosWrite( LnkHdl, &buff, sizeof( buff ), &dummy );
}
static void ProcessConnection( void )
{
char buff[MAX_TRANS];
ULONG bytes_read;
unsigned long max;
struct _AVAILDATA BytesAvail;
ULONG PipeState;
APIRET rc;
RESULTCODES res;
PID dummy;
char *dir;
for( ;; ) {
DosRead( LnkHdl, buff, sizeof( buff ), &bytes_read );
if( bytes_read == 0 ) break;
buff[bytes_read] = '\0';
switch( buff[0] ) {
case LNK_CWD:
rc = 0;
dir = &buff[1];
if( isalpha( dir[0] ) && dir[1] == ':' ) {
rc = DosSetDefaultDisk( toupper( dir[0] ) - ('A' - 1) );
dir += 2;
}
if( rc == 0 && dir[0] != '\0' ) {
rc = DosSetCurrentDir( dir );
}
SendStatus( rc );
break;
case LNK_RUN:
DosSetNPHState( RedirHdl, NP_NOWAIT | NP_READMODE_BYTE );
DosConnectNPipe( RedirHdl );
DosSetNPHState( RedirHdl, NP_WAIT | NP_READMODE_BYTE );
RunCmd( &buff[1] );
break;
case LNK_QUERY:
max = *(unsigned long *)&buff[1];
if( max > sizeof( buff ) ) max = sizeof( buff );
--max;
rc = DosPeekNPipe(RedirHdl, buff, 0, &bytes_read,
&BytesAvail, &PipeState );
if( rc == 0 && BytesAvail.cbpipe != 0 ) {
DosRead( RedirHdl, &buff[1], max, &bytes_read );
buff[0] = LNK_OUTPUT;
DosWrite( LnkHdl, buff, bytes_read + 1, &bytes_read );
} else {
rc = DosWaitChild( DCWA_PROCESS, DCWW_NOWAIT, &res,
&dummy, ProcId );
if( rc != ERROR_CHILD_NOT_COMPLETE ) {
DosDisConnectNPipe( RedirHdl );
SendStatus( res.codeResult );
ProcId = 0;
} else {
/* let someone else run */
DosSleep( 1 );
buff[0] = LNK_NOP;
DosWrite( LnkHdl, buff, 1, &bytes_read );
}
}
break;
case LNK_CANCEL:
DosSendSignalException( ProcId, XCPT_SIGNAL_INTR );
break;
case LNK_ABORT:
DosKillProcess( DKP_PROCESSTREE, ProcId );
break;
case LNK_DONE:
return;
case LNK_SHUTDOWN:
exit( 0 );
break;
}
}
}
void main( int argc, char *argv[] )
{
APIRET rc;
HFILE h;
unsigned long actiontaken;
unsigned long sent;
char done;
if( argc > 1 && (argv[1][0] == 'q' || argv[1][0] == 'Q') ) {
rc = DosOpen( PREFIX DEFAULT_NAME, &h, &actiontaken, 0ul,
0, 0x01, 0x41, 0ul );
if( rc == 0 ) {
done = LNK_SHUTDOWN;
DosWrite( h, &done, sizeof( done ), &sent );
DosClose( h );
}
exit( 0 );
}
CmdProc = getenv( "COMSPEC" );
if( CmdProc == NULL ) {
fprintf( stderr, "Unable to find command processor\n" );
exit( 1 );
}
//NYI: need to accept name for link pipe
rc = DosCreateNPipe( PREFIX DEFAULT_NAME, &LnkHdl,
NP_NOINHERIT | NP_NOWRITEBEHIND | NP_ACCESS_DUPLEX,
NP_WAIT | NP_READMODE_MESSAGE | NP_TYPE_MESSAGE | 1,
MAX_TRANS, MAX_TRANS, 0 );
if( rc != 0 ) {
fprintf( stderr, "Unable to create link pipe\n" );
exit( 1 );
}
sprintf( RedirName, PREFIX "%d", getpid() );
rc = DosCreateNPipe( RedirName, &RedirHdl,
NP_NOINHERIT | NP_WRITEBEHIND | NP_ACCESS_INBOUND,
NP_WAIT | NP_READMODE_BYTE | NP_TYPE_BYTE | 1,
MAX_TRANS, MAX_TRANS, 0 );
if( rc != 0 ) {
fprintf( stderr, "Unable to create redirection pipe\n" );
exit( 1 );
}
DosSetFHState( LnkHdl, OPEN_FLAGS_NOINHERIT );
DosSetFHState( RedirHdl, OPEN_FLAGS_NOINHERIT );
for( ;; ) {
rc = DosConnectNPipe( LnkHdl );
if( rc == 0 ) {
ProcessConnection();
DosDisConnectNPipe( LnkHdl );
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?