Commit | Line | Data |
---|---|---|
992de934 GM |
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 | |
c578271f | 23 | static char sccsid[] = "@(#)spintc.c 3.1 (Berkeley) %G%"; |
992de934 GM |
24 | #endif /* not lint */ |
25 | ||
211e0a3a GM |
26 | #include <stdio.h> |
27 | #include <dos.h> | |
28 | #include <stdlib.h> | |
29 | ||
f478095f | 30 | #include "../general/general.h" |
4599d553 | 31 | #include "spint.h" |
211e0a3a GM |
32 | |
33 | #define PSP_ENVIRONMENT 0x2c | |
34 | #define PSP_FCB1 0x5c | |
35 | #define PSP_FCB2 0x6c | |
36 | ||
211e0a3a GM |
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 | ||
84f75426 GM |
48 | |
49 | static int int_offset, int_segment; | |
50 | ||
51 | ||
211e0a3a | 52 | void |
84f75426 GM |
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) | |
211e0a3a | 98 | char *command; |
84f75426 | 99 | Spint *spint; |
211e0a3a GM |
100 | { |
101 | ExecList mylist; | |
102 | char *comspec; | |
84f75426 GM |
103 | void _spint_int(); |
104 | union REGS regs; | |
105 | struct SREGS sregs; | |
211e0a3a GM |
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."); | |
84f75426 GM |
113 | spint->done = 1; |
114 | spint->rc = 99; /* XXX */ | |
211e0a3a GM |
115 | return; |
116 | } | |
117 | ||
118 | /* | |
119 | * Now, hook up our interrupt routine. | |
120 | */ | |
121 | ||
84f75426 GM |
122 | regs.h.ah = 0x35; |
123 | regs.h.al = spint->int_no; | |
124 | intdosx(®s, ®s, &sregs); | |
211e0a3a GM |
125 | |
126 | /* Save old routine */ | |
84f75426 GM |
127 | int_offset = regs.x.bx; |
128 | int_segment = sregs.es; | |
211e0a3a | 129 | |
84f75426 GM |
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); | |
211e0a3a GM |
136 | |
137 | /* | |
138 | * Read in segment registers. | |
139 | */ | |
140 | ||
84f75426 | 141 | segread(&spint->sregs); |
211e0a3a GM |
142 | |
143 | /* | |
144 | * Set up registers for the EXEC call. | |
145 | */ | |
146 | ||
84f75426 GM |
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; | |
211e0a3a GM |
152 | |
153 | /* | |
154 | * Set up EXEC parameter list. | |
155 | */ | |
156 | ||
157 | ClearElement(mylist); | |
158 | mylist.cmd_ptr_offset = (int) command; | |
84f75426 | 159 | mylist.cmd_ptr_segment = spint->sregs.ds; |
211e0a3a GM |
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 | |
84f75426 | 168 | * the spint. |
211e0a3a GM |
169 | */ |
170 | ||
84f75426 | 171 | _spint_start(spint); |
211e0a3a | 172 | |
84f75426 | 173 | spint_finish(spint); |
211e0a3a | 174 | } |