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