/*		IQ_BOOT.PRG    ( The Intelligent Boot_Program )	 */
/*	Embryo sourcecode for an intelligent boot program meant to boot
	your system off a "booting" RDY\RDE ramdisk ( P:\ is best choice )
	"Tailor" it to your needs - No "Package" boot program is as flexible

	compile in MWC with:	  cc  -V -VSMALL -Nrcrtsg.o -s iq_boot.c
	or use the supplied   makefile

					W. Alan B. Evans  [wabe@ukc.ac.uk]
*/

#include <osbind.h>


/*  Cheap & minimal gets alternative - Saves a little space over gets() */
/*    But on earlier TOSes    CONTROL-C  is not recognised	*/

char *gts(data)
char *data;
{	register char *p = data;
	while ((*p=gemdos(1)) != '\r')
	if (*p == '\010') { --p; Cconws(" \010"); } else p++;
	*p= '\0';
	if (*data)	return(data);	else	return((char *)0);
}

/*   Filecopying Subroutine - Preserves DateStamp - very useful generally */

int fc(file1,file2)
char *file1,*file2;

{	register char *buf;
	int i,handle1,handle2,nsects,nsecmax,erc,no_tms,info[2];
	long lo,nrw,flngth;

	erc= 0;	buf= 0;
	if ((nsecmax = (int)(Malloc(-1L)/0x200L)-4) < 0)
	{ gemdos(9,"\r\n  INSUFFICIENT MEMORY!! ");  goto end;	}

	if ((handle1 = Fopen(file1,0)) < 0) return(0);
	Fdatime(info,handle1,0);
	flngth= Fseek(0L,handle1,2);
	nsects= 1+(int)(flngth/0x200L);
	if ((no_tms= nsects/nsecmax) == 0) nsecmax= nsects;

	if ((handle2 = Fopen(file2,0)) > 0)
	{ Fclose(handle2); Fdelete(file2);	}
	if ((handle2 = Fcreate(file2,0)) < 0 )
	{ gemdos(9,"\r\n Fcreate FAILURE - COULD NOT OPEN FILE: ");
	gemdos(9,file2);	--erc; goto end; }

	if ((buf= (char *)Malloc((long)nsecmax*0x200L+0x200L)) == 0)
	{ gemdos(9,"\r\n Malloc FAILURE!!! "); --erc; goto end; }
	Cconws("\r\n  Copying "); Cconws(file1);
	Cconws(" to "); Cconws(file2); Cconws("\r\n");
	i=-1; while (i++ < no_tms)
	{ if (i == no_tms) nrw= flngth- (long)nsecmax*0x200L*i;
	else  nrw= (long)nsecmax*0x200;

	{ if ((lo= Fseek((long)nsecmax*0x200L*i,handle1,0) < 0) 
	|| (lo=Fread(handle1,nrw,buf)) != nrw)
	{ gemdos(9,"\r\n Fseek or Fread FAILURE");  --erc; goto end;	}
	}

	{ if ((lo= Fseek((long)(nsecmax*0x200L*i),handle2,0) < 0) 
	|| (lo= Fwrite(handle2,nrw,buf)) != nrw)
	{ gemdos(9,"\r\n Fseek or Fwrite FAILURE!  DISK FULL? "); --erc; goto end; }
	}
	}    /*  end of i loop  */

end:	if (!Fclose(handle2))
	{ if (erc < 0) Fdelete(file2); else
	{ handle2=Fopen(file2,0); Fdatime(info,handle2,1); Fclose(handle2); }
	}
	if (buf != 0) Mfree(buf);
return(erc);
}



main()

{	int sv,i,dev;	long drv,st;	char ch,c,file[100],num[100];
	char *gts(),strcpy(),*strcat();

/* Check for Character Code input at Boot Time and, if present, capitalize it */
	if (Cconis()== -1)	ch= (Crawcin() & 0x5f);

/*  Load the Hard_disk Program if 'H' has not been Keyed	*/
	if (ch != 'H') Pexec(0,"AUTO\\AHDI\0","\0","\0");

/* Life_Saver Feature: Enter Shell to cure corrupted Boot Programs, ACC's etc.*/
	if (ch == 'X') {	Cconws("\r\n\n  PROGRAM PATH\\NAME= ");
	Pexec(0,gts(file),"\0","\0");
	}

/*  Check if Utility Ram Disk O:\ is Present, and if not, offer to load it */
	if (!((drv=Drvmap()) & 040000))	{
	Cconws("\r\n  Load UTIL_O Ramdisk? [y] ");
	st=0L;
/*  Wait for about 10 seconds for key_input	*/
	while (!Cconis() && ++st < 25000L)  ;
/*  If no key-input after 10 secs, do the default load	*/
	if (!Cconis() || (Cconin() & 0x5f) != 'N')
	if (Pexec(0,"C:\\UTIL_O.PRG\0","\0","\0"))
	{ Cconws("\r\n  Insert UTIL_O Floppy & Hit key ");
	Crawcin(); Pexec(0,"A:\\UTIL_O.PRG\0","\0","\0");	}
	}
/*  If O:\ Loads successfully a warm start ensues and booting restarts */

/*  Check for TOS Versions requiring the POOLFIX patch and implement it */
	if ((sv=Sversion()) >= 0x1400      /*  NEW TOS Present!	*/
	&& sv <= 0x1500 && Pexec(0,"O:\\POOLFIX?.PRG\0","\0","\0") &&
	Pexec(0,"C:\\POOLFIX?.PRG\0","\0","\0"))
	Pexec(0,"A:\\POOLFIX?.PRG\0","\0","\0");

eto:	i=0;	for (dev=0;dev<=15;++dev) {
	if (drv & 1L<<dev) {file[i++]= 'A'+dev; file[i+1]='\0'; }
	}
	Cconws("\r\n\n	VOLUMES PRESENT = \033p");	Cconws(file);
	strcpy(file," \0");
	Cconws("\033q\r\n\n\
	\033K\033p Optionally use RDSH to LOAD|DROP|COPY Ramdisks/Files etc.\033q\r\n\
  Enter RDSH Command: \033e");
	if  (gts(num))	{	strcat(file,num);

/*   Try to Find RDSH on O:\, then on C:\ and lastly on A:\	*/
	if (Pexec(0,"O:\\RDSH.PRG\0",file,"\0")== -33  &&
	Pexec(0,"C:\\RDSH.PRG\0",file,"\0") == -33  &&
	Pexec(0,"A:\\RDSH.PRG\0",file,"\0"))	goto eto;
	}

	Cconws("\r\n\n\
	  CHOOSE DESKTOP [def = Previous Desktop]\r\n\n\
	Signum2 		  s	Timeworks	 t\r\n\
	Mark Williams C v_3	  m	Fortran_2.154	 j\r\n\
	Degas Elite		  d	WordPlus	 w\r\n\
	Fontmake	 	  f	General Purpose	 g\r\n\
	Other:  Enter PATH to DESKTOP.INF (e.g. C:, E:\\MAIL etc. )\r\n\
	\033e");

	Cconws("\033f");
	if (gts(file))	{
	if (strlen(file) < 2)	{

	if ((c= (file[0] & 0x5f)) == 'S')	{
	if (drv & 0400) strcpy(file,"I:\0");
	else	{	strcpy(file,"D:\\SIGNUM\0");
/*  Load Signum Resident Code	*/
	if (Pexec(0,"D:\\SIGNUM\\INSTAL.PRG\0","\0","\0"))
	Cconws("\r\n  WARNING: INSTAL NOT LOADED! ");	}
	}

	if (c == 'M') if (drv & 0200) strcpy(file,"H:\0");
	else strcpy(file,"C:\\MWC30\0");

	if (c == 'J') strcpy(file,"J:\0");

	if (c == 'W') 	strcpy(file,"C:\\WORDPLUS\0");

	if (c == 'T')	{	strcpy(file,"E:\\PUBLISH\0");
/*  Load GDOS for Timeworks		*/
	fc("E:\\PUBLISH\\ASSIGN.SYS\0","ASSIGN.SYS\0");
	Pexec(0,"E:\\PUBLISH\\GDOS.PRG\0","\0","\0");
	}

	if (c == 'D') strcpy(file,"D:\\DEGAS\0");

/*  Load General Purpose Desktop, kept in AUTO folder of Ramdisk	*/
	if (c == 'G') strcpy(file,"AUTO\0");
	}

/*   Add filename to the selected Path to Desktop	*/
	strcat(file,"\\DESKTOP.INF\0");
	}

/*   Optionally Load GDOS	*/
	if (c != 'T')	{
	Cconws("\r\n  Load GDOS? [n] ");
	if ((Cconin() & 0x5f) == 'Y')	{
	fc("E:\\PUBLISH\\ASSIGN.SYS\0","ASSIGN.SYS\0");
	Pexec(0,"E:\\PUBLISH\\GDOS.PRG\0","\0","\0");
	}}

/*  Check for presence of drive C:\ and accordingly depending on TOS Version */
	if (drv & 04)	/*  C:\ Disk Present	*/
	{ if (sv >= 0x1400) { if (*file) fc(file,"C:\\DESKTOP.INF\0"); }

/*  Increase 40-Folder Limit on old TOSes if C:\ is present	*/
/*   NOTE: IQ_BOOT.PRG in "booting" AUTO-folder is renamed to FOLDRXXX.PRG
     where  XXX  is the desired number of extra folders e.g. FOLDR200.PRG   */
	else  Pexec(0,"C:\\FOLDR???.PRG\0","\0","\0");
	}
 /*  If C:\ absent, ACC's load from the booting Ramdisk - so copy them in */
	else  fc("A:\\CONTROL.ACC\0","CONTROL.ACC\0");

/*  On older TOSes the DESKTOP.INF must be on the booting RAM_DISK Rootdir */
	if (*file && sv < 0x1400)	fc(file,"DESKTOP.INF\0");

/*  Some default tasks ( Tailor these to your own needs )	*/
/*  Set ICD Clock on Hard Disk	*/
	Pexec(0,"C:\\BIN\\TIMESET.PRG\0","\0","\0");

/*  Load ANTIBOMB Utility	*/
	if (Pexec(0,"O:\\ANTIBOMB.PRG\0","\0","\0") == 33)
	Pexec(0,"C:\\ANTIBOMB.PRG\0","\0","\0");

/*  If Signum2 loaded on Ramdisk I:\, load its Libraries	*/
	Pexec(0,"I:\\INSTAL.PRG\0","\0","\0");

/*  For Older TOSes load the COPYFIX Program to preserve DATE/TIME stamp */
	if ( sv < 0x1400 && Pexec(0,"O:\\COPYFIX.PRG\0","\0","\0")
	&& Pexec(0,"C:\\COPYFIX.PRG\0","\0","\0"))
	Pexec(0,"A:\\COPYFIX.PRG\0","\0","\0");

/*   etc.  etc.		*/


Pterm0();
}


