home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / fonts / server / os / config.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-25  |  12.8 KB  |  567 lines

  1. /* $XConsortium: config.c,v 1.6 91/07/25 12:15:45 keith Exp $ */
  2. /*
  3.  * Copyright 1990, 1991 Network Computing Devices;
  4.  * Portions Copyright 1987 by Digital Equipment Corporation and the
  5.  * Massachusetts Institute of Technology
  6.  *
  7.  * Permission to use, copy, modify, and distribute this protoype software
  8.  * and its documentation to Members and Affiliates of the MIT X Consortium
  9.  * any purpose and without fee is hereby granted, provided
  10.  * that the above copyright notice appear in all copies and that both that
  11.  * copyright notice and this permission notice appear in supporting
  12.  * documentation, and that the names of Network Computing Devices, Digital or
  13.  * MIT not be used in advertising or publicity pertaining to distribution of
  14.  * the software without specific, written prior permission.
  15.  *
  16.  * NETWORK COMPUTING DEVICES, DIGITAL AND MIT DISCLAIM ALL WARRANTIES WITH
  17.  * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  18.  * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, DIGITAL OR MIT BE
  19.  * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  20.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  21.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  22.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  23.  *
  24.  * $NCDId: @(#)config.c,v 4.6 1991/07/09 14:08:09 lemke Exp $
  25.  *
  26.  */
  27.  
  28. #include    <stdio.h>
  29. #include    <ctype.h>
  30. #include    <X11/Xos.h>
  31. #include    "misc.h"
  32. #include    "configstr.h"
  33. #include    "osdep.h"
  34. #include    "globals.h"
  35. #include    "access.h"
  36.  
  37. static char *font_catalogue = NULL;
  38.  
  39. static char *config_set_int(),
  40.            *config_set_bool(),
  41.            *config_set_catalogue(),
  42.            *config_set_list(),
  43.            *config_set_file(),
  44.            *config_set_resolutions(),
  45.        *config_set_snf_format();
  46.  
  47. /* these need to be in lower case and alphabetical order so a
  48.  * binary search lookup can be used
  49.  */
  50. static ConfigOptionRec config_options[] = {
  51.     {"alternate-servers", config_set_list},
  52.     {"catalogue", config_set_catalogue},
  53.     {"client-limit", config_set_int},
  54.     {"clone-self", config_set_bool},
  55.     {"default-point-size", config_set_int},
  56.     {"default-resolutions", config_set_resolutions},
  57.     {"error-file", config_set_file},
  58.     {"port", config_set_int},
  59.     {"server-number", config_set_int},
  60.     {"snf-format", config_set_snf_format},
  61.     {"trusted-clients", config_set_list},
  62.     {"use-syslog", config_set_bool},
  63.     {(char *) 0, 0},
  64. };
  65.  
  66. char       *ConfigErrors[] = {
  67.     "",
  68.     "CONFIG: insufficient memory to load configuration file \"%s\"\n",
  69.     "CONFIG: can't open configuration file \"%s\"\n",
  70.     "CONFIG: error reading configuration file \"%s\"\n",
  71.     "CONFIG: bad value \"%s\" for parameter \"%s\"\n",
  72.     "CONFIG: unknown parameter \"%s\"\n",
  73.     "CONFIG: missing '=' after parameter \"%s\"\n",
  74.     "CONFIG: value out of range for parameter \"%s\"\n",
  75.     "CONFIG: syntax error near parameter \"%s\"\n",
  76.     "CONFIG: missing value for parameter \"%s\"\n",
  77.     "CONFIG: extra value for parameter \"%s\"\n",
  78. };
  79.  
  80. #define    iseol(c)    ((c) == '\n' || (c) == '\r' || (c) == '\f')
  81. #define    skip_whitespace(c)    while(isspace(*(c)) || *(c) == ',') (c)++;
  82. #define    skip_val(c)    while(!isspace(*(c)) && *(c) != ',' && *(c) != '\0')\
  83.                         (c) ++;
  84. #define    skip_list_val(c)    while(!isspace(*(c)) && *(c) != '\0')\
  85.                         (c) ++;
  86. #define    blank_comment(c)    while (!iseol(*(c)) && *(c) != '\0')    \
  87.                         *(c)++= ' ';
  88.  
  89. static char *
  90. next_assign(c)
  91.     char       *c;
  92. {
  93.     int         nesting = 0;
  94.  
  95.     while (*c != '\0') {
  96.     if (*c == '(')
  97.         nesting++;
  98.     else if (*c == ')')
  99.         nesting--;
  100.     else if (*c == '=' && nesting == 0)
  101.         return c;
  102.     c++;
  103.     }
  104.     return (char *) 0;
  105. }
  106.  
  107. static void
  108. strip_comments(data)
  109.     char       *data;
  110. {
  111.     char       *c;
  112.  
  113.     c = data;
  114.     while ((c = index(c, '#')) != NULL) {
  115.     if (c == data || *(c - 1) != '\\') {
  116.         blank_comment(c);
  117.     } else {
  118.         c++;
  119.     }
  120.     }
  121. }
  122.  
  123. static      ConfigOptionPtr
  124. match_param_name(name)
  125.     char       *name;
  126. {
  127.     int         pos,
  128.                 rc,
  129.                 low,
  130.                 high;
  131.  
  132.     low = 0;
  133.     high = sizeof(config_options) / sizeof(ConfigOptionRec) - 2;
  134.     pos = high >> 1;
  135.  
  136.     while (low <= high) {
  137.     rc = strcmp(name, config_options[pos].parm_name);
  138.     if (rc == 0) {
  139.         return &config_options[pos];
  140.     } else if (rc < 0) {
  141.         high = pos - 1;
  142.     } else {
  143.         low = pos + 1;
  144.     }
  145.     pos = ((high + low) >> 1);
  146.     }
  147.     return 0;
  148. }
  149.  
  150. static int
  151. parse_config(data)
  152.     char       *data;
  153. {
  154.     char       *c,
  155.                *val,
  156.                *next_eq,
  157.                *consumed,
  158.                *p;
  159.     char        param_name[64];
  160.     Bool        equals_missing;
  161.     ConfigOptionPtr param;
  162.  
  163.     c = data;
  164.     skip_whitespace(c);
  165.  
  166.     while (*c != '\0') {
  167.     equals_missing = FALSE;
  168.  
  169.     /* get parm name in lower case */
  170.     p = c;
  171.     while (isalnum(*c) || *c == '-') {
  172.         if (isupper(*c))
  173.         *c = tolower(*c);
  174.         c++;
  175.     }
  176.     bcopy(p, param_name, min(sizeof(param_name), (int) (c - p)));
  177.     param_name[(int) (c - p)] = '\0';
  178.  
  179.     /* check for junk */
  180.     if (!isspace(*c) && *c != '=') {
  181.         ErrorF(ConfigErrors[CONFIG_ERR_SYNTAX], param_name);
  182.         /* eat garbage */
  183.         while (!isspace(*c) && *c != '=' && *c != '\0')
  184.         c++;
  185.     }
  186.     skip_whitespace(c);
  187.     if (*c != '=') {
  188.         ErrorF(ConfigErrors[CONFIG_ERR_NOEQUALS], param_name);
  189.         equals_missing = TRUE;
  190.     } else {
  191.         c++;
  192.     }
  193.  
  194.     skip_whitespace(c);
  195.  
  196.     /* find next assignment to guess where the value ends */
  197.     if ((next_eq = next_assign(c)) != NULL) {
  198.         /* back up over whitespace */
  199.         for (val = next_eq - 1; val >= c &&
  200.             (isspace(*val) || *val == ',');
  201.             val--);
  202.  
  203.         /* back over parm name */
  204.         for (; val >= c && (isalnum(*val) || *val == '-'); val--);
  205.  
  206.         if (val <= c) {
  207.         /* no value, ignore */
  208.         ErrorF(ConfigErrors[CONFIG_ERR_NOVALUE], param_name);
  209.         continue;
  210.         }
  211.         *val = '\0';
  212.     } else if (*c == '\0') {
  213.         /* no value, ignore */
  214.         ErrorF(ConfigErrors[CONFIG_ERR_NOVALUE], param_name);
  215.         continue;
  216.     }
  217.     /* match parm name */
  218.     if (equals_missing) {
  219.         equals_missing = FALSE;
  220.     } else if ((param = match_param_name(param_name)) == NULL) {
  221.         ErrorF(ConfigErrors[CONFIG_ERR_UNKNOWN], param_name);
  222.     } else {
  223.         consumed = (param->set_func) (param, c);
  224.  
  225.         skip_whitespace(consumed);
  226.         if (*consumed != '\0') {
  227.         ErrorF(ConfigErrors[CONFIG_ERR_EXTRAVALUE],
  228.                param_name);
  229.         }
  230.     }
  231.  
  232.     if (next_eq != NULL)
  233.         c = val + 1;
  234.     else            /* last setting */
  235.         break;
  236.     }
  237.     return FSSuccess;
  238. }
  239.  
  240. /*
  241.  * handles anything that should be set once the file is parsed
  242.  */
  243. void
  244. SetConfigValues()
  245. {
  246.     int         err,
  247.                 num;
  248.  
  249.     err = SetFontCatalogue(font_catalogue, &num);
  250.     if (err != FSSuccess) {
  251.     FatalError("Element #%d of font path \"%s\" is bad\n",
  252.            num, font_catalogue);
  253.     }
  254.     InitErrors();
  255.     fsfree((char *) font_catalogue);
  256.     font_catalogue = NULL;
  257. }
  258.  
  259. int
  260. ReadConfigFile(filename)
  261.     char       *filename;
  262. {
  263.     FILE       *fp;
  264.     int         ret;
  265.     int         len;
  266.     char       *data;
  267.  
  268.     data = (char *) fsalloc(CONFIG_MAX_FILESIZE);
  269.     if (!data) {
  270.     ErrorF(ConfigErrors[CONFIG_ERR_MEMORY], filename);
  271.     return -1;
  272.     }
  273.     if ((fp = fopen(filename, "r")) == NULL) {
  274.     ErrorF(ConfigErrors[CONFIG_ERR_OPEN], filename);
  275.     return -1;
  276.     }
  277.     ret = fread(data, sizeof(char), CONFIG_MAX_FILESIZE, fp);
  278.     if (ret <= 0) {
  279.     ErrorF(ConfigErrors[CONFIG_ERR_READ], filename);
  280.     return -1;
  281.     }
  282.     len = ftell(fp);
  283.     len = min(len, CONFIG_MAX_FILESIZE);
  284.     data[len] = '\0';        /* NULL terminate the data */
  285.  
  286.     (void) fclose(fp);
  287.  
  288.     strip_comments(data);
  289.     ret = parse_config(data);
  290.  
  291.     fsfree(data);
  292.  
  293.     return ret;
  294. }
  295.  
  296. struct nameVal {
  297.     char       *name;
  298.     int         val;
  299. };
  300.  
  301. static char *
  302. config_parse_nameVal (c, ret, pval, name_val)
  303.     char       *c;
  304.     int        *ret;
  305.     int        *pval;
  306.     struct nameVal   *name_val;
  307. {
  308.     char       *start,
  309.                 t;
  310.     int         i,
  311.                 len;
  312.  
  313.     start = c;
  314.     skip_val(c);
  315.     t = *c;
  316.     *c = '\0';
  317.     len = c - start;
  318.  
  319.     for (i = 0; name_val[i].name; i++) {
  320.     if (!strncmpnocase(start, name_val[i].name, len)) {
  321.         *pval = name_val[i].val;
  322.         *ret = 0;
  323.         *c = t;
  324.         return c;
  325.     }
  326.     }
  327.     ErrorF(ConfigErrors[CONFIG_ERR_VALUE], start);
  328.     *c = t;
  329.     *ret = -1;
  330.     return c;
  331. }
  332.  
  333. static char *
  334. config_parse_bool (c, ret, pval)
  335.     char    *c;
  336.     int        *ret;
  337.     Bool    *pval;
  338. {
  339.     static struct nameVal bool_val[] = {
  340.             "yes", TRUE,
  341.             "on", TRUE,
  342.             "1", TRUE,
  343.             "true", TRUE,
  344.             "no", FALSE,
  345.             "off", FALSE,
  346.             "0", FALSE,
  347.             "false", FALSE,
  348.             (char *) 0, 0,
  349.     };
  350.     return config_parse_nameVal (c, ret, pval, bool_val);
  351. }
  352.  
  353. static char *
  354. config_parse_int(c, ret, pval)
  355.     char       *c;
  356.     int        *ret;
  357.     int        *pval;
  358. {
  359.     char       *start,
  360.                 t;
  361.  
  362.     start = c;
  363.     while (*c != '\0' && !isspace(*c) && *c != ',') {
  364.     if (!isdigit(*c)) {    /* error */
  365.         skip_val(c);
  366.         t = *c;
  367.         *c = '\0';
  368.         ErrorF(ConfigErrors[CONFIG_ERR_VALUE], start);
  369.         *ret = -1;
  370.         *c = t;
  371.         return c;
  372.     }
  373.     c++;
  374.     }
  375.     t = *c;
  376.     *c = '\0';
  377.     *ret = 0;
  378.     *pval = atoi(start);
  379.     *c = t;
  380.     return c;
  381. }
  382.  
  383.  
  384. /* config option sets */
  385. /* these have to know how to do the real work and tweak the proper things */
  386. static char *
  387. config_set_int(parm, val)
  388.     ConfigOptionPtr parm;
  389.     char       *val;
  390. {
  391.     int         ival,
  392.                 ret;
  393.     extern int  ListenPort;
  394.     extern void SetDefaultPointSize();
  395.  
  396.     val = config_parse_int(val, &ret, &ival);
  397.     if (ret == -1)
  398.     return val;
  399.  
  400.     /* now do individual attribute checks */
  401.     if (!strcmp(parm->parm_name, "port")) {
  402.     ListenPort = ival;
  403.     } else if (!strcmp(parm->parm_name, "client-limit")) {
  404.     AccessSetConnectionLimit(ival);
  405.     } else if (!strcmp(parm->parm_name, "default-point-size")) {
  406.     SetDefaultPointSize(ival);
  407.     }
  408.     return val;
  409. }
  410.  
  411. static char *
  412. config_set_bool(parm, val)
  413.     ConfigOptionPtr parm;
  414.     char       *val;
  415. {
  416.     int
  417.                 ret;
  418.     Bool        bval;
  419.     extern int  ClientLimit;
  420.     extern Bool UseSyslog,
  421.                 CloneSelf;
  422.  
  423.     val = config_parse_bool(val, &ret, &bval);
  424.     if (ret == -1)
  425.     return val;
  426.  
  427.     /* now do individual attribute checks */
  428.     if (!strcmp(parm->parm_name, "use-syslog")) {
  429.     UseSyslog = bval;
  430.     } else if (!strcmp(parm->parm_name, "clone-self")) {
  431.     CloneSelf = bval;
  432.     }
  433.     return val;
  434. }
  435.  
  436. static char *
  437. config_set_file(parm, val)
  438.     ConfigOptionPtr parm;
  439.     char       *val;
  440. {
  441.     extern char ErrorFile[];
  442.     char       *start = val,
  443.                 t;
  444.  
  445.     skip_val(val);
  446.     t = *val;
  447.     *val = '\0';
  448.     if (!strcmp(parm->parm_name, "error-file")) {
  449.     bcopy(start, ErrorFile, val - start + 1);
  450.     }
  451.     *val = t;
  452.     return val;
  453. }
  454.  
  455. static char *
  456. config_set_catalogue(parm, val)
  457.     ConfigOptionPtr parm;
  458.     char       *val;
  459. {
  460.     char       *b;
  461.  
  462.     if (!strcmp(parm->parm_name, "catalogue")) {
  463.     /* stash it for later */
  464.     fsfree((char *) font_catalogue);    /* dump any previous one */
  465.     b = font_catalogue = (char *) fsalloc(strlen(val) + 1);
  466.     if (!font_catalogue)
  467.         FatalError("Insufficent memory for font catalogue\n");
  468.     while (*val) {        /* remove all the gunk */
  469.         if (!isspace(*val)) {
  470.         *b++ = *val;
  471.         }
  472.         val++;
  473.     }
  474.     *b = '\0';
  475.     }
  476.     return val;
  477. }
  478.  
  479. static char *
  480. config_set_list(parm, val)
  481.     ConfigOptionPtr parm;
  482.     char       *val;
  483. {
  484.     char       *start = val,
  485.                 t;
  486.  
  487.     skip_list_val(val);
  488.     t = *val;
  489.     *val = '\0';
  490.     if (!strcmp(parm->parm_name, "alternate-servers")) {
  491.     SetAlternateServers(start);
  492.     }
  493.     *val = t;
  494.     return val;
  495. }
  496.  
  497. static char *
  498. config_set_resolutions(parm, val)
  499.     ConfigOptionPtr parm;
  500.     char       *val;
  501. {
  502.     char       *start = val,
  503.                 t;
  504.     int         err;
  505.  
  506.     skip_list_val(val);
  507.     t = *val;
  508.     *val = '\0';
  509.     if (!strcmp(parm->parm_name, "default-resolutions")) {
  510.     err = SetDefaultResolutions(start);
  511.     if (err != FSSuccess) {
  512.         FatalError("Bogus resolution list \"%s\"\n", start);
  513.     }
  514.     }
  515.     *val = t;
  516.     return val;
  517. }
  518.  
  519.  
  520. static char *
  521. config_parse_endian(c, ret, pval)
  522.     char       *c;
  523.     int        *ret;
  524.     int        *pval;
  525. {
  526.     static struct nameVal endian_val[] = {
  527.     "lsb",    LSBFirst,
  528.     "little",   LSBFirst,
  529.     "lsbfirst", LSBFirst,
  530.     "msb",        MSBFirst,
  531.     "big",        MSBFirst,
  532.     "msbfirst", MSBFirst,
  533.     (char *) 0, 0,
  534.     };
  535.     return config_parse_nameVal (c, ret, pval, endian_val);
  536. }
  537.  
  538. static char *
  539. config_set_snf_format (parm, val)
  540.     ConfigOptionPtr parm;
  541.     char        *val;
  542. {
  543.     char    *start = val,
  544.         t;
  545.     int        err;
  546.     int        bit, byte, glyph, scan;
  547.     int        ret;
  548.     
  549.     val = config_parse_endian (val, &ret, &bit);
  550.     if (ret == -1)
  551.     return val;
  552.     skip_whitespace (val);
  553.     val = config_parse_endian (val, &ret, &byte);
  554.     if (ret == -1)
  555.     return val;
  556.     skip_whitespace (val);
  557.     val = config_parse_int (val, &ret, &glyph);
  558.     if (ret == -1)
  559.     return val;
  560.     skip_whitespace (val);
  561.     val = config_parse_int (val, &ret, &scan);
  562.     if (ret == -1)
  563.     return val;
  564.     SnfSetFormat (bit, byte, glyph, scan);
  565.     return val;
  566. }
  567.