131151Sminshall #include <stdio.h>
231151Sminshall #include <dos.h>
331151Sminshall #include <stdlib.h>
431151Sminshall 
5*31185Sminshall #include "../general/general.h"
631152Sminshall #include "spint.h"
731151Sminshall 
831151Sminshall #define	PSP_ENVIRONMENT		0x2c
931151Sminshall #define	PSP_FCB1		0x5c
1031151Sminshall #define	PSP_FCB2		0x6c
1131151Sminshall 
1231151Sminshall typedef struct {
1331151Sminshall     int
1431151Sminshall 	environment,		/* Segment address of environment */
1531151Sminshall 	cmd_ptr_offset,		/* Offset of command to execute */
1631151Sminshall 	cmd_ptr_segment,	/* Segment where command lives */
1731151Sminshall 	fcb1_ptr_offset,	/* Offset of FCB 1 */
1831151Sminshall 	fcb1_ptr_segment,	/* Segment of FCB 1 */
1931151Sminshall 	fcb2_ptr_offset,	/* Offset of FCB 2 */
2031151Sminshall 	fcb2_ptr_segment;	/* Segment of FCB 2 */
2131151Sminshall } ExecList;
2231151Sminshall 
2331155Sminshall 
2431155Sminshall static int int_offset, int_segment;
2531155Sminshall 
2631155Sminshall 
2731151Sminshall void
2831155Sminshall spint_finish(spint)
2931155Sminshall Spint *spint;
3031155Sminshall {
3131155Sminshall     union REGS regs;
3231155Sminshall     struct SREGS sregs;
3331155Sminshall 
3431155Sminshall     if (spint->done == 0) {
3531155Sminshall 	return;				/* Not done yet */
3631155Sminshall     }
3731155Sminshall 
3831155Sminshall     /*
3931155Sminshall      * Restore old interrupt handler.
4031155Sminshall      */
4131155Sminshall 
4231155Sminshall     regs.h.ah = 0x25;
4331155Sminshall     regs.h.al = spint->int_no;
4431155Sminshall     regs.x.dx = int_offset;
4531155Sminshall     sregs.ds = int_segment;
4631155Sminshall     intdosx(&regs, &regs, &sregs);
4731155Sminshall 
4831155Sminshall     if (spint->regs.x.cflag) {
4931155Sminshall 	fprintf(stderr, "0x%x return code from EXEC.\n", spint->regs.x.ax);
5031155Sminshall 	spint->done = 1;
5131155Sminshall 	spint->rc = 99;
5231155Sminshall 	return;
5331155Sminshall     }
5431155Sminshall 
5531155Sminshall     regs.h.ah = 0x4d;			/* Get return code */
5631155Sminshall 
5731155Sminshall     intdos(&regs, &regs);
5831155Sminshall 
5931155Sminshall     spint->rc = regs.x.ax;
6031155Sminshall }
6131155Sminshall 
6231155Sminshall void
6331155Sminshall spint_continue(spint)
6431155Sminshall Spint *spint;
6531155Sminshall {
6631155Sminshall     _spint_continue(spint);		/* Return to caller */
6731155Sminshall     spint_finish(spint);
6831155Sminshall }
6931155Sminshall 
7031155Sminshall 
7131155Sminshall void
7231155Sminshall spint_start(command, spint)
7331151Sminshall char *command;
7431155Sminshall Spint *spint;
7531151Sminshall {
7631151Sminshall     ExecList mylist;
7731151Sminshall     char *comspec;
7831155Sminshall     void _spint_int();
7931155Sminshall     union REGS regs;
8031155Sminshall     struct SREGS sregs;
8131151Sminshall 
8231151Sminshall     /*
8331151Sminshall      * Get comspec.
8431151Sminshall      */
8531151Sminshall     comspec = getenv("COMSPEC");
8631151Sminshall     if (comspec == 0) {			/* Can't find where command.com is */
8731151Sminshall 	fprintf(stderr, "Unable to find COMSPEC in the environment.");
8831155Sminshall 	spint->done = 1;
8931155Sminshall 	spint->rc = 99;	/* XXX */
9031151Sminshall 	return;
9131151Sminshall     }
9231151Sminshall 
9331151Sminshall     /*
9431151Sminshall      * Now, hook up our interrupt routine.
9531151Sminshall      */
9631151Sminshall 
9731155Sminshall     regs.h.ah = 0x35;
9831155Sminshall     regs.h.al = spint->int_no;
9931155Sminshall     intdosx(&regs, &regs, &sregs);
10031151Sminshall 
10131151Sminshall     /* Save old routine */
10231155Sminshall     int_offset = regs.x.bx;
10331155Sminshall     int_segment = sregs.es;
10431151Sminshall 
10531155Sminshall     regs.h.ah = 0x25;
10631155Sminshall     regs.h.al = spint->int_no;
10731155Sminshall     regs.x.dx = (int) _spint_int;
10831155Sminshall     segread(&sregs);
10931155Sminshall     sregs.ds = sregs.cs;
11031155Sminshall     intdosx(&regs, &regs, &sregs);
11131151Sminshall 
11231151Sminshall     /*
11331151Sminshall      * Read in segment registers.
11431151Sminshall      */
11531151Sminshall 
11631155Sminshall     segread(&spint->sregs);
11731151Sminshall 
11831151Sminshall     /*
11931151Sminshall      * Set up registers for the EXEC call.
12031151Sminshall      */
12131151Sminshall 
12231155Sminshall     spint->regs.h.ah = 0x4b;
12331155Sminshall     spint->regs.h.al = 0;
12431155Sminshall     spint->regs.x.dx = (int) comspec;
12531155Sminshall     spint->sregs.es = spint->sregs.ds;		/* Superfluous, probably */
12631155Sminshall     spint->regs.x.bx = (int) &mylist;
12731151Sminshall 
12831151Sminshall     /*
12931151Sminshall      * Set up EXEC parameter list.
13031151Sminshall      */
13131151Sminshall 
13231151Sminshall     ClearElement(mylist);
13331151Sminshall     mylist.cmd_ptr_offset = (int) command;
13431155Sminshall     mylist.cmd_ptr_segment = spint->sregs.ds;
13531151Sminshall     mylist.fcb1_ptr_offset = PSP_FCB1;
13631151Sminshall     mylist.fcb1_ptr_segment = _psp;
13731151Sminshall     mylist.fcb2_ptr_offset = PSP_FCB2;
13831151Sminshall     mylist.fcb2_ptr_segment = _psp;
13931151Sminshall     mylist.environment = *((int far *)(((long)_psp<<16)|PSP_ENVIRONMENT));
14031151Sminshall 
14131151Sminshall     /*
14231151Sminshall      * Call to assembly language routine to actually set up for
14331155Sminshall      * the spint.
14431151Sminshall      */
14531151Sminshall 
14631155Sminshall     _spint_start(spint);
14731151Sminshall 
14831155Sminshall     spint_finish(spint);
14931151Sminshall }
150