home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / INTERNET / UPC2S1.ZIP / CONFIGUR.C < prev    next >
C/C++ Source or Header  |  1993-09-29  |  33KB  |  885 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    c o n f i g u r . c                                             */
  3. /*                                                                    */
  4. /*    Support routines for UUPC/extended                              */
  5. /*                                                                    */
  6. /*    Changes Copyright 1990, 1991 (c) Andrew H. Derbyshire           */
  7. /*                                                                    */
  8. /*    History:                                                        */
  9. /*       21Nov1991 Break out of lib.c                          ahd    */
  10. /*--------------------------------------------------------------------*/
  11.  
  12. /*--------------------------------------------------------------------*/
  13. /*    Changes Copyright (c) 1989-1993 by Kendra Electronic            */
  14. /*    Wonderworks.                                                    */
  15. /*                                                                    */
  16. /*    All rights reserved except those explicitly granted by the      */
  17. /*    UUPC/extended license agreement.                                */
  18. /*--------------------------------------------------------------------*/
  19.  
  20. /*--------------------------------------------------------------------*/
  21. /*                          RCS Information                           */
  22. /*--------------------------------------------------------------------*/
  23.  
  24. /*
  25.  *    $Id: configur.c 1.22 1993/09/29 23:29:56 ahd Exp $
  26.  *
  27.  *    Revision history:
  28.  *    $Log: configur.c $
  29.  *     Revision 1.22  1993/09/29  23:29:56  ahd
  30.  *     Add xqtrootdir for UUXQT
  31.  *
  32.  *     Revision 1.21  1993/09/29  04:49:20  ahd
  33.  *     Move priority variables to modem file
  34.  *
  35.  *     Revision 1.20  1993/09/24  03:43:27  ahd
  36.  *     Use positive defaults for unsigned priority values
  37.  *
  38.  *     Revision 1.19  1993/09/20  04:38:11  ahd
  39.  *     TCP/IP support from Dave Watt
  40.  *     't' protocol support
  41.  *     OS/2 2.x support
  42.  *
  43.  *     Revision 1.18  1993/07/31  16:22:16  ahd
  44.  *     Changes in support of Robert Denny's Windows 3.x support
  45.  *
  46.  *     Revision 1.17  1993/07/22  23:19:50  ahd
  47.  *     First pass for Robert Denny's Windows 3.x support changes
  48.  *
  49.  *     Revision 1.16  1993/07/05  14:45:29  ahd
  50.  *     Correct message-of-the-day variable name
  51.  *     Correct WIN32 prefix support
  52.  *
  53.  *     Revision 1.15  1993/06/16  04:03:25  ahd
  54.  *     Special case root directories for UUPC/extended variable default
  55.  *
  56.  *     Revision 1.14  1993/06/15  12:18:06  ahd
  57.  *     Saved changed directory name for debugging
  58.  *
  59.  *     Revision 1.13  1993/05/30  15:25:50  ahd
  60.  *     Multiple driver support
  61.  *
  62.  *     Revision 1.12  1993/05/29  15:19:59  ahd
  63.  *     Add systems file, passwd files
  64.  *
  65.  *     Revision 1.11  1993/05/09  03:49:21  ahd
  66.  *     Support banner, motd strings
  67.  *     Support longname, honordebug, senddebug options
  68.  *
  69.  *     Revision 1.10  1993/04/15  03:17:21  ahd
  70.  *     Add bounce system option
  71.  *
  72.  *     Revision 1.9  1993/04/11  00:31:31  dmwatt
  73.  *     Global edits for year, TEXT, etc.
  74.  *
  75.  *     Revision 1.8  1993/04/05  04:32:19  ahd
  76.  *     Set timezone, windows input mode in common routine
  77.  *
  78.  *     Revision 1.7  1993/04/04  04:57:01  ahd
  79.  *     Default configuration directory from UUPCSYSRC
  80.  *     Default system directories from Configuration directory
  81.  *
  82.  *     Revision 1.6  1993/03/06  22:48:23  ahd
  83.  *     Don't fall off end of shorter tables
  84.  *
  85.  *     Revision 1.5  1993/01/23  19:08:09  ahd
  86.  *     Add Windows/NT to allowed environments
  87.  *
  88.  * Revision 1.4  1992/12/01  04:37:03  ahd
  89.  * Add SpeedOverMemory
  90.  *
  91.  * Revision 1.3  1992/11/22  20:58:55  ahd
  92.  * Normalize directories as read
  93.  * Use strpool to allocate const strings
  94.  *
  95.  * Revision 1.2  1992/11/19  02:56:47  ahd
  96.  * drop rcsid
  97.  *
  98.  * Revision 1.1  1992/11/16  05:00:26  ahd
  99.  * Initial revision
  100.  *
  101.  */
  102.  
  103.  
  104. #include <stdio.h>
  105. #include <stdlib.h>
  106. #include <string.h>
  107. #include <time.h>
  108. #include <ctype.h>
  109.  
  110. #ifndef __GNUC__
  111. #include <io.h>
  112. #endif
  113.  
  114. /*--------------------------------------------------------------------*/
  115. /*                    UUPC/extended include files                     */
  116. /*--------------------------------------------------------------------*/
  117.  
  118. #include "lib.h"
  119. #include "hlib.h"
  120. #include "timestmp.h"
  121. #include "pushpop.h"
  122.  
  123. /*--------------------------------------------------------------------*/
  124. /*                          Global variables                          */
  125. /*--------------------------------------------------------------------*/
  126.  
  127. currentfile();
  128.  
  129. boolean bflag[F_LAST];        /* Initialized to zero by compiler     */
  130.  
  131. char **E_internal = NULL;
  132. char *E_aliases = NULL;
  133. char *E_altsignature = NULL;
  134. char *E_anonymous = NULL;
  135. char *E_archivedir = NULL;
  136. char *E_backup = NULL;
  137. char *E_banner = NULL;
  138. char *E_charset = NULL;
  139. char *E_passwd  = NULL;
  140. char *E_systems = NULL;
  141. char *E_confdir = NULL;
  142. char *E_domain = NULL;
  143. char *E_editor = NULL;
  144. char *E_fdomain = NULL;
  145. char *E_filesent = NULL;
  146. char *E_homedir = NULL;
  147. char *E_inmodem = NULL;
  148. char *E_localdomain = NULL;
  149. char *E_mailbox = NULL;
  150. char *E_maildir = NULL;
  151. char *E_mailext = NULL;
  152. char *E_mailserv = NULL;
  153. char *E_motd = NULL;
  154. char *E_name = NULL;
  155. char *E_newsdir = NULL;
  156. char *E_newsserv = NULL;
  157. char *E_nodename = NULL;
  158. char *E_organization = NULL;
  159. char *E_pager = NULL;
  160. char *E_postmaster = NULL;
  161. char *E_pubdir = NULL;
  162. char *E_replyto = NULL;
  163. char *E_signature = NULL;
  164. char *E_spooldir = NULL;
  165. char *E_tempdir = NULL;
  166. char *E_uncompress = NULL;
  167. char *E_uuxqtpath = NULL;
  168. char *E_version = NULL;
  169. char *E_cwd = NULL;
  170. char *E_xqtRootDir = NULL;
  171. KEWSHORT E_maxhops = 20;                                    /* ahd */
  172. static char *dummy = NULL;
  173. static char *E_tz = NULL;
  174.  
  175. /*--------------------------------------------------------------------*/
  176. /*                       Local emumerated types                       */
  177. /*--------------------------------------------------------------------*/
  178.  
  179. typedef enum {
  180.       ENV_UNKNOWN    = 0x0001,
  181.       ENV_DOS        = 0x0002,
  182.       ENV_BIT32      = 0x0004,
  183.       ENV_BIT16      = 0x0008,
  184.       ENV_OS2        = 0x0010,
  185.       ENV_OS2_32BIT  = 0x0020,
  186.       ENV_OS2_16BIT  = 0x0040,
  187.       ENV_WIN        = 0x0080,
  188.       ENV_WIN_32BIT  = 0x0100,
  189.       ENV_WIN_16BIT  = 0x0200
  190.       } ENV_TYPE;
  191.  
  192. #ifdef WIN32
  193. static ENV_TYPE active_env = ENV_WIN_32BIT | ENV_WIN | ENV_BIT32;
  194. #elif defined(_Windows)
  195. static ENV_TYPE active_env = ENV_WIN_16BIT | ENV_WIN | ENV_BIT16;
  196. #elif defined(__OS2__)
  197. static ENV_TYPE active_env = ENV_OS2_32BIT | ENV_OS2 | ENV_BIT32;
  198. #else
  199. static ENV_TYPE active_env = ENV_DOS | ENV_BIT16;
  200. #endif
  201.  
  202. static boolean getrcnames(char **sysp,char **usrp);
  203.  
  204. /*--------------------------------------------------------------------*/
  205. /*  The following table controls the configuration files processing   */
  206. /*--------------------------------------------------------------------*/
  207.  
  208. static CONFIGTABLE envtable[] = {
  209.    {"aliases",      &E_aliases,      B_TOKEN|B_MUA},
  210.    {"altsignature", &E_altsignature, B_TOKEN|B_MUA},
  211.    {"anonymouslogin", &E_anonymous,  B_GLOBAL|B_TOKEN|(B_ALL & ~ B_MAIL)},
  212.    {"archivedir",   &E_archivedir,   B_GLOBAL|B_PATH|B_ALL},
  213.    {"backupext",    &E_backup,       B_TOKEN|B_MUA},
  214.    {"banner",       &E_banner,       B_GLOBAL|B_PATH|B_UUCICO},
  215.    {"charset",      &E_charset,      B_TOKEN|B_GLOBAL|B_SPOOL},
  216.    {"confdir",      &E_confdir,      B_GLOBAL|B_PATH|B_ALL},
  217.    {"domain",       &E_domain,       B_REQUIRED|B_GLOBAL|B_TOKEN|B_ALL},
  218.    {"editor",       &E_editor,       B_STRING|B_MUA|B_NEWS},
  219.    {"filesent",     &E_filesent,     B_TOKEN|B_MUA|B_NEWS},
  220.    {"folders",      &dummy,          B_PATH|B_MUSH },
  221.    {"fromdomain",   &E_fdomain,      B_GLOBAL|B_MAIL|B_NEWS|B_TOKEN},
  222.    {"home",         &E_homedir,      B_PATH|B_REQUIRED|B_ALL},
  223.    {"inmodem",      &E_inmodem,      B_GLOBAL|B_TOKEN|B_UUCICO},
  224.    {"internalcommands", (char **)   &E_internal, B_GLOBAL|B_LIST|B_ALL},
  225.    {"localdomain",  &E_localdomain,  B_GLOBAL|B_TOKEN|B_MAIL},
  226.    {"mailbox",      &E_mailbox,      B_REQUIRED|B_TOKEN|B_ALL},
  227.    {"maildir",      &E_maildir,      B_GLOBAL|B_PATH|B_ALL},
  228.    {"mailext",      &E_mailext,      B_TOKEN|B_MAIL},
  229.    {"mailserv",     &E_mailserv,     B_REQUIRED|B_GLOBAL|B_TOKEN|B_ALL},
  230.    {"maximumhops",  (char **) &E_maxhops, B_MTA | B_SHORT | B_GLOBAL},
  231.    {"motd",         &E_motd,         B_GLOBAL|B_PATH|B_UUCICO},
  232.    {"mushdir",      &dummy,          B_GLOBAL|B_PATH|B_MUSH},
  233.    {"name",         &E_name,         B_REQUIRED|B_MAIL|B_NEWS|B_STRING},
  234.    {"newsdir",      &E_newsdir,      B_GLOBAL|B_PATH|B_ALL},
  235.    {"newsserv",     &E_newsserv,     B_GLOBAL|B_TOKEN|B_NEWS},
  236.    {"nodename",     &E_nodename,     B_REQUIRED|B_GLOBAL|B_TOKEN|B_ALL},
  237.    {"options",      (char **) bflag, B_ALL|B_BOOLEAN},
  238.    {"organization", &E_organization, B_STRING|B_MAIL|B_NEWS},
  239.    {"pager",        &E_pager,        B_STRING|B_MUA|B_NEWS},
  240.    {"path",         &E_uuxqtpath,    B_STRING|B_UUXQT|B_GLOBAL},
  241.    {"postmaster",   &E_postmaster,   B_REQUIRED|B_GLOBAL|B_TOKEN|B_MTA},
  242.    {"priority",     &dummy,          B_OBSOLETE },
  243.    {"prioritydelta",&dummy,          B_OBSOLETE },
  244.    {"pubdir",       &E_pubdir,       B_GLOBAL|B_PATH|B_ALL},
  245.    {"replyto",      &E_replyto,      B_TOKEN|B_MAIL|B_NEWS},
  246.    {"rmail",        &dummy,          B_OBSOLETE },
  247.    {"rnews",        &dummy,          B_OBSOLETE },
  248.    {"signature",    &E_signature,    B_TOKEN|B_MUA|B_NEWS},
  249.    {"spooldir",     &E_spooldir,     B_GLOBAL|B_PATH|B_ALL},
  250.    {"systems",      &E_systems,      B_GLOBAL|B_PATH|B_ALL},
  251.    {"passwd",       &E_passwd,       B_GLOBAL|B_PATH|B_ALL},
  252.    {"tempdir",      &E_tempdir,      B_GLOBAL|B_PATH|B_ALL},
  253.    {"tz",           &E_tz,           B_TOKEN|B_ALL},
  254.    {"uncompress",   &E_uncompress,   B_GLOBAL|B_STRING|B_NEWS },
  255.    {"version",      &E_version,      B_TOKEN|B_INSTALL},
  256.    {"xqtrootdir",   &E_xqtRootDir,   B_UUXQT|B_PATH|B_ALL},
  257.    { nil(char) }
  258. }; /* table */
  259.  
  260. /*--------------------------------------------------------------------*/
  261. /*               Boolean options shared by all programs               */
  262. /*--------------------------------------------------------------------*/
  263.  
  264. FLAGTABLE configFlags[] = {
  265.  { "askcc",       F_ASKCC,       B_LOCAL},
  266.  { "autoedit",    F_AUTOEDIT,    B_LOCAL},
  267.  { "autoinclude", F_AUTOINCLUDE, B_LOCAL},
  268.  { "autoprint",   F_AUTOPRINT,   B_LOCAL},
  269.  { "autosign",    F_AUTOSIGN,    B_LOCAL},
  270.  { "backup",      F_BACKUP,      B_LOCAL},
  271.  { "doskey",      F_DOSKEY,      B_LOCAL},
  272.  { "dot",         F_DOT,         B_LOCAL},
  273.  { "expert",      F_EXPERT,      B_LOCAL},
  274.  { "forwardsave", F_SAVERESENT,  B_LOCAL},
  275.  { "fromsep",     F_FROMSEP,     B_LOCAL},
  276.  { "pager",       F_PAGER,       B_LOCAL},
  277.  { "purge",       F_PURGE,       B_LOCAL},
  278.  { "save",        F_SAVE,        B_LOCAL},
  279.  { "suppresscopyright",
  280.                   F_SUPPRESSCOPYRIGHT,
  281.                                  B_LOCAL},
  282.  { "speedovermemory",
  283.                   F_SPEEDOVERMEMORY,
  284.                                  B_LOCAL},
  285.  { "undelete",    F_UNDELETE,    B_LOCAL},
  286.  { "verbose",     F_VERBOSE,     B_LOCAL},
  287.  { "windows",     F_WINDOWS,     B_LOCAL},
  288.  
  289.  { "bang",        F_BANG,        B_GLOBAL},
  290.  { "bounce",      F_BOUNCE,      B_GLOBAL},
  291.  { "collect",     F_COLLECTSTATS,B_GLOBAL},
  292.  { "directory",   F_DIRECT,      B_GLOBAL},
  293.  { "escape",      F_ESCAPE,      B_GLOBAL},
  294.  { "history",     F_HISTORY,     B_GLOBAL},
  295.  { "honordebug",  F_HONORDEBUG,  B_GLOBAL},
  296.  { "kanji",       F_KANJI,       B_GLOBAL},
  297.  { "longname",    B_LONGNAME,      B_GLOBAL},
  298.  { "monocase",    F_ONECASE,     B_GLOBAL},
  299.  { "multiqueue",  F_MULTI,       B_GLOBAL},
  300.  { "multitask",   F_MULTITASK,   B_GLOBAL},
  301.  { "senddebug",   F_SENDDEBUG,   B_GLOBAL},
  302.  { "snews",       F_SNEWS,       B_GLOBAL},
  303.  { "syslog",      F_SYSLOG,      B_GLOBAL},
  304.  { "symmetricgrades",
  305.                   F_SYMMETRICGRADES,
  306.                                  B_GLOBAL},
  307.  
  308.  { nil(char) }
  309. }           ;
  310.  
  311. /*--------------------------------------------------------------------*/
  312. /*    p r o c e s s c o n f i g                                       */
  313. /*                                                                    */
  314. /*    Handle a single line of a configuration file                    */
  315. /*--------------------------------------------------------------------*/
  316.  
  317. boolean processconfig(char *buff,
  318.                   SYSMODE sysmode,
  319.                   CONFIGBITS program,
  320.                   CONFIGTABLE *table,
  321.                   FLAGTABLE *btable)
  322. {
  323.    CONFIGTABLE *tptr;
  324.    char *cp;
  325.    char *keyword;
  326.    ENV_TYPE target_env;
  327.  
  328. /*--------------------------------------------------------------------*/
  329. /*                break out the keyword from its value                */
  330. /*--------------------------------------------------------------------*/
  331.  
  332.    if ((cp = strchr(buff, '=')) == nil(char))
  333.    {
  334.       printmsg(0,"Missing equals sign after keyword \"%s\", ignored",
  335.                   buff);
  336.       return TRUE;
  337.    }
  338.    *cp++ = '\0';
  339.    strlwr(buff);
  340.  
  341. /*--------------------------------------------------------------------*/
  342. /*    Determine if the keyword should processed in this environment   */
  343. /*--------------------------------------------------------------------*/
  344.  
  345.    keyword = strchr( buff, '.' );   /* Look for environment          */
  346.  
  347.    if ( keyword == NULL )     /* No environment?                     */
  348.    {
  349.       keyword = buff;         /* Then buffer starts with keyword     */
  350.       target_env = active_env;
  351.    }
  352.    else {
  353.  
  354.       typedef struct _ENVLIST {
  355.             char *name;
  356.             int value;
  357.       } ENVLIST;
  358.  
  359.       static ENVLIST envtable[] = {
  360.          { "dos",      ENV_DOS      },
  361.          { "16bit",    ENV_BIT16    },
  362.          { "32bit",    ENV_BIT32    },
  363.          { "32bitos2", ENV_OS2_16BIT},
  364.          { "16bitos2", ENV_OS2_32BIT},
  365.          { "os2",      ENV_OS2      },
  366.          { "win32",    ENV_WIN_32BIT},
  367.          { "win16",    ENV_WIN_16BIT},
  368.          { "32bitwin", ENV_WIN_32BIT},
  369.          { "16bitwin", ENV_WIN_16BIT},
  370.          { "win",      ENV_WIN      },
  371.          { NULL,       ENV_UNKNOWN  }
  372.        };
  373.  
  374.       short subscript = 0;
  375.  
  376.       *keyword++ = '\0';      /* Terminate environment string        */
  377.       target_env = ENV_UNKNOWN;
  378.  
  379.       while( envtable[subscript].name != NULL)
  380.       {
  381.          if (equal( envtable[subscript].name, buff ))
  382.          {
  383.             target_env = envtable[subscript].value;
  384.             break;
  385.          }
  386.          else
  387.             subscript ++;
  388.       } /* while */
  389.  
  390.       if ( target_env == ENV_UNKNOWN )
  391.       {
  392.          printmsg(0,"Unknown environment \"%s\", keyword \"%s\" ignored",
  393.                buff, keyword );
  394.          return FALSE;
  395.       }
  396.  
  397.    } /* else */
  398.  
  399. /*--------------------------------------------------------------------*/
  400. /*                    Scan the table for its value                    */
  401. /*--------------------------------------------------------------------*/
  402.  
  403.    for (tptr = table; tptr->sym != nil(char); tptr++)
  404.    {
  405.       boolean error = FALSE;
  406.       if (equal(keyword, tptr->sym)) {
  407. /*--------------------------------------------------------------------*/
  408. /*            Skip the keyword because of the environment?            */
  409. /*--------------------------------------------------------------------*/
  410.         if (!(active_env & target_env) )
  411.             printmsg(2,"%s-environment keyword \"%s\" skipped.",
  412.                         strupr(buff), keyword);
  413. /*--------------------------------------------------------------------*/
  414. /*                      Handle obsolete options                       */
  415. /*--------------------------------------------------------------------*/
  416.         else if (tptr->bits & B_OBSOLETE)
  417.             printmsg(2,"Obsolete keyword \"%s\" ignored.", keyword);
  418. /*--------------------------------------------------------------------*/
  419. /*                  Handle mis-placed system options                  */
  420. /*--------------------------------------------------------------------*/
  421.         else if ((tptr->bits & B_GLOBAL) && (sysmode != SYSTEM_CONFIG))
  422.             printmsg(0,
  423.                "User specified system keyword \"%s\" ignored.",
  424.                keyword);
  425. /*--------------------------------------------------------------------*/
  426. /*                       Handle Boolean options                       */
  427. /*--------------------------------------------------------------------*/
  428.          else {
  429.             if (tptr->bits & B_BOOLEAN)
  430.                options(cp, sysmode, btable, (boolean *) tptr->loc);
  431. /*--------------------------------------------------------------------*/
  432. /*                       Handle integer values                        */
  433. /*--------------------------------------------------------------------*/
  434.             else if (tptr->bits & (B_SHORT|B_LONG))
  435.             {
  436.                long foo;
  437.                cp = strtok(cp,WHITESPACE);
  438.                if ( equal(cp,"0"))
  439.                   foo = 0;
  440.                else {
  441.                   foo = atol(cp);
  442.  
  443.                   if ( foo == 0)
  444.                   {
  445.                      printmsg(0,
  446.                         "Unable to convert \"%s\" value \"%s\" to integer",
  447.                         keyword, cp);
  448.                      error = TRUE;
  449.                   } /* if */
  450.                } /* else */
  451.  
  452.                if (tptr->bits & B_LONG)
  453.                   *((long *) tptr->loc) = foo;
  454.                else
  455.                   *((KEWSHORT *) tptr->loc) = (KEWSHORT) foo;
  456.             } /* else */
  457. /*--------------------------------------------------------------------*/
  458. /*                       Handle lists of tokens                       */
  459. /*--------------------------------------------------------------------*/
  460.             else if ((tptr->bits & program) && (tptr->bits & (B_LIST | B_CLIST)))
  461.             {
  462.                char **list = malloc( (MAXLIST+1) * sizeof (*list));
  463.                char *colon;
  464.                int words;
  465.  
  466.                checkref( list );
  467.  
  468.                if (tptr->bits & B_CLIST)  /* Use colon as delimiter? */
  469.                   while ( (colon = strchr( cp , ':')) != NULL)
  470.                      *colon = ' ';     /* Make colons spaces ...           */
  471.  
  472.                words = getargs(cp, list);
  473.                if( words > MAXLIST)
  474.                   panic();
  475.  
  476.                if (words > 0)
  477.                {
  478.                   if ( *(tptr->loc) )
  479.                      free( *(tptr->loc) );
  480.                   list = realloc( list, (words+1) * sizeof(*list));
  481.                   checkref( list );
  482.                   *(tptr->loc) = (char *) list;
  483.                   list[words] = NULL;
  484.  
  485.                   while( *list != NULL)
  486.                   {
  487.                      if (strlen(*list))
  488.                      {
  489.                         *list = newstr(*list);
  490.                         checkref( *list++ );
  491.                      }
  492.                      else
  493.                         *list++ = "";
  494.                   } /* while */
  495.                } /* if (words > 0) */
  496.                else {
  497.                   printmsg(0,"No parameters given for keyword \"%s\"",
  498.                            keyword);
  499.                   error = TRUE;
  500.                } /* else */
  501.             } /* else if */
  502. /*--------------------------------------------------------------------*/
  503. /*                  Handle single tokens and strings                  */
  504. /*--------------------------------------------------------------------*/
  505.             else if (tptr->bits & program)
  506.             {
  507.                while( *cp == ' ' )     /* Trim leading whitespace    */
  508.                   cp++;
  509.  
  510.                if (*cp == '\0')
  511.                {
  512.                   error = TRUE;
  513.                   printmsg(0,"No parameter given for keyword \"%s\""
  514.                            ", ignored.",
  515.                            keyword);
  516.                } /* if */
  517.  
  518.                if (tptr->bits & B_TOKEN)  /* One word value?      */
  519.                   cp = strtok(cp,WHITESPACE); /* Yes --> Tokenize */
  520.  
  521.                if (tptr->bits & B_NORMAL)  /* Normalize path?     */
  522.                   cp = normalize( cp );
  523.  
  524.                if (tptr->bits & B_MALLOC)  /* Allocate normally?  */
  525.                {
  526.                   *(tptr->loc) = strdup(cp); /* Save string          */
  527.                   checkref( *(tptr->loc) );  /* Verify malloc()      */
  528.                }
  529.                else
  530.                   *(tptr->loc) = newstr(cp); /* Save string          */
  531.  
  532.             } /* else */
  533.          } /* else */
  534.  
  535.          if (!error)
  536.             tptr->bits |= B_FOUND;
  537.          return TRUE;         /* Report we found the keyword      */
  538.       } /* if (equal(keyword, tptr->sym)) */
  539.    } /* for */
  540.  
  541. /*--------------------------------------------------------------------*/
  542. /*      We didn't find the keyword; report failure to the caller      */
  543. /*--------------------------------------------------------------------*/
  544.  
  545.    return FALSE;
  546.  
  547. } /* processconfig */
  548.  
  549. /*--------------------------------------------------------------------*/
  550. /*    g e t c o n f i g                                               */
  551. /*                                                                    */
  552. /*    Process a single configuration file                             */
  553. /*--------------------------------------------------------------------*/
  554.  
  555. boolean getconfig(FILE *fp,
  556.                   SYSMODE sysmode,
  557.                   CONFIGBITS program,
  558.                   CONFIGTABLE *table,
  559.                   FLAGTABLE *btable)
  560. {
  561.  
  562.    char buff[BUFSIZ];
  563.    char *cp;
  564.  
  565.    while(!(fgets(buff, sizeof buff, fp) == nil(char))) {
  566.  
  567. /*--------------------------------------------------------------------*/
  568. /*                        Ingore comment lines                        */
  569. /*--------------------------------------------------------------------*/
  570.  
  571.       if (*buff == '#')
  572.          continue;            /* comment line   */
  573.  
  574. /*--------------------------------------------------------------------*/
  575. /*                       Drop trailing new line                       */
  576. /*--------------------------------------------------------------------*/
  577.  
  578.       if (*(cp = buff + strlen(buff) - 1) == '\n')
  579.          *cp = '\0';
  580.  
  581. /*--------------------------------------------------------------------*/
  582. /*                 Drop leading blanks on input line                  */
  583. /*--------------------------------------------------------------------*/
  584.  
  585.       cp = buff;
  586.       while( isspace( *cp ) )
  587.          cp ++ ;
  588.  
  589. /*--------------------------------------------------------------------*/
  590. /*                 If line was not blank, process it.                 */
  591. /*--------------------------------------------------------------------*/
  592.  
  593.       if ( (*cp != '\0') && !processconfig(cp,sysmode,program,table,btable))
  594.          printmsg(0,
  595.                "Unknown keyword \"%s\" in %s configuration file ignored",
  596.                buff, sysmode ? "system" : "user");
  597.  
  598.    } /*while*/
  599.  
  600.    return TRUE;
  601.  
  602. } /*getconfig*/
  603.  
  604. /*--------------------------------------------------------------------*/
  605. /*    o p t i o n s                                                   */
  606. /*                                                                    */
  607. /*    Process a line of boolean option flags.                         */
  608. /*--------------------------------------------------------------------*/
  609.  
  610. void options(char *s, SYSMODE sysmode , FLAGTABLE *flags, boolean *barray)
  611. {
  612.    char *token;
  613.  
  614.    strlwr(s);
  615.    token = strtok(s,WHITESPACE);
  616.  
  617.    while (token != NULL)
  618.    {
  619.       size_t subscript;
  620.       boolean hit = FALSE;
  621.       boolean negate;
  622.       negate = equaln(token,"no",2) && (strlen(token) > 2);
  623.  
  624.       for ( subscript=0; (flags[subscript].sym != NULL ) && !hit; subscript++)
  625.       {
  626.          if ((flags[subscript].bits & B_GLOBAL) && (sysmode != SYSTEM_CONFIG))
  627.             continue;
  628.          if (negate)
  629.          {
  630.             if (equal(&token[2],flags[subscript].sym))
  631.             {
  632.                barray[ flags[subscript].position ] = FALSE;
  633.                hit = TRUE;
  634.             }
  635.          } /* if negate */
  636.          else {
  637.             if (equal(token,flags[subscript].sym))
  638.             {
  639.                barray[ flags[subscript].position ] = TRUE;
  640.                hit = TRUE;
  641.             }
  642.          } /* else */
  643.       } /* for */
  644.  
  645.       if (!hit)
  646.          printf("Invalid or system option '%s' specified\n",token);
  647.  
  648.       token = strtok(NULL,WHITESPACE);  /* Step to next token on line */
  649.  
  650.    } /* while */
  651. } /* options */
  652.  
  653. /*--------------------------------------------------------------------*/
  654. /*    c o n f i g u r e                                               */
  655. /*                                                                    */
  656. /*    Define the global parameters of UUPC/extended                   */
  657. /*--------------------------------------------------------------------*/
  658.  
  659. boolean configure( CONFIGBITS program)
  660. {
  661.    char *sysrc, *usrrc;
  662.    FILE *fp;
  663.    boolean success;
  664.    char buf[BUFSIZ];
  665.    int subscript = 0;
  666.    char *s;
  667.  
  668.    CONFIGTABLE *tptr;
  669.  
  670.    static char *envlist[] = { "EDITOR",   "EDITOR",
  671.                               "HOME",     "HOME",
  672.                               "NAME",     "NAME",
  673.                               "MAILBOX",  "MAILBOX",
  674.                               "TEMP",     "TEMPDIR",
  675.                               "TMP",      "TEMPDIR",
  676.                               NULL } ;
  677.  
  678.    typedef struct _DEFAULTS {
  679.       char **value;
  680.       char *literal;
  681.    } DEFAULTS;
  682.  
  683.    static DEFAULTS deflist[] = {
  684.         {&E_archivedir,   "archive" },
  685.         {&E_maildir,      "mail"    },
  686.         {&E_newsdir,      "news"    },
  687.         {&E_pubdir,       "public"  },
  688.         {&E_spooldir,     "spool"   },
  689.         {&E_tempdir,      "tmp"     },
  690.         {&E_systems,      "systems" },
  691.         {&E_passwd,       "passwd"  },
  692.         {&E_tz,           "tz"      },
  693.         { NULL  }
  694.         } ;
  695.  
  696. /*--------------------------------------------------------------------*/
  697. /*     In Windows/NT, set the console input mode to non-linebased     */
  698. /*--------------------------------------------------------------------*/
  699.  
  700. #ifdef WIN32
  701.    setstdinmode();
  702. #endif
  703.  
  704. /*--------------------------------------------------------------------*/
  705. /*                  Determine the active environment                  */
  706. /*--------------------------------------------------------------------*/
  707.  
  708. #if !defined(__TURBOC__) && !defined(BIT32ENV)
  709.    if (_osmode != DOS_MODE)
  710.       active_env = ENV_OS2 | ENV_BIT16;
  711. #endif
  712.  
  713.    if (!getrcnames(&sysrc, &usrrc))
  714.       return FALSE;
  715.  
  716. /*--------------------------------------------------------------------*/
  717. /*          Extract selected variables from our environment           */
  718. /*--------------------------------------------------------------------*/
  719.  
  720.    while( envlist[subscript] != NULL )
  721.    {
  722.       s = getenv( envlist[subscript++] );
  723.  
  724.       if (s != NULL )
  725.       {
  726.          sprintf(buf,"%s=%s",envlist[subscript], s );
  727.          processconfig( buf, SYSTEM_CONFIG, program, envtable, configFlags);
  728.       } /* if (sysrc != NULL ) */
  729.  
  730.       subscript++;            /* Step to next environment var in list   */
  731.    }
  732.  
  733. /*--------------------------------------------------------------------*/
  734. /*          Determine configuration directory from UUPCSYSRC          */
  735. /*--------------------------------------------------------------------*/
  736.  
  737.    E_confdir = normalize( sysrc );     // Make 'em all slashes
  738.  
  739.    s = strrchr( E_confdir, '/' );      // Get end of path component
  740.    if ( s == NULL )                    // There WAS one, right?
  741.    {                                   // Er, no, sorry.
  742.       printmsg(0,"No path name in UUPCSYSRC: %s", sysrc);
  743.       panic();
  744.    }
  745.  
  746.    *(s+1) = '\0';                      // Terminate for Config Directory
  747.    E_confdir = newstr(normalize( E_confdir ));
  748.                                        // Drop trailing slash unless
  749.                                        // root directory and save
  750.  
  751. /*--------------------------------------------------------------------*/
  752. /*               Process the system configuration file                */
  753. /*--------------------------------------------------------------------*/
  754.  
  755.    if ((fp = FOPEN(sysrc, "r",TEXT_MODE)) == nil(FILE))
  756.    {
  757.       printmsg(0, "Cannot open system configuration file \"%s\"", sysrc);
  758.       printerr(sysrc);
  759.       return FALSE;
  760.    }
  761.  
  762.    PushDir( E_confdir );
  763.  
  764.    success = getconfig(fp, SYSTEM_CONFIG, program, envtable, configFlags);
  765.  
  766.    fclose(fp);
  767.    if (!success)
  768.    {
  769.       PopDir();
  770.       return FALSE;
  771.    }
  772.  
  773. /*--------------------------------------------------------------------*/
  774. /*                Process the user configuration value                */
  775. /*--------------------------------------------------------------------*/
  776.  
  777.    if (usrrc != nil(char))
  778.    {
  779.       usrrc = normalize( usrrc );
  780.       if ((fp = FOPEN(usrrc, "r",TEXT_MODE)) == nil(FILE))
  781.       {
  782.          printmsg(0, "Cannot open user configuration file \"%s\"", usrrc);
  783.          PopDir();
  784.          return FALSE;
  785.       }
  786.  
  787.       success = getconfig(fp, USER_CONFIG, program, envtable, configFlags);
  788.       fclose(fp);
  789.  
  790.       if (!success)
  791.       {
  792.          PopDir();
  793.          return FALSE;
  794.       }
  795.  
  796.    }
  797.  
  798. /*--------------------------------------------------------------------*/
  799. /*                       Display our copyright                        */
  800. /*--------------------------------------------------------------------*/
  801.  
  802.    if (! bflag[F_SUPPRESSCOPYRIGHT] &&
  803.         (program != B_MTA) &&
  804.         isatty(fileno(stdout)))
  805.       fprintf(stdout,
  806. "Changes and Compilation Copyright (c) 1990-1993 by Kendra Electronic\n"
  807. "Wonderworks.  May be freely distributed if original documentation and\n"
  808. "source is included.\n" );
  809.  
  810. /*--------------------------------------------------------------------*/
  811. /*          Validate that all required parameters were given          */
  812. /*--------------------------------------------------------------------*/
  813.  
  814.    for (tptr = envtable; tptr->sym != nil(char); tptr++)
  815.    {
  816.  
  817.       if ((tptr->bits & (B_REQUIRED | B_FOUND)) == B_REQUIRED)
  818.       {
  819.          printmsg(0, "%s configuration parameter \"%s\" must be set.",
  820.             (tptr->bits & B_GLOBAL) ? "System" : "User",
  821.             tptr->sym);
  822.          success = FALSE;
  823.       } /* if */
  824.  
  825.    } /* for */
  826.  
  827. /*--------------------------------------------------------------------*/
  828. /*                     Fill in derived parameters                     */
  829. /*--------------------------------------------------------------------*/
  830.  
  831.    subscript = 0;
  832.    while( deflist[subscript].value != NULL )
  833.    {
  834.       if ( *(deflist[subscript].value) == NULL )
  835.          *(deflist[subscript].value) =
  836.                      newstr( normalize(deflist[subscript].literal ) );
  837.       subscript++;
  838.    }
  839.  
  840. /*--------------------------------------------------------------------*/
  841. /*                         Set our time zone                          */
  842. /*--------------------------------------------------------------------*/
  843.  
  844.    if ((getenv("TZ") == NULL) && (E_tz != NULL))
  845.    {
  846.       sprintf( buf, "TZ=%s", E_tz );
  847.       E_tz = newstr( E_tz );
  848.       putenv( E_tz );
  849.    }
  850.  
  851.    tzset();                      /* Set up time zone information  */
  852.  
  853.    PopDir();
  854.  
  855.    return success;
  856.  
  857. } /*configure*/
  858.  
  859. /*--------------------------------------------------------------------*/
  860. /*    g e t r c n a m e s                                             */
  861. /*                                                                    */
  862. /*    Return the name of the configuration files                      */
  863. /*--------------------------------------------------------------------*/
  864.  
  865. static boolean getrcnames(char **sysp,char **usrp)
  866. {
  867.    char *debugp = NULL;      /* Pointer to debug environment variable  */
  868.  
  869.    if ((*sysp = getenv(SYSRCSYM)) == nil(char))
  870.    {
  871.       printf("environment variable %s must be specified\n", SYSRCSYM);
  872.       return FALSE;
  873.    }
  874.  
  875.    *usrp = getenv(USRRCSYM);
  876.  
  877.    debugp = getenv(SYSDEBUG);
  878.  
  879.    if ( debugp != nil(char))        /* Debug specified in environment?     */
  880.       debuglevel = atoi(debugp);    /* Yes --> preset debuglevel for user  */
  881.  
  882.    return TRUE;
  883.  
  884. } /*getrcnames*/
  885.