/* $Id: cfg.c,v 1.43 2004/11/29 04:42:06 reinelt Exp $^ * * config file stuff * * Copyright 1999, 2000 Michael Reinelt * Copyright 2004 The LCD4Linux Team * * This file is part of LCD4Linux. * * LCD4Linux 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, or (at your option) * any later version. * * LCD4Linux 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., 675 Mass Ave, Cambridge, MA 02139, USA. * * * $Log: cfg.c,v $ * Revision 1.43 2004/11/29 04:42:06 reinelt * removed the 99999 msec limit on widget update time (thanks to Petri Damsten) * * Revision 1.42 2004/06/26 12:04:59 reinelt * * uh-oh... the last CVS log message messed up things a lot... * * Revision 1.41 2004/06/26 09:27:20 reinelt * * added '-W' to CFLAGS * changed all C++ comments to C ones * cleaned up a lot of signed/unsigned mistakes * * Revision 1.40 2004/06/20 10:09:52 reinelt * * 'const'ified the whole source * * Revision 1.39 2004/03/11 06:39:58 reinelt * big patch from Martin: * - reuse filehandles * - memory leaks fixed * - earlier busy-flag checking with HD44780 * - reuse memory for strings in RESULT and hash * - netdev_fast to wavid time-consuming regex * * Revision 1.38 2004/03/08 16:26:26 reinelt * re-introduced \nnn (octal) characters in strings * text widgets can have a 'update' speed of 0 which means 'never' * (may be used for static content) * * Revision 1.37 2004/03/06 20:31:16 reinelt * Complete rewrite of the evaluator to get rid of the code * from mark Morley (because of license issues). * The new Evaluator does a pre-compile of expressions, and * stores them in trees. Therefore it should be reasonable faster... * * Revision 1.36 2004/03/03 03:47:04 reinelt * big patch from Martin Hejl: * - use qprintf() where appropriate * - save CPU cycles on gettimeofday() * - add quit() functions to free allocated memory * - fixed lots of memory leaks * * Revision 1.35 2004/03/01 04:29:51 reinelt * cfg_number() returns -1 on error, 0 if value not found (but default val used), * and 1 if value was used from the configuration. * HD44780 driver adopted to new cfg_number() * Crystalfontz 631 driver nearly finished * * Revision 1.34 2004/02/18 06:39:20 reinelt * T6963 driver for graphic displays finished * * Revision 1.33 2004/02/01 18:08:50 reinelt * removed strtok() from layout processing (took me hours to find this bug) * further strtok() removind should be done! * * Revision 1.32 2004/01/30 20:57:55 reinelt * HD44780 patch from Martin Hejl * dmalloc integrated * * Revision 1.31 2004/01/29 04:40:02 reinelt * every .c file includes "config.h" now * * Revision 1.30 2004/01/22 07:57:45 reinelt * several bugs fixed where segfaulting on layout>display * Crystalfontz driver optimized, 632 display already works * * Revision 1.29 2004/01/18 06:54:08 reinelt * bug in expr.c fixed (thanks to Xavier) * some progress with /proc/stat parsing * * Revision 1.28 2004/01/16 05:04:53 reinelt * started plugin proc_stat which should parse /proc/stat * which again is a paint in the a** * thinking over implementation methods of delta functions * (CPU load, ...) * * Revision 1.27 2004/01/14 11:33:00 reinelt * new plugin 'uname' which does what it's called * text widget nearly finished * first results displayed on MatrixOrbital * * Revision 1.26 2004/01/11 18:26:02 reinelt * further widget and layout processing * * Revision 1.25 2004/01/11 09:26:15 reinelt
# Voiron - France (DVB-T transmitter of Voiron ( Nondéfini ) )
# Voiron - France (signal DVB-T transmis depuis l'émetteur de Nondéfini )
#
# ATTENTION ! Ce fichier a ete construit automatiquement a partir
# des frequences obtenues sur : http://www.tvnt.net/multiplex_frequences.htm
# en Avril 2006. Si vous constatez des problemes et voulez apporter des
# modifications au fichier, envoyez le fichier modifie a
# l'adresse linux-dvb@linuxtv.org (depot des fichiers d'init dvb)
# ou a l'auteur du fichier :
# Nicolas Estre <n_estre@yahoo.fr>
#
# T freq bw fec_hi fec_lo mod transmission-mode guard-interval hierarchy
#### Voiron - Nondéfini ####
#R1
#T FREQ1 8MHz AUTO NONE QAM64 8k AUTO NONE
#R2
#T FREQ2 8MHz AUTO NONE QAM64 8k AUTO NONE
#R3
#T FREQ3 8MHz AUTO NONE QAM64 8k AUTO NONE
#R4
#T FREQ4 8MHz AUTO NONE QAM64 8k AUTO NONE
#R5
#T FREQ5 8MHz AUTO NONE QAM64 8k AUTO NONE
#R6
#T FREQ6 8MHz AUTO NONE QAM64 8k AUTO NONE
##############################################################
# en Avril 2006, l'emetteur pour Voiron n'etait pas defini
#  Vous devez donc modifier les frequences manuellement.
# SVP Renvoyez le fichier mis a jour aux contacts ci-dessus.
##############################################################
ry; /* 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) { 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; } 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; ival; return NULL; } 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 *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); } DelTree(tree); DelResult(&result); } 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) { 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); if (*value 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; } 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; } } /* 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); } /* 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); return -error; } int cfg_init (const char *file) { if (cfg_check_source(file) == -1) { error("config file '%s' is insecure, aborting", file); 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) { if (Config_File) return Config_File; else return ""; } int cfg_exit (void) { int i; for (i=0; i