#include "../ntn3270/general.h"
#define PSP_ENVIRONMENT 0x2c
environment
, /* Segment address of environment */
cmd_ptr_offset
, /* Offset of command to execute */
cmd_ptr_segment
, /* Segment where command lives */
fcb1_ptr_offset
, /* Offset of FCB 1 */
fcb1_ptr_segment
, /* Segment of FCB 1 */
fcb2_ptr_offset
, /* Offset of FCB 2 */
fcb2_ptr_segment
; /* Segment of FCB 2 */
int int_offset
, int_segment
;
comspec
= getenv("COMSPEC");
if (comspec
== 0) { /* Can't find where command.com is */
fprintf(stderr
, "Unable to find COMSPEC in the environment.");
spawn
->rc
= 99; /* XXX */
* Now, hook up our interrupt routine.
spawn
->regs
.h
.al
= spawn
->int_no
;
intdosx(&spawn
->regs
, &spawn
->regs
, &spawn
->sregs
);
int_offset
= spawn
->regs
.x
.bx
;
int_segment
= spawn
->sregs
.es
;
spawn
->regs
.h
.al
= spawn
->int_no
;
spawn
->regs
.x
.dx
= (int) int_spawn
;
spawn
->sregs
.ds
= spawn
->sregs
.cs
;
intdosx(&spawn
->regs
, &spawn
->regs
, &spawn
->sregs
);
* Read in segment registers.
* Set up registers for the EXEC call.
spawn
->regs
.x
.dx
= (int) comspec
;
spawn
->sregs
.es
= spawn
->sregs
.ds
; /* Superfluous, probably */
spawn
->regs
.x
.bx
= (int) &mylist
;
* Set up EXEC parameter list.
mylist
.cmd_ptr_offset
= (int) command
;
mylist
.cmd_ptr_segment
= spawn
->sregs
.ds
;
mylist
.fcb1_ptr_offset
= PSP_FCB1
;
mylist
.fcb1_ptr_segment
= _psp
;
mylist
.fcb2_ptr_offset
= PSP_FCB2
;
mylist
.fcb2_ptr_segment
= _psp
;
mylist
.environment
= *((int far
*)(((long)_psp
<<16)|PSP_ENVIRONMENT
));
* Call to assembly language routine to actually set up for
spawn
->done
= 1; /* XXX */
return; /* Not done yet */
if (spawn
->regs
.x
.cflag
) {
fprintf(stderr
, "0x%x return code from EXEC.\n", spawn
->regs
.x
.ax
);
spawn
->regs
.h
.ah
= 0x4d; /* Get return code */
intdos(&spawn
->regs
, &spawn
->regs
);
spawn
->rc
= spawn
->regs
.x
.ax
;
* Restore old interrupt handler.
spawn
->regs
.h
.al
= spawn
->int_no
;
spawn
->regs
.x
.dx
= int_offset
;
spawn
->sregs
.ds
= int_segment
;
intdosx(&spawn
->regs
, &spawn
->regs
, &spawn
->sregs
);
#define INTERRUPT_NUMBER 73
int argc
; /* Number of passed arguments */
char *argv
[]; /* Arguments passed */
char *envp
[]; /* Inherited environment */
static char command
[256];
spawned
.int_no
= INTERRUPT_NUMBER
;
cmdptr
= command
+strlen(command
);
if ((cmdptr
+strlen(*argv
)) >= (command
+sizeof command
)) {
fprintf(stderr
, "Argument list too long at argument *%s*.\n",
*cmdptr
++ = ' '; /* Blank separators */
cmdptr
+= strlen(cmdptr
);
length
= strlen(command
)-1;
* do_spawn() returns when either the command has finished, or when
* the required interrupt comes in. In the latter case, the appropriate
* thing to do is to process the interrupt, and then return to
* the interrupt issuer by calling continue_spawn().
do_spawn(command
, &spawned
);
while (spawned
.done
== 0) {
spawned
.regs
.x
.cflag
= 0; /* No errors (yet) */
switch (spawned
.regs
.h
.ah
) {
spawned
.regs
.x
.bx
+= spawned
.regs
.x
.cx
;
spawned
.regs
.x
.bx
-= spawned
.regs
.x
.cx
;
spawned
.regs
.x
.bx
*= spawned
.regs
.x
.cx
;
spawned
.regs
.x
.bx
/= spawned
.regs
.x
.cx
;
spawned
.regs
.h
.al
= -1; /* Error */
spawned
.regs
.x
.cflag
= 1;
spawned
.regs
.h
.ah
= 0; /* We saw this */
continue_spawn(&spawned
);
fprintf(stderr
, "Process generated a return code of 0x%x.\n",