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