1: /* $Header: intrp.c,v 4.3.1.5 85/05/23 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: #ifdef GETPWENT /* getpwnam() is not the paragon of efficiency */ 211: { 212: struct passwd *getpwnam(); 213: struct passwd *pwd = getpwnam(tildename); 214: 215: sprintf(scrbuf,"%s%s",pwd->pw_dir,s); 216: tildedir = savestr(pwd->pw_dir); 217: #ifdef NEWSADMIN 218: if (strEQ(newsadmin,tildename)) 219: newsuid = atoi(pwd->pw_uid); 220: #endif 221: strcpy(filename,scrbuf); 222: #ifdef GETPWENT 223: endpwent(); 224: #endif 225: } 226: #else /* this will run faster, and is less D space */ 227: { /* just be sure LOGDIRFIELD is correct */ 228: FILE *pfp = fopen("/etc/passwd","r"); 229: char tmpbuf[512]; 230: int i; 231: 232: if (pfp == Nullfp) { 233: printf(cantopen,"passwd") FLUSH; 234: sig_catcher(0); 235: } 236: while (fgets(tmpbuf,512,pfp) != Nullch) { 237: d = cpytill(scrbuf,tmpbuf,':'); 238: #ifdef DEBUGGING 239: if (debug & DEB_FILEXP) 240: printf("p %s\n",tmpbuf) FLUSH; 241: #endif 242: if (strEQ(scrbuf,tildename)) { 243: #ifdef NEWSADMIN 244: if (strEQ(newsadmin,tildename)) 245: newsuid = atoi(index(d,':')+1); 246: #endif 247: for (i=LOGDIRFIELD-2; i; i--) { 248: if (d) 249: d = index(d+1,':'); 250: } 251: if (d) { 252: cpytill(scrbuf,d+1,':'); 253: tildedir = savestr(scrbuf); 254: strcat(scrbuf,s); 255: strcpy(filename,scrbuf); 256: } 257: break; 258: } 259: } 260: fclose(pfp); 261: } 262: #endif 263: } 264: #else !TILDENAME 265: #ifdef VERBOSE 266: IF(verbose) 267: fputs("~loginname not implemented.\n",stdout) FLUSH; 268: ELSE 269: #endif 270: #ifdef TERSE 271: fputs("~login not impl.\n",stdout) FLUSH; 272: #endif 273: #endif 274: } 275: } 276: else if (*s == '$') { /* starts with some env variable? */ 277: d = scrbuf; 278: *d++ = '%'; 279: if (s[1] == '{') 280: strcpy(d,s+2); 281: else { 282: *d++ = '{'; 283: for (s++; isalnum(*s); s++) *d++ = *s; 284: /* skip over token */ 285: *d++ = '}'; 286: strcpy(d,s); 287: } 288: #ifdef DEBUGGING 289: if (debug & DEB_FILEXP) 290: printf("$ %s\n",scrbuf) FLUSH; 291: #endif 292: interp(filename, (sizeof filename), scrbuf); 293: /* this might do some extra '%'s but */ 294: /* that is how the Mercedes Benz */ 295: } 296: #ifdef DEBUGGING 297: if (debug & DEB_FILEXP) 298: printf("> %s\n",filename) FLUSH; 299: #endif 300: return filename; 301: } 302: 303: #ifdef CONDSUB 304: /* skip interpolations */ 305: 306: char * 307: skipinterp(pattern,stoppers) 308: register char *pattern; 309: char *stoppers; 310: { 311: 312: while (*pattern && (!stoppers || !index(stoppers,*pattern))) { 313: #ifdef DEBUGGING 314: if (debug & 8) 315: printf("skipinterp till %s at %s\n",stoppers?stoppers:"",pattern); 316: #endif 317: if (*pattern == '%' && pattern[1]) { 318: switch (*++pattern) { 319: case '{': 320: for (pattern++; *pattern && *pattern != '}'; pattern++) 321: if (*pattern == '\\') 322: pattern++; 323: break; 324: case '[': 325: for (pattern++; *pattern && *pattern != ']'; pattern++) 326: if (*pattern == '\\') 327: pattern++; 328: break; 329: #ifdef CONDSUB 330: case '(': { 331: pattern = skipinterp(pattern+1,"!="); 332: if (!*pattern) 333: goto getout; 334: for (pattern++; *pattern && *pattern != '?'; pattern++) 335: if (*pattern == '\\') 336: pattern++; 337: if (!*pattern) 338: goto getout; 339: pattern = skipinterp(pattern+1,":)"); 340: if (*pattern == ':') 341: pattern = skipinterp(pattern+1,")"); 342: break; 343: } 344: #endif 345: #ifdef BACKTICK 346: case '`': { 347: pattern = skipinterp(pattern+1,"`"); 348: break; 349: } 350: #endif 351: #ifdef PROMPTTTY 352: case '"': 353: pattern = skipinterp(pattern+1,"\""); 354: break; 355: #endif 356: default: 357: break; 358: } 359: pattern++; 360: } 361: else { 362: if (*pattern == '^' && pattern[1]) 363: pattern += 2; 364: else if (*pattern == '\\' && pattern[1]) 365: pattern += 2; 366: else 367: pattern++; 368: } 369: } 370: getout: 371: return pattern; /* where we left off */ 372: } 373: #endif 374: 375: /* interpret interpolations */ 376: 377: char * 378: dointerp(dest,destsize,pattern,stoppers) 379: register char *dest; 380: register int destsize; 381: register char *pattern; 382: char *stoppers; 383: { 384: char *subj_buf = Nullch; 385: char *ngs_buf = Nullch; 386: char *refs_buf = Nullch; 387: char *artid_buf = Nullch; 388: char *reply_buf = Nullch; 389: char *from_buf = Nullch; 390: char *path_buf = Nullch; 391: char *follow_buf = Nullch; 392: char *dist_buf = Nullch; 393: char *line_buf = Nullch; 394: register char *s, *h; 395: register int i; 396: char scrbuf[512]; 397: bool upper = FALSE; 398: bool lastcomp = FALSE; 399: int metabit = 0; 400: 401: while (*pattern && (!stoppers || !index(stoppers,*pattern))) { 402: #ifdef DEBUGGING 403: if (debug & 8) 404: printf("dointerp till %s at %s\n",stoppers?stoppers:"",pattern); 405: #endif 406: if (*pattern == '%' && pattern[1]) { 407: upper = FALSE; 408: lastcomp = FALSE; 409: for (s=Nullch; !s; ) { 410: switch (*++pattern) { 411: case '^': 412: upper = TRUE; 413: break; 414: case '_': 415: lastcomp = TRUE; 416: break; 417: case '/': 418: #ifdef ARTSRCH 419: s = scrbuf; 420: if (!index("/?g",pattern[-2])) 421: *s++ = '/'; 422: strcpy(s,lastpat); 423: s += strlen(s); 424: if (pattern[-2] != 'g') { 425: if (index("/?",pattern[-2])) 426: *s++ = pattern[-2]; 427: else 428: *s++ = '/'; 429: if (art_howmuch == 1) 430: *s++ = 'h'; 431: else if (art_howmuch == 2) 432: *s++ = 'a'; 433: if (art_doread) 434: *s++ = 'r'; 435: } 436: *s = '\0'; 437: s = scrbuf; 438: #else 439: s = nullstr; 440: #endif 441: break; 442: case '{': 443: pattern = cpytill(scrbuf,pattern+1,'}'); 444: if (s = index(scrbuf,'-')) 445: *s++ = '\0'; 446: else 447: s = nullstr; 448: s = getval(scrbuf,s); 449: break; 450: case '[': 451: pattern = cpytill(scrbuf,pattern+1,']'); 452: i = set_line_type(scrbuf,scrbuf+strlen(scrbuf)); 453: if (line_buf) 454: free(line_buf); 455: s = line_buf = fetchlines(art,i); 456: break; 457: #ifdef CONDSUB 458: case '(': { 459: COMPEX *oldbra_compex = bra_compex; 460: COMPEX cond_compex; 461: char rch; 462: bool matched; 463: 464: init_compex(&cond_compex); 465: pattern = dointerp(dest,destsize,pattern+1,"!="); 466: rch = *pattern; 467: if (rch == '!') 468: pattern++; 469: if (*pattern != '=') 470: goto getout; 471: pattern = cpytill(scrbuf,pattern+1,'?'); 472: if (!*pattern) 473: goto getout; 474: if (s = compile(&cond_compex,scrbuf,TRUE,TRUE)) { 475: printf("%s: %s\n",scrbuf,s) FLUSH; 476: pattern += strlen(pattern); 477: goto getout; 478: } 479: matched = (execute(&cond_compex,dest) != Nullch); 480: if (cond_compex.nbra) /* were there brackets? */ 481: bra_compex = &cond_compex; 482: if (matched==(rch == '=')) { 483: pattern = dointerp(dest,destsize,pattern+1,":)"); 484: if (*pattern == ':') 485: pattern = skipinterp(pattern+1,")"); 486: } 487: else { 488: pattern = skipinterp(pattern+1,":)"); 489: if (*pattern == ':') 490: pattern++; 491: pattern = dointerp(dest,destsize,pattern,")"); 492: } 493: s = dest; 494: bra_compex = oldbra_compex; 495: free_compex(&cond_compex); 496: break; 497: } 498: #endif 499: #ifdef BACKTICK 500: case '`': { 501: FILE *pipefp, *popen(); 502: 503: pattern = dointerp(scrbuf,(sizeof scrbuf),pattern+1,"`"); 504: pipefp = popen(scrbuf,"r"); 505: if (pipefp != Nullfp) { 506: int len; 507: 508: len = fread(scrbuf,sizeof(char),(sizeof scrbuf)-1, 509: pipefp); 510: scrbuf[len] = '\0'; 511: pclose(pipefp); 512: } 513: else { 514: printf("\nCan't run %s\n",scrbuf); 515: *scrbuf = '\0'; 516: } 517: for (s=scrbuf; *s; s++) { 518: if (*s == '\n') { 519: if (s[1]) 520: *s = ' '; 521: else 522: *s = '\0'; 523: } 524: } 525: s = scrbuf; 526: break; 527: } 528: #endif 529: #ifdef PROMPTTTY 530: case '"': 531: pattern = dointerp(scrbuf,(sizeof scrbuf),pattern+1,"\""); 532: fputs(scrbuf,stdout) FLUSH; 533: resetty(); 534: gets(scrbuf); 535: noecho(); 536: crmode(); 537: s = scrbuf; 538: break; 539: #endif 540: case '~': 541: s = homedir; 542: break; 543: case '.': 544: s = dotdir; 545: break; 546: case '$': 547: s = scrbuf; 548: sprintf(s,"%d",getpid()); 549: break; 550: case '0': case '1': case '2': case '3': case '4': 551: case '5': case '6': case '7': case '8': case '9': 552: #ifdef CONDSUB 553: s = getbracket(bra_compex,*pattern - '0'); 554: #else 555: s = nullstr; 556: #endif 557: break; 558: case 'a': 559: s = scrbuf; 560: sprintf(s,"%ld",(long)art); 561: break; 562: case 'A': 563: #ifdef LINKART 564: s = linkartname; /* so Eunice people get right file */ 565: #else 566: s = scrbuf; 567: sprintf(s,"%s/%s/%ld",spool,ngdir,(long)art); 568: #endif 569: break; 570: case 'b': 571: s = savedest; 572: break; 573: case 'B': 574: s = scrbuf; 575: sprintf(s,"%ld",(long)savefrom); 576: break; 577: case 'c': 578: s = ngdir; 579: break; 580: case 'C': 581: s = ngname; 582: break; 583: case 'd': 584: s = scrbuf; 585: sprintf(s,"%s/%s",spool,ngdir); 586: break; 587: case 'D': 588: s = dist_buf = fetchlines(art,DIST_LINE); 589: break; 590: case 'f': /* from line */ 591: #ifdef ASYNC_PARSE 592: parse_maybe(art); 593: #endif 594: if (htype[REPLY_LINE].ht_minpos >= 0) { 595: /* was there a reply line? */ 596: if (!(s=reply_buf)) 597: s = reply_buf = fetchlines(art,REPLY_LINE); 598: } 599: else if (!(s = from_buf)) 600: s = from_buf = fetchlines(art,FROM_LINE); 601: break; 602: case 'F': 603: #ifdef ASYNC_PARSE 604: parse_maybe(art); 605: #endif 606: if (htype[FOLLOW_LINE].ht_minpos >= 0) 607: /* is there a Followup-To line? */ 608: s = follow_buf = fetchlines(art,FOLLOW_LINE); 609: else { 610: int off; 611: 612: s = ngs_buf = fetchlines(art,NGS_LINE); 613: if (h = instr(s,"net.general")) { 614: off = h-s; 615: strncpy(scrbuf,s,off+4); 616: strcpy(scrbuf+off+4,"followup"); 617: safecpy(scrbuf+off+12,h+11,sizeof(scrbuf)); 618: s = scrbuf; 619: } 620: } 621: break; 622: case 'h': /* header file name */ 623: s = headname; 624: break; 625: case 'H': /* host name */ 626: s = sitename; 627: break; 628: case 'i': 629: if (!(s=artid_buf)) 630: s = artid_buf = fetchlines(art,MESSID_LINE); 631: if (*s && *s != '<') { 632: sprintf(scrbuf,"<%s>",artid_buf); 633: s = scrbuf; 634: } 635: break; 636: case 'I': /* ref article indicator */ 637: s = scrbuf; 638: sprintf(scrbuf,"'%s'",indstr); 639: break; 640: case 'l': /* rn library */ 641: #ifdef NEWSADMIN 642: s = newsadmin; 643: #else 644: s = "???"; 645: #endif 646: break; 647: case 'L': /* login id */ 648: s = logname; 649: break; 650: case 'm': /* current mode */ 651: s = scrbuf; 652: *s = mode; 653: s[1] = '\0'; 654: break; 655: case 'M': 656: #ifdef DELAYMARK 657: sprintf(scrbuf,"%ld",(long)dmcount); 658: s = scrbuf; 659: #else 660: s = nullstr; 661: #endif 662: break; 663: case 'n': /* newsgroups */ 664: s = ngs_buf = fetchlines(art,NGS_LINE); 665: break; 666: case 'N': /* full name */ 667: s = getval("NAME",realname); 668: break; 669: case 'o': /* organization */ 670: s = getval("ORGANIZATION",orgname); 671: #ifdef ORGFILE 672: if (*s == '/') { 673: FILE *ofp = fopen(s,"r"); 674: 675: if (ofp) { 676: fgets(scrbuf,sizeof scrbuf,ofp); 677: fclose(ofp); 678: s = scrbuf; 679: s[strlen(s)-1] = '\0'; 680: } 681: } 682: #endif 683: break; 684: case 'O': 685: s = origdir; 686: break; 687: case 'p': 688: s = cwd; 689: break; 690: case 'P': 691: s = spool; 692: break; 693: case 'r': 694: #ifdef ASYNC_PARSE 695: parse_maybe(art); 696: #endif 697: if (htype[REFS_LINE].ht_minpos >= 0) { 698: refs_buf = fetchlines(art,REFS_LINE); 699: refscpy(scrbuf,(sizeof scrbuf),refs_buf); 700: } 701: else 702: *scrbuf = '\0'; 703: s = rindex(scrbuf,'<'); 704: break; 705: case 'R': 706: #ifdef ASYNC_PARSE 707: parse_maybe(art); 708: #endif 709: if (htype[REFS_LINE].ht_minpos >= 0) { 710: refs_buf = fetchlines(art,REFS_LINE); 711: refscpy(scrbuf,(sizeof scrbuf),refs_buf); 712: } 713: else 714: *scrbuf = '\0'; 715: if (!artid_buf) 716: artid_buf = fetchlines(art,MESSID_LINE); 717: if (artid_buf[0] == '<') 718: safecat(scrbuf,artid_buf,sizeof(scrbuf)); 719: else if (artid_buf[0]) { 720: char tmpbuf[64]; 721: 722: sprintf(tmpbuf,"<%s>",artid_buf); 723: safecat(scrbuf,tmpbuf,sizeof(scrbuf)); 724: } 725: s = scrbuf; 726: break; 727: case 's': 728: if (!(s=subj_buf)) 729: s = subj_buf = fetchsubj(art,TRUE,TRUE); 730: /* get subject handy */ 731: while ((*s=='R'||*s=='r')&&(s[1]=='E'||s[1]=='e')&&s[2]==':') { 732: /* skip extra Re: */ 733: s += 3; 734: if (*s == ' ') 735: s++; 736: } 737: if (h = instr(s,"- (nf")) 738: *h = '\0'; 739: break; 740: case 'S': 741: if (!(s=subj_buf)) 742: s = subj_buf = fetchsubj(art,TRUE,TRUE); 743: /* get subject handy */ 744: if ((*s=='R'||*s=='r')&&(s[1]=='E'||s[1]=='e')&&s[2]==':') { 745: /* skip extra Re: */ 746: s += 3; 747: if (*s == ' ') 748: s++; 749: } 750: break; 751: case 't': 752: case 'T': 753: #ifdef ASYNC_PARSE 754: parse_maybe(art); 755: #endif 756: if (htype[REPLY_LINE].ht_minpos >= 0) { 757: /* was there a reply line? */ 758: if (!(s=reply_buf)) 759: s = reply_buf = fetchlines(art,REPLY_LINE); 760: } 761: else if (!(s = from_buf)) 762: s = from_buf = fetchlines(art,FROM_LINE); 763: if (*pattern == 'T') { 764: if (htype[PATH_LINE].ht_minpos >= 0) { 765: /* should we substitute path? */ 766: s = path_buf = fetchlines(art,PATH_LINE); 767: } 768: i = strlen(sitename); 769: if (strnEQ(sitename,s,i) && s[i] == '!') 770: s += i + 1; 771: } 772: if ((h=index(s,'(')) != Nullch) 773: /* strip garbage from end */ 774: *(h-1) = '\0'; 775: else if ((h=index(s,'<')) != Nullch) { 776: /* or perhaps from beginning */ 777: s = h+1; 778: if ((h=index(s,'>')) != Nullch) 779: *h = '\0'; 780: } 781: break; 782: case 'u': 783: sprintf(scrbuf,"%ld",(long)toread[ng]); 784: s = scrbuf; 785: break; 786: case 'U': 787: sprintf(scrbuf,"%ld", 788: (long)(((ART_NUM)toread[ng]) - 1 + was_read(art))); 789: s = scrbuf; 790: break; 791: case 'x': /* news library */ 792: s = lib; 793: break; 794: case 'X': /* rn library */ 795: s = rnlib; 796: break; 797: case 'z': 798: #ifdef LINKART 799: s = linkartname; /* so Eunice people get right file */ 800: #else 801: s = scrbuf; 802: sprintf(s,"%ld",(long)art); 803: #endif 804: if (stat(s,&filestat) < 0) 805: filestat.st_size = 0L; 806: sprintf(scrbuf,"%5ld",(long)filestat.st_size); 807: s = scrbuf; 808: break; 809: default: 810: if (--destsize <= 0) 811: abort_interp(); 812: *dest++ = *pattern | metabit; 813: s = nullstr; 814: break; 815: } 816: } 817: if (!s) 818: s = nullstr; 819: pattern++; 820: if (upper || lastcomp) { 821: char *t; 822: 823: if (s != scrbuf) { 824: safecpy(scrbuf,s,(sizeof scrbuf)); 825: s = scrbuf; 826: } 827: if (upper || !(t=rindex(s,'/'))) 828: t = s; 829: while (*t && !isalpha(*t)) 830: t++; 831: if (islower(*t)) 832: *t = toupper(*t); 833: } 834: i = metabit; /* maybe get into register */ 835: if (s == dest) { 836: while (*dest) { 837: if (--destsize <= 0) 838: abort_interp(); 839: *dest++ |= i; 840: } 841: } 842: else { 843: while (*s) { 844: if (--destsize <= 0) 845: abort_interp(); 846: *dest++ = *s++ | i; 847: } 848: } 849: } 850: else { 851: if (--destsize <= 0) 852: abort_interp(); 853: if (*pattern == '^' && pattern[1]) { 854: ++pattern; /* skip uparrow */ 855: i = *pattern; /* get char into a register */ 856: if (i == '?') 857: *dest++ = '\177' | metabit; 858: else if (i == '(') { 859: metabit = 0200; 860: destsize++; 861: } 862: else if (i == ')') { 863: metabit = 0; 864: destsize++; 865: } 866: else 867: *dest++ = i & 037 | metabit; 868: pattern++; 869: } 870: else if (*pattern == '\\' && pattern[1]) { 871: ++pattern; /* skip backslash */ 872: i = *pattern; /* get char into a register */ 873: 874: /* this used to be a switch but the if may save space */ 875: 876: if (i >= '0' && i <= '7') { 877: i = 1; 878: while (i < 01000 && *pattern >= '0' && *pattern <= '7') { 879: i <<= 3; 880: i += *pattern++ - '0'; 881: } 882: *dest++ = i & 0377 | metabit; 883: --pattern; 884: } 885: else if (i == 'b') 886: *dest++ = '\b' | metabit; 887: else if (i == 'f') 888: *dest++ = '\f' | metabit; 889: else if (i == 'n') 890: *dest++ = '\n' | metabit; 891: else if (i == 'r') 892: *dest++ = '\r' | metabit; 893: else if (i == 't') 894: *dest++ = '\t' | metabit; 895: else 896: *dest++ = i | metabit; 897: pattern++; 898: } 899: else 900: *dest++ = *pattern++ | metabit; 901: } 902: } 903: *dest = '\0'; 904: getout: 905: if (subj_buf != Nullch) /* return any checked out storage */ 906: free(subj_buf); 907: if (ngs_buf != Nullch) 908: free(ngs_buf); 909: if (refs_buf != Nullch) 910: free(refs_buf); 911: if (artid_buf != Nullch) 912: free(artid_buf); 913: if (reply_buf != Nullch) 914: free(reply_buf); 915: if (from_buf != Nullch) 916: free(from_buf); 917: if (path_buf != Nullch) 918: free(path_buf); 919: if (follow_buf != Nullch) 920: free(follow_buf); 921: if (dist_buf != Nullch) 922: free(dist_buf); 923: if (line_buf != Nullch) 924: free(line_buf); 925: return pattern; /* where we left off */ 926: } 927: 928: void 929: interp(dest,destsize,pattern) 930: char *dest; 931: int destsize; 932: char *pattern; 933: { 934: dointerp(dest,destsize,pattern,Nullch); 935: #ifdef DEBUGGING 936: if (debug & DEB_FILEXP) 937: fputs(dest,stdout); 938: #endif 939: } 940: 941: /* copy a references line, normalizing as we go */ 942: 943: void 944: refscpy(dest,destsize,src) 945: register char *dest, *src; 946: register int destsize; 947: { 948: register char *dot, *at, *beg; 949: char tmpbuf[64]; 950: 951: while (*src) { 952: if (*src != '<') { 953: if (--destsize <= 0) 954: break; 955: *dest++ = '<'; 956: at = dot = Nullch; 957: beg = src; 958: while (*src && *src != ' ' && *src != ',') { 959: if (*src == '.') 960: dot = src; 961: else if (*src == '@') 962: at = src; 963: if (--destsize <= 0) 964: break; 965: *dest++ = *src++; 966: } 967: if (destsize <= 0) 968: break; 969: if (dot && !at) { 970: int len; 971: 972: *dest = *dot++ = '\0'; 973: sprintf(tmpbuf,"%s@%s.UUCP",dot,beg); 974: len = strlen(tmpbuf); 975: if (destsize > len) { 976: strcpy(dest,tmpbuf); 977: dest = dest + len; 978: destsize -= len; 979: } 980: } 981: if (--destsize <= 0) 982: break; 983: *dest++ = '>'; 984: } 985: else { 986: while (*src && --destsize > 0 && (*dest++ = *src++) != '>') ; 987: if (destsize <= 0) 988: break; 989: } 990: while (*src == ' ' || *src == ',') src++; 991: if (*src && --destsize > 0) 992: *dest++ = ' '; 993: } 994: *dest = '\0'; 995: } 996: 997: /* get the person's real name from /etc/passwd */ 998: /* (string is overwritten, so it must be copied) */ 999: 1000: char * 1001: getrealname(uid) 1002: int uid; 1003: { 1004: char *s, *c; 1005: 1006: #ifdef PASSNAMES 1007: #ifdef GETPWENT 1008: struct passwd *pwd = getpwuid(uid); 1009: 1010: s = pwd->pw_gecos; 1011: #else 1012: char tmpbuf[512]; 1013: int i; 1014: 1015: getpw(uid, tmpbuf); 1016: for (s=tmpbuf, i=GCOSFIELD-1; i; i--) { 1017: if (s) 1018: s = index(s,':')+1; 1019: } 1020: if (!s) 1021: return nullstr; 1022: cpytill(tmpbuf,s,':'); 1023: s = tmpbuf; 1024: #endif 1025: #ifdef BERKNAMES 1026: #ifdef BERKJUNK 1027: while (*s && !isalnum(*s) && *s != '&') s++; 1028: #endif 1029: if ((c = index(s, ',')) != Nullch) 1030: *c = '\0'; 1031: if ((c = index(s, ';')) != Nullch) 1032: *c = '\0'; 1033: s = cpytill(buf,s,'&'); 1034: if (*s == '&') { /* whoever thought this one up was */ 1035: c = buf + strlen(buf); /* in the middle of the night */ 1036: strcat(c,logname); /* before the morning after */ 1037: strcat(c,s+1); 1038: if (islower(*c)) 1039: *c = toupper(*c); /* gack and double gack */ 1040: } 1041: #else 1042: if ((c = index(s, '(')) != Nullch) 1043: *c = '\0'; 1044: if ((c = index(s, '-')) != Nullch) 1045: s = c; 1046: strcpy(buf,tmpbuf); 1047: #endif 1048: #ifdef GETPWENT 1049: endpwent(); 1050: #endif 1051: return buf; /* return something static */ 1052: #else 1053: if ((tmpfp=fopen(filexp(FULLNAMEFILE),"r")) != Nullfp) { 1054: fgets(buf,sizeof buf,tmpfp); 1055: fclose(tmpfp); 1056: buf[strlen(buf)-1] = '\0'; 1057: return buf; 1058: } 1059: return "PUT YOUR NAME HERE"; 1060: #endif 1061: } 1062: 1063: static void 1064: abort_interp() 1065: { 1066: fputs("\n% interp buffer overflow!\n",stdout) FLUSH; 1067: sig_catcher(0); 1068: }