diff options
Diffstat (limited to 'cfg.c')
-rw-r--r-- | cfg.c | 892 |
1 files changed, 459 insertions, 433 deletions
@@ -1,4 +1,4 @@ -/* $Id: cfg.c,v 1.46 2005/05/02 05:15:46 reinelt Exp $^ +/* $Id: cfg.c,v 1.47 2005/05/08 04:32:43 reinelt Exp $^ * * config file stuff * @@ -23,6 +23,9 @@ * * * $Log: cfg.c,v $ + * Revision 1.47 2005/05/08 04:32:43 reinelt + * CodingStyle added and applied + * * Revision 1.46 2005/05/02 05:15:46 reinelt * make busy-flag checking configurable for LCD-Linux driver * @@ -293,538 +296,561 @@ #endif typedef struct { - char *key; - char *val; - int lock; + char *key; + char *val; + int lock; } ENTRY; -static char *Config_File=NULL; -static ENTRY *Config=NULL; -static int nConfig=0; +static char *Config_File = NULL; +static ENTRY *Config = NULL; +static int nConfig = 0; /* bsearch compare function for config entries */ -static int c_lookup (const void *a, const void *b) +static int c_lookup(const void *a, const void *b) { - char *key=(char*)a; - ENTRY *entry=(ENTRY*)b; + char *key = (char *) a; + ENTRY *entry = (ENTRY *) b; - return strcasecmp(key, entry->key); + return strcasecmp(key, entry->key); } /* qsort compare function for variables */ -static int c_sort (const void *a, const void *b) +static int c_sort(const void *a, const void *b) { - ENTRY *ea=(ENTRY*)a; - ENTRY *eb=(ENTRY*)b; + ENTRY *ea = (ENTRY *) a; + ENTRY *eb = (ENTRY *) b; - return strcasecmp(ea->key, eb->key); + return strcasecmp(ea->key, eb->key); } /* remove leading and trailing whitespace */ -static char *strip (char *s, const int strip_comments) +static char *strip(char *s, const int strip_comments) { - char *p; - - while (isblank(*s)) s++; - for (p=s; *p; p++) { - if (*p=='"') do p++; while (*p && *p!='\n' && *p!='"'); - if (*p=='\'') do p++; while (*p && *p!='\n' && *p!='\''); - if (*p=='\n' || (strip_comments && *p=='#' && (p==s || *(p-1)!='\\'))) { - *p='\0'; - break; + char *p; + + while (isblank(*s)) + s++; + for (p = s; *p; p++) { + if (*p == '"') + do + p++; + while (*p && *p != '\n' && *p != '"'); + if (*p == '\'') + do + p++; + while (*p && *p != '\n' && *p != '\''); + if (*p == '\n' || (strip_comments && *p == '#' && (p == s || *(p - 1) != '\\'))) { + *p = '\0'; + break; + } } - } - for (p--; p>s && isblank(*p); p--) *p='\0'; - return s; + for (p--; p > s && isblank(*p); p--) + *p = '\0'; + return s; } /* unquote a string */ -static char *dequote (char *string) +static char *dequote(char *string) { - int quote=0; - char *s = string; - char *p = string; - - do { - if (*s == '\'') { - quote = !quote; - *p++ = *s; - } - else if (quote && *s == '\\') { - s++; - if (*s >= '0' && *s <= '7') { - int n; - unsigned int c = 0; - sscanf (s, "%3o%n", &c, &n); - if (c == 0 || c > 255) { - error ("WARNING: illegal '\\' in <%s>", string); + int quote = 0; + char *s = string; + char *p = string; + + do { + if (*s == '\'') { + quote = !quote; + *p++ = *s; + } else if (quote && *s == '\\') { + s++; + if (*s >= '0' && *s <= '7') { + int n; + unsigned int c = 0; + sscanf(s, "%3o%n", &c, &n); + if (c == 0 || c > 255) { + error("WARNING: illegal '\\' in <%s>", string); + } else { + *p++ = c; + s += n - 1; + } + } else { + *p++ = *s; + } } else { - *p++ = c; - s += n-1; + *p++ = *s; } - } else { - *p++ = *s; - } - } - else { - *p++ = *s; - } - } while (*s++); - - return string; + } while (*s++); + + return string; } /* which if a string contains only valid chars */ /* i.e. start with a char and contains chars and nums */ -static int validchars (const char *string) +static int validchars(const char *string) { - const char *c; - - for (c=string; *c; c++) { - /* first and following chars */ - if ((*c>='A' && *c<='Z') || (*c>='a' && *c<='z') || (*c=='_')) continue; - /* only following chars */ - if ((c>string) && ((*c>='0' && *c<='9') || (*c=='.') || (*c=='-'))) continue; - return 0; - } - return 1; + const char *c; + + for (c = string; *c; c++) { + /* first and following chars */ + if ((*c >= 'A' && *c <= 'Z') || (*c >= 'a' && *c <= 'z') || (*c == '_')) + continue; + /* only following chars */ + if ((c > string) && ((*c >= '0' && *c <= '9') || (*c == '.') || (*c == '-'))) + continue; + return 0; + } + return 1; } -static void cfg_add (const char *section, const char *key, const char *val, const int lock) +static void cfg_add(const char *section, const char *key, const char *val, const int lock) { - char *buffer; - ENTRY *entry; - - /* allocate buffer */ - buffer=malloc(strlen(section)+strlen(key)+2); - *buffer='\0'; - - /* prepare section.key */ - if (section!=NULL && *section!='\0') { - strcpy(buffer, section); - strcat(buffer, "."); - } - strcat (buffer, key); - - /* does the key already exist? */ - entry=bsearch(buffer, Config, nConfig, sizeof(ENTRY), c_lookup); - - if (entry!=NULL) { - if (entry->lock>lock) return; - debug ("Warning: key <%s>: value <%s> overwritten with <%s>", buffer, entry->val, val); - free (buffer); - if (entry->val) free (entry->val); - entry->val=dequote(strdup(val)); - return; - } - - nConfig++; - Config=realloc(Config, nConfig*sizeof(ENTRY)); - Config[nConfig-1].key=buffer; - Config[nConfig-1].val=dequote(strdup(val)); - Config[nConfig-1].lock=lock; - - qsort(Config, nConfig, sizeof(ENTRY), c_sort); + char *buffer; + ENTRY *entry; + + /* allocate buffer */ + buffer = malloc(strlen(section) + strlen(key) + 2); + *buffer = '\0'; + + /* prepare section.key */ + if (section != NULL && *section != '\0') { + strcpy(buffer, section); + strcat(buffer, "."); + } + strcat(buffer, key); + + /* does the key already exist? */ + entry = bsearch(buffer, Config, nConfig, sizeof(ENTRY), c_lookup); + + if (entry != NULL) { + if (entry->lock > lock) + return; + debug("Warning: key <%s>: value <%s> overwritten with <%s>", buffer, entry->val, val); + free(buffer); + if (entry->val) + free(entry->val); + entry->val = dequote(strdup(val)); + return; + } + + nConfig++; + Config = realloc(Config, nConfig * sizeof(ENTRY)); + Config[nConfig - 1].key = buffer; + Config[nConfig - 1].val = dequote(strdup(val)); + Config[nConfig - 1].lock = lock; + + qsort(Config, nConfig, sizeof(ENTRY), c_sort); } -int cfg_cmd (const char *arg) +int cfg_cmd(const char *arg) { - char *key, *val; - char buffer[256]; - - strncpy (buffer, arg, sizeof(buffer)); - key=strip(buffer, 0); - for (val=key; *val; val++) { - if (*val=='=') { - *val++='\0'; - break; + char *key, *val; + char buffer[256]; + + strncpy(buffer, arg, sizeof(buffer)); + key = strip(buffer, 0); + for (val = key; *val; val++) { + if (*val == '=') { + *val++ = '\0'; + break; + } } - } - if (*key=='\0' || *val=='\0') return -1; - if (!validchars(key)) return -1; - cfg_add ("", key, val, 1); - return 0; + if (*key == '\0' || *val == '\0') + return -1; + if (!validchars(key)) + return -1; + cfg_add("", key, val, 1); + return 0; } -char *cfg_list (const char *section) +char *cfg_list(const char *section) { - int i, len; - char *key, *list; - - /* calculate key length */ - len=strlen(section)+1; - - /* prepare search key */ - key=malloc(len+1); - strcpy (key, section); - strcat (key, "."); - - /* start with empty string */ - list=malloc(1); - *list='\0'; - - /* search matching entries */ - for (i=0; i<nConfig; i++) { - if (strncasecmp(Config[i].key, key, len)==0) { - list=realloc(list, strlen(list)+strlen(Config[i].key)-len+2); - if (*list!='\0') strcat (list, "|"); - strcat (list, Config[i].key+len); + int i, len; + char *key, *list; + + /* calculate key length */ + len = strlen(section) + 1; + + /* prepare search key */ + key = malloc(len + 1); + strcpy(key, section); + strcat(key, "."); + + /* start with empty string */ + list = malloc(1); + *list = '\0'; + + /* search matching entries */ + for (i = 0; i < nConfig; i++) { + if (strncasecmp(Config[i].key, key, len) == 0) { + list = realloc(list, strlen(list) + strlen(Config[i].key) - len + 2); + if (*list != '\0') + strcat(list, "|"); + strcat(list, Config[i].key + len); + } } - } - - free (key); - return list; + + free(key); + return list; } -static char *cfg_lookup (const char *section, const char *key) +static char *cfg_lookup(const char *section, const char *key) { - int len; - char *buffer; - ENTRY *entry; - - /* calculate key length */ - len=strlen(key)+1; - if (section!=NULL) - len+=strlen(section)+1; - - /* allocate buffer */ - buffer=malloc(len); - *buffer='\0'; - - /* prepare section:key */ - if (section!=NULL && *section!='\0') { - strcpy(buffer, section); - strcat(buffer, "."); - } - strcat (buffer, key); - - /* search entry */ - entry=bsearch(buffer, Config, nConfig, sizeof(ENTRY), c_lookup); - - /* free buffer again */ - free (buffer); - - if (entry!=NULL) - return entry->val; - - return NULL; + int len; + char *buffer; + ENTRY *entry; + + /* calculate key length */ + len = strlen(key) + 1; + if (section != NULL) + len += strlen(section) + 1; + + /* allocate buffer */ + buffer = malloc(len); + *buffer = '\0'; + + /* prepare section:key */ + if (section != NULL && *section != '\0') { + strcpy(buffer, section); + strcat(buffer, "."); + } + strcat(buffer, key); + + /* search entry */ + entry = bsearch(buffer, Config, nConfig, sizeof(ENTRY), c_lookup); + + /* free buffer again */ + free(buffer); + + if (entry != NULL) + return entry->val; + + return NULL; } -char *cfg_get_raw (const char *section, const char *key, const char *defval) +char *cfg_get_raw(const char *section, const char *key, const char *defval) { - char *val=cfg_lookup(section, key); - - if (val!=NULL) return val; - return (char *)defval; + char *val = cfg_lookup(section, key); + + if (val != NULL) + return val; + return (char *) defval; } -char *cfg_get (const char *section, const char *key, const char *defval) +char *cfg_get(const char *section, const char *key, const char *defval) { - char *expression; - char *retval; - void *tree = NULL; - RESULT result = {0, 0, 0, NULL}; - - expression=cfg_lookup(section, key); - - if (expression!=NULL) { - if (*expression=='\0') return ""; - if (Compile(expression, &tree)==0 && Eval(tree, &result)==0) { - retval=strdup(R2S(&result)); - DelTree(tree); - DelResult(&result); - return(retval); + char *expression; + char *retval; + void *tree = NULL; + RESULT result = { 0, 0, 0, NULL }; + + expression = cfg_lookup(section, key); + + if (expression != NULL) { + if (*expression == '\0') + return ""; + if (Compile(expression, &tree) == 0 && Eval(tree, &result) == 0) { + retval = strdup(R2S(&result)); + DelTree(tree); + DelResult(&result); + return (retval); + } + DelTree(tree); + DelResult(&result); } - DelTree(tree); - DelResult(&result); - } - if (defval) return strdup(defval); - return NULL; + if (defval) + return strdup(defval); + return NULL; } -int cfg_number (const char *section, const char *key, const int defval, const int min, const int max, int *value) +int cfg_number(const char *section, const char *key, const int defval, const int min, const int max, int *value) { - char *expression; - void *tree = NULL; - RESULT result = {0, 0, 0, NULL}; - - /* start with default value */ - /* in case of an (uncatched) error, you have the */ - /* default value set, which may be handy... */ - *value=defval; - - expression=cfg_get_raw(section, key, NULL); - if (expression==NULL || *expression=='\0') { - return 0; - } - - if (Compile(expression, &tree) != 0) { - DelTree(tree); - return -1; - } - if (Eval(tree, &result) != 0) { + char *expression; + void *tree = NULL; + RESULT result = { 0, 0, 0, NULL }; + + /* start with default value */ + /* in case of an (uncatched) error, you have the */ + /* default value set, which may be handy... */ + *value = defval; + + expression = cfg_get_raw(section, key, NULL); + if (expression == NULL || *expression == '\0') { + return 0; + } + + if (Compile(expression, &tree) != 0) { + DelTree(tree); + return -1; + } + if (Eval(tree, &result) != 0) { + DelTree(tree); + DelResult(&result); + return -1; + } + *value = R2N(&result); DelTree(tree); DelResult(&result); - return -1; - } - *value=R2N(&result); - DelTree (tree); - DelResult(&result); - - if (*value<min) { - error ("bad '%s' value '%d' in %s, minimum is %d", key, *value, cfg_source(), min); - *value=min; - return -1; - } - - if (max > min && max != -1 && *value > max) { - error ("bad '%s' value '%d' in %s, maximum is %d", key, *value, cfg_source(), max); - *value=max; - return -1; - } - - return 1; + + if (*value < min) { + error("bad '%s' value '%d' in %s, minimum is %d", key, *value, cfg_source(), min); + *value = min; + return -1; + } + + if (max > min && max != -1 && *value > max) { + error("bad '%s' value '%d' in %s, maximum is %d", key, *value, cfg_source(), max); + *value = max; + return -1; + } + + return 1; } static int cfg_check_source(const char *file) { - /* as passwords and commands are stored in the config file, - * we will check that: - * - file is a normal file (or /dev/null) - * - file owner is owner of program - * - file is not accessible by group - * - file is not accessible by other - */ - - struct stat stbuf; - uid_t uid, gid; - int error; - - uid = geteuid(); - gid = getegid(); - - if (stat(file, &stbuf) == -1) { - error ("stat(%s) failed: %s", file, strerror(errno)); - return -1; - } - if (S_ISCHR(stbuf.st_mode) && strcmp(file, "/dev/null") == 0) - return 0; - - error=0; - if (!S_ISREG(stbuf.st_mode)) { - error ("security error: '%s' is not a regular file", file); - error=-1; - } - if (stbuf.st_uid != uid || stbuf.st_gid != gid) { - error ("security error: owner and/or group of '%s' don't match", file); - error=-1; - } - if (stbuf.st_mode & S_IRWXG || stbuf.st_mode & S_IRWXO) { - error ("security error: group or other have access to '%s'", file); - error=-1; - } - return error; + /* as passwords and commands are stored in the config file, + * we will check that: + * - file is a normal file (or /dev/null) + * - file owner is owner of program + * - file is not accessible by group + * - file is not accessible by other + */ + + struct stat stbuf; + uid_t uid, gid; + int error; + + uid = geteuid(); + gid = getegid(); + + if (stat(file, &stbuf) == -1) { + error("stat(%s) failed: %s", file, strerror(errno)); + return -1; + } + if (S_ISCHR(stbuf.st_mode) && strcmp(file, "/dev/null") == 0) + return 0; + + error = 0; + if (!S_ISREG(stbuf.st_mode)) { + error("security error: '%s' is not a regular file", file); + error = -1; + } + if (stbuf.st_uid != uid || stbuf.st_gid != gid) { + error("security error: owner and/or group of '%s' don't match", file); + error = -1; + } + if (stbuf.st_mode & S_IRWXG || stbuf.st_mode & S_IRWXO) { + error("security error: group or other have access to '%s'", file); + error = -1; + } + return error; } -static int cfg_read (const char *file) +static int cfg_read(const char *file) { - FILE *stream; - char buffer[256]; - char section[256]; - char *line, *key, *val, *end; - int section_open, section_close; - int error, lineno; - - stream=fopen (file, "r"); - if (stream==NULL) { - error ("open(%s) failed: %s", file, strerror(errno)); - return -1; - } - - /* start with empty section */ - strcpy(section, ""); - - error=0; - lineno=0; - while ((line=fgets(buffer,256,stream))!=NULL) { - - /* increment line number */ - lineno++; - - /* skip empty lines */ - if (*(line=strip(line, 1))=='\0') continue; - - /* reset section flags */ - section_open=0; - section_close=0; - - /* key is first word */ - key=line; - - /* search first blank between key and value */ - for (val=line; *val; val++) { - if (isblank(*val)) { - *val++='\0'; - break; - } + FILE *stream; + char buffer[256]; + char section[256]; + char *line, *key, *val, *end; + int section_open, section_close; + int error, lineno; + + stream = fopen(file, "r"); + if (stream == NULL) { + error("open(%s) failed: %s", file, strerror(errno)); + return -1; } - /* strip value */ - val=strip(val, 1); + /* start with empty section */ + strcpy(section, ""); - /* search end of value */ - if (*val) for (end=val; *(end+1); end++); - else end=val; + error = 0; + lineno = 0; + while ((line = fgets(buffer, 256, stream)) != NULL) { - /* if last char is '{', a section has been opened */ - if (*end=='{') { - section_open=1; - *end='\0'; - val=strip(val, 0); - } + /* increment line number */ + lineno++; - /* provess "value" in double-quotes */ - if (*val=='"' && *end=='"') { - *end='\0'; - val++; - } + /* skip empty lines */ + if (*(line = strip(line, 1)) == '\0') + continue; - /* if key is '}', a section has been closed */ - if (strcmp(key, "}")==0) { - section_close=1; - *key='\0'; - } + /* reset section flags */ + section_open = 0; + section_close = 0; - /* sanity check: '}' should be the only char in a line */ - if (section_close && (section_open || *val!='\0')) { - error ("error in config file '%s' line %d: garbage after '}'", file, lineno); - error=1; - break; - } - - /* check key for valid chars */ - if (!validchars(key)) { - error ("error in config file '%s' line %d: key '%s' is invalid", file, lineno, key); - error=1; - break; - } + /* key is first word */ + key = line; - /* on section-open, check value for valid chars */ - if (section_open && !validchars(val)) { - error ("error in config file '%s' line %d: section '%s' is invalid", file, lineno, val); - error=1; - break; - } + /* search first blank between key and value */ + for (val = line; *val; val++) { + if (isblank(*val)) { + *val++ = '\0'; + break; + } + } - /* on section-open, append new section name */ - if (section_open) { - /* is the section[] array big enough? */ - if (strlen(section)+strlen(key)+3 > sizeof(section)) { - error ("error in config file '%s' line %d: section buffer overflow", file, lineno); - error=1; - break; - } - if (*section!='\0') strcat (section, "."); - strcat (section, key); - if (*val!='\0') { - strcat (section, ":"); - strcat (section, val); - } - continue; - } + /* strip value */ + val = strip(val, 1); + + /* search end of value */ + if (*val) + for (end = val; *(end + 1); end++); + else + end = val; + + /* if last char is '{', a section has been opened */ + if (*end == '{') { + section_open = 1; + *end = '\0'; + val = strip(val, 0); + } + + /* provess "value" in double-quotes */ + if (*val == '"' && *end == '"') { + *end = '\0'; + val++; + } + + /* if key is '}', a section has been closed */ + if (strcmp(key, "}") == 0) { + section_close = 1; + *key = '\0'; + } + + /* sanity check: '}' should be the only char in a line */ + if (section_close && (section_open || *val != '\0')) { + error("error in config file '%s' line %d: garbage after '}'", file, lineno); + error = 1; + break; + } + + /* check key for valid chars */ + if (!validchars(key)) { + error("error in config file '%s' line %d: key '%s' is invalid", file, lineno, key); + error = 1; + break; + } + + /* on section-open, check value for valid chars */ + if (section_open && !validchars(val)) { + error("error in config file '%s' line %d: section '%s' is invalid", file, lineno, val); + error = 1; + break; + } + + /* on section-open, append new section name */ + if (section_open) { + /* is the section[] array big enough? */ + if (strlen(section) + strlen(key) + 3 > sizeof(section)) { + error("error in config file '%s' line %d: section buffer overflow", file, lineno); + error = 1; + break; + } + if (*section != '\0') + strcat(section, "."); + strcat(section, key); + if (*val != '\0') { + strcat(section, ":"); + strcat(section, val); + } + continue; + } + + /* on section-close, remove last section name */ + if (section_close) { + /* sanity check: section already empty? */ + if (*section == '\0') { + error("error in config file '%s' line %d: unmatched closing brace", file, lineno); + error = 1; + break; + } + + end = strrchr(section, '.'); + if (end == NULL) + *section = '\0'; + else + *end = '\0'; + continue; + } + + /* finally: add key */ + cfg_add(section, key, val, 0); - /* on section-close, remove last section name */ - if (section_close) { - /* sanity check: section already empty? */ - if (*section=='\0') { - error ("error in config file '%s' line %d: unmatched closing brace", file, lineno); - error=1; - break; - } - - end=strrchr(section, '.'); - if (end==NULL) - *section='\0'; - else - *end='\0'; - continue; } - /* finally: add key */ - cfg_add (section, key, val, 0); - - } - - /* sanity check: are the braces balanced? */ - if (!error && *section!='\0') { - error ("error in config file '%s' line %d: unbalanced braces", file, lineno); - error=1; - } + /* sanity check: are the braces balanced? */ + if (!error && *section != '\0') { + error("error in config file '%s' line %d: unbalanced braces", file, lineno); + error = 1; + } - fclose (stream); + fclose(stream); - return -error; + return -error; } -int cfg_init (const char *file) +int cfg_init(const char *file) { - if (cfg_check_source(file) == -1) { - return -1; - } - - if (cfg_read(file)<0) return -1; - - if (Config_File) free (Config_File); - Config_File=strdup(file); - - return 0; + if (cfg_check_source(file) == -1) { + return -1; + } + + if (cfg_read(file) < 0) + return -1; + + if (Config_File) + free(Config_File); + Config_File = strdup(file); + + return 0; } -char *cfg_source (void) +char *cfg_source(void) { - if (Config_File) - return Config_File; - else - return ""; + if (Config_File) + return Config_File; + else + return ""; } -int cfg_exit (void) +int cfg_exit(void) { - int i; - for (i=0; i<nConfig; i++) { - if (Config[i].key) free (Config[i].key); - if (Config[i].val) free (Config[i].val); - } - - if (Config) { - free (Config); - Config=NULL; - } - - if (Config_File) { - free (Config_File); - Config_File=NULL; - } - - return 0; -} + int i; + for (i = 0; i < nConfig; i++) { + if (Config[i].key) + free(Config[i].key); + if (Config[i].val) + free(Config[i].val); + } + + if (Config) { + free(Config); + Config = NULL; + } + + if (Config_File) { + free(Config_File); + Config_File = NULL; + } + return 0; +} |