/*- * Copyright (c) 2001 Peter Pentchev * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "penv.h" #include "pe_compat.h" #include "pe_log.h" #include "pe_var.h" __RINGID("$Ringlet: c/misc/penv/pe_var.c,v 1.9 2004/01/06 16:38:10 roam Exp $"); pe_err_t pe_var_readfile(struct pe_var *vars, const char *fname, int required) { FILE *fp; char *line; size_t sz; pe_err_t r; r = PE_ERR_NONE; pe_verbose(1, "Reading config file %s\n", fname); if (fp = fopen(fname, "rt"), fp == NULL) { if ((errno == ENOENT) && !required) return (PE_ERR_NONE); return (PE_ERR_CFG_OPEN); } for (;;) { if (r = pe_getline(fp, &line, &sz), r) return (r); if (line == NULL) break; r = pe_var_parseline(vars, line, sz); free(line); if (r != PE_ERR_NONE) break; } fclose(fp); return (r); } pe_err_t pe_var_parseline(struct pe_var *vars, const char *line, size_t sz) { size_t n0, n1, v0, v1; char *name, *val; pe_err_t r; if (sz == 0) return (PE_ERR_NONE); for (n0 = 0; n0 < sz; n0++) if (!isspace(line[n0])) break; if ((n0 == sz) || (line[n0] == '#')) return (PE_ERR_NONE); for (n1 = n0 + 1; n1 < sz; n1++) if (isspace(line[n1]) || (line[n1] == '=')) break; if (n1 == sz) return (PE_ERR_CFG_SYNTAX); for (v0 = n1; v0 < sz; v0++) if (!isspace(line[v0])) break; if ((v0 == sz) || (line[v0] != '=')) return (PE_ERR_CFG_SYNTAX); for (v0++; v0 < sz; v0++) if (!isspace(line[v0])) break; for (v1 = sz; v1 > v0 + 1; v1--) if (!isspace(line[v1 - 1])) break; name = calloc(1, n1 - n0 + 1); val = calloc(1, v1 - v0 + 1); if ((name == NULL) || (val == NULL)) { free(name); free(val); return (PE_ERR_NOMEM); } memcpy(name, line + n0, n1 - n0); memcpy(val, line + v0, v1 - v0); r = pe_var_set(vars, name, val); free(name); free(val); return (r); } pe_err_t pe_var_set(struct pe_var *vars, const char *name, const char *val) { unsigned v; unsigned long uval; long lval; char *end; pe_verbose(2, "varset(\"%s\", \"%s\")\n", name, val); for (v = 0; vars[v].name != NULL; v++) if (!strcmp(vars[v].name, name)) break; if (vars[v].name == NULL) return (PE_ERR_CFG_NXVAR); if (vars[v].set) { pe_verbose(2, " - ignored.\n"); return (PE_ERR_NONE); } switch (vars[v].type) { case PE_VT_INT: lval = strtol(val, &end, 0); if ((lval < INT_MIN) || (lval > INT_MAX) || (*end != '\0')) return (PE_ERR_CFG_BADVAL); *(unsigned *)vars[v].val = (int) lval; break; case PE_VT_UINT: if (val[0] == '-') return (PE_ERR_CFG_BADVAL); uval = strtoul(val, &end, 0); if ((uval > UINT_MAX) || (*end != '\0')) return (PE_ERR_CFG_BADVAL); *(unsigned *)vars[v].val = (unsigned) uval; break; case PE_VT_STRING: if (strlen(val) > vars[v].size - 1) return (PE_ERR_CFG_STRLONG); pe_strlcpy((char *)vars[v].val, val, vars[v].size); break; default: return (PE_ERR_INT); } vars[v].set = 1; return (PE_ERR_NONE); }