1*31895Sminshall /*
2*31895Sminshall  *	Copyright (c) 1984-1987 by the Regents of the
3*31895Sminshall  *	University of California and by Gregory Glenn Minshall.
4*31895Sminshall  *
5*31895Sminshall  *	Permission to use, copy, modify, and distribute these
6*31895Sminshall  *	programs and their documentation for any purpose and
7*31895Sminshall  *	without fee is hereby granted, provided that this
8*31895Sminshall  *	copyright and permission appear on all copies and
9*31895Sminshall  *	supporting documentation, the name of the Regents of
10*31895Sminshall  *	the University of California not be used in advertising
11*31895Sminshall  *	or publicity pertaining to distribution of the programs
12*31895Sminshall  *	without specific prior permission, and notice be given in
13*31895Sminshall  *	supporting documentation that copying and distribution is
14*31895Sminshall  *	by permission of the Regents of the University of California
15*31895Sminshall  *	and by Gregory Glenn Minshall.  Neither the Regents of the
16*31895Sminshall  *	University of California nor Gregory Glenn Minshall make
17*31895Sminshall  *	representations about the suitability of this software
18*31895Sminshall  *	for any purpose.  It is provided "as is" without
19*31895Sminshall  *	express or implied warranty.
20*31895Sminshall  */
21*31895Sminshall 
22*31895Sminshall #ifndef lint
23*31895Sminshall static char sccsid[] = "@(#)spintc.c	1.6 (Berkeley) 07/17/87";
24*31895Sminshall #endif	/* not lint */
25*31895Sminshall 
2631151Sminshall #include <stdio.h>
2731151Sminshall #include <dos.h>
2831151Sminshall #include <stdlib.h>
2931151Sminshall 
3031185Sminshall #include "../general/general.h"
3131152Sminshall #include "spint.h"
3231151Sminshall 
3331151Sminshall #define	PSP_ENVIRONMENT		0x2c
3431151Sminshall #define	PSP_FCB1		0x5c
3531151Sminshall #define	PSP_FCB2		0x6c
3631151Sminshall 
3731151Sminshall typedef struct {
3831151Sminshall     int
3931151Sminshall 	environment,		/* Segment address of environment */
4031151Sminshall 	cmd_ptr_offset,		/* Offset of command to execute */
4131151Sminshall 	cmd_ptr_segment,	/* Segment where command lives */
4231151Sminshall 	fcb1_ptr_offset,	/* Offset of FCB 1 */
4331151Sminshall 	fcb1_ptr_segment,	/* Segment of FCB 1 */
4431151Sminshall 	fcb2_ptr_offset,	/* Offset of FCB 2 */
4531151Sminshall 	fcb2_ptr_segment;	/* Segment of FCB 2 */
4631151Sminshall } ExecList;
4731151Sminshall 
4831155Sminshall 
4931155Sminshall static int int_offset, int_segment;
5031155Sminshall 
5131155Sminshall 
5231151Sminshall void
5331155Sminshall spint_finish(spint)
5431155Sminshall Spint *spint;
5531155Sminshall {
5631155Sminshall     union REGS regs;
5731155Sminshall     struct SREGS sregs;
5831155Sminshall 
5931155Sminshall     if (spint->done == 0) {
6031155Sminshall 	return;				/* Not done yet */
6131155Sminshall     }
6231155Sminshall 
6331155Sminshall     /*
6431155Sminshall      * Restore old interrupt handler.
6531155Sminshall      */
6631155Sminshall 
6731155Sminshall     regs.h.ah = 0x25;
6831155Sminshall     regs.h.al = spint->int_no;
6931155Sminshall     regs.x.dx = int_offset;
7031155Sminshall     sregs.ds = int_segment;
7131155Sminshall     intdosx(&regs, &regs, &sregs);
7231155Sminshall 
7331155Sminshall     if (spint->regs.x.cflag) {
7431155Sminshall 	fprintf(stderr, "0x%x return code from EXEC.\n", spint->regs.x.ax);
7531155Sminshall 	spint->done = 1;
7631155Sminshall 	spint->rc = 99;
7731155Sminshall 	return;
7831155Sminshall     }
7931155Sminshall 
8031155Sminshall     regs.h.ah = 0x4d;			/* Get return code */
8131155Sminshall 
8231155Sminshall     intdos(&regs, &regs);
8331155Sminshall 
8431155Sminshall     spint->rc = regs.x.ax;
8531155Sminshall }
8631155Sminshall 
8731155Sminshall void
8831155Sminshall spint_continue(spint)
8931155Sminshall Spint *spint;
9031155Sminshall {
9131155Sminshall     _spint_continue(spint);		/* Return to caller */
9231155Sminshall     spint_finish(spint);
9331155Sminshall }
9431155Sminshall 
9531155Sminshall 
9631155Sminshall void
9731155Sminshall spint_start(command, spint)
9831151Sminshall char *command;
9931155Sminshall Spint *spint;
10031151Sminshall {
10131151Sminshall     ExecList mylist;
10231151Sminshall     char *comspec;
10331155Sminshall     void _spint_int();
10431155Sminshall     union REGS regs;
10531155Sminshall     struct SREGS sregs;
10631151Sminshall 
10731151Sminshall     /*
10831151Sminshall      * Get comspec.
10931151Sminshall      */
11031151Sminshall     comspec = getenv("COMSPEC");
11131151Sminshall     if (comspec == 0) {			/* Can't find where command.com is */
11231151Sminshall 	fprintf(stderr, "Unable to find COMSPEC in the environment.");
11331155Sminshall 	spint->done = 1;
11431155Sminshall 	spint->rc = 99;	/* XXX */
11531151Sminshall 	return;
11631151Sminshall     }
11731151Sminshall 
11831151Sminshall     /*
11931151Sminshall      * Now, hook up our interrupt routine.
12031151Sminshall      */
12131151Sminshall 
12231155Sminshall     regs.h.ah = 0x35;
12331155Sminshall     regs.h.al = spint->int_no;
12431155Sminshall     intdosx(&regs, &regs, &sregs);
12531151Sminshall 
12631151Sminshall     /* Save old routine */
12731155Sminshall     int_offset = regs.x.bx;
12831155Sminshall     int_segment = sregs.es;
12931151Sminshall 
13031155Sminshall     regs.h.ah = 0x25;
13131155Sminshall     regs.h.al = spint->int_no;
13231155Sminshall     regs.x.dx = (int) _spint_int;
13331155Sminshall     segread(&sregs);
13431155Sminshall     sregs.ds = sregs.cs;
13531155Sminshall     intdosx(&regs, &regs, &sregs);
13631151Sminshall 
13731151Sminshall     /*
13831151Sminshall      * Read in segment registers.
13931151Sminshall      */
14031151Sminshall 
14131155Sminshall     segread(&spint->sregs);
14231151Sminshall 
14331151Sminshall     /*
14431151Sminshall      * Set up registers for the EXEC call.
14531151Sminshall      */
14631151Sminshall 
14731155Sminshall     spint->regs.h.ah = 0x4b;
14831155Sminshall     spint->regs.h.al = 0;
14931155Sminshall     spint->regs.x.dx = (int) comspec;
15031155Sminshall     spint->sregs.es = spint->sregs.ds;		/* Superfluous, probably */
15131155Sminshall     spint->regs.x.bx = (int) &mylist;
15231151Sminshall 
15331151Sminshall     /*
15431151Sminshall      * Set up EXEC parameter list.
15531151Sminshall      */
15631151Sminshall 
15731151Sminshall     ClearElement(mylist);
15831151Sminshall     mylist.cmd_ptr_offset = (int) command;
15931155Sminshall     mylist.cmd_ptr_segment = spint->sregs.ds;
16031151Sminshall     mylist.fcb1_ptr_offset = PSP_FCB1;
16131151Sminshall     mylist.fcb1_ptr_segment = _psp;
16231151Sminshall     mylist.fcb2_ptr_offset = PSP_FCB2;
16331151Sminshall     mylist.fcb2_ptr_segment = _psp;
16431151Sminshall     mylist.environment = *((int far *)(((long)_psp<<16)|PSP_ENVIRONMENT));
16531151Sminshall 
16631151Sminshall     /*
16731151Sminshall      * Call to assembly language routine to actually set up for
16831155Sminshall      * the spint.
16931151Sminshall      */
17031151Sminshall 
17131155Sminshall     _spint_start(spint);
17231151Sminshall 
17331155Sminshall     spint_finish(spint);
17431151Sminshall }
175