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
spint_finish(spint)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
spint_continue(spint)74 spint_continue(spint)
75 Spint *spint;
76 {
77 _spint_continue(spint); /* Return to caller */
78 spint_finish(spint);
79 }
80
81
82 void
spint_start(command,spint)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