00001
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00045
00046
00047
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
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
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
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
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
00217
00218
00219
00220
00221
00222
00223
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
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
00287
00288 for(;*ptr && isspace(*ptr) && *ptr != (u_char)012;ptr++);
00289 if(*ptr == (u_char)012 || *ptr == (u_char)0 || *ptr == '#') break;
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
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
00334 if(len >= 0 && !(*args)[len]) (*args)[len] = strdup("\0");
00335
00336 return len + 1;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
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
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
00384
00385 while(*ptr) {
00386
00387 ++linenum;
00388
00389
00390 for(;*ptr && isspace(*ptr);ptr++);
00391
00392
00393 if(!*ptr) break;
00394
00395
00396 if(*ptr == '#') {
00397
00398 for(;*ptr && *ptr != (u_char)012;ptr++);
00399 if(!*ptr) break;
00400 ptr += 1;
00401 continue;
00402 }
00403
00404
00405 if(*ptr == (u_char)012) {
00406 ptr += 1;
00407 continue;
00408 }
00409
00410
00411 ptr1 = ptr;
00412
00413
00414 for(;*ptr && !isspace(*ptr);ptr++);
00415
00416
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
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
00457 for(;*ptr && *ptr != (u_char)012;ptr++);
00458
00459
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
00473
00474
00475
00476
00477
00478
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
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
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
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
00558
00559
00560
00561
00562
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
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
00596
00597
00598
00599
00600
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
00613
00614
00615
00616
00617
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
00634
00635
00636
00637
00638
00639
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
00649
00650
00651
00652
00653
00654
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
00674
00675
00676
00677
00678
00679
00680
00681 void cfg_cleanup_file(t_configfile *conf) {
00682 cf_hash_destroy(conf->options);
00683 free(conf->filename);
00684 }
00685
00686
00687