1 /* 2 * Copyright (c) 1984-1987 by the Regents of the 3 * University of California and by Gregory Glenn Minshall. 4 * 5 * Permission to use, copy, modify, and distribute these 6 * programs and their documentation for any purpose and 7 * without fee is hereby granted, provided that this 8 * copyright and permission appear on all copies and 9 * supporting documentation, the name of the Regents of 10 * the University of California not be used in advertising 11 * or publicity pertaining to distribution of the programs 12 * without specific prior permission, and notice be given in 13 * supporting documentation that copying and distribution is 14 * by permission of the Regents of the University of California 15 * and by Gregory Glenn Minshall. Neither the Regents of the 16 * University of California nor Gregory Glenn Minshall make 17 * representations about the suitability of this software 18 * for any purpose. It is provided "as is" without 19 * express or implied warranty. 20 */ 21 22 #ifndef lint 23 static char sccsid[] = "@(#)spintc.c 1.6 (Berkeley) 07/17/87"; 24 #endif /* not lint */ 25 26 #include <stdio.h> 27 #include <dos.h> 28 #include <stdlib.h> 29 30 #include "../general/general.h" 31 #include "spint.h" 32 33 #define PSP_ENVIRONMENT 0x2c 34 #define PSP_FCB1 0x5c 35 #define PSP_FCB2 0x6c 36 37 typedef struct { 38 int 39 environment, /* Segment address of environment */ 40 cmd_ptr_offset, /* Offset of command to execute */ 41 cmd_ptr_segment, /* Segment where command lives */ 42 fcb1_ptr_offset, /* Offset of FCB 1 */ 43 fcb1_ptr_segment, /* Segment of FCB 1 */ 44 fcb2_ptr_offset, /* Offset of FCB 2 */ 45 fcb2_ptr_segment; /* Segment of FCB 2 */ 46 } ExecList; 47 48 49 static int int_offset, int_segment; 50 51 52 void 53 spint_finish(spint) 54 Spint *spint; 55 { 56 union REGS regs; 57 struct SREGS sregs; 58 59 if (spint->done == 0) { 60 return; /* Not done yet */ 61 } 62 63 /* 64 * Restore old interrupt handler. 65 */ 66 67 regs.h.ah = 0x25; 68 regs.h.al = spint->int_no; 69 regs.x.dx = int_offset; 70 sregs.ds = int_segment; 71 intdosx(®s, ®s, &sregs); 72 73 if (spint->regs.x.cflag) { 74 fprintf(stderr, "0x%x return code from EXEC.\n", spint->regs.x.ax); 75 spint->done = 1; 76 spint->rc = 99; 77 return; 78 } 79 80 regs.h.ah = 0x4d; /* Get return code */ 81 82 intdos(®s, ®s); 83 84 spint->rc = regs.x.ax; 85 } 86 87 void 88 spint_continue(spint) 89 Spint *spint; 90 { 91 _spint_continue(spint); /* Return to caller */ 92 spint_finish(spint); 93 } 94 95 96 void 97 spint_start(command, spint) 98 char *command; 99 Spint *spint; 100 { 101 ExecList mylist; 102 char *comspec; 103 void _spint_int(); 104 union REGS regs; 105 struct SREGS sregs; 106 107 /* 108 * Get comspec. 109 */ 110 comspec = getenv("COMSPEC"); 111 if (comspec == 0) { /* Can't find where command.com is */ 112 fprintf(stderr, "Unable to find COMSPEC in the environment."); 113 spint->done = 1; 114 spint->rc = 99; /* XXX */ 115 return; 116 } 117 118 /* 119 * Now, hook up our interrupt routine. 120 */ 121 122 regs.h.ah = 0x35; 123 regs.h.al = spint->int_no; 124 intdosx(®s, ®s, &sregs); 125 126 /* Save old routine */ 127 int_offset = regs.x.bx; 128 int_segment = sregs.es; 129 130 regs.h.ah = 0x25; 131 regs.h.al = spint->int_no; 132 regs.x.dx = (int) _spint_int; 133 segread(&sregs); 134 sregs.ds = sregs.cs; 135 intdosx(®s, ®s, &sregs); 136 137 /* 138 * Read in segment registers. 139 */ 140 141 segread(&spint->sregs); 142 143 /* 144 * Set up registers for the EXEC call. 145 */ 146 147 spint->regs.h.ah = 0x4b; 148 spint->regs.h.al = 0; 149 spint->regs.x.dx = (int) comspec; 150 spint->sregs.es = spint->sregs.ds; /* Superfluous, probably */ 151 spint->regs.x.bx = (int) &mylist; 152 153 /* 154 * Set up EXEC parameter list. 155 */ 156 157 ClearElement(mylist); 158 mylist.cmd_ptr_offset = (int) command; 159 mylist.cmd_ptr_segment = spint->sregs.ds; 160 mylist.fcb1_ptr_offset = PSP_FCB1; 161 mylist.fcb1_ptr_segment = _psp; 162 mylist.fcb2_ptr_offset = PSP_FCB2; 163 mylist.fcb2_ptr_segment = _psp; 164 mylist.environment = *((int far *)(((long)_psp<<16)|PSP_ENVIRONMENT)); 165 166 /* 167 * Call to assembly language routine to actually set up for 168 * the spint. 169 */ 170 171 _spint_start(spint); 172 173 spint_finish(spint); 174 } 175