1 /* $OpenBSD: c_sh.c,v 1.40 2009/05/05 17:59:55 millert Exp $ */ 2 3 /* 4 * built-in Bourne commands 5 */ 6 7 #include "sh.h" 8 #include <sys/stat.h> 9 #include <sys/time.h> 10 #include <sys/resource.h> 11 12 static void p_time(struct shf *, int, struct timeval *, int, char *, char *); 13 14 /* :, false and true */ 15 int 16 c_label(char **wp) 17 { 18 return wp[0][0] == 'f' ? 1 : 0; 19 } 20 21 int 22 c_shift(char **wp) 23 { 24 struct block *l = e->loc; 25 int n; 26 long val; 27 char *arg; 28 29 if (ksh_getopt(wp, &builtin_opt, null) == '?') 30 return 1; 31 arg = wp[builtin_opt.optind]; 32 33 if (arg) { 34 evaluate(arg, &val, KSH_UNWIND_ERROR, false); 35 n = val; 36 } else 37 n = 1; 38 if (n < 0) { 39 bi_errorf("%s: bad number", arg); 40 return (1); 41 } 42 if (l->argc < n) { 43 bi_errorf("nothing to shift"); 44 return (1); 45 } 46 l->argv[n] = l->argv[0]; 47 l->argv += n; 48 l->argc -= n; 49 return 0; 50 } 51 52 int 53 c_umask(char **wp) 54 { 55 int i; 56 char *cp; 57 int symbolic = 0; 58 mode_t old_umask; 59 int optc; 60 61 while ((optc = ksh_getopt(wp, &builtin_opt, "S")) != -1) 62 switch (optc) { 63 case 'S': 64 symbolic = 1; 65 break; 66 case '?': 67 return 1; 68 } 69 cp = wp[builtin_opt.optind]; 70 if (cp == NULL) { 71 old_umask = umask(0); 72 umask(old_umask); 73 if (symbolic) { 74 char buf[18]; 75 int j; 76 77 old_umask = ~old_umask; 78 cp = buf; 79 for (i = 0; i < 3; i++) { 80 *cp++ = "ugo"[i]; 81 *cp++ = '='; 82 for (j = 0; j < 3; j++) 83 if (old_umask & (1 << (8 - (3*i + j)))) 84 *cp++ = "rwx"[j]; 85 *cp++ = ','; 86 } 87 cp[-1] = '\0'; 88 shprintf("%s\n", buf); 89 } else 90 shprintf("%#3.3o\n", old_umask); 91 } else { 92 mode_t new_umask; 93 94 if (digit(*cp)) { 95 for (new_umask = 0; *cp >= '0' && *cp <= '7'; cp++) 96 new_umask = new_umask * 8 + (*cp - '0'); 97 if (*cp) { 98 bi_errorf("bad number"); 99 return 1; 100 } 101 } else { 102 /* symbolic format */ 103 int positions, new_val; 104 char op; 105 106 old_umask = umask(0); 107 umask(old_umask); /* in case of error */ 108 old_umask = ~old_umask; 109 new_umask = old_umask; 110 positions = 0; 111 while (*cp) { 112 while (*cp && strchr("augo", *cp)) 113 switch (*cp++) { 114 case 'a': 115 positions |= 0111; 116 break; 117 case 'u': 118 positions |= 0100; 119 break; 120 case 'g': 121 positions |= 0010; 122 break; 123 case 'o': 124 positions |= 0001; 125 break; 126 } 127 if (!positions) 128 positions = 0111; /* default is a */ 129 if (!strchr("=+-", op = *cp)) 130 break; 131 cp++; 132 new_val = 0; 133 while (*cp && strchr("rwxugoXs", *cp)) 134 switch (*cp++) { 135 case 'r': new_val |= 04; break; 136 case 'w': new_val |= 02; break; 137 case 'x': new_val |= 01; break; 138 case 'u': new_val |= old_umask >> 6; 139 break; 140 case 'g': new_val |= old_umask >> 3; 141 break; 142 case 'o': new_val |= old_umask >> 0; 143 break; 144 case 'X': if (old_umask & 0111) 145 new_val |= 01; 146 break; 147 case 's': /* ignored */ 148 break; 149 } 150 new_val = (new_val & 07) * positions; 151 switch (op) { 152 case '-': 153 new_umask &= ~new_val; 154 break; 155 case '=': 156 new_umask = new_val | 157 (new_umask & ~(positions * 07)); 158 break; 159 case '+': 160 new_umask |= new_val; 161 } 162 if (*cp == ',') { 163 positions = 0; 164 cp++; 165 } else if (!strchr("=+-", *cp)) 166 break; 167 } 168 if (*cp) { 169 bi_errorf("bad mask"); 170 return 1; 171 } 172 new_umask = ~new_umask; 173 } 174 umask(new_umask); 175 } 176 return 0; 177 } 178 179 int 180 c_dot(char **wp) 181 { 182 char *file, *cp; 183 char **argv; 184 int argc; 185 int i; 186 int err; 187 188 if (ksh_getopt(wp, &builtin_opt, null) == '?') 189 return 1; 190 191 if ((cp = wp[builtin_opt.optind]) == NULL) 192 return 0; 193 file = search(cp, path, R_OK, &err); 194 if (file == NULL) { 195 bi_errorf("%s: %s", cp, err ? strerror(err) : "not found"); 196 return 1; 197 } 198 199 /* Set positional parameters? */ 200 if (wp[builtin_opt.optind + 1]) { 201 argv = wp + builtin_opt.optind; 202 argv[0] = e->loc->argv[0]; /* preserve $0 */ 203 for (argc = 0; argv[argc + 1]; argc++) 204 ; 205 } else { 206 argc = 0; 207 argv = (char **) 0; 208 } 209 i = include(file, argc, argv, 0); 210 if (i < 0) { /* should not happen */ 211 bi_errorf("%s: %s", cp, strerror(errno)); 212 return 1; 213 } 214 return i; 215 } 216 217 int 218 c_wait(char **wp) 219 { 220 int rv = 0; 221 int sig; 222 223 if (ksh_getopt(wp, &builtin_opt, null) == '?') 224 return 1; 225 wp += builtin_opt.optind; 226 if (*wp == (char *) 0) { 227 while (waitfor((char *) 0, &sig) >= 0) 228 ; 229 rv = sig; 230 } else { 231 for (; *wp; wp++) 232 rv = waitfor(*wp, &sig); 233 if (rv < 0) 234 rv = sig ? sig : 127; /* magic exit code: bad job-id */ 235 } 236 return rv; 237 } 238 239 int 240 c_read(char **wp) 241 { 242 int c = 0; 243 int expand = 1, history = 0; 244 int expanding; 245 int ecode = 0; 246 char *cp; 247 int fd = 0; 248 struct shf *shf; 249 int optc; 250 const char *emsg; 251 XString cs, xs; 252 struct tbl *vp; 253 char *xp = NULL; 254 255 while ((optc = ksh_getopt(wp, &builtin_opt, "prsu,")) != -1) 256 switch (optc) { 257 case 'p': 258 if ((fd = coproc_getfd(R_OK, &emsg)) < 0) { 259 bi_errorf("-p: %s", emsg); 260 return 1; 261 } 262 break; 263 case 'r': 264 expand = 0; 265 break; 266 case 's': 267 history = 1; 268 break; 269 case 'u': 270 if (!*(cp = builtin_opt.optarg)) 271 fd = 0; 272 else if ((fd = check_fd(cp, R_OK, &emsg)) < 0) { 273 bi_errorf("-u: %s: %s", cp, emsg); 274 return 1; 275 } 276 break; 277 case '?': 278 return 1; 279 } 280 wp += builtin_opt.optind; 281 282 if (*wp == NULL) 283 *--wp = "REPLY"; 284 285 /* Since we can't necessarily seek backwards on non-regular files, 286 * don't buffer them so we can't read too much. 287 */ 288 shf = shf_reopen(fd, SHF_RD | SHF_INTERRUPT | can_seek(fd), shl_spare); 289 290 if ((cp = strchr(*wp, '?')) != NULL) { 291 *cp = 0; 292 if (isatty(fd)) { 293 /* at&t ksh says it prints prompt on fd if it's open 294 * for writing and is a tty, but it doesn't do it 295 * (it also doesn't check the interactive flag, 296 * as is indicated in the Kornshell book). 297 */ 298 shellf("%s", cp+1); 299 } 300 } 301 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 compatible with at&t ksh... the fd is kept so another 307 * coproc can be started with same output, 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 313 if (history) 314 Xinit(xs, xp, 128, ATEMP); 315 expanding = 0; 316 Xinit(cs, cp, 128, ATEMP); 317 for (; *wp != NULL; wp++) { 318 for (cp = Xstring(cs, cp); ; ) { 319 if (c == '\n' || c == EOF) 320 break; 321 while (1) { 322 c = shf_getc(shf); 323 if (c == '\0') 324 continue; 325 if (c == EOF && shf_error(shf) && 326 shf_errno(shf) == EINTR) { 327 /* Was the offending signal one that 328 * would normally kill a process? 329 * If so, pretend the read was killed. 330 */ 331 ecode = fatal_trap_check(); 332 333 /* non fatal (eg, CHLD), carry on */ 334 if (!ecode) { 335 shf_clearerr(shf); 336 continue; 337 } 338 } 339 break; 340 } 341 if (history) { 342 Xcheck(xs, xp); 343 Xput(xs, xp, c); 344 } 345 Xcheck(cs, cp); 346 if (expanding) { 347 expanding = 0; 348 if (c == '\n') { 349 c = 0; 350 if (Flag(FTALKING_I) && isatty(fd)) { 351 /* set prompt in case this is 352 * called from .profile or $ENV 353 */ 354 set_prompt(PS2, (Source *) 0); 355 pprompt(prompt, 0); 356 } 357 } else if (c != EOF) 358 Xput(cs, cp, c); 359 continue; 360 } 361 if (expand && c == '\\') { 362 expanding = 1; 363 continue; 364 } 365 if (c == '\n' || c == EOF) 366 break; 367 if (ctype(c, C_IFS)) { 368 if (Xlength(cs, cp) == 0 && ctype(c, C_IFSWS)) 369 continue; 370 if (wp[1]) 371 break; 372 } 373 Xput(cs, cp, c); 374 } 375 /* strip trailing IFS white space from last variable */ 376 if (!wp[1]) 377 while (Xlength(cs, cp) && ctype(cp[-1], C_IFS) && 378 ctype(cp[-1], C_IFSWS)) 379 cp--; 380 Xput(cs, cp, '\0'); 381 vp = global(*wp); 382 /* Must be done before setting export. */ 383 if (vp->flag & RDONLY) { 384 shf_flush(shf); 385 bi_errorf("%s is read only", *wp); 386 return 1; 387 } 388 if (Flag(FEXPORT)) 389 typeset(*wp, EXPORT, 0, 0, 0); 390 if (!setstr(vp, Xstring(cs, cp), KSH_RETURN_ERROR)) { 391 shf_flush(shf); 392 return 1; 393 } 394 } 395 396 shf_flush(shf); 397 if (history) { 398 Xput(xs, xp, '\0'); 399 source->line++; 400 histsave(source->line, Xstring(xs, xp), 1); 401 Xfree(xs, xp); 402 } 403 /* if this is the co-process fd, close the file descriptor 404 * (can get eof if and only if all processes are have died, ie, 405 * coproc.njobs is 0 and the pipe is closed). 406 */ 407 if (c == EOF && !ecode) 408 coproc_read_close(fd); 409 410 return ecode ? ecode : c == EOF; 411 } 412 413 int 414 c_eval(char **wp) 415 { 416 struct source *s; 417 int rv; 418 419 if (ksh_getopt(wp, &builtin_opt, null) == '?') 420 return 1; 421 s = pushs(SWORDS, ATEMP); 422 s->u.strv = wp + builtin_opt.optind; 423 if (!Flag(FPOSIX)) { 424 /* 425 * Handle case where the command is empty due to failed 426 * command substitution, eg, eval "$(false)". 427 * In this case, shell() will not set/change exstat (because 428 * compiled tree is empty), so will use this value. 429 * subst_exstat is cleared in execute(), so should be 0 if 430 * there were no substitutions. 431 * 432 * A strict reading of POSIX says we don't do this (though 433 * it is traditionally done). [from 1003.2-1992] 434 * 3.9.1: Simple Commands 435 * ... If there is a command name, execution shall 436 * continue as described in 3.9.1.1. If there 437 * is no command name, but the command contained a command 438 * substitution, the command shall complete with the exit 439 * status of the last command substitution 440 * 3.9.1.1: Command Search and Execution 441 * ...(1)...(a) If the command name matches the name of 442 * a special built-in utility, that special built-in 443 * utility shall be invoked. 444 * 3.14.5: Eval 445 * ... If there are no arguments, or only null arguments, 446 * eval shall return an exit status of zero. 447 */ 448 exstat = subst_exstat; 449 } 450 451 rv = shell(s, false); 452 afree(s, ATEMP); 453 return (rv); 454 } 455 456 int 457 c_trap(char **wp) 458 { 459 int i; 460 char *s; 461 Trap *p; 462 463 if (ksh_getopt(wp, &builtin_opt, null) == '?') 464 return 1; 465 wp += builtin_opt.optind; 466 467 if (*wp == NULL) { 468 int anydfl = 0; 469 470 for (p = sigtraps, i = NSIG+1; --i >= 0; p++) { 471 if (p->trap == NULL) 472 anydfl = 1; 473 else { 474 shprintf("trap -- "); 475 print_value_quoted(p->trap); 476 shprintf(" %s\n", p->name); 477 } 478 } 479 #if 0 /* this is ugly and not clear POSIX needs it */ 480 /* POSIX may need this so output of trap can be saved and 481 * used to restore trap conditions 482 */ 483 if (anydfl) { 484 shprintf("trap -- -"); 485 for (p = sigtraps, i = NSIG+1; --i >= 0; p++) 486 if (p->trap == NULL && p->name) 487 shprintf(" %s", p->name); 488 shprintf(newline); 489 } 490 #endif 491 return 0; 492 } 493 494 /* 495 * Use case sensitive lookup for first arg so the 496 * command 'exit' isn't confused with the pseudo-signal 497 * 'EXIT'. 498 */ 499 s = (gettrap(*wp, false) == NULL) ? *wp++ : NULL; /* get command */ 500 if (s != NULL && s[0] == '-' && s[1] == '\0') 501 s = NULL; 502 503 /* set/clear traps */ 504 while (*wp != NULL) { 505 p = gettrap(*wp++, true); 506 if (p == NULL) { 507 bi_errorf("bad signal %s", wp[-1]); 508 return 1; 509 } 510 settrap(p, s); 511 } 512 return 0; 513 } 514 515 int 516 c_exitreturn(char **wp) 517 { 518 int how = LEXIT; 519 int n; 520 char *arg; 521 522 if (ksh_getopt(wp, &builtin_opt, null) == '?') 523 return 1; 524 arg = wp[builtin_opt.optind]; 525 526 if (arg) { 527 if (!getn(arg, &n)) { 528 exstat = 1; 529 warningf(true, "%s: bad number", arg); 530 } else 531 exstat = n; 532 } 533 if (wp[0][0] == 'r') { /* return */ 534 struct env *ep; 535 536 /* need to tell if this is exit or return so trap exit will 537 * work right (POSIX) 538 */ 539 for (ep = e; ep; ep = ep->oenv) 540 if (STOP_RETURN(ep->type)) { 541 how = LRETURN; 542 break; 543 } 544 } 545 546 if (how == LEXIT && !really_exit && j_stopped_running()) { 547 really_exit = 1; 548 how = LSHELL; 549 } 550 551 quitenv(NULL); /* get rid of any i/o redirections */ 552 unwind(how); 553 /* NOTREACHED */ 554 return 0; 555 } 556 557 int 558 c_brkcont(char **wp) 559 { 560 int n, quit; 561 struct env *ep, *last_ep = (struct env *) 0; 562 char *arg; 563 564 if (ksh_getopt(wp, &builtin_opt, null) == '?') 565 return 1; 566 arg = wp[builtin_opt.optind]; 567 568 if (!arg) 569 n = 1; 570 else if (!bi_getn(arg, &n)) 571 return 1; 572 quit = n; 573 if (quit <= 0) { 574 /* at&t ksh does this for non-interactive shells only - weird */ 575 bi_errorf("%s: bad value", arg); 576 return 1; 577 } 578 579 /* Stop at E_NONE, E_PARSE, E_FUNC, or E_INCL */ 580 for (ep = e; ep && !STOP_BRKCONT(ep->type); ep = ep->oenv) 581 if (ep->type == E_LOOP) { 582 if (--quit == 0) 583 break; 584 ep->flags |= EF_BRKCONT_PASS; 585 last_ep = ep; 586 } 587 588 if (quit) { 589 /* at&t ksh doesn't print a message - just does what it 590 * can. We print a message 'cause it helps in debugging 591 * scripts, but don't generate an error (ie, keep going). 592 */ 593 if (n == quit) { 594 warningf(true, "%s: cannot %s", wp[0], wp[0]); 595 return 0; 596 } 597 /* POSIX says if n is too big, the last enclosing loop 598 * shall be used. Doesn't say to print an error but we 599 * do anyway 'cause the user messed up. 600 */ 601 if (last_ep) 602 last_ep->flags &= ~EF_BRKCONT_PASS; 603 warningf(true, "%s: can only %s %d level(s)", 604 wp[0], wp[0], n - quit); 605 } 606 607 unwind(*wp[0] == 'b' ? LBREAK : LCONTIN); 608 /* NOTREACHED */ 609 } 610 611 int 612 c_set(char **wp) 613 { 614 int argi, setargs; 615 struct block *l = e->loc; 616 char **owp = wp; 617 618 if (wp[1] == NULL) { 619 static const char *const args [] = { "set", "-", NULL }; 620 return c_typeset((char **) args); 621 } 622 623 argi = parse_args(wp, OF_SET, &setargs); 624 if (argi < 0) 625 return 1; 626 /* set $# and $* */ 627 if (setargs) { 628 owp = wp += argi - 1; 629 wp[0] = l->argv[0]; /* save $0 */ 630 while (*++wp != NULL) 631 *wp = str_save(*wp, &l->area); 632 l->argc = wp - owp - 1; 633 l->argv = (char **) alloc(sizeofN(char *, l->argc+2), &l->area); 634 for (wp = l->argv; (*wp++ = *owp++) != NULL; ) 635 ; 636 } 637 /* POSIX says set exit status is 0, but old scripts that use 638 * getopt(1), use the construct: set -- `getopt ab:c "$@"` 639 * which assumes the exit value set will be that of the `` 640 * (subst_exstat is cleared in execute() so that it will be 0 641 * if there are no command substitutions). 642 */ 643 return Flag(FPOSIX) ? 0 : subst_exstat; 644 } 645 646 int 647 c_unset(char **wp) 648 { 649 char *id; 650 int optc, unset_var = 1; 651 652 while ((optc = ksh_getopt(wp, &builtin_opt, "fv")) != -1) 653 switch (optc) { 654 case 'f': 655 unset_var = 0; 656 break; 657 case 'v': 658 unset_var = 1; 659 break; 660 case '?': 661 return 1; 662 } 663 wp += builtin_opt.optind; 664 for (; (id = *wp) != NULL; wp++) 665 if (unset_var) { /* unset variable */ 666 struct tbl *vp = global(id); 667 668 if ((vp->flag&RDONLY)) { 669 bi_errorf("%s is read only", vp->name); 670 return 1; 671 } 672 unset(vp, strchr(id, '[') ? 1 : 0); 673 } else { /* unset function */ 674 define(id, (struct op *) NULL); 675 } 676 return 0; 677 } 678 679 static void 680 p_time(struct shf *shf, int posix, struct timeval *tv, int width, char *prefix, 681 char *suffix) 682 { 683 if (posix) 684 shf_fprintf(shf, "%s%*ld.%02ld%s", prefix ? prefix : "", 685 width, tv->tv_sec, tv->tv_usec / 10000, suffix); 686 else 687 shf_fprintf(shf, "%s%*ldm%ld.%02lds%s", prefix ? prefix : "", 688 width, tv->tv_sec / 60, tv->tv_sec % 60, 689 tv->tv_usec / 10000, suffix); 690 } 691 692 int 693 c_times(char **wp) 694 { 695 struct rusage usage; 696 697 (void) getrusage(RUSAGE_SELF, &usage); 698 p_time(shl_stdout, 0, &usage.ru_utime, 0, NULL, " "); 699 p_time(shl_stdout, 0, &usage.ru_stime, 0, NULL, "\n"); 700 701 (void) getrusage(RUSAGE_CHILDREN, &usage); 702 p_time(shl_stdout, 0, &usage.ru_utime, 0, NULL, " "); 703 p_time(shl_stdout, 0, &usage.ru_stime, 0, NULL, "\n"); 704 705 return 0; 706 } 707 708 /* 709 * time pipeline (really a statement, not a built-in command) 710 */ 711 int 712 timex(struct op *t, int f, volatile int *xerrok) 713 { 714 #define TF_NOARGS BIT(0) 715 #define TF_NOREAL BIT(1) /* don't report real time */ 716 #define TF_POSIX BIT(2) /* report in posix format */ 717 int rv = 0; 718 struct rusage ru0, ru1, cru0, cru1; 719 struct timeval usrtime, systime, tv0, tv1; 720 int tf = 0; 721 extern struct timeval j_usrtime, j_systime; /* computed by j_wait */ 722 723 gettimeofday(&tv0, NULL); 724 getrusage(RUSAGE_SELF, &ru0); 725 getrusage(RUSAGE_CHILDREN, &cru0); 726 if (t->left) { 727 /* 728 * Two ways of getting cpu usage of a command: just use t0 729 * and t1 (which will get cpu usage from other jobs that 730 * finish while we are executing t->left), or get the 731 * cpu usage of t->left. at&t ksh does the former, while 732 * pdksh tries to do the later (the j_usrtime hack doesn't 733 * really work as it only counts the last job). 734 */ 735 timerclear(&j_usrtime); 736 timerclear(&j_systime); 737 rv = execute(t->left, f | XTIME, xerrok); 738 if (t->left->type == TCOM) 739 tf |= t->left->str[0]; 740 gettimeofday(&tv1, NULL); 741 getrusage(RUSAGE_SELF, &ru1); 742 getrusage(RUSAGE_CHILDREN, &cru1); 743 } else 744 tf = TF_NOARGS; 745 746 if (tf & TF_NOARGS) { /* ksh93 - report shell times (shell+kids) */ 747 tf |= TF_NOREAL; 748 timeradd(&ru0.ru_utime, &cru0.ru_utime, &usrtime); 749 timeradd(&ru0.ru_stime, &cru0.ru_stime, &systime); 750 } else { 751 timersub(&ru1.ru_utime, &ru0.ru_utime, &usrtime); 752 timeradd(&usrtime, &j_usrtime, &usrtime); 753 timersub(&ru1.ru_stime, &ru0.ru_stime, &systime); 754 timeradd(&systime, &j_systime, &systime); 755 } 756 757 if (!(tf & TF_NOREAL)) { 758 timersub(&tv1, &tv0, &tv1); 759 if (tf & TF_POSIX) 760 p_time(shl_out, 1, &tv1, 5, "real ", "\n"); 761 else 762 p_time(shl_out, 0, &tv1, 5, NULL, " real "); 763 } 764 if (tf & TF_POSIX) 765 p_time(shl_out, 1, &usrtime, 5, "user ", "\n"); 766 else 767 p_time(shl_out, 0, &usrtime, 5, NULL, " user "); 768 if (tf & TF_POSIX) 769 p_time(shl_out, 1, &systime, 5, "sys ", "\n"); 770 else 771 p_time(shl_out, 0, &systime, 5, NULL, " system\n"); 772 shf_flush(shl_out); 773 774 return rv; 775 } 776 777 void 778 timex_hook(struct op *t, char **volatile *app) 779 { 780 char **wp = *app; 781 int optc; 782 int i, j; 783 Getopt opt; 784 785 ksh_getopt_reset(&opt, 0); 786 opt.optind = 0; /* start at the start */ 787 while ((optc = ksh_getopt(wp, &opt, ":p")) != -1) 788 switch (optc) { 789 case 'p': 790 t->str[0] |= TF_POSIX; 791 break; 792 case '?': 793 errorf("time: -%s unknown option", opt.optarg); 794 case ':': 795 errorf("time: -%s requires an argument", 796 opt.optarg); 797 } 798 /* Copy command words down over options. */ 799 if (opt.optind != 0) { 800 for (i = 0; i < opt.optind; i++) 801 afree(wp[i], ATEMP); 802 for (i = 0, j = opt.optind; (wp[i] = wp[j]); i++, j++) 803 ; 804 } 805 if (!wp[0]) 806 t->str[0] |= TF_NOARGS; 807 *app = wp; 808 } 809 810 /* exec with no args - args case is taken care of in comexec() */ 811 int 812 c_exec(char **wp) 813 { 814 int i; 815 816 /* make sure redirects stay in place */ 817 if (e->savefd != NULL) { 818 for (i = 0; i < NUFILE; i++) { 819 if (e->savefd[i] > 0) 820 close(e->savefd[i]); 821 /* 822 * For ksh keep anything > 2 private, 823 * for sh, let them be (POSIX says what 824 * happens is unspecified and the bourne shell 825 * keeps them open). 826 */ 827 if (!Flag(FSH) && i > 2 && e->savefd[i]) 828 fcntl(i, F_SETFD, FD_CLOEXEC); 829 } 830 e->savefd = NULL; 831 } 832 return 0; 833 } 834 835 static int 836 c_mknod(char **wp) 837 { 838 int argc, optc, ismkfifo = 0, ret; 839 char **argv; 840 void *set = NULL; 841 mode_t mode = 0, oldmode = 0; 842 843 while ((optc = ksh_getopt(wp, &builtin_opt, "m:")) != -1) { 844 switch (optc) { 845 case 'm': 846 set = setmode(builtin_opt.optarg); 847 if (set == NULL) { 848 bi_errorf("invalid file mode"); 849 return 1; 850 } 851 mode = getmode(set, DEFFILEMODE); 852 free(set); 853 break; 854 default: 855 goto usage; 856 } 857 } 858 argv = &wp[builtin_opt.optind]; 859 if (argv[0] == NULL) 860 goto usage; 861 for (argc = 0; argv[argc]; argc++) 862 ; 863 if (argc == 2 && argv[1][0] == 'p') { 864 ismkfifo = 1; 865 argc--; 866 } else if (argc != 4) 867 goto usage; 868 869 if (set) 870 oldmode = umask(0); 871 else 872 mode = DEFFILEMODE; 873 874 if (ismkfifo) 875 ret = domkfifo(argc, argv, mode); 876 else 877 ret = domknod(argc, argv, mode); 878 879 if (set) 880 umask(oldmode); 881 return ret; 882 usage: 883 builtin_argv0 = NULL; 884 bi_errorf("usage: mknod [-m mode] name [b | c] major minor"); 885 bi_errorf("usage: mknod [-m mode] name p"); 886 return 1; 887 } 888 889 /* dummy function, special case in comexec() */ 890 int 891 c_builtin(char **wp) 892 { 893 return 0; 894 } 895 896 extern int c_test(char **wp); /* in c_test.c */ 897 extern int c_ulimit(char **wp); /* in c_ulimit.c */ 898 899 /* A leading = means assignments before command are kept; 900 * a leading * means a POSIX special builtin; 901 * a leading + means a POSIX regular builtin 902 * (* and + should not be combined). 903 */ 904 const struct builtin shbuiltins [] = { 905 {"*=.", c_dot}, 906 {"*=:", c_label}, 907 {"[", c_test}, 908 {"*=break", c_brkcont}, 909 {"=builtin", c_builtin}, 910 {"*=continue", c_brkcont}, 911 {"*=eval", c_eval}, 912 {"*=exec", c_exec}, 913 {"*=exit", c_exitreturn}, 914 {"+false", c_label}, 915 {"*=return", c_exitreturn}, 916 {"*=set", c_set}, 917 {"*=shift", c_shift}, 918 {"=times", c_times}, 919 {"*=trap", c_trap}, 920 {"+=wait", c_wait}, 921 {"+read", c_read}, 922 {"test", c_test}, 923 {"+true", c_label}, 924 {"ulimit", c_ulimit}, 925 {"+umask", c_umask}, 926 {"*=unset", c_unset}, 927 {"mknod", c_mknod}, 928 {NULL, NULL} 929 }; 930