/*** *setup.c - disked setup * *Copyright (c) 1991-1995, Gregg Jennings. All wrongs reserved. * P O Box 200, Falmouth, MA 02541-0200 * *Purpose: * Initialization. * *Notice: * This progam may be freely used and distributed. Any distrubution * with modifications must retain the above copyright statement and * modifications noted. * No pulp-publication, in whole or in part, permitted without * permission (magazines or books). *******************************************************************************/ /* Versions: 2.7 15-Dec-1994 corrected Processor ID equate order 2.6 09-Nov-1994 general cleaning, comments, 2.5 04-Sep-1994 consolodated all extern references. removed some code in setup() and startup() and placed into functions. 2.4 18-Apr-1994 cleaned up extern defs 2.3 09-Mar-1994 hugefree() file/clusters, bump to revision 2.2 03-Feb-1994 added startup() 2.1 04-Jan-1994 added get_volume() Notes: The startup code (startup()) is just plain confusing. It will probably be the last to be cleaned up. Also: the logdisk() functions return DISKIO for no errors, less than DISKIO for warnings, and greater than DISKIO for unrecoverable errors. I forgot this once and totally messed things up! */ #include #include #include #include #include #include #ifdef __BORLANDC__ #include #endif #include "disked.h" #include "diskio.h" #include "files.h" #include "mylib.h" #include "alloc.h" #include "error.h" #include "direct.h" #include "console.h" /* globals referenced here All of the DISKED configuration switches (mixed case identifiers), all of the "start-up" variables (for initial sector position, control switches. Some of the DISKIO globals. error, err_msg[] ERROR.C enum DISKIO_RETURNS DISKIO.H comspec[],promptvar[] DISKED.C (probably more) */ /* gloabls defined here */ /* version nu. */ const char * const Version=" 2.9." #ifdef _QC /* Compiler ID */ "MQ." /* keep track of compiler */ #elif defined(__BORLANDC__) /* for BUGZZZZ! */ "BC." #elif defined(_MSC_VER) "MC." #elif defined(__WATCOMC__) "WC." #else "XX." /* put others here and below */ #endif #if defined(M_I386) || defined(__386__) /* Processor ID */ "I386"; /* note order */ #elif defined(M_I286) || defined(__286__) "I286"; #elif defined(M_I8086) || defined(M_I86) "I86"; #else "x86"; #endif /* Borland does not have such defines, I edit the EXE */ /* Watcom's WCL does not define these either! */ /* error message stuff -- for the INT 24 handler */ const char *harderr_list[] = { "Disk is write-protected", "Unknown unit", "Drive not ready", "Unknown command", "CRC error in data", "Bad drive-request structure length", "Seek error", "Unknown media type", "Sector not found", "Printer out of paper", "Write fault", "Read fault", "General failure", }; /* internal data */ /* copyleft stuff */ static const char * const Author="Gregg Jennings"; static const char * const Title="DISKED The DISK EDitor"; static const char * const Copyr="(c) 1989-1995, All wrongs reserved"; static const char * const Namep="DISKED"; static const char *disked_ini="DISKED.INI"; static const char *disked_sav="DISKED.SAV"; static int min_mem; /* for running with an IDE */ static int find_flag; /* find string arg */ static char set_file[67]; /* file being set-to/tracked */ /* internal functions */ static void setupmem(void); static void set_inifile(char *arv); static void program_args(char **argv, int drives[], unsigned int *dsk); static void drive_status(int status); static int getdriveinfo(int *drives, unsigned int *num); static void do_find(void); static void do_set(unsigned int cdisk); static int do_files(void); static void quit(int e); #ifdef __WATCOMC__ int _far hhandler(unsigned deverr, unsigned doserr, unsigned _far *hdr); #else void _cdecl _far hhandler(unsigned deverr, unsigned doserr, unsigned _far *hdr); #endif /*** *setup - sets up everything * * args: char **argv passed to option handler * int drives[] gets filled with system drives (boolean) * UNIT *dsk gets set to current drive or to drive set * by command line * * Return: void * * 2.11 23-Mar-1995 returns current drive * 2.10 25-Nov-1994 BigScreen reference * 2.9 09-Nov-1994 void return * 2.8 02-Oct-1994 fixed error of setting current disk if drive arg * 2.7 08-Apr-1994 put some code in sub-functions * 2.6 03-Feb-1994 /s, moved stuff here (startup()) from DISKED.C * ver 2.5 21-Jan-1994 added +|-t * ver 2.4 03-Dec-1993 added /@ * ver 2.3 20-Nov-1993 order of options parsed * ver 2.2 13-Nov-1993 better finding of INI file, newalloc() * ver 2.1 19-Apr-1992 Added /? ****/ extern int setup(char **argv, int drives[], unsigned int *dsk) { int cdisk; /* preset all non-init-structure globals */ write_to = FALSE; /* global booleans */ files_indexed = FALSE; Signon = TRUE; Save = Restore = FALSE; BigScreen = FALSE; byte_cnt = 0; /* global object counters */ n_files = 1; n_dirs = 1; find_flag = min_mem = 0; /* start-up flags */ set_sector = -1L; dir_cluster = 0; set_file[0] = '\0'; volume[0] = format[0] = /* others */ fatsize[0] = '\0'; memset(tagged,0,sizeof(tagged)); /* get drive info -- set current drive and get drive count */ cdisk = *dsk = getdriveinfo(drives,&max_drive); /* initialize the world */ set_inifile(*argv); initialize(inifile); /* setup video stuff */ initvideo(Output); _harderr(hhandler); /* capture INT 24 handler */ program_args(argv,drives,dsk); /* check command line parameters */ /* set disk to use if an arg */ return cdisk; } /*** *program_args - Check command line arguments, set global prameters etc. * * Args: same as for setup() * Return: void * ****/ static void program_args(char **argv, int drives[], unsigned int *dsk) { int c; int tempd; if (*++argv) { do { c=tolower(**argv); if (c == '-') /* turn things off */ { switch (*++*argv) { case '?': goto Help; case 'D': Debug=FALSE; break; case 't': Translate=FALSE; break; case 's': Save=FALSE; break; case 'r': Restore=FALSE; break; case 'f': Files=FALSE; break; case 'h': Home=FALSE; break; default: break; } } else if (c == '/') /* do/set things */ { switch (*++*argv) { case 's': ++*argv; if (**argv == '\0') ++argv; switch(**argv) { case 'B': set_sector = 0; break; case 'F': set_sector = reserved_secs + 1; break; default: if (isdigit(**argv)) set_sector = atoi(*argv); if (isalpha(**argv)) strcpy(set_file,*argv); break; } break; case '@': Signon = 0; break; case 'h': /* help ! */ case '?': Help: printc(Title); /* display (centered) logo */ printc(Version); printc(Copyr); disptext(com_line_text); exit(0); break; case 'm': /* minimize memory */ min_mem = 1; break; case 'x': /* set INI file name */ ++*argv; if (**argv) strcpy(inifile,*argv); else if (**(argv+1)) strcpy(inifile,*++argv); break; case 'r': /* set Restore/Save file name */ ++*argv; if (**argv) strcpy(savfile,*argv); else if (**(argv+1)) strcpy(savfile,*++argv); break; case 'f': /* find string arg */ ++*argv; if (**argv) /* be careful of space after 'f' */ { find_flag = 1; strcpy(findstr,*argv); } else if (**(argv+1)) { find_flag = 1; strcpy(findstr,*++argv); } break; case '5': BigScreen = 1; break; default: break; } } else if (c == '+') /* turn things on */ { switch (*++*argv) { case 'D': Debug=TRUE; break; case 't': Translate=TRUE; break; case 's': Save=TRUE; break; case 'r': Restore=TRUE; break; case 'f': if (find_flag == 1) find_flag = 2; /* index files AFTER find() */ Files = TRUE; break; case 'h': Home=TRUE; break; default: break; } } else if (isalpha(c)) /* disk drive letter */ { tempd=toupper(**argv)-'@'; /* make valid */ if (drives[tempd]) /* check it */ { *dsk=tempd; /* log it */ Restore=FALSE; /* drive spec higher precedence */ /*Save=FALSE;*/ /* than Restore */ } } } while (*++argv); } } /*** *getdriveinfo - makes a list of all valid drives, set the number * of drives * RETURNS current drive * * 1.0 02-Sep-1994 moved from setup() ****/ static int getdriveinfo(int *drives, unsigned int *num) { unsigned i,tempd,cdisk; *num = 0; /* initialize */ _dos_getdrive(&cdisk); /* get current drive */ for (i = 0; i < MAX_DRIVE; i++) /* loop to verify drives */ { _dos_setdrive(i,&tempd); /* try and set */ _dos_getdrive(&tempd); /* see if it was set */ if (i == tempd) /* if it was set */ { drives[i] = TRUE; /* then the drive is real */ ++(*num); /* increment count */ } else drives[i] = FALSE; } _dos_setdrive(cdisk,&tempd); /* reset current disk */ return cdisk; } /*** *set_inifile - Form the INI filespecs. * * 1.1 29-Nov-1994 prompt variable string now global to work * with MSC 8.0 * ****/ static void set_inifile(char *argv) { unsigned i,tempd; char *tempc; strcpy(comspec,getenv("COMSPEC")); /* get where COMMAND.COM is */ strcpy(promptvar,"PROMPT="); strcat(promptvar,getenv("PROMPT")); /* change prompt for shell */ strcat(promptvar,"(DE)"); putenv(promptvar); tempd = 1; /* for INI file test */ if ((tempc = getenv("INIT")) != NULL) { strcpy(savfile,tempc); /* get env dir */ strcpy(inifile,tempc); if (inifile[strlen(inifile)-1]!='\\') { strcat(savfile,"\\"); strcat(inifile,"\\"); } strcat(savfile,disked_sav); strcat(inifile,disked_ini); tempd = !exist(inifile); } if (tempd) /* if INI file not in dir */ { if (exist(disked_ini)) { strcpy(inifile,disked_ini); strcpy(savfile,disked_sav); return; } strcpy(savfile,argv); /* get where DISKED resides */ strcpy(inifile,argv); i=strlen(inifile); inifile[--i]='I'; inifile[--i]='N'; inifile[--i]='I'; i=strlen(savfile); savfile[--i]='V'; savfile[--i]='A'; savfile[--i]='S'; } } /*** *startup() - login drive and do startup stuff like index files, * set to particular spot, etc. * * Args: char *curdir gets set to current directory * UNIT cdisk current disk * * Returns: void * * NOTES: The disk to use is the global 'disk' which has been * previously set (by setup()). * * * 1.1 03-Feb-1994 set_sector * ver 1.0 22-Jan-1994 ****/ extern void startup(char *ccurdir, unsigned int cdisk) { int c,status; /* get current directory, and save it for exit */ _getcwd(curdir,_MAX_DIR); _getcwd(ccurdir,_MAX_DIR); /* login drive and if error find out what to do */ while ((status = logdisk(disk)) > DISK_OK) { printerror(Debug); if (disk == cdisk) /* if disk is current disk */ exit(2); /* just quit */ print(" %c: Use current? (or Retry) ",disk+'@'); if ((c = input()) == 'y' || c == 'Y') /* use current drive ? */ disk = cdisk; /* yes, try it */ else if (tolower(c) != 'r') /* try again ? */ exit(0); /* no, quit */ output('\n'); } /* allocate memory for sector buffers and file buffer */ setupmem(); /* First do Special Commands which bypass normal start-up sequence only one for now: /f{text}. Note that the order of /f and +|-f on the command line is followed. */ if (find_flag) /* find text via command line */ { do_find(); } /* end of Special Commands */ else { if (Signon == TRUE) disptext(signon_text); /* signon text */ if (Files > 0) do_files(); /* index files */ else if (Signon == TRUE) /* use the delay of do_files() */ { /* for the pause */ pause(); output('\n'); } if (!Files) /* didn't index so get volume label */ get_volume(volume); do_set(cdisk); /* find out what sector to start at */ if (!(Files && !Home && Translate)) /* display disk parameters */ dparams(curdir); /* if not dir display */ print("\n\n\t'/' for help"); } /* Now display any errors */ if (error.num != -1) /* if error */ { output('\n'); /* place the message */ printerror(Debug); /* before the dump */ } drive_status(status); /* display anything weird */ if (Restore) { if (Display && !Verify) print("restoring..."); if (Verify && getver(" restore",0)) getinit(savfile,INIT_RESTORE); else Restore = FALSE; } } /*** *do_find - Search for text specified on command line. * The complexity is due to whether or no to index the * files before or after seaching (command line order). * ****/ static void do_find(void) { int i; rootsector(); /* set to root */ if (Display) { printc(Title); /* display (centered) logo */ printc(Copyr); /* instead of drive parameters */ } if (Files && find_flag == 1) /* index files first? */ i = do_files(); else i = 1; if (error.num != -1) /* was there an error? */ { output('\n'); printerror(Debug); output('\n'); } if (i == 0 && Verify) getver(" find",MOV_YN); print("\nfind %s",findstr); if ((i = find(1,0,0)) >= 0) /* find text */ { print("found at "); pn(i,Radix); } if (Files && find_flag == 2) /* index files now? */ do_files(); } /*** *do_set - Set to the proper starting sector. More complexity * due to command line arguments. * * 0.1 19-Mar-1995 changed set file for filetrack() ****/ static void do_set(unsigned int cdisk) { int i,tempd; long templ; char tempstr[67]; if (Restore) /* if Restored */ { /* read current sector */ readsector(); } else if (set_sector != -1L) /* set to a sector? */ { setsector(set_sector); } else if (set_file[0] != '\0') /* set to file? */ { if ((tempd = file_start(set_file)) != 0) /* if found */ { setcluster(tempd); /* set to first sector */ if (Files) { tempd = clusters[tempd]; if ((i = filetrack(gfile(tempd),tempd)) != 1) print("file track error: %d",i); } } else rootsector(); /* not found */ } else if (Files && !Home) /* if indexed files and not go home */ { /* set to current directory */ strcpy(tempstr,&curdir[2]); if ((tempd = findfile(tempstr)) != 0) setcluster(tempd); else rootsector(); } else if (cdisk == disk) /* else goto current directory */ { set_sector = templ = cwdstart(); dir_cluster = sectortocluster(templ); setsector(templ); } else rootsector(); } /*** *do_files - Index the files. * ****/ static int do_files(void) { if (Display) bprint(" indexing..."); files_indexed = Files = initfiles(); if (Display) clreol(); return files_indexed; } /*** *setupmem - * ****/ static void setupmem(void) { unsigned u; /* Yeah I can make it a long and get a huge pointer for a really large buffer, but so far that large of a buffer has not been needed. Next time Im bored... */ /* try and get memory */ for (u = (min_mem) ? 8192U : 65024U ; ; u -= 512U) if ((data_buf = (unsigned char *)alloc(u,sizeof(char)))!=NULL) break; if (u < 512U*10U) quit(NO_MEM); max_bytes = u; /****** can only alloc sector buffer if sector size is known ******/ if ((sec_buf = alloc(sec_size,sizeof(char))) == NULL) quit(NO_MEM); if ((save_sec = alloc(sec_size,sizeof(char))) != NULL) if ((spare_sec = alloc(sec_size,sizeof(char))) == NULL) freep(save_sec); } /*** *newdisk() - consolated disk change stuff * * 1.3 23-Mar-1995 tempd != disk test for 0'ing tagged * ver 1.2 19-Jan-1994 'removable' test ****/ extern int newdisk(int tempd) { int i; unsigned int temps; temps = sec_size; /* save current sector size */ savesector(); /* and sector data */ if ((i = logdisk(tempd)) > DISK_OK) { restoresector(); disk_moved = 0; return 0; /* RETURN */ } drive_status(i); if (temps != sec_size) /* new sector size */ { sec_buf = newalloc(sec_buf,sec_size*sizeof(char)); if (sec_buf == NULL) { print("\nReallocation Failure.\n"); print("Sorry, but I am too confused to continue...\n"); exit(3); } save_sec = newalloc(save_sec,sec_size*sizeof(char)); spare_sec = newalloc(spare_sec,sec_size*sizeof(char)); } _getcwd(curdir,_MAX_DIR); /* get current directory */ n_files = 1; /* setup for files */ n_dirs = 1; if (Files) /* if to index them */ { if (files_indexed) /* if already */ { hugefreep(clusters); /* free them first */ hugefreep(files); } do_files(); } if (!Files) get_volume(volume); set_sector = -1L; /* kill original start-sector */ if (Home) rootsector(); else { if (log_sector >= num_sectors) lastsector(); else readsector(); } return 1; } /*** * Handler to deal with hard error codes. Since DOS is not reentrant, * it is not safe to use DOS calls for doing I/O within the DOS Critical * Error Handler (int 24h) used by _harderr. Therefore, screen output and * keyboard input must be done through the BIOS. ****/ #if defined (_MSC_VER) && (_MSC_VER > 600) #pragma warning (disable:4100) #endif #ifdef __BORLANDC__ #pragma warn -par #endif #ifdef __WATCOMC__ int _far hhandler(unsigned deverr, unsigned doserr, unsigned _far *hdr) #else void _cdecl _far hhandler(unsigned deverr, unsigned doserr, unsigned _far *hdr) #endif { if (doserr <= 0x0C) error.msg = harderr_list[doserr]; error.num = doserr; error.mod = error.func = "harderr"; _hardretn(doserr&0xff); #ifdef __WATCOMC__ return _HARDERR_IGNORE; #endif } #ifdef __BORLANDC__ #pragma warn +par #endif #if defined (_MSC_VER) && (_MSC_VER > 600) #pragma warning (default:4100) #endif /* exit() shell */ static void quit(int e) { print(err_msg[e]); exit(e); } /* common index files stuff */ static void drive_status(int status) { if (removable && status == USE_DPB) /* floppy BOOT record bad */ print("\nInvalid BOOT record. Using DPB."); if (!removable && status == USE_BOOT) /* non-floppy no DPB available */ print("\nDPB not supported (ramdrive?)"); }