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