1: /* $Header: intrp.c,v 4.3.1.5.1 95/01/21 17:21:24 lwall Exp $ 2: * 3: * $Log: intrp.c,v $ 4: * Revision 4.3.1.5 85/05/23 17:21:24 lwall 5: * Now allows 'r' and 'f' on null articles. 6: * 7: * Revision 4.3.1.4 85/05/21 13:35:21 lwall 8: * Sped up "rn -c" by not doing unnecessary initialization. 9: * 10: * Revision 4.3.1.3 85/05/17 10:37:11 lwall 11: * Fixed & substitution to capitalize last name too. 12: * 13: * Revision 4.3.1.2 85/05/15 14:39:45 lwall 14: * Spelled gecos right. 15: * 16: * Revision 4.3.1.1 85/05/10 11:33:51 lwall 17: * Branch for patches. 18: * 19: * Revision 4.3 85/05/01 11:40:54 lwall 20: * Baseline for release with 4.3bsd. 21: * 22: */ 23: 24: #include "EXTERN.h" 25: #include "common.h" 26: #include "util.h" 27: #include "search.h" 28: #include "head.h" 29: #include "rn.h" 30: #include "artsrch.h" 31: #include "ng.h" 32: #include "util.h" 33: #include "respond.h" 34: #include "rcstuff.h" 35: #include "bits.h" 36: #include "artio.h" 37: #include "term.h" 38: #include "final.h" 39: #include "INTERN.h" 40: #include "intrp.h" 41: 42: char orgname[] = ORGNAME; 43: 44: /* name of this site */ 45: #ifdef GETHOSTNAME 46: char *hostname; 47: # undef SITENAME 48: # define SITENAME hostname 49: #else !GETHOSTNAME 50: # ifdef DOUNAME 51: # include <sys/utsname.h> 52: struct utsname uts; 53: # undef SITENAME 54: # define SITENAME uts.nodename 55: # else !DOUNAME 56: # ifdef PHOSTNAME 57: char *hostname; 58: # undef SITENAME 59: # define SITENAME hostname 60: # else !PHOSTNAME 61: # ifdef WHOAMI 62: # undef SITENAME 63: # define SITENAME sysname 64: # endif WHOAMI 65: # endif PHOSTNAME 66: # endif DOUNAME 67: #endif GETHOSTNAME 68: 69: #ifdef TILDENAME 70: static char *tildename = Nullch; 71: static char *tildedir = Nullch; 72: #endif 73: 74: char *realname INIT(Nullch); /* real name of sender from /etc/passwd */ 75: 76: char *dointerp(); 77: char *getrealname(); 78: #ifdef CONDSUB 79: char *skipinterp(); 80: #endif 81: 82: static void abort_interp(); 83: 84: void 85: intrp_init(tcbuf) 86: char *tcbuf; 87: { 88: char *getlogin(); 89: 90: spool = savestr(filexp(SPOOL)); /* usually /usr/spool/news */ 91: 92: /* get environmental stuff */ 93: 94: /* get home directory */ 95: 96: homedir = getenv("HOME"); 97: if (homedir == Nullch) 98: homedir = getenv("LOGDIR"); 99: 100: dotdir = getval("DOTDIR",homedir); 101: 102: /* get login name */ 103: 104: logname = getenv("USER"); 105: if (logname == Nullch) 106: logname = getenv("LOGNAME"); 107: #ifdef GETLOGIN 108: if (logname == Nullch) 109: logname = savestr(getlogin()); 110: #endif 111: 112: if (checkflag) /* that getwd below takes ~1/3 sec. */ 113: return; /* and we do not need it for -c */ 114: getwd(tcbuf); /* find working directory name */ 115: origdir = savestr(tcbuf); /* and remember it */ 116: 117: /* get the real name of the person (%N) */ 118: /* Must be done after logname is read in because BERKNAMES uses that */ 119: 120: strcpy(tcbuf,getrealname(getuid())); 121: realname = savestr(tcbuf); 122: 123: /* name of header file (%h) */ 124: 125: headname = savestr(filexp(HEADNAME)); 126: 127: /* name of this site (%H) */ 128: 129: #ifdef GETHOSTNAME 130: gethostname(buf,sizeof buf); 131: hostname = savestr(buf); 132: #else 133: #ifdef DOUNAME 134: /* get sysname */ 135: uname(&uts); 136: #else 137: #ifdef PHOSTNAME 138: { 139: FILE *popen(); 140: FILE *pipefp = popen(PHOSTNAME,"r"); 141: 142: if (pipefp == Nullfp) { 143: printf("Can't find hostname\n"); 144: sig_catcher(0); 145: } 146: fgets(buf,sizeof buf,pipefp); 147: buf[strlen(buf)-1] = '\0'; /* wipe out newline */ 148: hostname = savestr(buf); 149: pclose(pipefp); 150: } 151: #endif 152: #endif 153: #endif 154: sitename = savestr(SITENAME); 155: } 156: 157: /* expand filename via %, ~, and $ interpretation */ 158: /* returns pointer to static area */ 159: /* Note that there is a 1-deep cache of ~name interpretation */ 160: 161: char * 162: filexp(s) 163: register char *s; 164: { 165: static char filename[CBUFLEN]; 166: char scrbuf[CBUFLEN]; 167: register char *d; 168: 169: #ifdef DEBUGGING 170: if (debug & DEB_FILEXP) 171: printf("< %s\n",s) FLUSH; 172: #endif 173: interp(filename, (sizeof filename), s); /* interpret any % escapes */ 174: #ifdef DEBUGGING 175: if (debug & DEB_FILEXP) 176: printf("%% %s\n",filename) FLUSH; 177: #endif 178: s = filename; 179: if (*s == '~') { /* does destination start with ~? */ 180: if (!*(++s) || *s == '/') { 181: sprintf(scrbuf,"%s%s",homedir,s); 182: /* swap $HOME for it */ 183: #ifdef DEBUGGING 184: if (debug & DEB_FILEXP) 185: printf("~ %s\n",scrbuf) FLUSH; 186: #endif 187: strcpy(filename,scrbuf); 188: } 189: else { 190: #ifdef TILDENAME 191: for (d=scrbuf; isalnum(*s); s++,d++) 192: *d = *s; 193: *d = '\0'; 194: if (tildedir && strEQ(tildename,scrbuf)) { 195: strcpy(scrbuf,tildedir); 196: strcat(scrbuf, s); 197: strcpy(filename, scrbuf); 198: #ifdef DEBUGGING 199: if (debug & DEB_FILEXP) 200: printf("r %s %s\n",tildename,tildedir) FLUSH; 201: #endif 202: } 203: else { 204: if (tildename) { 205: free(tildename); 206: free(tildedir); 207: } 208: tildedir = Nullch; 209: tildename = savestr(scrbuf); 210: { 211: struct passwd *getpwnam(); 212: struct passwd *pwd = getpwnam(tildename); 213: 214: sprintf(scrbuf,"%s%s",pwd->pw_dir,s); 215: tildedir = savestr(pwd->pw_dir); 216: #ifdef NEWSADMIN 217: if (strEQ(newsadmin,tildename)) 218: newsuid = atoi(pwd->pw_uid); 219: #endif 220: strcpy(filename,scrbuf); 221: endpwent(); 222: } 223: } 224: #else !TILDENAME 225: #ifdef VERBOSE 226: IF(verbose) 227: fputs("~loginname not implemented.\n",stdout) FLUSH; 228: ELSE 229: #endif 230: #ifdef TERSE 231: fputs("~login not impl.\n",stdout) FLUSH; 232: #endif 233: #endif 234: } 235: } 236: else if (*s == '$') { /* starts with some env variable? */ 237: d = scrbuf; 238: *d++ = '%'; 239: if (s[1] == '{') 240: strcpy(d,s+2); 241: else { 242: *d++ = '{'; 243: for (s++; isalnum(*s); s++) *d++ = *s; 244: /* skip over token */ 245: *d++ = '}'; 246: strcpy(d,s); 247: } 248: #ifdef DEBUGGING 249: if (debug & DEB_FILEXP) 250: printf("$ %s\n",scrbuf) FLUSH; 251: #endif 252: interp(filename, (sizeof filename), scrbuf); 253: /* this might do some extra '%'s but */ 254: /* that is how the Mercedes Benz */ 255: } 256: #ifdef DEBUGGING 257: if (debug & DEB_FILEXP) 258: printf("> %s\n",filename) FLUSH; 259: #endif 260: return filename; 261: } 262: 263: #ifdef CONDSUB 264: /* skip interpolations */ 265: 266: char * 267: skipinterp(pattern,stoppers) 268: register char *pattern; 269: char *stoppers; 270: { 271: 272: while (*pattern && (!stoppers || !index(stoppers,*pattern))) { 273: #ifdef DEBUGGING 274: if (debug & 8) 275: printf("skipinterp till %s at %s\n",stoppers?stoppers:"",pattern); 276: #endif 277: if (*pattern == '%' && pattern[1]) { 278: switch (*++pattern) { 279: case '{': 280: for (pattern++; *pattern && *pattern != '}'; pattern++) 281: if (*pattern == '\\') 282: pattern++; 283: break; 284: case '[': 285: for (pattern++; *pattern && *pattern != ']'; pattern++) 286: if (*pattern == '\\') 287: pattern++; 288: break; 289: #ifdef CONDSUB 290: case '(': { 291: pattern = skipinterp(pattern+1,"!="); 292: if (!*pattern) 293: goto getout; 294: for (pattern++; *pattern && *pattern != '?'; pattern++) 295: if (*pattern == '\\') 296: pattern++; 297: if (!*pattern) 298: goto getout; 299: pattern = skipinterp(pattern+1,":)"); 300: if (*pattern == ':') 301: pattern = skipinterp(pattern+1,")"); 302: break; 303: } 304: #endif 305: #ifdef BACKTICK 306: case '`': { 307: pattern = skipinterp(pattern+1,"`"); 308: break; 309: } 310: #endif 311: #ifdef PROMPTTTY 312: case '"': 313: pattern = skipinterp(pattern+1,"\""); 314: break; 315: #endif 316: default: 317: break; 318: } 319: pattern++; 320: } 321: else { 322: if (*pattern == '^' && pattern[1]) 323: pattern += 2; 324: else if (*pattern == '\\' && pattern[1]) 325: pattern += 2; 326: else 327: pattern++; 328: } 329: } 330: getout: 331: return pattern; /* where we left off */ 332: } 333: #endif 334: 335: /* interpret interpolations */ 336: 337: char * 338: dointerp(dest,destsize,pattern,stoppers) 339: register char *dest; 340: register int destsize; 341: register char *pattern; 342: char *stoppers; 343: { 344: char *subj_buf = Nullch; 345: char *ngs_buf = Nullch; 346: char *refs_buf = Nullch; 347: char *artid_buf = Nullch; 348: char *reply_buf = Nullch; 349: char *from_buf = Nullch; 350: char *path_buf = Nullch; 351: char *follow_buf = Nullch; 352: char *dist_buf = Nullch; 353: char *line_buf = Nullch; 354: register char *s, *h; 355: register int i; 356: char scrbuf[512]; 357: bool upper = FALSE; 358: bool lastcomp = FALSE; 359: int metabit = 0; 360: 361: while (*pattern && (!stoppers || !index(stoppers,*pattern))) { 362: #ifdef DEBUGGING 363: if (debug & 8) 364: printf("dointerp till %s at %s\n",stoppers?stoppers:"",pattern); 365: #endif 366: if (*pattern == '%' && pattern[1]) { 367: upper = FALSE; 368: lastcomp = FALSE; 369: for (s=Nullch; !s; ) { 370: switch (*++pattern) { 371: case '^': 372: upper = TRUE; 373: break; 374: case '_': 375: lastcomp = TRUE; 376: break; 377: case '/': 378: #ifdef ARTSRCH 379: s = scrbuf; 380: if (!index("/?g",pattern[-2])) 381: *s++ = '/'; 382: strcpy(s,lastpat); 383: s += strlen(s); 384: if (pattern[-2] != 'g') { 385: if (index("/?",pattern[-2])) 386: *s++ = pattern[-2]; 387: else 388: *s++ = '/'; 389: if (art_howmuch == 1) 390: *s++ = 'h'; 391: else if (art_howmuch == 2) 392: *s++ = 'a'; 393: if (art_doread) 394: *s++ = 'r'; 395: } 396: *s = '\0'; 397: s = scrbuf; 398: #else 399: s = nullstr; 400: #endif 401: break; 402: case '{': 403: pattern = cpytill(scrbuf,pattern+1,'}'); 404: if (s = index(scrbuf,'-')) 405: *s++ = '\0'; 406: else 407: s = nullstr; 408: s = getval(scrbuf,s); 409: break; 410: case '[': 411: pattern = cpytill(scrbuf,pattern+1,']'); 412: i = set_line_type(scrbuf,scrbuf+strlen(scrbuf)); 413: if (line_buf) 414: free(line_buf); 415: s = line_buf = fetchlines(art,i); 416: break; 417: #ifdef CONDSUB 418: case '(': { 419: COMPEX *oldbra_compex = bra_compex; 420: COMPEX cond_compex; 421: char rch; 422: bool matched; 423: 424: init_compex(&cond_compex); 425: pattern = dointerp(dest,destsize,pattern+1,"!="); 426: rch = *pattern; 427: if (rch == '!') 428: pattern++; 429: if (*pattern != '=') 430: goto getout; 431: pattern = cpytill(scrbuf,pattern+1,'?'); 432: if (!*pattern) 433: goto getout; 434: if (s = compile(&cond_compex,scrbuf,TRUE,TRUE)) { 435: printf("%s: %s\n",scrbuf,s) FLUSH; 436: pattern += strlen(pattern); 437: goto getout; 438: } 439: matched = (execute(&cond_compex,dest) != Nullch); 440: if (cond_compex.nbra) /* were there brackets? */ 441: bra_compex = &cond_compex; 442: if (matched==(rch == '=')) { 443: pattern = dointerp(dest,destsize,pattern+1,":)"); 444: if (*pattern == ':') 445: pattern = skipinterp(pattern+1,")"); 446: } 447: else { 448: pattern = skipinterp(pattern+1,":)"); 449: if (*pattern == ':') 450: pattern++; 451: pattern = dointerp(dest,destsize,pattern,")"); 452: } 453: s = dest; 454: bra_compex = oldbra_compex; 455: free_compex(&cond_compex); 456: break; 457: } 458: #endif 459: #ifdef BACKTICK 460: case '`': { 461: FILE *pipefp, *popen(); 462: 463: pattern = dointerp(scrbuf,(sizeof scrbuf),pattern+1,"`"); 464: pipefp = popen(scrbuf,"r"); 465: if (pipefp != Nullfp) { 466: int len; 467: 468: len = fread(scrbuf,sizeof(char),(sizeof scrbuf)-1, 469: pipefp); 470: scrbuf[len] = '\0'; 471: pclose(pipefp); 472: } 473: else { 474: printf("\nCan't run %s\n",scrbuf); 475: *scrbuf = '\0'; 476: } 477: for (s=scrbuf; *s; s++) { 478: if (*s == '\n') { 479: if (s[1]) 480: *s = ' '; 481: else 482: *s = '\0'; 483: } 484: } 485: s = scrbuf; 486: break; 487: } 488: #endif 489: #ifdef PROMPTTTY 490: case '"': 491: pattern = dointerp(scrbuf,(sizeof scrbuf),pattern+1,"\""); 492: fputs(scrbuf,stdout) FLUSH; 493: resetty(); 494: gets(scrbuf); 495: noecho(); 496: crmode(); 497: s = scrbuf; 498: break; 499: #endif 500: case '~': 501: s = homedir; 502: break; 503: case '.': 504: s = dotdir; 505: break; 506: case '$': 507: s = scrbuf; 508: sprintf(s,"%d",getpid()); 509: break; 510: case '0': case '1': case '2': case '3': case '4': 511: case '5': case '6': case '7': case '8': case '9': 512: #ifdef CONDSUB 513: s = getbracket(bra_compex,*pattern - '0'); 514: #else 515: s = nullstr; 516: #endif 517: break; 518: case 'a': 519: s = scrbuf; 520: sprintf(s,"%ld",(long)art); 521: break; 522: case 'A': 523: #ifdef LINKART 524: s = linkartname; /* so Eunice people get right file */ 525: #else 526: s = scrbuf; 527: sprintf(s,"%s/%s/%ld",spool,ngdir,(long)art); 528: #endif 529: break; 530: case 'b': 531: s = savedest; 532: break; 533: case 'B': 534: s = scrbuf; 535: sprintf(s,"%ld",(long)savefrom); 536: break; 537: case 'c': 538: s = ngdir; 539: break; 540: case 'C': 541: s = ngname; 542: break; 543: case 'd': 544: s = scrbuf; 545: sprintf(s,"%s/%s",spool,ngdir); 546: break; 547: case 'D': 548: s = dist_buf = fetchlines(art,DIST_LINE); 549: break; 550: case 'f': /* from line */ 551: #ifdef ASYNC_PARSE 552: parse_maybe(art); 553: #endif 554: if (htype[REPLY_LINE].ht_minpos >= 0) { 555: /* was there a reply line? */ 556: if (!(s=reply_buf)) 557: s = reply_buf = fetchlines(art,REPLY_LINE); 558: } 559: else if (!(s = from_buf)) 560: s = from_buf = fetchlines(art,FROM_LINE); 561: break; 562: case 'F': 563: #ifdef ASYNC_PARSE 564: parse_maybe(art); 565: #endif 566: if (htype[FOLLOW_LINE].ht_minpos >= 0) 567: /* is there a Followup-To line? */ 568: s = follow_buf = fetchlines(art,FOLLOW_LINE); 569: else { 570: int off; 571: 572: s = ngs_buf = fetchlines(art,NGS_LINE); 573: if (h = instr(s,"net.general")) { 574: off = h-s; 575: strncpy(scrbuf,s,off+4); 576: strcpy(scrbuf+off+4,"followup"); 577: safecpy(scrbuf+off+12,h+11,sizeof(scrbuf)); 578: s = scrbuf; 579: } 580: } 581: break; 582: case 'h': /* header file name */ 583: s = headname; 584: break; 585: case 'H': /* host name */ 586: s = sitename; 587: break; 588: case 'i': 589: if (!(s=artid_buf)) 590: s = artid_buf = fetchlines(art,MESSID_LINE); 591: if (*s && *s != '<') { 592: sprintf(scrbuf,"<%s>",artid_buf); 593: s = scrbuf; 594: } 595: break; 596: case 'I': /* ref article indicator */ 597: s = scrbuf; 598: sprintf(scrbuf,"'%s'",indstr); 599: break; 600: case 'l': /* rn library */ 601: #ifdef NEWSADMIN 602: s = newsadmin; 603: #else 604: s = "???"; 605: #endif 606: break; 607: case 'L': /* login id */ 608: s = logname; 609: break; 610: case 'm': /* current mode */ 611: s = scrbuf; 612: *s = mode; 613: s[1] = '\0'; 614: break; 615: case 'M': 616: #ifdef DELAYMARK 617: sprintf(scrbuf,"%ld",(long)dmcount); 618: s = scrbuf; 619: #else 620: s = nullstr; 621: #endif 622: break; 623: case 'n': /* newsgroups */ 624: s = ngs_buf = fetchlines(art,NGS_LINE); 625: break; 626: case 'N': /* full name */ 627: s = getval("NAME",realname); 628: break; 629: case 'o': /* organization */ 630: s = getval("ORGANIZATION",orgname); 631: #ifdef ORGFILE 632: if (*s == '/') { 633: FILE *ofp = fopen(s,"r"); 634: 635: if (ofp) { 636: fgets(scrbuf,sizeof scrbuf,ofp); 637: fclose(ofp); 638: s = scrbuf; 639: s[strlen(s)-1] = '\0'; 640: } 641: } 642: #endif 643: break; 644: case 'O': 645: s = origdir; 646: break; 647: case 'p': 648: s = cwd; 649: break; 650: case 'P': 651: s = spool; 652: break; 653: case 'r': 654: #ifdef ASYNC_PARSE 655: parse_maybe(art); 656: #endif 657: if (htype[REFS_LINE].ht_minpos >= 0) { 658: refs_buf = fetchlines(art,REFS_LINE); 659: refscpy(scrbuf,(sizeof scrbuf),refs_buf); 660: } 661: else 662: *scrbuf = '\0'; 663: s = rindex(scrbuf,'<'); 664: break; 665: case 'R': 666: #ifdef ASYNC_PARSE 667: parse_maybe(art); 668: #endif 669: if (htype[REFS_LINE].ht_minpos >= 0) { 670: refs_buf = fetchlines(art,REFS_LINE); 671: refscpy(scrbuf,(sizeof scrbuf),refs_buf); 672: } 673: else 674: *scrbuf = '\0'; 675: if (!artid_buf) 676: artid_buf = fetchlines(art,MESSID_LINE); 677: if (artid_buf[0] == '<') 678: safecat(scrbuf,artid_buf,sizeof(scrbuf)); 679: else if (artid_buf[0]) { 680: char tmpbuf[64]; 681: 682: sprintf(tmpbuf,"<%s>",artid_buf); 683: safecat(scrbuf,tmpbuf,sizeof(scrbuf)); 684: } 685: s = scrbuf; 686: break; 687: case 's': 688: if (!(s=subj_buf)) 689: s = subj_buf = fetchsubj(art,TRUE,TRUE); 690: /* get subject handy */ 691: while ((*s=='R'||*s=='r')&&(s[1]=='E'||s[1]=='e')&&s[2]==':') { 692: /* skip extra Re: */ 693: s += 3; 694: if (*s == ' ') 695: s++; 696: } 697: if (h = instr(s,"- (nf")) 698: *h = '\0'; 699: break; 700: case 'S': 701: if (!(s=subj_buf)) 702: s = subj_buf = fetchsubj(art,TRUE,TRUE); 703: /* get subject handy */ 704: if ((*s=='R'||*s=='r')&&(s[1]=='E'||s[1]=='e')&&s[2]==':') { 705: /* skip extra Re: */ 706: s += 3; 707: if (*s == ' ') 708: s++; 709: } 710: break; 711: case 't': 712: case 'T': 713: #ifdef ASYNC_PARSE 714: parse_maybe(art); 715: #endif 716: if (htype[REPLY_LINE].ht_minpos >= 0) { 717: /* was there a reply line? */ 718: if (!(s=reply_buf)) 719: s = reply_buf = fetchlines(art,REPLY_LINE); 720: } 721: else if (!(s = from_buf)) 722: s = from_buf = fetchlines(art,FROM_LINE); 723: if (*pattern == 'T') { 724: if (htype[PATH_LINE].ht_minpos >= 0) { 725: /* should we substitute path? */ 726: s = path_buf = fetchlines(art,PATH_LINE); 727: } 728: i = strlen(sitename); 729: if (strnEQ(sitename,s,i) && s[i] == '!') 730: s += i + 1; 731: } 732: if ((h=index(s,'(')) != Nullch) 733: /* strip garbage from end */ 734: *(h-1) = '\0'; 735: else if ((h=index(s,'<')) != Nullch) { 736: /* or perhaps from beginning */ 737: s = h+1; 738: if ((h=index(s,'>')) != Nullch) 739: *h = '\0'; 740: } 741: break; 742: case 'u': 743: sprintf(scrbuf,"%ld",(long)toread[ng]); 744: s = scrbuf; 745: break; 746: case 'U': 747: sprintf(scrbuf,"%ld", 748: (long)(((ART_NUM)toread[ng]) - 1 + was_read(art))); 749: s = scrbuf; 750: break; 751: case 'x': /* news library */ 752: s = lib; 753: break; 754: case 'X': /* rn library */ 755: s = rnlib; 756: break; 757: case 'z': 758: #ifdef LINKART 759: s = linkartname; /* so Eunice people get right file */ 760: #else 761: s = scrbuf; 762: sprintf(s,"%ld",(long)art); 763: #endif 764: if (stat(s,&filestat) < 0) 765: filestat.st_size = 0L; 766: sprintf(scrbuf,"%5ld",(long)filestat.st_size); 767: s = scrbuf; 768: break; 769: default: 770: if (--destsize <= 0) 771: abort_interp(); 772: *dest++ = *pattern | metabit; 773: s = nullstr; 774: break; 775: } 776: } 777: if (!s) 778: s = nullstr; 779: pattern++; 780: if (upper || lastcomp) { 781: char *t; 782: 783: if (s != scrbuf) { 784: safecpy(scrbuf,s,(sizeof scrbuf)); 785: s = scrbuf; 786: } 787: if (upper || !(t=rindex(s,'/'))) 788: t = s; 789: while (*t && !isalpha(*t)) 790: t++; 791: if (islower(*t)) 792: *t = toupper(*t); 793: } 794: i = metabit; /* maybe get into register */ 795: if (s == dest) { 796: while (*dest) { 797: if (--destsize <= 0) 798: abort_interp(); 799: *dest++ |= i; 800: } 801: } 802: else { 803: while (*s) { 804: if (--destsize <= 0) 805: abort_interp(); 806: *dest++ = *s++ | i; 807: } 808: } 809: } 810: else { 811: if (--destsize <= 0) 812: abort_interp(); 813: if (*pattern == '^' && pattern[1]) { 814: ++pattern; /* skip uparrow */ 815: i = *pattern; /* get char into a register */ 816: if (i == '?') 817: *dest++ = '\177' | metabit; 818: else if (i == '(') { 819: metabit = 0200; 820: destsize++; 821: } 822: else if (i == ')') { 823: metabit = 0; 824: destsize++; 825: } 826: else 827: *dest++ = i & 037 | metabit; 828: pattern++; 829: } 830: else if (*pattern == '\\' && pattern[1]) { 831: ++pattern; /* skip backslash */ 832: i = *pattern; /* get char into a register */ 833: 834: /* this used to be a switch but the if may save space */ 835: 836: if (i >= '0' && i <= '7') { 837: i = 1; 838: while (i < 01000 && *pattern >= '0' && *pattern <= '7') { 839: i <<= 3; 840: i += *pattern++ - '0'; 841: } 842: *dest++ = i & 0377 | metabit; 843: --pattern; 844: } 845: else if (i == 'b') 846: *dest++ = '\b' | metabit; 847: else if (i == 'f') 848: *dest++ = '\f' | metabit; 849: else if (i == 'n') 850: *dest++ = '\n' | metabit; 851: else if (i == 'r') 852: *dest++ = '\r' | metabit; 853: else if (i == 't') 854: *dest++ = '\t' | metabit; 855: else 856: *dest++ = i | metabit; 857: pattern++; 858: } 859: else 860: *dest++ = *pattern++ | metabit; 861: } 862: } 863: *dest = '\0'; 864: getout: 865: if (subj_buf != Nullch) /* return any checked out storage */ 866: free(subj_buf); 867: if (ngs_buf != Nullch) 868: free(ngs_buf); 869: if (refs_buf != Nullch) 870: free(refs_buf); 871: if (artid_buf != Nullch) 872: free(artid_buf); 873: if (reply_buf != Nullch) 874: free(reply_buf); 875: if (from_buf != Nullch) 876: free(from_buf); 877: if (path_buf != Nullch) 878: free(path_buf); 879: if (follow_buf != Nullch) 880: free(follow_buf); 881: if (dist_buf != Nullch) 882: free(dist_buf); 883: if (line_buf != Nullch) 884: free(line_buf); 885: return pattern; /* where we left off */ 886: } 887: 888: void 889: interp(dest,destsize,pattern) 890: char *dest; 891: int destsize; 892: char *pattern; 893: { 894: dointerp(dest,destsize,pattern,Nullch); 895: #ifdef DEBUGGING 896: if (debug & DEB_FILEXP) 897: fputs(dest,stdout); 898: #endif 899: } 900: 901: /* copy a references line, normalizing as we go */ 902: 903: void 904: refscpy(dest,destsize,src) 905: register char *dest, *src; 906: register int destsize; 907: { 908: register char *dot, *at, *beg; 909: char tmpbuf[64]; 910: 911: while (*src) { 912: if (*src != '<') { 913: if (--destsize <= 0) 914: break; 915: *dest++ = '<'; 916: at = dot = Nullch; 917: beg = src; 918: while (*src && *src != ' ' && *src != ',') { 919: if (*src == '.') 920: dot = src; 921: else if (*src == '@') 922: at = src; 923: if (--destsize <= 0) 924: break; 925: *dest++ = *src++; 926: } 927: if (destsize <= 0) 928: break; 929: if (dot && !at) { 930: int len; 931: 932: *dest = *dot++ = '\0'; 933: sprintf(tmpbuf,"%s@%s.UUCP",dot,beg); 934: len = strlen(tmpbuf); 935: if (destsize > len) { 936: strcpy(dest,tmpbuf); 937: dest = dest + len; 938: destsize -= len; 939: } 940: } 941: if (--destsize <= 0) 942: break; 943: *dest++ = '>'; 944: } 945: else { 946: while (*src && --destsize > 0 && (*dest++ = *src++) != '>') ; 947: if (destsize <= 0) 948: break; 949: } 950: while (*src == ' ' || *src == ',') src++; 951: if (*src && --destsize > 0) 952: *dest++ = ' '; 953: } 954: *dest = '\0'; 955: } 956: 957: /* get the person's real name from /etc/passwd */ 958: /* (string is overwritten, so it must be copied) */ 959: 960: char * 961: getrealname(uid) 962: int uid; 963: { 964: char *s, *c; 965: 966: #ifdef PASSNAMES 967: struct passwd *pwd = getpwuid(uid); 968: 969: s = pwd->pw_gecos; 970: #ifdef BERKNAMES 971: #ifdef BERKJUNK 972: while (*s && !isalnum(*s) && *s != '&') s++; 973: #endif 974: if ((c = index(s, ',')) != Nullch) 975: *c = '\0'; 976: if ((c = index(s, ';')) != Nullch) 977: *c = '\0'; 978: s = cpytill(buf,s,'&'); 979: if (*s == '&') { /* whoever thought this one up was */ 980: c = buf + strlen(buf); /* in the middle of the night */ 981: strcat(c,logname); /* before the morning after */ 982: strcat(c,s+1); 983: if (islower(*c)) 984: *c = toupper(*c); /* gack and double gack */ 985: } 986: #else 987: if ((c = index(s, '(')) != Nullch) 988: *c = '\0'; 989: if ((c = index(s, '-')) != Nullch) 990: s = c; 991: strcpy(buf,tmpbuf); 992: #endif 993: endpwent(); 994: return buf; /* return something static */ 995: #else 996: if ((tmpfp=fopen(filexp(FULLNAMEFILE),"r")) != Nullfp) { 997: fgets(buf,sizeof buf,tmpfp); 998: fclose(tmpfp); 999: buf[strlen(buf)-1] = '\0'; 1000: return buf; 1001: } 1002: return "PUT YOUR NAME HERE"; 1003: #endif 1004: } 1005: 1006: static void 1007: abort_interp() 1008: { 1009: fputs("\n% interp buffer overflow!\n",stdout) FLUSH; 1010: sig_catcher(0); 1011: }