/* * NVRAM WakeUp * Copyright (C) 2001-2004, Sergei Haller. * * $Id: readconf.c 926 2010-01-24 11:53:49Z tiber $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #define CVSREV_readconf_c \ "$Id: readconf.c 926 2010-01-24 11:53:49Z tiber $" /* * * The syntax of the configuration file is the following: * * - lines containing no non-space characters are comments. * * - If there's a '#' somewhere on the line, the rest of the line * is a comment. * * - lines of the form VARIABLE = VALUE with optional following * comment are interpreted as a definition of the variable * VARIABLE to the value VALUE. * * Read `man nvram-wakeup.conf(5)' for the list on allowed variable * names */ #include #include #include #include #include #include #include #include "nvram-wakeup.h" struct biosinfo lnrs; /* store line numbers for different variables */ void deprecated(char * old, char * new) { nvprintf(LOG_WARNING, "Use of \"%s\" is deprecated. Use \"%s\" instead.\n", old, new); } int assign(int lnr, struct biosinfo * b, int * ptr, char * val, int allow_symbolic) { char * tail; /* * now is the tricky part: * pointer to the member of lnrs corresponding * to the member pointed by ptr in *b * I love C */ int * prev = (int *)((int)(&lnrs) + ((int)ptr - (int)b)); if (*prev) { return *prev; } else { *prev = lnr; switch (allow_symbolic) { case 0: /* no symbolic assignments allowed */ break; case 1: /* only ON/OFF allowed */ if (!strcmp(val, "ON" )) {*ptr = ON ; return 0;} else if (!strcmp(val, "OFF" )) {*ptr = OFF ; return 0;} break; case 2: /* ON_STAT and stuff like this */ if (!strcmp(val, "ALWAYS" )) {*ptr = ALWAYS ; deprecated("ALWAYS", "ON_ANY_CHANGE"); return 0;} else if (!strcmp(val, "ON_ANY_CHANGE" )) {*ptr = ON_ANY_CHANGE ; return 0;} else if (!strcmp(val, "ON_STAT" )) {*ptr = ON_STAT ; return 0;} else if (!strcmp(val, "ON_MON" )) {*ptr = ON_MON ; return 0;} else if (!strcmp(val, "ON_DAY" )) {*ptr = ON_DAY ; return 0;} else if (!strcmp(val, "ON_WDAYS" )) {*ptr = ON_WDAYS ; return 0;} else if (!strcmp(val, "ON_HOUR" )) {*ptr = ON_HOUR ; return 0;} else if (!strcmp(val, "ON_MIN" )) {*ptr = ON_MIN ; return 0;} else if (!strcmp(val, "ON_SEC" )) {*ptr = ON_SEC ; return 0;} else if (!strcmp(val, "OFF" )) {*ptr = OFF ; return 0;} /* ... more to come ??? ... */ break; case 3: /* upper methods */ if (!strcmp(val, "OFF" )) {*ptr = OFF ; return 0;} else if (!strcmp(val, "INTEL" )) {*ptr = INTEL ; return 0;} else if (!strcmp(val, "DS1685" )) {*ptr = DS1685 ; return 0;} else if (!strcmp(val, "VT82Cxxx" )) {*ptr = VT82Cxxx ; return 0;} else if (!strcmp(val, "VT8235_37" )) {*ptr = VT8235_37 ; return 0;} /* ... more to come ??? ... */ break; case 4: /* checksum algorithms */ if (!strcmp(val, "DELL" )) {*ptr = DELL ; return 0;} else if (!strcmp(val, "FSC" )) {*ptr = FSC ; return 0;} /* ... more to come ??? ... */ break; } errno = 0; *ptr = strtol(val, &tail, 0); if (*tail != 0) return -2; /* val is not a number */ if (errno) return -3; /* overflow (number too large/too small) */ return 0; /* ok */ } } int readconf(struct biosinfo *b, const char * filename) { char * line=NULL; char * rest=NULL; char * comment=NULL; char * name=NULL; char * val=NULL; size_t n = 0; int lnr = 0; /* number of the line */ ssize_t got; FILE * fd_conf; if (!set_biosinfo_defaults(b)) { nvprintf(LOG_ERR, "Can't set biosinfo defaults\n"); return 0; } nvprintf(LOG_DEBUG, "Opening %s in 'r' mode...\n", filename); if ((fd_conf = fopen(filename, "r")) == NULL) { nvprintf(LOG_ERR, "%s: %m\n", filename); return 0; } /* read the next line */ while ((got = getline(&line,&n,fd_conf)) > -1) { lnr++; /* * printf("got %d characters\n",got); */ /* copy contents of the line to be used with strsep */ comment = strdupa(line); /* release space allocated by getline and reset n */ free(line); n=0; /* everything after a # is a comment */ rest = strip(strsep(&comment, "#")); /* remove trailing line break */ if (comment && comment[strlen(comment)-1] == '\n') comment[strlen(comment)-1] = 0; if (comment) nvprintf(LOG_DEBUG, "%s: %d: comment: #%s\n", filename, lnr, comment); if (rest && *rest) { /* split the rest into a pair of name and value */ name = strip(strsep(&rest, "=")); val = strip(rest); nvprintf(LOG_DEBUG, "%s: %d: name : %s\n", filename, lnr, name ); nvprintf(LOG_DEBUG, "%s: %d: value : %s\n", filename, lnr, val ); if (name && *name && val && *val) { int ret; /* now assign values */ if (!strcmp(name, "need_reboot" )) ret = assign(lnr, b, &(b->need_reboot ), val, 2); else if (!strcmp(name, "addr_chk_h" )) ret = assign(lnr, b, &(b->addr_chk_h ), val, 0); else if (!strcmp(name, "addr_chk_l" )) ret = assign(lnr, b, &(b->addr_chk_l ), val, 0); else if (!strcmp(name, "addr_chk_h2" )) ret = assign(lnr, b, &(b->addr_chk_h2 ), val, 0); else if (!strcmp(name, "addr_chk_l2" )) ret = assign(lnr, b, &(b->addr_chk_l2 ), val, 0); else if (!strcmp(name, "addr_stat" )) ret = assign(lnr, b, &(b->addr_stat ), val, 0); else if (!strcmp(name, "addr_mon" )) ret = assign(lnr, b, &(b->addr_mon ), val, 0); else if (!strcmp(name, "addr_day" )) ret = assign(lnr, b, &(b->addr_day ), val, 0); else if (!strcmp(name, "addr_wdays" )) ret = assign(lnr, b, &(b->addr_wdays ), val, 0); else if (!strcmp(name, "addr_hour" )) ret = assign(lnr, b, &(b->addr_hour ), val, 0); else if (!strcmp(name, "addr_min" )) ret = assign(lnr, b, &(b->addr_min ), val, 0); else if (!strcmp(name, "addr_sec" )) ret = assign(lnr, b, &(b->addr_sec ), val, 0); else if (!strcmp(name, "shift_stat" )) ret = assign(lnr, b, &(b->shift_stat ), val, 0); else if (!strcmp(name, "shift_mon" )) ret = assign(lnr, b, &(b->shift_mon ), val, 0); else if (!strcmp(name, "shift_day" )) ret = assign(lnr, b, &(b->shift_day ), val, 0); else if (!strcmp(name, "shift_wdays" )) ret = assign(lnr, b, &(b->shift_wdays ), val, 0); else if (!strcmp(name, "shift_hour" )) ret = assign(lnr, b, &(b->shift_hour ), val, 0); else if (!strcmp(name, "shift_min" )) ret = assign(lnr, b, &(b->shift_min ), val, 0); else if (!strcmp(name, "shift_sec" )) ret = assign(lnr, b, &(b->shift_sec ), val, 0); else if (!strcmp(name, "rtc_time" )) ret = assign(lnr, b, &(b->rtc_time ), val, 1); else if (!strcmp(name, "rtc_day" )) ret = assign(lnr, b, &(b->rtc_day ), val, 0); else if (!strcmp(name, "rtc_mon" )) ret = assign(lnr, b, &(b->rtc_mon ), val, 0); else if (!strcmp(name, "rtc_day_0_is_c0" )) ret = assign(lnr, b, &(b->rtc_day_0_is_c0 ), val, 1); else if (!strcmp(name, "rtc_mon_0_is_c0" )) ret = assign(lnr, b, &(b->rtc_mon_0_is_c0 ), val, 1); else if (!strcmp(name, "reset_day" )) ret = assign(lnr, b, &(b->reset_day ), val, 1); else if (!strcmp(name, "reset_mon" )) ret = assign(lnr, b, &(b->reset_mon ), val, 1); else if (!strcmp(name, "nr_stat" )) ret = assign(lnr, b, &(b->nr_stat ), val, 0); else if (!strcmp(name, "nr_mon" )) ret = assign(lnr, b, &(b->nr_mon ), val, 0); else if (!strcmp(name, "nr_day" )) ret = assign(lnr, b, &(b->nr_day ), val, 0); else if (!strcmp(name, "nr_hour" )) ret = assign(lnr, b, &(b->nr_hour ), val, 0); else if (!strcmp(name, "nr_min" )) ret = assign(lnr, b, &(b->nr_min ), val, 0); else if (!strcmp(name, "nr_sec" )) ret = assign(lnr, b, &(b->nr_sec ), val, 0); else if (!strcmp(name, "nr_rtc_day" )) ret = assign(lnr, b, &(b->nr_rtc_day ), val, 0); else if (!strcmp(name, "nr_rtc_mon" )) ret = assign(lnr, b, &(b->nr_rtc_mon ), val, 0); else if (!strcmp(name, "nr_wdays" )) ret = assign(lnr, b, &(b->nr_wdays ), val, 0); else if (!strcmp(name, "bcd" )) ret = assign(lnr, b, &(b->bcd ), val, 1); else if (!strcmp(name, "day_no_bcd" )) ret = assign(lnr, b, &(b->day_no_bcd ), val, 1); else if (!strcmp(name, "day_hack" )) ret = assign(lnr, b, &(b->day_hack ), val, 0); else if (!strcmp(name, "upper_method" )) ret = assign(lnr, b, &(b->upper_method ), val, 3); else if (!strcmp(name, "chk_method" )) ret = assign(lnr, b, &(b->chk_method ), val, 4); else if (!strcmp(name, "addr_date" )) { deprecated("addr_date", "addr_day" ); ret = assign(lnr, b, &(b->addr_day ), val, 0); } else if (!strcmp(name, "shift_date" )) { deprecated("shift_date", "shift_day" ); ret = assign(lnr, b, &(b->shift_day ), val, 0); } else if (!strcmp(name, "rtc_date" )) { deprecated("rtc_date", "rtc_day" ); ret = assign(lnr, b, &(b->rtc_day ), val, 0); } else if (!strcmp(name, "rtc_date_0_is_c0")) { deprecated("rtc_date_0_is_c0", "rtc_day_0_is_c0" ); ret = assign(lnr, b, &(b->rtc_day_0_is_c0 ), val, 1); } else if (!strcmp(name, "reset_date" )) { deprecated("reset_date", "reset_day" ); ret = assign(lnr, b, &(b->reset_day ), val, 1); } else if (!strcmp(name, "nr_date" )) { deprecated("nr_date", "nr_day" ); ret = assign(lnr, b, &(b->nr_day ), val, 0); } else if (!strcmp(name, "nr_rtc_date" )) { deprecated("nr_rtc_date", "nr_rtc_day" ); ret = assign(lnr, b, &(b->nr_rtc_day ), val, 0); } else if (!strcmp(name, "date_hack" )) { deprecated("date_hack", "day_hack" ); ret = assign(lnr, b, &(b->day_hack ), val, 0); } else ret = -1; switch(ret) { case -1: nvprintf(LOG_ERR, "%s: %d: Syntax error: unknown variable name\n", filename, lnr); fclose(fd_conf); return 0; case -2: nvprintf(LOG_ERR, "%s: %d: Syntax error: value is not a number\n", filename, lnr); fclose(fd_conf); return 0; case -3: nvprintf(LOG_ERR, "%s: %d: Syntax error: value too large/too small\n", filename, lnr); fclose(fd_conf); return 0; case 0: break; default : if (ret>0) { nvprintf(LOG_ERR, "%s: %d: Previous definition of variable `%s': first definition in line %d\n", filename, lnr, name, ret); fclose(fd_conf); return 0; } /* should have no negative numbers here */ } } else { nvprintf(LOG_ERR, "%s: %d: Syntax error: no value\n", filename, lnr); fclose(fd_conf); return 0; } } } nvprintf(LOG_DEBUG, "Closing %s ...\n", filename); fclose(fd_conf); return 1; }