diff options
Diffstat (limited to 'os/config.c')
-rw-r--r-- | os/config.c | 610 |
1 files changed, 610 insertions, 0 deletions
diff --git a/os/config.c b/os/config.c new file mode 100644 index 0000000..5648e5b --- /dev/null +++ b/os/config.c @@ -0,0 +1,610 @@ +/* $Xorg: config.c,v 1.4 2001/02/09 02:05:44 xorgcvs Exp $ */ +/* +Copyright 1987, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + * Copyright 1990, 1991 Network Computing Devices; + * Portions Copyright 1987 by Digital Equipment Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the names of Network Computing Devices, + * or Digital not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Network Computing Devices, or Digital + * make no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, OR DIGITAL BE + * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $NCDId: @(#)config.c,v 4.6 1991/07/09 14:08:09 lemke Exp $ + * + */ + +#include <stdio.h> +#include <ctype.h> +#include <X11/Xos.h> +#include "misc.h" +#include "configstr.h" +#include "osdep.h" +#include "globals.h" +#include "access.h" + +static char *font_catalogue = NULL; + +static char *config_set_int(), + *config_set_bool(), + *config_set_catalogue(), + *config_set_glyph_caching_mode(), + *config_set_list(), + *config_set_file(), + *config_set_resolutions(), + *config_set_snf_format(); + +/* these need to be in lower case and alphabetical order so a + * binary search lookup can be used + */ +static ConfigOptionRec config_options[] = { + {"alternate-servers", config_set_list}, + {"catalogue", config_set_catalogue}, + {"client-limit", config_set_int}, + {"clone-self", config_set_bool}, + {"default-point-size", config_set_int}, + {"default-resolutions", config_set_resolutions}, + {"deferglyphs", config_set_glyph_caching_mode}, + {"error-file", config_set_file}, + {"port", config_set_int}, + {"server-number", config_set_int}, + {"snf-format", config_set_snf_format}, + {"trusted-clients", config_set_list}, + {"use-syslog", config_set_bool}, + {(char *) 0, 0}, +}; + +char *ConfigErrors[] = { + "", + "CONFIG: insufficient memory to load configuration file \"%s\"\n", + "CONFIG: can't open configuration file \"%s\"\n", + "CONFIG: error reading configuration file \"%s\"\n", + "CONFIG: bad value \"%s\" for parameter \"%s\"\n", + "CONFIG: unknown parameter \"%s\"\n", + "CONFIG: missing '=' after parameter \"%s\"\n", + "CONFIG: value out of range for parameter \"%s\"\n", + "CONFIG: syntax error near parameter \"%s\"\n", + "CONFIG: missing value for parameter \"%s\"\n", + "CONFIG: extra value for parameter \"%s\"\n", +}; + +#define iseol(c) ((c) == '\n' || (c) == '\r' || (c) == '\f') +#define skip_whitespace(c) while(isspace(*(c)) || *(c) == ',') (c)++; +#define skip_val(c) while(!isspace(*(c)) && *(c) != ',' && *(c) != '\0')\ + (c) ++; +#define skip_list_val(c) while(!isspace(*(c)) && *(c) != '\0')\ + (c) ++; +#define blank_comment(c) while (!iseol(*(c)) && *(c) != '\0') \ + *(c)++= ' '; + +static char * +next_assign(c) + char *c; +{ + int nesting = 0; + + while (*c != '\0') { + if (*c == '(') + nesting++; + else if (*c == ')') + nesting--; + else if (*c == '=' && nesting == 0) + return c; + c++; + } + return (char *) 0; +} + +static void +strip_comments(data) + char *data; +{ + char *c; + + c = data; + while ((c = strchr(c, '#')) != NULL) { + if (c == data || *(c - 1) != '\\') { + blank_comment(c); + } else { + c++; + } + } +} + +static ConfigOptionPtr +match_param_name(name) + char *name; +{ + int pos, + rc, + low, + high; + + low = 0; + high = sizeof(config_options) / sizeof(ConfigOptionRec) - 2; + pos = high >> 1; + + while (low <= high) { + rc = strcmp(name, config_options[pos].parm_name); + if (rc == 0) { + return &config_options[pos]; + } else if (rc < 0) { + high = pos - 1; + } else { + low = pos + 1; + } + pos = ((high + low) >> 1); + } + return 0; +} + +static int +parse_config(data) + char *data; +{ + char *c, + *val, + *next_eq, + *consumed, + *p; + char param_name[64]; + Bool equals_missing; + ConfigOptionPtr param; + + c = data; + skip_whitespace(c); + + while (*c != '\0') { + equals_missing = FALSE; + + /* get parm name in lower case */ + p = c; + while (isalnum(*c) || *c == '-') { + if (isupper(*c)) + *c = tolower(*c); + c++; + } + memmove( param_name, p, min(sizeof(param_name), (int) (c - p))); + param_name[(int) (c - p)] = '\0'; + + /* check for junk */ + if (!isspace(*c) && *c != '=') { + ErrorF(ConfigErrors[CONFIG_ERR_SYNTAX], param_name); + /* eat garbage */ + while (!isspace(*c) && *c != '=' && *c != '\0') + c++; + } + skip_whitespace(c); + if (*c != '=') { + ErrorF(ConfigErrors[CONFIG_ERR_NOEQUALS], param_name); + equals_missing = TRUE; + } else { + c++; + } + + skip_whitespace(c); + + /* find next assignment to guess where the value ends */ + if ((next_eq = next_assign(c)) != NULL) { + /* back up over whitespace */ + for (val = next_eq - 1; val >= c && + (isspace(*val) || *val == ','); + val--); + + /* back over parm name */ + for (; val >= c && (isalnum(*val) || *val == '-'); val--); + + if (val <= c) { + /* no value, ignore */ + ErrorF(ConfigErrors[CONFIG_ERR_NOVALUE], param_name); + continue; + } + *val = '\0'; + } else if (*c == '\0') { + /* no value, ignore */ + ErrorF(ConfigErrors[CONFIG_ERR_NOVALUE], param_name); + continue; + } + /* match parm name */ + if (equals_missing) { + equals_missing = FALSE; + } else if ((param = match_param_name(param_name)) == NULL) { + ErrorF(ConfigErrors[CONFIG_ERR_UNKNOWN], param_name); + } else { + consumed = (param->set_func) (param, c); + + skip_whitespace(consumed); + if (*consumed != '\0') { + ErrorF(ConfigErrors[CONFIG_ERR_EXTRAVALUE], + param_name); + } + } + + if (next_eq != NULL) + c = val + 1; + else /* last setting */ + break; + } + return FSSuccess; +} + +/* + * handles anything that should be set once the file is parsed + */ +void +SetConfigValues() +{ + int err, + num; + + err = SetFontCatalogue(font_catalogue, &num); + if (err != FSSuccess) { + FatalError("Element #%d (starting at 0) of font path is bad or has a bad font:\n\"%s\"\n", + num, font_catalogue); + } + InitErrors(); + fsfree((char *) font_catalogue); + font_catalogue = NULL; +} + +int +ReadConfigFile(filename) + char *filename; +{ + FILE *fp; + int ret; + int len; + char *data; + + data = (char *) fsalloc(CONFIG_MAX_FILESIZE); + if (!data) { + ErrorF(ConfigErrors[CONFIG_ERR_MEMORY], filename); + return FSBadAlloc; + } + if ((fp = fopen(filename, "r")) == NULL) { + fsfree(data); + ErrorF(ConfigErrors[CONFIG_ERR_OPEN], filename); + return FSBadName; + } + ret = fread(data, sizeof(char), CONFIG_MAX_FILESIZE, fp); + if (ret <= 0) { + fsfree(data); + (void) fclose(fp); + ErrorF(ConfigErrors[CONFIG_ERR_READ], filename); + return FSBadName; + } + len = ftell(fp); + len = min(len, CONFIG_MAX_FILESIZE); + data[len] = '\0'; /* NULL terminate the data */ + + (void) fclose(fp); + + strip_comments(data); + ret = parse_config(data); + + fsfree(data); + + return ret; +} + +struct nameVal { + char *name; + int val; +}; + +static char * +config_parse_nameVal (c, ret, pval, name_val) + char *c; + int *ret; + int *pval; + struct nameVal *name_val; +{ + char *start, + t; + int i, + len; + + start = c; + skip_val(c); + t = *c; + *c = '\0'; + len = c - start; + + for (i = 0; name_val[i].name; i++) { + if (!strncmpnocase(start, name_val[i].name, len)) { + *pval = name_val[i].val; + *ret = 0; + *c = t; + return c; + } + } + ErrorF(ConfigErrors[CONFIG_ERR_VALUE], start); + *c = t; + *ret = -1; + return c; +} + +static char * +config_parse_bool (c, ret, pval) + char *c; + int *ret; + Bool *pval; +{ + static struct nameVal bool_val[] = { + "yes", TRUE, + "on", TRUE, + "1", TRUE, + "true", TRUE, + "no", FALSE, + "off", FALSE, + "0", FALSE, + "false", FALSE, + (char *) 0, 0, + }; + return config_parse_nameVal (c, ret, pval, bool_val); +} + +static char * +config_parse_int(c, ret, pval) + char *c; + int *ret; + int *pval; +{ + char *start, + t; + + start = c; + while (*c != '\0' && !isspace(*c) && *c != ',') { + if (!isdigit(*c)) { /* error */ + skip_val(c); + t = *c; + *c = '\0'; + ErrorF(ConfigErrors[CONFIG_ERR_VALUE], start); + *ret = -1; + *c = t; + return c; + } + c++; + } + t = *c; + *c = '\0'; + *ret = 0; + *pval = atoi(start); + *c = t; + return c; +} + + +/* config option sets */ +/* these have to know how to do the real work and tweak the proper things */ +static char * +config_set_int(parm, val) + ConfigOptionPtr parm; + char *val; +{ + int ival, + ret; + extern int ListenPort; + extern void SetDefaultPointSize(); + + val = config_parse_int(val, &ret, &ival); + if (ret == -1) + return val; + + /* now do individual attribute checks */ + if (!strcmp(parm->parm_name, "port")) { + ListenPort = ival; + } else if (!strcmp(parm->parm_name, "client-limit")) { + AccessSetConnectionLimit(ival); + } else if (!strcmp(parm->parm_name, "default-point-size")) { + SetDefaultPointSize(ival); + } + return val; +} + +static char * +config_set_bool(parm, val) + ConfigOptionPtr parm; + char *val; +{ + int + ret; + Bool bval; + extern int ClientLimit; + extern Bool UseSyslog, + CloneSelf; + + val = config_parse_bool(val, &ret, &bval); + if (ret == -1) + return val; + + /* now do individual attribute checks */ + if (!strcmp(parm->parm_name, "use-syslog")) { + UseSyslog = bval; + } else if (!strcmp(parm->parm_name, "clone-self")) { + CloneSelf = bval; + } + return val; +} + +static char * +config_set_file(parm, val) + ConfigOptionPtr parm; + char *val; +{ + extern char ErrorFile[]; + char *start = val, + t; + + skip_val(val); + t = *val; + *val = '\0'; + if (!strcmp(parm->parm_name, "error-file")) { + memmove( ErrorFile, start, val - start + 1); + } + *val = t; + return val; +} + +static char * +config_set_catalogue(parm, val) + ConfigOptionPtr parm; + char *val; +{ + char *b; + + if (!strcmp(parm->parm_name, "catalogue")) { + /* stash it for later */ + fsfree((char *) font_catalogue); /* dump any previous one */ + b = font_catalogue = (char *) fsalloc(strlen(val) + 1); + if (!font_catalogue) + FatalError("Insufficent memory for font catalogue\n"); + while (*val) { /* remove all the gunk */ + if (!isspace(*val)) { + *b++ = *val; + } + val++; + } + *b = '\0'; + } + return val; +} + +static char * +config_set_list(parm, val) + ConfigOptionPtr parm; + char *val; +{ + char *start = val, + t; + + skip_list_val(val); + t = *val; + *val = '\0'; + if (!strcmp(parm->parm_name, "alternate-servers")) { + SetAlternateServers(start); + } + *val = t; + return val; +} + +static char * +config_set_glyph_caching_mode(parm, val) + ConfigOptionPtr parm; + char *val; +{ + char *start = val, + t; + + skip_list_val(val); + t = *val; + *val = '\0'; + if (!strcmp(parm->parm_name, "deferglyphs")) { + ParseGlyphCachingMode(start); + } + *val = t; + return val; +} + +static char * +config_set_resolutions(parm, val) + ConfigOptionPtr parm; + char *val; +{ + char *start = val, + t; + int err; + + skip_list_val(val); + t = *val; + *val = '\0'; + if (!strcmp(parm->parm_name, "default-resolutions")) { + err = SetDefaultResolutions(start); + if (err != FSSuccess) { + FatalError("Bogus resolution list \"%s\"\n", start); + } + } + *val = t; + return val; +} + + +static char * +config_parse_endian(c, ret, pval) + char *c; + int *ret; + int *pval; +{ + static struct nameVal endian_val[] = { + "lsb", LSBFirst, + "little", LSBFirst, + "lsbfirst", LSBFirst, + "msb", MSBFirst, + "big", MSBFirst, + "msbfirst", MSBFirst, + (char *) 0, 0, + }; + return config_parse_nameVal (c, ret, pval, endian_val); +} + +/* ARGSUSED */ +static char * +config_set_snf_format (parm, val) + ConfigOptionPtr parm; + char *val; +{ + int bit, byte, glyph, scan; + int ret; + + val = config_parse_endian (val, &ret, &bit); + if (ret == -1) + return val; + skip_whitespace (val); + val = config_parse_endian (val, &ret, &byte); + if (ret == -1) + return val; + skip_whitespace (val); + val = config_parse_int (val, &ret, &glyph); + if (ret == -1) + return val; + skip_whitespace (val); + val = config_parse_int (val, &ret, &scan); + if (ret == -1) + return val; + SnfSetFormat (bit, byte, glyph, scan); + return val; +} |