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