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