00001 // Copyright (C) 2001, Compaq Computer Corporation 00002 // 00003 // This file is part of Vesta. 00004 // 00005 // Vesta is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU Lesser General Public 00007 // License as published by the Free Software Foundation; either 00008 // version 2.1 of the License, or (at your option) any later version. 00009 // 00010 // Vesta is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // Lesser General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU Lesser General Public 00016 // License along with Vesta; if not, write to the Free Software 00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 00019 // Last modified on Mon Jan 3 14:03:38 EST 2005 by ken@xorian.net 00020 // modified on Tue Dec 12 13:25:25 PST 2000 by mann 00021 // modified on Tue Dec 5 13:45:30 PST 1995 by levin 00022 00023 // The VestaConfig class provides an interface to the central configuration 00024 // file for a Vesta installation. The configuration file is stored at 00025 // an installation-specific location; see the comments on the get() method. 00026 // 00027 // The configuration file itself is a text file with the following syntax 00028 // 00029 // config file = line* 00030 // line = ws ( sect | option | comment ) ws new-line 00031 // sect = '[' ws name ws ']' | '[' "include" name ']' 00032 // option = name ws '=' ws value 00033 // comment = ( ';' | "//" ) non-new-line* | <empty> 00034 // name = ( letter | digit | special )+ 00035 // value = non-new-line* 00036 // new-line = <ASCII CR> | <ASCII LF> 00037 // non-new-line = <any ASCII character except those for new-line> 00038 // ws = <space> | <tab> 00039 // 00040 // This syntax is slightly ambiguous, but the intent should be clear. 00041 // The file is a sequence of lines, each of which is either a section name 00042 // in square brackets, a <name,value> pair separated by an equal sign, or 00043 // a comment. Leading and trailing white space is ignored, as are blank 00044 // lines and comment lines. A comment line has a semicolon or two slashes 00045 // as its first non-whitespace characters. 00046 // 00047 // The configuration file defines a two-level naming structure, with 00048 // sections as the upper level and the names of <name, value> pairs as the 00049 // lower level. Once the file has been parsed, the basic operation is 00050 // to lookup a <section, name> pair, obtaining the associated value. 00051 // 00052 // There is a limited facility for one configuration file to refer to 00053 // another one. Notice the second alternative for the 'sect' nonterminal 00054 // in the grammar above. When this form is used, it doesn't introduce 00055 // a section name; instead, the specified file is read and processed instead. 00056 // That is, if the file contains a line of the form: 00057 // [include /proj/vesta/pkg/config-file/vesta.cfg] 00058 // then the line will effectively be replaced by the contents of the file 00059 // /proj/vesta/pkg/config-file/vesta.cfg 00060 // 00061 // This mechanism is chiefly intended for overriding a set of shared 00062 // defaults. A configuration file containing standard definitions is 00063 // stored in a public location (e.g., /etc/vesta.cfg; or at SRC, 00064 // /udir/vestasrv/misc/vesta.cfg). A second configuration file is stored 00065 // in the user's home directory or at the location specified by the 00066 // environment variable VESTACONFIG. This second file begins with an 00067 // "include" line that mentions the first file, then continues with 00068 // additional sections that either add to or override the standard 00069 // definitions. Thus, it is not an error for a <section, name> pair to 00070 // appear more than once in the course of configuration file processing 00071 // (which may involve reading multiple files). The last-encountered value 00072 // wins. 00073 00074 #ifndef _VestaConfig_H 00075 #define _VestaConfig_H 00076 00077 #include <Basics.H> 00078 #include <Generics.H> 00079 00080 namespace VestaConfig { 00081 00082 struct failure { 00083 Text msg; 00084 inline failure(const Text &msg) { this->msg = msg; }; 00085 inline failure(const failure &f) { this->msg = f.msg; }; 00086 inline failure& operator=(const failure &f) { 00087 this->msg = f.msg; return *this; }; 00088 }; 00089 00090 // ********************************* 00091 // * Configuration file location * 00092 // ********************************* 00093 00094 void set_location(const Text &file_name); 00095 // 'file_name' specifies the location of the configuration file. This 00096 // file's contents are used by subsequent calls of 'get' (see below). 00097 00098 Text get_location() throw(failure); 00099 // Returns the location of the configuration file. The location is 00100 // is determined as described under 'get', below. 00101 00102 00103 // ******************************************** 00104 // * Reading fields from configuration file * 00105 // ******************************************** 00106 00107 bool get(const Text §ion, const Text &name, Text &value) 00108 throw(failure); 00109 // The configuration file is examined for a section whose name is 'section'. 00110 // If such a section is found and it contains a <name, value> pair whose 00111 // name matches the 'name' argument, then the value is stored in the 00112 // 'value' argument and this function returns true. If no matching 00113 // section and name can be found, the function leaves 'value' unchanged 00114 // and returns false. If the configuration file cannot be 00115 // successfully read and parsed, 'failure' is thrown. 00116 // 00117 // The location of the configuration file is determined as follows: 00118 // 1. If 'set_location' was previously called, the path it 00119 // specified is used. If the specified file can't be read, 00120 // 'failure' is thrown. 00121 // 2. If 'set_location' was not previously invoked, the value of 00122 // the environment variable VESTACONFIG is used. If the 00123 // specified file can't be found, 'failure' is thrown. 00124 // 3. If VESTACONFIG isn't defined, the environment variable 00125 // HOME is used to define a directory from which 'vesta.cfg' 00126 // is read. If it exists, it is read and used for all 00127 // subsequent calls of 'get', unless 'set_location' is 00128 // subsequently called. 00129 // 4. If 'vesta.cfg' is not found in $HOME, /etc/vesta.cfg is 00130 // tried next. If it exists, it is read and used for all 00131 // subsequent calls of 'get', unless 'set_location' is 00132 // subsequently called. If it does not exist, 'failure' is 00133 // thrown. 00134 00135 bool is_set(const Text §ion, const Text &name) 00136 throw(failure); 00137 // This function is semantically equivalent to: 00138 // Text value; 00139 // return get(section, name, value); 00140 // It avoids the need for declaring a dummy variable to call get to 00141 // determine whether a variable is set. 00142 00143 Text get_Text(const Text §ion, const Text &name) 00144 throw(failure); 00145 // This function is semantically equivalent to: 00146 // Text value; 00147 // if (get(section, name, value)) return value; 00148 // throw(failure(<suitable message about [section]name not found>)); 00149 00150 int get_int(const Text §ion, const Text &name) 00151 throw(failure); 00152 // This function is semantically equivalent to: 00153 // istrstream ss(get_Text(section, name).chars()); 00154 // int value; 00155 // if (ss >> value) return value; 00156 // throw(failure(<message about [section]name not an integer>)); 00157 00158 bool get_bool(const Text §ion, const Text &name) 00159 throw(failure); 00160 // This function inteprets the setting of a configuration variable 00161 // as a boolean. If it is equal (witout regard to case) to "yes", 00162 // "on", or "true", or can be parsed as an integer that is non-zero, 00163 // it's interpreted as a true value. If it is equal (witout regard 00164 // to case) to "no", "off", or "false", or can be parsed as an 00165 // integer that is zero, it's interpreted as a false value. 00166 // Otherwise an expetion is thrown. (Exceptions can also be thrown 00167 // if the value isn't set or if there are parsing errors.) 00168 00169 float get_float(const Text §ion, const Text &name) 00170 throw(failure); 00171 // This function is semantically equivalent to: 00172 // istrstream ss(get_Text(section, name).chars()); 00173 // float value; 00174 // if (ss >> value) return value; 00175 // throw(failure(<message about [section]name not an integer>)); 00176 00177 TextSeq sections() 00178 throw(failure); 00179 // Returns all the sections in the configuration file. If the 00180 // configuration file cannot be successfully read and parsed, 00181 // 'failure' is thrown. 00182 00183 TextSeq section_vars(const Text §ion) 00184 throw(failure); 00185 // Returns all the names in the given section in the configuration 00186 // file. If the specified section doesn't exist, the empty sequence 00187 // is returned. If the configuration file cannot be successfully 00188 // read and parsed, 'failure' is thrown. 00189 00190 } 00191 00192 #endif /* _VestaConfig_H */