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

Defined functions

abort_interp defined in line 1006; used 5 times
dointerp defined in line 337; used 10 times
getrealname defined in line 960; used 3 times
intrp_init defined in line 84; used 2 times
refscpy defined in line 903; used 3 times
skipinterp defined in line 266; 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 6 times
tildename defined in line 70; used 7 times
uts defined in line 52; used 2 times

Defined macros

SITENAME defined in line 63; used 5 times
Last modified: 1995-01-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6232
Valid CSS Valid XHTML 1.0 Strict