131151Sminshall #define	LINT_ARGS
231151Sminshall 
331151Sminshall #include <stdio.h>
431151Sminshall #include <dos.h>
531151Sminshall #include <stdlib.h>
631151Sminshall 
731151Sminshall #include "../ntn3270/general.h"
831152Sminshall #include "spint.h"
931151Sminshall 
1031151Sminshall #define	PSP_ENVIRONMENT		0x2c
1131151Sminshall #define	PSP_FCB1		0x5c
1231151Sminshall #define	PSP_FCB2		0x6c
1331151Sminshall 
1431151Sminshall typedef struct {
1531151Sminshall     int
1631151Sminshall 	environment,		/* Segment address of environment */
1731151Sminshall 	cmd_ptr_offset,		/* Offset of command to execute */
1831151Sminshall 	cmd_ptr_segment,	/* Segment where command lives */
1931151Sminshall 	fcb1_ptr_offset,	/* Offset of FCB 1 */
2031151Sminshall 	fcb1_ptr_segment,	/* Segment of FCB 1 */
2131151Sminshall 	fcb2_ptr_offset,	/* Offset of FCB 2 */
2231151Sminshall 	fcb2_ptr_segment;	/* Segment of FCB 2 */
2331151Sminshall } ExecList;
2431151Sminshall 
25*31155Sminshall 
26*31155Sminshall static int int_offset, int_segment;
27*31155Sminshall 
28*31155Sminshall 
2931151Sminshall void
30*31155Sminshall spint_finish(spint)
31*31155Sminshall Spint *spint;
32*31155Sminshall {
33*31155Sminshall     union REGS regs;
34*31155Sminshall     struct SREGS sregs;
35*31155Sminshall 
36*31155Sminshall     if (spint->done == 0) {
37*31155Sminshall 	return;				/* Not done yet */
38*31155Sminshall     }
39*31155Sminshall 
40*31155Sminshall     /*
41*31155Sminshall      * Restore old interrupt handler.
42*31155Sminshall      */
43*31155Sminshall 
44*31155Sminshall     regs.h.ah = 0x25;
45*31155Sminshall     regs.h.al = spint->int_no;
46*31155Sminshall     regs.x.dx = int_offset;
47*31155Sminshall     sregs.ds = int_segment;
48*31155Sminshall     intdosx(&regs, &regs, &sregs);
49*31155Sminshall 
50*31155Sminshall     if (spint->regs.x.cflag) {
51*31155Sminshall 	fprintf(stderr, "0x%x return code from EXEC.\n", spint->regs.x.ax);
52*31155Sminshall 	spint->done = 1;
53*31155Sminshall 	spint->rc = 99;
54*31155Sminshall 	return;
55*31155Sminshall     }
56*31155Sminshall 
57*31155Sminshall     regs.h.ah = 0x4d;			/* Get return code */
58*31155Sminshall 
59*31155Sminshall     intdos(&regs, &regs);
60*31155Sminshall 
61*31155Sminshall     spint->rc = regs.x.ax;
62*31155Sminshall }
63*31155Sminshall 
64*31155Sminshall void
65*31155Sminshall spint_continue(spint)
66*31155Sminshall Spint *spint;
67*31155Sminshall {
68*31155Sminshall     _spint_continue(spint);		/* Return to caller */
69*31155Sminshall     spint_finish(spint);
70*31155Sminshall }
71*31155Sminshall 
72*31155Sminshall 
73*31155Sminshall void
74*31155Sminshall spint_start(command, spint)
7531151Sminshall char *command;
76*31155Sminshall Spint *spint;
7731151Sminshall {
7831151Sminshall     ExecList mylist;
7931151Sminshall     char *comspec;
80*31155Sminshall     void _spint_int();
81*31155Sminshall     union REGS regs;
82*31155Sminshall     struct SREGS sregs;
8331151Sminshall 
8431151Sminshall     /*
8531151Sminshall      * Get comspec.
8631151Sminshall      */
8731151Sminshall     comspec = getenv("COMSPEC");
8831151Sminshall     if (comspec == 0) {			/* Can't find where command.com is */
8931151Sminshall 	fprintf(stderr, "Unable to find COMSPEC in the environment.");
90*31155Sminshall 	spint->done = 1;
91*31155Sminshall 	spint->rc = 99;	/* XXX */
9231151Sminshall 	return;
9331151Sminshall     }
9431151Sminshall 
9531151Sminshall     /*
9631151Sminshall      * Now, hook up our interrupt routine.
9731151Sminshall      */
9831151Sminshall 
99*31155Sminshall     regs.h.ah = 0x35;
100*31155Sminshall     regs.h.al = spint->int_no;
101*31155Sminshall     intdosx(&regs, &regs, &sregs);
10231151Sminshall 
10331151Sminshall     /* Save old routine */
104*31155Sminshall     int_offset = regs.x.bx;
105*31155Sminshall     int_segment = sregs.es;
10631151Sminshall 
107*31155Sminshall     regs.h.ah = 0x25;
108*31155Sminshall     regs.h.al = spint->int_no;
109*31155Sminshall     regs.x.dx = (int) _spint_int;
110*31155Sminshall     segread(&sregs);
111*31155Sminshall     sregs.ds = sregs.cs;
112*31155Sminshall     intdosx(&regs, &regs, &sregs);
11331151Sminshall 
11431151Sminshall     /*
11531151Sminshall      * Read in segment registers.
11631151Sminshall      */
11731151Sminshall 
118*31155Sminshall     segread(&spint->sregs);
11931151Sminshall 
12031151Sminshall     /*
12131151Sminshall      * Set up registers for the EXEC call.
12231151Sminshall      */
12331151Sminshall 
124*31155Sminshall     spint->regs.h.ah = 0x4b;
125*31155Sminshall     spint->regs.h.al = 0;
126*31155Sminshall     spint->regs.x.dx = (int) comspec;
127*31155Sminshall     spint->sregs.es = spint->sregs.ds;		/* Superfluous, probably */
128*31155Sminshall     spint->regs.x.bx = (int) &mylist;
12931151Sminshall 
13031151Sminshall     /*
13131151Sminshall      * Set up EXEC parameter list.
13231151Sminshall      */
13331151Sminshall 
13431151Sminshall     ClearElement(mylist);
13531151Sminshall     mylist.cmd_ptr_offset = (int) command;
136*31155Sminshall     mylist.cmd_ptr_segment = spint->sregs.ds;
13731151Sminshall     mylist.fcb1_ptr_offset = PSP_FCB1;
13831151Sminshall     mylist.fcb1_ptr_segment = _psp;
13931151Sminshall     mylist.fcb2_ptr_offset = PSP_FCB2;
14031151Sminshall     mylist.fcb2_ptr_segment = _psp;
14131151Sminshall     mylist.environment = *((int far *)(((long)_psp<<16)|PSP_ENVIRONMENT));
14231151Sminshall 
14331151Sminshall     /*
14431151Sminshall      * Call to assembly language routine to actually set up for
145*31155Sminshall      * the spint.
14631151Sminshall      */
14731151Sminshall 
148*31155Sminshall     _spint_start(spint);
14931151Sminshall 
150*31155Sminshall     spint_finish(spint);
15131151Sminshall }
152