c_sh.c revision 1.2 1 /* $NetBSD: c_sh.c,v 1.2 1997/01/12 19:11:40 tls Exp $ */
2
3 /*
4 * built-in Bourne commands
5 */
6
7 #include "sh.h"
8 #include "ksh_stat.h" /* umask() */
9 #include "ksh_time.h"
10 #include "ksh_times.h"
11
12 static char *clocktos ARGS((clock_t t));
13
14 /* :, false and true */
15 int
16 c_label(wp)
17 char **wp;
18 {
19 return wp[0][0] == 'f' ? 1 : 0;
20 }
21
22 int
23 c_shift(wp)
24 char **wp;
25 {
26 register struct block *l = e->loc;
27 register int n;
28 long val;
29 char *arg;
30
31 if (ksh_getopt(wp, &builtin_opt, null) == '?')
32 return 1;
33 arg = wp[builtin_opt.optind];
34
35 if (arg) {
36 evaluate(arg, &val, FALSE);
37 n = val;
38 } else
39 n = 1;
40 if (n < 0) {
41 bi_errorf("%s: bad number", arg);
42 return (1);
43 }
44 if (l->argc < n) {
45 bi_errorf("nothing to shift");
46 return (1);
47 }
48 l->argv[n] = l->argv[0];
49 l->argv += n;
50 l->argc -= n;
51 return 0;
52 }
53
54 int
55 c_umask(wp)
56 char **wp;
57 {
58 register int i;
59 register char *cp;
60 int symbolic = 0;
61 int old_umask;
62 int optc;
63
64 while ((optc = ksh_getopt(wp, &builtin_opt, "S")) != EOF)
65 switch (optc) {
66 case 'S':
67 symbolic = 1;
68 break;
69 case '?':
70 return 1;
71 }
72 cp = wp[builtin_opt.optind];
73 if (cp == NULL) {
74 old_umask = umask(0);
75 umask(old_umask);
76 if (symbolic) {
77 char buf[18];
78 int j;
79
80 old_umask = ~old_umask;
81 cp = buf;
82 for (i = 0; i < 3; i++) {
83 *cp++ = "ugo"[i];
84 *cp++ = '=';
85 for (j = 0; j < 3; j++)
86 if (old_umask & (1 << (8 - (3*i + j))))
87 *cp++ = "rwx"[j];
88 *cp++ = ',';
89 }
90 cp[-1] = '\0';
91 shprintf("%s\n", buf);
92 } else
93 shprintf("%#3.3o\n", old_umask);
94 } else {
95 int new_umask;
96
97 if (digit(*cp)) {
98 for (new_umask = 0; *cp >= '0' && *cp <= '7'; cp++)
99 new_umask = new_umask * 8 + (*cp - '0');
100 if (*cp) {
101 bi_errorf("bad number");
102 return 1;
103 }
104 } else {
105 /* symbolic format */
106 int positions, new_val;
107 char op;
108
109 old_umask = umask(0);
110 umask(old_umask); /* in case of error */
111 old_umask = ~old_umask;
112 new_umask = old_umask;
113 positions = 0;
114 while (*cp) {
115 while (*cp && strchr("augo", *cp))
116 switch (*cp++) {
117 case 'a': positions |= 0111; break;
118 case 'u': positions |= 0100; break;
119 case 'g': positions |= 0010; break;
120 case 'o': positions |= 0001; break;
121 }
122 if (!positions)
123 positions = 0111; /* default is a */
124 if (!strchr("=+-", op = *cp))
125 break;
126 cp++;
127 new_val = 0;
128 while (*cp && strchr("rwxugoXs", *cp))
129 switch (*cp++) {
130 case 'r': new_val |= 04; break;
131 case 'w': new_val |= 02; break;
132 case 'x': new_val |= 01; break;
133 case 'u': new_val |= old_umask >> 6;
134 break;
135 case 'g': new_val |= old_umask >> 3;
136 break;
137 case 'o': new_val |= old_umask >> 0;
138 break;
139 case 'X': if (old_umask & 0111)
140 new_val |= 01;
141 break;
142 case 's': /* ignored */
143 break;
144 }
145 new_val = (new_val & 07) * positions;
146 switch (op) {
147 case '-':
148 new_umask &= ~new_val;
149 break;
150 case '=':
151 new_umask = new_val
152 | (new_umask & ~(positions * 07));
153 break;
154 case '+':
155 new_umask |= new_val;
156 }
157 if (*cp == ',') {
158 positions = 0;
159 cp++;
160 } else if (!strchr("=+-", *cp))
161 break;
162 }
163 if (*cp) {
164 bi_errorf("bad mask");
165 return 1;
166 }
167 new_umask = ~new_umask;
168 }
169 umask(new_umask);
170 }
171 return 0;
172 }
173
174 int
175 c_dot(wp)
176 char **wp;
177 {
178 char *file, *cp;
179 char **argv;
180 int argc;
181 int i;
182
183 if (ksh_getopt(wp, &builtin_opt, null) == '?')
184 return 1;
185
186 if ((cp = wp[builtin_opt.optind]) == NULL)
187 return 0;
188 file = search(cp, path, R_OK, (int *) 0);
189 if (file == NULL) {
190 bi_errorf("%s: not found", cp);
191 return 1;
192 }
193
194 /* Set positional parameters? */
195 if (wp[builtin_opt.optind + 1]) {
196 argv = wp + builtin_opt.optind;
197 argv[0] = e->loc->argv[0]; /* preserve $0 */
198 for (argc = 0; argv[argc + 1]; argc++)
199 ;
200 } else {
201 argc = 0;
202 argv = (char **) 0;
203 }
204 i = include(file, argc, argv, 0);
205 if (i < 0) { /* should not happen */
206 bi_errorf("%s: %s", cp, strerror(errno));
207 return 1;
208 }
209 return i;
210 }
211
212 int
213 c_wait(wp)
214 char **wp;
215 {
216 int UNINITIALIZED(rv);
217 int sig;
218
219 if (ksh_getopt(wp, &builtin_opt, null) == '?')
220 return 1;
221 wp += builtin_opt.optind;
222 if (*wp == (char *) 0) {
223 while (waitfor((char *) 0, &sig) >= 0)
224 ;
225 rv = sig;
226 } else {
227 for (; *wp; wp++)
228 rv = waitfor(*wp, &sig);
229 if (rv < 0)
230 rv = sig ? sig : 127; /* magic exit code: bad job-id */
231 }
232 return rv;
233 }
234
235 int
236 c_read(wp)
237 char **wp;
238 {
239 register int c = 0;
240 int expand = 1, history = 0;
241 int expanding;
242 int ecode = 0;
243 register char *cp;
244 int fd = 0;
245 struct shf *shf;
246 int optc;
247 const char *emsg;
248 XString cs, xs;
249 struct tbl *vp;
250 char UNINITIALIZED(*xp);
251
252 while ((optc = ksh_getopt(wp, &builtin_opt, "prsu,")) != EOF)
253 switch (optc) {
254 #ifdef KSH
255 case 'p':
256 if ((fd = coproc_getfd(R_OK, &emsg)) < 0) {
257 bi_errorf("-p: %s", emsg);
258 return 1;
259 }
260 break;
261 #endif /* KSH */
262 case 'r':
263 expand = 0;
264 break;
265 case 's':
266 history = 1;
267 break;
268 case 'u':
269 if (!*(cp = builtin_opt.optarg))
270 fd = 0;
271 else if ((fd = check_fd(cp, R_OK, &emsg)) < 0) {
272 bi_errorf("-u: %s: %s", cp, emsg);
273 return 1;
274 }
275 break;
276 case '?':
277 return 1;
278 }
279 wp += builtin_opt.optind;
280
281 if (*wp == NULL)
282 *--wp = "REPLY";
283
284 /* Since we can't necessarily seek backwards on non-regular files,
285 * don't buffer them so we can't read too much.
286 */
287 shf = shf_reopen(fd, SHF_RD | SHF_INTERRUPT | can_seek(fd), shl_spare);
288
289 if ((cp = strchr(*wp, '?')) != NULL) {
290 *cp = 0;
291 if (isatty(fd)) {
292 /* at&t ksh says it prints prompt on fd if it's open
293 * for writing and is a tty, but it doesn't do it
294 * (it also doesn't check the interactive flag,
295 * as is indicated in the Kornshell book).
296 */
297 shellf("%s", cp+1);
298 }
299 }
300
301 #ifdef KSH
302 /* If we are reading from the co-process for the first time,
303 * make sure the other side of the pipe is closed first. This allows
304 * the detection of eof.
305 *
306 * This is not compatiable with at&t ksh... the fd is kept so another
307 * coproc can be started with same ouput, however, this means eof
308 * can't be detected... This is why it is closed here.
309 * If this call is removed, remove the eof check below, too.
310 * coproc_readw_close(fd);
311 */
312 #endif /* KSH */
313
314 if (history)
315 Xinit(xs, xp, 128, ATEMP);
316 expanding = 0;
317 Xinit(cs, cp, 128, ATEMP);
318 for (; *wp != NULL; wp++) {
319 for (cp = Xstring(cs, cp); ; ) {
320 if (c == '\n' || c == EOF)
321 break;
322 while (1) {
323 c = shf_getc(shf);
324 if (c == '\0'
325 #ifdef OS2
326 || c == '\r'
327 #endif /* OS2 */
328 )
329 continue;
330 if (c == EOF && shf_error(shf)
331 && shf_errno(shf) == EINTR)
332 {
333 /* Was the offending signal one that
334 * would normally kill a process?
335 * If so, pretend the read was killed.
336 */
337 ecode = fatal_trap_check();
338
339 /* non fatal (eg, CHLD), carry on */
340 if (!ecode) {
341 shf_clearerr(shf);
342 continue;
343 }
344 }
345 break;
346 }
347 if (history) {
348 Xcheck(xs, xp);
349 Xput(xs, xp, c);
350 }
351 Xcheck(cs, cp);
352 if (expanding) {
353 expanding = 0;
354 if (c == '\n') {
355 c = 0;
356 if (Flag(FTALKING) && isatty(fd)) {
357 /* set prompt in case this is
358 * called from .profile or $ENV
359 */
360 set_prompt(PS2, (Source *) 0);
361 pprompt(prompt, 0);
362 }
363 } else if (c != EOF)
364 Xput(cs, cp, c);
365 continue;
366 }
367 if (expand && c == '\\') {
368 expanding = 1;
369 continue;
370 }
371 if (c == '\n' || c == EOF)
372 break;
373 if (ctype(c, C_IFS)) {
374 if (Xlength(cs, cp) == 0 && ctype(c, C_IFSWS))
375 continue;
376 if (wp[1])
377 break;
378 }
379 Xput(cs, cp, c);
380 }
381 /* strip trailing IFS white space from last variable */
382 if (!wp[1])
383 while (Xlength(cs, cp) && ctype(cp[-1], C_IFS)
384 && ctype(cp[-1], C_IFSWS))
385 cp--;
386 Xput(cs, cp, '\0');
387 vp = global(*wp);
388 if (vp->flag & RDONLY) {
389 shf_flush(shf);
390 bi_errorf("%s is read only", *wp);
391 return 1;
392 }
393 if (Flag(FEXPORT))
394 typeset(*wp, EXPORT, 0, 0, 0);
395 setstr(vp, Xstring(cs, cp));
396 }
397
398 shf_flush(shf);
399 if (history) {
400 Xput(xs, xp, '\0');
401 source->line++;
402 histsave(source->line, Xstring(xs, xp), 1);
403 Xfree(xs, xp);
404 }
405 #ifdef KSH
406 /* if this is the co-process fd, close the file descriptor
407 * (can get eof if and only if all processes are have died, ie,
408 * coproc.njobs is 0 and the pipe is closed).
409 */
410 if (c == EOF && !ecode)
411 coproc_read_close(fd);
412 #endif /* KSH */
413
414 return ecode ? ecode : c == EOF;
415 }
416
417 int
418 c_eval(wp)
419 char **wp;
420 {
421 register struct source *s;
422
423 if (ksh_getopt(wp, &builtin_opt, null) == '?')
424 return 1;
425 s = pushs(SWORDS, ATEMP);
426 s->u.strv = wp + builtin_opt.optind;
427 return shell(s, FALSE);
428 }
429
430 int
431 c_trap(wp)
432 char **wp;
433 {
434 int i;
435 char *s;
436 register Trap *p;
437
438 if (ksh_getopt(wp, &builtin_opt, null) == '?')
439 return 1;
440 wp += builtin_opt.optind;
441
442 if (*wp == NULL) {
443 int anydfl = 0;
444
445 for (p = sigtraps, i = SIGNALS+1; --i >= 0; p++) {
446 if (p->trap == NULL)
447 anydfl = 1;
448 else {
449 shprintf("trap -- ");
450 print_value_quoted(p->trap);
451 shprintf(" %s\n", p->name);
452 }
453 }
454 #if 0 /* this is ugly and not clear POSIX needs it */
455 /* POSIX may need this so output of trap can be saved and
456 * used to restore trap conditions
457 */
458 if (anydfl) {
459 shprintf("trap -- -");
460 for (p = sigtraps, i = SIGNALS+1; --i >= 0; p++)
461 if (p->trap == NULL && p->name)
462 shprintf(" %s", p->name);
463 shprintf(newline);
464 }
465 #endif
466 return 0;
467 }
468
469 s = (gettrap(*wp) == NULL) ? *wp++ : NULL; /* get command */
470 if (s != NULL && s[0] == '-' && s[1] == '\0')
471 s = NULL;
472
473 /* set/clear traps */
474 while (*wp != NULL) {
475 p = gettrap(*wp++);
476 if (p == NULL) {
477 bi_errorf("bad signal %s", wp[-1]);
478 return 1;
479 }
480 settrap(p, s);
481 }
482 return 0;
483 }
484
485 int
486 c_exitreturn(wp)
487 char **wp;
488 {
489 int how = LEXIT;
490 char *arg;
491
492 if (ksh_getopt(wp, &builtin_opt, null) == '?')
493 return 1;
494 arg = wp[builtin_opt.optind];
495
496 if (arg != NULL && !getn(arg, &exstat)) {
497 exstat = 1;
498 warningf(TRUE, "%s: bad number", arg);
499 }
500 if (wp[0][0] == 'r') { /* return */
501 struct env *ep;
502
503 /* need to tell if this is exit or return so trap exit will
504 * work right (POSIX)
505 */
506 for (ep = e; ep; ep = ep->oenv)
507 if (STOP_RETURN(ep->type)) {
508 how = LRETURN;
509 break;
510 }
511 }
512
513 if (how == LEXIT && !really_exit && j_stopped_running()) {
514 really_exit = 1;
515 how = LSHELL;
516 }
517
518 quitenv(); /* get rid of any i/o redirections */
519 unwind(how);
520 /*NOTREACHED*/
521 return 0;
522 }
523
524 int
525 c_brkcont(wp)
526 char **wp;
527 {
528 int n, quit;
529 struct env *ep, *last_ep = (struct env *) 0;
530 char *arg;
531
532 if (ksh_getopt(wp, &builtin_opt, null) == '?')
533 return 1;
534 arg = wp[builtin_opt.optind];
535
536 if (!arg)
537 n = 1;
538 else if (!bi_getn(arg, &n))
539 return 1;
540 quit = n;
541 if (quit <= 0) {
542 /* at&t ksh does this for non-interactive shells only - weird */
543 bi_errorf("%s: bad value", arg);
544 return 1;
545 }
546
547 /* Stop at E_NONE, E_PARSE, E_FUNC, or E_INCL */
548 for (ep = e; ep && !STOP_BRKCONT(ep->type); ep = ep->oenv)
549 if (ep->type == E_LOOP) {
550 if (--quit == 0)
551 break;
552 ep->flags |= EF_BRKCONT_PASS;
553 last_ep = ep;
554 }
555
556 if (quit) {
557 /* at&t ksh doesn't print a message - just does what it
558 * can. We print a message 'cause it helps in debugging
559 * scripts, but don't generate an error (ie, keep going).
560 */
561 if (n == quit) {
562 warningf(TRUE, "%s: cannot %s", wp[0], wp[0]);
563 return 0;
564 }
565 /* POSIX says if n is too big, the last enclosing loop
566 * shall be used. Doesn't say to print an error but we
567 * do anyway 'cause the user messed up.
568 */
569 last_ep->flags &= ~EF_BRKCONT_PASS;
570 warningf(TRUE, "%s: can only %s %d level(s)",
571 wp[0], wp[0], n - quit);
572 }
573
574 unwind(*wp[0] == 'b' ? LBREAK : LCONTIN);
575 /*NOTREACHED*/
576 }
577
578 int
579 c_set(wp)
580 char **wp;
581 {
582 int argi, setargs;
583 struct block *l = e->loc;
584 register char **owp = wp;
585
586 if (wp[1] == NULL) {
587 static const char *const args [] = { "set", "-", NULL };
588 return c_typeset((char **) args);
589 }
590
591 argi = parse_args(wp, OF_SET, &setargs);
592 if (argi < 0)
593 return 1;
594 /* set $# and $* */
595 if (setargs) {
596 owp = wp += argi - 1;
597 wp[0] = l->argv[0]; /* save $0 */
598 while (*++wp != NULL)
599 *wp = str_save(*wp, &l->area);
600 l->argc = wp - owp - 1;
601 l->argv = (char **) alloc(sizeofN(char *, l->argc+2), &l->area);
602 for (wp = l->argv; (*wp++ = *owp++) != NULL; )
603 ;
604 }
605 /* POSIX says set exit status is 0, but old scripts that use
606 * getopt(1), use the construct: set -- `getopt ab:c "$@"`
607 * which assumes the exit value set will be that of the ``
608 * (subst_exstat is cleared in execute() so that it will be 0
609 * if there are no command substitutions).
610 */
611 return Flag(FPOSIX) ? 0 : subst_exstat;
612 }
613
614 int
615 c_unset(wp)
616 char **wp;
617 {
618 register char *id;
619 int optc, unset_var = 1;
620 int ret = 0;
621
622 while ((optc = ksh_getopt(wp, &builtin_opt, "fv")) != EOF)
623 switch (optc) {
624 case 'f':
625 unset_var = 0;
626 break;
627 case 'v':
628 unset_var = 1;
629 break;
630 case '?':
631 return 1;
632 }
633 wp += builtin_opt.optind;
634 for (; (id = *wp) != NULL; wp++)
635 if (unset_var) { /* unset variable */
636 struct tbl *vp = global(id);
637
638 if (!(vp->flag & ISSET))
639 ret = 1;
640 if ((vp->flag&RDONLY)) {
641 bi_errorf("%s is read only", vp->name);
642 return 1;
643 }
644 unset(vp, strchr(id, '[') ? 1 : 0);
645 } else { /* unset function */
646 if (define(id, (struct op *) NULL))
647 ret = 1;
648 }
649 return ret;
650 }
651
652 int
653 c_times(wp)
654 char **wp;
655 {
656 struct tms all;
657
658 (void) ksh_times(&all);
659 shprintf("Shell: %8s user ", clocktos(all.tms_utime));
660 shprintf("%8s system\n", clocktos(all.tms_stime));
661 shprintf("Kids: %8s user ", clocktos(all.tms_cutime));
662 shprintf("%8s system\n", clocktos(all.tms_cstime));
663
664 return 0;
665 }
666
667 /*
668 * time pipeline (really a statement, not a built-in command)
669 */
670 int
671 timex(t, f)
672 struct op *t;
673 int f;
674 {
675 int rv;
676 struct tms t0, t1;
677 clock_t t0t, t1t;
678 extern clock_t j_usrtime, j_systime; /* computed by j_wait */
679
680 j_usrtime = j_systime = 0;
681 t0t = ksh_times(&t0);
682 rv = execute(t->left, f);
683 t1t = ksh_times(&t1);
684
685 shf_fprintf(shl_out, "%8s real ", clocktos(t1t - t0t));
686 shf_fprintf(shl_out, "%8s user ",
687 clocktos(t1.tms_utime - t0.tms_utime + j_usrtime));
688 shf_fprintf(shl_out, "%8s system ",
689 clocktos(t1.tms_stime - t0.tms_stime + j_systime));
690 shf_fprintf(shl_out, newline);
691
692 return rv;
693 }
694
695 static char *
696 clocktos(t)
697 clock_t t;
698 {
699 static char temp[20];
700 register int i;
701 register char *cp = temp + sizeof(temp);
702
703 if (CLK_TCK != 100) /* convert to 1/100'ths */
704 t = (t < 1000000000/CLK_TCK) ?
705 (t * 100) / CLK_TCK : (t / CLK_TCK) * 100;
706
707 *--cp = '\0';
708 *--cp = 's';
709 for (i = -2; i <= 0 || t > 0; i++) {
710 if (i == 0)
711 *--cp = '.';
712 *--cp = '0' + (char)(t%10);
713 t /= 10;
714 }
715 return cp;
716 }
717
718 /* exec with no args - args case is taken care of in comexec() */
719 int
720 c_exec(wp)
721 char ** wp;
722 {
723 int i;
724
725 /* make sure redirects stay in place */
726 if (e->savefd != NULL) {
727 for (i = 0; i < NUFILE; i++) {
728 if (e->savefd[i] > 0)
729 close(e->savefd[i]);
730 /* keep anything > 2 private */
731 if (i > 2 && e->savefd[i])
732 fd_clexec(i);
733 }
734 e->savefd = NULL;
735 }
736 return 0;
737 }
738
739 /* dummy function, special case in comexec() */
740 int
741 c_builtin(wp)
742 char ** wp;
743 {
744 return 0;
745 }
746
747 extern int c_test ARGS((char **wp)); /* in c_test.c */
748 extern int c_ulimit ARGS((char **wp)); /* in c_ulimit.c */
749
750 /* A leading = means assignments before command are kept;
751 * a leading * means a POSIX special builtin;
752 * a leading + means a POSIX regular builtin
753 * (* and + should not be combined).
754 */
755 const struct builtin shbuiltins [] = {
756 {"*=.", c_dot},
757 {"*=:", c_label},
758 {"[", c_test},
759 {"*=break", c_brkcont},
760 {"=builtin", c_builtin},
761 {"*=continue", c_brkcont},
762 {"*=eval", c_eval},
763 {"*=exec", c_exec},
764 {"*=exit", c_exitreturn},
765 {"+false", c_label},
766 {"*=return", c_exitreturn},
767 {"*=set", c_set},
768 {"*=shift", c_shift},
769 {"=times", c_times},
770 {"*=trap", c_trap},
771 {"+=wait", c_wait},
772 {"+read", c_read},
773 {"test", c_test},
774 {"+true", c_label},
775 {"ulimit", c_ulimit},
776 {"+umask", c_umask},
777 {"*=unset", c_unset},
778 #ifdef OS2
779 /* In OS2, the first line of a file can be "extproc name", which
780 * tells the command interpreter (cmd.exe) to use name to execute
781 * the file. For this to be useful, ksh must ignore commands
782 * starting with extproc and this does the trick...
783 */
784 {"extproc", c_label},
785 #endif /* OS2 */
786 {NULL, NULL}
787 };
788