|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.