131151Sminshall #define LINT_ARGS 231151Sminshall 331151Sminshall #include <stdio.h> 431151Sminshall #include <dos.h> 531151Sminshall #include <stdlib.h> 631151Sminshall 731151Sminshall #include "../ntn3270/general.h" 8*31152Sminshall #include "spint.h" 931151Sminshall 1031151Sminshall #define PSP_ENVIRONMENT 0x2c 1131151Sminshall #define PSP_FCB1 0x5c 1231151Sminshall #define PSP_FCB2 0x6c 1331151Sminshall 1431151Sminshall typedef struct { 1531151Sminshall int 1631151Sminshall environment, /* Segment address of environment */ 1731151Sminshall cmd_ptr_offset, /* Offset of command to execute */ 1831151Sminshall cmd_ptr_segment, /* Segment where command lives */ 1931151Sminshall fcb1_ptr_offset, /* Offset of FCB 1 */ 2031151Sminshall fcb1_ptr_segment, /* Segment of FCB 1 */ 2131151Sminshall fcb2_ptr_offset, /* Offset of FCB 2 */ 2231151Sminshall fcb2_ptr_segment; /* Segment of FCB 2 */ 2331151Sminshall } ExecList; 2431151Sminshall 2531151Sminshall void 2631151Sminshall do_spawn(command, spawn) 2731151Sminshall char *command; 2831151Sminshall Spawn *spawn; 2931151Sminshall { 3031151Sminshall ExecList mylist; 3131151Sminshall char *comspec; 3231151Sminshall void int_spawn(); 3331151Sminshall int int_offset, int_segment; 3431151Sminshall 3531151Sminshall /* 3631151Sminshall * Get comspec. 3731151Sminshall */ 3831151Sminshall comspec = getenv("COMSPEC"); 3931151Sminshall if (comspec == 0) { /* Can't find where command.com is */ 4031151Sminshall fprintf(stderr, "Unable to find COMSPEC in the environment."); 4131151Sminshall spawn->done = 1; 4231151Sminshall spawn->rc = 99; /* XXX */ 4331151Sminshall return; 4431151Sminshall } 4531151Sminshall 4631151Sminshall /* 4731151Sminshall * Now, hook up our interrupt routine. 4831151Sminshall */ 4931151Sminshall 5031151Sminshall spawn->regs.h.ah = 0x35; 5131151Sminshall spawn->regs.h.al = spawn->int_no; 5231151Sminshall intdosx(&spawn->regs, &spawn->regs, &spawn->sregs); 5331151Sminshall 5431151Sminshall /* Save old routine */ 5531151Sminshall int_offset = spawn->regs.x.bx; 5631151Sminshall int_segment = spawn->sregs.es; 5731151Sminshall 5831151Sminshall spawn->regs.h.ah = 0x25; 5931151Sminshall spawn->regs.h.al = spawn->int_no; 6031151Sminshall spawn->regs.x.dx = (int) int_spawn; 6131151Sminshall segread(&spawn->sregs); 6231151Sminshall spawn->sregs.ds = spawn->sregs.cs; 6331151Sminshall intdosx(&spawn->regs, &spawn->regs, &spawn->sregs); 6431151Sminshall 6531151Sminshall /* 6631151Sminshall * Read in segment registers. 6731151Sminshall */ 6831151Sminshall 6931151Sminshall segread(&spawn->sregs); 7031151Sminshall 7131151Sminshall /* 7231151Sminshall * Set up registers for the EXEC call. 7331151Sminshall */ 7431151Sminshall 7531151Sminshall spawn->regs.h.ah = 0x4b; 7631151Sminshall spawn->regs.h.al = 0; 7731151Sminshall spawn->regs.x.dx = (int) comspec; 7831151Sminshall spawn->sregs.es = spawn->sregs.ds; /* Superfluous, probably */ 7931151Sminshall spawn->regs.x.bx = (int) &mylist; 8031151Sminshall 8131151Sminshall /* 8231151Sminshall * Set up EXEC parameter list. 8331151Sminshall */ 8431151Sminshall 8531151Sminshall ClearElement(mylist); 8631151Sminshall mylist.cmd_ptr_offset = (int) command; 8731151Sminshall mylist.cmd_ptr_segment = spawn->sregs.ds; 8831151Sminshall mylist.fcb1_ptr_offset = PSP_FCB1; 8931151Sminshall mylist.fcb1_ptr_segment = _psp; 9031151Sminshall mylist.fcb2_ptr_offset = PSP_FCB2; 9131151Sminshall mylist.fcb2_ptr_segment = _psp; 9231151Sminshall mylist.environment = *((int far *)(((long)_psp<<16)|PSP_ENVIRONMENT)); 9331151Sminshall 9431151Sminshall /* 9531151Sminshall * Call to assembly language routine to actually set up for 9631151Sminshall * the spawn. 9731151Sminshall */ 9831151Sminshall 9931151Sminshall start_spawn(spawn); 10031151Sminshall spawn->done = 1; /* XXX */ 10131151Sminshall 10231151Sminshall if (spawn->done == 0) { 10331151Sminshall return; /* Not done yet */ 10431151Sminshall } 10531151Sminshall 10631151Sminshall if (spawn->regs.x.cflag) { 10731151Sminshall fprintf(stderr, "0x%x return code from EXEC.\n", spawn->regs.x.ax); 10831151Sminshall spawn->done = 1; 10931151Sminshall spawn->rc = 99; 11031151Sminshall return; 11131151Sminshall } 11231151Sminshall 11331151Sminshall spawn->regs.h.ah = 0x4d; /* Get return code */ 11431151Sminshall 11531151Sminshall intdos(&spawn->regs, &spawn->regs); 11631151Sminshall 11731151Sminshall spawn->rc = spawn->regs.x.ax; 11831151Sminshall 11931151Sminshall /* 12031151Sminshall * Restore old interrupt handler. 12131151Sminshall */ 12231151Sminshall 12331151Sminshall spawn->regs.h.ah = 0x25; 12431151Sminshall spawn->regs.h.al = spawn->int_no; 12531151Sminshall spawn->regs.x.dx = int_offset; 12631151Sminshall spawn->sregs.ds = int_segment; 12731151Sminshall intdosx(&spawn->regs, &spawn->regs, &spawn->sregs); 12831151Sminshall } 129*31152Sminshall 130*31152Sminshall /* XXX */ 13131151Sminshall 132*31152Sminshall #define INTERRUPT_NUMBER 73 133*31152Sminshall 13431151Sminshall main(argc, argv, envp) 13531151Sminshall int argc; /* Number of passed arguments */ 13631151Sminshall char *argv[]; /* Arguments passed */ 13731151Sminshall char *envp[]; /* Inherited environment */ 13831151Sminshall { 13931151Sminshall Spawn spawned; 14031151Sminshall static char command[256]; 14131151Sminshall 14231151Sminshall ClearElement(spawned); 14331151Sminshall spawned.int_no = INTERRUPT_NUMBER; 14431151Sminshall if (argc == 1) { 14531151Sminshall command[0] = 0; 14631151Sminshall } else { 14731151Sminshall char *cmdptr; 14831151Sminshall int length; 14931151Sminshall 15031151Sminshall argc--; 15131151Sminshall argv++; 15231151Sminshall strcpy(command, " /c"); 15331151Sminshall cmdptr = command+strlen(command); 15431151Sminshall while (argc) { 15531151Sminshall if ((cmdptr+strlen(*argv)) >= (command+sizeof command)) { 15631151Sminshall fprintf(stderr, "Argument list too long at argument *%s*.\n", 15731151Sminshall *argv); 15831151Sminshall return 0; 15931151Sminshall } 16031151Sminshall *cmdptr++ = ' '; /* Blank separators */ 16131151Sminshall strcpy(cmdptr, *argv); 16231151Sminshall cmdptr += strlen(cmdptr); 16331151Sminshall argc--; 16431151Sminshall argv++; 16531151Sminshall } 16631151Sminshall length = strlen(command)-1; 16731151Sminshall if (length < 0) { 16831151Sminshall length = 0; 16931151Sminshall } 17031151Sminshall command[0] = length; 17131151Sminshall } 17231151Sminshall 17331151Sminshall /* 174*31152Sminshall * do_spawn() returns when either the command has finished, or when 17531151Sminshall * the required interrupt comes in. In the latter case, the appropriate 17631151Sminshall * thing to do is to process the interrupt, and then return to 177*31152Sminshall * the interrupt issuer by calling continue_spawn(). 17831151Sminshall */ 17931151Sminshall do_spawn(command, &spawned); 180*31152Sminshall while (spawned.done == 0) { 18131151Sminshall /* Process request */ 182*31152Sminshall spawned.regs.h.al = 0; 183*31152Sminshall spawned.regs.x.cflag = 0; /* No errors (yet) */ 18431151Sminshall switch (spawned.regs.h.ah) { 18531151Sminshall case 1: /* Add */ 186*31152Sminshall spawned.regs.x.bx += spawned.regs.x.cx; 18731151Sminshall break; 18831151Sminshall case 2: /* Subtract */ 189*31152Sminshall spawned.regs.x.bx -= spawned.regs.x.cx; 19031151Sminshall break; 19131151Sminshall case 3: /* Multiply */ 192*31152Sminshall spawned.regs.x.bx *= spawned.regs.x.cx; 19331151Sminshall break; 19431151Sminshall case 4: /* Divide */ 195*31152Sminshall spawned.regs.x.bx /= spawned.regs.x.cx; 19631151Sminshall break; 19731151Sminshall default: 19831151Sminshall spawned.regs.h.al = -1; /* Error */ 19931151Sminshall spawned.regs.x.cflag = 1; 20031151Sminshall break; 20131151Sminshall } 202*31152Sminshall spawned.regs.h.ah = 0; /* We saw this */ 20331151Sminshall continue_spawn(&spawned); 20431151Sminshall } 20531151Sminshall if (spawned.rc != 0) { 20631151Sminshall fprintf(stderr, "Process generated a return code of 0x%x.\n", 20731151Sminshall spawned.rc); 20831151Sminshall } 20931151Sminshall } 210