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(®s, ®s, &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(®s, ®s);
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(®s, ®s, &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(®s, ®s, &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