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