131895Sminshall /*
2*33814Sbostic  * Copyright (c) 1988 Regents of the University of California.
3*33814Sbostic  * All rights reserved.
431895Sminshall  *
5*33814Sbostic  * Redistribution and use in source and binary forms are permitted
6*33814Sbostic  * provided that this notice is preserved and that due credit is given
7*33814Sbostic  * to the University of California at Berkeley. The name of the University
8*33814Sbostic  * may not be used to endorse or promote products derived from this
9*33814Sbostic  * software without specific prior written permission. This software
10*33814Sbostic  * is provided ``as is'' without express or implied warranty.
1131895Sminshall  */
1231895Sminshall 
1331895Sminshall #ifndef lint
14*33814Sbostic static char sccsid[] = "@(#)spintc.c	3.2 (Berkeley) 03/28/88";
15*33814Sbostic #endif /* not lint */
1631895Sminshall 
1731151Sminshall #include <stdio.h>
1831151Sminshall #include <dos.h>
1931151Sminshall #include <stdlib.h>
2031151Sminshall 
2131185Sminshall #include "../general/general.h"
2231152Sminshall #include "spint.h"
2331151Sminshall 
2431151Sminshall #define	PSP_ENVIRONMENT		0x2c
2531151Sminshall #define	PSP_FCB1		0x5c
2631151Sminshall #define	PSP_FCB2		0x6c
2731151Sminshall 
2831151Sminshall typedef struct {
2931151Sminshall     int
3031151Sminshall 	environment,		/* Segment address of environment */
3131151Sminshall 	cmd_ptr_offset,		/* Offset of command to execute */
3231151Sminshall 	cmd_ptr_segment,	/* Segment where command lives */
3331151Sminshall 	fcb1_ptr_offset,	/* Offset of FCB 1 */
3431151Sminshall 	fcb1_ptr_segment,	/* Segment of FCB 1 */
3531151Sminshall 	fcb2_ptr_offset,	/* Offset of FCB 2 */
3631151Sminshall 	fcb2_ptr_segment;	/* Segment of FCB 2 */
3731151Sminshall } ExecList;
3831151Sminshall 
3931155Sminshall 
4031155Sminshall static int int_offset, int_segment;
4131155Sminshall 
4231155Sminshall 
4331151Sminshall void
4431155Sminshall spint_finish(spint)
4531155Sminshall Spint *spint;
4631155Sminshall {
4731155Sminshall     union REGS regs;
4831155Sminshall     struct SREGS sregs;
4931155Sminshall 
5031155Sminshall     if (spint->done == 0) {
5131155Sminshall 	return;				/* Not done yet */
5231155Sminshall     }
5331155Sminshall 
5431155Sminshall     /*
5531155Sminshall      * Restore old interrupt handler.
5631155Sminshall      */
5731155Sminshall 
5831155Sminshall     regs.h.ah = 0x25;
5931155Sminshall     regs.h.al = spint->int_no;
6031155Sminshall     regs.x.dx = int_offset;
6131155Sminshall     sregs.ds = int_segment;
6231155Sminshall     intdosx(&regs, &regs, &sregs);
6331155Sminshall 
6431155Sminshall     if (spint->regs.x.cflag) {
6531155Sminshall 	fprintf(stderr, "0x%x return code from EXEC.\n", spint->regs.x.ax);
6631155Sminshall 	spint->done = 1;
6731155Sminshall 	spint->rc = 99;
6831155Sminshall 	return;
6931155Sminshall     }
7031155Sminshall 
7131155Sminshall     regs.h.ah = 0x4d;			/* Get return code */
7231155Sminshall 
7331155Sminshall     intdos(&regs, &regs);
7431155Sminshall 
7531155Sminshall     spint->rc = regs.x.ax;
7631155Sminshall }
7731155Sminshall 
7831155Sminshall void
7931155Sminshall spint_continue(spint)
8031155Sminshall Spint *spint;
8131155Sminshall {
8231155Sminshall     _spint_continue(spint);		/* Return to caller */
8331155Sminshall     spint_finish(spint);
8431155Sminshall }
8531155Sminshall 
8631155Sminshall 
8731155Sminshall void
8831155Sminshall spint_start(command, spint)
8931151Sminshall char *command;
9031155Sminshall Spint *spint;
9131151Sminshall {
9231151Sminshall     ExecList mylist;
9331151Sminshall     char *comspec;
9431155Sminshall     void _spint_int();
9531155Sminshall     union REGS regs;
9631155Sminshall     struct SREGS sregs;
9731151Sminshall 
9831151Sminshall     /*
9931151Sminshall      * Get comspec.
10031151Sminshall      */
10131151Sminshall     comspec = getenv("COMSPEC");
10231151Sminshall     if (comspec == 0) {			/* Can't find where command.com is */
10331151Sminshall 	fprintf(stderr, "Unable to find COMSPEC in the environment.");
10431155Sminshall 	spint->done = 1;
10531155Sminshall 	spint->rc = 99;	/* XXX */
10631151Sminshall 	return;
10731151Sminshall     }
10831151Sminshall 
10931151Sminshall     /*
11031151Sminshall      * Now, hook up our interrupt routine.
11131151Sminshall      */
11231151Sminshall 
11331155Sminshall     regs.h.ah = 0x35;
11431155Sminshall     regs.h.al = spint->int_no;
11531155Sminshall     intdosx(&regs, &regs, &sregs);
11631151Sminshall 
11731151Sminshall     /* Save old routine */
11831155Sminshall     int_offset = regs.x.bx;
11931155Sminshall     int_segment = sregs.es;
12031151Sminshall 
12131155Sminshall     regs.h.ah = 0x25;
12231155Sminshall     regs.h.al = spint->int_no;
12331155Sminshall     regs.x.dx = (int) _spint_int;
12431155Sminshall     segread(&sregs);
12531155Sminshall     sregs.ds = sregs.cs;
12631155Sminshall     intdosx(&regs, &regs, &sregs);
12731151Sminshall 
12831151Sminshall     /*
12931151Sminshall      * Read in segment registers.
13031151Sminshall      */
13131151Sminshall 
13231155Sminshall     segread(&spint->sregs);
13331151Sminshall 
13431151Sminshall     /*
13531151Sminshall      * Set up registers for the EXEC call.
13631151Sminshall      */
13731151Sminshall 
13831155Sminshall     spint->regs.h.ah = 0x4b;
13931155Sminshall     spint->regs.h.al = 0;
14031155Sminshall     spint->regs.x.dx = (int) comspec;
14131155Sminshall     spint->sregs.es = spint->sregs.ds;		/* Superfluous, probably */
14231155Sminshall     spint->regs.x.bx = (int) &mylist;
14331151Sminshall 
14431151Sminshall     /*
14531151Sminshall      * Set up EXEC parameter list.
14631151Sminshall      */
14731151Sminshall 
14831151Sminshall     ClearElement(mylist);
14931151Sminshall     mylist.cmd_ptr_offset = (int) command;
15031155Sminshall     mylist.cmd_ptr_segment = spint->sregs.ds;
15131151Sminshall     mylist.fcb1_ptr_offset = PSP_FCB1;
15231151Sminshall     mylist.fcb1_ptr_segment = _psp;
15331151Sminshall     mylist.fcb2_ptr_offset = PSP_FCB2;
15431151Sminshall     mylist.fcb2_ptr_segment = _psp;
15531151Sminshall     mylist.environment = *((int far *)(((long)_psp<<16)|PSP_ENVIRONMENT));
15631151Sminshall 
15731151Sminshall     /*
15831151Sminshall      * Call to assembly language routine to actually set up for
15931155Sminshall      * the spint.
16031151Sminshall      */
16131151Sminshall 
16231155Sminshall     _spint_start(spint);
16331151Sminshall 
16431155Sminshall     spint_finish(spint);
16531151Sminshall }
166