#include <stdio.h>
#include <fcntl.h>
#include <api.h>
#include "spawn.hdr"

unsigned int _STKSIZ={8192/16};
unsigned int _HEAPSIZ={8192/16};
unsigned int _STKLOW={1}; /* force stack below heap */
			  /* this forces minimum memory usage */

char dv_loc[200] = {0,0,0,0,0,0,0,0,0,0,
	"This is the leader for the structure"};
struct _dv_loc { /* actual structure format for dv_loc */
	char header[10]; /* leader of 10 zero bytes */
	char identifier[50]; /* holds the leader string for locating */
	char dv_path[139]; /* holds the directory path */
	char cksum; /* holds the correcting checksum */
} *dv;

/* current directory/path */
char cur_path[139];

main(argc,argv)
int argc;
char **argv;
{
	char work[100];
	/* activate the DESQVIEW system if present */
	if(!api_dvver()) {
		fprintf(stderr,"Load: Desqview must be loaded\n");
		exit(255);
	}
	api_level(0x0200); /* must have API level 2.x */

	/* get current directory and path */
	cur_path[0] = (bdos(0x19,0,0) + 'A');
	cur_path[1] = ':';
	cur_path[2] = 0;
	getcwd(work,99);
	if(*work != '/' && *work != '\\')
		strcat(cur_path,"\\");
	strcat(cur_path,work);

	/* test for initialization call */
	dv = (struct _dv_loc *) dv_loc;
	if(!*(dv->dv_path)) /* need initialization */
		run_setup();

	/* test for legal argument counts and call process loader */
	if(argc < 2) {
		fprintf(stderr,"usage: load [&]ii [parameters]\n");
		exit(255);
	}

	/* spawn the process */
	spawn(argc,argv);
	exit(0);

}

/*
*run the setup program for this file
*read newload.exe copying it to load.exe
*until the string in dv_loc is found
*then add the current directory string into the new file
*and copy the rest of the file to load.exe
*/
run_setup()
{
	FILE *fin, *fout;
	register int ch, mode;
	char *q;
	fprintf(stderr,"newload: creating load.exe\n");
	if((fin = fopen("newload.exe","r")) == NULL) {
		fprintf(stderr,"newload: cannot access newload.exe - aborting\n");
		exit(255);
	}
	if((fout = fopen("load.exe","w")) == NULL) {
		fprintf(stderr,"newload: cannot create load.exe - aborting\n");
		exit(255);
	}
srchloop:
	mode = 0;
	while((ch = getc(fin)) != EOF) {
		putc(ch,fout);
		if(ch != dv->identifier[mode])
			goto srchloop;
		++mode;
		if(!ch)
			goto change; /* got the string */
	}
	fprintf(stderr,"newload: invalid newload.exe - no identifier string\n");
	exit(255);
change:
	/* got id string, skip path array */
	while(mode < 50) {
		ch = getc(fin);
		putc(ch,fout);
		++mode;
	}
	for(mode = 0; mode < 140; ++mode)
		getc(fin);
	/* then write out current path + checksum byte */
	ch = 0;
	for(mode = 0; mode < 139; ++mode) {
		putc(cur_path[mode],fout);
		ch = (ch ^ cur_path[mode]);
	}
	putc(ch,fout);
	/* then copy rest of file over */
	while((ch = getc(fin)) != EOF)
		putc(ch,fout);
	fclose(fin);
	fclose(fout);
	fprintf(stderr,"newload: load.exe successfully created\n");
	exit(0);
}

/*
*spawn function for spawning new processes
*/
int spawn(argc,argv)
int argc;
char **argv;
{
	register char *p;
	register int i;
	int force_foreground;
	int status;
	struct _spawn_blk t;
	long temp, app_start();

	/* if invoked with &, force to foreground after spawning */
	if(force_foreground = (*argv[1] == '&'))
		++argv[1];

	/* get the appropriate .dvp file for this job */
	if(strlen(argv[1]) != 2) {
		fprintf(stderr,"load: pif label (%s) must be 2 characters\n",argv[1]);
		exit(255);
	}
	i = strlen(dv->dv_path) - 1;
	if(dv->dv_path[i] != '/' && dv->dv_path[i] != '\\')
		strcat(dv->dv_path,"\\");
	strcat(dv->dv_path,argv[1]);
	strcat(dv->dv_path,"-pif.dvp");
	if((i = open(dv->dv_path,O_RDONLY)) < 0 || read(i,&t,416) != 416) {
		if(i >= 0)
			close(i);
		fprintf(stderr,"load: unable to locate file %s to spawn process\n",
			dv->dv_path);
		exit(255);
	}
	close(i);

	/* set up the process file for spawning */
	/* set null drive/directory to current */
	if(t.defdrive == ' ' && *t.defdirectory == 0) {
		t.defdrive = cur_path[0];
		strcpy(t.defdirectory, &cur_path[2]);
	}

	/* if in command field and */
	/* there are items left in command line, use them */
	if(argc > 2  && strcmp(t.progparms,"?") == 0) {
		t.progparms[0] = 0;
		for(i = 2; i < argc; ++i) {
			strcat(t.progparms," ");
			strcat(t.progparms,argv[i]);
		}
		if(strlen(t.progparms) > 63) {
			fprintf(stderr,"load: command line too long\n");
			exit(255);
		}
	}

	/* spawn the new process now */
	temp = app_start(&t,416);

	if(!temp) {
		fprintf(stderr,"load: load %s failed\n", argv[1]);
		exit(255);
	}

	if(force_foreground)
		app_gofore(tsk_me());

}
