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