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

Defined functions

abort_interp defined in line 1063; used 5 times
dointerp defined in line 377; used 10 times
getrealname defined in line 1000; used 3 times
intrp_init defined in line 84; used 2 times
refscpy defined in line 943; used 3 times
skipinterp defined in line 306; used 8 times

Defined variables

hostname defined in line 57; used 4 times
orgname defined in line 42; used 1 times
realname defined in line 74; used 2 times
tildedir defined in line 71; used 7 times
tildename defined in line 70; used 9 times
uts defined in line 52; used 2 times

Defined macros

SITENAME defined in line 63; used 5 times
Last modified: 1985-06-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3318
Valid CSS Valid XHTML 1.0 Strict