|
|
1.1 root 1: /*
2: * built-in Korn commands: c_*
3: */
4:
5: static char *RCSid = "$Header: c_ksh.c,v 3.1 88/11/03 09:14:21 egisin Exp $";
6:
7: #include <stddef.h>
8: #include <stdlib.h>
9: #include <stdio.h>
10: #include <string.h>
11: #include <errno.h>
12: #include <setjmp.h>
13: #include <signal.h>
14: #include "sh.h"
15: #include "table.h"
16:
17: int
18: c_hash(wp)
19: register char **wp;
20: {
21: register int i;
22: register struct tbl *tp, **p;
23:
24: wp++;
25: if (*wp == NULL) {
26: for (p = tsort(&commands); (tp = *p++) != NULL; )
27: if ((tp->flag&ISSET))
28: printf("%s\n", tp->val.s);
29: return 0;
30: }
31:
32: if (strcmp(*wp, "-r") == 0)
33: flushcom(1);
34: while (*wp != NULL)
35: findcom(*wp++, 1);
36: return 0;
37: }
38:
39: int
40: c_print(wp)
41: register char **wp;
42: {
43: int nl = 1;
44: int expand = 1;
45: FILE *f = stdout;
46:
47: for (wp++; *wp != NULL && **wp == '-'; wp++) {
48: register char *s = *wp + 1;
49: if (*s == '\0') {
50: wp++;
51: break;
52: }
53: while (*s) switch (*s++) {
54: case 'n':
55: nl = 0;
56: break;
57: case 'e':
58: expand = 1;
59: break;
60: case 'r':
61: expand = 0;
62: break;
63: case 'u':
64: if (!digit(*s) || (f = shf[*s++-'0']) == NULL)
65: errorf("bad -u argument\n");
66: break;
67: }
68: }
69:
70: while (*wp != NULL) {
71: register char *s = *wp;
72: register int c;
73: while ((c = *s++) != '\0')
74: if (expand && c == '\\') {
75: switch ((c = *s++)) {
76: case 'b': c = '\b'; break;
77: case 'c': nl = 0; continue; /* AT&T brain damage */
78: case 'f': c = '\f'; break;
79: case 'n': c = '\n'; break;
80: case 'r': c = '\r'; break;
81: case 't': c = '\t'; break;
82: case 'v': c = 0x0B; break;
83: case '0': case '1': case '2': case '3':
84: case '4': case '5': case '6': case '7':
85: c = c - '0';
86: if (*s >= '0' && *s <= '7')
87: c = 8*c + *s++ - '0';
88: if (*s >= '0' && *s <= '7')
89: c = 8*c + *s++ - '0';
90: break;
91: case '\\': break;
92: default:
93: putc('\\', f);
94: }
95: putc(c, f);
96: } else
97: putc(c, f);
98: if (*++wp != NULL)
99: putc(' ', f);
100: }
101: if (nl)
102: putc('\n', f);
103: return 0;
104: }
105:
106: /* todo: handle case where id is both lexical and command */
107: int
108: c_whence(wp)
109: register char **wp;
110: {
111: register struct tbl *tp;
112: char *id;
113: int vflag = 0;
114:
115: for (wp++; (id = *wp) != NULL && *id == '-'; wp++)
116: if (id[1] == 'v')
117: vflag = 1;
118:
119: while ((id = *wp++) != NULL) {
120: tp = tsearch(&lexicals, id, hash(id));
121: if (tp == NULL)
122: tp = findcom(id, 1);
123: if (vflag)
124: switch ((tp == NULL) ? CNONE : tp->type) {
125: case CNONE:
126: printf("%s is unknown\n", id);
127: break;
128: case CSHELL:
129: printf("%s is a shell builtin\n", id);
130: break;
131: case CFUNC:
132: printf("%s is a function\n", id);
133: fptreef(stdout, "function %s %T\n", id, tp->val.t);
134: break;
135: case CEXEC:
136: printf("%s is %s\n", id,
137: (tp->flag&ISSET) ? tp->val.s : "unknown");
138: break;
139: case CALIAS:
140: printf("%s is the alias '%s'\n", id, tp->val.s);
141: break;
142: case CKEYWD:
143: printf("%s is a shell keyword\n", id);
144: break;
145: default:
146: printf("%s is *GOK*\n", id);
147: break;
148: }
149: else
150: switch ((tp == NULL) ? CNONE : tp->type) {
151: case CNONE:
152: printf("\n");
153: break;
154: case CSHELL:
155: printf("builtin %s\n", id);
156: break;
157: case CFUNC:
158: printf("%s\n", id);
159: break;
160: case CEXEC:
161: printf("%s\n", (tp->flag&ISSET) ? tp->val.s : id);
162: break;
163: case CALIAS:
164: printf("%s\n", tp->val.s);
165: break;
166: case CKEYWD:
167: printf("%s\n", id);
168: break;
169: default:
170: printf("*GOK*\n");
171: break;
172: }
173: }
174: return 0;
175: }
176:
177: int
178: c_typeset(wp)
179: register char **wp;
180: {
181: register char *id;
182: struct block *l = e.loc;
183: register struct tbl *vp, **p;
184: int fset = 0, fclr = 0;
185: int thing = 0, func = 0;
186:
187: for (wp++; (id = *wp) != NULL && (*id == '-' || *id == '+'); wp++) {
188: int flag = 0;
189: thing = *id;
190: while (*++id != '\0') switch (*id) {
191: case 'f':
192: flag |= FUNCT;
193: func = 1;
194: break;
195: case 'i':
196: flag |= INTEGER;
197: break;
198: case 'r':
199: flag |= RDONLY;
200: break;
201: case 'x':
202: flag |= EXPORT;
203: break;
204: case 't':
205: flag |= TRACE;
206: break;
207: default:
208: errorf("unknown flag -%c\n", *id);
209: }
210: if (flag != 0) { /* + or - with options */
211: if (thing == '-')
212: fset |= flag;
213: else
214: fclr |= flag;
215: thing = 0;
216: }
217: }
218:
219: /* list variables and attributes */
220: if (*wp == NULL) {
221: for (l = e.loc; l != NULL; l = l->next) {
222: for (p = tsort((func==0) ? &l->vars : &l->funs);
223: (vp = *p++) != NULL; )
224: if ((vp->flag&ISSET))
225: if (thing == 0 && fclr == 0 && fset == 0) {
226: printf("typeset ");
227: if ((vp->flag&INTEGER))
228: printf("-i ");
229: if ((vp->flag&EXPORT))
230: printf("-x ");
231: if ((vp->flag&RDONLY))
232: printf("-r ");
233: if ((vp->flag&TRACE))
234: printf("-t ");
235: printf("%s\n", vp->name);
236: } else
237: if (thing == '+' ||
238: fclr && (vp->flag&fclr) == fclr) {
239: printf("%s\n", vp->name);
240: } else
241: if (thing == '-' ||
242: fset && (vp->flag&fset) == fset) {
243: if (fset&FUNCT)
244: printf("function %s\n", vp->name);
245: else
246: printf("%s=%s\n", vp->name, strval(vp));
247: }
248: }
249: return (0);
250: }
251:
252: fset |= LOCAL;
253: for (; *wp != NULL; wp++)
254: #if 0
255: if (func) {
256: } else
257: #endif
258: if (typeset(*wp, fset, fclr) == NULL)
259: errorf("%s: not identifier\n", *wp);
260: return 0;
261: }
262:
263: int
264: c_alias(wp)
265: register char **wp;
266: {
267: register struct table *t = &lexicals;
268: register struct tbl *ap, **p;
269: register int i;
270: int rv = 0;
271:
272: if (*++wp != NULL && strcmp(*wp, "-d") == 0) {
273: t = &homedirs;
274: wp++;
275: }
276:
277: if (*wp == NULL)
278: for (p = tsort(t); (ap = *p++) != NULL; )
279: if (ap->type == CALIAS && (ap->flag&DEFINED))
280: printf("%s='%s'\n", ap->name, ap->val.s);
281:
282: for (; *wp != NULL; wp++) {
283: register char *id = *wp;
284: register char *val = strchr(id, '=');
285:
286: if (val == NULL) {
287: ap = tsearch(t, id, hash(id));
288: if (ap != NULL && ap->type == CALIAS && (ap->flag&DEFINED))
289: printf("%s='%s'\n", ap->name, ap->val.s);
290: else
291: rv = 1;
292: } else {
293: *val++ = '\0';
294: ap = tenter(t, id, hash(id));
295: if (ap->type == CKEYWD)
296: errorf("cannot alias keyword\n");
297: if ((ap->flag&ALLOC)) {
298: afree((Void*)ap->val.s, APERM);
299: ap->flag &=~ ALLOC|ISSET;
300: }
301: ap->type = CALIAS;
302: ap->val.s = strsave(val, APERM);
303: ap->flag |= DEFINED|ALLOC|ISSET;
304: }
305: }
306: return rv;
307: }
308:
309: int
310: c_unalias(wp)
311: register char **wp;
312: {
313: register struct table *t = &lexicals;
314: register struct tbl *ap;
315:
316: if (*++wp != NULL && strcmp(*wp, "-d") == 0) {
317: t = &homedirs;
318: wp++;
319: }
320:
321: for (; *wp != NULL; wp++) {
322: ap = tsearch(t, *wp, hash(*wp));
323: if (ap == NULL || ap->type != CALIAS)
324: continue;
325: if ((ap->flag&ALLOC))
326: afree((Void*)ap->val.s, APERM);
327: ap->flag &=~ DEFINED|ISSET|ALLOC;
328: }
329: return 0;
330: }
331:
332: int
333: c_let(wp)
334: char **wp;
335: {
336: int rv = 1;
337:
338: for (wp++; *wp; wp++)
339: rv = evaluate(*wp) == 0;
340: return rv;
341: }
342:
343: int
344: c_jobs(wp)
345: char **wp;
346: {
347: j_jobs();
348: return 0;
349: }
350:
351: #if JOBS
352: int
353: c_fgbg(wp)
354: register char **wp;
355: {
356: int bg = strcmp(*wp, "bg") == 0;
357:
358: if (!flag[FMONITOR])
359: errorf("Job control not enabled\n");
360: wp++;
361: j_resume(j_lookup((*wp == NULL) ? "%" : *wp), bg);
362: return 0;
363: }
364: #endif
365:
366: int
367: c_kill(wp)
368: register char **wp;
369: {
370: register char *cp;
371: int sig = SIGTERM;
372: int rv = 0;
373:
374: if (*++wp == NULL)
375: errorf("Usage: kill [-l] [-signal] {pid|job} ...\n");
376: if (strcmp(*wp, "-l") == 0) {
377: register struct trap *p = sigtraps;
378: for (sig = 0; sig < SIGNALS; sig++, p++)
379: if (p->signal)
380: printf("%2d %8s %s\n", p->signal, p->name, p->mess);
381: return 0;
382: }
383:
384: for (; (cp = *wp) != NULL; wp++)
385: if (*cp == '-' || isalpha(*cp)) {
386: struct trap *p;
387: p = gettrap((*cp == '-') ? cp+1 : cp);
388: if (p == NULL)
389: errorf("bad signal %s\n",
390: (*cp == '-') ? cp+1 : cp);
391: sig = p->signal;
392: } else if (digit(*cp)) {
393: if (kill(atoi(cp), sig) < 0) {
394: shellf("%s: %s\n", cp, strerror(errno));
395: rv++;
396: }
397: } else if (*cp == '%')
398: j_kill(j_lookup(cp), sig);
399: else
400: errorf("invalid argument\n");
401: return rv;
402: }
403:
404: int
405: c_bind(wp)
406: register char **wp;
407: {
408: int macro = 0;
409: register char *cp;
410:
411: for (wp++; (cp = *wp) != NULL && *cp == '-'; wp++)
412: if (cp[1] == 'm')
413: macro = 1;
414:
415: if (*wp == NULL) /* list all */
416: x_bind((char*)NULL, (char*)NULL, 0);
417:
418: for (; *wp != NULL; wp++) {
419: cp = strchr(*wp, '=');
420: if (cp != NULL)
421: *cp++ = 0;
422: x_bind(*wp, cp, macro);
423: }
424:
425: return 0;
426: }
427:
428: extern c_fc();
429: extern c_getopts();
430:
431: Const struct builtin kshbuiltins [] = {
432: {"print", c_print},
433: {"getopts", c_getopts},
434: {"=typeset", c_typeset},
435: {"whence", c_whence},
436: {"alias", c_alias},
437: {"unalias", c_unalias},
438: {"hash", c_hash},
439: {"let", c_let},
440: {"fc", c_fc},
441: {"jobs", c_jobs},
442: {"kill", c_kill},
443: #if JOBS
444: {"fg", c_fgbg},
445: {"bg", c_fgbg},
446: #endif
447: #if EDIT
448: {"bind", c_bind},
449: #endif
450: {NULL, NULL}
451: };
452:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.