1: /* $Header: /usr/src/games/warp/RCS/intrp.c,v 1.3.2 97/10/2 22:40:37 games Exp $
   2:  *
   3:  * $Log:	intrp.c,v $
   4:  * Revision 7.0.2  93/12/31  23:40:37  games
   5:  * Removed shortnames.h for new version of 2.11BSD
   6:  *
   7:  * Revision 7.0.1.2a  87/07/03  00:56:37  games
   8:  * Included shortnames.h for 2.10BSD
   9:  *
  10:  * Revision 7.0.1.2  86/12/12  16:59:04  lwall
  11:  * Baseline for net release.
  12:  *
  13:  * Revision 7.0.1.1  86/10/16  10:51:43  lwall
  14:  * Added Damage.  Fixed random bugs.
  15:  *
  16:  * Revision 7.0  86/10/08  15:12:19  lwall
  17:  * Split into separate files.  Added amoebas and pirates.
  18:  *
  19:  */
  20: 
  21: #include "EXTERN.h"
  22: #include "warp.h"
  23: #include "sig.h"
  24: #include "util.h"
  25: #include "term.h"
  26: #include "INTERN.h"
  27: #include "intrp.h"
  28: #include <unistd.h>
  29: 
  30: /* name of this host */
  31: #ifdef GETHOSTNAME
  32:     char *hostname;
  33: #   undef HOSTNAME
  34: #   define HOSTNAME hostname
  35: #else /* !GETHOSTNAME */
  36: #   ifdef DOUNAME
  37: #	include <sys/utsname.h>
  38:     struct utsname uts;
  39: #	undef HOSTNAME
  40: #	define HOSTNAME uts.nodename
  41: #   else /* !DOUNAME */
  42: #	ifdef PHOSTNAME
  43:         char *hostname;
  44: #	    undef HOSTNAME
  45: #	    define HOSTNAME hostname
  46: #	else /* !PHOSTNAME */
  47: #	    ifdef WHOAMI
  48: #		undef HOSTNAME
  49: #		define HOSTNAME sysname
  50: #	    endif /* WHOAMI */
  51: #	endif /* PHOSTNAME */
  52: #   endif /* DOUNAME */
  53: #endif /* GETHOSTNAME */
  54: 
  55: #ifdef TILDENAME
  56: static char *tildename = Nullch;
  57: static char *tildedir = Nullch;
  58: #endif
  59: 
  60: char *dointerp();
  61: char *getrealname();
  62: #ifdef CONDSUB
  63: char *skipinterp();
  64: #endif
  65: 
  66: static void abort_interp();
  67: 
  68: void
  69: intrp_init(tcbuf)
  70: char *tcbuf;
  71: {
  72: 
  73:     /* get environmental stuff */
  74: 
  75:     /* get home directory */
  76: 
  77:     homedir = getenv("HOME");
  78:     if (homedir == Nullch)
  79:     homedir = getenv("LOGDIR");
  80: 
  81:     dotdir = getval("DOTDIR",homedir);
  82: 
  83:     /* get login name */
  84: 
  85:     logname = getenv("USER");
  86:     if (logname == Nullch)
  87:     logname = getenv("LOGNAME");
  88: #ifdef GETLOGIN
  89:     if (logname == Nullch)
  90:     logname = savestr(getlogin());
  91: #endif
  92: 
  93:     /* get the real name of the person (%N) */
  94:     /* Must be done after logname is read in because BERKNAMES uses that */
  95: 
  96:     strcpy(tcbuf,getrealname(getuid()));
  97:     realname = savestr(tcbuf);
  98: 
  99:     /* name of this host (%H) */
 100: 
 101: #ifdef GETHOSTNAME
 102:     gethostname(buf,sizeof buf);
 103:     hostname = savestr(buf);
 104: #else
 105: #ifdef DOUNAME
 106:     /* get sysname */
 107:     uname(&uts);
 108: #else
 109: #ifdef PHOSTNAME
 110:     {
 111:     FILE *popen();
 112:     FILE *pipefp = popen(PHOSTNAME,"r");
 113: 
 114:     if (pipefp == Nullfp) {
 115:         printf("Can't find hostname\r\n");
 116:         sig_catcher(0);
 117:     }
 118:     Fgets(buf,sizeof buf,pipefp);
 119:     buf[strlen(buf)-1] = '\0';  /* wipe out newline */
 120:     hostname = savestr(buf);
 121:     pclose(pipefp);
 122:     }
 123: #endif
 124: #endif
 125: #endif
 126:     if (index(HOSTNAME,'.'))
 127:     hostname = savestr(HOSTNAME);
 128:     else {
 129:     char hname[128];
 130: 
 131:     strcpy(hname,HOSTNAME);
 132:     strcat(hname,MYDOMAIN);
 133:     hostname=savestr(hname);
 134:     }
 135:     warplib = savestr(filexp(WARPLIB));
 136: 
 137:     if (scorespec)          /* that getwd below takes ~1/3 sec. */
 138:     return;             /* and we do not need it for -s */
 139:     (void) getwd(tcbuf);        /* find working directory name */
 140:     origdir = savestr(tcbuf);       /* and remember it */
 141: }
 142: 
 143: /* expand filename via %, ~, and $ interpretation */
 144: /* returns pointer to static area */
 145: /* Note that there is a 1-deep cache of ~name interpretation */
 146: 
 147: char *
 148: filexp(s)
 149: Reg1 char *s;
 150: {
 151:     static char filename[CBUFLEN];
 152:     char scrbuf[CBUFLEN];
 153:     Reg2 char *d;
 154: 
 155: #ifdef DEBUGGING
 156:     if (debug & DEB_FILEXP)
 157:     printf("< %s\r\n",s);
 158: #endif
 159:     interp(filename, (sizeof filename), s);         /* interpret any % escapes */
 160: #ifdef DEBUGGING
 161:     if (debug & DEB_FILEXP)
 162:     printf("%% %s\r\n",filename);
 163: #endif
 164:     s = filename;
 165:     if (*s == '~') {    /* does destination start with ~? */
 166:     if (!*(++s) || *s == '/') {
 167:         Sprintf(scrbuf,"%s%s",homedir,s);
 168:                 /* swap $HOME for it */
 169: #ifdef DEBUGGING
 170:     if (debug & DEB_FILEXP)
 171:     printf("~ %s\r\n",scrbuf);
 172: #endif
 173:         strcpy(filename,scrbuf);
 174:     }
 175:     else {
 176: #ifdef TILDENAME
 177:         for (d=scrbuf; isalnum(*s); s++,d++)
 178:         *d = *s;
 179:         *d = '\0';
 180:         if (tildedir && strEQ(tildename,scrbuf)) {
 181:         strcpy(scrbuf,tildedir);
 182:         strcat(scrbuf, s);
 183:         strcpy(filename, scrbuf);
 184: #ifdef DEBUGGING
 185:         if (debug & DEB_FILEXP)
 186:             printf("r %s %s\r\n",tildename,tildedir);
 187: #endif
 188:         }
 189:         else {
 190:         if (tildename) {
 191:             free(tildename);
 192:             free(tildedir);
 193:         }
 194:         tildedir = Nullch;
 195:         tildename = savestr(scrbuf);
 196: #ifdef GETPWENT     /* getpwnam() is not the paragon of efficiency */
 197:         {
 198:             struct passwd *getpwnam();
 199:             struct passwd *pwd = getpwnam(tildename);
 200: 
 201:             Sprintf(scrbuf,"%s%s",pwd->pw_dir,s);
 202:             tildedir = savestr(pwd->pw_dir);
 203:             strcpy(filename,scrbuf);
 204: #ifdef GETPWENT
 205:             endpwent();
 206: #endif
 207:         }
 208: #else           /* this will run faster, and is less D space */
 209:         {   /* just be sure LOGDIRFIELD is correct */
 210:             FILE *pfp = fopen("/etc/passwd","r");
 211:             char tmpbuf[512];
 212:             int i;
 213: 
 214:             if (pfp == Nullfp) {
 215:             printf(cantopen,"passwd");
 216:             sig_catcher(0);
 217:             }
 218:             while (fgets(tmpbuf,512,pfp) != Nullch) {
 219:             d = cpytill(scrbuf,tmpbuf,':');
 220: #ifdef DEBUGGING
 221:             if (debug & DEB_FILEXP)
 222:                 printf("p %s\r\n",tmpbuf);
 223: #endif
 224:             if (strEQ(scrbuf,tildename)) {
 225:                 for (i=LOGDIRFIELD-2; i; i--) {
 226:                 if (d)
 227:                     d = index(d+1,':');
 228:                 }
 229:                 if (d) {
 230:                 Cpytill(scrbuf,d+1,':');
 231:                 tildedir = savestr(scrbuf);
 232:                 strcat(scrbuf,s);
 233:                 strcpy(filename,scrbuf);
 234:                 }
 235:                 break;
 236:             }
 237:             }
 238:             Fclose(pfp);
 239:         }
 240: #endif
 241:         }
 242: #else /* !TILDENAME */
 243: #ifdef VERBOSE
 244:         IF(verbose)
 245:         fputs("~loginname not implemented.\r\n",stdout);
 246:         ELSE
 247: #endif
 248: #ifdef TERSE
 249:         fputs("~login not impl.\r\n",stdout);
 250: #endif
 251: #endif
 252:     }
 253:     }
 254:     else if (*s == '$') {   /* starts with some env variable? */
 255:     d = scrbuf;
 256:     *d++ = '%';
 257:     if (s[1] == '{')
 258:         strcpy(d,s+2);
 259:     else {
 260:         *d++ = '{';
 261:         for (s++; isalnum(*s); s++) *d++ = *s;
 262:                 /* skip over token */
 263:         *d++ = '}';
 264:         strcpy(d,s);
 265:     }
 266: #ifdef DEBUGGING
 267:     if (debug & DEB_FILEXP)
 268:         printf("$ %s\r\n",scrbuf);
 269: #endif
 270:     interp(filename, (sizeof filename), scrbuf);
 271:                     /* this might do some extra '%'s but */
 272:                     /* that is how the Mercedes Benz */
 273:     }
 274: #ifdef DEBUGGING
 275:     if (debug & DEB_FILEXP)
 276:     printf("> %s\r\n",filename);
 277: #endif
 278:     return filename;
 279: }
 280: 
 281: #ifdef CONDSUB
 282: /* skip interpolations */
 283: 
 284: char *
 285: skipinterp(pattern,stoppers)
 286: Reg1 char *pattern;
 287: char *stoppers;
 288: {
 289: 
 290:     while (*pattern && (!stoppers || !index(stoppers,*pattern))) {
 291: #ifdef DEBUGGING
 292:     if (debug & 8)
 293:         printf("skipinterp till %s at %s\r\n",stoppers?stoppers:"",pattern);
 294: #endif
 295:     if (*pattern == '%' && pattern[1]) {
 296:         switch (*++pattern) {
 297:         case '{':
 298:         for (pattern++; *pattern && *pattern != '}'; pattern++)
 299:             if (*pattern == '\\')
 300:             pattern++;
 301:         break;
 302: #ifdef CONDSUB
 303:         case '(': {
 304:         pattern = skipinterp(pattern+1,"!=");
 305:         if (!*pattern)
 306:             goto getout;
 307:         for (pattern++; *pattern && *pattern != '?'; pattern++)
 308:             if (*pattern == '\\')
 309:             pattern++;
 310:         if (!*pattern)
 311:             goto getout;
 312:         pattern = skipinterp(pattern+1,":)");
 313:         if (*pattern == ':')
 314:             pattern = skipinterp(pattern+1,")");
 315:         break;
 316:         }
 317: #endif
 318: #ifdef BACKTICK
 319:         case '`': {
 320:         pattern = skipinterp(pattern+1,"`");
 321:         break;
 322:         }
 323: #endif
 324: #ifdef PROMPTTTY
 325:         case '"':
 326:         pattern = skipinterp(pattern+1,"\"");
 327:         break;
 328: #endif
 329:         default:
 330:         break;
 331:         }
 332:         pattern++;
 333:     }
 334:     else {
 335:         if (*pattern == '^' && pattern[1])
 336:         pattern += 2;
 337:         else if (*pattern == '\\' && pattern[1])
 338:         pattern += 2;
 339:         else
 340:         pattern++;
 341:     }
 342:     }
 343: getout:
 344:     return pattern;         /* where we left off */
 345: }
 346: #endif
 347: 
 348: /* interpret interpolations */
 349: 
 350: char *
 351: dointerp(dest,destsize,pattern,stoppers)
 352: Reg1 char *dest;
 353: Reg2 int destsize;
 354: Reg3 char *pattern;
 355: char *stoppers;
 356: {
 357:     Reg4 char *s;
 358:     Reg5 int i;
 359:     char scrbuf[512];
 360:     bool upper = FALSE;
 361:     bool lastcomp = FALSE;
 362:     int metabit = 0;
 363: 
 364:     while (*pattern && (!stoppers || !index(stoppers,*pattern))) {
 365: #ifdef DEBUGGING
 366:     if (debug & 8)
 367:         printf("dointerp till %s at %s\r\n",stoppers?stoppers:"",pattern);
 368: #endif
 369:     if (*pattern == '%' && pattern[1]) {
 370:         upper = FALSE;
 371:         lastcomp = FALSE;
 372:         for (s=Nullch; !s; ) {
 373:         switch (*++pattern) {
 374:         case '^':
 375:             upper = TRUE;
 376:             break;
 377:         case '_':
 378:             lastcomp = TRUE;
 379:             break;
 380:         case '{':
 381:             pattern = cpytill(scrbuf,pattern+1,'}');
 382:             if (s = index(scrbuf,'-'))
 383:             *s++ = '\0';
 384:             else
 385:             s = nullstr;
 386:             s = getval(scrbuf,s);
 387:             break;
 388: #ifdef CONDSUB
 389:         case '(': {
 390:             char rch;
 391:             bool matched;
 392: 
 393:             pattern = dointerp(dest,destsize,pattern+1,"!=");
 394:             rch = *pattern;
 395:             if (rch == '!')
 396:             pattern++;
 397:             if (*pattern != '=')
 398:             goto getout;
 399:             pattern = cpytill(scrbuf,pattern+1,'?');
 400:             if (!*pattern)
 401:             goto getout;
 402:             if (*scrbuf == '^' && scrbuf[strlen(scrbuf)-1] == '$') {
 403:             scrbuf[strlen(scrbuf)-1] = '\0';
 404:             matched = strEQ(scrbuf+1,dest);
 405:             }
 406:             else
 407:             matched = instr(dest,scrbuf) != Nullch;
 408:             if (matched==(rch == '=')) {
 409:             pattern = dointerp(dest,destsize,pattern+1,":)");
 410:             if (*pattern == ':')
 411:                 pattern = skipinterp(pattern+1,")");
 412:             }
 413:             else {
 414:             pattern = skipinterp(pattern+1,":)");
 415:             if (*pattern == ':')
 416:                 pattern++;
 417:             pattern = dointerp(dest,destsize,pattern,")");
 418:             }
 419:             s = dest;
 420:             break;
 421:         }
 422: #endif
 423: #ifdef BACKTICK
 424:         case '`': {
 425:             FILE *pipefp, *popen();
 426: 
 427:             pattern = dointerp(scrbuf,(sizeof scrbuf),pattern+1,"`");
 428:             pipefp = popen(scrbuf,"r");
 429:             if (pipefp != Nullfp) {
 430:             int len;
 431: 
 432:             len = fread(scrbuf,sizeof(char),(sizeof scrbuf)-1,
 433:                 pipefp);
 434:             scrbuf[len] = '\0';
 435:             pclose(pipefp);
 436:             }
 437:             else {
 438:             printf("\r\nCan't run %s\r\n",scrbuf);
 439:             *scrbuf = '\0';
 440:             }
 441:             for (s=scrbuf; *s; s++) {
 442:             if (*s == '\n') {
 443:                 if (s[1])
 444:                 *s = ' ';
 445:                 else
 446:                 *s = '\0';
 447:             }
 448:             }
 449:             s = scrbuf;
 450:             break;
 451:         }
 452: #endif
 453: #ifdef PROMPTTTY
 454:         case '"':
 455:             pattern = dointerp(scrbuf,(sizeof scrbuf),pattern+1,"\"");
 456:             fputs(scrbuf,stdout);
 457:             resetty();
 458:             gets(scrbuf);
 459:             crmode();
 460:             raw();
 461:             noecho();
 462:             nonl();
 463:             s = scrbuf;
 464:             break;
 465: #endif
 466:         case '~':
 467:             s = homedir;
 468:             break;
 469:         case '.':
 470:             s = dotdir;
 471:             break;
 472:         case '$':
 473:             s = scrbuf;
 474:             Sprintf(s,"%d",getpid());
 475:             break;
 476:         case 'H':           /* host name */
 477:             s = hostname;
 478:             break;
 479:         case 'L':           /* login id */
 480:             s = logname;
 481:             break;
 482:         case 'N':           /* full name */
 483:             s = getval("NAME",realname);
 484:             break;
 485:         case 'O':
 486:             s = origdir;
 487:             break;
 488:         case 'p':
 489:             s = cwd;
 490:             break;
 491:         case 'X':           /* warp library */
 492:             s = warplib;
 493:             break;
 494:         default:
 495:             if (--destsize <= 0)
 496:             abort_interp();
 497:             *dest++ = *pattern | metabit;
 498:             s = nullstr;
 499:             break;
 500:         }
 501:         }
 502:         if (!s)
 503:         s = nullstr;
 504:         pattern++;
 505:         if (upper || lastcomp) {
 506:         char *t;
 507: 
 508:         if (s != scrbuf) {
 509:             Safecpy(scrbuf,s,(sizeof scrbuf));
 510:             s = scrbuf;
 511:         }
 512:         if (upper || !(t=rindex(s,'/')))
 513:             t = s;
 514:         while (*t && !isalpha(*t))
 515:             t++;
 516:         if (islower(*t))
 517:             *t = toupper(*t);
 518:         }
 519:         i = metabit;        /* maybe get into register */
 520:         if (s == dest) {
 521:         while (*dest) {
 522:             if (--destsize <= 0)
 523:             abort_interp();
 524:             *dest++ |= i;
 525:         }
 526:         }
 527:         else {
 528:         while (*s) {
 529:             if (--destsize <= 0)
 530:             abort_interp();
 531:             *dest++ = *s++ | i;
 532:         }
 533:         }
 534:     }
 535:     else {
 536:         if (--destsize <= 0)
 537:         abort_interp();
 538:         if (*pattern == '^' && pattern[1]) {
 539:         ++pattern;          /* skip uparrow */
 540:         i = *pattern;       /* get char into a register */
 541:         if (i == '?')
 542:             *dest++ = '\177' | metabit;
 543:         else if (i == '(') {
 544:             metabit = 0200;
 545:             destsize++;
 546:         }
 547:         else if (i == ')') {
 548:             metabit = 0;
 549:             destsize++;
 550:         }
 551:         else
 552:             *dest++ = i & 037 | metabit;
 553:         pattern++;
 554:         }
 555:         else if (*pattern == '\\' && pattern[1]) {
 556:         ++pattern;          /* skip backslash */
 557:         i = *pattern;       /* get char into a register */
 558: 
 559:         /* this used to be a switch but the if may save space */
 560: 
 561:         if (i >= '0' && i <= '7') {
 562:             i = 1;
 563:             while (i < 01000 && *pattern >= '0' && *pattern <= '7') {
 564:             i <<= 3;
 565:             i += *pattern++ - '0';
 566:             }
 567:             *dest++ = i & 0377 | metabit;
 568:             --pattern;
 569:         }
 570:         else if (i == 'b')
 571:             *dest++ = '\b' | metabit;
 572:         else if (i == 'f')
 573:             *dest++ = '\f' | metabit;
 574:         else if (i == 'n')
 575:             *dest++ = '\n' | metabit;
 576:         else if (i == 'r')
 577:             *dest++ = '\r' | metabit;
 578:         else if (i == 't')
 579:             *dest++ = '\t' | metabit;
 580:         else
 581:             *dest++ = i | metabit;
 582:         pattern++;
 583:         }
 584:         else
 585:         *dest++ = *pattern++ | metabit;
 586:     }
 587:     }
 588:     *dest = '\0';
 589: getout:
 590:     return pattern;         /* where we left off */
 591: }
 592: 
 593: void
 594: interp(dest,destsize,pattern)
 595: char *dest;
 596: int destsize;
 597: char *pattern;
 598: {
 599:     (void) dointerp(dest,destsize,pattern,Nullch);
 600: #ifdef DEBUGGING
 601:     if (debug & DEB_FILEXP)
 602:     fputs(dest,stdout);
 603: #endif
 604: }
 605: 
 606: /* get the person's real name from /etc/passwd */
 607: /* (string is overwritten, so it must be copied) */
 608: 
 609: char *
 610: getrealname(uid)
 611: int uid;
 612: {
 613:     char *s, *c;
 614: 
 615: #ifdef PASSNAMES
 616:     struct passwd *pwd = getpwuid(uid);
 617: 
 618:     s = pwd->pw_gecos;
 619: #ifdef BERKNAMES
 620: #ifdef BERKJUNK
 621:     while (*s && !isalnum(*s) && *s != '&') s++;
 622: #endif
 623:     if ((c = index(s, ',')) != Nullch)
 624:     *c = '\0';
 625:     if ((c = index(s, ';')) != Nullch)
 626:     *c = '\0';
 627:     s = cpytill(buf,s,'&');
 628:     if (*s == '&') {            /* whoever thought this one up was */
 629:     c = buf + strlen(buf);      /* in the middle of the night */
 630:     strcat(c,logname);      /* before the morning after */
 631:     strcat(c,s+1);
 632:     if (islower(*c))
 633:         *c = toupper(*c);       /* gack and double gack */
 634:     }
 635: #else
 636:     if ((c = index(s, '(')) != Nullch)
 637:     *c = '\0';
 638:     if ((c = index(s, '-')) != Nullch)
 639:     s = c;
 640:     strcpy(buf,tmpbuf);
 641: #endif
 642:     endpwent();
 643:     return buf;             /* return something static */
 644: #else
 645:     if ((tmpfp=fopen(filexp(FULLNAMEFILE),"r")) != Nullfp) {
 646:     Fgets(buf,sizeof buf,tmpfp);
 647:     Fclose(tmpfp);
 648:     }
 649:     else {
 650:     resetty();
 651:     printf("What is your name? ");
 652:     Fgets(buf,(sizeof buf),stdin);
 653:     crmode();
 654:     raw();
 655:     noecho();
 656:     nonl();
 657:     if (fork())
 658:         wait(0);
 659:     else {
 660:         setuid(getuid());
 661:         if ((tmpfp = fopen(filexp(FULLNAMEFILE),"w")) == NULL)
 662:         exit(1);
 663:         fprintf(tmpfp, "%s\n", buf);
 664:         Fclose(tmpfp);
 665:         exit(0);
 666:     }
 667:     }
 668:     buf[strlen(buf)-1] = '\0';
 669:     return buf;
 670: #endif
 671: }
 672: 
 673: static void
 674: abort_interp()
 675: {
 676:     fputs("\r\n% interp buffer overflow!\r\n",stdout);
 677:     sig_catcher(0);
 678: }

Defined functions

abort_interp defined in line 673; used 5 times
dointerp defined in line 350; used 9 times
filexp defined in line 147; used 5 times
getrealname defined in line 609; used 3 times
interp defined in line 593; used 6 times
intrp_init defined in line 68; used 2 times
skipinterp defined in line 284; used 8 times

Defined variables

hostname defined in line 43; used 7 times
tildedir defined in line 57; used 7 times
tildename defined in line 56; used 7 times
uts defined in line 38; used 2 times

Defined macros

HOSTNAME defined in line 49; used 7 times
Last modified: 1997-10-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4511
Valid CSS Valid XHTML 1.0 Strict