Metropoli BBS
VIEWER: setup.c MODE: TEXT (ASCII)
/***
*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 <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <string.h>
#include <ctype.h>
#include <direct.h>
#ifdef __BORLANDC__
#include <conio.h>
#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?)");
}
[ RETURN TO DIRECTORY ]