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