|
|
1.1 root 1: /* load_cfg.c */
2:
3: /* Synchronet configuration load routines (exported) */
4:
1.1.1.2 ! root 5: /* $Id: load_cfg.c,v 1.54 2004/11/17 11:35:12 rswindell Exp $ */
1.1 root 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: * *
1.1.1.2 ! root 11: * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html *
1.1 root 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"
1.1.1.2 ! root 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 */
1.1 root 46:
47: /****************************************************************************/
48: /* Initializes system and node configuration information and data variables */
49: /****************************************************************************/
1.1.1.2 ! root 50: BOOL DLLCALL load_cfg(scfg_t* cfg, char* text[], BOOL prep, char* error)
1.1 root 51: {
52: char str[256],fname[13];
53: int i;
54: long line=0L;
55: FILE *instream;
1.1.1.2 ! root 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: }
1.1 root 62:
63: free_cfg(cfg); /* free allocated config parameters */
64:
1.1.1.2 ! root 65: cfg->prepped=FALSE; /* reset prepped flag */
1.1 root 66:
67: if(cfg->node_num<1)
68: cfg->node_num=1;
69:
70: backslash(cfg->ctrl_dir);
1.1.1.2 ! root 71: if(read_main_cfg(cfg, error)==FALSE)
1.1 root 72: return(FALSE);
1.1.1.2 ! root 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)
1.1 root 81: return(FALSE);
1.1.1.2 ! root 82: if(read_msgs_cfg(cfg, error)==FALSE)
1.1 root 83: return(FALSE);
1.1.1.2 ! root 84: if(read_file_cfg(cfg, error)==FALSE)
1.1 root 85: return(FALSE);
1.1.1.2 ! root 86: if(read_xtrn_cfg(cfg, error)==FALSE)
1.1 root 87: return(FALSE);
1.1.1.2 ! root 88: if(read_chat_cfg(cfg, error)==FALSE)
1.1 root 89: return(FALSE);
1.1.1.2 ! root 90: if(read_attr_cfg(cfg, error)==FALSE)
1.1 root 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) {
1.1.1.2 ! root 101: sprintf(error,"%d opening %s",errno,str);
! 102: return(FALSE);
! 103: }
1.1 root 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) {
1.1.1.2 ! root 112: sprintf(error,"line %lu in %s: Less than TOTAL_TEXT (%u) strings defined in %s."
! 113: ,i,fname
1.1 root 114: ,TOTAL_TEXT,fname);
1.1.1.2 ! root 115: return(FALSE);
! 116: }
1.1 root 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:
1.1.1.2 ! root 123: if(prep)
! 124: prep_cfg(cfg);
! 125:
! 126: /* Auto-toggle daylight savings time in US time-zones */
! 127: sys_timezone(cfg);
! 128:
1.1 root 129: return(TRUE);
130: }
131:
1.1.1.2 ! root 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: strcpy(cfg->sub[i]->tagline,cfg->qnet_tagline);
! 181:
! 182: /* default origin line */
! 183: if(!cfg->sub[i]->origline[0])
! 184: strcpy(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: sprintf(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:
1.1 root 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);
1.1.1.2 ! root 261: free_attr_cfg(cfg);
1.1 root 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:
1.1.1.2 ! root 284: if(inpath[0]==0)
! 285: return(FALSE);
! 286:
! 287: SAFECOPY(path,inpath);
1.1 root 288:
1.1.1.2 ! root 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]=='/')
1.1 root 295: path[strlen(path)-1]=0;
296:
297: dir=opendir(path);
298: if(dir==NULL) {
1.1.1.2 ! root 299: /* lprintf("Creating directory: %s",path); */
! 300: if(MKDIR(path)) {
! 301: lprintf(LOG_WARNING,"!ERROR %d creating directory: %s",errno,path);
1.1 root 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) {
1.1.1.2 ! root 329: lprintf(LOG_ERR,"No quotation marks in line %d of text.dat",*line);
! 330: return(NULL);
! 331: }
! 332: return(NULL);
! 333: }
1.1 root 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;
1.1.1.2 ! root 347: break;
! 348: }
1.1 root 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++;
1.1.1.2 ! root 359: continue;
! 360: }
1.1 root 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++];
1.1.1.2 ! root 373: tmp[2]=0;
! 374: }
1.1 root 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];
1.1.1.2 ! root 406: break;
! 407: }
! 408: continue;
! 409: }
! 410: str[j]=buf[i++];
! 411: }
1.1 root 412: str[j]=0;
1.1.1.2 ! root 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: }
1.1 root 417: strcpy(p,str);
418: return(p);
419: }
420:
421: /****************************************************************************/
422: /* Reads in ATTR.CFG and initializes the associated variables */
423: /****************************************************************************/
1.1.1.2 ! root 424: BOOL read_attr_cfg(scfg_t* cfg, char* error)
1.1 root 425: {
1.1.1.2 ! root 426: char* p;
1.1 root 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) {
1.1.1.2 ! root 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: }
1.1 root 454: fclose(instream);
1.1.1.2 ! root 455: if(cfg->total_colors<MIN_COLORS)
! 456: cfg->total_colors=MIN_COLORS;
1.1 root 457: return(TRUE);
458: }
459:
1.1.1.2 ! root 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.