1 #include <stdio.h> 2 #include <dos.h> 3 #include <stdlib.h> 4 5 #include "../general/general.h" 6 #include "spint.h" 7 8 #define PSP_ENVIRONMENT 0x2c 9 #define PSP_FCB1 0x5c 10 #define PSP_FCB2 0x6c 11 12 typedef struct { 13 int 14 environment, /* Segment address of environment */ 15 cmd_ptr_offset, /* Offset of command to execute */ 16 cmd_ptr_segment, /* Segment where command lives */ 17 fcb1_ptr_offset, /* Offset of FCB 1 */ 18 fcb1_ptr_segment, /* Segment of FCB 1 */ 19 fcb2_ptr_offset, /* Offset of FCB 2 */ 20 fcb2_ptr_segment; /* Segment of FCB 2 */ 21 } ExecList; 22 23 24 static int int_offset, int_segment; 25 26 27 void 28 spint_finish(spint) 29 Spint *spint; 30 { 31 union REGS regs; 32 struct SREGS sregs; 33 34 if (spint->done == 0) { 35 return; /* Not done yet */ 36 } 37 38 /* 39 * Restore old interrupt handler. 40 */ 41 42 regs.h.ah = 0x25; 43 regs.h.al = spint->int_no; 44 regs.x.dx = int_offset; 45 sregs.ds = int_segment; 46 intdosx(®s, ®s, &sregs); 47 48 if (spint->regs.x.cflag) { 49 fprintf(stderr, "0x%x return code from EXEC.\n", spint->regs.x.ax); 50 spint->done = 1; 51 spint->rc = 99; 52 return; 53 } 54 55 regs.h.ah = 0x4d; /* Get return code */ 56 57 intdos(®s, ®s); 58 59 spint->rc = regs.x.ax; 60 } 61 62 void 63 spint_continue(spint) 64 Spint *spint; 65 { 66 _spint_continue(spint); /* Return to caller */ 67 spint_finish(spint); 68 } 69 70 71 void 72 spint_start(command, spint) 73 char *command; 74 Spint *spint; 75 { 76 ExecList mylist; 77 char *comspec; 78 void _spint_int(); 79 union REGS regs; 80 struct SREGS sregs; 81 82 /* 83 * Get comspec. 84 */ 85 comspec = getenv("COMSPEC"); 86 if (comspec == 0) { /* Can't find where command.com is */ 87 fprintf(stderr, "Unable to find COMSPEC in the environment."); 88 spint->done = 1; 89 spint->rc = 99; /* XXX */ 90 return; 91 } 92 93 /* 94 * Now, hook up our interrupt routine. 95 */ 96 97 regs.h.ah = 0x35; 98 regs.h.al = spint->int_no; 99 intdosx(®s, ®s, &sregs); 100 101 /* Save old routine */ 102 int_offset = regs.x.bx; 103 int_segment = sregs.es; 104 105 regs.h.ah = 0x25; 106 regs.h.al = spint->int_no; 107 regs.x.dx = (int) _spint_int; 108 segread(&sregs); 109 sregs.ds = sregs.cs; 110 intdosx(®s, ®s, &sregs); 111 112 /* 113 * Read in segment registers. 114 */ 115 116 segread(&spint->sregs); 117 118 /* 119 * Set up registers for the EXEC call. 120 */ 121 122 spint->regs.h.ah = 0x4b; 123 spint->regs.h.al = 0; 124 spint->regs.x.dx = (int) comspec; 125 spint->sregs.es = spint->sregs.ds; /* Superfluous, probably */ 126 spint->regs.x.bx = (int) &mylist; 127 128 /* 129 * Set up EXEC parameter list. 130 */ 131 132 ClearElement(mylist); 133 mylist.cmd_ptr_offset = (int) command; 134 mylist.cmd_ptr_segment = spint->sregs.ds; 135 mylist.fcb1_ptr_offset = PSP_FCB1; 136 mylist.fcb1_ptr_segment = _psp; 137 mylist.fcb2_ptr_offset = PSP_FCB2; 138 mylist.fcb2_ptr_segment = _psp; 139 mylist.environment = *((int far *)(((long)_psp<<16)|PSP_ENVIRONMENT)); 140 141 /* 142 * Call to assembly language routine to actually set up for 143 * the spint. 144 */ 145 146 _spint_start(spint); 147 148 spint_finish(spint); 149 } 150