/****************************************************************************
*
*  TITLE:        FSACCESS utility
*
*  DESCRIPTION:  alter the INT 21 filter's drive map for the user
*
*  INPUT:        command line arguments - drives to access
*
*  OUTPUT:       change drive map in memory
*
*  SIDE EFFECTS: will load INT 21 filter if not present
*
*  REVISION HISTORY:
*
*    B001  9/4/91  CP20 PTR B726219  Mark Rogalski
*          Add check to see if running in real mode.
*
*    B002  10/26/91  CP20 PTR B730291  Mark Rogalski
*          Place help text in oso001 message file. Get mapped drive message
*          from that file too.
*
*
*
*****************************************************************************/


#include <os2std.h>
#include <doscalls.h>
#include <stdio.h>
#include <ctype.h>
#include <comsub.h>
#include <basemid.h>
#include <utilmd42.h>
#include <utilmd25.h>                                                /*BN001*/


#define  NOT_SYMBOL  '!'
#define  EMPTY       0xff
#define  UN_MAP      0
#define  LOCK_DRIVE         0x0000         /* IOCTL FUNCTION 00             */
#define  UNLOCK_DRIVE       0x0001         /* IOCTL FUNCTION 01             */
#define  NOT_REMOVABLE      0xfff1
#define  PROTECTMODE        1                                        /*BN001*/


int  process_args(int,char **);
char get_token(int, char **);
void show_mappings(void);
int  set_map(char,char);
int  far pascal filter_in(char far * far *);        /* assembler call */
int  far pascal cur_drive(void);                    /* assembler call */
int  far pascal vdsk_release(void);                 /* assembler call */
int  far pascal lock_drive_req(unsigned,unsigned);  /* assembler call */


int  rc = 0;
int  arg_ptr = 1;            /* start at first arg */
int  pos_ptr = 0;            /* start at first char */
int  curdrv;                 /* number of current drive */
char far *drive_map;

main(argc, argv, envp)
  int argc;
  char *argv[];
  char *envp[];
{
 char mode;                                                          /*BN001*/

  DOSGETMACHINEMODE((char far *)&mode);                              /*BN001*/
  if (mode == PROTECTMODE)                                           /*BN001*/
    rc = MSG_REAL_MODE_ONLY;                                         /*BN001*/

/* see if this is a call for help */

  if (!rc && argc == 2 && argv[1][0] == '/' && argv[1][1] == '?')    /*BC001*/
   {
    computmsg((char *)0,                                             /*BN002*/
              0,                                                     /*BN002*/
              MSG_FSA_HELP_TEXT,                                     /*BN002*/
              (char *)"OSO001.MSG",                                  /*BN002*/
              0,                                                     /*BN002*/
              0,                                                     /*BN002*/
              (char *)0,                                             /*BN002*/
              0);                                                    /*BN002*/
    return(0);
   }

/* determine if filter is installed. if not report error */

  if (!rc && !filter_in(&drive_map))                                 /*BC001*/
      rc = MSG_FSA_FILTER_NOT_PRESENT;

/* if no args then show current mappings else process args */

  if (rc == 0)
   {
    if (argc == 1)
     {
      show_mappings();
     }
    else
     {
      curdrv = cur_drive();                      /* get current drive */
      rc = process_args(argc,argv);
     }
   }

  if (rc)                            /* if there was error print error msg */
   {
    computmsg((char *)0,
              0,
              rc,
              (char *)"OSO001.MSG",
              0,
              0,
              (char *)0,
              0);
   }

  return(rc);
}



void show_mappings()
{
 int i;
 unsigned char *ivtable[2];    /* table for computmsg arguments        BN002*/
 char local[2];                                                      /*BN002*/
 char drive[2];                                                      /*BN002*/

  local[1] = '\0';              /* setup null to terminate arg         BN002*/
  drive[1] = '\0';                                                   /*BN002*/
  ivtable[0] = local;           /* setup argument table to point to    BN002*/
  ivtable[1] = drive;           /* drive letter locations              BN002*/

  for (i=0; i < 26; i++ )
   {
    if (drive_map[i])
     {
      local[0] = (char)(i + 'A');                                    /*BN002*/
      drive[0] = drive_map[i];                                       /*BN002*/

      computmsg(ivtable,                                             /*BN002*/
              2,                    /* two arguments  */             /*BN002*/
              MSG_FSA_MAPPED_DRIVE,                                  /*BN002*/
              (char *)"OSO001.MSG",                                  /*BN002*/
              0,                                                     /*BN002*/
              0,                                                     /*BN002*/
              (char *)0,                                             /*BN002*/
              0);                                                    /*BN002*/
      }                                                              /*BN002*/
   }
}


process_args(argc,argv)
int argc;
char **argv;
{
 char turnon;                     /* turn mapping on or off */
 char i;
 unsigned char token = EMPTY;     /* start with no token read in */
 char first, second;

  while (token && rc == 0)        /* while there are arguments left & no error*/
   {
    if (token == EMPTY)           /* if we don't have a token, get one */
     {
      token = get_token(argc,argv);
      if (!token) break;
     }

    if (token == NOT_SYMBOL)      /* if not op set flag and get next token */
     {
      turnon = FALSE;
      token = get_token(argc,argv);
     }
    else
      turnon = TRUE;

    if ( isalpha(token) )
     {
      first = token;
      token = get_token(argc,argv);
      if (token == '=')                          /* map local to OS2 */
       {
        second = get_token(argc,argv);
        if (!second || !isalpha(second))
          return (MSG_FSA_SYN_MAP_TWO_LETTERS);
        rc = set_map((char)(first - 'A'),(char)(turnon ? second : UN_MAP));
        token = EMPTY;
       }
      else if (token == '-')                     /* access range */
       {
        second = get_token(argc,argv);
        if (!second || !isalpha(second))
          return (MSG_FSA_SYN_NOT_FIRST_AND_LAST);
        for (i=first; i <= second; i++ )
         {
          rc = set_map((char)(i - 'A'),(char)(turnon ? i : UN_MAP));
          if (rc) break;
         }
        token = EMPTY;
       }
      else                                       /* access single drive */
       {
        rc = set_map((char)(first - 'A'),(char)(turnon ? first : UN_MAP));
       }
     }
    else
     {
      if (turnon)
        return(MSG_FSA_SYN_SPECIFY_LETTER);
      else
        return(MSG_SYN_NOT_SYM_MUST_PRECEDE);
     }
   }
  return(rc);
}


set_map(element,value)
char element, value;
{
int rc;

 if (drive_map[element] == value)        /* no need to change what's there */
   return(0);

 if (element == (char)curdrv)            /* can't change current drive     */
   return(MSG_FSA_ACCESSED_DRIVE_IN_USE);


/* if un-mapping drive - try to lock it - un-map only if lockable          */
/*                                        else say drive not ready         */
/* if mapping drive - un-map it first - then unlock it                     */
/*                  - if A: then call VDSK too                             */

 if (value == UN_MAP)                       /* try to lock drive */
  {
   rc = lock_drive_req(LOCK_DRIVE,element + 1);

   if (rc && rc != NOT_REMOVABLE)
     return(MSG_DRIVE_NOT_READY);

   drive_map[element] = value;
  }
 else                                       /* unlock drive */
  {
   drive_map[element] = value;
   lock_drive_req(UNLOCK_DRIVE,element + 1);

   if (element == 0)                        /* if a: drive do release */
     vdsk_release();
  }

 return(0);
}


char get_token(argc,argv)
int argc;
char **argv;
{
 char token = 0;                    /* default no token */

/* valid tokens are capital alphas, -, = and ! */

  if (arg_ptr < argc)
   {
    token = argv[arg_ptr][pos_ptr++];
    if (argv[arg_ptr][pos_ptr] == ':')
     {
      pos_ptr++;
     }
    if (argv[arg_ptr][pos_ptr] == '\0')
     {
      arg_ptr++;
      pos_ptr = 0;
     }
   }

  return((char) toupper(token));
}


