/*--------------------------------------------------------------------*/
/*    c o n f i g u r . c                                             */
/*                                                                    */
/*    Support routines for UUPC/extended                              */
/*                                                                    */
/*    Changes Copyright 1990, 1991 (c) Andrew H. Derbyshire           */
/*                                                                    */
/*    History:                                                        */
/*       21Nov1991 Break out of lib.c                          ahd    */
/*--------------------------------------------------------------------*/

/*--------------------------------------------------------------------*/
/*    Changes Copyright (c) 1989 by Andrew H. Derbyshire.             */
/*                                                                    */
/*    Changes Copyright (c) 1990-1993 by Kendra Electronic            */
/*    Wonderworks.                                                    */
/*                                                                    */
/*    All rights reserved except those explicitly granted by the      */
/*    UUPC/extended license agreement.                                */
/*--------------------------------------------------------------------*/

/*--------------------------------------------------------------------*/
/*                          RCS Information                           */
/*--------------------------------------------------------------------*/

/*
 *    $Id: CONFIGUR.C 1.10 1993/04/15 03:17:21 ahd Exp $
 *
 *    Revision history:
 *    $Log: CONFIGUR.C $
 *     Revision 1.10  1993/04/15  03:17:21  ahd
 *     Add bounce system option
 *
 *     Revision 1.9  1993/04/11  00:31:31  dmwatt
 *     Global edits for year, TEXT, etc.
 *
 *     Revision 1.8  1993/04/05  04:32:19  ahd
 *     Set timezone, windows input mode in common routine
 *
 *     Revision 1.7  1993/04/04  04:57:01  ahd
 *     Default configuration directory from UUPCSYSRC
 *     Default system directories from Configuration directory
 *
 *     Revision 1.6  1993/03/06  22:48:23  ahd
 *     Don't fall off end of shorter tables
 *
 *     Revision 1.5  1993/01/23  19:08:09  ahd
 *     Add Windows/NT to allowed environments
 *
 * Revision 1.4  1992/12/01  04:37:03  ahd
 * Add SpeedOverMemory
 *
 * Revision 1.3  1992/11/22  20:58:55  ahd
 * Normalize directories as read
 * Use strpool to allocate const strings
 *
 * Revision 1.2  1992/11/19  02:56:47  ahd
 * drop rcsid
 *
 * Revision 1.1  1992/11/16  05:00:26  ahd
 * Initial revision
 *
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>

#ifndef __GNUC__
#include <io.h>
#endif

/*--------------------------------------------------------------------*/
/*                    UUPC/extended include files                     */
/*--------------------------------------------------------------------*/

#include "lib.h"
#include "hlib.h"
#include "timestmp.h"
#include "pushpop.h"

/*--------------------------------------------------------------------*/
/*                          Global variables                          */
/*--------------------------------------------------------------------*/

currentfile();

boolean bflag[F_LAST];        /* Initialized to zero by compiler     */

char *E_aliases = NULL;
char *E_anonymous = NULL;
char *E_archivedir = NULL;
char *E_confdir = NULL;
char *E_domain = NULL;
char *E_altsignature = NULL;
char *E_backup = NULL;
char *E_charset = NULL;
char *E_editor = NULL;
char *E_filesent = NULL;
char *E_inmodem = NULL;
char *E_mailext = NULL;
char *E_pager = NULL;
char *E_signature = NULL;
char *E_uuxqtpath = NULL;
char *E_fdomain = NULL;
char *E_homedir = NULL;
char *E_localdomain = NULL;
char *E_mailbox = NULL;
char *E_maildir = NULL;
char *E_mailserv = NULL;
char *E_name = NULL;
char **E_internal = NULL;
char *E_newsdir = NULL;
char *E_newsserv = NULL;
char *E_nodename = NULL;
char *E_organization = NULL;
char *E_postmaster = NULL;
char *E_pubdir = NULL;
char *E_replyto = NULL;
char *E_spooldir = NULL;
char *E_tempdir = NULL;
char *E_version = NULL;
char *E_uncompress = NULL;
static char *dummy = NULL;
INTEGER E_priority = -99;
INTEGER E_prioritydelta = -99;

INTEGER E_maxhops = 20;                                     /* ahd */

/*--------------------------------------------------------------------*/
/*                       Local emumerated types                       */
/*--------------------------------------------------------------------*/

typedef enum {
      OS2_ENV,
      DOS_ENV,
      WIN32_ENV,
      UNKNOWN_ENV
      } ENV_TYPE;

#ifdef WIN32
static ENV_TYPE active_env = WIN32_ENV;
#else
static ENV_TYPE active_env = DOS_ENV;
#endif

static boolean getrcnames(char **sysp,char **usrp);

/*--------------------------------------------------------------------*/
/*  The following table controls the configuration files processing   */
/*--------------------------------------------------------------------*/

static CONFIGTABLE envtable[] = {
   {"aliases",      &E_aliases,      B_TOKEN|B_MUA},
   {"altsignature", &E_altsignature, B_TOKEN|B_MUA},
   {"anonymouslogin",
                    &E_anonymous,    B_GLOBAL|B_TOKEN|(B_ALL & ~ B_MAIL)},
   {"archivedir",   &E_archivedir,   B_GLOBAL|B_PATH|B_ALL},
   {"backupext",    &E_backup,       B_TOKEN|B_MUA},
   {"confdir",      &E_confdir,      B_GLOBAL|B_PATH|B_ALL},
   {"charset",      &E_charset,      B_TOKEN|B_GLOBAL|B_SPOOL},
   {"domain",       &E_domain,       B_REQUIRED|B_GLOBAL|B_TOKEN|B_ALL},
   {"editor",       &E_editor,       B_STRING|B_MUA|B_NEWS},
   {"filesent",     &E_filesent,     B_TOKEN|B_MUA|B_NEWS},
   {"folders",      &dummy,          B_PATH|B_MUSH },
   {"fromdomain",   &E_fdomain,      B_GLOBAL|B_MAIL|B_NEWS|B_TOKEN},
   {"home",         &E_homedir,      B_PATH|B_REQUIRED|B_ALL},
   {"inmodem",      &E_inmodem,      B_GLOBAL|B_TOKEN|B_UUCICO},
   {"internalcommands", (char **)   &E_internal,
                                     B_GLOBAL|B_LIST|B_UUXQT},
   {"localdomain",  &E_localdomain,  B_GLOBAL|B_TOKEN|B_MAIL},
   {"mailbox",      &E_mailbox,      B_REQUIRED|B_TOKEN|B_ALL},
   {"mailext",      &E_mailext,      B_TOKEN|B_MAIL},
   {"maildir",      &E_maildir,      B_GLOBAL|B_PATH|B_ALL},
   {"mailserv",     &E_mailserv,     B_REQUIRED|B_GLOBAL|B_TOKEN|B_ALL},
   {"maximumhops",  (char **) &E_maxhops,
                                     B_MTA | B_INTEGER | B_GLOBAL},
   {"mushdir",      &dummy,          B_GLOBAL|B_PATH|B_MUSH},
   {"name",         &E_name,         B_REQUIRED|B_MAIL|B_NEWS|B_STRING},
   {"newsdir",      &E_newsdir,      B_GLOBAL|B_PATH|B_ALL},
   {"newsserv",     &E_newsserv,     B_GLOBAL|B_TOKEN|B_NEWS},
   {"nodename",     &E_nodename,     B_REQUIRED|B_GLOBAL|B_TOKEN|B_ALL},
   {"options",      (char **) bflag, B_ALL|B_BOOLEAN},
   {"organization", &E_organization, B_STRING|B_MAIL|B_NEWS},
   {"pager",        &E_pager,        B_STRING|B_MUA|B_NEWS},
   {"path",         &E_uuxqtpath,    B_STRING|B_UUXQT|B_GLOBAL},
   {"postmaster",   &E_postmaster,   B_REQUIRED|B_GLOBAL|B_TOKEN|B_MTA},
   {"pubdir",       &E_pubdir,       B_GLOBAL|B_PATH|B_ALL},
   {"priority",     (char **) &E_priority,
                                     B_INTEGER |B_UUCICO},
   {"prioritydelta",(char **) &E_prioritydelta,
                                     B_INTEGER |B_UUCICO},
   {"replyto",      &E_replyto,      B_TOKEN|B_MAIL|B_NEWS},
   {"signature",    &E_signature,    B_TOKEN|B_MUA|B_NEWS},
   {"spooldir",     &E_spooldir,     B_GLOBAL|B_PATH|B_ALL},
   {"tempdir",      &E_tempdir,      B_GLOBAL|B_PATH|B_ALL},
   {"uncompress",   &E_uncompress,   B_GLOBAL|B_STRING|B_NEWS },
   {"version",      &E_version,      B_TOKEN|B_INSTALL},
   {"rmail",        &dummy,          B_OBSOLETE },
   {"rnews",        &dummy,          B_OBSOLETE },
   { nil(char) }
}; /* table */

/*--------------------------------------------------------------------*/
/*               Boolean options shared by all programs               */
/*--------------------------------------------------------------------*/

FLAGTABLE configFlags[] = {
 { "askcc",       F_ASKCC,       B_LOCAL},
 { "autoedit",    F_AUTOEDIT,    B_LOCAL},
 { "autoinclude", F_AUTOINCLUDE, B_LOCAL},
 { "autoprint",   F_AUTOPRINT,   B_LOCAL},
 { "autosign",    F_AUTOSIGN,    B_LOCAL},
 { "backup",      F_BACKUP,      B_LOCAL},
 { "doskey",      F_DOSKEY,      B_LOCAL},
 { "dot",         F_DOT,         B_LOCAL},
 { "expert",      F_EXPERT,      B_LOCAL},
 { "forwardsave", F_SAVERESENT,  B_LOCAL},
 { "fromsep",     F_FROMSEP,     B_LOCAL},
 { "pager",       F_PAGER,       B_LOCAL},
 { "purge",       F_PURGE,       B_LOCAL},
 { "save",        F_SAVE,        B_LOCAL},
 { "suppresscopyright",
                  F_SUPPRESSCOPYRIGHT,
                                 B_LOCAL},
 { "speedovermemory",
                  F_SPEEDOVERMEMORY,
                                 B_LOCAL},
 { "verbose",     F_VERBOSE,     B_LOCAL},
 { "undelete",    F_UNDELETE,    B_LOCAL},

 { "bang",        F_BANG,        B_GLOBAL},
 { "bounce",      F_BOUNCE,      B_GLOBAL},
 { "collect",     F_COLLECTSTATS,B_GLOBAL},
 { "directory",   F_DIRECT,      B_GLOBAL},
 { "escape",      F_ESCAPE,      B_GLOBAL},
 { "hpfs",        F_HPFS,        B_GLOBAL},
 { "history",     F_HISTORY,     B_GLOBAL},
 { "kanji",       F_KANJI,       B_GLOBAL},
 { "monocase",    F_ONECASE,     B_GLOBAL},
 { "multiqueue",  F_MULTI,       B_GLOBAL},
 { "multitask",   F_MULTITASK,   B_GLOBAL},
 { "snews",       F_SNEWS,       B_GLOBAL},
 { "syslog",      F_SYSLOG,      B_GLOBAL},
 { "symmetricgrades",
                  F_SYMMETRICGRADES,
                                 B_GLOBAL},

 { nil(char) }
}           ;

/*--------------------------------------------------------------------*/
/*    p r o c e s s c o n f i g                                       */
/*                                                                    */
/*    Handle a single line of a configuration file                    */
/*--------------------------------------------------------------------*/

boolean processconfig(char *buff,
                  SYSMODE sysmode,
                  CONFIGBITS program,
                  CONFIGTABLE *table,
                  FLAGTABLE *btable)
{
   CONFIGTABLE *tptr;
   char *cp;
   char *keyword;
   ENV_TYPE target_env;

/*--------------------------------------------------------------------*/
/*                break out the keyword from its value                */
/*--------------------------------------------------------------------*/

   if ((cp = strchr(buff, '=')) == nil(char))
   {
      printmsg(0,"Missing equals sign after keyword \"%s\", ignored",
                  buff);
      return TRUE;
   }
   *cp++ = '\0';
   strlwr(buff);

/*--------------------------------------------------------------------*/
/*    Determine if the keyword should processed in this environment   */
/*--------------------------------------------------------------------*/

   keyword = strchr( buff, '.' );   /* Look for environment          */

   if ( keyword == NULL )     /* No environment?                     */
   {
      keyword = buff;         /* Then buffer starts with keyword     */
      target_env = active_env;
   }
   else {
      *keyword++ = '\0';      /* Terminate environment string        */

      if ( equal( buff, "dos" ))
         target_env = DOS_ENV;
      else if ( equal( buff, "os2" ))
         target_env = OS2_ENV;
      else if ( equal( buff, "win32" ))
         target_env = WIN32_ENV;
      else {
         printmsg(0,"Unknown environment \"%s\", keyword \"%s\" ignored",
               buff, keyword );
         return FALSE;
      } /* else */
   } /* else */

/*--------------------------------------------------------------------*/
/*                    Scan the table for its value                    */
/*--------------------------------------------------------------------*/

   for (tptr = table; tptr->sym != nil(char); tptr++)
   {
      boolean error = FALSE;
      if (equal(keyword, tptr->sym)) {
/*--------------------------------------------------------------------*/
/*            Skip the keyword because of the environment?            */
/*--------------------------------------------------------------------*/
        if (active_env != target_env )
            printmsg(2,"%s-only keyword \"%s\" skipped.",
                        buff, keyword);
/*--------------------------------------------------------------------*/
/*                      Handle obsolete options                       */
/*--------------------------------------------------------------------*/
        else if (tptr->bits & B_OBSOLETE)
            printmsg(2,"Obsolete keyword \"%s\" ignored.", keyword);
/*--------------------------------------------------------------------*/
/*                  Handle mis-placed system options                  */
/*--------------------------------------------------------------------*/
        else if ((tptr->bits & B_GLOBAL) && (sysmode != SYSTEM_CONFIG))
            printmsg(0,
               "User specified system keyword \"%s\" ignored.",
               keyword);
/*--------------------------------------------------------------------*/
/*                       Handle Boolean options                       */
/*--------------------------------------------------------------------*/
         else {
            if (tptr->bits & B_BOOLEAN)
               options(cp, sysmode, btable, (boolean *) tptr->loc);
/*--------------------------------------------------------------------*/
/*                       Handle integer values                        */
/*--------------------------------------------------------------------*/
            else if (tptr->bits & B_INTEGER)
            {
               int *value = (int *) tptr->loc;
               cp = strtok(cp,WHITESPACE);
               if ( equal(cp,"0"))
                  *value = 0;
               else {
                  *value = atoi(cp);
                  if ( *value == 0)
                  {
                     printmsg(0,
                        "Unable to convert \"%s\" value \"%s\" to integer",
                        keyword, cp);
                     error = TRUE;
                  } /* if */
               } /* else */
            } /* else */
/*--------------------------------------------------------------------*/
/*                       Handle lists of tokens                       */
/*--------------------------------------------------------------------*/
            else if ((tptr->bits & program) && (tptr->bits & (B_LIST | B_CLIST)))
            {
               char **list = malloc( (MAXLIST+1) * sizeof (*list));
               char *colon;
               int words;

               checkref( list );

               if (tptr->bits & B_CLIST)  /* Use colon as delimiter? */
                  while ( (colon = strchr( cp , ':')) != NULL)
                     *colon = ' ';     /* Make colons spaces ...           */

               words = getargs(cp, list);
               if( words > MAXLIST)
                  panic();

               if (words > 0)
               {
                  if ( *(tptr->loc) )
                     free( *(tptr->loc) );
                  list = realloc( list, (words+1) * sizeof(*list));
                  checkref( list );
                  *(tptr->loc) = (char *) list;
                  list[words] = NULL;

                  while( *list != NULL)
                  {
                     if (strlen(*list))
                     {
                        *list = newstr(*list);
                        checkref( *list++ );
                     }
                     else
                        *list++ = "";
                  } /* while */
               } /* if (words > 0) */
               else {
                  printmsg(0,"No parameters given for keyword \"%s\"",
                           keyword);
                  error = TRUE;
               } /* else */
            } /* else if */
/*--------------------------------------------------------------------*/
/*                  Handle single tokens and strings                  */
/*--------------------------------------------------------------------*/
            else if (tptr->bits & program)
            {
               while( *cp == ' ' )     /* Trim leading whitespace    */
                  cp++;

               if (*cp == '\0')
               {
                  error = TRUE;
                  printmsg(0,"No parameter given for keyword \"%s\""
                           ", ignored.",
                           keyword);
               } /* if */

               if (tptr->bits & B_TOKEN)  /* One word value?      */
                  cp = strtok(cp,WHITESPACE); /* Yes --> Tokenize */

               if (tptr->bits & B_NORMAL)  /* Normalize path?     */
                  cp = normalize( cp );

               if (tptr->bits & B_MALLOC)  /* Allocate normally?  */
               {
                  *(tptr->loc) = strdup(cp); /* Save string          */
                  checkref( *(tptr->loc) );  /* Verify malloc()      */
               }
               else
                  *(tptr->loc) = newstr(cp); /* Save string          */

            } /* else */
         } /* else */

         if (!error)
            tptr->bits |= B_FOUND;
         return TRUE;         /* Report we found the keyword      */
      } /* if (equal(keyword, tptr->sym)) */
   } /* for */

/*--------------------------------------------------------------------*/
/*      We didn't find the keyword; report failure to the caller      */
/*--------------------------------------------------------------------*/

   return FALSE;

} /* processconfig */

/*--------------------------------------------------------------------*/
/*    g e t c o n f i g                                               */
/*                                                                    */
/*    Process a single configuration file                             */
/*--------------------------------------------------------------------*/

boolean getconfig(FILE *fp,
                  SYSMODE sysmode,
                  CONFIGBITS program,
                  CONFIGTABLE *table,
                  FLAGTABLE *btable)
{

   char buff[BUFSIZ];
   char *cp;

   while(!(fgets(buff, sizeof buff, fp) == nil(char))) {

/*--------------------------------------------------------------------*/
/*                        Ingore comment lines                        */
/*--------------------------------------------------------------------*/

      if (*buff == '#')
         continue;            /* comment line   */

/*--------------------------------------------------------------------*/
/*                       Drop trailing new line                       */
/*--------------------------------------------------------------------*/

      if (*(cp = buff + strlen(buff) - 1) == '\n')
         *cp = '\0';

/*--------------------------------------------------------------------*/
/*                 Drop leading blanks on input line                  */
/*--------------------------------------------------------------------*/

      cp = buff;
      while( isspace( *cp ) )
         cp ++ ;

/*--------------------------------------------------------------------*/
/*                 If line was not blank, process it.                 */
/*--------------------------------------------------------------------*/

      if ( (*cp != '\0') && !processconfig(cp,sysmode,program,table,btable))
         printmsg(0,
               "Unknown keyword \"%s\" in %s configuration file ignored",
               buff, sysmode ? "system" : "user");

   } /*while*/

   return TRUE;

} /*getconfig*/

/*--------------------------------------------------------------------*/
/*    o p t i o n s                                                   */
/*                                                                    */
/*    Process a line of boolean option flags.                         */
/*--------------------------------------------------------------------*/

void options(char *s, SYSMODE sysmode , FLAGTABLE *flags, boolean *barray)
{
   char *token;

   strlwr(s);
   token = strtok(s,WHITESPACE);

   while (token != NULL)
   {
      size_t subscript;
      boolean hit = FALSE;
      boolean negate;
      negate = equaln(token,"no",2) && (strlen(token) > 2);

      for ( subscript=0; (flags[subscript].sym != NULL ) && !hit; subscript++)
      {
         if ((flags[subscript].bits & B_GLOBAL) && (sysmode != SYSTEM_CONFIG))
            continue;
         if (negate)
         {
            if (equal(&token[2],flags[subscript].sym))
            {
               barray[ flags[subscript].position ] = FALSE;
               hit = TRUE;
            }
         } /* if negate */
         else {
            if (equal(token,flags[subscript].sym))
            {
               barray[ flags[subscript].position ] = TRUE;
               hit = TRUE;
            }
         } /* else */
      } /* for */

      if (!hit)
         printf("Invalid or system option '%s' specified\n",token);

      token = strtok(NULL,WHITESPACE);  /* Step to next token on line */

   } /* while */
} /* options */

/*--------------------------------------------------------------------*/
/*    c o n f i g u r e                                               */
/*                                                                    */
/*    Define the global parameters of UUPC/extended                   */
/*--------------------------------------------------------------------*/

boolean configure( CONFIGBITS program)
{
   char *sysrc, *usrrc;
   FILE *fp;
   boolean success;
   char buf[BUFSIZ];
   int subscript = 0;
   char *s;

   CONFIGTABLE *tptr;

   static char *envlist[] = { "EDITOR",   "EDITOR",
                              "HOME",     "HOME",
                              "NAME",     "NAME",
                              "MAILBOX",  "MAILBOX",
                              "TEMP",     "TEMPDIR",
                              "TMP",      "TEMPDIR",
                              NULL } ;

   typedef struct _DEFAULTS {
      char **value;
      char *literal;
   } DEFAULTS;

   static DEFAULTS deflist[] = {
        {&E_archivedir,   "archive" },
        {&E_maildir,      "mail"    },
        {&E_newsdir,      "news"    },
        {&E_pubdir,       "public"  },
        {&E_spooldir,     "spool"   },
        {&E_tempdir,      "tmp"     },
        { NULL  }
        } ;

/*--------------------------------------------------------------------*/
/*     In Windows/NT, set the console input mode to non-linebased     */
/*--------------------------------------------------------------------*/

#ifdef WIN32
   setstdinmode();
#endif

/*--------------------------------------------------------------------*/
/*                         Set our time zone                          */
/*--------------------------------------------------------------------*/

   if (getenv("TZ") == NULL )
   {
      printmsg(0,"Environment variable TZ must be set!");
      panic();
   }
   tzset();                      /* Set up time zone information  */

/*--------------------------------------------------------------------*/
/*                  Determine the active environment                  */
/*--------------------------------------------------------------------*/

#ifndef __TURBOC__
#ifndef __GNUC__
   if (_osmode != DOS_MODE)
      active_env = OS2_ENV;
#endif
#endif

   if (!getrcnames(&sysrc, &usrrc))
      return FALSE;

/*--------------------------------------------------------------------*/
/*          Extract selected variables from our environment           */
/*--------------------------------------------------------------------*/

   while( envlist[subscript] != NULL )
   {
      s = getenv( envlist[subscript++] );

      if (s != NULL )
      {
         sprintf(buf,"%s=%s",envlist[subscript], s );
         processconfig( buf, SYSTEM_CONFIG, program, envtable, configFlags);
      } /* if (sysrc != NULL ) */

      subscript++;            /* Step to next environment var in list   */
   }

/*--------------------------------------------------------------------*/
/*          Determine configuration directory from UUPCSYSRC          */
/*--------------------------------------------------------------------*/

   E_confdir = normalize( sysrc );     // Make 'em all slashes

   s = strrchr( E_confdir, '/' );      // Get end of path component
   if ( s == NULL )                    // There WAS one, right?
   {                                   // Er, no, sorry.
      printmsg(0,"No path name in UUPCSYSRC: %s", sysrc);
      panic();
   }

   *s = '\0';                          // Terminate for Config Directory
   E_confdir = newstr( E_confdir );    // Save in permanent pool

/*--------------------------------------------------------------------*/
/*               Process the system configuration file                */
/*--------------------------------------------------------------------*/

   if ((fp = FOPEN(sysrc, "r",TEXT_MODE)) == nil(FILE))
   {
      printmsg(0, "Cannot open system configuration file \"%s\"", sysrc);
      printerr(sysrc);
      return FALSE;
   }

   PushDir( E_confdir );

   success = getconfig(fp, SYSTEM_CONFIG, program, envtable, configFlags);

   fclose(fp);
   if (!success)
   {
      PopDir();
      return FALSE;
   }

/*--------------------------------------------------------------------*/
/*                Process the user configuration value                */
/*--------------------------------------------------------------------*/

   if (usrrc != nil(char))
   {
      usrrc = normalize( usrrc );
      if ((fp = FOPEN(usrrc, "r",TEXT_MODE)) == nil(FILE))
      {
         printmsg(0, "Cannot open user configuration file \"%s\"", usrrc);
         PopDir();
         return FALSE;
      }

      success = getconfig(fp, USER_CONFIG, program, envtable, configFlags);
      fclose(fp);

      if (!success)
      {
         PopDir();
         return FALSE;
      }

   }

/*--------------------------------------------------------------------*/
/*                       Display our copyright                        */
/*--------------------------------------------------------------------*/

   if (! bflag[F_SUPPRESSCOPYRIGHT] &&
        (program != B_MTA) &&
        isatty(fileno(stdout)))
      fprintf(stdout,
"Changes and Compilation Copyright (c) 1990-1993 by Kendra Electronic\n"
"Wonderworks.  May be freely distributed if original documentation and\n"
"source is included.\n" );

/*--------------------------------------------------------------------*/
/*          Validate that all required parameters were given          */
/*--------------------------------------------------------------------*/

   for (tptr = envtable; tptr->sym != nil(char); tptr++)
   {

      if ((tptr->bits & (B_REQUIRED | B_FOUND)) == B_REQUIRED)
      {
         printmsg(0, "%s configuration parameter \"%s\" must be set.",
            (tptr->bits & B_GLOBAL) ? "System" : "User",
            tptr->sym);
         success = FALSE;
      } /* if */

   } /* for */

/*--------------------------------------------------------------------*/
/*                     Fill in derived parameters                     */
/*--------------------------------------------------------------------*/

   subscript = 0;
   while( deflist[subscript].value != NULL )
   {
      if ( *(deflist[subscript].value) == NULL )
         *(deflist[subscript].value) =
                     newstr( normalize(deflist[subscript].literal ) );
      subscript++;
   }

   PopDir();
   return success;

} /*configure*/

/*--------------------------------------------------------------------*/
/*    g e t r c n a m e s                                             */
/*                                                                    */
/*    Return the name of the configuration files                      */
/*--------------------------------------------------------------------*/

static boolean getrcnames(char **sysp,char **usrp)
{
   char *debugp = NULL;      /* Pointer to debug environment variable  */

   if ((*sysp = getenv(SYSRCSYM)) == nil(char))
   {
      printf("environment variable %s must be specified\n", SYSRCSYM);
      return FALSE;
   }

   *usrp = getenv(USRRCSYM);

   debugp = getenv(SYSDEBUG);

   if ( debugp != nil(char))        /* Debug specified in environment?     */
      debuglevel = atoi(debugp);    /* Yes --> preset debuglevel for user  */

   return TRUE;

} /*getrcnames*/
