|
|
1.1 root 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: /* 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.