Annotation of sbbs/src/sbbs3/str_util.c, revision 1.1.1.1

1.1       root        1: /* str_util.c */
                      2: 
                      3: /* Synchronet string utility routines */
                      4: 
                      5: /* $Id: str_util.c,v 1.35 2006/01/26 00:52:47 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 2006 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: 
                     40: /****************************************************************************/
                     41: /* Removes ctrl-a codes from the string 'instr'                             */
                     42: /****************************************************************************/
                     43: char* DLLCALL remove_ctrl_a(char *instr, char *outstr)
                     44: {
                     45:        char str[1024],*p;
                     46:        uint i,j;
                     47: 
                     48:        for(i=j=0;instr[i] && j<sizeof(str)-1;i++) {
                     49:                if(instr[i]==CTRL_A && instr[i+1]!=0)
                     50:                        i++;
                     51:                else str[j++]=instr[i]; 
                     52:        }
                     53:        str[j]=0;
                     54:        if(outstr!=NULL)
                     55:                p=outstr;
                     56:        else
                     57:                p=instr;
                     58:        strcpy(p,str);
                     59:        return(p);
                     60: }
                     61: 
                     62: char* DLLCALL strip_ctrl(char *str)
                     63: {
                     64:        char tmp[1024];
                     65:        int i,j;
                     66: 
                     67:        for(i=j=0;str[i] && j<(int)sizeof(tmp)-1;i++) {
                     68:                if(str[i]==CTRL_A && str[i+1]!=0)
                     69:                        i++;
                     70:                else if((uchar)str[i]>=' ')
                     71:                        tmp[j++]=str[i];
                     72:        }
                     73:        if(i!=j) {
                     74:                tmp[j]=0;
                     75:                strcpy(str,tmp);
                     76:        }
                     77:        return(str);
                     78: }
                     79: 
                     80: char* DLLCALL strip_exascii(char *str)
                     81: {
                     82:        char tmp[1024];
                     83:        int i,j;
                     84: 
                     85:        for(i=j=0;str[i] && j<(int)sizeof(tmp)-1;i++)
                     86:                if(!(str[i]&0x80))
                     87:                        tmp[j++]=str[i];
                     88:        tmp[j]=0;
                     89:        strcpy(str,tmp);
                     90:        return(str);
                     91: }
                     92: 
                     93: char* DLLCALL prep_file_desc(char *str)
                     94: {
                     95:        char tmp[1024];
                     96:        int i,j;
                     97: 
                     98:        for(i=j=0;str[i];i++)
                     99:                if(str[i]==CTRL_A && str[i+1]!=0)
                    100:                        i++;
                    101:                else if(j && str[i]<=' ' && tmp[j-1]==' ')
                    102:                        continue;
                    103:                else if(i && !isalnum(str[i]) && str[i]==str[i-1])
                    104:                        continue;
                    105:                else if((uchar)str[i]>=' ')
                    106:                        tmp[j++]=str[i];
                    107:                else if(str[i]==TAB || (str[i]==CR && str[i+1]==LF))
                    108:                        tmp[j++]=' ';
                    109:        tmp[j]=0;
                    110:        strcpy(str,tmp);
                    111:        return(str);
                    112: }
                    113: 
                    114: /****************************************************************************/
                    115: /* Pattern matching string search of 'insearchof' in 'fname'.                          */
                    116: /****************************************************************************/
                    117: BOOL DLLCALL findstr(char* insearchof, char* fname)
                    118: {
                    119:        char*   p;
                    120:        char    str[128];
                    121:        char    search[81];
                    122:        int             c;
                    123:        int             i;
                    124:        BOOL    found;
                    125:        FILE*   stream;
                    126: 
                    127:        if((stream=fopen(fname,"r"))==NULL)
                    128:                return(FALSE); 
                    129: 
                    130:        SAFECOPY(search,insearchof);
                    131:        strupr(search);
                    132: 
                    133:        found=FALSE;
                    134: 
                    135:        while(!feof(stream) && !ferror(stream) && !found) {
                    136:                if(!fgets(str,sizeof(str),stream))
                    137:                        break;
                    138:                
                    139:                found=FALSE;
                    140: 
                    141:                p=str;  
                    142:                while(*p && *p<=' ') p++; /* Skip white-space */
                    143: 
                    144:                if(*p==';')             /* comment */
                    145:                        continue;
                    146: 
                    147:                if(*p=='!')     {       /* !match */
                    148:                        found=TRUE;
                    149:                        p++;
                    150:                }
                    151: 
                    152:                truncsp(p);
                    153:                c=strlen(p);
                    154:                if(c) {
                    155:                        c--;
                    156:                        strupr(p);
                    157:                        if(p[c]=='~') {
                    158:                                p[c]=0;
                    159:                                if(strstr(search,p))
                    160:                                        found=!found; 
                    161:                        }
                    162: 
                    163:                        else if(p[c]=='^' || p[c]=='*') {
                    164:                                p[c]=0;
                    165:                                if(!strncmp(p,search,c))
                    166:                                        found=!found; 
                    167:                        }
                    168: 
                    169:                        else if(p[0]=='*') {
                    170:                                i=strlen(search);
                    171:                                if(i<c)
                    172:                                        continue;
                    173:                                if(!strncmp(p+1,search+(i-c),c))
                    174:                                        found=!found; 
                    175:                        }
                    176: 
                    177:                        else if(!strcmp(p,search))
                    178:                                found=!found; 
                    179:                } 
                    180:        }
                    181:        fclose(stream);
                    182:        return(found);
                    183: }
                    184: 
                    185: /****************************************************************************/
                    186: /* Searches the file <name>.can in the TEXT directory for matches                      */
                    187: /* Returns TRUE if found in list, FALSE if not.                                                                */
                    188: /****************************************************************************/
                    189: BOOL DLLCALL trashcan(scfg_t* cfg, char* insearchof, char* name)
                    190: {
                    191:        char fname[MAX_PATH+1];
                    192: 
                    193:        sprintf(fname,"%s%s.can",cfg->text_dir,name);
                    194:        return(findstr(insearchof,fname));
                    195: }
                    196: 
                    197: /****************************************************************************/
                    198: /* Returns the number of characters in 'str' not counting ctrl-ax codes                */
                    199: /* or the null terminator                                                                                                      */
                    200: /****************************************************************************/
                    201: int bstrlen(char *str)
                    202: {
                    203:        int i=0;
                    204: 
                    205:        while(*str) {
                    206:                if(*str==CTRL_A)
                    207:                        str++;
                    208:                else
                    209:                        i++;
                    210:                if(!(*str)) break;
                    211:                str++; }
                    212:        return(i);
                    213: }
                    214: 
                    215: /****************************************************************************/
                    216: /* Returns in 'string' a character representation of the number in l with   */
                    217: /* commas.                                                                                                                                     */
                    218: /****************************************************************************/
                    219: char* DLLCALL ultoac(ulong l, char *string)
                    220: {
                    221:        char str[256];
                    222:        int i,j,k;
                    223: 
                    224:        ultoa(l,str,10);
                    225:        i=strlen(str)-1;
                    226:        j=i/3+1+i;
                    227:        string[j--]=0;
                    228:        for(k=1;i>-1;k++) {
                    229:                string[j--]=str[i--];
                    230:                if(j>0 && !(k%3))
                    231:                        string[j--]=','; }
                    232:        return(string);
                    233: }
                    234: 
                    235: /****************************************************************************/
                    236: /* Truncate string at first occurance of char in specified character set       */
                    237: /****************************************************************************/
                    238: char* DLLCALL truncstr(char* str, const char* set)
                    239: {
                    240:        char* p;
                    241: 
                    242:        p=strpbrk(str,set);
                    243:        if(p!=NULL && *p!=0)
                    244:                *p=0;
                    245: 
                    246:        return(p);
                    247: }
                    248: 
                    249: /****************************************************************************/
                    250: /* rot13 encoder/decoder - courtesy of Mike Acar                                                       */
                    251: /****************************************************************************/
                    252: char* DLLCALL rot13(char* str)
                    253: {
                    254:        char ch, cap;
                    255:        char* p;
                    256:   
                    257:        p=str;
                    258:        while((ch=*p)!=0) {
                    259:                cap = ch & 32;
                    260:                ch &= ~cap;
                    261:                ch = ((ch >= 'A') && (ch <= 'Z') ? ((ch - 'A' + 13) % 26 + 'A') : ch) | cap;
                    262:                *(p++)=ch;
                    263:     }
                    264: 
                    265:        return(str);
                    266: }
                    267: 
                    268: /****************************************************************************/
                    269: /* Puts a backslash on path strings if not just a drive letter and colon       */
                    270: /****************************************************************************/
                    271: void backslashcolon(char *str)
                    272: {
                    273:     int i;
                    274: 
                    275:        i=strlen(str);
                    276:        if(i && !IS_PATH_DELIM(str[i-1]) && str[i-1]!=':') {
                    277:                str[i]=PATH_DELIM; 
                    278:                str[i+1]=0; 
                    279:        }
                    280: }
                    281: 
                    282: /****************************************************************************/
                    283: /* Compares pointers to pointers to char. Used in conjuction with qsort()   */
                    284: /****************************************************************************/
                    285: int pstrcmp(char **str1, char **str2)
                    286: {
                    287:        return(strcmp(*str1,*str2));
                    288: }
                    289: 
                    290: /****************************************************************************/
                    291: /* Returns the number of characters that are the same between str1 and str2 */
                    292: /****************************************************************************/
                    293: int strsame(char *str1, char *str2)
                    294: {
                    295:        int i,j=0;
                    296: 
                    297:        for(i=0;str1[i];i++)
                    298:                if(str1[i]==str2[i]) j++;
                    299:        return(j);
                    300: }
                    301: 
                    302: 
                    303: /****************************************************************************/
                    304: /* Returns string for 2 digit hex+ numbers up to 575                                           */
                    305: /****************************************************************************/
                    306: char *hexplus(uint num, char *str)
                    307: {
                    308:        sprintf(str,"%03x",num);
                    309:        str[0]=num/0x100 ? 'f'+(num/0x10)-0xf : str[1];
                    310:        str[1]=str[2];
                    311:        str[2]=0;
                    312:        return(str);
                    313: }
                    314: 
                    315: /****************************************************************************/
                    316: /* Converts an ASCII Hex string into an ulong                               */
                    317: /* by Steve Deppe (Ille Homine Albe)                                                                           */
                    318: /****************************************************************************/
                    319: ulong ahtoul(char *str)
                    320: {
                    321:     ulong l,val=0;
                    322: 
                    323:        while((l=(*str++)|0x20)!=0x20)
                    324:                val=(l&0xf)+(l>>6&1)*9+val*16;
                    325:        return(val);
                    326: }
                    327: 
                    328: /****************************************************************************/
                    329: /* Converts hex-plus string to integer                                                                         */
                    330: /****************************************************************************/
                    331: uint hptoi(char *str)
                    332: {
                    333:        char tmp[128];
                    334:        uint i;
                    335: 
                    336:        if(!str[1] || toupper(str[0])<='F')
                    337:                return(ahtoul(str));
                    338:        strcpy(tmp,str);
                    339:        tmp[0]='F';
                    340:        i=ahtoul(tmp)+((toupper(str[0])-'F')*0x10);
                    341:        return(i);
                    342: }
                    343: 
                    344: /****************************************************************************/
                    345: /* Returns 1 if a is a valid ctrl-a code, 0 if it isn't.                    */
                    346: /****************************************************************************/
                    347: BOOL DLLCALL validattr(char a)
                    348: {
                    349: 
                    350:        switch(toupper(a)) {
                    351:                case '+':       /* push attr    */
                    352:                case '-':   /* pop attr         */
                    353:                case '_':   /* clear        */
                    354:                case 'B':   /* blue     fg  */
                    355:                case 'C':   /* cyan     fg  */
                    356:                case 'G':   /* green    fg  */
                    357:                case 'H':   /* high     fg  */
                    358:                case 'I':   /* blink        */
                    359:                case 'K':   /* black    fg  */
                    360:                case 'L':   /* cls          */
                    361:                case 'M':   /* magenta  fg  */
                    362:                case 'N':   /* normal       */
                    363:                case 'P':   /* pause        */
                    364:                case 'R':   /* red      fg  */
                    365:                case 'W':   /* white    fg  */
                    366:                case 'Y':   /* yellow   fg  */
                    367:                case '0':   /* black    bg  */
                    368:                case '1':   /* red      bg  */
                    369:                case '2':   /* green    bg  */
                    370:                case '3':   /* brown    bg  */
                    371:                case '4':   /* blue     bg  */
                    372:                case '5':   /* magenta  bg  */
                    373:                case '6':   /* cyan     bg  */
                    374:                case '7':   /* white    bg  */
                    375:                        return(TRUE); 
                    376:        }
                    377:        return(FALSE);
                    378: }
                    379: 
                    380: /****************************************************************************/
                    381: /* Strips invalid Ctrl-Ax sequences from str                                */
                    382: /* Returns number of ^A's in line                                           */
                    383: /****************************************************************************/
                    384: size_t DLLCALL strip_invalid_attr(char *strin)
                    385: {
                    386:     char str[1024];
                    387:     size_t a,c,d;
                    388: 
                    389:        for(a=c=d=0;strin[c] && d<sizeof(str)-1;c++) {
                    390:                if(strin[c]==CTRL_A && strin[c+1]!=0) {
                    391:                        a++;
                    392:                        if(!validattr(strin[c+1])) {
                    393:                                c++;
                    394:                                continue; 
                    395:                        } 
                    396:                }
                    397:                str[d++]=strin[c]; 
                    398:        }
                    399:        str[d]=0;
                    400:        strcpy(strin,str);
                    401:        return(a);
                    402: }
                    403: 
                    404: char* replace_named_values(const char* src
                    405:                                           ,char* buf
                    406:                                           ,size_t buflen       /* includes '\0' terminator */
                    407:                                           ,char* escape_seq
                    408:                                           ,named_string_t* string_list
                    409:                                           ,named_int_t* int_list
                    410:                                           ,BOOL case_sensitive)
                    411: {
                    412:        char    val[32];
                    413:        size_t  i;
                    414:        size_t  esc_len=0;
                    415:        size_t  name_len;
                    416:        size_t  value_len;
                    417:        char*   p = buf;
                    418:        int (*cmp)(const char*, const char*, size_t);
                    419: 
                    420:        if(case_sensitive)
                    421:                cmp=strncmp;
                    422:        else
                    423:                cmp=strnicmp;
                    424: 
                    425:        if(escape_seq!=NULL)
                    426:                esc_len = strlen(escape_seq);
                    427: 
                    428:        while(*src && (size_t)(p-buf) < buflen-1) {
                    429:                if(esc_len) {
                    430:                        if(cmp(src, escape_seq, esc_len)!=0) {
                    431:                                *p++ = *src++;
                    432:                                continue;
                    433:                        }
                    434:                        src += esc_len; /* skip the escape seq */
                    435:                }
                    436:                if(string_list) {
                    437:                        for(i=0; string_list[i].name!=NULL /* terminator */; i++) {
                    438:                                name_len = strlen(string_list[i].name);
                    439:                                if(cmp(src, string_list[i].name, name_len)==0) {
                    440:                                        value_len = strlen(string_list[i].value);
                    441:                                        if((p-buf)+value_len > buflen-1)        /* buffer overflow? */
                    442:                                                value_len = (buflen-1)-(p-buf); /* truncate value */
                    443:                                        memcpy(p, string_list[i].value, value_len);
                    444:                                        p += value_len;
                    445:                                        src += name_len;
                    446:                                        break;
                    447:                                }
                    448:                        }
                    449:                        if(string_list[i].name!=NULL) /* variable match */
                    450:                                continue;
                    451:                }
                    452:                if(int_list) {
                    453:                        for(i=0; int_list[i].name!=NULL /* terminator */; i++) {
                    454:                                name_len = strlen(int_list[i].name);
                    455:                                if(cmp(src, int_list[i].name, name_len)==0) {
                    456:                                        SAFEPRINTF(val,"%d",int_list[i].value);
                    457:                                        value_len = strlen(val);
                    458:                                        if((p-buf)+value_len > buflen-1)        /* buffer overflow? */
                    459:                                                value_len = (buflen-1)-(p-buf); /* truncate value */
                    460:                                        memcpy(p, val, value_len);
                    461:                                        p += value_len;
                    462:                                        src += name_len;
                    463:                                        break;
                    464:                                }
                    465:                        }
                    466:                        if(int_list[i].name!=NULL) /* variable match */
                    467:                                continue;
                    468:                }
                    469: 
                    470:                *p++ = *src++;
                    471:        }
                    472:        *p=0;   /* terminate string in destination buffer */
                    473: 
                    474:        return(buf);
                    475: }
                    476: 
                    477: char* replace_keyed_values(const char* src
                    478:                                           ,char* buf
                    479:                                           ,size_t buflen       /* includes '\0' terminator */
                    480:                                           ,char esc_char
                    481:                                           ,keyed_string_t* string_list
                    482:                                           ,keyed_int_t* int_list
                    483:                                           ,BOOL case_sensitive)
                    484: {
                    485:        char    val[32];
                    486:        size_t  i;
                    487:        size_t  value_len;
                    488:        char*   p = buf;
                    489: 
                    490: 
                    491:        while(*src && (size_t)(p-buf) < buflen-1) {
                    492:                if(esc_char) {
                    493:                        if(*src != esc_char) {
                    494:                                *p++ = *src++;
                    495:                                continue;
                    496:                        }
                    497:                        src ++; /* skip the escape char */
                    498:                }
                    499:                if(string_list) {
                    500:                        for(i=0; string_list[i].key!=0 /* terminator */; i++) {
                    501:                                if((case_sensitive && *src == string_list[i].key)
                    502:                                        || ((!case_sensitive) && toupper(*src) == toupper(string_list[i].key))) {
                    503:                                        value_len = strlen(string_list[i].value);
                    504:                                        if((p-buf)+value_len > buflen-1)        /* buffer overflow? */
                    505:                                                value_len = (buflen-1)-(p-buf); /* truncate value */
                    506:                                        memcpy(p, string_list[i].value, value_len);
                    507:                                        p += value_len;
                    508:                                        src++;
                    509:                                        break;
                    510:                                }
                    511:                        }
                    512:                        if(string_list[i].key!=0) /* variable match */
                    513:                                continue;
                    514:                }
                    515:                if(int_list) {
                    516:                        for(i=0; int_list[i].key!=0 /* terminator */; i++) {
                    517:                                if((case_sensitive && *src == int_list[i].key)
                    518:                                        || ((!case_sensitive) && toupper(*src) == toupper(int_list[i].key))) {
                    519:                                        SAFEPRINTF(val,"%d",int_list[i].value);
                    520:                                        value_len = strlen(val);
                    521:                                        if((p-buf)+value_len > buflen-1)        /* buffer overflow? */
                    522:                                                value_len = (buflen-1)-(p-buf); /* truncate value */
                    523:                                        memcpy(p, val, value_len);
                    524:                                        p += value_len;
                    525:                                        src++;
                    526:                                        break;
                    527:                                }
                    528:                        }
                    529:                        if(int_list[i].key!=0) /* variable match */
                    530:                                continue;
                    531:                }
                    532: 
                    533:                *p++ = *src++;
                    534:        }
                    535:        *p=0;   /* terminate string in destination buffer */
                    536: 
                    537:        return(buf);
                    538: }
                    539: 
                    540: 
                    541: #if 0  /* replace_*_values test */
                    542: 
                    543: void main(void)
                    544: {
                    545:        char buf[128];
                    546:        keyed_string_t strs[] = {
                    547:                { '+', "plus" },
                    548:                { '=', "equals" },
                    549:                { 0 }
                    550:        };
                    551:        keyed_int_t ints[] = {
                    552:                { 'o', 1 },
                    553:                { 't', 2 },
                    554:                { 'h', 3 },
                    555:                { NULL }
                    556:        };
                    557: 
                    558:        printf("'%s'\n", replace_keyed_values("$o $+ $t $= $h", buf, sizeof(buf), '$'
                    559:                ,strs, ints, FALSE));
                    560: 
                    561: }
                    562: 
                    563: #endif
                    564: 
                    565: #if 0 /* to be moved here from xtrn.cpp */
                    566: 
                    567: char* quoted_string(const char* str, char* buf, size_t maxlen)
                    568: {
                    569:        if(strchr(str,' ')==NULL)
                    570:                return((char*)str);
                    571:        safe_snprintf(buf,maxlen,"\"%s\"",str);
                    572:        return(buf);
                    573: }
                    574: 
                    575: #endif
                    576: 
                    577: #if 0 /* I think is is a misguided idea :-(  */
                    578: 
                    579: char* sbbs_cmdstr(const char* src
                    580:                                        ,char* buf
                    581:                                        ,size_t buflen  /* includes '\0' terminator */
                    582:                                        ,scfg_t* scfg
                    583:                                        ,user_t* user
                    584:                                        ,int node_num
                    585:                                        ,int minutes
                    586:                                        ,int rows
                    587:                                        ,int timeleft
                    588:                                        ,SOCKET socket_descriptor
                    589:                                        ,char* protocol
                    590:                                        ,char* ip_address
                    591:                                        ,char* fpath
                    592:                                        ,char* fspec
                    593:                                        )
                    594: {
                    595:        const char* nulstr = "";
                    596:        char alias_buf[LEN_ALIAS+1];
                    597:        char fpath_buf[MAX_PATH+1];
                    598:        char fspec_buf[MAX_PATH+1];
                    599:        char sysop_buf[sizeof(scfg->sys_op)];
                    600: 
                    601:        keyed_string_t str_list[] = {
                    602:                /* user alias */
                    603:                { 'a',  user!=NULL ? quoted_string(user->alias, alias_buf, sizeof(alias_buf)) : nulstr },
                    604:                { 'A',  user!=NULL ? user->alias : nulstr },
                    605:                
                    606:                /* connection */
                    607:                { 'c',  protocol },
                    608:                { 'C',  protocol },
                    609: 
                    610:                /* file path */
                    611:                { 'f',  quoted_string(fpath, fpath_buf, sizeof(fpath_buf)) },
                    612:                { 'F',  fpath },
                    613: 
                    614:                /* temp dir */
                    615:                { 'g',  scfg->temp_dir },
                    616:                { 'G',  scfg->temp_dir },
                    617: 
                    618:                /* IP address */
                    619:                { 'h',  ip_address },
                    620:                { 'H',  ip_address },
                    621: 
                    622:                /* data dir */
                    623:                { 'j',  scfg->data_dir },
                    624:                { 'J',  scfg->data_dir },
                    625: 
                    626:                /* ctrl dir */
                    627:                { 'k',  scfg->ctrl_dir },
                    628:                { 'K',  scfg->ctrl_dir },
                    629: 
                    630:                /* node dir */
                    631:                { 'n',  scfg->node_dir },
                    632:                { 'N',  scfg->node_dir },
                    633: 
                    634:                /* sysop */
                    635:                { 'o',  quoted_string(scfg->sys_op, sysop_buf, sizeof(sysop_buf)) },
                    636:                { 'O',  scfg->sys_op },
                    637: 
                    638:                /* protocol */
                    639:                { 'p',  protocol },
                    640:                { 'P',  protocol },
                    641: 
                    642:                /* system QWK-ID */
                    643:                { 'q',  scfg->sys_id },
                    644:                { 'Q',  scfg->sys_id },
                    645: 
                    646:                /* file spec */
                    647:                { 's',  quoted_string(fspec, fspec_buf, sizeof(fspec_buf)) },
                    648:                { 'S',  fspec },
                    649: 
                    650:                /* UART I/O Address (in hex) 'f' for FOSSIL */
                    651:                { 'u',  "f" },
                    652:                { 'U',  "f" },
                    653: 
                    654:                /* text dir */
                    655:                { 'z',  scfg->text_dir },
                    656:                { 'Z',  scfg->text_dir },
                    657: 
                    658:                /* exec dir */
                    659:                { '!',  scfg->exec_dir },
                    660:                { '@',
                    661: #ifndef __unix__
                    662:                        scfg->exec_dir
                    663: #else
                    664:                        nulstr
                    665: #endif
                    666:                },
                    667: 
                    668:                /* .exe (on Windows) */
                    669:                { '.',
                    670: #ifndef __unix__
                    671:                ".exe"
                    672: #else
                    673:                nulstr
                    674: #endif
                    675:                },
                    676: 
                    677:                /* terminator */
                    678:                { 0 }   
                    679:        };
                    680:        keyed_int_t int_list[] = {
                    681:                /* node number */
                    682:                { '#',  node_num },
                    683: 
                    684:                /* DTE rate */
                    685:                { 'b',  38400 },        
                    686:                { 'B',  38400 },
                    687: 
                    688:                /* DCE rate */
                    689:                { 'd',  30000 },
                    690:                { 'D',  30000 },
                    691: 
                    692:                /* Estimated Rate (cps) */
                    693:                { 'e',  3000 },
                    694:                { 'E',  3000 },
                    695: 
                    696:                { 'h',  socket_descriptor },
                    697:                { 'H',  socket_descriptor },
                    698: 
                    699:                { 'l',  user==NULL ? 0 : scfg->level_linespermsg[user->level] },
                    700:                { 'L',  user==NULL ? 0 : scfg->level_linespermsg[user->level] },
                    701: 
                    702:                { 'm',  minutes },
                    703:                { 'M',  minutes },
                    704: 
                    705:                { 'r',  rows },
                    706:                { 'R',  rows },
                    707: 
                    708:                /* Time left in seconds */
                    709:                { 't',  timeleft },
                    710:                { 'T',  timeleft },
                    711: 
                    712:                /* Credits */
                    713:                { '$',  user==NULL ? 0 : (user->cdt+user->freecdt) },
                    714: 
                    715:                /* terminator */
                    716:                { 0 }   
                    717:        };
                    718: 
                    719: 
                    720:        return replace_keyed_values(src, buf, buflen, '%', str_list, int_list, TRUE);
                    721: }
                    722: 
                    723: #endif

unix.superglobalmegacorp.com

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