1*31151Sminshall #define	LINT_ARGS
2*31151Sminshall 
3*31151Sminshall #include <stdio.h>
4*31151Sminshall #include <dos.h>
5*31151Sminshall #include <stdlib.h>
6*31151Sminshall 
7*31151Sminshall #include "../ntn3270/general.h"
8*31151Sminshall 
9*31151Sminshall #define	PSP_ENVIRONMENT		0x2c
10*31151Sminshall #define	PSP_FCB1		0x5c
11*31151Sminshall #define	PSP_FCB2		0x6c
12*31151Sminshall 
13*31151Sminshall #define	INTERRUPT_NUMBER	73
14*31151Sminshall 
15*31151Sminshall typedef struct {
16*31151Sminshall     int
17*31151Sminshall 	environment,		/* Segment address of environment */
18*31151Sminshall 	cmd_ptr_offset,		/* Offset of command to execute */
19*31151Sminshall 	cmd_ptr_segment,	/* Segment where command lives */
20*31151Sminshall 	fcb1_ptr_offset,	/* Offset of FCB 1 */
21*31151Sminshall 	fcb1_ptr_segment,	/* Segment of FCB 1 */
22*31151Sminshall 	fcb2_ptr_offset,	/* Offset of FCB 2 */
23*31151Sminshall 	fcb2_ptr_segment;	/* Segment of FCB 2 */
24*31151Sminshall } ExecList;
25*31151Sminshall 
26*31151Sminshall typedef struct {
27*31151Sminshall     union REGS		regs;
28*31151Sminshall     struct SREGS	sregs;
29*31151Sminshall     int			int_no;	/* Which interrupt to wait on */
30*31151Sminshall     int			done;	/* Are we done, or just took an interrupt? */
31*31151Sminshall     int			rc;	/* return code */
32*31151Sminshall } Spawn;
33*31151Sminshall 
34*31151Sminshall 
35*31151Sminshall void
36*31151Sminshall do_spawn(command, spawn)
37*31151Sminshall char *command;
38*31151Sminshall Spawn *spawn;
39*31151Sminshall {
40*31151Sminshall     ExecList mylist;
41*31151Sminshall     char *comspec;
42*31151Sminshall     void int_spawn();
43*31151Sminshall     int int_offset, int_segment;
44*31151Sminshall 
45*31151Sminshall     /*
46*31151Sminshall      * Get comspec.
47*31151Sminshall      */
48*31151Sminshall     comspec = getenv("COMSPEC");
49*31151Sminshall     if (comspec == 0) {			/* Can't find where command.com is */
50*31151Sminshall 	fprintf(stderr, "Unable to find COMSPEC in the environment.");
51*31151Sminshall 	spawn->done = 1;
52*31151Sminshall 	spawn->rc = 99;	/* XXX */
53*31151Sminshall 	return;
54*31151Sminshall     }
55*31151Sminshall 
56*31151Sminshall     /*
57*31151Sminshall      * Now, hook up our interrupt routine.
58*31151Sminshall      */
59*31151Sminshall 
60*31151Sminshall     spawn->regs.h.ah = 0x35;
61*31151Sminshall     spawn->regs.h.al = spawn->int_no;
62*31151Sminshall     intdosx(&spawn->regs, &spawn->regs, &spawn->sregs);
63*31151Sminshall 
64*31151Sminshall     /* Save old routine */
65*31151Sminshall     int_offset = spawn->regs.x.bx;
66*31151Sminshall     int_segment = spawn->sregs.es;
67*31151Sminshall 
68*31151Sminshall     spawn->regs.h.ah = 0x25;
69*31151Sminshall     spawn->regs.h.al = spawn->int_no;
70*31151Sminshall     spawn->regs.x.dx = (int) int_spawn;
71*31151Sminshall     segread(&spawn->sregs);
72*31151Sminshall     spawn->sregs.ds = spawn->sregs.cs;
73*31151Sminshall     intdosx(&spawn->regs, &spawn->regs, &spawn->sregs);
74*31151Sminshall 
75*31151Sminshall     /*
76*31151Sminshall      * Read in segment registers.
77*31151Sminshall      */
78*31151Sminshall 
79*31151Sminshall     segread(&spawn->sregs);
80*31151Sminshall 
81*31151Sminshall     /*
82*31151Sminshall      * Set up registers for the EXEC call.
83*31151Sminshall      */
84*31151Sminshall 
85*31151Sminshall     spawn->regs.h.ah = 0x4b;
86*31151Sminshall     spawn->regs.h.al = 0;
87*31151Sminshall     spawn->regs.x.dx = (int) comspec;
88*31151Sminshall     spawn->sregs.es = spawn->sregs.ds;		/* Superfluous, probably */
89*31151Sminshall     spawn->regs.x.bx = (int) &mylist;
90*31151Sminshall 
91*31151Sminshall     /*
92*31151Sminshall      * Set up EXEC parameter list.
93*31151Sminshall      */
94*31151Sminshall 
95*31151Sminshall     ClearElement(mylist);
96*31151Sminshall     mylist.cmd_ptr_offset = (int) command;
97*31151Sminshall     mylist.cmd_ptr_segment = spawn->sregs.ds;
98*31151Sminshall     mylist.fcb1_ptr_offset = PSP_FCB1;
99*31151Sminshall     mylist.fcb1_ptr_segment = _psp;
100*31151Sminshall     mylist.fcb2_ptr_offset = PSP_FCB2;
101*31151Sminshall     mylist.fcb2_ptr_segment = _psp;
102*31151Sminshall     mylist.environment = *((int far *)(((long)_psp<<16)|PSP_ENVIRONMENT));
103*31151Sminshall 
104*31151Sminshall     /*
105*31151Sminshall      * Call to assembly language routine to actually set up for
106*31151Sminshall      * the spawn.
107*31151Sminshall      */
108*31151Sminshall 
109*31151Sminshall     start_spawn(spawn);
110*31151Sminshall     spawn->done = 1;			/* XXX */
111*31151Sminshall 
112*31151Sminshall     if (spawn->done == 0) {
113*31151Sminshall 	return;				/* Not done yet */
114*31151Sminshall     }
115*31151Sminshall 
116*31151Sminshall     if (spawn->regs.x.cflag) {
117*31151Sminshall 	fprintf(stderr, "0x%x return code from EXEC.\n", spawn->regs.x.ax);
118*31151Sminshall 	spawn->done = 1;
119*31151Sminshall 	spawn->rc = 99;
120*31151Sminshall 	return;
121*31151Sminshall     }
122*31151Sminshall 
123*31151Sminshall     spawn->regs.h.ah = 0x4d;			/* Get return code */
124*31151Sminshall 
125*31151Sminshall     intdos(&spawn->regs, &spawn->regs);
126*31151Sminshall 
127*31151Sminshall     spawn->rc = spawn->regs.x.ax;
128*31151Sminshall 
129*31151Sminshall     /*
130*31151Sminshall      * Restore old interrupt handler.
131*31151Sminshall      */
132*31151Sminshall 
133*31151Sminshall     spawn->regs.h.ah = 0x25;
134*31151Sminshall     spawn->regs.h.al = spawn->int_no;
135*31151Sminshall     spawn->regs.x.dx = int_offset;
136*31151Sminshall     spawn->sregs.ds = int_segment;
137*31151Sminshall     intdosx(&spawn->regs, &spawn->regs, &spawn->sregs);
138*31151Sminshall }
139*31151Sminshall 
140*31151Sminshall main(argc, argv, envp)
141*31151Sminshall int	argc;				/* Number of passed arguments */
142*31151Sminshall char	*argv[];			/* Arguments passed */
143*31151Sminshall char	*envp[];			/* Inherited environment */
144*31151Sminshall {
145*31151Sminshall     Spawn spawned;
146*31151Sminshall     static char command[256];
147*31151Sminshall 
148*31151Sminshall     ClearElement(spawned);
149*31151Sminshall     spawned.int_no = INTERRUPT_NUMBER;
150*31151Sminshall     if (argc == 1) {
151*31151Sminshall 	command[0] = 0;
152*31151Sminshall     } else {
153*31151Sminshall 	char *cmdptr;
154*31151Sminshall 	int length;
155*31151Sminshall 
156*31151Sminshall 	argc--;
157*31151Sminshall 	argv++;
158*31151Sminshall 	strcpy(command, " /c");
159*31151Sminshall 	cmdptr = command+strlen(command);
160*31151Sminshall 	while (argc) {
161*31151Sminshall 	    if ((cmdptr+strlen(*argv)) >= (command+sizeof command)) {
162*31151Sminshall 		fprintf(stderr, "Argument list too long at argument *%s*.\n",
163*31151Sminshall 			    *argv);
164*31151Sminshall 		return 0;
165*31151Sminshall 	    }
166*31151Sminshall 	    *cmdptr++ = ' ';		/* Blank separators */
167*31151Sminshall 	    strcpy(cmdptr, *argv);
168*31151Sminshall 	    cmdptr += strlen(cmdptr);
169*31151Sminshall 	    argc--;
170*31151Sminshall 	    argv++;
171*31151Sminshall 	}
172*31151Sminshall 	length = strlen(command)-1;
173*31151Sminshall 	if (length < 0) {
174*31151Sminshall 	    length = 0;
175*31151Sminshall 	}
176*31151Sminshall 	command[0] = length;
177*31151Sminshall     }
178*31151Sminshall 
179*31151Sminshall     /*
180*31151Sminshall      * do_spawn returns when either the command has finished, or when
181*31151Sminshall      * the required interrupt comes in.  In the latter case, the appropriate
182*31151Sminshall      * thing to do is to process the interrupt, and then return to
183*31151Sminshall      * the interrupt issuer.
184*31151Sminshall      */
185*31151Sminshall     do_spawn(command, &spawned);
186*31151Sminshall     if (spawned.done == 0) {
187*31151Sminshall 	/* Process request */
188*31151Sminshall 	switch (spawned.regs.h.ah) {
189*31151Sminshall 	case 1:			/* Add */
190*31151Sminshall 	    spawned.regs.x.cx += spawned.regs.x.dx;
191*31151Sminshall 	    break;
192*31151Sminshall 	case 2:			/* Subtract */
193*31151Sminshall 	    spawned.regs.x.cx -= spawned.regs.x.dx;
194*31151Sminshall 	    break;
195*31151Sminshall 	case 3:			/* Multiply */
196*31151Sminshall 	    spawned.regs.x.cx *= spawned.regs.x.dx;
197*31151Sminshall 	    break;
198*31151Sminshall 	case 4:			/* Divide */
199*31151Sminshall 	    spawned.regs.x.cx /= spawned.regs.x.dx;
200*31151Sminshall 	    break;
201*31151Sminshall 	default:
202*31151Sminshall 	    spawned.regs.h.al = -1;	/* Error */
203*31151Sminshall 	    spawned.regs.x.cflag = 1;
204*31151Sminshall 	    break;
205*31151Sminshall 	}
206*31151Sminshall 	continue_spawn(&spawned);
207*31151Sminshall 	/*NOTREACHED*/
208*31151Sminshall 	/* continue_spawn() causes an eventual return from do_spawn. */
209*31151Sminshall     }
210*31151Sminshall     if (spawned.rc != 0) {
211*31151Sminshall 	fprintf(stderr, "Process generated a return code of 0x%x.\n",
212*31151Sminshall 								spawned.rc);
213*31151Sminshall     }
214*31151Sminshall }
215