Home | History | Annotate | Line # | Download | only in warp
intrp.c revision 1.1
      1 /* $Header: /tank/opengrok/rsync2/NetBSD/src/games/warp/intrp.c,v 1.1 2020/11/09 23:37:05 kamil 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 /* interpret interpolations */
    261 
    262 char *
    263 dointerp(dest,destsize,pattern,stoppers)
    264 Reg1 char *dest;
    265 Reg2 int destsize;
    266 Reg3 char *pattern;
    267 char *stoppers;
    268 {
    269     Reg4 char *s;
    270     Reg5 int i;
    271     char scrbuf[512];
    272     bool upper = FALSE;
    273     bool lastcomp = FALSE;
    274     int metabit = 0;
    275 
    276     while (*pattern && (!stoppers || !index(stoppers,*pattern))) {
    277 #ifdef DEBUGGING
    278 	if (debug & 8)
    279 	    printf("dointerp till %s at %s\r\n",stoppers?stoppers:"",pattern);
    280 #endif
    281 	if (*pattern == '%' && pattern[1]) {
    282 	    upper = FALSE;
    283 	    lastcomp = FALSE;
    284 	    for (s=Nullch; !s; ) {
    285 		switch (*++pattern) {
    286 		case '^':
    287 		    upper = TRUE;
    288 		    break;
    289 		case '_':
    290 		    lastcomp = TRUE;
    291 		    break;
    292 		case '{':
    293 		    pattern = cpytill(scrbuf,pattern+1,'}');
    294 		    if (s = index(scrbuf,'-'))
    295 			*s++ = '\0';
    296 		    else
    297 			s = nullstr;
    298 		    s = getval(scrbuf,s);
    299 		    break;
    300 #ifdef CONDSUB
    301 		case '(': {
    302 		    char rch;
    303 		    bool matched;
    304 
    305 		    pattern = dointerp(dest,destsize,pattern+1,"!=");
    306 		    rch = *pattern;
    307 		    if (rch == '!')
    308 			pattern++;
    309 		    if (*pattern != '=')
    310 			goto getout;
    311 		    pattern = cpytill(scrbuf,pattern+1,'?');
    312 		    if (!*pattern)
    313 			goto getout;
    314 		    if (*scrbuf == '^' && scrbuf[strlen(scrbuf)-1] == '$') {
    315 			scrbuf[strlen(scrbuf)-1] = '\0';
    316 			matched = strEQ(scrbuf+1,dest);
    317 		    }
    318 		    else
    319 			matched = instr(dest,scrbuf) != Nullch;
    320 		    if (matched==(rch == '=')) {
    321 			pattern = dointerp(dest,destsize,pattern+1,":)");
    322 			if (*pattern == ':')
    323 			    pattern = skipinterp(pattern+1,")");
    324 		    }
    325 		    else {
    326 			pattern = skipinterp(pattern+1,":)");
    327 			if (*pattern == ':')
    328 			    pattern++;
    329 			pattern = dointerp(dest,destsize,pattern,")");
    330 		    }
    331 		    s = dest;
    332 		    break;
    333 		}
    334 #endif
    335 #ifdef BACKTICK
    336 		case '`': {
    337 		    FILE *pipefp, *popen();
    338 
    339 		    pattern = dointerp(scrbuf,(sizeof scrbuf),pattern+1,"`");
    340 		    pipefp = popen(scrbuf,"r");
    341 		    if (pipefp != Nullfp) {
    342 			int len;
    343 
    344 			len = fread(scrbuf,sizeof(char),(sizeof scrbuf)-1,
    345 			    pipefp);
    346 			scrbuf[len] = '\0';
    347 			pclose(pipefp);
    348 		    }
    349 		    else {
    350 			printf("\r\nCan't run %s\r\n",scrbuf);
    351 			*scrbuf = '\0';
    352 		    }
    353 		    for (s=scrbuf; *s; s++) {
    354 			if (*s == '\n') {
    355 			    if (s[1])
    356 				*s = ' ';
    357 			    else
    358 				*s = '\0';
    359 			}
    360 		    }
    361 		    s = scrbuf;
    362 		    break;
    363 		}
    364 #endif
    365 #ifdef PROMPTTTY
    366 		case '"':
    367 		    pattern = dointerp(scrbuf,(sizeof scrbuf),pattern+1,"\"");
    368 		    fputs(scrbuf,stdout);
    369 		    resetty();
    370 		    gets(scrbuf);
    371 		    crmode();
    372 		    raw();
    373 		    noecho();
    374 		    nonl();
    375 		    s = scrbuf;
    376 		    break;
    377 #endif
    378 		case '~':
    379 		    s = homedir;
    380 		    break;
    381 		case '.':
    382 		    s = dotdir;
    383 		    break;
    384 		case '$':
    385 		    s = scrbuf;
    386 		    Sprintf(s,"%d",getpid());
    387 		    break;
    388 		case 'H':			/* host name */
    389 		    s = hostname;
    390 		    break;
    391 		case 'L':			/* login id */
    392 		    s = logname;
    393 		    break;
    394 		case 'N':			/* full name */
    395 		    s = getval("NAME",realname);
    396 		    break;
    397 		case 'O':
    398 		    s = origdir;
    399 		    break;
    400 		case 'p':
    401 		    s = cwd;
    402 		    break;
    403 		case 'X':			/* warp library */
    404 		    s = warplib;
    405 		    break;
    406 		default:
    407 		    if (--destsize <= 0)
    408 			abort_interp();
    409 		    *dest++ = *pattern | metabit;
    410 		    s = nullstr;
    411 		    break;
    412 		}
    413 	    }
    414 	    if (!s)
    415 		s = nullstr;
    416 	    pattern++;
    417 	    if (upper || lastcomp) {
    418 		char *t;
    419 
    420 		if (s != scrbuf) {
    421 		    Safecpy(scrbuf,s,(sizeof scrbuf));
    422 		    s = scrbuf;
    423 		}
    424 		if (upper || !(t=rindex(s,'/')))
    425 		    t = s;
    426 		while (*t && !isalpha(*t))
    427 		    t++;
    428 		if (islower(*t))
    429 		    *t = toupper(*t);
    430 	    }
    431 	    i = metabit;		/* maybe get into register */
    432 	    if (s == dest) {
    433 		while (*dest) {
    434 		    if (--destsize <= 0)
    435 			abort_interp();
    436 		    *dest++ |= i;
    437 		}
    438 	    }
    439 	    else {
    440 		while (*s) {
    441 		    if (--destsize <= 0)
    442 			abort_interp();
    443 		    *dest++ = *s++ | i;
    444 		}
    445 	    }
    446 	}
    447 	else {
    448 	    if (--destsize <= 0)
    449 		abort_interp();
    450 	    if (*pattern == '^' && pattern[1]) {
    451 		++pattern;			/* skip uparrow */
    452 		i = *pattern;		/* get char into a register */
    453 		if (i == '?')
    454 		    *dest++ = '\177' | metabit;
    455 		else if (i == '(') {
    456 		    metabit = 0200;
    457 		    destsize++;
    458 		}
    459 		else if (i == ')') {
    460 		    metabit = 0;
    461 		    destsize++;
    462 		}
    463 		else
    464 		    *dest++ = i & 037 | metabit;
    465 		pattern++;
    466 	    }
    467 	    else if (*pattern == '\\' && pattern[1]) {
    468 		++pattern;			/* skip backslash */
    469 		i = *pattern;		/* get char into a register */
    470 
    471 		/* this used to be a switch but the if may save space */
    472 
    473 		if (i >= '0' && i <= '7') {
    474 		    i = 1;
    475 		    while (i < 01000 && *pattern >= '0' && *pattern <= '7') {
    476 			i <<= 3;
    477 			i += *pattern++ - '0';
    478 		    }
    479 		    *dest++ = i & 0377 | metabit;
    480 		    --pattern;
    481 		}
    482 		else if (i == 'b')
    483 		    *dest++ = '\b' | metabit;
    484 		else if (i == 'f')
    485 		    *dest++ = '\f' | metabit;
    486 		else if (i == 'n')
    487 		    *dest++ = '\n' | metabit;
    488 		else if (i == 'r')
    489 		    *dest++ = '\r' | metabit;
    490 		else if (i == 't')
    491 		    *dest++ = '\t' | metabit;
    492 		else
    493 		    *dest++ = i | metabit;
    494 		pattern++;
    495 	    }
    496 	    else
    497 		*dest++ = *pattern++ | metabit;
    498 	}
    499     }
    500     *dest = '\0';
    501 getout:
    502     return pattern;			/* where we left off */
    503 }
    504 
    505 void
    506 interp(dest,destsize,pattern)
    507 char *dest;
    508 int destsize;
    509 char *pattern;
    510 {
    511     (void) dointerp(dest,destsize,pattern,Nullch);
    512 #ifdef DEBUGGING
    513     if (debug & DEB_FILEXP)
    514 	fputs(dest,stdout);
    515 #endif
    516 }
    517 
    518 /* get the person's real name from /etc/passwd */
    519 /* (string is overwritten, so it must be copied) */
    520 
    521 char *
    522 getrealname(uid)
    523 int uid;
    524 {
    525     char *s, *c;
    526 
    527 #ifdef PASSNAMES
    528     struct passwd *pwd = getpwuid(uid);
    529 
    530     s = pwd->pw_gecos;
    531 #ifdef BERKNAMES
    532 #ifdef BERKJUNK
    533     while (*s && !isalnum(*s) && *s != '&') s++;
    534 #endif
    535     if ((c = index(s, ',')) != Nullch)
    536 	*c = '\0';
    537     if ((c = index(s, ';')) != Nullch)
    538 	*c = '\0';
    539     s = cpytill(buf,s,'&');
    540     if (*s == '&') {			/* whoever thought this one up was */
    541 	c = buf + strlen(buf);		/* in the middle of the night */
    542 	strcat(c,logname);		/* before the morning after */
    543 	strcat(c,s+1);
    544 	if (islower(*c))
    545 	    *c = toupper(*c);		/* gack and double gack */
    546     }
    547 #else
    548     if ((c = index(s, '(')) != Nullch)
    549 	*c = '\0';
    550     if ((c = index(s, '-')) != Nullch)
    551 	s = c;
    552     strcpy(buf,tmpbuf);
    553 #endif
    554     endpwent();
    555     return buf;				/* return something static */
    556 #else
    557     if ((tmpfp=fopen(filexp(FULLNAMEFILE),"r")) != Nullfp) {
    558 	Fgets(buf,sizeof buf,tmpfp);
    559 	Fclose(tmpfp);
    560     }
    561     else {
    562 	resetty();
    563 	printf("What is your name? ");
    564 	Fgets(buf,(sizeof buf),stdin);
    565 	crmode();
    566 	raw();
    567 	noecho();
    568 	nonl();
    569 	if (fork())
    570 	    wait(0);
    571 	else {
    572 	    setuid(getuid());
    573 	    if ((tmpfp = fopen(filexp(FULLNAMEFILE),"w")) == NULL)
    574 		exit(1);
    575 	    fprintf(tmpfp, "%s\n", buf);
    576 	    Fclose(tmpfp);
    577 	    exit(0);
    578 	}
    579     }
    580     buf[strlen(buf)-1] = '\0';
    581     return buf;
    582 #endif
    583 }
    584 
    585 static void
    586 abort_interp()
    587 {
    588     fputs("\r\n% interp buffer overflow!\r\n",stdout);
    589     sig_catcher(0);
    590 }
    591