Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

configparser.c

Go to the documentation of this file.
00001 
00009 /* {{{ Initial comments */
00010 /*
00011  * $LastChangedDate: 2004-04-15 14:41:57 +0200 (Thu, 15 Apr 2004) $
00012  * $LastChangedRevision: 53 $
00013  * $LastChangedBy: ckruse $
00014  *
00015  */
00016 /* }}} */
00017 
00018 /* {{{ Includes */
00019 #include "config.h"
00020 #include "defines.h"
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <unistd.h>
00025 #include <string.h>
00026 #include <ctype.h>
00027 #include <errno.h>
00028 
00029 #include <dlfcn.h>
00030 
00031 #include <fcntl.h>
00032 #include <sys/types.h>
00033 #include <sys/stat.h>
00034 #include <sys/mman.h>
00035 #include <sys/uio.h>
00036 
00037 #include <pwd.h>
00038 
00039 #include "utils.h"
00040 #include "hashlib.h"
00041 #include "configparser.h"
00042 /* }}} */
00043 
00044 /* {{{ globals */
00045 
00046 /***************************************** CONFIGURATION OPTIONS ************************************************
00047  * defining the global variables for configuration
00048  *
00049  ***/
00050 
00051 t_configuration fo_default_conf  = { NULL, NULL, 0 };
00052 t_configuration fo_server_conf   = { NULL, NULL, 0 };
00053 t_configuration fo_view_conf     = { NULL, NULL, 0 };
00054 t_configuration fo_arcview_conf  = { NULL, NULL, 0 };
00055 t_configuration fo_post_conf     = { NULL, NULL, 0 };
00056 
00057 t_array Modules[MOD_MAX+1];
00058 
00059 /*
00060  * forum default config options
00061  */
00062 t_conf_opt default_options[] = {
00063   { "<General>",                NULL,             NULL             },
00064   { "ExternCharset",            handle_command,   &fo_default_conf },
00065   { "TemplateMode",             handle_command,   &fo_default_conf },
00066   { "MessagePath",              handle_command,   &fo_default_conf },
00067   { "ArchivePath",              handle_command,   &fo_default_conf },
00068   { "ThreadIndexFile",          handle_command,   &fo_default_conf },
00069   { "SocketName",               handle_command,   &fo_default_conf },
00070   { "BaseURL",                  handle_command,   &fo_default_conf },
00071   { "UBaseURL",                 handle_command,   &fo_default_conf },
00072   { "ArchiveURL",               handle_command,   &fo_default_conf },
00073   { "ErrorTemplate",            handle_command,   &fo_default_conf },
00074   { "ErrorMessages",            handle_command,   &fo_default_conf },
00075   { "PostScript",               handle_command,   &fo_default_conf },
00076   { "UPostScript",              handle_command,   &fo_default_conf },
00077   { "UserConfig",               handle_command,   &fo_default_conf },
00078   { "UserRegister",             handle_command,   &fo_default_conf },
00079   { "SharedMemIds",             handle_command,   &fo_default_conf },
00080   { "Administrators",           handle_command,   &fo_default_conf },
00081   { "AuthMode",                 handle_command,   &fo_default_conf },
00082   { "</General>",               NULL,             NULL             },
00083 
00084   { "<Categories>",             NULL,             NULL             },
00085   { "Category",                 handle_command,   &fo_default_conf },
00086   { "</Categories>",            NULL,             NULL             },
00087 
00088   { "<DateConfig>",             NULL,             NULL             },
00089   { "DateLocale",               handle_command,   &fo_default_conf },
00090   { "</DateConfig>",            NULL,             NULL             },
00091 
00092   { "<Users>",                  NULL,             NULL             },
00093   { "ConfigDirectory",          handle_command,   &fo_default_conf },
00094   { "InactivityDelete",         handle_command,   &fo_default_conf },
00095   { "SendMailBeforeDelete",     handle_command,   &fo_default_conf },
00096   { "</Users>",                 NULL,             NULL             },
00097 
00098   { NULL,                       NULL,             NULL             }
00099 };
00100 
00101 /*
00102  * forum client config options
00103  */
00104 t_conf_opt fo_view_options[] = {
00105   { "<ForumBehavior>",            NULL,             NULL          },
00106   { "ShowFlags",                  handle_command,   &fo_view_conf },
00107   { "ReadMode",                   handle_command,   &fo_view_conf },
00108   { "</ForumBehavior>",           NULL,             NULL          },
00109 
00110   { "<Templates>",                NULL,             NULL          },
00111   { "TemplateForumBegin",         handle_command,   &fo_view_conf },
00112   { "TemplateForumEnd",           handle_command,   &fo_view_conf },
00113   { "TemplateForumThread",        handle_command,   &fo_view_conf },
00114   { "TemplatePosting",            handle_command,   &fo_view_conf },
00115   { "</Templates>",               NULL,             NULL          },
00116 
00117   { "<DateConfig>",               NULL,             NULL          },
00118   { "DateFormatThreadList",       handle_command,   &fo_view_conf },
00119   { "DateFormatThreadView",       handle_command,   &fo_view_conf },
00120   { "DateFormatLoadTime",         handle_command,   &fo_view_conf },
00121   { "</DateConfig>",              NULL,             NULL          },
00122 
00123   { "<Form>",                     NULL,             NULL          },
00124   { "Name",                       handle_command,   &fo_view_conf },
00125   { "EMail",                      handle_command,   &fo_view_conf },
00126   { "HomepageUrl",                handle_command,   &fo_view_conf },
00127   { "ImageUrl",                   handle_command,   &fo_view_conf },
00128   { "</Form>",                    NULL,             NULL          },
00129 
00130   { "<Filters>",                  NULL,             NULL          },
00131   { "AddFilter",                  add_module,       &Modules      },
00132   { "</Filters>",                 NULL,             NULL          },
00133 
00134   { NULL,                         NULL,             NULL          }
00135 };
00136 
00137 /*
00138  * Posting configuration options
00139  */
00140 t_conf_opt fo_post_options[] = {
00141   {  "<General>",                 NULL,             NULL          },
00142   {  "AddFilter",                 add_module,       &Modules      },
00143   {  "PostingUrl",                handle_command,   &fo_post_conf },
00144   {  "FieldConfig",               handle_command,   &fo_post_conf },
00145   {  "FieldNeeded",               handle_command,   &fo_post_conf },
00146   {  "RedirectOnPost",            handle_command,   &Modules      },
00147   {  "</General>",                NULL,             NULL          },
00148   {  "<Images>",                  NULL,             NULL          },
00149   {  "Image",                     handle_command,   &fo_post_conf },
00150   {  "</Images>",                 NULL,             NULL          },
00151   {  "<Templates>",               NULL,             NULL          },
00152   {  "ThreadTemplate",            handle_command,   &fo_post_conf },
00153   {  "FatalTemplate",             handle_command,   &fo_post_conf },
00154   {  "OkTemplate",                handle_command,   &fo_post_conf },
00155   {  "</Templates>",              handle_command,   &fo_post_conf },
00156   {  NULL,                        NULL,             NULL          }
00157 };
00158 
00159 /*
00160  * fo_server config options
00161  */
00162 t_conf_opt fo_server_options[] = {
00163   { "<General>",            NULL,             NULL },
00164   { "SortThreads",          handle_command,   &fo_server_conf },
00165   { "SortMessages",         handle_command,   &fo_server_conf },
00166   { "RunArchiver",          handle_command,   &fo_server_conf },
00167   { "ErrorLog",             handle_command,   &fo_server_conf },
00168   { "StdLog",               handle_command,   &fo_server_conf },
00169   { "PIDFile",              handle_command,   &fo_server_conf },
00170   { "</General>",           NULL,             NULL },
00171 
00172   { "<Archiving>",          NULL,             NULL },
00173   { "ArchiveOnVote",        handle_command,   &fo_server_conf },
00174   { "MainFileMaxBytes",     handle_command,   &fo_server_conf },
00175   { "MainFileMaxPostings",  handle_command,   &fo_server_conf },
00176   { "MainFileMaxThreads",   handle_command,   &fo_server_conf },
00177   { "</Archiving>",         NULL,             NULL },
00178 
00179   { "<Filters>",            handle_command,   &fo_server_conf },
00180   { "AddFilter",            add_module,       &Modules        },
00181   { "</Filters>",           NULL,             NULL },
00182 
00183   { NULL,                   NULL,             NULL            }
00184 };
00185 
00186 t_conf_opt fo_arcview_options[] = {
00187   { "<Filters>",            NULL,             NULL },
00188   { "AddFilter",            add_module,       &Modules        },
00189   { "</Filters>",           NULL,             NULL },
00190 
00191   { "<General>",            NULL,             NULL },
00192   { "SortYearList",         handle_command,   &fo_arcview_conf },
00193   { "SortMonthList",        handle_command,   &fo_arcview_conf },
00194   { "DateFormatList",       handle_command,   &fo_arcview_conf },
00195   { "</General>",           NULL,             NULL },
00196 
00197   { "<Templates>",             NULL,             NULL },
00198   { "FatalTemplate",           handle_command,   &fo_arcview_conf },
00199   { "YearsTemplate",           handle_command,   &fo_arcview_conf },
00200   { "YearListTemplate",        handle_command,   &fo_arcview_conf },
00201   { "MonthsTemplate",          handle_command,   &fo_arcview_conf },
00202   { "MonthsListTemplate",      handle_command,   &fo_arcview_conf },
00203   { "ThreadListMonthTemplate", handle_command,   &fo_arcview_conf },
00204   { "ThreadTemplate",          handle_command,   &fo_arcview_conf },
00205   { "ThreadListTemplate",      handle_command,   &fo_arcview_conf },
00206   { "PerThreadTemplate",       handle_command,   &fo_arcview_conf },
00207   { "UpDownTemplate",          handle_command,   &fo_arcview_conf },
00208   { "</Templates>",            NULL,             NULL },
00209 
00210   { NULL,                      NULL,             NULL            }
00211 };
00212 
00213 
00214 /* }}} */
00215 
00216 /* {{{ get_conf_file
00217  * Returns: u_char ** (NULL on failure, a string-array on success)
00218  * Parameters:
00219  *   - u_char **argv  a list of parameter strings
00220  *
00221  * this function expects the argv parameter list of main(). It uses
00222  * the first parameter, the complete path to the program and returns
00223  * the pathes to the configuration files
00224  *
00225  */
00226 t_array *get_conf_file(const u_char **which,size_t llen) {
00227   t_array *ary = fo_alloc(NULL,1,sizeof(*ary),FO_ALLOC_CALLOC);
00228   u_char *env;
00229   t_string file;
00230   size_t len;
00231   struct stat st;
00232   size_t i;
00233 
00234   if((env = getenv("CF_CONF_DIR")) == NULL) {
00235     return NULL;
00236   }
00237 
00238   len = strlen(env);
00239 
00240   array_init(ary,sizeof(u_char **),NULL);
00241 
00242   for(i=0;i<llen;i++) {
00243     str_init(&file);
00244 
00245     str_char_set(&file,env,len);
00246 
00247     if(file.content[file.len-1] != '/') {
00248       str_char_append(&file,'/');
00249     }
00250 
00251     str_chars_append(&file,which[i],strlen(which[i]));
00252     str_chars_append(&file,".conf",5);
00253 
00254     memset(&st,0,sizeof(st));
00255     if(stat(file.content,&st) == -1) {
00256       str_cleanup(&file);
00257       perror("stat");
00258       return NULL;
00259     }
00260 
00261     array_push(ary,&file.content);
00262   }
00263 
00264   return ary;
00265 }
00266 /* }}} */
00267 
00268 /* {{{ parse_args */
00277 int parse_args(u_char *line,u_char ***args,int lnum) {
00278   register u_char *ptr = line;
00279   int len = -1,run;
00280   t_string argument;
00281 
00282   *args = NULL;
00283 
00284   while(len < 2) {
00285     /*
00286      * skip trailing whitespaces
00287      */
00288     for(;*ptr && isspace(*ptr) && *ptr != (u_char)012;ptr++);
00289     if(*ptr == (u_char)012 || *ptr == (u_char)0 || *ptr == '#') break; /* end of line or end of file or comment */
00290 
00291     if(*ptr != '"') {
00292       fprintf(stderr,"unexpected character %d at line %d!\n",*ptr,lnum);
00293       return -1;
00294     }
00295 
00296     str_init(&argument);
00297     run = 1;
00298 
00299     for(ptr++;*ptr && run;ptr++) {
00300       switch(*ptr) {
00301         case '\\':
00302           switch(*++ptr) {
00303             case 'n':
00304               str_char_append(&argument,'\n');
00305               break;
00306             case 't':
00307               str_char_append(&argument,'\t');
00308               break;
00309             case 'r':
00310               str_char_append(&argument,'\r');
00311               break;
00312             default:
00313               str_char_append(&argument,*ptr);
00314               break;
00315           }
00316           break;
00317         case '"':
00318           /* empty arguments have to be filled up with a \0 byte */
00319           if(len >= 0 && !(*args)[len]) (*args)[len] = strdup("\0");
00320 
00321           *args = fo_alloc(*args,++len + 1,sizeof(u_char *),FO_ALLOC_REALLOC);
00322           (*args)[len] = argument.content;
00323           run = 0;
00324           break;
00325         default:
00326           str_char_append(&argument,*ptr);
00327           break;
00328       }
00329     }
00330 
00331   }
00332 
00333   /* empty arguments have to be filled up with a \0 byte */
00334   if(len >= 0 && !(*args)[len]) (*args)[len] = strdup("\0");
00335 
00336   return len + 1;
00337 }
00338 /* }}} */
00339 
00340 /* {{{ read_config
00341  * Returns: int              0 on success, 1 on error
00342  * Parameters:
00343  *   - t_configuration conf  the configuration structure
00344  *
00345  * This function parses an configuration structure
00346  *
00347  */
00348 int read_config(t_configfile *conf,t_take_default deflt) {
00349   int fd  = open(conf->filename,O_RDONLY);
00350   u_char *buff;
00351   u_char *ptr,*ptr1;
00352   struct stat st;
00353   u_char *directive_name;
00354   u_char **args;
00355   int i,found;
00356   t_conf_opt *opt;
00357   unsigned int linenum = 0;
00358   int argnum;
00359 
00360   /*
00361    * open() could fail :)
00362    */
00363   if(fd == -1) {
00364     perror("open");
00365     return 1;
00366   }
00367 
00368   if(stat(conf->filename,&st) == -1) {
00369     close(fd);
00370     perror("stat");
00371     return 1;
00372   }
00373 
00374   if(((void *)(buff = mmap(0,st.st_size+1,PROT_READ,MAP_FILE|MAP_SHARED,fd,0))) == (caddr_t)-1) {
00375     close(fd);
00376     perror("mmap");
00377     return 1;
00378   }
00379 
00380   ptr = buff;
00381 
00382   /*
00383    * loop through the hole file
00384    */
00385   while(*ptr) {
00386     /* we're at the next line */
00387     ++linenum;
00388 
00389     /* first, lets find the beginning of the line (whitespaces have to be ignored) */
00390     for(;*ptr && isspace(*ptr);ptr++);
00391 
00392     /* eof */
00393     if(!*ptr) break;
00394 
00395     /* comment - continue with next line */
00396     if(*ptr == '#') {
00397       /* read until the end of the line */
00398       for(;*ptr && *ptr != (u_char)012;ptr++);
00399       if(!*ptr) break;
00400       ptr += 1;
00401       continue;
00402     }
00403 
00404     /* got end of line - continue with next line */
00405     if(*ptr == (u_char)012) {
00406       ptr += 1;
00407       continue;
00408     }
00409 
00410     /* ok, we're at the beginning of the directive. */
00411     ptr1 = ptr;
00412 
00413     /* now we got the end of the directive */
00414     for(;*ptr && !isspace(*ptr);ptr++);
00415 
00416     /* eof */
00417     if(!*ptr) break;
00418 
00419     directive_name = memdup(ptr1,ptr-ptr1+1);
00420     directive_name[ptr-ptr1] = '\0';
00421 
00422     if((argnum = parse_args(ptr,&args,linenum)) == -1) {
00423       close(fd);
00424       munmap(buff,st.st_size);
00425       return 1;
00426     }
00427 
00428     found = 0;
00429     if((opt = cf_hash_get(conf->options,directive_name,ptr-ptr1)) != NULL) {
00430       if(opt->callback) found = opt->callback(conf,opt,args,argnum);
00431     }
00432     else {
00433       if(deflt) {
00434         found = deflt(conf,args,argnum);
00435       }
00436       else {
00437         fprintf(stderr,"Configuration entry for directive %s not found!\n",directive_name);
00438         return 1;
00439       }
00440     }
00441 
00442     if(found == 0) {
00443       /* arguments are no longer needed */
00444       if(argnum > 0) {
00445         for(i=0;i<argnum;i++) free(args[i]);
00446         free(args);
00447       }
00448     }
00449     else if(found != -1) {
00450       fprintf(stderr,"Callback function returned not 0 or -1!\n");
00451       return 1;
00452     }
00453 
00454     free(directive_name);
00455 
00456     /* now everything whith this directive has finished. Find end of line... */
00457     for(;*ptr && *ptr != (u_char)012;ptr++);
00458 
00459     /* eof */
00460     if(!*ptr) break;
00461 
00462     ptr += 1;
00463   }
00464 
00465   close(fd);
00466   munmap(buff,st.st_size);
00467 
00468   return 0;
00469 }
00470 /* }}} */
00471 
00472 /* {{{ handle_command
00473  * Returns: int    FO_CONF_OK or FO_CONF_PARENTHESIS
00474  * Parameters:
00475  *   - t_conf_entry *entry   a pointer to the configuration entry
00476  *   - void *arg             user argument (the configuration variable)
00477  *
00478  * this function puts an entry to a configuration structure
00479  *
00480  */
00481 int handle_command(t_configfile *cfile,t_conf_opt *opt,u_char **args,int argnum) {
00482   t_configuration *conf = (t_configuration *)opt->data;
00483   t_name_value *tmp;
00484 
00485   tmp         = fo_alloc(NULL,1,sizeof(t_name_value),FO_ALLOC_CALLOC);
00486   tmp->values = args;
00487   tmp->valnum = argnum;
00488   tmp->name   = strdup(opt->name);
00489 
00490   tmp->next        = conf->directives;
00491   conf->directives = tmp;
00492 
00493   conf->len++;
00494 
00495   return -1;
00496 }
00497 /* }}} */
00498 
00499 /* {{{ add_module */
00500 
00501 int add_module(t_configfile *cfile,t_conf_opt *opt,u_char **args,int argnum) {
00502   t_array *modules = (t_array *)opt->data;
00503   void *mod = dlopen(args[0],RTLD_LAZY);
00504   char *error;
00505   t_module module = { NULL, NULL, NULL };
00506 
00507   if(mod) {
00508     void *mod_cfg_p = dlsym(mod,args[1]);
00509 
00510     if((error = (char *)dlerror()) == NULL) {
00511       t_module_config *mod_cfg = (t_module_config *)mod_cfg_p;
00512       int i;
00513 
00514       if(!mod_cfg_p) {
00515         fprintf(stderr,"ERROR: cannot load plugin configuration!\n");
00516         return -1;
00517       }
00518 
00519       if(mod_cfg->cfgopts) {
00520         cfg_register_options(cfile,mod_cfg->cfgopts);
00521       }
00522 
00523       /* register the module in the module list */
00524       if(!modules[0].element_size) {
00525         array_init(&modules[0],sizeof(t_module),cfg_destroy_module);
00526       }
00527 
00528       module.module = mod;
00529       module.cfg    = mod_cfg;
00530 
00531       array_push(&modules[0],&module);
00532 
00533       /* register all handlers */
00534       for(i=0;mod_cfg->handlers[i].handler;i++) {
00535         if(!modules[mod_cfg->handlers[i].handler].element_size) {
00536           array_init(&modules[mod_cfg->handlers[i].handler],sizeof(t_handler_config),NULL);
00537         }
00538 
00539         array_push(&modules[mod_cfg->handlers[i].handler],&mod_cfg->handlers[i]);
00540       }
00541     }
00542     else {
00543       dlclose(mod);
00544       fprintf(stderr,"could not get module conmfig: %s\n",error);
00545       return -1;
00546     }
00547   }
00548   else {
00549     fprintf(stderr,"%s\n",dlerror());
00550   }
00551 
00552   return 0;
00553 }
00554 
00555 /* }}} */
00556 
00557 /* {{{ cfg_cleanup
00558  * Returns: nothing
00559  * Parameters:
00560  *   - t_configuration *cfg  the configuration structure
00561  *
00562  * this function cleans a configuration structure and frees all mem
00563  *
00564  */
00565 void cfg_cleanup(t_configuration *cfg) {
00566   int i,j;
00567   t_name_value *ent = cfg->directives,*entlast = cfg->directives;
00568 
00569   for(j=0;j<cfg->len;j++,ent=entlast) {
00570     entlast = ent->next;
00571 
00572     free(ent->name);
00573 
00574     if(ent->valnum > 0) {
00575       for(i=0;i<ent->valnum;i++) free(ent->values[i]);
00576       free(ent->values);
00577     }
00578 
00579     free(ent);
00580   }
00581 }
00582 /* }}} */
00583 
00584 /* {{{ cfg_destroy_module */
00585 void cfg_destroy_module(void *element) {
00586   t_module *mod = (t_module *)element;
00587 
00588   if(mod->module) {
00589     if(mod->cfg->finish) mod->cfg->finish();
00590     dlclose(mod->module);
00591   }
00592 }
00593 /* }}} */
00594 
00595 /* {{{ cleanup_modules
00596  * Returns: nothing
00597  * Parameters:
00598  *   - t_module *mod   the module structure
00599  *
00600  * this function cleans up the modules
00601  *
00602  */
00603 void cleanup_modules(t_array *modules) {
00604   int i;
00605 
00606   for(i=0;i<MOD_MAX;i++) {
00607     array_destroy(&modules[i]);
00608   }
00609 }
00610 /* }}} */
00611 
00612 /* {{{ cfg_get_value
00613  * Returns: t_name_value *   the configuration entry
00614  * Parameters:
00615  *   - t_configuration *cfg  the configuration structure
00616  *
00617  * this function gets a configuration entry
00618  *
00619  */
00620 t_name_value *cfg_get_value(t_configuration *cfg,const u_char *name) {
00621   t_name_value *ent;
00622 
00623   for(ent=cfg->directives;ent;ent=ent->next) {
00624     if(cf_strcmp(ent->name,name) == 0) {
00625       return ent;
00626     }
00627   }
00628 
00629   return NULL;
00630 }
00631 /* }}} */
00632 
00633 /* {{{ cfg_init_file
00634  * Returns: nothing
00635  * Parameters:
00636  *   - t_configfile *conf  the configfile structure
00637  *   - u_char *filename     the filename of the config file
00638  *
00639  * this function initializes the configfile structure
00640  *
00641  */
00642 void cfg_init_file(t_configfile *conf,u_char *filename) {
00643   conf->filename = strdup(filename);
00644   conf->options  = cf_hash_new(NULL);
00645 }
00646 /* }}} */
00647 
00648 /* {{{ cfg_register_options
00649  * Returns: nothing
00650  * Parameters:
00651  *   - t_configfile *conf  the configfile structure
00652  *   - t_conf_opt *opts    the configuration options to register
00653  *
00654  * this function registers configuration options
00655  *
00656  */
00657 int cfg_register_options(t_configfile *conf,t_conf_opt *opts) {
00658   int i;
00659 
00660   for(i=0;opts[i].name;i++) {
00661     if(cf_hash_get(conf->options,(u_char *)opts[i].name,strlen(opts[i].name)) != NULL) {
00662       errno = EINVAL;
00663       return -1;
00664     }
00665 
00666     cf_hash_set(conf->options,(u_char *)opts[i].name,strlen(opts[i].name),&opts[i],sizeof(opts[i]));
00667   }
00668 
00669   return 0;
00670 }
00671 /* }}} */
00672 
00673 /* {{{ cfg_cleanup_file
00674  * Returns: nothing
00675  * Parameters:
00676  *   - t_configfile *conf  the configfile structure
00677  *
00678  * this function cleans up a configuration file structure
00679  *
00680  */
00681 void cfg_cleanup_file(t_configfile *conf) {
00682   cf_hash_destroy(conf->options);
00683   free(conf->filename);
00684 }
00685 /* }}} */
00686 
00687 /* eof */

Generated on Sun Apr 25 16:37:37 2004 for Classic Forum by doxygen 1.3.5