148757Sbostic /*-
2*62343Sbostic  * Copyright (c) 1988, 1993
3*62343Sbostic  *	The Regents of the University of California.  All rights reserved.
431895Sminshall  *
548757Sbostic  * %sccs.include.redist.c%
631895Sminshall  */
731895Sminshall 
831895Sminshall #ifndef lint
9*62343Sbostic static char sccsid[] = "@(#)spintc.c	8.1 (Berkeley) 06/06/93";
1033814Sbostic #endif /* not lint */
1131895Sminshall 
1231151Sminshall #include <stdio.h>
1331151Sminshall #include <dos.h>
1431151Sminshall #include <stdlib.h>
1531151Sminshall 
1631185Sminshall #include "../general/general.h"
1731152Sminshall #include "spint.h"
1831151Sminshall 
1931151Sminshall #define	PSP_ENVIRONMENT		0x2c
2031151Sminshall #define	PSP_FCB1		0x5c
2131151Sminshall #define	PSP_FCB2		0x6c
2231151Sminshall 
2331151Sminshall typedef struct {
2431151Sminshall     int
2531151Sminshall 	environment,		/* Segment address of environment */
2631151Sminshall 	cmd_ptr_offset,		/* Offset of command to execute */
2731151Sminshall 	cmd_ptr_segment,	/* Segment where command lives */
2831151Sminshall 	fcb1_ptr_offset,	/* Offset of FCB 1 */
2931151Sminshall 	fcb1_ptr_segment,	/* Segment of FCB 1 */
3031151Sminshall 	fcb2_ptr_offset,	/* Offset of FCB 2 */
3131151Sminshall 	fcb2_ptr_segment;	/* Segment of FCB 2 */
3231151Sminshall } ExecList;
3331151Sminshall 
3431155Sminshall 
3531155Sminshall static int int_offset, int_segment;
3631155Sminshall 
3731155Sminshall 
3831151Sminshall void
spint_finish(spint)3931155Sminshall spint_finish(spint)
4031155Sminshall Spint *spint;
4131155Sminshall {
4231155Sminshall     union REGS regs;
4331155Sminshall     struct SREGS sregs;
4431155Sminshall 
4531155Sminshall     if (spint->done == 0) {
4631155Sminshall 	return;				/* Not done yet */
4731155Sminshall     }
4831155Sminshall 
4931155Sminshall     /*
5031155Sminshall      * Restore old interrupt handler.
5131155Sminshall      */
5231155Sminshall 
5331155Sminshall     regs.h.ah = 0x25;
5431155Sminshall     regs.h.al = spint->int_no;
5531155Sminshall     regs.x.dx = int_offset;
5631155Sminshall     sregs.ds = int_segment;
5731155Sminshall     intdosx(&regs, &regs, &sregs);
5831155Sminshall 
5931155Sminshall     if (spint->regs.x.cflag) {
6031155Sminshall 	fprintf(stderr, "0x%x return code from EXEC.\n", spint->regs.x.ax);
6131155Sminshall 	spint->done = 1;
6231155Sminshall 	spint->rc = 99;
6331155Sminshall 	return;
6431155Sminshall     }
6531155Sminshall 
6631155Sminshall     regs.h.ah = 0x4d;			/* Get return code */
6731155Sminshall 
6831155Sminshall     intdos(&regs, &regs);
6931155Sminshall 
7031155Sminshall     spint->rc = regs.x.ax;
7131155Sminshall }
7231155Sminshall 
7331155Sminshall void
spint_continue(spint)7431155Sminshall spint_continue(spint)
7531155Sminshall Spint *spint;
7631155Sminshall {
7731155Sminshall     _spint_continue(spint);		/* Return to caller */
7831155Sminshall     spint_finish(spint);
7931155Sminshall }
8031155Sminshall 
8131155Sminshall 
8231155Sminshall void
spint_start(command,spint)8331155Sminshall spint_start(command, spint)
8431151Sminshall char *command;
8531155Sminshall Spint *spint;
8631151Sminshall {
8731151Sminshall     ExecList mylist;
8831151Sminshall     char *comspec;
8931155Sminshall     void _spint_int();
9031155Sminshall     union REGS regs;
9131155Sminshall     struct SREGS sregs;
9231151Sminshall 
9331151Sminshall     /*
9431151Sminshall      * Get comspec.
9531151Sminshall      */
9631151Sminshall     comspec = getenv("COMSPEC");
9731151Sminshall     if (comspec == 0) {			/* Can't find where command.com is */
9831151Sminshall 	fprintf(stderr, "Unable to find COMSPEC in the environment.");
9931155Sminshall 	spint->done = 1;
10031155Sminshall 	spint->rc = 99;	/* XXX */
10131151Sminshall 	return;
10231151Sminshall     }
10331151Sminshall 
10431151Sminshall     /*
10531151Sminshall      * Now, hook up our interrupt routine.
10631151Sminshall      */
10731151Sminshall 
10831155Sminshall     regs.h.ah = 0x35;
10931155Sminshall     regs.h.al = spint->int_no;
11031155Sminshall     intdosx(&regs, &regs, &sregs);
11131151Sminshall 
11231151Sminshall     /* Save old routine */
11331155Sminshall     int_offset = regs.x.bx;
11431155Sminshall     int_segment = sregs.es;
11531151Sminshall 
11631155Sminshall     regs.h.ah = 0x25;
11731155Sminshall     regs.h.al = spint->int_no;
11831155Sminshall     regs.x.dx = (int) _spint_int;
11931155Sminshall     segread(&sregs);
12031155Sminshall     sregs.ds = sregs.cs;
12131155Sminshall     intdosx(&regs, &regs, &sregs);
12231151Sminshall 
12331151Sminshall     /*
12431151Sminshall      * Read in segment registers.
12531151Sminshall      */
12631151Sminshall 
12731155Sminshall     segread(&spint->sregs);
12831151Sminshall 
12931151Sminshall     /*
13031151Sminshall      * Set up registers for the EXEC call.
13131151Sminshall      */
13231151Sminshall 
13331155Sminshall     spint->regs.h.ah = 0x4b;
13431155Sminshall     spint->regs.h.al = 0;
13531155Sminshall     spint->regs.x.dx = (int) comspec;
13631155Sminshall     spint->sregs.es = spint->sregs.ds;		/* Superfluous, probably */
13731155Sminshall     spint->regs.x.bx = (int) &mylist;
13831151Sminshall 
13931151Sminshall     /*
14031151Sminshall      * Set up EXEC parameter list.
14131151Sminshall      */
14231151Sminshall 
14331151Sminshall     ClearElement(mylist);
14431151Sminshall     mylist.cmd_ptr_offset = (int) command;
14531155Sminshall     mylist.cmd_ptr_segment = spint->sregs.ds;
14631151Sminshall     mylist.fcb1_ptr_offset = PSP_FCB1;
14731151Sminshall     mylist.fcb1_ptr_segment = _psp;
14831151Sminshall     mylist.fcb2_ptr_offset = PSP_FCB2;
14931151Sminshall     mylist.fcb2_ptr_segment = _psp;
15031151Sminshall     mylist.environment = *((int far *)(((long)_psp<<16)|PSP_ENVIRONMENT));
15131151Sminshall 
15231151Sminshall     /*
15331151Sminshall      * Call to assembly language routine to actually set up for
15431155Sminshall      * the spint.
15531151Sminshall      */
15631151Sminshall 
15731155Sminshall     _spint_start(spint);
15831151Sminshall 
15931155Sminshall     spint_finish(spint);
16031151Sminshall }
161