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