|
|
1.1 ! root 1: /* load_cfg.c */ ! 2: ! 3: /* Synchronet configuration load routines (exported) */ ! 4: ! 5: /* $Id: load_cfg.c,v 1.56 2006/01/09 23:41:13 rswindell Exp $ */ ! 6: ! 7: /**************************************************************************** ! 8: * @format.tab-size 4 (Plain Text/Source Code File Header) * ! 9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * ! 10: * * ! 11: * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html * ! 12: * * ! 13: * This program is free software; you can redistribute it and/or * ! 14: * modify it under the terms of the GNU General Public License * ! 15: * as published by the Free Software Foundation; either version 2 * ! 16: * of the License, or (at your option) any later version. * ! 17: * See the GNU General Public License for more details: gpl.txt or * ! 18: * http://www.fsf.org/copyleft/gpl.html * ! 19: * * ! 20: * Anonymous FTP access to the most recent released source is available at * ! 21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * ! 22: * * ! 23: * Anonymous CVS access to the development source and modification history * ! 24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: * ! 25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login * ! 26: * (just hit return, no password is necessary) * ! 27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src * ! 28: * * ! 29: * For Synchronet coding style and modification guidelines, see * ! 30: * http://www.synchro.net/source.html * ! 31: * * ! 32: * You are encouraged to submit any modifications (preferably in Unix diff * ! 33: * format) via e-mail to [email protected] * ! 34: * * ! 35: * Note: If this box doesn't appear square, then you need to fix your tabs. * ! 36: ****************************************************************************/ ! 37: ! 38: #include "sbbs.h" ! 39: #include "text.h" /* TOTAL_TEXT */ ! 40: ! 41: static void prep_cfg(scfg_t* cfg); ! 42: static void free_attr_cfg(scfg_t* cfg); ! 43: ! 44: char * readtext(long *line, FILE *stream); ! 45: int lprintf(int level, char *fmt, ...); /* log output */ ! 46: ! 47: /****************************************************************************/ ! 48: /* Initializes system and node configuration information and data variables */ ! 49: /****************************************************************************/ ! 50: BOOL DLLCALL load_cfg(scfg_t* cfg, char* text[], BOOL prep, char* error) ! 51: { ! 52: char str[256],fname[13]; ! 53: int i; ! 54: long line=0L; ! 55: FILE *instream; ! 56: ! 57: if(cfg->size!=sizeof(scfg_t)) { ! 58: sprintf(error,"cfg->size (%ld) != sizeof(scfg_t) (%d)" ! 59: ,cfg->size,sizeof(scfg_t)); ! 60: return(FALSE); ! 61: } ! 62: ! 63: free_cfg(cfg); /* free allocated config parameters */ ! 64: ! 65: cfg->prepped=FALSE; /* reset prepped flag */ ! 66: ! 67: if(cfg->node_num<1) ! 68: cfg->node_num=1; ! 69: ! 70: backslash(cfg->ctrl_dir); ! 71: if(read_main_cfg(cfg, error)==FALSE) ! 72: return(FALSE); ! 73: ! 74: if(prep) ! 75: for(i=0;i<cfg->sys_nodes;i++) ! 76: prep_dir(cfg->ctrl_dir, cfg->node_path[i], sizeof(cfg->node_path[i])); ! 77: ! 78: SAFECOPY(cfg->node_dir,cfg->node_path[cfg->node_num-1]); ! 79: prep_dir(cfg->ctrl_dir, cfg->node_dir, sizeof(cfg->node_dir)); ! 80: if(read_node_cfg(cfg, error)==FALSE) ! 81: return(FALSE); ! 82: if(read_msgs_cfg(cfg, error)==FALSE) ! 83: return(FALSE); ! 84: if(read_file_cfg(cfg, error)==FALSE) ! 85: return(FALSE); ! 86: if(read_xtrn_cfg(cfg, error)==FALSE) ! 87: return(FALSE); ! 88: if(read_chat_cfg(cfg, error)==FALSE) ! 89: return(FALSE); ! 90: if(read_attr_cfg(cfg, error)==FALSE) ! 91: return(FALSE); ! 92: ! 93: if(text!=NULL) { ! 94: ! 95: /* Free existing text if allocated */ ! 96: free_text(text); ! 97: ! 98: strcpy(fname,"text.dat"); ! 99: sprintf(str,"%s%s",cfg->ctrl_dir,fname); ! 100: if((instream=fnopen(NULL,str,O_RDONLY))==NULL) { ! 101: sprintf(error,"%d opening %s",errno,str); ! 102: return(FALSE); ! 103: } ! 104: for(i=0;i<TOTAL_TEXT && !feof(instream) && !ferror(instream);i++) ! 105: if((text[i]=readtext(&line,instream))==NULL) { ! 106: i--; ! 107: break; ! 108: } ! 109: fclose(instream); ! 110: ! 111: if(i<TOTAL_TEXT) { ! 112: sprintf(error,"line %lu in %s: Less than TOTAL_TEXT (%u) strings defined in %s." ! 113: ,i,fname ! 114: ,TOTAL_TEXT,fname); ! 115: return(FALSE); ! 116: } ! 117: } ! 118: ! 119: /* Override com-port settings */ ! 120: cfg->com_base=0xf; /* All nodes use FOSSIL */ ! 121: cfg->com_port=1; /* All nodes use "COM1" */ ! 122: ! 123: if(prep) ! 124: prep_cfg(cfg); ! 125: ! 126: /* Auto-toggle daylight savings time in US time-zones */ ! 127: sys_timezone(cfg); ! 128: ! 129: return(TRUE); ! 130: } ! 131: ! 132: /****************************************************************************/ ! 133: /* Prepare configuration for run-time (resolve relative paths, etc) */ ! 134: /****************************************************************************/ ! 135: void prep_cfg(scfg_t* cfg) ! 136: { ! 137: int i; ! 138: ! 139: #if 0 /* def __unix__ */ ! 140: strlwr(cfg->text_dir); /* temporary Unix-compatibility hack */ ! 141: strlwr(cfg->temp_dir); /* temporary Unix-compatibility hack */ ! 142: strlwr(cfg->data_dir); /* temporary Unix-compatibility hack */ ! 143: strlwr(cfg->exec_dir); /* temporary Unix-compatibility hack */ ! 144: #endif ! 145: ! 146: /* Fix-up paths */ ! 147: prep_dir(cfg->ctrl_dir, cfg->data_dir, sizeof(cfg->data_dir)); ! 148: prep_dir(cfg->ctrl_dir, cfg->logs_dir, sizeof(cfg->logs_dir)); ! 149: prep_dir(cfg->ctrl_dir, cfg->exec_dir, sizeof(cfg->exec_dir)); ! 150: prep_dir(cfg->ctrl_dir, cfg->mods_dir, sizeof(cfg->mods_dir)); ! 151: prep_dir(cfg->ctrl_dir, cfg->text_dir, sizeof(cfg->text_dir)); ! 152: ! 153: prep_dir(cfg->ctrl_dir, cfg->netmail_dir, sizeof(cfg->netmail_dir)); ! 154: prep_dir(cfg->ctrl_dir, cfg->echomail_dir, sizeof(cfg->echomail_dir)); ! 155: prep_dir(cfg->ctrl_dir, cfg->fidofile_dir, sizeof(cfg->fidofile_dir)); ! 156: ! 157: prep_path(cfg->netmail_sem); ! 158: prep_path(cfg->echomail_sem); ! 159: prep_path(cfg->inetmail_sem); ! 160: ! 161: #if 0 /* def __unix__ */ ! 162: /* temporary hack for Unix compatibility */ ! 163: strlwr(cfg->logon_mod); ! 164: strlwr(cfg->logoff_mod); ! 165: strlwr(cfg->newuser_mod); ! 166: strlwr(cfg->login_mod); ! 167: strlwr(cfg->logout_mod); ! 168: strlwr(cfg->sync_mod); ! 169: strlwr(cfg->expire_mod); ! 170: #endif ! 171: ! 172: for(i=0;i<cfg->total_subs;i++) { ! 173: ! 174: if(!cfg->sub[i]->data_dir[0]) /* no data storage path specified */ ! 175: sprintf(cfg->sub[i]->data_dir,"%ssubs",cfg->data_dir); ! 176: prep_dir(cfg->ctrl_dir, cfg->sub[i]->data_dir, sizeof(cfg->sub[i]->data_dir)); ! 177: ! 178: /* default QWKnet tagline */ ! 179: if(!cfg->sub[i]->tagline[0]) ! 180: SAFECOPY(cfg->sub[i]->tagline,cfg->qnet_tagline); ! 181: ! 182: /* default origin line */ ! 183: if(!cfg->sub[i]->origline[0]) ! 184: SAFECOPY(cfg->sub[i]->origline,cfg->origline); ! 185: ! 186: /* A sub-board's internal code is the combination of the grp's code_prefix & the sub's code_suffix */ ! 187: SAFEPRINTF2(cfg->sub[i]->code,"%s%s" ! 188: ,cfg->grp[cfg->sub[i]->grp]->code_prefix ! 189: ,cfg->sub[i]->code_suffix); ! 190: ! 191: strlwr(cfg->sub[i]->code); /* data filenames are all lowercase */ ! 192: ! 193: prep_path(cfg->sub[i]->post_sem); ! 194: } ! 195: ! 196: for(i=0;i<cfg->total_libs;i++) { ! 197: if(cfg->lib[i]->parent_path[0]) ! 198: prep_dir(cfg->ctrl_dir, cfg->lib[i]->parent_path, sizeof(cfg->lib[i]->parent_path)); ! 199: } ! 200: ! 201: for(i=0;i<cfg->total_dirs;i++) { ! 202: ! 203: if(!cfg->dir[i]->data_dir[0]) /* no data storage path specified */ ! 204: sprintf(cfg->dir[i]->data_dir,"%sdirs",cfg->data_dir); ! 205: prep_dir(cfg->ctrl_dir, cfg->dir[i]->data_dir, sizeof(cfg->dir[i]->data_dir)); ! 206: ! 207: if(!cfg->dir[i]->path[0]) /* no file storage path specified */ ! 208: sprintf(cfg->dir[i]->path,"%sdirs/%s/",cfg->data_dir,cfg->dir[i]->code); ! 209: else if(cfg->lib[cfg->dir[i]->lib]->parent_path[0]) ! 210: prep_dir(cfg->lib[cfg->dir[i]->lib]->parent_path, cfg->dir[i]->path, sizeof(cfg->dir[i]->path)); ! 211: else ! 212: prep_dir(cfg->ctrl_dir, cfg->dir[i]->path, sizeof(cfg->dir[i]->path)); ! 213: ! 214: /* A directory's internal code is the combination of the lib's code_prefix & the dir's code_suffix */ ! 215: sprintf(cfg->dir[i]->code,"%s%s" ! 216: ,cfg->lib[cfg->dir[i]->lib]->code_prefix ! 217: ,cfg->dir[i]->code_suffix); ! 218: ! 219: strlwr(cfg->dir[i]->code); /* data filenames are all lowercase */ ! 220: ! 221: prep_path(cfg->dir[i]->upload_sem); ! 222: } ! 223: ! 224: ! 225: /* make data filenames are all lowercase */ ! 226: for(i=0;i<cfg->total_shells;i++) ! 227: strlwr(cfg->shell[i]->code); ! 228: ! 229: for(i=0;i<cfg->total_gurus;i++) ! 230: strlwr(cfg->guru[i]->code); ! 231: ! 232: for(i=0;i<cfg->total_txtsecs;i++) ! 233: strlwr(cfg->txtsec[i]->code); ! 234: ! 235: for(i=0;i<cfg->total_xtrnsecs;i++) ! 236: strlwr(cfg->xtrnsec[i]->code); ! 237: ! 238: for(i=0;i<cfg->total_xtrns;i++) ! 239: { ! 240: strlwr(cfg->xtrn[i]->code); ! 241: prep_dir(cfg->ctrl_dir, cfg->xtrn[i]->path, sizeof(cfg->xtrn[i]->path)); ! 242: } ! 243: for(i=0;i<cfg->total_events;i++) { ! 244: strlwr(cfg->event[i]->code); /* data filenames are all lowercase */ ! 245: prep_dir(cfg->ctrl_dir, cfg->event[i]->dir, sizeof(cfg->event[i]->dir)); ! 246: } ! 247: for(i=0;i<cfg->total_xedits;i++) ! 248: strlwr(cfg->xedit[i]->code); ! 249: ! 250: cfg->prepped=TRUE; /* data prepared for run-time, DO NOT SAVE TO DISK! */ ! 251: } ! 252: ! 253: void DLLCALL free_cfg(scfg_t* cfg) ! 254: { ! 255: free_node_cfg(cfg); ! 256: free_main_cfg(cfg); ! 257: free_msgs_cfg(cfg); ! 258: free_file_cfg(cfg); ! 259: free_chat_cfg(cfg); ! 260: free_xtrn_cfg(cfg); ! 261: free_attr_cfg(cfg); ! 262: } ! 263: ! 264: void DLLCALL free_text(char* text[]) ! 265: { ! 266: int i; ! 267: ! 268: if(text==NULL) ! 269: return; ! 270: ! 271: for(i=0;i<TOTAL_TEXT;i++) { ! 272: FREE_AND_NULL(text[i]); ! 273: } ! 274: } ! 275: ! 276: /****************************************************************************/ ! 277: /* If the directory 'path' doesn't exist, create it. */ ! 278: /****************************************************************************/ ! 279: BOOL md(char *inpath) ! 280: { ! 281: DIR* dir; ! 282: char path[MAX_PATH+1]; ! 283: ! 284: if(inpath[0]==0) ! 285: return(FALSE); ! 286: ! 287: SAFECOPY(path,inpath); ! 288: ! 289: /* Remove trailing '.' if present */ ! 290: if(path[strlen(path)-1]=='.') ! 291: path[strlen(path)-1]=0; ! 292: ! 293: /* Remove trailing slash if present */ ! 294: if(path[strlen(path)-1]=='\\' || path[strlen(path)-1]=='/') ! 295: path[strlen(path)-1]=0; ! 296: ! 297: dir=opendir(path); ! 298: if(dir==NULL) { ! 299: /* lprintf("Creating directory: %s",path); */ ! 300: if(MKDIR(path)) { ! 301: lprintf(LOG_WARNING,"!ERROR %d creating directory: %s",errno,path); ! 302: return(FALSE); ! 303: } ! 304: } ! 305: else ! 306: closedir(dir); ! 307: ! 308: return(TRUE); ! 309: } ! 310: ! 311: /****************************************************************************/ ! 312: /* Reads special TEXT.DAT printf style text lines, splicing multiple lines, */ ! 313: /* replacing escaped characters, and allocating the memory */ ! 314: /****************************************************************************/ ! 315: char *readtext(long *line,FILE *stream) ! 316: { ! 317: char buf[2048],str[2048],tmp[256],*p,*p2; ! 318: int i,j,k; ! 319: ! 320: if(!fgets(buf,256,stream)) ! 321: return(NULL); ! 322: if(line) ! 323: (*line)++; ! 324: if(buf[0]=='#') ! 325: return(NULL); ! 326: p=strrchr(buf,'"'); ! 327: if(!p) { ! 328: if(line) { ! 329: lprintf(LOG_ERR,"No quotation marks in line %d of text.dat",*line); ! 330: return(NULL); ! 331: } ! 332: return(NULL); ! 333: } ! 334: if(*(p+1)=='\\') /* merge multiple lines */ ! 335: while(strlen(buf)<2000) { ! 336: if(!fgets(str,255,stream)) ! 337: return(NULL); ! 338: if(line) ! 339: (*line)++; ! 340: p2=strchr(str,'"'); ! 341: if(!p2) ! 342: continue; ! 343: strcpy(p,p2+1); ! 344: p=strrchr(p,'"'); ! 345: if(p && *(p+1)=='\\') ! 346: continue; ! 347: break; ! 348: } ! 349: *(p)=0; ! 350: k=strlen(buf); ! 351: for(i=1,j=0;i<k;j++) { ! 352: if(buf[i]=='\\') { /* escape */ ! 353: i++; ! 354: if(isdigit(buf[i])) { ! 355: str[j]=atoi(buf+i); /* decimal, NOT octal */ ! 356: if(isdigit(buf[++i])) /* skip up to 3 digits */ ! 357: if(isdigit(buf[++i])) ! 358: i++; ! 359: continue; ! 360: } ! 361: switch(buf[i++]) { ! 362: case '\\': ! 363: str[j]='\\'; ! 364: break; ! 365: case '?': ! 366: str[j]='?'; ! 367: break; ! 368: case 'x': ! 369: tmp[0]=buf[i++]; /* skip next character */ ! 370: tmp[1]=0; ! 371: if(isxdigit(buf[i])) { /* if another hex digit, skip too */ ! 372: tmp[1]=buf[i++]; ! 373: tmp[2]=0; ! 374: } ! 375: str[j]=(char)ahtoul(tmp); ! 376: break; ! 377: case '\'': ! 378: str[j]='\''; ! 379: break; ! 380: case '"': ! 381: str[j]='"'; ! 382: break; ! 383: case 'r': ! 384: str[j]=CR; ! 385: break; ! 386: case 'n': ! 387: str[j]=LF; ! 388: break; ! 389: case 't': ! 390: str[j]=TAB; ! 391: break; ! 392: case 'b': ! 393: str[j]=BS; ! 394: break; ! 395: case 'a': ! 396: str[j]=BEL; ! 397: break; ! 398: case 'f': ! 399: str[j]=FF; ! 400: break; ! 401: case 'v': ! 402: str[j]=11; /* VT */ ! 403: break; ! 404: default: ! 405: str[j]=buf[i]; ! 406: break; ! 407: } ! 408: continue; ! 409: } ! 410: str[j]=buf[i++]; ! 411: } ! 412: str[j]=0; ! 413: if((p=(char *)calloc(1,j+2))==NULL) { /* +1 for terminator, +1 for YNQX line */ ! 414: lprintf(LOG_CRIT,"Error allocating %u bytes of memory from text.dat",j); ! 415: return(NULL); ! 416: } ! 417: strcpy(p,str); ! 418: return(p); ! 419: } ! 420: ! 421: /****************************************************************************/ ! 422: /* Reads in ATTR.CFG and initializes the associated variables */ ! 423: /****************************************************************************/ ! 424: BOOL read_attr_cfg(scfg_t* cfg, char* error) ! 425: { ! 426: char* p; ! 427: char str[256],fname[13]; ! 428: long offset=0; ! 429: FILE *instream; ! 430: ! 431: strcpy(fname,"attr.cfg"); ! 432: sprintf(str,"%s%s",cfg->ctrl_dir,fname); ! 433: if((instream=fnopen(NULL,str,O_RDONLY))==NULL) { ! 434: sprintf(error,"%d opening %s",errno,str); ! 435: return(FALSE); ! 436: } ! 437: FREE_AND_NULL(cfg->color); ! 438: if((cfg->color=malloc(MIN_COLORS))==NULL) { ! 439: sprintf(error,"Error allocating memory (%u bytes) for colors" ! 440: ,MIN_COLORS); ! 441: return(FALSE); ! 442: } ! 443: memset(cfg->color,LIGHTGRAY|HIGH,MIN_COLORS); ! 444: for(cfg->total_colors=0;!feof(instream) && !ferror(instream);cfg->total_colors++) { ! 445: if(readline(&offset,str,4,instream)==NULL) ! 446: break; ! 447: if(cfg->total_colors>=MIN_COLORS) { ! 448: if((p=realloc(cfg->color,cfg->total_colors+1))==NULL) ! 449: break; ! 450: cfg->color=p; ! 451: } ! 452: cfg->color[cfg->total_colors]=attrstr(str); ! 453: } ! 454: fclose(instream); ! 455: if(cfg->total_colors<MIN_COLORS) ! 456: cfg->total_colors=MIN_COLORS; ! 457: return(TRUE); ! 458: } ! 459: ! 460: static void free_attr_cfg(scfg_t* cfg) ! 461: { ! 462: if(cfg->color!=NULL) ! 463: FREE_AND_NULL(cfg->color); ! 464: cfg->total_colors=0; ! 465: } ! 466: ! 467: char* DLLCALL prep_dir(char* base, char* path, size_t buflen) ! 468: { ! 469: #ifdef __unix__ ! 470: char *p; ! 471: #endif ! 472: char str[MAX_PATH+1]; ! 473: char abspath[MAX_PATH+1]; ! 474: char ch; ! 475: ! 476: if(!path[0]) ! 477: return(path); ! 478: if(path[0]!='\\' && path[0]!='/' && path[1]!=':') { /* Relative directory */ ! 479: ch=*lastchar(base); ! 480: if(ch=='\\' || ch=='/') ! 481: sprintf(str,"%s%s",base,path); ! 482: else ! 483: sprintf(str,"%s%c%s",base,PATH_DELIM,path); ! 484: } else ! 485: strcpy(str,path); ! 486: ! 487: #ifdef __unix__ /* Change backslashes to forward slashes on Unix */ ! 488: for(p=str;*p;p++) ! 489: if(*p=='\\') ! 490: *p='/'; ! 491: #endif ! 492: ! 493: backslashcolon(str); ! 494: strcat(str,"."); /* Change C: to C:. and C:\SBBS\ to C:\SBBS\. */ ! 495: FULLPATH(abspath,str,buflen); /* Change C:\SBBS\NODE1\..\EXEC to C:\SBBS\EXEC */ ! 496: backslash(abspath); ! 497: ! 498: sprintf(path,"%.*s",(int)(buflen-1),abspath); ! 499: return(path); ! 500: } ! 501: ! 502: char* prep_path(char* path) ! 503: { ! 504: #ifdef __unix__ /* Change backslashes to forward slashes on Unix */ ! 505: char *p; ! 506: ! 507: for(p=path;*p;p++) ! 508: if(*p=='\\') ! 509: *p='/'; ! 510: #endif ! 511: ! 512: return(path); ! 513: } ! 514: ! 515: /****************************************************************************/ ! 516: /* Auto-toggle daylight savings time in US time-zones */ ! 517: /****************************************************************************/ ! 518: ushort DLLCALL sys_timezone(scfg_t* cfg) ! 519: { ! 520: time_t now; ! 521: struct tm tm; ! 522: ! 523: if(cfg->sys_misc&SM_AUTO_DST && !OTHER_ZONE(cfg->sys_timezone) && cfg->sys_timezone&US_ZONE) { ! 524: now=time(NULL); ! 525: if(localtime_r(&now,&tm)!=NULL) { ! 526: if(tm.tm_isdst>0) ! 527: cfg->sys_timezone|=DAYLIGHT; ! 528: else if(tm.tm_isdst==0) ! 529: cfg->sys_timezone&=~DAYLIGHT; ! 530: } ! 531: } ! 532: ! 533: return(cfg->sys_timezone); ! 534: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.