/*****************************************************************************/
/*
                                Config.c

This module performs three functions.

  1.  It reads the HTTPD configuration file, converting the directives
      into internal representations.

  2.  Provides functions, accessed by other modules, returning the
      original directive information as appropriate.

  3.  Provides HTML form-based configuration and reports.

Configuration can only be performed at server startup.  To reset the 
configuration the server must be restarted.

WASD HTTPd Configuration is a relevant subset of the CERN configuration 
directives (sort-of, well it started that way anyhow!)  Although there are
some  differences (beware!) the CERN documentation can be consulted for a
general discussion of the purpose and functioning some of these directives. 

The file formats may be IN ONE OF TWO possible formats (not mixed).  The
older format contains one directive at the start of a line, followed by a
mandatory parameter.  The newer format (in part to support forms-based
configuration) has the directive contained within square brackets (e.g.
"[accept]") followed on the same line, or by one or more lines containing
comments, containing parameter information, or empty.  The directive applies
to all lines following up until another directive (square bracket in column
one) is encountered.

DIRECTIVES
----------

  o  Accept             <host/domain>
  o  ActivityDays       <integer>
  o  AddType            <.suffix> <content-type> [</script>] [<description>]
  o  AddMimeTypesFile   <filename>
  o  AddIcon            <URL> <alternative-text> <content-type-template>
  o  AddDefaultIcon     <URL> <alternative-text>
  o  AddDirIcon         <URL> <alternative-text>
  o  AddBlankIcon       <URL> <alternative-text>
  o  AddUnknownIcon     <URL> <alternative-text>
  o  AddParentIcon      <URL> <alternative-text>
  o  AuthBasic          DISABLED | ENABLED
  o  AuthCacheEntriesMax         <integer>
  o  AuthCacheEntrySize          <integer>
  o  AuthCacheMinutes   <integer>
  o  AuthDigest         DISABLED | ENABLED
  o  AuthDigestGetLife  <integer>
  o  AuthDigestPutLife  <integer>
  o  AuthFailureLimit   <integer>
  o  AuthFailurePeriod  <integer>
  o  AuthFailureTimeout <integer>
  o  AuthRevalidateUserMinutes   <integer>
  o  AuthRevalidateLoginCookie   DISABLED | ENABLED
  o  AuthSYSUAFacceptExpPwd      DISABLED | ENABLED
  o  AuthSYSUAFpwdExpUrl         <string>
  o  AuthSYSUAFuseACME           DISABLED | ENABLED
  o  BufferSizeDclCgiHeader      <integer>
  o  BufferSizeDclCgiPlusIn      <integer>
  o  BufferSizeDclCommand        <integer>
  o  BufferSizeDclOutput         <integer>
  o  BufferSizeNetRead           <integer>
  o  BufferSizeNetWrite          <integer>
  o  Busy               <integer>
  o  Cache              DISABLED | ENABLED
  o  CacheEntriesMax    <integer>
  o  CacheFileKBytesMax <integer>
  o  CacheFrequentHits      <integer>
  o  CacheFrequentPeriod    <hh:mm:ss>
  o  CacheGuardPeriod       <hh:mm:ss>
  o  CacheTotalKBytesMax    <integer>
  o  CacheValidatePeriod    <hh:mm:ss>
  o  CgiStrictOutput    DISABLED | ENABLED
  o  CharsetDefault     <string>
  o  CharsetConvert     <string>
  o  DclBitBucketTimeout    <hh:mm:ss>
  o  DclCgiPlusLifeTime     <hh:mm:ss>
  o  DclCleanupScratchMinutesMax      <integer>
  o  DclCleanupScratchMinutesOld      <integer>
  o  DclDetachProcess   DISABLED | ENABLED
  o  DclDetachProcessPriority         <string>
  o  DclGatewayBg       DISABLED | ENABLED
  o  DclHardLimit       <integer>
  o  DclScriptRunTime   <string>
  o  DclSoftLimit       <integer>
  o  DclSpawnAuthPriv   DISABLED | ENABLED
  o  DclZombieLifeTime      <hh:mm:ss>
  o  DECnetReuseLifeTime    <hh:mm:ss>
  o  DECnetConnectListMax   <integer>
  o  DirAccess          DISABLED | ENABLED | SELECTIVE
  o  DirBodyTag         <string>
  o  DirDescription     <integer>
  o  DirLayout          <string>
  o  DirMetaInfo        DISABLED | ENABLED
  o  DirOwner           DISABLED | ENABLED
  o  DirPreExpired      DISABLED | ENABLED
  o  DirReadMe          DISABLED | TOP | BOTTOM
  o  DirReadMeFile      <file.suffix>
  o  DirNoImpliedWildcard   DISABLED | ENABLED
  o  DirNoPrivIgnore    DISABLED | ENABLED
  o  DirWildcard        DISABLED | ENABLED
  o  DNSLookupClient    DISABLED | ENABLED
  o  DNSLookupLifeTime  <hh:mm:ss>
  o  DNSLookupRetry     <integer>
  o  ErrorRecommend     DISABLED | ENABLED
  o  ErrorReportPath    <path-to-report>
  o  IncludeFile        <filename>
  o  InstanceMax        <integer> | CPU
  o  Logging            DISABLED | ENABLED
  o  LogExcludeHosts    <string>
  o  LogFile            <string>
  o  LogFileExtend      <integer>
  o  LogFormat          <string>
  o  LogNaming          <string>
  o  LogPeriod          <string>
  o  LogPerInstance                   DISABLED | ENABLED
  o  LogPerService                    DISABLED | ENABLED
  o  LogPerServiceHostOnly            DISABLED | ENABLED
  o  MapUserNameCacheEntries          <integer>
  o  Monitor            DISABLED | ENABLED
  o  OpcomAdmin         DISABLED | ENABLED
  o  OpcomAuthorization DISABLED | ENABLED
  o  OpcomControl       DISABLED | ENABLED
  o  OpcomProxyMaint    DISABLED | ENABLED
  o  OpcomTarget        <string>
  o  PersonaCacheEntries              <integer>
  o  Port               <integer>
  o  ProxyCache                       DISABLED | ENABLED
  o  ProxyCacheDeviceCheckMinutes     <integer>
  o  ProxyCacheDeviceDirOrg           flat256 | 64x64
  o  ProxyCacheDeviceMaxPercent       <integer>
  o  ProxyCacheDevicePurgePercent     <integer>
  o  ProxyCacheFileKBytesMax          <integer>
  o  ProxyCacheNoReloadSeconds        <integer>
  o  ProxyCachePurgeList              <string>
  o  ProxyCacheReloadList             <string>
  o  ProxyCacheRoutineHourOfDay       <integer> (or empty to disabled)
  o  ProxyForwarded                   DISABLED | BY | FOR | ADDRESS
  o  ProxyHostLookupRetryCount        <integer>
  o  ProxyReportCacheLog              DISABLED | ENABLED
  o  ProxyReportLog                   DISABLED | ENABLED
  o  ProxyServing                     DISABLED | ENABLED
  o  ProxyUnknownRequestFields        DISABLED | ENABLED
  o  ProxyVerifyRecordMax             <integer>
  o  ProxyXForwardedFor               DISABLED | ENABLED | UNKNOWN | ADDRESS
  o  PutMaxKbytes       <integer>
  o  RegEx              DISABLED | ENABLED
  o  Reject             <host/domain>
  o  ReportBasicOnly    DISABLED | ENABLED
  o  ReportMetaInfo     DISABLED | ENABLED
  o  RequestHistory     <integer>
  o  Scripting          DISABLED | ENABLED
  o  SearchScript       <path-to-search-script>
  o  SearchScriptExclude              <string>
  o  ServerAdmin        <string>
  o  ServerAdminBodyTag               <string>
  o  ServerReportBodyTag              <string>
  o  ServerSignature    DISABLED | ENABLED
  o  Service            <string>
  o  ServiceListenBacklog             <integer>
  o  ServiceNotFoundURL <string>
  o  SSI | Shtml                      DISABLED | ENABLED
  o  SSIAccesses | ShtmlAccesses      DISABLED | ENABLED
  o  SSIExec | ShtmlExec              DISABLED | ENABLED
  o  SSISizeMax         <integer>
  o  StreamLf           <integer>
  o  TimeoutInput       <hh:mm:ss>
  o  TimeoutKeepAlive   <hh:mm:ss>
  o  TimeoutNoProgress  <hh:mm:ss>
  o  TimeoutOutput      <hh:mm:ss>
  o  Track              DISABLED | ENABLED
  o  TrackMultiSession  DISABLED | ENABLED
  o  TrackDomain        <string>
  o  Welcome            <file.suffix>


VERSION HISTORY
---------------
22-MAR-2004  MGD  [AuthSYSUAFuseACME]
22-NOV-2003  MGD  [ProxyVerifyRecordMax]
15-AUG-2003  MGD  where CDATA constraints make using &#10; entity impossible
                  use a field name of hidden$lf and &#94; substituted for it
07-JUL-2003  MGD  [CacheGuardPeriod]
08-JUL-2003  MGD  [CacheChunkKBytes] obsolete
15-MAY-2003  MGD  [AuthFailurePeriod], [AuthFailureTimeout],
                  [ProxyUnknownRequestFields]
02-APR-2003  MGD  [ProxyXForwardedFor], [ProxyForwarded] supercedes
                  [ProxyAddForwardedBy] (with backward compatibility)
08-MAR-2003  MGD  ConfigAddIcon() just exit if empty string
12-OCT-2002  MGD  refine metacon reporting
10-SEP-2002  MGD  bugfix; ConfigIconFor() terminate on content-type
26-MAY-2002  MGD  [LogPerInstance]
13-MAY-2002  MGD  [AuthSysUafPwdExpUrl], [AuthSysUafAllowdExpPwd]
27-APR-2002  MGD  use sys$setprv()
11-MAR-2002  MGD  content-type include FTP transfer mode (WASD and MIME.TYPES)
10-NOV-2001  MGD  [CharsetConvert]
29-SEP-2001  MGD  instance support,
                  [AuthCacheEntriesMax], [AuthCacheEntrySize]
15-SEP-2001  MGD  meta-config,
                  [SsiSizeMax] and [ProxyCacheNoReloadSeconds]
04-AUG-2001  MGD  support module WATCHing,
                  [CacheHashTableEntries] obsolete
13-APR-2001  MGD  [DclBitBucketTimeout]
20-MAR-2001  MGD  [LogFileExtend] (DEQ blocks) see LOGGING.C same date,
                  "hh:mm:ss" for providing a more versatile period
28-FEB-2001  MGD  [AddMimeTypesFile], [AddDefaultIcon],
                  [AddType] autoscript now indicated by leading '/',
                  OdsLoadTextFile(), OdsParseTextFile(), [IncludeFile]
06-DEC-2000  MGD  [DclCleanupScratchMinutes...]
01-NOV-2000  MGD  [DclDetachProcessPriority]
02-OCT-2000  MGD  [DclDetachProcess], [PersonaCacheEntries]
01-SEP-2000  MGD  [AuthRequestPath] (pre-7.1 compatibility)
19-AUG-2000  MGD  [DclGatewayBg] to enable raw socket,
                  [DclFullRequest] removed (HTTPD_DCL_FULL_REQUEST environment
                  variable can be defined for backward compatbility)
15-JUN-2000  MGD  [ServiceListenBacklog] for TCP/IP v5.0 or greater
06-MAY-2000  MGD  reorganise configuration data structures,
                  allow continuation lines ('\') in comma lists,
                  [AuthRevalidateLoginCookie],
                  [Track...]
07-APR-2000  MGD  [ServerAdmin], [ServerSignature], [CgiStrictOutput],
                  [DirMetaInfo], [Scripting], [ReportBasicOnly] and
                  [ReportMetaInfo] (which replaces [IncludedCommentedInfo]
                  and [ErrorSourceInfo]).
04-MAR-2000  MGD  use NetWriteFaol(), et.al.
16-FEB-2000  MGD  [SearchScriptExclude] directive,
                  [LogPerServiceHostOnly] directive,
                  allow wildcards in content-type file suffix specifications
02-JAN-2000  MGD  [Opcom...] directives,
                  config file opened via ODS module
30-OCT-1999  MGD  include IP address for services in ConfigReportNow(),
                  'Buffer...', 'MapUserNameCacheEntries', 'ServiceNotFoundURL',
                  'Timeout...' directives (with backward compatibility),
                  increase buffer space for ConfigCommaList()
03-MAR-1999  MGD  improve [AddType] and [AddIcon] directive checking
18-JAN-1999  MGD  [Proxy...] configuration parameters
                  bugfix; ignore empty lines (even with spaces in them!)
17-OCT-1998  MGD  [ErrorReportPath] added,
                  [Search] changed to [SearchScript],
                  [StreamLfPaths] obsoleted in favour of SET mapping rule
29-SEP-1998  MGD  [AddType] now allows "text/html; charset=ISO8859-5",
                  [CharsetDefault] text and server character set
27-AUG-1998  MGD  generic ConfigSetCommaList(),
                  add [AuthRevalidateUserMinutes], [LogExcludeHosts],
                      [DECnetReuseLifeTime], [DECnetConnectListMax],
                      [StreamLfPaths]
08-AUG-1998  MGD  add [DirNoImpliedWildcard]
17-JUN-1998  MGD  add [LogNaming], [LogPerService]
28-FEB-1998  MGD  improved icon handling efficiency
07-FEB-1998  MGD  v5.0 hash table for content-type suffix and icon searches,
                  default content type (for unknowns) configurable,
                  HTTP protocol name in [service] (for SSL),
                  [DirDescription] changed from boolean to integer
05-OCT-1997  MGD  cache parameters,
                  DCL script run-time parameter,
                  additional logging parameters
09-AUG-1997  MGD  v4.4 retired "ErrorInfo", "ErrorSysAdmin" (now in messages)
                  and AuthVMS (now /SYSUAF qualifier);  introduced
                  "DirDescription", "DirNoPrivIgnore", "ErrorSourceInfo",
                  bugfix; memory leak in file-based report and revise
01-AUG-1997  MGD  v4.3 activity number of days, DCL supply full request,
                  bugfix; annoying repeated instances of "unknown" content type
01-JUN-1997  MGD  v4.2 required additional DCL/scripting parameters
01-FEB-1997  MGD  HTTPd version 4;
                  major changes for form-based config;
                  added error message URLs
01-OCT-1996  MGD  HTML configuration report
01-AUG-1996  MGD  StreamLF conversion directive;
                  AuthBasic and AuthDigest directives;
12-APR-1996  MGD  file record/binary now determined by record format
                  (has removed the need of the text/binary, etc., in "AddType")
01-DEC-1995  MGD  HTTPd version 3
27-SEP-1995  MGD  added auto-scripting funtionality
07-AUG-1995  MGD  added support for VMS-style directory listing
16-JUN-1995  MGD  file contents description in 'AddType' (also see DIR.C)
20-DEC-1994  MGD  developed for multi-threaded HTTP daemon
*/
/*****************************************************************************/

#ifdef WASD_VMS_V6
#undef _VMS_V6_SOURCE
#define _VMS_V6_SOURCE
#undef __VMS_VER
#define __VMS_VER 60000000
#undef __CRTL_VER
#define __CRTL_VER 60000000
#endif

/* standard C header files */
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* VMS related header files */
#include <opcdef.h>
#include <ssdef.h>
#include <stsdef.h>

/* application related header */
#include "wasd.h"

#define WASD_MODULE "CONFIG"

/******************/
/* global storage */
/******************/

CONFIG_STRUCT  Config;
CONFIG_STRUCT  *ConfigMetaPtr;

struct OpcomStruct {
   int  Number;
   char  *Name;
} ConfigOpcomTarget [] = {
   0, "none",
   OPC$M_NM_CARDS, "CARDS",
   OPC$M_NM_CENTRL, "CENTRAL",
   OPC$M_NM_CLUSTER, "CLUSTER",
   OPC$M_NM_DEVICE, "DEVICE",
   OPC$M_NM_DISKS, "DISKS",
   OPC$M_NM_NTWORK, "NETWORK",
   OPC$M_NM_PRINT, "PRINT",
   OPC$M_NM_SECURITY, "SECURITY",
   OPC$M_NM_TAPES, "TAPES",
   OPC$M_NM_OPER1, "OPER1",
   OPC$M_NM_OPER2, "OPER2",
   OPC$M_NM_OPER3, "OPER3",
   OPC$M_NM_OPER4, "OPER4",
   OPC$M_NM_OPER5, "OPER5",
   OPC$M_NM_OPER6, "OPER6",
   OPC$M_NM_OPER7, "OPER7",
   OPC$M_NM_OPER8, "OPER8",
   OPC$M_NM_OPER9, "OPER9",
   OPC$M_NM_OPER10, "OPER10",
   OPC$M_NM_OPER11, "OPER11",
   OPC$M_NM_OPER12, "OPER12",
   -1, NULL
};

int  ConfigDnsLookupRetryCount;

char  ConfigContentTypeBlank [] = "x-internal/blank",
      ConfigContentTypeDefaultIcon [] = "x-internal/default-icon",
      ConfigContentTypeDir [] = "x-internal/directory",
      ConfigContentTypeIsMap [] = "text/x-ismap",
      ConfigContentTypeMenu [] = "text/x-menu",
      ConfigContentTypeParent [] = "x-internal/parent",
      ConfigContentTypeSsi [] = "text/x-shtml",
      ConfigContentTypeUnknown [] = "x-internal/unknown",
      ConfigContentTypeUrl [] = "x-internal/url",
      ConfigDefaultFileContentType [] = "application/octet-stream",
      ConfigStringOverflow [] = "*ERROR* string overflow";

char  *ConfigBlankIconPtr,
      *ConfigDirIconPtr,
      *ConfigDefaultIconPtr,
      *ConfigParentIconPtr,
      *ConfigUnknownIconPtr;

/********************/
/* external storage */
/********************/

#ifdef DBUG
extern BOOL Debug;
#else
#define Debug 0 
#endif

extern BOOL  HttpdServerStartup;

extern int  AuthFailureLimit,
            AuthFailurePeriodSeconds,
            AuthFailureTimeoutSeconds,
            DclCgiHeaderSize,
            DclCgiPlusInSize,
            DclSysCommandSize,
            DclSysOutputSize,
            InstanceConcurrentMax,
            MapUrlUserNameCacheEntries,
            NetReadBufferSize,
            OpcomMessages,
            OpcomTarget,
            OutputBufferSize,
            PersonaCacheEntries,
            ServiceLoadFromConfigFile,
            SsiSizeMax;

extern unsigned long  SysPrvMask[];

extern char  *CliAcceptHostsPtr,
             *CliRejectHostsPtr;

extern char  ServerHostPort[],
             SoftwareID[],
             TimeGmtString[],
             Utility[];

extern HTTPD_PROCESS  HttpdProcess;
extern MSG_STRUCT  Msgs;
extern META_CONFIG  *MetaGlobalConfigPtr;
extern WATCH_STRUCT  Watch;

/*****************************************************************************/
/*
*/ 
 
int ConfigLoad (META_CONFIG **MetaConPtrPtr)

{
   int  status;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigLoad() !AZ", CONFIG_FILE_NAME);

   status = MetaConLoad (MetaConPtrPtr, CONFIG_FILE_NAME,
                         &ConfigLoadCallback, true, false);
   if (*MetaConPtrPtr == MetaGlobalConfigPtr)
   {
      /* server startup */
      MetaConStartupReport (MetaGlobalConfigPtr, "CONFIG");
      if (VMSnok (status)) exit (status);
   }
   return (status);
}

/*****************************************************************************/
/*
Called by MetaConUnload() to free resources allocated during service
configuration.
*/ 
 
ConfigUnload (META_CONFIG *mcptr)

{
   int  status;
   MAPPING_META  *mmptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG, "ConfigUnload()");

   if (mcptr->ConfigMetaPtr &&
       mcptr->ConfigMetaPtr != ConfigMetaPtr)
   {
      VmFree (mcptr->ConfigMetaPtr, FI_LI);
      mcptr->ConfigMetaPtr = NULL;
   }
}

/*****************************************************************************/
/*
For each non-meta-config directive line read by MetaConLoad() this function is
called to parse the line text's contents and to configure the private data
structure associated with each rule.
*/

BOOL ConfigLoadCallback (META_CONFIG *mcptr)

{
   static char  ProblemMixed [] = "Mixed directive formats",
                ProblemObsolete [] = "Directive is obsolete",
                ProblemOverflow [] = "Storage overflow",
                ProblemParameter [] = "Parameter confusing",
                ProblemDirective [] = "Unknown directive",
                ProblemUsage [] = "Cannot use during service configuration";

   int  status;
   char  *cptr, *sptr, *zptr;
   char  StringBuffer [256];
   CONFIG_STRUCT  *cfptr;
   METACON_LINE  *mclptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
   {
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigLoadCallback() !&F !&X", &ConfigLoadCallback, mcptr);
      if (WATCH_MODULE(WATCH_MOD__DETAIL))
      {
         mclptr = mcptr->ParsePtr;
         WatchDataFormatted ("!&X !UL !UL !UL !UL !&X !&Z !&Z\n",
            mclptr, mclptr->Size, mclptr->Token, mclptr->Number,
            mclptr->Length, mclptr->LineDataPtr, mclptr->TextPtr,
            mclptr->InlineTextPtr);
      }
   }

   /* get a pointer to the current "line" */
   mclptr = mcptr->ParsePtr;

   /* if this is during server startup then set the global service pointer */
   if (HttpdServerStartup)
      cfptr = mcptr->ConfigMetaPtr = ConfigMetaPtr = &Config;
   else
   /* if a report then conjure one up ex cathedra */
   if (!mcptr->ConfigMetaPtr)
      cfptr = mcptr->ConfigMetaPtr = VmGet (sizeof(CONFIG_STRUCT));
   else
      /* not the first time through */
      cfptr = mcptr->ConfigMetaPtr;

   if (mclptr->Token == METACON_TOKEN_PRE)
   {
      /******************/
      /* pre-initialize */
      /******************/

      cfptr->cfScript.Enabled = true;
      cfptr->BracketDirectives =
         cfptr->EquateDirectives = false;
      cfptr->cfAuth.CacheMinutes =
         cfptr->cfAuth.RevalidateUserMinutes = 60;
      cfptr->cfDir.PreExpired = PRE_EXPIRE_INDEX_OF;
      strcpy (cfptr->cfDir.DefaultLayout, DEFAULT_DIR_LAYOUT);
      cfptr->cfServer.AcceptHostsPtr =
         cfptr->cfContent.ContentInfoListHeadPtr =
         cfptr->cfContent.IconListHeadPtr =
         cfptr->cfLog.ExcludeHostsPtr =
         cfptr->cfServer.RejectHostsPtr = NULL;
      cfptr->cfContent.ContentTypeStructOverhead = sizeof(CONTENT_TYPE);
      cfptr->cfContent.IconStructOverhead = sizeof(ICON_TYPE);
      cfptr->cfContent.ContentTypeDefaultPtr = "";

      return (true);
   }

   if (mclptr->Token == METACON_TOKEN_POST)
   {
      /****************/
      /* post-process */
      /****************/

      if (!cfptr->cfMisc.PutMaxKbytes)
         cfptr->cfMisc.PutMaxKbytes = PUT_DEFAULT_KBYTES_MAX;
      if (!cfptr->cfMisc.PutVersionLimit)
         cfptr->cfMisc.PutVersionLimit = PUT_DEFAULT_VERSION_LIMIT;

      if (cfptr->cfAuth.CacheMinutes > CONFIG_REVALIDATE_MINUTES_MAX)
         cfptr->cfAuth.CacheMinutes = CONFIG_REVALIDATE_MINUTES_MAX;

      if (cfptr->cfAuth.RevalidateUserMinutes >
          CONFIG_REVALIDATE_MINUTES_MAX)
          cfptr->cfAuth.RevalidateUserMinutes =
             CONFIG_REVALIDATE_MINUTES_MAX;

      if (CliAcceptHostsPtr)
         cfptr->cfServer.AcceptHostsPtr = CliAcceptHostsPtr;

      if (CliRejectHostsPtr)
         cfptr->cfServer.RejectHostsPtr = CliRejectHostsPtr;

      /* push these to all upper case (just cause it looks uniform) */
      if (cfptr->cfScript.DefaultSearchExcludePtr)
         for (cptr = cfptr->cfScript.DefaultSearchExcludePtr; *cptr; cptr++)
            *cptr = toupper(*cptr);

      ConfigContentTypeIcon (mcptr);

      if (!cfptr->cfDir.BodyTag[0])
         strcpy (cfptr->cfDir.BodyTag, CONFIG_DEFAULT_DIR_BODY_TAG);
      if (!cfptr->cfServer.AdminBodyTag[0])
         strcpy (cfptr->cfServer.AdminBodyTag,
                 CONFIG_DEFAULT_ADMIN_BODY_TAG);
      if (!cfptr->cfServer.ReportBodyTag[0])
         strcpy (cfptr->cfServer.ReportBodyTag,
                 CONFIG_DEFAULT_REPORT_BODY_TAG);

      if (cfptr->cfServer.ListenBacklog <= 0 ||
          cfptr->cfServer.ListenBacklog > 999)
         cfptr->cfServer.ListenBacklog = DEFAULT_LISTEN_BACKLOG;

      /* for backward compatibility with pre-v4.3 behaviour (see DCL.C) */
      if (getenv ("HTTPD_DCL_FULL_REQUEST"))
         cfptr->cfScript.FullRequest = true;

      if (HttpdServerStartup)
      {
         /*************************/
         /* during server startup */
         /*************************/

         if (Config.cfServer.BusyLimit)
            InstanceConcurrentMax = Config.cfServer.BusyLimit;

         if (OpcomTarget = Config.cfOpcom.Target)
            OpcomMessages = Config.cfOpcom.Messages;
         else
            OpcomMessages = 0;

         /* command line overrides configuration, default fallbacks */
         if (!NetReadBufferSize)
            NetReadBufferSize = Config.cfBuffer.SizeNetRead;
         if (!NetReadBufferSize)
            NetReadBufferSize = DEFAULT_NET_READ_BUFFER_SIZE;
         if (!OutputBufferSize)
            OutputBufferSize = Config.cfBuffer.SizeNetWrite;
         if (!OutputBufferSize)
            OutputBufferSize = DEFAULT_OUTPUT_BUFFER_SIZE;

         SsiSizeMax = cfptr->cfSsi.SizeMax * 1024;
         if (!SsiSizeMax) SsiSizeMax = FILE_TYPE_SSI_SIZE_MAX;

         if (Config.cfContent.CharsetConvertPtr)
            ResponseCharsetConfig (mcptr);

         if (Config.cfMisc.DnsLookupRetryCount)
            ConfigDnsLookupRetryCount = Config.cfMisc.DnsLookupRetryCount;
         else
            ConfigDnsLookupRetryCount = TCPIP_LOOKUP_RETRY_COUNT;
         if (ConfigDnsLookupRetryCount < 0 || ConfigDnsLookupRetryCount > 100)
            ConfigDnsLookupRetryCount = TCPIP_LOOKUP_RETRY_COUNT;
      }

      return (true);
   }

   /***********/
   /* process */
   /***********/

   /* if it's not text then config is not interested in it! */
   if (mclptr->Token != METACON_TOKEN_TEXT)
   {
      MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemUsage);
      return (true);
   }

   /* buffer the text associated with the current "line" */
   zptr = (sptr = StringBuffer) + sizeof(StringBuffer);
   cptr = mclptr->TextPtr;
   while (*cptr && sptr < zptr) *sptr++ = *cptr++;
   if (sptr >= zptr)
   {
      MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemOverflow);
      return (false);
   }
   *sptr = '\0';
   cptr = StringBuffer;

   while (*cptr && ISLWS(*cptr)) cptr++;
   if (*cptr == '[')
   {
      if (cfptr->EquateDirectives)
      {
         MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemMixed);
         return (false);
      }
      cfptr->BracketDirectives = true;
      cptr++;
      zptr = (sptr = cfptr->DirectiveName) + sizeof(cfptr->DirectiveName)-1;
      while (*cptr && *cptr != ']' && sptr < zptr) *sptr++ = *cptr++;
      if (sptr > zptr)
      {
         MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemOverflow);
         return (false);
      }
      *sptr = '\0';
      if (*cptr) cptr++;
      while (*cptr && ISLWS(*cptr)) cptr++;
   }
   else
   if (!cfptr->BracketDirectives)
   {
      cfptr->EquateDirectives = true;
      zptr = (sptr = cfptr->DirectiveName) + sizeof(cfptr->DirectiveName)-1;
      while (*cptr && !ISLWS(*cptr) && *cptr != '=' && sptr < zptr)
         *sptr++ = *cptr++;
      while (*cptr && *cptr != '=') cptr++;
      if (sptr > zptr)
      {
         MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemOverflow);
         return (false);
      }
      *sptr = '\0';
      if (*cptr) cptr++;
      while (*cptr && ISLWS(*cptr)) cptr++;
   }
   sptr = cptr;
   cptr = cfptr->DirectiveName; 
   if (Debug) fprintf (stdout, "|%s|%s|\n", cptr, sptr);
   if (cfptr->BracketDirectives && !*sptr) return (true);
   if (!*sptr)
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
      return (true);
   }

   /**************/
   /* directives */
   /**************/

   if (strsame (cptr, "Accept", -1))
      StringListAdd (sptr, &cfptr->cfServer.AcceptHostsPtr,
                           &cfptr->cfServer.AcceptHostsLength);
   else
   if (strsame (cptr, "ActivityDays", -1))
      cfptr->cfMisc.ActivityNumberOfDays = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "AddType", -1))
      ConfigAddType (mcptr, sptr);
   else
   if (strsame (cptr, "AddMimeTypesFile", -1))
      ConfigAddMimeTypesFile (mcptr, sptr);
   else
   if (strsame (cptr, "AddIcon", -1))
      ConfigAddIcon (mcptr, sptr, NULL, false);
   else
   if (strsame (cptr, "AddBlankIcon", -1))
      ConfigAddIcon (mcptr, sptr, ConfigContentTypeBlank, false);
   else
   if (strsame (cptr, "AddDirIcon", -1))
      ConfigAddIcon (mcptr, sptr, ConfigContentTypeDir, false);
   else
   if (strsame (cptr, "AddDefaultIcon", -1))
      ConfigAddIcon (mcptr, sptr, ConfigContentTypeDefaultIcon, false);
   else
   if (strsame (cptr, "AddParentIcon", -1))
      ConfigAddIcon (mcptr, sptr, ConfigContentTypeParent, false);
   else
   if (strsame (cptr, "AddUnknownIcon", -1))
      ConfigAddIcon (mcptr, sptr, ConfigContentTypeUnknown, false);
   else
   if (strsame (cptr, "AuthBasic", -1))
      cfptr->cfAuth.BasicEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "AuthCacheEntriesMax", -1))
      cfptr->cfAuth.CacheEntriesMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "AuthCacheEntrySize", -1))
      cfptr->cfAuth.CacheEntrySize = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "AuthCacheMinutes", -1))
      cfptr->cfAuth.CacheMinutes = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "AuthDigestGetLife", -1))
      cfptr->cfAuth.DigestNonceGetLifeTime = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "AuthDigestPutLife", -1))
      cfptr->cfAuth.DigestNoncePutLifeTime = MetaConSetInteger (mcptr, sptr);
   else
   /* "AuthDigest" MUST come after other AuthDigests for obvious reasons */
   if (strsame (cptr, "AuthDigest", -1))
      cfptr->cfAuth.DigestEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "AuthFailureLimit", -1))
      cfptr->cfAuth.FailureLimit = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "AuthFailurePeriod", -1))
      cfptr->cfAuth.FailurePeriodSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "AuthFailureTimeout", -1))
      cfptr->cfAuth.FailureTimeoutSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "AuthRevalidateUserMinutes", -1))
      cfptr->cfAuth.RevalidateUserMinutes = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "AuthRevalidateLoginCookie", -1))
      cfptr->cfAuth.RevalidateLoginCookie = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "AuthSYSUAFacceptExpPwd", -1))
      cfptr->cfAuth.SysUafAcceptExpPwd = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "AuthSYSUAFpwdExpUrl", -1))
      MetaConSetString (mcptr, sptr, cfptr->cfAuth.SysUafPwdExpUrl,
                                     sizeof(cfptr->cfAuth.SysUafPwdExpUrl));
   else
   if (strsame (cptr, "AuthSYSUAFuseACME", -1))
      cfptr->cfAuth.SysUafUseACME = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "BufferSizeDclCommand", -1))
      cfptr->cfBuffer.SizeDclCommand = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "BufferSizeDclOutput", -1))
      cfptr->cfBuffer.SizeDclOutput = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "BufferSizeDclCgiHeader", -1))
      cfptr->cfBuffer.SizeDclCgiHeader = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "BufferSizeDclCgiPlusIn", -1))
      cfptr->cfBuffer.SizeDclCgiPlusIn = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "BufferSizeNetRead", -1))
      cfptr->cfBuffer.SizeNetRead = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "BufferSizeNetWrite", -1))
      cfptr->cfBuffer.SizeNetWrite = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "Busy", -1))
      cfptr->cfServer.BusyLimit = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "CacheChunkKBytes", -1))
      MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete);
   else
   if (strsame (cptr, "CacheEntriesMax", -1))
      cfptr->cfCache.EntriesMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "CacheFileKBytesMax", -1))
      cfptr->cfCache.FileKBytesMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "CacheFrequentHits", -1))
      cfptr->cfCache.FrequentHits = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "CacheFrequentPeriod", -1))
      cfptr->cfCache.FrequentSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   /* "CacheFrequentSeconds" for backward compatibility */
   if (strsame (cptr, "CacheFrequentSeconds", -1))
      cfptr->cfCache.FrequentSeconds = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "CacheGuardPeriod", -1))
      cfptr->cfCache.GuardSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "CacheTotalKBytesMax", -1))
      cfptr->cfCache.TotalKBytesMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "CacheValidatePeriod", -1))
      cfptr->cfCache.ValidateSeconds = MetaConSetSeconds (mcptr, sptr, 1);
   else
   /* "CacheValidateSeconds" for backward compatibility */
   if (strsame (cptr, "CacheValidateSeconds", -1))
      cfptr->cfCache.ValidateSeconds = MetaConSetInteger (mcptr, sptr);
   else
   /* "cache" must follow all the others for the obvious reason */
   if (strsame (cptr, "Cache", -1))
      cfptr->cfCache.Enabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "CgiStrictOutput", -1))
      cfptr->cfScript.CgiStrictOutput = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "CharsetDefault", -1))
      MetaConSetString (mcptr, sptr, cfptr->cfContent.CharsetDefault,
                                     sizeof(cfptr->cfContent.CharsetDefault));
   else
   if (strsame (cptr, "CharsetConvert", -1))
      StringListAdd (sptr, &cfptr->cfContent.CharsetConvertPtr,
                           &cfptr->cfContent.CharsetConvertLength);
   else
   if (strsame (cptr, "DclDetachProcess", -1))
      cfptr->cfScript.DetachProcess = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DclDetachProcessPriority", -1))
      MetaConSetString (mcptr, sptr, cfptr->cfScript.DetachProcessPriority,
                               sizeof(cfptr->cfScript.DetachProcessPriority));
   else
   if (strsame (cptr, "DclGatewayBg", -1))
      cfptr->cfScript.GatewayBg = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DclHardLimit", -1))
      cfptr->cfScript.ScriptProcessHardLimit =
         MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DclScriptRunTime", -1))
      ConfigSetScriptRunTime (mcptr, sptr);
   else
   if (strsame (cptr, "DclSoftLimit", -1))
      cfptr->cfScript.ScriptProcessSoftLimit = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DclBitBucketTimeout", -1))
      cfptr->cfScript.BitBucketTimeout = MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "DclCgiPlusLifeTime", -1))
      cfptr->cfScript.CgiPlusLifeTime = MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "DclCleanupScratchMinutesMax", -1))
      cfptr->cfScript.CleanupScratchMinutesMax =
         MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DclCleanupScratchMinutesOld", -1))
      cfptr->cfScript.CleanupScratchMinutesOld =
         MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DclZombieLifeTime", -1))
      cfptr->cfScript.ZombieLifeTime = MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "DclSpawnAuthPriv", -1))
      cfptr->cfScript.SpawnAuthPriv = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DECnetReuseLifeTime", -1))
      cfptr->cfScript.DECnetReuseLifeTime =
          MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "DECnetConnectListMax", -1))
      cfptr->cfScript.DECnetConnectListMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DirAccess", -1))
      ConfigSetDirAccess (mcptr, sptr);
   else
   if (strsame (cptr, "DirBodyTag", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfDir.BodyTag, sizeof(cfptr->cfDir.BodyTag));
   else
   if (strsame (cptr, "DirDescription", -1))
   {
      /*
         [DirDescription] boolean deprecated in v5.0, noow using
         integer [DirDescriptionLines], provide fallback behaviour.
      */
      if (MetaConSetBoolean (mcptr, sptr))
         cfptr->cfDir.DescriptionLines = 30;
      else
         cfptr->cfDir.DescriptionLines = 0;
   }
   else
   if (strsame (cptr, "DirDescriptionLines", -1))
      cfptr->cfDir.DescriptionLines = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DirLayout", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfDir.DefaultLayout,
                        sizeof(cfptr->cfDir.DefaultLayout));
   else
   if (strsame (cptr, "DirMetaInfo", -1))
      cfptr->cfDir.MetaInfoEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DirOwner", -1))
      cfptr->cfDir.OwnerEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DirPreExpired", -1))
      cfptr->cfDir.PreExpired = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DirNoImpliedWildcard", -1))
      cfptr->cfDir.NoImpliedWildcard = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DirNoPrivIgnore", -1))
      cfptr->cfDir.NoPrivIgnore = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DirReadMeFile", -1))
      ConfigSetDirReadMeFile (mcptr, sptr);
   else
   /* "ReadMe" MUST come after the other ReadMes for obvious reasons */
   if (strsame (cptr, "DirReadMe", -1))
      ConfigSetDirReadMe (mcptr, sptr);
   else
   if (strsame (cptr, "DirWildcard", -1))
      cfptr->cfDir.WildcardEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   /* "DNSLookup" for backward compatibility */
   if (strsame (cptr, "DNSLookupClient", -1) ||
       strsame (cptr, "DNSLookup", -1))
      cfptr->cfMisc.DnsLookupClient = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "DNSLookupRetry", -1))
      cfptr->cfMisc.DnsLookupRetryCount = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "DNSLookupLifeTime", -1))
      cfptr->cfMisc.DnsLookupLifeTimeSeconds =
         MetaConSetSeconds (mcptr, sptr, 1);
   else
   /* "Recommend" for backward compatibility */
   if (strsame (cptr, "ErrorRecommend", -1) ||
       strsame (cptr, "Recommend", -1))
      cfptr->cfReport.ErrorRecommend = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "ErrorReportPath", -1))
   {
      MetaConSetString (mcptr, sptr,
                        cfptr->cfReport.ErrorReportPath,
                        sizeof(cfptr->cfReport.ErrorReportPath));
      cfptr->cfReport.ErrorReportPathLength =
         strlen(cfptr->cfReport.ErrorReportPath);
   }
   else
   if (strsame (cptr, "InstanceMax", -1))
   {
      if (strsame (sptr, "CPU", 3))
         cfptr->cfServer.InstanceMax = INSTANCE_PER_CPU;
      else
         cfptr->cfServer.InstanceMax = MetaConSetInteger (mcptr, sptr);
   }
   else
   if (strsame (cptr, "Logging", -1))
      cfptr->cfLog.Enabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "LogExcludeHosts", -1))
      StringListAdd (sptr, &cfptr->cfLog.ExcludeHostsPtr,
                           &cfptr->cfLog.ExcludeHostsLength);
   else
   if (strsame (cptr, "LogFile", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfLog.FileName, sizeof(cfptr->cfLog.FileName));
   else
   if (strsame (cptr, "LogFileExtend", -1))
      cfptr->cfLog.ExtendBlocks = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "LogFormat", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfLog.Format, sizeof(cfptr->cfLog.Format));
   else
   if (strsame (cptr, "LogNaming", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfLog.Naming, sizeof(cfptr->cfLog.Naming));
   else
   if (strsame (cptr, "LogPeriod", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfLog.Period, sizeof(cfptr->cfLog.Period));
   else
   if (strsame (cptr, "LogPerInstance", -1))
      cfptr->cfLog.PerInstance = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "LogPerService", -1))
      cfptr->cfLog.PerService = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "LogPerServiceHostOnly", -1))
      cfptr->cfLog.PerServiceHostOnly = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "MapUserNameCacheEntries", -1))
      cfptr->cfMisc.MapUserNameCacheEntries = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "Monitor", -1))
      cfptr->cfMisc.MonitorEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "OpcomTarget", -1) ||
       strsame (cptr, "OpcomAdmin", -1) ||
       strsame (cptr, "OpcomAuthorization", -1) ||
       strsame (cptr, "OpcomControl", -1) ||
       strsame (cptr, "OpcomHTTPd", -1) ||
       strsame (cptr, "OpcomProxyMaint", -1))
      ConfigSetOpcom (mcptr, cptr, sptr);
   else
   if (strsame (cptr, "PersonaCacheEntries", -1))
      cfptr->cfMisc.PersonaCacheEntries = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyCache", -1))
      cfptr->cfProxy.CacheEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyCacheDeviceCheckMinutes", -1))
      cfptr->cfProxy.CacheDeviceCheckMinutes = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyCacheDeviceDirOrg", -1))
   {
      if (strsame (sptr, "flat256", 7))
         cfptr->cfProxy.CacheDeviceDirOrg = PROXY_CACHE_DIR_ORG_FLAT256;
      else
      if (strsame (sptr, "64x64", 5))
         cfptr->cfProxy.CacheDeviceDirOrg = PROXY_CACHE_DIR_ORG_64X64;
      else
      {
         cfptr->cfProxy.CacheDeviceDirOrg = 0;
         MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemParameter);
      }
   }
   else
   if (strsame (cptr, "ProxyCacheDeviceMaxPercent", -1))
      cfptr->cfProxy.CacheDeviceMaxPercent = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyCacheDevicePurgePercent", -1))
      cfptr->cfProxy.CacheDevicePurgePercent = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyCacheFileKBytesMax", -1))
      cfptr->cfProxy.CacheFileKBytesMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyCacheNoReloadSeconds", -1))
      cfptr->cfProxy.CacheNoReloadSeconds = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyCacheRoutineHourOfDay", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfProxy.CacheRoutineHourOfDayString,
                        sizeof(cfptr->cfProxy.CacheRoutineHourOfDayString));
   else
   if (strsame (cptr, "ProxyCachePurgeList", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfProxy.CachePurgeList,
                        sizeof(cfptr->cfProxy.CachePurgeList));
   else
   if (strsame (cptr, "ProxyCacheReloadList", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfProxy.CacheReloadList,
                        sizeof(cfptr->cfProxy.CacheReloadList));
   else
   if (strsame (cptr, "ProxyForwarded", -1))
   {
      if (strsame (sptr, "BY", 2))
         cfptr->cfProxy.ForwardedBy = PROXY_FORWARDED_BY;
      else
      if (strsame (sptr, "DISABLED", 8))
         cfptr->cfProxy.ForwardedBy = PROXY_FORWARDED_DISABLED;
      else
      if (strsame (sptr, "FOR", 3))
         cfptr->cfProxy.ForwardedBy = PROXY_FORWARDED_FOR;
      else
      if (strsame (sptr, "ADDRESS", 7))
         cfptr->cfProxy.ForwardedBy = PROXY_FORWARDED_ADDRESS;
      else
      {
         cfptr->cfProxy.ForwardedBy = PROXY_FORWARDED_DISABLED;
         MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemParameter);
      }
   }
   else
   /* "ProxyAddForwardedBy" for backward compatibility with 'ProxyForwarded' */
   if (strsame (cptr, "ProxyAddForwardedBy", -1))
   {
      if (MetaConSetBoolean (mcptr, sptr))
         cfptr->cfProxy.ForwardedBy = PROXY_FORWARDED_BY;
      else
         cfptr->cfProxy.ForwardedBy = PROXY_FORWARDED_DISABLED;
   }
   else
   if (strsame (cptr, "ProxyHostCachePurgeHours", -1))
      MetaConReport (mcptr, METACON_REPORT_INFORM, ProblemObsolete);
   else
   if (strsame (cptr, "ProxyHostLookupRetryCount", -1))
      cfptr->cfProxy.HostLookupRetryCount = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyReportCacheLog", -1))
      cfptr->cfProxy.ReportCacheLog = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyReportLog", -1))
      cfptr->cfProxy.ReportLog = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyServing", -1))
      cfptr->cfProxy.ServingEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyUnknownRequestFields", -1))
      cfptr->cfProxy.UnknownRequestFields = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyVerifyRecordMax", -1))
      cfptr->cfProxy.VerifyRecordMax = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ProxyXForwardedFor", -1))
   {
      if (strsame (sptr, "ENABLED", 7))
         cfptr->cfProxy.XForwardedFor = PROXY_XFORWARDEDFOR_ENABLED;
      else
      if (strsame (sptr, "UNKNOWN", 7))
         cfptr->cfProxy.XForwardedFor = PROXY_XFORWARDEDFOR_UNKNOWN;
      else
      if (strsame (sptr, "ADDRESS", 7))
         cfptr->cfProxy.XForwardedFor = PROXY_XFORWARDEDFOR_ADDRESS;
      else
      if (strsame (sptr, "DISABLED", 8))
         cfptr->cfProxy.XForwardedFor = PROXY_XFORWARDEDFOR_DISABLED;
      else
      {
         cfptr->cfProxy.XForwardedFor = PROXY_XFORWARDEDFOR_DISABLED;
         MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemParameter);
      }
   }
   else
   if (strsame (cptr, "Port", -1))
      cfptr->cfServer.DefaultPort = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "PutMaxKbytes", -1))
      cfptr->cfMisc.PutMaxKbytes = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "PutVersionLimit", -1))
      cfptr->cfMisc.PutVersionLimit = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "RegEx", -1))
      cfptr->cfMisc.RegexEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "Reject", -1))
      StringListAdd (sptr, &cfptr->cfServer.RejectHostsPtr,
                           &cfptr->cfServer.RejectHostsLength);
   else
   if (strsame (cptr, "ReportBasicOnly", -1))
      cfptr->cfReport.BasicOnly = MetaConSetBoolean (mcptr, sptr);
   else
   /* "CommentedInfo" & "ErrorSourceInfo" for backward compatibility */
   if (strsame (cptr, "ReportMetaInfo", -1) ||
       strsame (cptr, "CommentedInfo", -1) ||
       strsame (cptr, "ErrorSourceInfo", -1))
      cfptr->cfReport.MetaInfoEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "RequestHistory", -1))
      cfptr->cfMisc.RequestHistory = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "Scripting", -1))
      cfptr->cfScript.Enabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "Search", -1) ||
       strsame (cptr, "SearchScript", -1))
   {
      MetaConSetString (mcptr, sptr,
                        cfptr->cfScript.DefaultSearch,
                        sizeof(cfptr->cfScript.DefaultSearch));
      cfptr->cfScript.DefaultSearchLength =
         strlen(cfptr->cfScript.DefaultSearch);
   }
   else
   if (strsame (cptr, "SearchScriptExclude", -1))
      StringListAdd (sptr, &cfptr->cfScript.DefaultSearchExcludePtr,
                           &cfptr->cfScript.DefaultSearchExcludeLength);
   else
   if (strsame (cptr, "ServerAdmin", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfServer.AdminEmail,
                        sizeof(cfptr->cfServer.AdminEmail));
   else
   if (strsame (cptr, "ServerAdminBodyTag", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfServer.AdminBodyTag,
                        sizeof(cfptr->cfServer.AdminBodyTag));
   else
   if (strsame (cptr, "ServerReportBodyTag", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfServer.ReportBodyTag,
                        sizeof(cfptr->cfServer.ReportBodyTag));
   else
   if (strsame (cptr, "ServerSignature", -1))
      cfptr->cfProxy.ServingEnabled = ConfigSetServerSignature (mcptr, sptr);
   else
   if (strsame (cptr, "Service", -1))
      StringListAdd (sptr, &cfptr->cfServer.ServicePtr,
                           &cfptr->cfServer.ServiceLength);
   else
   if (strsame (cptr, "ServiceListenBacklog", -1))
      cfptr->cfServer.ListenBacklog = MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "ServiceNotFoundURL", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfServer.ServiceNotFoundUrl,
                        sizeof(cfptr->cfServer.ServiceNotFoundUrl));
   else
   /* "ShtmlAccesses" for backward compatibility */
   if (strsame (cptr, "SSIAccesses", -1) ||
       strsame (cptr, "ShtmlAccesses", -1))
      cfptr->cfSsi.AccessesEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   /* "ShtmlExec" for backward compatibility */
   if (strsame (cptr, "SSIExec", -1) ||
       strsame (cptr, "ShtmlExec", -1))
      cfptr->cfSsi.ExecEnabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "SSISizeMax", -1))
      cfptr->cfSsi.SizeMax = MetaConSetInteger (mcptr, sptr);
   else
   /* "SSI" MUST come after the other SSIs for obvious reasons */
   /* "Shtml" for backward compatibility */
   if (strsame (cptr, "SSI", -1) ||
       strsame (cptr, "Shtml", -1))
      cfptr->cfSsi.Enabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "StreamLF", -1))
      cfptr->cfMisc.StreamLfConversionMaxKbytes =
         MetaConSetInteger (mcptr, sptr);
   else
   if (strsame (cptr, "TimeoutInput", -1) ||
       strsame (cptr, "InputTimeout", -1))
      cfptr->cfTimeout.Input = MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "TimeoutKeepAlive", -1) ||
       strsame (cptr, "KeepAliveTimeout", -1))
      cfptr->cfTimeout.KeepAlive = MetaConSetSeconds (mcptr, sptr, 1);
   else
   if (strsame (cptr, "TimeoutNoProgress", -1))
      cfptr->cfTimeout.NoProgress =
         MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "TimeoutOutput", -1) ||
       strsame (cptr, "OutputTimeout", -1))
      cfptr->cfTimeout.Output = MetaConSetSeconds (mcptr, sptr, 60);
   else
   if (strsame (cptr, "Track", -1))
      cfptr->cfTrack.Enabled = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "TrackDomain", -1))
      MetaConSetString (mcptr, sptr,
                        cfptr->cfTrack.Domain, sizeof(cfptr->cfTrack.Domain));
   else
   if (strsame (cptr, "TrackMultiSession", -1))
      cfptr->cfTrack.MultiSession = MetaConSetBoolean (mcptr, sptr);
   else
   if (strsame (cptr, "Welcome", -1))
      ConfigSetWelcome (mcptr, sptr);
   else
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemDirective);

   return (true);
}

/*****************************************************************************/
/*
Free all memory allocated for a configuration.  Only used after file-based
configuration report or revision.
*/

ConfigFree (META_CONFIG *mcptr)

{
   int  Count;
   char  *cptr;
   CONFIG_STRUCT  *cfptr;
   CONTENT_TYPE  *ctptr;
   ICON_TYPE  *itptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG, "ConfigFree()");

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   ctptr = cfptr->cfContent.ContentInfoListHeadPtr;
   while (ctptr)
   {
      cptr = (char*)ctptr;
      ctptr = ctptr->NextPtr;
      VmFree (cptr, FI_LI);
   }

   itptr = cfptr->cfContent.IconListHeadPtr;
   while (itptr)
   {
      cptr = (char*)itptr;
      itptr = itptr->NextPtr;
      VmFree (cptr, FI_LI);
   }

   for (Count = 0; Count < cfptr->cfContent.HomePageCount; Count++)
      if (cfptr->cfContent.HomePageArray[Count])
         VmFree (cfptr->cfContent.HomePageArray[Count], FI_LI);

   if (cfptr->cfContent.CharsetConvertPtr)
      VmFree (cfptr->cfContent.CharsetConvertPtr, FI_LI);
   if (cfptr->cfServer.AcceptHostsPtr)
      VmFree (cfptr->cfServer.AcceptHostsPtr, FI_LI);
   if (cfptr->cfLog.ExcludeHostsPtr)
      VmFree (cfptr->cfLog.ExcludeHostsPtr, FI_LI);
   if (cfptr->cfServer.RejectHostsPtr)
      VmFree (cfptr->cfServer.RejectHostsPtr, FI_LI);
   if (cfptr->cfScript.DefaultSearchExcludePtr)
      VmFree (cfptr->cfScript.DefaultSearchExcludePtr, FI_LI);
   if (cfptr->cfServer.ServicePtr)
      VmFree (cfptr->cfServer.ServicePtr, FI_LI);
}

/*****************************************************************************/
/*
Add a mime content type corresponding to the file suffix (extension, type). 
The file suffix can contain the asterisk wildcard character, matching zero or
more characters.  The content-type can be quoted and can include additional
characteristics, including an FTP transfer mode (ASCII - 'A', binary/Image -
'B'/'I' as shown in the final example).

Format: "AddType <.suffix> <type[;forw
charset=]> [</script>] [<description>]"

Examples: "AddType .html text/html HTML"
          "AddType .html text/html;charset=ISO8859-5 HTML"
          "AddType .html "text/html; charset=ISO8859-5" HTML"
          "AddType .txt text/plain plain text"
          "AddType .read* text/plain plain text"
          "AddType .hlb text/x-script /cgi-bin/conan VMS help library"
          "AddType .gif image/gif GIF image"
          "AddType .ps application/postscript(FTP:A) Postscript document"

The directive is stored as a linked list of structures of dynamically
allocated memory containing a reformatted version of the directive string.
Function ConfigContentType() searches this list to get pointers to the content
type, any auto-script, and description, into the client request data
structure. A hash table is used to more rapidy index into the list.
*/ 

ConfigAddType
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemFtpMode [] = "unknown FTP mode";

   char  FtpMode;
   char  *AutoScriptPtr,
         *DescriptionPtr,
         *MimeTypePtr,
         *SuffixPtr;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigAddType() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   AutoScriptPtr = DescriptionPtr = MimeTypePtr = SuffixPtr = "";
   FtpMode = 0;

   for (SuffixPtr = pptr; *pptr && !ISLWS(*pptr); pptr++);
   if (*pptr) *pptr++ = '\0';

   /* content type (can include quotes, e.g. "text/html; charset=ISO-8859-5" */
   while (*pptr && ISLWS(*pptr)) pptr++;
   if (*pptr == '\"')
   {
      pptr++;
      MimeTypePtr = pptr;
      while (*pptr && *pptr != '\"') pptr++;
   }
   else
   {
      MimeTypePtr = pptr;
      while (*pptr && !ISLWS(*pptr) && *pptr != '(') pptr++;
   }
   if (*pptr == '(' || *(unsigned short*)pptr == '\"(')
   {
      if (*pptr) *pptr++ = '\0';
      if (*pptr == '(') pptr++;
      if (strsame (pptr, "FTP:", 4))
         if (pptr[4] == 'A' || pptr[4] == 'B' || pptr[4] == 'I')
            FtpMode = pptr[4];
      while (*pptr && !ISLWS(*pptr)) pptr++;
      if (!FtpMode) MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemFtpMode);
   }
   else
   if (*pptr)
      *pptr++ = '\0';

   /* (optional) script activation indicated by leading slash */
   while (*pptr && ISLWS(*pptr)) pptr++;
   if (*pptr == '/')
   {
      AutoScriptPtr = pptr;
      while (*pptr && !ISLWS(*pptr)) pptr++;
      if (*pptr) *pptr++ = '\0';
   }
   else
   if (*pptr == '-')
   {
      /* backward compatibility for those still place-holding with '-' */
      while (*pptr && !ISLWS(*pptr)) pptr++;
      AutoScriptPtr = "";
   }
   else
      AutoScriptPtr = "";

   /* (optional) description, to end of line */
   while (*pptr && ISLWS(*pptr)) pptr++;
   DescriptionPtr = pptr;
   /* find the end-of-line */
   while (*pptr) pptr++;
   if (*pptr) *pptr++ = '\0';

   ConfigAddTypeNow (mcptr, MimeTypePtr, SuffixPtr, AutoScriptPtr,
                     DescriptionPtr, FtpMode, false);
}

/*****************************************************************************/
/*
MIME.TYPES file (with WASD 'commented' extensions).

Format: mime/type file-ext [file-ext file-ext]
        #! optional descriptive text    (applies to above)
        #!/optional/auto-script         (applies to above)
        #[alt] /optional/icon.gif       (applies to above)
        mime/type file-ext [file-ext file-ext]

Examples: text/html          html htm
          #! HTML markup
          text/plain         asc txt
          #! plain text
          #[TXT] /httpd/-/text.gif
          application/x-script   bks decw$bookshelf
          #/cgi-bin/hypershelf
          #! Bookreader shelf
          application/x-script   bkb decw$book
          #/cgi-bin/hypershelf
          #! Bookreader book
*/ 

ConfigAddMimeTypesFile
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemParameter [] = "Parameter confusing";

   int  status;
   char  *cptr, *sptr, *zptr;
   CONFIG_STRUCT  *cfptr;
   ODS_STRUCT  MimeTypesFileOds;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigAddMimeTypesFile() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   zptr = (sptr = cfptr->cfContent.MimeTypesFileName) +
          sizeof(cfptr->cfContent.MimeTypesFileName);
   for (cptr = pptr; *cptr && sptr < zptr; *sptr++ = *cptr++);
   if (sptr >= zptr)
   {
      MetaConReport (mcptr, METACON_REPORT_ERROR, ConfigStringOverflow);
      return (false);
   }

   /* use SYSPRV to allow access to possibly protected file */
   sys$setprv (1, &SysPrvMask, 0, 0);

   status = OdsLoadTextFile (&MimeTypesFileOds,
                             cfptr->cfContent.MimeTypesFileName);

   sys$setprv (0, &SysPrvMask, 0, 0);

   if (VMSnok (status))
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
      return (true);
   }

   while ((cptr = OdsParseTextFile (&MimeTypesFileOds, '*')))
      ConfigAddMimeType (mcptr, cptr);

   VmFree (MimeTypesFileOds.DataPtr, FI_LI);

   /* ensure the final MIME type and file suffix(es) is configured */
   ConfigAddMimeType (mcptr, NULL);
}

/*****************************************************************************/
/*
Process a single line from a MIME.TYPES file (with WASD extensions).

  "#!/" ... an auto-script/presentation-script (e.g. "#!/cgi-bin/script-name")
  "#![" ... an icon specification (e.g. "#![ALT] /httpd/-/icon.gif")
  "#! " ... a file suffix (file type) description (e.g. "#! plain text")
  "#!%" ... reserved for local viewers (ignored by WASD)
  "#!+A ... FTP transfer mode ASCII
  "#!+B ... FTP transfer mode binary (Image)
  "#!+I ... FTP transfer mode binary (Image)
  "#!!" ... WASD-specific MIME type (should be ignored by non-WASD)

This function expects the WASD-specific information to follow a MIME type and
it's file suffixes.  The detection of another MIME type causes the previous one
and any following WASD-specifics to be configured.
*/ 

ConfigAddMimeType
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemAutoScript [] = "autoscript too large",
                ProblemDescription [] = "description too large",
                ProblemFtpMode [] = "unknown FTP mode",
                ProblemIcon [] = "icon too large",
                ProblemMimeType [] = "MIME type too large";

   static char  FtpMode;

   static char  AutoScript [64],
                CurrentMimeType [128],
                Description [64],
                IconUrl [64];

   char  *cptr, *sptr, *zptr,
         *MimeTypePtr,
         *SuffixPtr;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigAddMimeType() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   /* loop is never actually used, just somthing to break out of */
   if (pptr)
   {
      while (*pptr && ISLWS(*pptr)) pptr++;
      if (!*pptr) return;

      if (*pptr == '#')
      {
         pptr++;

         if (*(unsigned short*)pptr == '!%')
            return;
         else
         if (*(unsigned short*)pptr == '!/')
         {
            /* autoscript */
            pptr++;
            zptr = (sptr = AutoScript) + sizeof(AutoScript)-1;
            while (*pptr && !ISLWS(*pptr) && sptr < zptr) *sptr++ = *pptr++;
            if (sptr >= zptr)
            {
               AutoScript[0] = '\0';
               MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemAutoScript);
            }
            *sptr = '\0';
            return;
         }
         else
         if (*(unsigned short*)pptr == '! ')
         {
            /* descriptive text, begins with space */
            pptr += 2;
            while (*pptr && ISLWS(*pptr)) pptr++;
            zptr = (sptr = Description) + sizeof(Description)-1;
            while (*pptr && sptr < zptr) *sptr++ = *pptr++;
            if (sptr >= zptr)
            {
               Description[0] = '\0';
               MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemDescription);
               return;
            }
            *sptr = '\0';
            return;
         }
         else
         if (*(unsigned short*)pptr == '![')
         {
            /* icon URL */
            pptr++;
            /* must reverse the order of the string for WASD icon processing */
            for (cptr = pptr; *cptr && !ISLWS(*cptr); cptr++);
            while (*cptr && ISLWS(*cptr)) cptr++;
            zptr = (sptr = IconUrl) + sizeof(IconUrl)-1;
            while (*cptr && sptr < zptr) *sptr++ = *cptr++;
            if (sptr < zptr) *sptr++ = ' ';
            while (*pptr && !ISLWS(*pptr) && sptr < zptr) *sptr++ = *pptr++;
            if (sptr >= zptr)
            {
               IconUrl[0] = '\0';
               MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemIcon);
               return;
            }
            *sptr = '\0';
            return;
         }
         else
         if (*(unsigned short*)pptr == '!+')
         {
            /* FTP transfer mode */
            pptr += 2;
            if (*pptr == 'A' || *pptr == 'B' || *pptr == 'I')
               FtpMode = *pptr++;
            else
            {
               MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemFtpMode);
               return;
            }
            return;
         }
         else
         if (*(unsigned short*)pptr == '!!')
         {
            /* WASD-specific MIME type */
            pptr += 2;
            /* to continue processing MIME type */
         }
         else
         {
            /* nothing WASD is interested in */
            return;
         }
      }
   }

   /*************/                       
   /* MIME type */
   /*************/

   if (CurrentMimeType[0])
   {
      /* new MIME type and file suffixes, configure the current one */
      for (cptr = CurrentMimeType; *cptr && !ISLWS(*cptr); cptr++);
      if (*cptr) *cptr++ = '\0';

      while (*cptr && ISLWS(*cptr)) cptr++;
      while (*cptr)
      {
         SuffixPtr = cptr;
         while (*cptr && !ISLWS(*cptr)) cptr++;
         if (*cptr) *cptr++ = '\0';
         while (*cptr && ISLWS(*cptr)) cptr++;
         ConfigAddTypeNow (mcptr, CurrentMimeType, SuffixPtr, AutoScript,
                           Description, FtpMode, true);
      }

      if (IconUrl[0])
      {
         /*******************/
         /* associated icon */
         /*******************/

         ConfigAddIcon (mcptr, IconUrl, CurrentMimeType, true);
      }
   }

   AutoScript[0] = Description[0] = IconUrl[0] = CurrentMimeType[0] = '\0';
   FtpMode = 0;

   if (pptr)
   {
      /* buffer this MIME type and file suffixes */
      zptr = (sptr = CurrentMimeType) + sizeof(CurrentMimeType)-1;
      while (*pptr && sptr < zptr) *sptr++ = *pptr++;
      if (sptr >= zptr)
      {
         CurrentMimeType[0] = '\0';
         MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemMimeType);
         return;
      }
      *sptr = '\0';
   }
}

/*****************************************************************************/
/*
Add the following content-type to the list and hash table.  Later definitions
of the same file suffix supercedes earlier ones.
*/ 

ConfigAddTypeNow
(
META_CONFIG *mcptr,
char *MimeType,
char *FileSuffix,
char *AutoScript,
char *Description,
char FtpMode,
BOOL FromMimeTypes
)
{
   BOOL  ContainsWildcard;
   int  Count;
   unsigned long  HashValue;
   char  *cptr, *sptr;
   char  HtmlDescription [256];
   CONTENT_TYPE  *ctptr, *hctptr;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigAddTypeNow() !&Z !&Z !&Z !&Z !UL",
                 MimeType, FileSuffix, AutoScript, Description, FtpMode);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   /* escape any HTML-forbidden characters */
   WriteFao (HtmlDescription, sizeof(HtmlDescription), NULL,
             "!&;AZ", Description);

   Count = strlen (MimeType);
   Count += strlen (FileSuffix);
   Count += strlen (AutoScript);
   Count += strlen (HtmlDescription);

   /* plus structure overhead, plus 4 x null terminators, plus possible '.' */
   Count += cfptr->cfContent.ContentTypeStructOverhead + 5;
   ctptr = (CONTENT_TYPE*)VmGet (Count);

   sptr = (char*)ctptr + cfptr->cfContent.ContentTypeStructOverhead;

   ctptr->FromMimeTypes = FromMimeTypes;

   ContainsWildcard = false;
   ctptr->SuffixPtr = sptr;
   cptr = FileSuffix;
   if (*cptr != '.' && *(unsigned short*)cptr != '*\0') *sptr++ = '.';
   while (*cptr)
   {
      if (*cptr == '*') ContainsWildcard = true;
      /* ensure suffix is in upper-case so we don't have to do it matching */
      *sptr++ = toupper(*cptr++);
   }
   *sptr++ = '\0';

   ctptr->ContentTypePtr = sptr;
   cptr = MimeType;
   while (*cptr) *sptr++ = *cptr++;
   *sptr++ = '\0';
   if (strsame (MimeType, "text/", 5)) ctptr->TypeText = true;

   ctptr->AutoScriptNamePtr = sptr;
   cptr = AutoScript;
   while (*cptr) *sptr++ = *cptr++;
   *sptr++ = '\0';

   ctptr->DescriptionPtr = sptr;
   cptr = HtmlDescription;
   while (*cptr) *sptr++ = *cptr++;
   *sptr = '\0';

   /* check if there is a previous entry of this suffix */
   for (hctptr = cfptr->cfContent.ContentInfoListHeadPtr;
        hctptr;
        hctptr = hctptr->NextPtr)
   {
      /* if a later type definition was loaded then ignore this one */
      if (strsame (hctptr->SuffixPtr, ctptr->SuffixPtr, -1))
         hctptr->Superceded = true;
   }

   /* add to list */
   if (!cfptr->cfContent.ContentInfoListHeadPtr)
      cfptr->cfContent.ContentInfoListHeadPtr = ctptr; 
   else
      cfptr->cfContent.ContentInfoListTailPtr->NextPtr = ctptr; 
   cfptr->cfContent.ContentInfoListTailPtr = ctptr;
   ctptr->NextPtr = NULL;

   if (ContainsWildcard)
   {
      /* all wildcarded types are listed from hash value 0 */
      HashValue = 0;
   }
   else
   {
      /* generates an upper-case hash */
      HashValue = 1;
      for (cptr = ctptr->SuffixPtr; *cptr && *cptr != ';'; cptr++)
         HashValue = (((*cptr)*541)^(HashValue*3)) &
                     CONTENT_TYPE_HASH_TABLE_MASK;
   }
   if (Debug)
      fprintf (stdout, "HashValue: %d %d\n",
               HashValue, cfptr->cfContent.ContentInfoHashTable[HashValue]);
   if (cfptr->cfContent.ContentInfoHashTable[HashValue])
   {
      /* add to the hash-collision list */
      for (hctptr = cfptr->cfContent.ContentInfoHashTable[HashValue];
           hctptr->HashCollisionPtr;
           hctptr = hctptr->HashCollisionPtr);
      hctptr->HashCollisionPtr = ctptr;
   }
   else
      cfptr->cfContent.ContentInfoHashTable[HashValue] = ctptr;

   /* special case, default content-type for unknown suffixes */
   if (*(unsigned short*)ctptr->SuffixPtr == '*\0')
   {
      cfptr->cfContent.ContentTypeDefaultPtr =
         VmGet (strlen(HtmlDescription+1));
      strcpy (cfptr->cfContent.ContentTypeDefaultPtr, HtmlDescription);
      ctptr->TypeUnknown = true;
      /* cancel type description */
      *ctptr->DescriptionPtr = '\0';
   }
   else
      ctptr->TypeUnknown = false;

   ctptr->FtpMode = FtpMode;

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchDataFormatted ("!&Z !&Z !&Z !&Z !&B !&B !UL\n",
               ctptr->SuffixPtr, ctptr->ContentTypePtr,
               ctptr->AutoScriptNamePtr, ctptr->DescriptionPtr, 
               ctptr->TypeText, ctptr->TypeUnknown, ctptr->FtpMode);
}

/*****************************************************************************/
/*
After loading all content-types (i.e. after configuration) this function sets
the corresponding icon for each type.
*/ 

ConfigContentTypeIcon (META_CONFIG *mcptr)

{
   CONTENT_TYPE  *ctptr;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG, "ConfigContentTypeIcon()");

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   /* do the default icon first (needless-to-say) */
   ConfigDefaultIconPtr = ConfigIconFor (ConfigContentTypeDefaultIcon, 0, 0);
   ConfigBlankIconPtr = ConfigIconFor (ConfigContentTypeBlank, 0, 0);
   ConfigDirIconPtr = ConfigIconFor (ConfigContentTypeDir, 0, 0);
   ConfigParentIconPtr = ConfigIconFor (ConfigContentTypeParent, 0, 0);
   ConfigUnknownIconPtr = ConfigIconFor (ConfigContentTypeUnknown, 0, 0);

   for (ctptr = cfptr->cfContent.ContentInfoListHeadPtr;
        ctptr;
        ctptr = ctptr->NextPtr)
   {
      /** if (Debug) fprintf (stdout, "ctptr: %d\n", ctptr); **/
      if (ctptr->TypeUnknown)
         ctptr->IconPtr = ConfigIconFor (ConfigContentTypeUnknown, 0, 0);
      else
         ctptr->IconPtr = ConfigIconFor (ctptr->ContentTypePtr, 0, 0);
   }
}

/*****************************************************************************/
/*
Using the hash table this function searches the list of file suffixes (types,
extensions) and content-types, returning a pointer to the content-type string
and if supplied with a content-type structure fills out the appropriate
fields.  Wildcarded file types are always stored in the list beginning with
hash table zero (i.e. [0]).
*/ 

char* ConfigContentType
(
CONTENT_TYPE *ciptr,
char *SuffixPtr
)
{
   BOOL  CheckedForWildcards;
   char  *cptr, *sptr;
   unsigned long  HashValue;
   CONTENT_TYPE  *ctptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigContentType() !&Z", SuffixPtr);

   /* generate an upper-case hash */
   if (*SuffixPtr != '.') SuffixPtr = ".";
   HashValue = 1;
   for (cptr = SuffixPtr; *cptr && *cptr != ';'; cptr++)
      HashValue = ((toupper(*cptr)*541)^(HashValue*3)) &
                  CONTENT_TYPE_HASH_TABLE_MASK;
   if (Debug)
      fprintf (stdout, "HashValue: %d %d\n",
               HashValue, Config.cfContent.ContentInfoHashTable[HashValue]);

   CheckedForWildcards = false;

   if (!(ctptr = Config.cfContent.ContentInfoHashTable[HashValue]))
      ctptr = Config.cfContent.ContentInfoHashTable[0];
   while (ctptr)
   {
      /** if (Debug) fprintf (stdout, "ctptr: %d\n", ctptr); **/

      /* if a later type definition was loaded then ignore this one */
      if (ctptr->Superceded)
      {
         if ((ctptr = ctptr->HashCollisionPtr)) continue;
         /* end of collision list, check for wildcarded file types */
         if (!CheckedForWildcards)
         {
            CheckedForWildcards = true;
            ctptr = Config.cfContent.ContentInfoHashTable[0];
         }
         continue;
      }

      /* 'ctptr->SuffixPtr' has already been converted to upper case! */
      cptr = ctptr->SuffixPtr;
      if (Debug) fprintf (stdout, "|%s|\n", cptr);
      sptr = SuffixPtr;
      while (*cptr && *sptr && *sptr != ';' && *cptr == toupper(*sptr))
      {
         if (*cptr != '*')
         {
            /* not a wildcard */
            cptr++;
            sptr++;
            if (*cptr != '*') continue;
         }
         /* consecutive wildcards are the same as a single wildcard */
         while (*cptr && *cptr == '*') cptr++;
         if (*cptr)
         {
            /* find first matching the character following the wildcard */
            while (*sptr && *sptr != ';' && toupper(*sptr) != *cptr) sptr++;
            continue;
         }
         /* wildcard at end of list file type, matches all following */
         while (*sptr && *sptr != ';') sptr++;
      }

      if (*cptr || (*sptr && *sptr != ';'))
      {
         /* didn't match, traversing the hash-collision list */
         if ((ctptr = ctptr->HashCollisionPtr)) continue;
         /* end of collision list, check for wildcarded file types */
         if (!CheckedForWildcards)
         {
            CheckedForWildcards = true;
            ctptr = Config.cfContent.ContentInfoHashTable[0];
         }
         continue;
      }

      /**********/
      /* match! */
      /**********/

      /* if just getting a pointer to a content type then just return that */
      if (!ciptr) return (ctptr->ContentTypePtr);

      ciptr->TypeUnknown = false;
      ciptr->TypeText = ctptr->TypeText;
      ciptr->IconPtr = ctptr->IconPtr;
      ciptr->ContentTypePtr = ctptr->ContentTypePtr;
      ciptr->AutoScriptNamePtr = ctptr->AutoScriptNamePtr;
      ciptr->DescriptionPtr = ctptr->DescriptionPtr;
      ciptr->FtpMode = ctptr->FtpMode;

      if (WATCH_MODULE(WATCH_MOD_CONFIG))
         WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG, "!UL !&Z !&Z !&Z",
                    ciptr->FtpMode, ciptr->ContentTypePtr,
                    ciptr->AutoScriptNamePtr, ciptr->DescriptionPtr);

      return (ctptr->ContentTypePtr);
   }

   /*************/
   /* no match! */
   /*************/

   /* if just getting a pointer to a content type then just return that */
   if (!ciptr) return (ConfigContentTypeUnknown);

   ciptr->TypeUnknown = true;
   ciptr->TypeText = false;
   ciptr->IconPtr = ConfigUnknownIconPtr;
   ciptr->ContentTypePtr = ConfigContentTypeUnknown;
   ciptr->AutoScriptNamePtr = ciptr->DescriptionPtr = "";
   return (ConfigContentTypeUnknown);
}

/****************************************************************************/
/*
Compare two MIME content-types where only the type is compared (i.e. only the
"text/html" from something like "text/html;charset=ISO8859-5").  It works much
the same as strsame(), except a semi-colon or white-space in either string will
terminate a comparison, as will an exhausted count value.
*/ 
 
BOOL ConfigSameContentType
(
char *sptr1,
char *sptr2,
int count
)
{
   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigSameContentType() !&Z !&Z !SL",
                 sptr1, sptr2, count);

   if (!sptr1 || !sptr2) return (false);

   while (*sptr1 && *sptr1 != ';' && !ISLWS(*sptr1) &&
          *sptr2 && *sptr2 != ';' && !ISLWS(*sptr2))
   {
      if (toupper (*sptr1++) != toupper (*sptr2++)) return (false);
      if (count)
         if (!--count) return (true);
   }
   if ((!*sptr1 && (!*sptr2 || *sptr2 == ';')) ||
       (!*sptr2 && (!*sptr1 || *sptr1 == ';')))
      return (true);
   else
      return (false);
}
 
/*****************************************************************************/
/*
Add a URL for an icon corresponding to the mime content type.

Format:   "AddIcon <URL> <alternative-text> <content-type-template>"

Examples: "AddIcon /icon/httpd/text.xbm [TXT] text/plain"
          "AddIcon /icon/httpd/doc.xbm [HTM] text/html"
          "AddIcon /icon/httpd/image.xbm [IMG] image/jpeg"

The template can contain a wildcard in place of a string in either side of the 
template slash.  In this case the wildcard matches any string on that side.

The directive is stored as a linked-list of structures of dynamically
allocated memory containing a reformatted version of the directive string,
including a complete HTML anchor for the URL. Function ConfigIconFor()
searches this list to return a pointer to the anchor. A hash table is used to
more rapidy index into the list.
*/ 

ConfigAddIcon
(
META_CONFIG *mcptr,
char *pptr,
char *TypePtr,
BOOL FromMimeTypes
)
{
   static char  ProblemParameter [] = "Parameter confusing";

   int  Count = 0;
   unsigned long  HashValue;
   char  *cptr, *sptr,
         *AltTextPtr,
         *IconUrlPtr,
         *ContentTypePtr;
   CONFIG_STRUCT  *cfptr;
   ICON_TYPE  *itptr, *hitptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigAddIcon() !&Z !&Z !UL", pptr, TypePtr, FromMimeTypes);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   IconUrlPtr = pptr;
   while (*pptr && ISLWS(*pptr)) pptr++;
   if (!*pptr) return;
   while (*pptr && !ISLWS(*pptr)) pptr++;
   /* storing the icon URI twice, as the URI plus within the <IMG..> */
   Count = (pptr - IconUrlPtr) * 2;
   if (*pptr) *pptr++ = '\0';

   /* alternative text */
   while (*pptr && ISLWS(*pptr)) pptr++;
   AltTextPtr = pptr;
   while (*pptr && !ISLWS(*pptr))
   {
      /* underscores represent spaces! (especially for the "blank" icon) */
      if (*pptr == '_') *pptr = ' ';
      pptr++;
   }
   /* storing the alternate text twice, as it is plus within the <IMG..> */
   Count += (pptr - AltTextPtr) * 2;
   if (*pptr) *pptr++ = '\0';

   /* content-type  */
   if (TypePtr) pptr = TypePtr;
   while (*pptr && ISLWS(*pptr)) pptr++;
   ContentTypePtr = pptr;
   /* force to lower case to save a tolower() in ConfigIconFor() */
   for ( /* above */ ; *pptr && !ISLWS(*pptr); pptr++)
      *pptr = tolower(*pptr);
   Count += pptr - ContentTypePtr;
   if (*pptr) *pptr = '\0';

   if (!*IconUrlPtr && *IconUrlPtr != '/' ||
       !*AltTextPtr ||
       !*ContentTypePtr || !strchr(ContentTypePtr, '/'))
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
      return;
   }

   /* plus structure overhead, plus the HTML IMG element used below */
   Count += cfptr->cfContent.IconStructOverhead + 32;
   itptr = (ICON_TYPE*)VmGet (Count);                  

   itptr->FromMimeTypes = FromMimeTypes;

   sptr = (char*)itptr + cfptr->cfContent.IconStructOverhead;

   itptr->ContentTypePtr = sptr;
   for (cptr = ContentTypePtr; *cptr; *sptr++ = *cptr++);
   *sptr++ = '\0';

   itptr->IconUriPtr = sptr;
   for (cptr = IconUrlPtr; *cptr; *sptr++ = *cptr++);
   *sptr++ = '\0';

   itptr->AltTextPtr = sptr;
   for (cptr = AltTextPtr; *cptr; *sptr++ = *cptr++);
   *sptr++ = '\0';

   itptr->IconUrlPtr = sptr;
   sprintf (sptr, "<IMG ALIGN=top BORDER=0 SRC=\"%s\" ALT=\"%s\">",
            IconUrlPtr, AltTextPtr);

   for (hitptr = Config.cfContent.IconListHeadPtr;
        hitptr;
        hitptr = hitptr->NextPtr)
   {
      if (strsame (hitptr->ContentTypePtr, ContentTypePtr, -1))
      {
         hitptr->Superceded = true;
         break;
      }
   }

   /* add to list */
   if (!cfptr->cfContent.IconListHeadPtr)
      cfptr->cfContent.IconListHeadPtr = itptr; 
   else
      cfptr->cfContent.IconListTailPtr->NextPtr = itptr; 
   cfptr->cfContent.IconListTailPtr = itptr;
   itptr->NextPtr = NULL;

   /* generates a lower-case hash */
   HashValue = 1;
   for (cptr = ContentTypePtr; *cptr; cptr++)
      HashValue = (((*cptr)*541)^(HashValue*3)) &
                  ICON_HASH_TABLE_MASK;
   if (Debug)
      fprintf (stdout, "HashValue: %d %d\n",
               HashValue, cfptr->cfContent.ContentInfoHashTable [HashValue]);
   if (cfptr->cfContent.IconHashTable[HashValue])
   {
      /* add to the hash-collision list */
      for (hitptr = cfptr->cfContent.IconHashTable[HashValue];
           hitptr->HashCollisionPtr;
           hitptr = hitptr->HashCollisionPtr);
      hitptr->HashCollisionPtr = itptr;
   }
   else
      cfptr->cfContent.IconHashTable[HashValue] = itptr;
}

/*****************************************************************************/
/*
Using the hash table this function searches the icons for one corresponding to
the supplied mime content type. The directive content type and associated HTML
anchor (containing the original configuration-supplied URL) is stored as an
list of structures dynamically allocated memory containing a string.
*/

char* ConfigIconFor
(
char *ContentType,
char **IconUriPtrPtr,
char **AltTextPtrPtr
)
{
   static BOOL  DefaultIconFlipFlop;
   static char  IconNotFound [] = "<FONT COLOR=\"#ff0000\"><B>[?]</B></FONT>";

   char  ch;
   char  *cptr, *sptr,
         *AltTextPtr, *IconUriPtr;
   unsigned long  HashValue;
   ICON_TYPE  *itptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigIconFor() !&Z !&X !&X",
                 ContentType, IconUriPtrPtr, AltTextPtrPtr);

   /* generates a lower-case hash */
   HashValue = 1;
   for (cptr = ContentType; *cptr && *cptr != ';' && !ISLWS(*cptr); cptr++)
      HashValue = ((tolower(*cptr)*541)^(HashValue*3)) & ICON_HASH_TABLE_MASK;
   ch = *cptr;
   *cptr = '\0';

   for (itptr = Config.cfContent.IconHashTable[HashValue];
        itptr;
        itptr = itptr->HashCollisionPtr)
   {
      if (itptr->Superceded) continue;
      /* only need to match the content types if there was a collision */
      if (itptr->HashCollisionPtr)
         if (!StringMatch (NULL, ContentType, itptr->ContentTypePtr))
            continue;
      if (IconUriPtrPtr) *IconUriPtrPtr = itptr->IconUriPtr;
      if (AltTextPtrPtr) *AltTextPtrPtr = itptr->AltTextPtr;
      *cptr = ch;
      return (itptr->IconUrlPtr);
   }
   *cptr = ch;

   if (ConfigDefaultIconPtr && (IconUriPtrPtr || AltTextPtrPtr))
   {
      if (DefaultIconFlipFlop = !DefaultIconFlipFlop)
      {
         ConfigIconFor (ConfigContentTypeDefaultIcon, &IconUriPtr, &AltTextPtr);
         if (IconUriPtrPtr) *IconUriPtrPtr = IconUriPtr;
         if (AltTextPtrPtr) *AltTextPtrPtr = AltTextPtr;
         return (ConfigDefaultIconPtr);
      }
      if (IconUriPtrPtr) *IconUriPtrPtr = "";
      if (AltTextPtrPtr) *AltTextPtrPtr = "";
   }
   if (ConfigDefaultIconPtr) return (ConfigDefaultIconPtr);
   return (IconNotFound);
}

/*****************************************************************************/
/*
Accept or reject the client connection.  Lists of hosts must be a comma-
separated string.  A wildcard '*' in a domain specification matches any string 
that occurs between the dots.
Example: "host1.network1.domain1,*.network2.domain1,*.*.domain2". 
*/ 

BOOL ConfigAcceptClientHostName
(
char *ClientIpAddressString,
char *ClientHostName
)
{
   char  *cptr, *sptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigAcceptConnection() !&Z", ClientHostName);

   if (!Config.cfServer.AcceptHostsPtr &&
       !Config.cfServer.RejectHostsPtr)
      return (true);

   if (!ClientHostName[0] || ClientHostName[0] == '?') return (false);

   /******************/
   /* hosts accepted */
   /******************/

   if (Config.cfServer.AcceptHostsPtr)
   {
      sptr = Config.cfServer.AcceptHostsPtr;
      while (*sptr)
      {
         /** if (Debug) fprintf (stdout, "sptr |%s|\n", sptr); **/
         if (isdigit(*sptr))
            cptr = ClientIpAddressString;
         else
            cptr = ClientHostName;
         while (*cptr)
         {
            if (*sptr == STRING_LIST_CHAR) break;
            if (*sptr == '*')
            {
               while (*sptr && *sptr == '*' && *sptr != STRING_LIST_CHAR)
                  sptr++;
               while (*cptr && *cptr != *sptr) cptr++;
            }
            if (tolower(*cptr) != tolower(*sptr)) break;
            if (*cptr) cptr++;
            if (*sptr) sptr++;
         }
         if (!*cptr && (!*sptr || *sptr == STRING_LIST_CHAR)) break;
         while (*sptr && *sptr != STRING_LIST_CHAR) sptr++;
         if (*sptr) sptr++;
      }
      /* if it was NOT found then reject the connection request */
      if (!(!*cptr && (!*sptr || *sptr == STRING_LIST_CHAR)))
         return (false);
   }

   /******************/
   /* hosts rejected */
   /******************/

   if (Config.cfServer.RejectHostsPtr)
   {
      sptr = Config.cfServer.RejectHostsPtr;
      while (*sptr)
      {
         /** if (Debug) fprintf (stdout, "sptr |%s|\n", sptr); **/
         cptr = ClientHostName;
         while (*cptr)
         {
            if (*sptr == STRING_LIST_CHAR) break;
            if (*sptr == '*')
            {
               while (*sptr && *sptr == '*' && *sptr != STRING_LIST_CHAR)
                  sptr++;
               while (*cptr && *cptr != *sptr) cptr++;
            }
            if (tolower(*cptr) != tolower(*sptr)) break;
            if (*cptr) cptr++;
            if (*sptr) sptr++;
         }
         if (!*cptr && (!*sptr || *sptr == STRING_LIST_CHAR)) break;
         while (*sptr && *sptr != STRING_LIST_CHAR) sptr++;
         if (*sptr) sptr++;
      }
      /* if it WAS found then reject the connection request */
      if (!*cptr && (!*sptr || *sptr == STRING_LIST_CHAR))
         return (false);
   }

   /* accept the connection */
   return (true);
}

/*****************************************************************************/
/*
Set directory access booleans.  Allowed values OFF, ON, SELECTIVE.
*/

ConfigSetDirAccess
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemParameter [] = "Parameter confusing";

   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigSetDirAccess() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   if (strsame (pptr, "YES", 3) ||
       strsame (pptr, "ON", 2) ||
       strsame (pptr, "ENABLED", 7))
   {
      cfptr->cfDir.Access = true;
      cfptr->cfDir.AccessSelective = false;
   }
   else
   if (strsame (pptr, "NO", 2) ||
       strsame (pptr, "OFF", 3) ||
       strsame (pptr, "DISABLED", 8))
      cfptr->cfDir.Access = cfptr->cfDir.AccessSelective = false;
   else
   if (strsame (pptr, "SELECTIVE", 9))
      cfptr->cfDir.Access = cfptr->cfDir.AccessSelective = true;
   else
      MetaConReport (mcptr, METACON_REPORT_ERROR, ProblemParameter);
}

/*****************************************************************************/
/*
Set directory README file booleans.  Allowed values OFF, TOP, BOTTOM.
*/

ConfigSetDirReadMe
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemParameter [] = "Parameter confusing";

   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigSetDirReadMe() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   if (strsame (pptr, "NO", 2) ||
       strsame (pptr, "OFF", 3) ||
       strsame (pptr, "DISABLED", 8))
      cfptr->cfDir.ReadMeBottom = cfptr->cfDir.ReadMeTop = false;
   else
   if (strsame (pptr, "BOTTOM", 6))
   {
      cfptr->cfDir.ReadMeTop = false;
      cfptr->cfDir.ReadMeBottom = true;
   }
   else
   if (strsame (pptr, "TOP", 3))
   {
      cfptr->cfDir.ReadMeTop = true;
      cfptr->cfDir.ReadMeBottom = false;
   }
   else
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
}

/*****************************************************************************/
/*
Add a "read-me" file name.

Format:   "ReadMeFile file.suffix"

Examples: "ReadMeFile README.HTML"
          "ReadMeFile README.TXT"
          "ReadMeFile README."

The directive is stored as an array of pointers to dynamically allocated 
memory containing the "read-me" file name.  Function ConfigReadMeFile() gets 
these by index number.
*/

ConfigSetDirReadMeFile
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemParameter [] = "Parameter confusing",
                ProblemReadMeMax [] = "Maximum read-me exceeded";

   int  status,
        Count;
   char  *NamePtr;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigSetDirReadMeFile() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   if (cfptr->cfDir.ReadMeFileCount >= CONFIG_README_FILES_MAX)
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemReadMeMax);
      return;
   }

   NamePtr = pptr;
   while (*pptr && !ISLWS(*pptr))
   {
      *pptr = toupper(*pptr);
      pptr++;
   }
   Count = pptr - NamePtr;
   *pptr = '\0';

   if (!*NamePtr)
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
      return;
   }

   if (Debug) fprintf (stdout, "VmGet()ing %d bytes\n", Count+1);
   cfptr->cfDir.ReadMeFileArray[cfptr->cfDir.ReadMeFileCount] = VmGet(Count+1);

   strcpy (cfptr->cfDir.ReadMeFileArray[cfptr->cfDir.ReadMeFileCount], NamePtr);
   if (Debug)
      fprintf (stdout, "|%s|\n",
               cfptr->cfDir.ReadMeFileArray[cfptr->cfDir.ReadMeFileCount]);
   cfptr->cfDir.ReadMeFileCount++;
}

/*****************************************************************************/
/*
Return a pointer to the "read-me" file name stored against the index number of 
the array.  If none exists return a null string.  The calling function would 
use this by stepping through the index numbers 0 to n, until the null string 
was returned indicating the possible "read-me" file names were exhausted.
*/

char* ConfigReadMeFile (int Number)

{
   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigReadMeFile !UL", Number);

   if (Number >= 0 && Number < Config.cfDir.ReadMeFileCount)
      return (Config.cfDir.ReadMeFileArray[Number]);
   else
      return ("");
}

/*****************************************************************************/
/*
Set OPCOM target and message categories.
*/

ConfigSetOpcom
(
META_CONFIG *mcptr,
char *cptr,
char *sptr
)
{
   static char  ProblemParameter [] = "Parameter confusing";

   int  idx;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigSetOpcom() !&Z !&Z", cptr, sptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   if (strsame (cptr, "OpcomTarget", -1))
   {
      for (idx = 0; ConfigOpcomTarget[idx].Number >= 0; idx++)
         if (strsame (ConfigOpcomTarget[idx].Name, sptr, -1)) break;
      if (ConfigOpcomTarget[idx].Number >= 0)
      {
         cfptr->cfOpcom.Target =
            ConfigOpcomTarget[cfptr->cfOpcom.Index = idx].Number;
         return;
      }
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
      return;
   }

   if (strsame (cptr, "OpcomAdmin", -1))
   {
      if (MetaConSetBoolean (mcptr, sptr))
         cfptr->cfOpcom.Messages |= OPCOM_ADMIN;
   }
   else
   if (strsame (cptr, "OpcomAuthorization", -1))
   {
      if (MetaConSetBoolean (mcptr, sptr))
         cfptr->cfOpcom.Messages |= OPCOM_AUTHORIZATION;
   }
   else
   if (strsame (cptr, "OpcomControl", -1))
   {
      if (MetaConSetBoolean (mcptr, sptr))
         cfptr->cfOpcom.Messages |= OPCOM_CONTROL;
   }
   else
   if (strsame (cptr, "OpcomHTTPd", -1))
   {
      if (MetaConSetBoolean (mcptr, sptr))
         cfptr->cfOpcom.Messages |= OPCOM_HTTPD;
   }
   else
   if (strsame (cptr, "OpcomProxyMaint", -1))
   {
      if (MetaConSetBoolean (mcptr, sptr))
         cfptr->cfOpcom.Messages |= OPCOM_PROXY_MAINT;
   }
   else
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
}

/*****************************************************************************/
/*
Add a script type.

Format:   "file-type verb"

Examples: ".PL PERL"
          ".PL $PERL_EXE:PERL.EXE"
          ".CGI $HT_EXE:CGIPERLUS.EXE"

The directive is stored as an array of pointers to dynamically allocated 
memory containing definition.  Function DclFindScript() uses this information.
The array entries comprise a reconstructed string from the directive.  The
verb part of the directive can have a leading '@' or '$' indicating that the
verb should be create before invoking the script.  If not having these leading
characters the verb is considered to be globally available.  The leading '@'
and '$' verbs are reconstructed from "$perl_exe:perl.exe" into
"PERL=\"$perl_exe:perl.exe\"".  From this the DCL module creates an
excecutable DCL command sequence.
*/ 

ConfigSetScriptRunTime
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemParameter [] = "Parameter confusing",
                ProblemRunTimeMax [] = "Maximum runtime exceeded",
                ProblemRunTimeTooLong [] = "Runtime too long";

   int  status,
        Count,
        RunTimeCount;
   char  *cptr, *sptr, *zptr;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigSetScriptRunTime() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   if ((RunTimeCount = cfptr->cfScript.RunTimeCount) >=
       CONFIG_SCRIPT_RUNTIME_MAX)
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemRunTimeMax);
      return;
   }

   zptr = (sptr = cfptr->cfScript.RunTime[RunTimeCount].String) +
          sizeof(cfptr->cfScript.RunTime[RunTimeCount].String)-1;
   if (*pptr != '.' && sptr < zptr) *sptr++ = '.';
   while (*pptr && !ISLWS(*pptr) && *pptr != ';' && sptr < zptr)
      *sptr++ = toupper(*pptr++);
   if (sptr < zptr) *sptr++ = ';';
   cfptr->cfScript.RunTime[RunTimeCount].FileTypeLength =
      sptr - cfptr->cfScript.RunTime[RunTimeCount].String;
   while (*pptr && (ISLWS(*pptr) || *pptr == ';')) pptr++;
   if (!*pptr)
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
      return;
   }
   if (sptr < zptr) *sptr++ = ' ';
   while (*pptr && sptr < zptr) *sptr++ = *pptr++;
   if (sptr >= zptr)
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemRunTimeTooLong);
      return;
   }
   *sptr = '\0';

   if (Debug)
      fprintf (stdout, "%d |%s|\n",
               cfptr->cfScript.RunTime[RunTimeCount].FileTypeLength,
               cfptr->cfScript.RunTime[RunTimeCount].String);

   cfptr->cfScript.RunTimeCount++;
}

/*****************************************************************************/
/*
Set directory access booleans.  Allowed values OFF, ON, EMAIL.
*/

ConfigSetServerSignature
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemParameter [] = "Parameter confusing";

   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigSetServerSignature() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   if (strsame (pptr, "YES", 3) ||
       strsame (pptr, "ON", 2) ||
       strsame (pptr, "ENABLED", 7))
      cfptr->cfServer.Signature = CONFIG_SERVER_SIGNATURE_ON;
   else
   if (strsame (pptr, "NO", 2) ||
       strsame (pptr, "OFF", 3) ||
       strsame (pptr, "DISABLED", 8))
      cfptr->cfServer.Signature = CONFIG_SERVER_SIGNATURE_OFF;
   else
   if (strsame (pptr, "EMAIL", 5))
      cfptr->cfServer.Signature = CONFIG_SERVER_SIGNATURE_EMAIL;
   else
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemParameter);
}

/*****************************************************************************/
/*
Add a welcome (home) page file name.

Format:   "Welcome file.suffix"

Examples: "Welcome HOME.HTML"
          "Welcome HOME.HTM"
          "Welcome HOME.MENU"

The directive is stored as an array of pointers to dynamically allocated 
memory containing the home page file name.  Function ConfigHomePage() gets 
these by index number.
*/ 

ConfigSetWelcome
(
META_CONFIG *mcptr,
char *pptr
)
{
   static char  ProblemWelcomeMax [] = "Maximum welcome exceeded";

   int  status,
        Count;
   char  *WelcomePtr;
   CONFIG_STRUCT  *cfptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigSetWelcome() !&Z", pptr);

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   if (cfptr->cfContent.HomePageCount >= CONFIG_HOME_PAGES_MAX)
   {
      MetaConReport (mcptr, METACON_REPORT_WARNING, ProblemWelcomeMax);
      return;
   }

   WelcomePtr = pptr;
   while (*pptr && !ISLWS(*pptr))
   {
      *pptr = toupper(*pptr);
      pptr++;
   }
   Count = pptr - WelcomePtr;
   *pptr = '\0';

   cfptr->cfContent.HomePageArray[cfptr->cfContent.HomePageCount] =
      VmGet (Count+1);

   strcpy (cfptr->cfContent.HomePageArray[cfptr->cfContent.HomePageCount],
           WelcomePtr);
   if (Debug)
      fprintf (stdout, "|%s|\n",
               cfptr->cfContent.HomePageArray[cfptr->cfContent.HomePageCount]);
   cfptr->cfContent.HomePageCount++;
}

/*****************************************************************************/
/*
Return a pointer to the home page (welcome) file name stored against the index 
number of the array.  If none exists return a null string.  The calling 
function would use this by stepping through the index numbers 0 to n, until 
the null string was returned indicating the possible home page file names were 
exhausted.
*/

char* ConfigHomePage (int Number)

{
   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (NULL, FI_LI, WATCH_MOD_CONFIG, "ConfigHomePage !UL", Number);

   if (Number >= 0 && Number < Config.cfContent.HomePageCount)
      return (Config.cfContent.HomePageArray[Number]);
   else
      return ("");
}

/*****************************************************************************/
/*
A server administration report on the server's configuration. This function
just wraps the reporting function, loading a temporary database if necessary
for reporting from the configuration file.
*/ 

ConfigReport
(
REQUEST_STRUCT *rqptr,
REQUEST_AST NextTaskFunction,
BOOL UseServerDatabase
)
{
   int  status;
   META_CONFIG  *mcptr;

   /*********/
   /* begin */
   /*********/

   if (WATCHING(rqptr) && WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (rqptr, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigReport() !&F !&A !UL",
                 &ConfigReport, NextTaskFunction, UseServerDatabase);

   if (UseServerDatabase)
      ConfigReportNow (rqptr, MetaGlobalConfigPtr);
   else
   {
      status = ConfigLoad (&mcptr);
      if (VMSnok (status))
      {
         /* severe error reported */
         rqptr->rqResponse.HttpStatus = 403;
         ErrorGeneral (rqptr, mcptr->LoadReport.TextPtr, FI_LI);
      }
      else
         ConfigReportNow (rqptr, mcptr);
      MetaConUnload (&mcptr, NULL);
   }

   SysDclAst (NextTaskFunction, rqptr);
}

/*****************************************************************************/
/*
Return a report on the HTTPd server's configuration ... now!  This function
blocks while executing.
*/ 

ConfigReportNow
(
REQUEST_STRUCT *rqptr,
META_CONFIG *mcptr
)
{
/* macro to push booleans onto the parameter list */
#define REP_ENDIS(b) \
if (b) *vecptr++ = "[enabled]"; else *vecptr++ = "[disabled]";

/* report a string, or if empty as "(none)" */
#define REP_NOTNONE(s) \
if (s[0]) *vecptr++ = s; else *vecptr++ = NotNone;

/* report a number of seconds as HH:MM:SS */
#define REP_HHMMSS(s) \
*vecptr++ = "!2ZL:!2ZL:!2ZL"; \
*vecptr++ = s / 3600; \
*vecptr++ = (s % 3600) / 60; \
*vecptr++ = (s % 3600) % 60;

   static char
      NotNone [] = "<I>(none)</I>\n",
      NoRestriction [] = "<I>(no restriction)</I>\n",
      ServerOnly [] = "<I>(this server only)</I>\n";

   static char ReportGeneralFao [] =
"<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>GMT</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>Offset:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Current:</TH><TD>!AZ</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>General</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>Instance Max:</TH><TD>!&@</TD>\
<TD><I>per-node servers</I></TR>\
<TR><TH ALIGN=right>Busy:</TH><TD>!UL</TD>\
<TD><I>connections</I></TR>\
<TR><TH ALIGN=right>Listen Backlog:</TH><TD>!UL</TD>\
<TD><I>connections</I></TR>\
<TR><TH ALIGN=right>Request History:</TH><TD>!UL</TD>\
<TD><I>requests</I></TD></TR>\n\
<TR><TH ALIGN=right>Activity History:</TH><TD>!UL</TD>\
<TD><I>days</I></TD></TR>\n\
<TR><TH ALIGN=right>Charset Default:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right VALIGN=top>Charset Convert:</TH>\
<TD COLSPAN=2><NOBR>!AZ</NOBR></TD></TR>\
<TR><TH ALIGN=right>Monitor:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Regular Expressions:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>IP Port:</TH><TD>!UL</TD></TR>\n\
<TR><TH ALIGN=right>StreamLF:</TH><TD>!UL</TD>\
<TD><I>kBytes</I></TD></TR>\n\
<TR><TH ALIGN=right>Search Script:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right VALIGN=top>Search Script Exclude:</TH><TD>!AZ</TD>\n\
<TD VALIGN=top><I>file type</I></TD></TR>\n\
<TR><TH ALIGN=right>PUT/POST Max Length:</TH><TD>!UL</TD>\
<TD><I>kBytes</I></TD></TR>\n\
<TR><TH ALIGN=right>PUT/POST Files:</TH><TD>!UL</TD>\
<TD><I>version limit</I></TD></TR>\n\
<TR><TH ALIGN=right><NOBR>/~username/ Cache Entries:</NOBR></TH><TD>!UL</TD>\
<TD><I>user names</I></TD></TR>\n\
<TR><TH ALIGN=right>Persona Cache Entries:</TH><TD>!UL</TD>\
<TD><I>users</I></TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Host Resolution</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>Lookup&nbsp;Client:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Life-Time:</TH><TD COLSPAN=2>!&@</TD></TR>\n\
<TR><TH ALIGN=right>Retry:</TH><TD COLSPAN=2>!UL</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Log</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>Logging:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Format:</TH><TD>!AZ</TD>\
<TR><TH ALIGN=right>Naming:</TH><TD>!AZ</TD>\
<TR><TH ALIGN=right>Period:</TH><TD>!AZ</TD>\
<TR><TH ALIGN=right>Per-Instance:</TH><TD>!AZ</TD>\
<TR><TH ALIGN=right>Per-Service:</TH><TD>!AZ</TD>\
<TR><TH ALIGN=right>Per-Service Host Only:</TH><TD>!AZ</TD>\
<TR><TH ALIGN=right>File:</TH><TD>!AZ</TD>\
<TR><TH ALIGN=right>Extend Blocks:</TH><TD>!UL</TD>\
<TR><TH ALIGN=right VALIGN=top>Exclude Hosts:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Track:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Track Multi-Session:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Track Domain:</TH><TD>!AZ</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>OPCOM</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>Target:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Admin:</TH><TD>!AZ</TD></TR>\
<TR><TH ALIGN=right>Authorization:</TH><TD>!AZ</TD></TR>\
<TR><TH ALIGN=right>Control:</TH><TD>!AZ</TD></TR>\
<TR><TH ALIGN=right>HTTPd:</TH><TD>!AZ</TD></TR>\
<TR><TH ALIGN=right>ProxyMaint:</TH><TD>!AZ</TD></TR>\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>File Cache</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>Caching:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Max Entries:</TH><TD>!UL</TD>\
<TD><I>files</I></TD></TR>\n\
<TR><TH ALIGN=right>Max Cache Size:</TH><TD>!UL</TD>\
<TD><I>kBytes</I></TD></TR>\n\
<TR><TH ALIGN=right>Max Entry Size:</TH><TD>!UL</TD>\
<TD><I>kBytes</I></TD></TR>\n\
<TR><TH ALIGN=right>Guard:</TH><TD>!&@</TD>\
<TD><I>(hh:mm:ss)</I></TD></TR>\n\
<TR><TH ALIGN=right>Validate:</TH><TD>!&@</TD></TR>\n\
<TR><TH ALIGN=right>Frequent /Hits:</TH><TD>!UL</TD></TR>\
<TR><TH ALIGN=right>/Within:</TH><TD>!&@</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Timeouts</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>Input:</TH><TD>!&@</TD>\
<TD><I>(hh:mm:ss)</I></TD></TR>\n\
<TR><TH ALIGN=right>Output:</TH><TD>!&@</TD></TR>\n\
<TR><TH ALIGN=right>No-Progress:</TH><TD>!&@</TD></TR>\n\
<TR><TH ALIGN=right>Keep-Alive:</TH><TD>!&@</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Buffer Sizes</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>DCL <FONT SIZE=-1>SYS$COMMAND</FONT>:</TH>\
<TD>!UL</TD></TR>\n\
<TR><TH ALIGN=right>DCL <FONT SIZE=-1>SYS$OUTPUT</FONT>:</TH>\
<TD>!UL</TD></TR>\n\
<TR><TH ALIGN=right>DCL <FONT SIZE=-1>CGIPLUSIN</FONT>:</TH>\
<TD>!UL</TD></TR>\n\
<TR><TH ALIGN=right>CGI Header:</TH>\
<TD>!UL</TD></TR>\n\
<TR><TH ALIGN=right>Network Read:</TH><TD>!UL</TD></TR>\n\
<TR><TH ALIGN=right>Network Write:</TH><TD>!UL</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Welcome (Home) Pages</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n";

   static char ReportHostsFao [] =
"</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Hosts</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>Accept:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Reject:</TH><TD>!AZ</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Server Generated Reports</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>Server Admin Email:</TH>\
<TD COLSPAN=2>!&@</TD></TD></TR>\n\
<TR><TH ALIGN=right>Server Signature:</TH><TD>!&;AZ</TD></TR>\n\
<TR><TH ALIGN=right VALIGN=top>Server Report &lt;BODY&gt;:</TH>\
<TD COLSPAN=2><TT>!&;AZ</TT></TD></TR>\n\
<TR><TH ALIGN=right VALIGN=top>Admin Menu &lt;BODY&gt;:</TH>\
<TD COLSPAN=2><TT>!&;AZ</TT></TD></TR>\n\
<TR><TH ALIGN=right>Basic Info Only:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>&lt;META&gt; Info:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Error Report Path:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Error Recommend:</TH><TD>!AZ</TD></TR>\n\
</TD></TR>\n\
</TABLE>\n\
</TABLE>\n\
</TD></TR>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Authorization</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>Cache Entries:</TH><TD>!UL</TD></TR>\n\
<TR><TH ALIGN=right>Cache Entry Size:</TH><TD>!UL</TD>\
<TD><I>bytes</I></TD></TR>\n\
<TR><TH ALIGN=right>Cache Valid:</TH><TD>!UL</TD>\
<TD><I>minutes</I></TD></TR>\n\
<TR><TH ALIGN=right>Revalidate User:</TH><TD>!UL</TD>\
<TD><I>minutes</I></TD></TR>\n\
<TR><TH ALIGN=right>Revalidate Cookie:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Failure Limit:</TH><TD>!UL</TD>\
<TD><I>attempts</I></TD></TR>\n\
<TR><TH ALIGN=right>Failure Period:</TH><TD>!&@</TD>\
<TD><I>(hh:mm:ss)</I></TD></TR>\n\
<TR><TH ALIGN=right>Failure Timeout:</TH><TD>!&@</TD></TR>\n\
<TR><TH ALIGN=right>Basic</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Digest:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Digest GET lifetime:</TH><TD>!UL</TD>\
<TD><I>minutes</I></TD></TR>\n\
<TR><TH ALIGN=right>Digest PUT lifetime:</TH><TD>!UL</TD>\
<TD><I>minutes</I></TD></TR>\n\
<TR><TH ALIGN=right>SYSUAF use ACME:</TH>\
<TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right><NOBR>SYSUAF Accept Expired Pwd:</NOBR></TH>\
<TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>SYSUAF Pwd Expired URL:</TH>\
<TD COLSPAN=2>!AZ</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Proxy Serving</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>Proxy Serving:</TH>\
<TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Cache:</TH>\
<TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Unknown Request Fields:</TH>\
<TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Add &quot;Forwarded: by&quot;:</TH>\
<TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Add &quot;X-Forwarded-For:&quot;:</TH>\
<TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Report Events To Log:</TH>\
<TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right><NOBR>Report Cache Events To Log:</NOBR></TH>\
<TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Verify Max:</TH><TD>!UL</TD>\
<TD><I>records</I></TD></TR>\n\
<TR><TH ALIGN=right>Host Name Lookup Retry:</TH><TD>!UL</TD>\
<TD><I>attempts</I></TD></TR>\n\
<TR><TH ALIGN=right><U>Cache</U></TH></TR>\n\
<TR><TH ALIGN=right>Max Load:</TH><TD>!UL</TD>\
<TD><I>kBytes</I></TD></TR>\n\
<TR><TH ALIGN=right>No Reload:</TH><TD>!UL</TD>\
<TD><I>seconds</I></TD></TR>\n\
<TR><TH ALIGN=right>Reload List:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Routine Purge:</TH><TD>!AZ</TD>\
<TD><I>hour-of-day</I></TD></TR>\n\
<TR><TH ALIGN=right>Purge List:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right><U>Cache Device</U></TH></TR>\n\
<TR><TH ALIGN=right>Directory Organization:</TH><TD COLSPAN=2>!AZ</TD>\
<TR><TH ALIGN=right>Usage Check:</TH><TD>!UL</TD>\
<TD><I>minutes</I></TD></TR>\n\
<TR><TH ALIGN=right>Usage Max:</TH><TD>!UL</TD>\
<TD><I>percent</I></TD></TR>\n\
<TR><TH ALIGN=right>Reduce By:</TH><TD>!UL</TD>\
<TD><I>percent</I></TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Scripting &nbsp;(CGI, DCL & DECnet)</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>Scripting:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Detach Process:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Process Priority:</TH><TD>!AZ</TD>\
<TD><I>server,user</I></TD></TR>\n\
<TR><TH ALIGN=right>Strict CGI Output:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Spawn Authorized Privileges:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Gateway BG:</TH><TD COLSPAN=2>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Soft Limit:</TH><TD>!UL</TD>\
<TD><I>script processes</I></TD></TR>\n\
<TR><TH ALIGN=right>Hard Limit:</TH><TD>!UL</TD>\
<TD><I>script processes</I></TD></TR>\n\
<TR><TH ALIGN=right>Bit-Bucket Timeout:</TH><TD>!&@</TD>\
<TD><I>(hh:mm:ss)</I></TD></TR>\n\
<TR><TH ALIGN=right>Zombie Life-Time:</TH><TD>!&@</TD></TR>\n\
<TR><TH ALIGN=right>CGIplus Life-Time:</TH><TD>!&@</TD></TR>\n\
<TR><TH ALIGN=right>DECnet Reuse Life-Time:</TH><TD>!&@</TD></TR>\n\
<TR><TH ALIGN=right>DECnet Connect List Max:</TH><TD>!UL</TD>\
<TD><I>connections</I></TD></TR>\n\
<TR><TH ALIGN=right>Cleanup Scratch Max:</TH><TD>!UL</TD>\
<TD><I>minutes</I></TD></TR>\n\
<TR><TH ALIGN=right>Cleanup Older-than:</TH><TD>!UL</TD>\
<TD><I>minutes</I></TD></TR>\n\
<TR><TH ALIGN=right>Script Run-Time:</TH>\
<TD ALIGN=left><U>suffix</U></TD><TD ALIGN=left><U>verb</U></TD></TR>\n";

   static char ReportSsiFao [] =
"</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
</TABLE>\n\
</TD></TR>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Server-Side Includes</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>SSI:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Exec:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Accesses:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Max Size:</TH><TD>!UL</TD>\
<TD><I>kBytes</I></TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Directory</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=0 CELLSPACING=5 BORDER=0>\n\
<TR><TH ALIGN=right>Access:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Layout:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right VALIGN=top>Listing &lt;BODY&gt;:</TH>\
<TD><NOBR><TT>!&;AZ</TT></NOBR></TD></TR>\n\
<TR><TH ALIGN=right>HTML Description:</TH><TD>!UL\
&nbsp;<I>lines</I></TD></TR>\n\
<TR><TH ALIGN=right>&lt;META&gt; Info:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Owner:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Pre-Expired:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Wildcard:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>No Implied Wildcard:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Prot Violations Ignored:</TH><TD>!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Readme:</TH><TD>!AZ &nbsp;!AZ</TD></TR>\n\
<TR><TH ALIGN=right>Readme Files:</TH>\n";

   static char  ReportIconsFao [] =
"</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH COLSPAN=4>Directory Icons</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=1 CELLSPACING=0 BORDER=0>\n\
<TR>\
<TH ALIGN=left><NOBR>&nbsp;<U>Content-Type</U>&nbsp;&nbsp;</NOBR></TH>\
<TH ALIGN=left><U>Icon</U>&nbsp;&nbsp;</TH>\
<TH ALIGN=left><U>Path</U>&nbsp;&nbsp;</TH>\
<TH ALIGN=left><NOBR><U>Alt.Text</U>&nbsp;</NOBR></TH>\
</TR>\n\
<TR HEIGHT=5></TR>\n";

   static char  ReportContentTypeFao [] =
"</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH COLSPAN=5>Content-Type</TH></TR>\n\
<TR><TD>\n\
<TABLE CELLPADDING=1 CELLSPACING=0 BORDER=0>\n\
<TR>\
<TH ALIGN=left>&nbsp;<U>Suffix</U>&nbsp;&nbsp;</TH>\
<TH ALIGN=left><NOBR><U>Content-Type</U>&nbsp;&nbsp;</NOBR></TH>\
<TH ALIGN=left><U>Icon</U>&nbsp;&nbsp;</TH>\
<TH ALIGN=left><NOBR><U>Auto-script</U>&nbsp;&nbsp;</NOBR></TH>\
<TH ALIGN=left><U>Description</U></TH>\
</TR>\n\
<TR HEIGHT=5></TR>\n";

   static char  EndPageFao [] =
"<TR HEIGHT=5></TR>\n\
<TR><TH COLSPAN=5 ALIGN=left>&nbsp;<U>MIME.TYPES&nbsp;File:</U>\
&nbsp;&nbsp;!AZ</TH></TR>\n\
<TR HEIGHT=5></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
</BODY>\n\
</HTML>\n";

   int  idx,
        status,
        ServiceListCount;
   unsigned long  *vecptr;
   unsigned long  FaoVector [128];
   char  HtmlIconAltText [256],
         IconAltText [256],
         IconPath [256];
   char  *cptr, *sptr, *zptr;
   CONFIG_STRUCT  *cfptr;
   CONTENT_TYPE  ContentType;
   CONTENT_TYPE  *ctptr;
   ICON_TYPE  *itptr;

   /*********/
   /* begin */
   /*********/

   if (WATCHING(rqptr) && WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (rqptr, FI_LI, WATCH_MOD_CONFIG, "ConfigReportNow()");

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN;
   RESPONSE_HEADER_200_HTML (rqptr);
   AdminPageTitle (rqptr, "Server Configuration");
   AdminMetaConReport (rqptr, mcptr, MetaGlobalConfigPtr);
   AdminMetaConSource (rqptr, mcptr, MetaGlobalConfigPtr, mcptr->IncludeFile);

   /************/
   /* services */
   /************/

   if (VMSnok (ServiceReportConfigFromString (rqptr, cfptr)))
      return;

   /***********/
   /* general */
   /***********/

   vecptr = FaoVector;

   /* GMT */
   *vecptr++ = TimeGmtString;
   *vecptr++ = rqptr->rqTime.GmDateTime;

   /* general */
   if (cfptr->cfServer.InstanceMax == INSTANCE_PER_CPU)
      *vecptr++ = "CPU";
   else
   {
      *vecptr++ = "!UL";
      *vecptr++ = cfptr->cfServer.InstanceMax;
   }
   *vecptr++ = cfptr->cfServer.BusyLimit;
   if (cfptr->cfServer.ListenBacklog)
      *vecptr++ = cfptr->cfServer.ListenBacklog;
   else
      *vecptr++ = DEFAULT_LISTEN_BACKLOG;
   *vecptr++ = cfptr->cfMisc.RequestHistory;
   *vecptr++ = cfptr->cfMisc.ActivityNumberOfDays;
   REP_NOTNONE (cfptr->cfContent.CharsetDefault)
   if (cfptr->cfContent.CharsetConvertPtr)
      *vecptr++ = ConfigStringList (rqptr,
                     cfptr->cfContent.CharsetConvertPtr, '\r');
   else
      *vecptr++ = NotNone;
   REP_ENDIS (cfptr->cfMisc.MonitorEnabled)
   REP_ENDIS (cfptr->cfMisc.RegexEnabled)
   *vecptr++ = cfptr->cfServer.DefaultPort;
   *vecptr++ = cfptr->cfMisc.StreamLfConversionMaxKbytes;
   *vecptr++ = cfptr->cfScript.DefaultSearch;
   if (cfptr->cfScript.DefaultSearchExcludePtr)
      *vecptr++ = ConfigStringList (rqptr,
                     cfptr->cfScript.DefaultSearchExcludePtr, '\r');
   else
      *vecptr++ = NotNone;
   *vecptr++ = cfptr->cfMisc.PutMaxKbytes;
   *vecptr++ = cfptr->cfMisc.PutVersionLimit;
   if (cfptr == &Config)
      *vecptr++ = MapUrlUserNameCacheEntries;
   else
      *vecptr++ = cfptr->cfMisc.MapUserNameCacheEntries;
   if (cfptr == &Config)
      *vecptr++ = PersonaCacheEntries;
   else
      *vecptr++ = cfptr->cfMisc.PersonaCacheEntries;

   /* DNS host resolution */
   REP_ENDIS (cfptr->cfMisc.DnsLookupClient)
   REP_HHMMSS (cfptr->cfMisc.DnsLookupLifeTimeSeconds)
   *vecptr++ = cfptr->cfMisc.DnsLookupRetryCount;

   /* logging */
   REP_ENDIS (cfptr->cfLog.Enabled)
   REP_NOTNONE (cfptr->cfLog.Format)
   REP_NOTNONE (cfptr->cfLog.Naming)
   REP_NOTNONE (cfptr->cfLog.Period)
   REP_ENDIS (cfptr->cfLog.PerInstance)
   REP_ENDIS (cfptr->cfLog.PerService)
   REP_ENDIS (cfptr->cfLog.PerServiceHostOnly)
   REP_NOTNONE (cfptr->cfLog.FileName)
   *vecptr++ = cfptr->cfLog.ExtendBlocks;
   if (cfptr->cfLog.ExcludeHostsPtr)
      *vecptr++ = ConfigStringList (rqptr, cfptr->cfLog.ExcludeHostsPtr, '\n');
   else
      *vecptr++ = NotNone;
   REP_ENDIS (cfptr->cfTrack.Enabled)
   REP_ENDIS (cfptr->cfTrack.MultiSession)
   if (cfptr->cfTrack.Domain[0])
      *vecptr++ = cfptr->cfTrack.Domain;
   else
      *vecptr++ = ServerOnly;

   /* OPCOM messages */
   *vecptr++ = ConfigOpcomTarget[cfptr->cfOpcom.Index].Name;
   REP_ENDIS (cfptr->cfOpcom.Messages & OPCOM_ADMIN)
   REP_ENDIS (cfptr->cfOpcom.Messages & OPCOM_AUTHORIZATION)
   REP_ENDIS (cfptr->cfOpcom.Messages & OPCOM_CONTROL)
   REP_ENDIS (cfptr->cfOpcom.Messages & OPCOM_HTTPD)
   REP_ENDIS (cfptr->cfOpcom.Messages & OPCOM_PROXY_MAINT)

   /* cache */
   REP_ENDIS (cfptr->cfCache.Enabled)
   *vecptr++ = cfptr->cfCache.EntriesMax;
   *vecptr++ = cfptr->cfCache.TotalKBytesMax;
   *vecptr++ = cfptr->cfCache.FileKBytesMax;
   REP_HHMMSS (cfptr->cfCache.GuardSeconds)
   REP_HHMMSS (cfptr->cfCache.ValidateSeconds)
   *vecptr++ = cfptr->cfCache.FrequentHits;
   REP_HHMMSS (cfptr->cfCache.FrequentSeconds)

   /* timeouts */
   REP_HHMMSS (cfptr->cfTimeout.Input)
   REP_HHMMSS (cfptr->cfTimeout.Output)
   REP_HHMMSS (cfptr->cfTimeout.NoProgress)
   REP_HHMMSS (cfptr->cfTimeout.KeepAlive)

   /* buffer sizes */
   if (cfptr == &Config)
   {
      /* in-use values */
      *vecptr++ = DclSysCommandSize;
      *vecptr++ = DclSysOutputSize;
      *vecptr++ = DclCgiPlusInSize;
      *vecptr++ = DclCgiHeaderSize;
      *vecptr++ = NetReadBufferSize;
      *vecptr++ = OutputBufferSize;
   }
   else
   {
      /* file values */
      *vecptr++ = cfptr->cfBuffer.SizeDclCommand;
      *vecptr++ = cfptr->cfBuffer.SizeDclOutput;
      *vecptr++ = cfptr->cfBuffer.SizeDclCgiPlusIn;
      *vecptr++ = cfptr->cfBuffer.SizeDclCgiHeader;
      *vecptr++ = cfptr->cfBuffer.SizeNetRead;
      *vecptr++ = cfptr->cfBuffer.SizeNetWrite;
   }

   status = NetWriteFaol (rqptr, ReportGeneralFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

   /*****************************/
   /* welcome (home page) files */
   /*****************************/

   for (idx = 0; idx < cfptr->cfContent.HomePageCount; idx++)
   {
      status = NetWriteFao (rqptr, "<TR><TD><TT>!&;AZ</TT></TD></TR>\n",
                            cfptr->cfContent.HomePageArray[idx]);
      if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);
   }

   /*********************/
   /* host access, etc. */
   /*********************/

   vecptr = FaoVector;

   if (cfptr->cfServer.AcceptHostsPtr)
      *vecptr++ = ConfigStringList (rqptr, cfptr->cfServer.AcceptHostsPtr, ',');
   else
      *vecptr++ = NotNone;

   if (cfptr->cfServer.RejectHostsPtr)
      *vecptr++ = ConfigStringList (rqptr, cfptr->cfServer.RejectHostsPtr, ',');
   else
      *vecptr++ = NotNone;

   /* reports */
   if (cfptr->cfServer.AdminEmail[0])
   {
      *vecptr++ = "!&;AZ";
      *vecptr++ = cfptr->cfServer.AdminEmail;
   }
   else
   {
      *vecptr++ = "!AZ";
      *vecptr++ = NotNone;
   }
   if (cfptr->cfServer.Signature == CONFIG_SERVER_SIGNATURE_ON)
      *vecptr++ = "[enabled]";
   else
   if (cfptr->cfServer.Signature == CONFIG_SERVER_SIGNATURE_EMAIL)
      *vecptr++ = "[enabled] [email]";
   else
      *vecptr++ = "[disabled]";
   *vecptr++ = cfptr->cfServer.ReportBodyTag;
   *vecptr++ = cfptr->cfServer.AdminBodyTag;
   REP_ENDIS (cfptr->cfReport.BasicOnly)
   REP_ENDIS (cfptr->cfReport.MetaInfoEnabled)
   REP_NOTNONE (cfptr->cfReport.ErrorReportPath)
   REP_ENDIS (cfptr->cfReport.ErrorRecommend)

   /* authentication */
   *vecptr++ = cfptr->cfAuth.CacheEntriesMax;
   *vecptr++ = cfptr->cfAuth.CacheEntrySize;
   *vecptr++ = cfptr->cfAuth.CacheMinutes;
   *vecptr++ = cfptr->cfAuth.RevalidateUserMinutes;
   REP_ENDIS (cfptr->cfAuth.RevalidateLoginCookie)
   if (mcptr == MetaGlobalConfigPtr)
   {
      /* server, show the values in use */
      *vecptr++ = AuthFailureLimit;
      REP_HHMMSS (AuthFailurePeriodSeconds)
      REP_HHMMSS (AuthFailureTimeoutSeconds)
   }
   else
   {
      /* from file, show the config values */
      *vecptr++ = cfptr->cfAuth.FailureLimit;
      REP_HHMMSS (cfptr->cfAuth.FailurePeriodSeconds)
      REP_HHMMSS (cfptr->cfAuth.FailureTimeoutSeconds)
   }
   REP_ENDIS (cfptr->cfAuth.BasicEnabled)
   REP_ENDIS (cfptr->cfAuth.DigestEnabled)
   *vecptr++ = cfptr->cfAuth.DigestNonceGetLifeTime;
   *vecptr++ = cfptr->cfAuth.DigestNonceGetLifeTime;
   REP_ENDIS (cfptr->cfAuth.SysUafUseACME)
   REP_ENDIS (cfptr->cfAuth.SysUafAcceptExpPwd)
   REP_NOTNONE (cfptr->cfAuth.SysUafPwdExpUrl)

   /* proxy serving */
   REP_ENDIS (cfptr->cfProxy.ServingEnabled)
   REP_ENDIS (cfptr->cfProxy.CacheEnabled)
   REP_ENDIS (cfptr->cfProxy.UnknownRequestFields)
   if (cfptr->cfProxy.ForwardedBy == PROXY_FORWARDED_BY)
      *vecptr++ = "BY";
   else
   if (cfptr->cfProxy.ForwardedBy == PROXY_FORWARDED_FOR)
      *vecptr++ = "FOR";
   else
   if (cfptr->cfProxy.ForwardedBy == PROXY_FORWARDED_ADDRESS)
      *vecptr++ = "ADDRESS";
   else
      *vecptr++ = NotNone;
   if (cfptr->cfProxy.XForwardedFor == PROXY_XFORWARDEDFOR_ENABLED)
      *vecptr++ = "ENABLED";
   else
   if (cfptr->cfProxy.XForwardedFor == PROXY_XFORWARDEDFOR_UNKNOWN)
      *vecptr++ = "UNKNOWN";
   else
   if (cfptr->cfProxy.XForwardedFor == PROXY_XFORWARDEDFOR_ADDRESS)
      *vecptr++ = "ADDRESS";
   else
      *vecptr++ = NotNone;
   REP_ENDIS (cfptr->cfProxy.ReportLog)
   REP_ENDIS (cfptr->cfProxy.ReportCacheLog)
   *vecptr++ = cfptr->cfProxy.VerifyRecordMax;
   *vecptr++ = cfptr->cfProxy.HostLookupRetryCount;
   *vecptr++ = cfptr->cfProxy.CacheFileKBytesMax;
   *vecptr++ = cfptr->cfProxy.CacheNoReloadSeconds;
   REP_NOTNONE (cfptr->cfProxy.CacheReloadList)
   *vecptr++ = cfptr->cfProxy.CacheRoutineHourOfDayString;
   REP_NOTNONE (cfptr->cfProxy.CachePurgeList)
   if (cfptr->cfProxy.CacheDeviceDirOrg == PROXY_CACHE_DIR_ORG_FLAT256)
      *vecptr++ = "flat256";
   else
   if (cfptr->cfProxy.CacheDeviceDirOrg == PROXY_CACHE_DIR_ORG_64X64)
      *vecptr++ = "64x64";
   else
      *vecptr++ = "";
   *vecptr++ = cfptr->cfProxy.CacheDeviceCheckMinutes;
   *vecptr++ = cfptr->cfProxy.CacheDeviceMaxPercent;
   *vecptr++ = cfptr->cfProxy.CacheDevicePurgePercent;

   /* scripting */
   REP_ENDIS (cfptr->cfScript.Enabled)
   REP_ENDIS (cfptr->cfScript.DetachProcess)
   *vecptr++ = cfptr->cfScript.DetachProcessPriority;
   REP_ENDIS (cfptr->cfScript.CgiStrictOutput)
   REP_ENDIS (cfptr->cfScript.SpawnAuthPriv)
   REP_ENDIS (cfptr->cfScript.GatewayBg)
   *vecptr++ = cfptr->cfScript.ScriptProcessSoftLimit;
   *vecptr++ = cfptr->cfScript.ScriptProcessHardLimit;
   REP_HHMMSS (cfptr->cfScript.BitBucketTimeout)
   REP_HHMMSS (cfptr->cfScript.ZombieLifeTime)
   REP_HHMMSS (cfptr->cfScript.CgiPlusLifeTime)
   REP_HHMMSS (cfptr->cfScript.DECnetReuseLifeTime)
   *vecptr++ = cfptr->cfScript.DECnetConnectListMax;
   *vecptr++ = cfptr->cfScript.CleanupScratchMinutesMax;
   *vecptr++ = cfptr->cfScript.CleanupScratchMinutesOld;

   status = NetWriteFaol (rqptr, ReportHostsFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

   /****************/
   /* script types */
   /****************/

   if (cfptr->cfScript.RunTimeCount)
   {
      for (idx = 0; idx < cfptr->cfScript.RunTimeCount; idx++)
      {
         vecptr = FaoVector;

         cptr = sptr = cfptr->cfScript.RunTime[idx].String;
         /* length of and location of the file type */
         while (*cptr && *cptr != ';') cptr++;
         *vecptr++ = cptr - sptr;
         *vecptr++ = sptr;
         /*  location of verb */
         cptr += 2;
         *vecptr++ = cptr;

         status = NetWriteFaol (rqptr,
"<TR><TD></TD><TD>!#&;AZ</TD><TD><TT>!&;AZ</TT></TD><TD></TR>\n",
                     &FaoVector);
         if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);
      }
   }
   else
   {
      static char  NotNone [] =
"<TR><TD COLSPAN=2><I>(none)</I></TD></TR>\n";

      status = NetWriteFaol (rqptr, NotNone, NULL);
      if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);
   }

   /**********************/
   /* Reports, SSI, etc. */
   /**********************/

   vecptr = FaoVector;

   /* SSI (.shtml) */
   REP_ENDIS (cfptr->cfSsi.Enabled)
   REP_ENDIS (cfptr->cfSsi.ExecEnabled)
   REP_ENDIS (cfptr->cfSsi.AccessesEnabled)
   *vecptr++ = cfptr->cfSsi.SizeMax;

   REP_ENDIS (cfptr->cfDir.Access)
   REP_NOTNONE (cfptr->cfDir.DefaultLayout)
   *vecptr++ = cfptr->cfDir.BodyTag;
   *vecptr++ = cfptr->cfDir.DescriptionLines;
   REP_ENDIS (cfptr->cfDir.MetaInfoEnabled)
   REP_ENDIS (cfptr->cfDir.OwnerEnabled)
   REP_ENDIS (cfptr->cfDir.PreExpired)
   REP_ENDIS (cfptr->cfDir.WildcardEnabled)
   REP_ENDIS (cfptr->cfDir.NoImpliedWildcard)
   REP_ENDIS (cfptr->cfDir.NoPrivIgnore)
   REP_ENDIS (cfptr->cfDir.ReadMeTop | cfptr->cfDir.ReadMeBottom)
   if (cfptr->cfDir.ReadMeTop)
      *vecptr++ = "[top]";
   else
   if (cfptr->cfDir.ReadMeBottom)
      *vecptr++ = "[bottom]";
   else
      *vecptr++ = "";

   status = NetWriteFaol (rqptr, ReportSsiFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

   /*********************/
   /* directory (contd) */
   /*********************/

   for (idx = 0; idx < cfptr->cfDir.ReadMeFileCount; idx++)
   {
      status = NetWriteFao (rqptr, "!&@<TD><TT>!AZ</TT></TD></TR>\n",
                            idx ? "<TR><TD></TD>" : "",
                            cfptr->cfDir.ReadMeFileArray[idx]);
      if (VMSnok (status)) ErrorNoticed (status, "NetWriteFao()", FI_LI);
   }

   /*********/
   /* icons */
   /*********/

   status = NetWriteFaol (rqptr, ReportIconsFao, NULL);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

   itptr = cfptr->cfContent.IconListHeadPtr;
   while (itptr)
   {
      vecptr = FaoVector;
      *vecptr++ = itptr->ContentTypePtr;
      *vecptr++ = itptr->IconUrlPtr;
      *vecptr++ = itptr->IconUriPtr;
      *vecptr++ = itptr->AltTextPtr;

      if (itptr->Superceded)
         cptr =
"<TR><TD>&nbsp;<I><STRIKE>!AZ</STRIKE></I>&nbsp;&nbsp;</TD>\
<TD ALIGN=center>!AZ&nbsp;&nbsp;</TD>\
<TD><I><STRIKE>!AZ</STRIKE></I>&nbsp;&nbsp;</TD>\
<TD><I><STRIKE>[!&;AZ]</STRIKE></I>&nbsp;&nbsp;</TD></TR>\n";
      else
         cptr =
"<TR><TD>&nbsp;!AZ&nbsp;&nbsp;</TD>\
<TD ALIGN=center>!AZ&nbsp;&nbsp;</TD>\
<TD>!AZ&nbsp;&nbsp;</TD>\
<TD>!AZ</TD></TR>\n";

      status = NetWriteFaol (rqptr, cptr, &FaoVector);
      if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

      itptr = itptr->NextPtr;
   }

   /*****************/
   /* content-types */
   /*****************/

   status = NetWriteFaol (rqptr, ReportContentTypeFao, NULL);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

   for (ctptr = cfptr->cfContent.ContentInfoListHeadPtr;
        ctptr;
        ctptr = ctptr->NextPtr)
   {
      vecptr = &FaoVector;
      if (ctptr->FromMimeTypes)
         if (*ctptr->SuffixPtr == '.')
            *vecptr++ = ctptr->SuffixPtr+1;
         else
            *vecptr++ = ctptr->SuffixPtr;
      else
         *vecptr++ = ctptr->SuffixPtr;
      *vecptr++ = ctptr->ContentTypePtr;
      if (ctptr->FtpMode)
      {
         *vecptr++ = "&nbsp;(FTP:!&C)";
         *vecptr++ = ctptr->FtpMode;
      }
      else
         *vecptr++ = "";
      *vecptr++ = ctptr->IconPtr;
      *vecptr++ = ctptr->AutoScriptNamePtr;
      if (ctptr->TypeUnknown)
         *vecptr++ = cfptr->cfContent.ContentTypeDefaultPtr;
      else
         *vecptr++ = ctptr->DescriptionPtr;

      if (ctptr->Superceded)
         cptr = 
"<TR><TD>&nbsp;<I><STRIKE>!AZ</STRIKE></I>&nbsp;&nbsp;</TD>\
<TD><I><STRIKE>!AZ!&@</STRIKE></I>&nbsp;&nbsp;</TD>\
<TD>!AZ&nbsp;&nbsp;</TD>\
<TD><I><STRIKE>!AZ</STRIKE></I>&nbsp;&nbsp;</TD>\
<TD><I><STRIKE>!AZ</STRIKE></I></TD></TR>\n";
      else
         cptr =
"<TR><TD>&nbsp;!AZ&nbsp;&nbsp;</TD>\
<TD>!AZ!&@&nbsp;&nbsp;</TD>\
<TD>!AZ&nbsp;&nbsp;</TD>\
<TD>!AZ&nbsp;&nbsp;</TD>\
<TD>!AZ</TD></TR>\n";

      status = NetWriteFaol (rqptr, cptr, &FaoVector);
      if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);
   }

   vecptr = &FaoVector;
   if (cfptr->cfContent.MimeTypesFileName[0])
      *vecptr++ = cfptr->cfContent.MimeTypesFileName;
   else
      *vecptr++ = "<I>(none)</I>";;

   status = NetWriteFaol (rqptr, EndPageFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

#undef REP_ENDIS
#undef REP_NOTNONE
#undef REP_HHMMSS
}

/*****************************************************************************/
/*
This function just wraps the revision function, loading a temporary database
if necessary for reporting from the configuration file.
*/ 

ConfigRevise
(
REQUEST_STRUCT *rqptr,
REQUEST_AST NextTaskFunction,
BOOL UseServerDatabase
)
{
   int  status;
   META_CONFIG  *mcptr;

   /*********/
   /* begin */
   /*********/

   if (WATCHING(rqptr) && WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (rqptr, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigRevise() !&F !&A !UL",
                 &ConfigRevise, NextTaskFunction, UseServerDatabase);

   if (UseServerDatabase)
      ConfigReviseNow (rqptr, MetaGlobalConfigPtr);
   else
   {
      status = ConfigLoad (&mcptr);
      if (VMSnok (status))
      {
         /* severe error reported */
         rqptr->rqResponse.HttpStatus = 403;
         ErrorGeneral (rqptr, mcptr->LoadReport.TextPtr, FI_LI);
      }
      else
         ConfigReviseNow (rqptr, mcptr);
      MetaConUnload (&mcptr, NULL);
   }

   SysDclAst (NextTaskFunction, rqptr);
}

/*****************************************************************************/
/*
Return a form for the HTTPd server's configuration.  POSTing the form to the
server results in the URL-decoded form as a configuration file.  This function
blocks while executing.
*/ 

ConfigReviseNow
(
REQUEST_STRUCT *rqptr,
META_CONFIG *mcptr
)
{
#define SIZEOF_SPECIAL_ICON 256

#define REP_BOOL_RADIO(b)\
if (b)\
{\
   *vecptr++ = RadioButtonChecked;\
   *vecptr++ = RadioButtonUnchecked;\
}\
else\
{\
   *vecptr++ = RadioButtonUnchecked;\
   *vecptr++ = RadioButtonChecked;\
}

/* report a number of seconds as HH:MM:SS */
#define REP_HHMMSS(s) \
*vecptr++ = "!2ZL:!2ZL:!2ZL"; \
*vecptr++ = s / 3600; \
*vecptr++ = (s % 3600) / 60; \
*vecptr++ = (s % 3600) % 60;

   static char  ConfigGeneralFao [] =
"<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Service</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;# -SERVICE-&#94;\">\n\
<TR><TD>\n\
!&@\
<BR><NOBR><B>Service Not Found URL:</NOBR></B>&nbsp;\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ServiceNotFoundURL]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=40 NAME=ServiceNotFoundURL VALUE=!AZ>\n\
</TD></TR>\n\
</TABLE>\n\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>General</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -GENERAL-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TH ALIGN=right>Instance Max:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[InstanceMax]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=InstanceMax VALUE=!&@>\n\
<I>per-node servers</I></TD></TR>\n\
<TR><TH ALIGN=right>Busy:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[Busy]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=4 NAME=Busy VALUE=!UL>\n\
<I>connections</I></TD></TR>\n\
<TR><TH ALIGN=right>Listen Backlog:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ServiceListenBacklog]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=ServiceListenBacklog VALUE=!UL>\n\
<I>connections</I></TD></TR>\n\
<TR><TH ALIGN=right>Request History:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[RequestHistory]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=RequestHistory VALUE=!UL>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Activity History:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ActivityDays]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=ActivityDays VALUE=!UL>\n\
<I>days</I></TD></TR>\n\
<TR><TH ALIGN=right>Charset Default:</TH><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[CharsetDefault]&#32;&#32;\">\n\
<INPUT TYPE=text size=40 NAME=CharsetDefault VALUE=\"!AZ\">\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Charset Convert:</TH></TR>\n\
<TR><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[CharsetConvert]&#94;\">\n\
<TEXTAREA NAME=CharsetConvert ROWS=4 COLS=60 NOWRAP>\
!AZ\
</TEXTAREA>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Monitor:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[Monitor]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=Monitor VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=Monitor VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Regular&nbsp;Expressions:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[RegEx]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=RegEx VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=RegEx VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>IP Port:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[Port]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=5 NAME=Port VALUE=!UL>\n\
<I>(overridden by <I>service</I> directive)</I></TD></TR>\n\
<TR><TH ALIGN=right>StreamLF:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[StreamLF]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=StreamLF VALUE=!UL>\n\
<I>kBytes</I></TD></TR>\n\
<TR><TH ALIGN=right>Search Script:</TH><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[SearchScript]&#32;&#32;\">\n\
<INPUT TYPE=text size=40 NAME=SearchScript VALUE=\"!AZ\">\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Search&nbsp;Script&nbsp;Exclude:</TH></TR>\n\
<TR><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[SearchScriptExclude]&#94;\">\n\
<TEXTAREA NAME=SearchScriptExclude ROWS=4 COLS=40 NOWRAP>\
!AZ\
</TEXTAREA>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>PUT/POST Max Length:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[PutMaxKbytes]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=5 NAME=PutMaxKbytes VALUE=!UL>\n\
<I>kBytes</I></TD></TR>\n\
<TR><TH ALIGN=right>Put/Post Files:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[PutVersionLimit]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=5 NAME=PutVersionLimit VALUE=!UL>\n\
<I>version limit</I></TD></TR>\n\
</TD></TR>\n\
<TR><TH ALIGN=right><NOBR>/~username/ Cache Entries:</NOBR></TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[MapUserNameCacheEntries]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=MapUserNameCacheEntries VALUE=!UL>\n\
<I>user names</I>\
</TD></TR>\n\
<TR><TH ALIGN=right>Persona Cache Entries:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[PersonaCacheEntries]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=PersonaCacheEntries VALUE=!UL>\n\
<I>users</I>\
</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Host Resolution</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -DNS-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TH ALIGN=right>Client&nbsp;Lookup:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DNSLookupClient]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=DNSLookupClient VALUE=enabled!AZ>yes\n\
<INPUT TYPE=radio NAME=DNSLookupClient VALUE=disabled!AZ>no\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Life-Time:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DNSLookupLifeTime]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=8 NAME=DNSLookupLifeTime VALUE=!&@>\n\
<I>hh:mm:ss</I></TD></TR>\n\
<TR><TH ALIGN=right>Retry&nbsp;Count:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DNSLookupRetryCount]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=DNSLookupRetryCount VALUE=!UL></TD></TR>\n\
\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Log</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -LOGGING-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TH ALIGN=right>Logging:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[Logging]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=Logging VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=Logging VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Format:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[LogFormat]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=10 NAME=LogFormat VALUE=!AZ></TD></TR>\n\
<TR><TH ALIGN=right>Naming:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[LogNaming]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=10 NAME=LogNaming VALUE=!AZ></TD></TR>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Period:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[LogPeriod]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=10 NAME=LogPeriod VALUE=!AZ></TD></TR>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Per-Instance:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[LogPerInstance]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=LogPerInstance VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=LogPerInstance VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Per-Service:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[LogPerService]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=LogPerService VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=LogPerService VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Per-Service Host Only:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[LogPerServiceHostOnly]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=LogPerServiceHostOnly VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=LogPerServiceHostOnly VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>File:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[LogFile]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=40 NAME=LogFile VALUE=!AZ></TD></TR>\n\
<TR><TH ALIGN=right>Extend Blocks:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[LogFileExtend]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=5 NAME=LogFileExtend VALUE=!UL>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Exclude Hosts:</TH></TR>\n\
<TR><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[LogExcludeHosts]&#94;\">\n\
<TEXTAREA NAME=LogExcludeHosts ROWS=4 COLS=40 NOWRAP>\
!AZ\
</TEXTAREA>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Track:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[Track]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=Track VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=Track VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Track Multi-Session:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[TrackMultiSession]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=TrackMultiSession VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=TrackMultiSession VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Track Domain:</TH><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[TrackDomain]&#32;&#32;\">\n\
<INPUT TYPE=text size=30 NAME=TrackDomain VALUE=\"!AZ\">\n\
</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>OPCOM</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -OPCOM-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TH ALIGN=right>Target:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[OpcomTarget]&#32;&#32;\">\n\
<SELECT NAME=OpcomTarget>\n";

   static char  ConfigOpcomTargetFao [] =
"<OPTION VALUE=\"!AZ\"!&? SELECTED\r\r>!AZ\n";

   static char  ConfigOpcomFao [] =
"</SELECT>\n\
<TR><TH ALIGN=right>Admin:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[OpcomAdmin]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=OpcomAdmin VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=OpcomAdmin VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Authorization:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[OpcomAuthorization]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=OpcomAuthorization VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=OpcomAuthorization VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Control:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[OpcomControl]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=OpcomControl VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=OpcomControl VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>HTTPd:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[OpcomHTTPd]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=OpcomHTTPd VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=OpcomHTTPd VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>ProxyMaint:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[OpcomProxyMaint]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=OpcomProxyMaint VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=OpcomProxyMaint VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Cache</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -CACHE-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TH ALIGN=right>Caching:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[Cache]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=Cache VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=Cache VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Max Entries:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[CacheEntriesMax]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=4 NAME=CacheEntriesMax VALUE=!UL>\n\
<I>files</I></TD></TR>\n\
<TR><TH ALIGN=right>Max Cache Size:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[CacheTotalKBytesMax]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=4 NAME=CacheTotalKBytesMax VALUE=!UL>\n\
<I>kBytes</I></TD></TR>\n\
<TR><TH ALIGN=right>Max Entry Size:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[CacheFileKBytesMax]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=CacheFileKBytesMax VALUE=!UL>\n\
<I>kBytes</I></TD></TR>\n\
<TR><TH ALIGN=right>Guard:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[CacheGuardPeriod]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=8 NAME=CacheGuardPeriod VALUE=!&@>\n\
<I>hh:mm:ss</I></TD></TR>\n\
<TR><TH ALIGN=right>Validate:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[CacheValidatePeriod]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=8 NAME=CacheValidatePeriod VALUE=!&@>\n</TR>\n\
<TR><TH ALIGN=right>Frequent After:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[CacheFrequentHits]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=CacheFrequentHits VALUE=!UL> \
<I>hits, last within</I>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[CacheFrequentPeriod]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=8 NAME=CacheFrequentPeriod VALUE=!&@>\n</TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Timeouts</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -TIMEOUTS-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TH ALIGN=right>Input:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[TimeoutInput]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=8 NAME=TimeoutInput VALUE=!&@>\n\
<I>hh:mm:ss</I></TD></TR>\n\
<TR><TH ALIGN=right>Output:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[TimeoutOutput]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=8 NAME=TimeoutOutput VALUE=!&@>\n</TR>\n\
<TR><TH ALIGN=right>No-Progress:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[TimeoutNoProgress]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=8 NAME=TimeoutNoProgress VALUE=!&@>\n</TR>\n\
<TR><TH ALIGN=right>Keep-Alive:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[TimeoutKeepAlive]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=8 NAME=TimeoutKeepAlive VALUE=!&@>\n</TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Buffer Sizes</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -BUFFER SIZES-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TH ALIGN=right>DCL <FONT SIZE=-1>SYS$COMMAND</FONT>:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[BufferSizeDclCommand]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=4 NAME=BufferSizeDclCommand VALUE=!UL>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>DCL <FONT SIZE=-1>SYS$OUTPUT</FONT>:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[BufferSizeDclOutput]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=4 NAME=BufferSizeDclOutput VALUE=!UL>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>DCL <FONT SIZE=-1>CGIPLUSIN</FONT>:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[BufferSizeDclCgiPlusIn]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=4 NAME=BufferSizeDclCgiPlusIn VALUE=!UL>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>CGI Header:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[BufferSizeDclCgiHeader]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=4 NAME=BufferSizeDclCgiHeader VALUE=!UL>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Network Read:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[BufferSizeNetRead]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=4 NAME=BufferSizeNetRead VALUE=!UL>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Network Write:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[BufferSizeNetWrite]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=4 NAME=BufferSizeNetWrite VALUE=!UL>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Note ...</A></TH>\
<TD>adjust with caution!!</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Welcome (index/home pages)</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -INDEX PAGES-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TD COLSPAN=2><I>Format: \"file-name.file-type\" \
(e.g. HOME.HTML)</I></TD></TR>\n\
<TR><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[Welcome]&#94;\">\n\
<TEXTAREA NAME=Welcome ROWS=5 COLS=40 NOWRAP>";

   static char  ConfigAcceptFao [] = 
"</TEXTAREA>\n\
</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Host Access Control</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -HOST ACCESS-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TH>Accept</TH></TR>\n\
<TR><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[Accept]&#94;\">\n\
<TEXTAREA NAME=Accept ROWS=4 COLS=40 NOWRAP>\
!AZ\
</TEXTAREA>\n\
</TD></TR>\n\
<TR><TH>Reject</TH></TR>\n\
<TR><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[Reject]&#94;\">\n\
<TEXTAREA NAME=Reject ROWS=4 COLS=40 NOWRAP>\
!AZ\
</TEXTAREA>\n\
</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Server Generated Reports</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -REPORTS-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TH ALIGN=right>Server Admin:</TH><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ServerAdmin]&#32;&#32;\">\n\
<INPUT TYPE=text size=40 NAME=ServerAdmin VALUE=\"!&;AZ\">\n\
<I>email</I></TD></TR>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Server Signature:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ServerSignature]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=ServerSignature VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=ServerSignature VALUE=email!AZ>enabled-email\n\
<INPUT TYPE=radio NAME=ServerSignature VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Server Report &lt;BODY&gt;:</TH><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ServerReportBodyTag]&#32;&#32;\">\n\
<INPUT TYPE=text size=40 NAME=ServerReportBodyTag VALUE=\"!&;AZ\">\n\
<I>HTML tag</I></TD></TR>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Admin Menu &lt;BODY&gt;:</TH><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ServerAdminBodyTag]&#32;&#32;\">\n\
<INPUT TYPE=text size=40 NAME=ServerAdminBodyTag VALUE=\"!&;AZ\">\n\
<I>HTML tag</I></TD></TR>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Basic Info Only:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ReportBasicOnly]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=ReportBasicOnly VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=ReportBasicOnly VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>&lt;META&gt; Info:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ReportMetaInfo]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=ReportMetaInfo VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=ReportMetaInfo VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Error Report Path:</TH><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ErrorReportPath]&#32;&#32;\">\n\
<INPUT TYPE=text size=40 NAME=ErrorReportPath VALUE=\"!AZ\">\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Error Recommend:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ErrorRecommend]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=ErrorRecommend VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=ErrorRecommend VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Authorization</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -AUTHORIZATION-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TH ALIGN=right>Cache Entries:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthCacheEntriesMax]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=AuthCacheEntriesMax VALUE=!UL></TD></TR>\n\
<TR><TH ALIGN=right>Cache Entry Size:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthCacheEntrySize]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=4 NAME=AuthCacheEntrySize VALUE=!UL>\n\
<I>bytes</I></TD></TR>\n\
<TR><TH ALIGN=right>Cache Valid:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthCacheMinutes]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=AuthCacheMinutes VALUE=!UL>\n\
<I>minutes</I></TD></TR>\n\
<TR><TH ALIGN=right>Revalidate User:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthRevalidateUserMinutes]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=AuthRevalidateUserMinutes VALUE=!UL>\n\
<I>minutes</I></TD></TR>\n\
<TR><TH ALIGN=right>Revalidate Cookie:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthRevalidateLoginCookie]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=AuthRevalidateLoginCookie VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=AuthRevalidateLoginCookie VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Failure Limit:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthFailureLimit]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=AuthFailureLimit VALUE=!UL>\n\
<I>attempts</I></TD></TR>\n\
<TR><TH ALIGN=right>Failure Limit:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthFailurePeriod]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=AuthFailurePeriod VALUE=!&@>\n\
<I>attempts</I></TD></TR>\n\
<TR><TH ALIGN=right>Failure Limit:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthFailureTimeout]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=AuthFailureTimeout VALUE=!&@>\n\
<I>attempts</I></TD></TR>\n\
<TR><TH ALIGN=right>Basic Authorization:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthBasic]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=AuthBasic VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=AuthBasic VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Digest Authorization:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthDigest]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=AuthDigest VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=AuthDigest VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>GET nonce lifetime:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthDigestGetLife]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=AuthDigestGetLife VALUE=!UL>\n\
<I>minutes</I></TD>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>PUT nonce lifetime:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthDigestPutLife]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=AuthDigestPutLife VALUE=!UL>\n\
<I>minutes</I></TD></TR>\n\
<TR><TH ALIGN=right>SYSUAF use ACME:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthSYSUAFuseACME]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=AuthSYSUAFuseACME VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=AuthSYSUAFuseACME VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>SYSUAF Accept Expired Pwd:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthSYSUAFacceptExpPwd]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=AuthSYSUAFacceptExpPwd VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=AuthSYSUAFacceptExpPwd VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right><NOBR>SYSUAF Pwd Expired URL:</NOBR></TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AuthSYSUAFpwdExpURL]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=40 NAME=AuthSYSUAFpwdExpURL VALUE=\"!AZ\">\n\
</TD></TR>\n\
</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Proxy Serving</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -PROXY SERVING-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TH ALIGN=right>Serving:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyServing]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=ProxyServing VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=ProxyServing VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Cache:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyCache]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=ProxyCache VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=ProxyCache VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Unknown Request Fields:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyUnknownRequestFields]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=ProxyUnknownRequestFields VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=ProxyProxyUnknownRequestFields VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Add &quot;Forwarded: by&quot;:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyForwarded]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=10 NAME=ProxyForwarded VALUE=\"!AZ\">\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Add &quot;X-Forwarded-For:&quot;:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyXForwardedFor]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=10 NAME=ProxyXForwardedFor VALUE=\"!AZ\">\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Report Events To Log:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyReportLog]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=ProxyReportLog VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=ProxyReportLog VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Report Cache Events To Log:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyReportCacheLog]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=ProxyReportCacheLog VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=ProxyReportCacheLog VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Verify Max:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyVerifyRecordMax]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=ProxyVerifyRecordMax VALUE=!UL>\n\
<I>records</I></TD></TR>\n\
<TR><TH ALIGN=right>Host Name Lookup Retry:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyHostLookupRetryCount]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=ProxyHostLookupRetryCount VALUE=!UL>\n\
<I>count</I></TD></TR>\n\
<TR><TH ALIGN=right>Maximum Load Size:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyCacheFileKBytesMax]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=ProxyCacheFileKBytesMax VALUE=!UL>\n\
<I>kBytes</I></TD></TR>\n\
<TR><TH ALIGN=right>No Reload:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyCacheNoReloadSeconds]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=ProxyCacheNoReloadSeconds VALUE=!UL>\n\
<I>seconds</I></TD></TR>\n\
<TR><TH ALIGN=right>Reload List:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyCacheReloadList]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=30 NAME=ProxyCacheReloadList VALUE=\"!AZ\">\n\
<I>hours</I></TD></TR>\n\
<TR><TH ALIGN=right>Routine Purge:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyCacheRoutineHourOfDay]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=ProxyCacheRoutineHourOfDay VALUE=!AZ>\n\
<I>hour-of-day (00-23 or 24)</I></TD></TR>\n\
<TR><TH ALIGN=right>Purge List:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyCachePurgeList]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=30 NAME=ProxyCachePurgeList VALUE=\"!AZ\">\n\
<I>hours</I></TD></TR>\n\
<TR><TH ALIGN=right>Device Directory Organization:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyCacheDeviceDirOrg]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=5 NAME=ProxyCacheDeviceDirOrg VALUE=!AZ>\n\
<I>flat256 or 64x64</I></TD></TR>\n\
<TR><TH ALIGN=right>Device Usage Check:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyCacheDeviceCheckMinutes]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=ProxyCacheDeviceCheckMinutes VALUE=!UL>\n\
<I>minutes</I></TD></TR>\n\
<TR><TH ALIGN=right>Device Usage Max:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyCacheDeviceMaxPercent]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=ProxyCacheDeviceMaxPercent VALUE=!UL>\n\
<I>percent</I></TD></TR>\n\
<TR><TH ALIGN=right>Device Reduce By:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[ProxyCacheDevicePurgePercent]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=ProxyCacheDevicePurgePercent VALUE=!UL>\n\
<I>percent</I></TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Scripting &nbsp;(CGI, DCL & DECnet)</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -SCRIPTING-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TH ALIGN=right>Scripting:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[Scripting]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=Scripting VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=Scripting VALUE=disabled!AZ>disabled\n\
</TD><TD></TD></TR>\n\
<TR><TH ALIGN=right>Detach Process:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DclDetachProcess]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=DclDetachProcess VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=DclDetachProcess VALUE=disabled!AZ>disabled\n\
</TD><TD></TD></TR>\n\
<TR><TH ALIGN=right>Process Priority:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DclDetachProcessPriority]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=6 NAME=DclDetachProcessPriority VALUE=\"!AZ\">\n\
<I>server,user</I></TD></TR>\n\
<TR><TH ALIGN=right>Strict CGI Output:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[CgiStrictOutput]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=CgiStrictOutput VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=CgiStrictOutput VALUE=disabled!AZ>disabled\n\
</TD><TD></TD></TR>\n\
<TR><TH ALIGN=right>Spawn Authorized Privileges:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DclSpawnAuthPriv]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=DclSpawnAuthPriv VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=DclSpawnAuthPriv VALUE=disabled!AZ>disabled\n\
</TD><TD></TD></TR>\n\
<TR><TH ALIGN=right>Gateway BG:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DclGatewayBg]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=DclGatewayBg VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=DclGatewayBg VALUE=disabled!AZ>disabled\n\
</TD><TD></TD></TR>\n\
<TR><TH ALIGN=right>Soft Limit:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DclSoftLimit]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=DclSoftLimit VALUE=!UL>\n\
<I>script processes</I></TD></TR>\n\
<TR><TH ALIGN=right>Hard Limit:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DclHardLimit]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=3 NAME=DclHardLimit VALUE=!UL>\n\
<I>script processes</I></TD></TR>\n\
<TR><TH ALIGN=right>Bit-Bucket Timeout:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DclBitBucketTimeout]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=8 NAME=DclBitBucketTimeout VALUE=!&@>\n\
<I>hh:mm:ss</I></TR>\n\
<TR><TH ALIGN=right>Zombie Life-Time:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DclZombieLifeTime]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=8 NAME=DclZombieLifeTime VALUE=!&@>\n</TR>\n\
<TR><TH ALIGN=right>CGIplus Life-Time:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DclCgiPlusLifeTime]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=8 NAME=DclCgiPlusLifeTime VALUE=!&@>\n</TR>\n\
<TR><TH ALIGN=right>DECnet Reuse Life-Time:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DECnetReuseLifeTime]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=8 NAME=DECnetReuseLifeTime VALUE=!&@>\n</TR>\n\
<TR><TH ALIGN=right>DECnet Connect List Limit:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DECnetConnectListMax]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=4 NAME=DECnetConnectListMax VALUE=!UL>\n\
<I>connections</I></TD></TR>\n\
<TR><TH ALIGN=right>Cleanup Scratch Max:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DclCleanupScratchMinutesMax]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=4 NAME=DclCleanupScratchMinutesMax VALUE=!UL>\n\
<I>minutes</I></TD></TR>\n\
<TR><TH ALIGN=right>Cleanup Older-than:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DclCleanupScratchMinutesOld]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=4 NAME=DclCleanupScratchMinutesOld VALUE=!UL>\n\
<I>minutes</I></TD></TR>\n\
<TR><TH ALIGN=left>Script Run-Time:</TH></TR>\n\
<TR><TD COLSPAN=2><I>\
Format: &quot;file-type [SPACE] verb&quot;<BR>\
(e.g. &quot;.PL [SPACE] PERL&quot; or &quot;.PL [SPACE] $PERL_EXE:PERL&quot;)\
</I>\
</TD></TR>\n\
<TR><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DclScriptRunTime]&#94;\">\n\
<TEXTAREA NAME=DclScriptRunTime ROWS=5 COLS=60 NOWRAP>";

   static char  ConfigSsiFao [] =
"</TEXTAREA>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Server-Side Includes</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -SSI-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TH ALIGN=right>SSI:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[SSI]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=SSI VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=SSI VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Exec:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[SSIexec]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=SSIexec VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=SSIexec VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Access Counting:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[SSIaccesses]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=SSIaccesses VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=SSIaccesses VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Max Size:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[SSISizeMax]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=4 NAME=SSISizeMax VALUE=!UL>\n\
<I>kBytes</I></TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Directory (Index of...)</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -DIRECTORY-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TH ALIGN=right>Access:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DirAccess]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=DirAccess VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=DirAccess VALUE=selective!AZ>selective\n\
<INPUT TYPE=radio NAME=DirAccess VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Layout:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DirLayout]&#32;&#32;\">\n\
<INPUT TYPE=text size=30 NAME=DirLayout VALUE=\"!AZ\">\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Listing &lt;BODY&gt;:</TH><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DirBodyTag]&#32;&#32;\">\n\
<INPUT TYPE=text size=40 NAME=DirBodyTag VALUE=\"!&;AZ\">\n\
<I>HTML tag</I></TD></TR>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>HTML Description:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DirDescriptionLines]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=6 NAME=DirDescriptionLines VALUE=!UL>\n\
<I>lines</I></TD></TR>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>&lt;META&gt; Info:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DirMetaInfo]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=DirMetaInfo VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=DirMetaInfo VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Owner:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DirOwner]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=DirOwner VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=DirOwner VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Pre-Expired:</TH><TD>\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DirPreExpired]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=DirPreExpired VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=DirPreExpired VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Wildcard:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DirWildcard]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=DirWildcard VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=DirWildcard VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>No Implied Wildcard:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DirNoImpliedWildcard]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=DirNoImpliedWildcard VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=DirNoImpliedWildcard VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Prot Violations Ignored:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DirNoPrivIgnore]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=DirNoPrivIgnore VALUE=enabled!AZ>enabled\n\
<INPUT TYPE=radio NAME=DirNoPrivIgnore VALUE=disabled!AZ>disabled\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Readme:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DirReadme]&#32;&#32;\">\n\
<INPUT TYPE=radio NAME=DirReadme VALUE=top!AZ>top\n\
<INPUT TYPE=radio NAME=DirReadme VALUE=bottom!AZ>bottom\n\
<INPUT TYPE=radio NAME=DirReadme VALUE=disabled!AZ>none\n\
</TD></TR>\n\
<TR><TH ALIGN=left>Readme Files:</TH></TR>\n\
<TR><TD COLSPAN=2><I>Format: &quot;file-name.file-type&quot; \
(e.g. README.HTML)</I></TD></TR>\n\
<TR><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[DirReadmeFile]&#94;\">\n\
<TEXTAREA NAME=DirReadmeFile ROWS=5 COLS=40 NOWRAP>";

   static char  ConfigIconsFao [] =
"</TEXTAREA>\n\
</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n\
<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH>Icons</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -ICONS-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TD COLSPAN=2><I>Format: &quot;icon-path [SPACE] \
alternative-text [SPACE] content-type&quot;</I></TD></TR>\n\
<TR><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AddIcon]&#94;\">\n\
<TEXTAREA NAME=AddIcon ROWS=7 COLS=60 NOWRAP>";

   static char  ConfigSpecialIconsFao [] =
"</TEXTAREA>\n\
</TD></TR>\n\
<TR><TH COLSPAN=2>Special Icons</TH></TR>\n\
<TR><TD COLSPAN=2><I>Format: &quot;icon-path [SPACE] \
alternative-text&quot;</I></TD></TR>\n\
<TR><TH ALIGN=right>Blank:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AddBlankIcon]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=40 NAME=AddBlankIcon VALUE=\"!&;AZ\">\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Default:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AddDefaultIcon]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=40 NAME=AddDefaultIcon VALUE=\"!&;AZ\">\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Directory:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AddDirIcon]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=40 NAME=AddDirIcon VALUE=\"!&;AZ\">\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Parent Directory:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AddParentIcon]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=40 NAME=AddParentIcon VALUE=\"!&;AZ\">\n\
</TD></TR>\n\
<TR><TH ALIGN=right>Unknown:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AddUnknownIcon]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=40 NAME=AddUnknownIcon VALUE=\"!&;AZ\">\n\
</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n";

   static char  ConfigContentTypesFao [] =
"<P><TABLE CELLPADDING=3 CELLSPACING=0 BORDER=1>\n\
<TR><TH COLSPAN=2>Content Types</TH></TR>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;&#94;# -CONTENT TYPES-&#94;\">\n\
<TR><TD>\n\
<TABLE CELLPADDING=3 CELLSPACING=0 BORDER=0>\n\
<TR><TD COLSPAN=2><I>Format: &quot;file-suffix &nbsp; \
content-type[;charset=] &nbsp; [/auto-script-path] &nbsp; \
description (to-end-of-line)&quot;</I></TD></TR>\n\
<TR><TD COLSPAN=2>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AddType]&#94;\">\n\
<TEXTAREA NAME=AddType ROWS=7 COLS=60 NOWRAP>";

   static char  AddMimeTypesFao [] =
"</TEXTAREA>\n\
</TD></TR>\n\
<TR><TH ALIGN=right>MIME.TYPES File:</TH><TD>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[AddMimeTypesFile]&#32;&#32;\">\n\
<INPUT TYPE=text SIZE=40 NAME=AddMimeTypesFile VALUE=\"!&;AZ\">\n\
</TD></TR>\n\
</TABLE>\n\
</TD></TR>\n\
</TABLE>\n";

   static char  RadioButtonChecked [] = " CHECKED",
                RadioButtonUnchecked [] = "";

   int  idx,
        status;
   unsigned short  Length;
   unsigned long  *vecptr;
   unsigned long  FaoVector [128];
   char  *cptr, *sptr, *zptr,
         *IconAltPtr,
         *IconAltEndPositionPtr,
         *IconAltStartPositionPtr,
         *IconUrlPtr,
         *IconTypePtr,
         *IconTypePositionPtr,
         *SpecialIconPtr;
   char  HtmlIconUrl [256],
         Scratch [256],
         SpecialIconBlank [SIZEOF_SPECIAL_ICON],
         SpecialIconDir [SIZEOF_SPECIAL_ICON],
         SpecialIconDefault [SIZEOF_SPECIAL_ICON],
         SpecialIconParent [SIZEOF_SPECIAL_ICON],
         SpecialIconUnknown [SIZEOF_SPECIAL_ICON],
         TimeCurrent [32];
   CONFIG_STRUCT  *cfptr;
   CONTENT_TYPE  ContentType;
   CONTENT_TYPE  *ctptr;
   ICON_TYPE  *itptr;

   /*********/
   /* begin */
   /*********/

   if (WATCHING(rqptr) && WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (rqptr, FI_LI, WATCH_MOD_CONFIG, "ConfigReviseNow()");

   /* get a pointer to the meta-config data */
   cfptr = mcptr->ConfigMetaPtr;

   rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN;
   RESPONSE_HEADER_200_HTML (rqptr);
   AdminPageTitle (rqptr, "Server Configuration");
   AdminMetaConReport (rqptr, mcptr, MetaGlobalConfigPtr);
   AdminMetaConSource (rqptr, mcptr, MetaGlobalConfigPtr, mcptr->IncludeFile);

   AdminMetaConBeginUpdateForm (rqptr);

   vecptr = FaoVector;

   /* services */
   if (ServiceLoadFromConfigFile)
   {
      *vecptr++ =
"<CENTER><B>(See &quot;Services&quot; Configuration)</B></CENTER>\n\
<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[Service]&#94;!AZ\">\n";
   }
   else
   {
      *vecptr++ =
"<INPUT TYPE=hidden name=hidden$lf VALUE=\"&#94;[Service]&#94;\">\n\
<TEXTAREA NAME=Service ROWS=5 COLS=60 NOWRAP>\
!AZ\
</TEXTAREA>\n";
   }                   \
   *vecptr++ = ConfigStringList (rqptr, cfptr->cfServer.ServicePtr, '\n');
   *vecptr++ = cfptr->cfServer.ServiceNotFoundUrl;

   /* general */
   if (cfptr->cfServer.InstanceMax == INSTANCE_PER_CPU)
      *vecptr++ = "CPU";
   else
   {
      *vecptr++ = "!UL";
      *vecptr++ = cfptr->cfServer.InstanceMax;
   }
   if (cfptr->cfServer.BusyLimit)
      *vecptr++ = cfptr->cfServer.BusyLimit;
   else
      *vecptr++ = DEFAULT_CONCURRENT_CONNECT_MAX;
   if (cfptr->cfServer.ListenBacklog)
      *vecptr++ = cfptr->cfServer.ListenBacklog;
   else
      *vecptr++ = DEFAULT_LISTEN_BACKLOG;
   *vecptr++ = cfptr->cfMisc.RequestHistory;
   *vecptr++ = cfptr->cfMisc.ActivityNumberOfDays;
   *vecptr++ = cfptr->cfContent.CharsetDefault;
   *vecptr++ = ConfigStringList (rqptr,
                  cfptr->cfContent.CharsetConvertPtr, '\n');
   REP_BOOL_RADIO (cfptr->cfMisc.MonitorEnabled)
   REP_BOOL_RADIO (cfptr->cfMisc.RegexEnabled)
   *vecptr++ = cfptr->cfServer.DefaultPort;
   *vecptr++ = cfptr->cfMisc.StreamLfConversionMaxKbytes;
   *vecptr++ = cfptr->cfScript.DefaultSearch;
   *vecptr++ = ConfigStringList (rqptr,
                  cfptr->cfScript.DefaultSearchExcludePtr, '\n');
   *vecptr++ = cfptr->cfMisc.PutMaxKbytes;
   *vecptr++ = cfptr->cfMisc.PutVersionLimit;
   if (cfptr == &Config)
      *vecptr++ = MapUrlUserNameCacheEntries;
   else
      *vecptr++ = cfptr->cfMisc.MapUserNameCacheEntries;
   if (cfptr == &Config)
      *vecptr++ = PersonaCacheEntries;
   else
      *vecptr++ = cfptr->cfMisc.PersonaCacheEntries;

   /* DNS host resolution */
   REP_BOOL_RADIO (cfptr->cfMisc.DnsLookupClient)
   REP_HHMMSS (cfptr->cfMisc.DnsLookupLifeTimeSeconds)
   *vecptr++ = cfptr->cfMisc.DnsLookupRetryCount;

   /* logging */
   REP_BOOL_RADIO (cfptr->cfLog.Enabled)
   *vecptr++ = cfptr->cfLog.Format;
   *vecptr++ = cfptr->cfLog.Naming;
   *vecptr++ = cfptr->cfLog.Period;
   REP_BOOL_RADIO (cfptr->cfLog.PerInstance)
   REP_BOOL_RADIO (cfptr->cfLog.PerService)
   REP_BOOL_RADIO (cfptr->cfLog.PerServiceHostOnly)
   *vecptr++ = cfptr->cfLog.FileName;
   *vecptr++ = cfptr->cfLog.ExtendBlocks;
   *vecptr++ = ConfigStringList (rqptr, cfptr->cfLog.ExcludeHostsPtr, '\n');
   REP_BOOL_RADIO (cfptr->cfTrack.Enabled)
   REP_BOOL_RADIO (cfptr->cfTrack.MultiSession)
   *vecptr++ = cfptr->cfTrack.Domain;

   status = NetWriteFaol (rqptr, ConfigGeneralFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

   /* OPCOM messages */
   for (idx = 0; ConfigOpcomTarget[idx].Number >= 0; idx++)
   {
      vecptr = FaoVector;
      *vecptr++ = ConfigOpcomTarget[idx].Name;
      *vecptr++ = (OpcomTarget == ConfigOpcomTarget[idx].Number);
      *vecptr++ = ConfigOpcomTarget[idx].Name;

      status = NetWriteFaol (rqptr, ConfigOpcomTargetFao, &FaoVector);
      if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);
   }

   vecptr = FaoVector;

   REP_BOOL_RADIO (cfptr->cfOpcom.Messages & OPCOM_ADMIN)
   REP_BOOL_RADIO (cfptr->cfOpcom.Messages & OPCOM_AUTHORIZATION)
   REP_BOOL_RADIO (cfptr->cfOpcom.Messages & OPCOM_CONTROL)
   REP_BOOL_RADIO (cfptr->cfOpcom.Messages & OPCOM_HTTPD)
   REP_BOOL_RADIO (cfptr->cfOpcom.Messages & OPCOM_PROXY_MAINT)

   /* cache */
   REP_BOOL_RADIO (cfptr->cfCache.Enabled)
   *vecptr++ = cfptr->cfCache.EntriesMax;
   *vecptr++ = cfptr->cfCache.TotalKBytesMax;
   *vecptr++ = cfptr->cfCache.FileKBytesMax;
   REP_HHMMSS (cfptr->cfCache.GuardSeconds)
   REP_HHMMSS (cfptr->cfCache.ValidateSeconds)
   *vecptr++ = cfptr->cfCache.FrequentHits;
   REP_HHMMSS (cfptr->cfCache.FrequentSeconds)

   /* timeouts */
   REP_HHMMSS (cfptr->cfTimeout.Input)
   REP_HHMMSS (cfptr->cfTimeout.Output)
   REP_HHMMSS (cfptr->cfTimeout.NoProgress)
   REP_HHMMSS (cfptr->cfTimeout.KeepAlive)

   /* buffer sizes */
   if (cfptr == &Config)
   {
      /* in-use values */
      *vecptr++ = DclSysCommandSize;
      *vecptr++ = DclSysOutputSize;
      *vecptr++ = DclCgiPlusInSize;
      *vecptr++ = DclCgiHeaderSize;
      *vecptr++ = NetReadBufferSize;
      *vecptr++ = OutputBufferSize;
   }
   else
   {
      /* file values */
      *vecptr++ = cfptr->cfBuffer.SizeDclCommand;
      *vecptr++ = cfptr->cfBuffer.SizeDclOutput;
      *vecptr++ = cfptr->cfBuffer.SizeDclCgiPlusIn;
      *vecptr++ = cfptr->cfBuffer.SizeDclCgiHeader;
      *vecptr++ = cfptr->cfBuffer.SizeNetRead;
      *vecptr++ = cfptr->cfBuffer.SizeNetWrite;
   }

   status = NetWriteFaol (rqptr, ConfigOpcomFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

   /*****************************/
   /* welcome (home page) files */
   /*****************************/

   for (idx = 0; idx < cfptr->cfContent.HomePageCount; idx++)
   {
      status = NetWriteFao (rqptr, "!&;AZ\n", cfptr->cfContent.HomePageArray[idx]);
      if (VMSnok (status)) ErrorNoticed (status, "NetWriteFao()", FI_LI);
   }

   /********/
   /* more */
   /********/

   vecptr = FaoVector;

   /* accept and reject hosts */
   *vecptr++ = ConfigStringList (rqptr, cfptr->cfServer.AcceptHostsPtr, '\n');
   *vecptr++ = ConfigStringList (rqptr, cfptr->cfServer.RejectHostsPtr, '\n');

   *vecptr++ = cfptr->cfServer.AdminEmail;
   if (cfptr->cfServer.Signature == CONFIG_SERVER_SIGNATURE_ON)
      *vecptr++ = " CHECKED";
   else
      *vecptr++ = "";
   if (cfptr->cfServer.Signature == CONFIG_SERVER_SIGNATURE_EMAIL)
      *vecptr++ = " CHECKED";
   else
      *vecptr++ = "";
   if (cfptr->cfServer.Signature == CONFIG_SERVER_SIGNATURE_OFF)
      *vecptr++ = " CHECKED";
   else
      *vecptr++ = "";
   *vecptr++ = cfptr->cfServer.ReportBodyTag;
   *vecptr++ = cfptr->cfServer.AdminBodyTag;
   REP_BOOL_RADIO (cfptr->cfReport.BasicOnly)
   REP_BOOL_RADIO (cfptr->cfReport.MetaInfoEnabled)
   *vecptr++ = cfptr->cfReport.ErrorReportPath;
   REP_BOOL_RADIO (cfptr->cfReport.ErrorRecommend)

   /* authorization */
   *vecptr++ = cfptr->cfAuth.CacheEntriesMax;
   *vecptr++ = cfptr->cfAuth.CacheEntrySize;
   *vecptr++ = cfptr->cfAuth.CacheMinutes;
   *vecptr++ = cfptr->cfAuth.RevalidateUserMinutes;
   REP_BOOL_RADIO (cfptr->cfAuth.RevalidateLoginCookie)
   *vecptr++ = cfptr->cfAuth.FailureLimit;
   REP_HHMMSS (cfptr->cfAuth.FailurePeriodSeconds)
   REP_HHMMSS (cfptr->cfAuth.FailureTimeoutSeconds)
   REP_BOOL_RADIO (cfptr->cfAuth.BasicEnabled)
   REP_BOOL_RADIO (cfptr->cfAuth.DigestEnabled)
   *vecptr++ = cfptr->cfAuth.DigestNonceGetLifeTime;
   *vecptr++ = cfptr->cfAuth.DigestNonceGetLifeTime;
   REP_BOOL_RADIO (cfptr->cfAuth.SysUafUseACME)
   REP_BOOL_RADIO (cfptr->cfAuth.SysUafAcceptExpPwd)
   *vecptr++ = cfptr->cfAuth.SysUafPwdExpUrl;

   /* proxy serving */
   REP_BOOL_RADIO (cfptr->cfProxy.ServingEnabled)
   REP_BOOL_RADIO (cfptr->cfProxy.CacheEnabled)
   REP_BOOL_RADIO (cfptr->cfProxy.UnknownRequestFields)
   if (cfptr->cfProxy.ForwardedBy == PROXY_FORWARDED_BY)
      *vecptr++ = "BY";
   else
   if (cfptr->cfProxy.ForwardedBy == PROXY_FORWARDED_FOR)
      *vecptr++ = "FOR";
   else
   if (cfptr->cfProxy.ForwardedBy == PROXY_FORWARDED_ADDRESS)
      *vecptr++ = "ADDRESS";
   else
      *vecptr++ = "disabled";
   if (cfptr->cfProxy.XForwardedFor == PROXY_XFORWARDEDFOR_ENABLED)
      *vecptr++ = "ENABLED";
   else
   if (cfptr->cfProxy.XForwardedFor == PROXY_XFORWARDEDFOR_UNKNOWN)
      *vecptr++ = "UNKNOWN";
   else
   if (cfptr->cfProxy.XForwardedFor == PROXY_XFORWARDEDFOR_ADDRESS)
      *vecptr++ = "ADDRESS";
   else
      *vecptr++ = "disabled";
   REP_BOOL_RADIO (cfptr->cfProxy.ReportLog)
   REP_BOOL_RADIO (cfptr->cfProxy.ReportCacheLog)
   *vecptr++ = cfptr->cfProxy.VerifyRecordMax;
   *vecptr++ = cfptr->cfProxy.HostLookupRetryCount;
   *vecptr++ = cfptr->cfProxy.CacheFileKBytesMax;
   *vecptr++ = cfptr->cfProxy.CacheNoReloadSeconds;
   *vecptr++ = cfptr->cfProxy.CacheReloadList;
   *vecptr++ = cfptr->cfProxy.CacheRoutineHourOfDayString;
   *vecptr++ = cfptr->cfProxy.CachePurgeList;
   if (cfptr->cfProxy.CacheDeviceDirOrg == PROXY_CACHE_DIR_ORG_FLAT256)
      *vecptr++ = "flat256";
   else
   if (cfptr->cfProxy.CacheDeviceDirOrg == PROXY_CACHE_DIR_ORG_64X64)
      *vecptr++ = "64x64";
   else
      *vecptr++ = "";
   *vecptr++ = cfptr->cfProxy.CacheDeviceCheckMinutes;
   *vecptr++ = cfptr->cfProxy.CacheDeviceMaxPercent;
   *vecptr++ = cfptr->cfProxy.CacheDevicePurgePercent;

   /* scripting */
   REP_BOOL_RADIO (cfptr->cfScript.Enabled)
   REP_BOOL_RADIO (cfptr->cfScript.DetachProcess)
   *vecptr++ = cfptr->cfScript.DetachProcessPriority;
   REP_BOOL_RADIO (cfptr->cfScript.CgiStrictOutput)
   REP_BOOL_RADIO (cfptr->cfScript.SpawnAuthPriv)
   REP_BOOL_RADIO (cfptr->cfScript.GatewayBg)
   *vecptr++ = cfptr->cfScript.ScriptProcessSoftLimit;
   *vecptr++ = cfptr->cfScript.ScriptProcessHardLimit;
   REP_HHMMSS (cfptr->cfScript.BitBucketTimeout)
   REP_HHMMSS (cfptr->cfScript.ZombieLifeTime)
   REP_HHMMSS (cfptr->cfScript.CgiPlusLifeTime)
   REP_HHMMSS (cfptr->cfScript.DECnetReuseLifeTime)
   *vecptr++ = cfptr->cfScript.DECnetConnectListMax;
   *vecptr++ = cfptr->cfScript.CleanupScratchMinutesMax;
   *vecptr++ = cfptr->cfScript.CleanupScratchMinutesOld;

   status = NetWriteFaol (rqptr, ConfigAcceptFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

   /****************/
   /* script types */
   /****************/

   for (idx = 0; idx < cfptr->cfScript.RunTimeCount; idx++)
   {
      vecptr = FaoVector;

      cptr = sptr = cfptr->cfScript.RunTime[idx].String;
      /* length of and location of the file type */
      while (*cptr && *cptr != ';') cptr++;
      *vecptr++ = cptr - sptr;
      *vecptr++ = sptr;
      /* location of verb */
      cptr += 2;
      *vecptr++ = cptr;

      status = NetWriteFaol (rqptr, "!#&;AZ !&;AZ\n", &FaoVector);
      if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);
   }

   /********/
   /* more */
   /********/

   vecptr = FaoVector;

   /* SSI (.shtml) */
   REP_BOOL_RADIO (cfptr->cfSsi.Enabled)
   REP_BOOL_RADIO (cfptr->cfSsi.ExecEnabled)
   REP_BOOL_RADIO (cfptr->cfSsi.AccessesEnabled)
   *vecptr++ = cfptr->cfSsi.SizeMax;

   /* directory */
   if (cfptr->cfDir.Access)
   {
      *vecptr++ = " CHECKED";
      *vecptr++ = "";
      *vecptr++ = "";
   }
   else
   if (cfptr->cfDir.AccessSelective)
   {
      *vecptr++ = "";
      *vecptr++ = " CHECKED";
      *vecptr++ = "";
   }
   else
   {
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = " CHECKED";
   }
   *vecptr++ = cfptr->cfDir.DefaultLayout;
   *vecptr++ = cfptr->cfDir.BodyTag;
   *vecptr++ = cfptr->cfDir.DescriptionLines;
   REP_BOOL_RADIO (cfptr->cfDir.MetaInfoEnabled)
   REP_BOOL_RADIO (cfptr->cfDir.OwnerEnabled)
   REP_BOOL_RADIO (cfptr->cfDir.PreExpired)
   REP_BOOL_RADIO (cfptr->cfDir.WildcardEnabled)
   REP_BOOL_RADIO (cfptr->cfDir.NoImpliedWildcard)
   REP_BOOL_RADIO (cfptr->cfDir.NoPrivIgnore)
   if (cfptr->cfDir.ReadMeTop)
   {
      *vecptr++ = " CHECKED";
      *vecptr++ = "";
      *vecptr++ = "";
   }
   else
   if (cfptr->cfDir.ReadMeBottom)
   {
      *vecptr++ = "";
      *vecptr++ = " CHECKED";
      *vecptr++ = "";
   }
   else
   {
      *vecptr++ = "";
      *vecptr++ = "";
      *vecptr++ = " CHECKED";
   }
   REP_BOOL_RADIO (cfptr->cfDir.WildcardEnabled)

   status = NetWriteFaol (rqptr, ConfigSsiFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

   /****************/
   /* readme files */
   /****************/

   for (idx = 0; idx < cfptr->cfDir.ReadMeFileCount; idx++)
   {
      status = NetWriteFao (rqptr, "!&@!&;AZ",
                            idx ? "\n" : "", cfptr->cfDir.ReadMeFileArray[idx]);
      if (VMSnok (status)) ErrorNoticed (status, "NetWriteFao()", FI_LI);
   }

   /*********/
   /* icons */
   /*********/

   status = NetWriteFaol (rqptr, ConfigIconsFao, NULL);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

   SpecialIconBlank[0] = SpecialIconDefault[0] = SpecialIconDir[0] =
      SpecialIconParent[0] = SpecialIconUnknown[0] = '\n';
   SpecialIconBlank[1] = SpecialIconDefault[0] = SpecialIconDir[1] =
      SpecialIconParent[1] = SpecialIconUnknown[1] = '\0';

   for (itptr = cfptr->cfContent.IconListHeadPtr;
        itptr;
        itptr = itptr->NextPtr)
   {
      if (itptr->FromMimeTypes) continue;

      SpecialIconPtr = NULL;
      if (strsame (itptr->ContentTypePtr, ConfigContentTypeBlank, -1))
         SpecialIconPtr = SpecialIconBlank;
      else
      if (strsame (itptr->ContentTypePtr, ConfigContentTypeDir, -1))
         SpecialIconPtr = SpecialIconDir;
      else
      if (strsame (itptr->ContentTypePtr, ConfigContentTypeDefaultIcon, -1))
         SpecialIconPtr = SpecialIconDefault;
      else
      if (strsame (itptr->ContentTypePtr, ConfigContentTypeParent, -1))
         SpecialIconPtr = SpecialIconParent;
      else
      if (strsame (itptr->ContentTypePtr, ConfigContentTypeUnknown, -1))
         SpecialIconPtr = SpecialIconUnknown;

      vecptr = FaoVector;
      *vecptr++ = itptr->IconUriPtr;
      *vecptr++ = itptr->AltTextPtr;
      if (!SpecialIconPtr)
      {
         *vecptr++ = itptr->ContentTypePtr;
         status = NetWriteFaol (rqptr, "!AZ  !AZ  !&;AZ\n", &FaoVector);
      }
      else
      {
         WriteFaol (SpecialIconPtr, SIZEOF_SPECIAL_ICON, NULL,
                    "!AZ  !AZ", &FaoVector);
         if (SpecialIconPtr == SpecialIconBlank)
         {
            /* convert blanks in the alternate text into underscores */
            for (cptr = SpecialIconPtr; *cptr && !ISLWS(*cptr); cptr++);
            if (ISLWS(*cptr)) cptr++;
            if (ISLWS(*cptr)) cptr++;
            sptr = itptr->AltTextPtr;
            while (*sptr++) *cptr++ = '_';
         }
      }
      if (VMSnok (status)) ErrorNoticed (status, "NetWriteFao()", FI_LI);
   }

   vecptr = FaoVector;
   *vecptr++ = SpecialIconBlank;
   *vecptr++ = SpecialIconDefault;
   *vecptr++ = SpecialIconDir;
   *vecptr++ = SpecialIconParent;
   *vecptr++ = SpecialIconUnknown;

   status = NetWriteFaol (rqptr, ConfigSpecialIconsFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

   /*****************/
   /* content types */
   /*****************/

   status = NetWriteFaol (rqptr, ConfigContentTypesFao, NULL);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

   for (ctptr = cfptr->cfContent.ContentInfoListHeadPtr;
        ctptr;
        ctptr = ctptr->NextPtr)
   {
      if (ctptr->FromMimeTypes) continue;

      vecptr = &FaoVector;
      *vecptr++ = ctptr->SuffixPtr;
      if (!strchr (ctptr->ContentTypePtr, ';'))
         *vecptr++ = "  !AZ";
      else
         *vecptr++ = "  \"!AZ\"";
      *vecptr++ = ctptr->ContentTypePtr;
      if (ctptr->FtpMode)
      {
         *vecptr++ = "(FTP:!&C)";
         *vecptr++ = ctptr->FtpMode;
      }
      else
         *vecptr++ = "";
      if (ctptr->AutoScriptNamePtr[0])
      {
         *vecptr++ = "  !AZ";
         *vecptr++ = ctptr->AutoScriptNamePtr;
      }
      else
         *vecptr++ = "";
      *vecptr++ = "  !&;AZ";
      if (ctptr->TypeUnknown)
         *vecptr++ = cfptr->cfContent.ContentTypeDefaultPtr;
      else
         *vecptr++ = ctptr->DescriptionPtr;

      status = NetWriteFaol (rqptr, "!AZ!&@!&@!&@!&@\n", &FaoVector);
      if (VMSnok (status)) ErrorNoticed (status, "NetWriteFao()", FI_LI);
   }

   vecptr = FaoVector;
   *vecptr++ = cfptr->cfContent.MimeTypesFileName;
   status = NetWriteFaol (rqptr, AddMimeTypesFao, &FaoVector);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

   AdminMetaConEndUpdateForm (rqptr);

   status = NetWriteFaol (rqptr, "</BODY>\n</HTML>\n", NULL);
   if (VMSnok (status)) ErrorNoticed (status, "NetWriteFaol()", FI_LI);

#undef REP_BOOL_RADIO
#undef REP_HHMMSS
}

/*****************************************************************************/
/*
Takes a comma-separated list of elements and returns a pointer to a dynamically
allocated string with that list reformated for inclusion in HTML.  The
separator is intended to be either a newline or comma character.  If a comma an
extra space is added after each (so that when displayed in HTML it will be
wrapped).  If a carriage-return ('\r'), it is converted into an HTML <BR> (new
line) tag so that each appears on a new line in areas where '\n' doesn't behave
that way.
*/

char* ConfigStringList
(
REQUEST_STRUCT *rqptr,
char *ListPtr,
char Separator
)
{
   int  Length;
   char  *cptr, *sptr, *zptr;
   char  ListBuffer [8192],
         HtmlListBuffer [8192];

   /*********/
   /* begin */
   /*********/
   
   if (WATCHING(rqptr) && WATCH_MODULE(WATCH_MOD_CONFIG))
      WatchThis (rqptr, FI_LI, WATCH_MOD_CONFIG,
                 "ConfigStringList() !&Z !UL", ListPtr, Separator);

   if (!ListPtr) return ("");

   zptr = (sptr = ListBuffer) + sizeof(ListBuffer);
   for (cptr = ListPtr; *cptr && sptr < zptr; cptr++)
   {
      if (*cptr == STRING_LIST_CHAR)
         *sptr++ = Separator;
      else
         *sptr++ = *cptr;
      if (Separator == ',' && *cptr == STRING_LIST_CHAR && sptr < zptr)
         *sptr++ = ' ';
   }
   if (sptr >= zptr) return (ConfigStringOverflow);
   *sptr = '\0';

   /* now HTML-escape */
   zptr = (sptr = HtmlListBuffer) + sizeof(HtmlListBuffer);
   for (cptr = ListBuffer; *cptr && sptr < zptr; cptr++)
   {
      if (*cptr == '\r')
      {
         *sptr++ = '<';
         if (sptr < zptr) *sptr++ = 'B';
         if (sptr < zptr) *sptr++ = 'R';
         if (sptr < zptr) *sptr++ = '>';
      }
      else
      {
         switch (*cptr)
         {
            case '<' :
               if (sptr+4 >= zptr) return (ConfigStringOverflow);
               memcpy (sptr, "&lt;", 4); sptr += 4; break;
            case '>' :
               if (sptr+4 >= zptr) return (ConfigStringOverflow);
               memcpy (sptr, "&gt;", 4); sptr += 4; break;
            case '&' :
               if (sptr+5 >= zptr) return (ConfigStringOverflow);
               memcpy (sptr, "&amp;", 5); sptr += 5; break;
            case '\"' :
               if (sptr+6 >= zptr) return (ConfigStringOverflow);
               memcpy (sptr, "&quot;", 6); sptr += 6; break;
            default :
               *sptr++ = *cptr;
         }
      }

      if (Separator == ',' && *cptr == STRING_LIST_CHAR && sptr < zptr)
         *sptr++ = ' ';
   }
   if (sptr >= zptr) return (ConfigStringOverflow);
   *sptr = '\0';
   Length = sptr - HtmlListBuffer; 

   sptr = VmGetHeap (rqptr, Length+1);
   memcpy (sptr, HtmlListBuffer, Length+1);
   if (Debug) fprintf (stdout, "|%s|\n", sptr);

   return (sptr);
}

/*****************************************************************************/
