Annotation of sbbs/sbbs3/load_cfg.c, revision 1.1.1.2

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.