diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-02-23 01:04:50 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-02-23 01:04:50 +0000 |
| commit | fe1f00a7a7fe19e330ad9c610e21823b93bed8ed (patch) | |
| tree | b115c56533abb69ddac5f790835322a705678ede /shell | |
| parent | 9650f3621033542bd2ad4aac88fdc2f90890feca (diff) | |
| download | busybox-w32-fe1f00a7a7fe19e330ad9c610e21823b93bed8ed.tar.gz busybox-w32-fe1f00a7a7fe19e330ad9c610e21823b93bed8ed.tar.bz2 busybox-w32-fe1f00a7a7fe19e330ad9c610e21823b93bed8ed.zip | |
ash: cleanup part 4
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/ash.c | 1244 |
1 files changed, 597 insertions, 647 deletions
diff --git a/shell/ash.c b/shell/ash.c index 3107181a6..7ffecf43d 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -65,36 +65,6 @@ | |||
| 65 | #error "Do not even bother, ash will not run on uClinux" | 65 | #error "Do not even bother, ash will not run on uClinux" |
| 66 | #endif | 66 | #endif |
| 67 | 67 | ||
| 68 | #if DEBUG | ||
| 69 | #define TRACE(param) trace param | ||
| 70 | #define TRACEV(param) tracev param | ||
| 71 | #else | ||
| 72 | #define TRACE(param) | ||
| 73 | #define TRACEV(param) | ||
| 74 | #endif | ||
| 75 | |||
| 76 | #ifdef __GLIBC__ | ||
| 77 | /* glibc sucks */ | ||
| 78 | static int *dash_errno; | ||
| 79 | #undef errno | ||
| 80 | #define errno (*dash_errno) | ||
| 81 | #endif | ||
| 82 | |||
| 83 | |||
| 84 | #if ENABLE_ASH_ALIAS | ||
| 85 | #define ALIASINUSE 1 | ||
| 86 | #define ALIASDEAD 2 | ||
| 87 | struct alias { | ||
| 88 | struct alias *next; | ||
| 89 | char *name; | ||
| 90 | char *val; | ||
| 91 | int flag; | ||
| 92 | }; | ||
| 93 | static int aliascmd(int, char **); | ||
| 94 | static int unaliascmd(int, char **); | ||
| 95 | static void printalias(const struct alias *); | ||
| 96 | #endif | ||
| 97 | |||
| 98 | 68 | ||
| 99 | /* ============ Shell options */ | 69 | /* ============ Shell options */ |
| 100 | 70 | ||
| @@ -148,6 +118,13 @@ static char optlist[NOPTS]; | |||
| 148 | 118 | ||
| 149 | /* ============ Misc data */ | 119 | /* ============ Misc data */ |
| 150 | 120 | ||
| 121 | #ifdef __GLIBC__ | ||
| 122 | /* glibc sucks */ | ||
| 123 | static int *dash_errno; | ||
| 124 | #undef errno | ||
| 125 | #define errno (*dash_errno) | ||
| 126 | #endif | ||
| 127 | |||
| 151 | static char nullstr[1]; /* zero length string */ | 128 | static char nullstr[1]; /* zero length string */ |
| 152 | static const char homestr[] = "HOME"; | 129 | static const char homestr[] = "HOME"; |
| 153 | static const char snlfmt[] = "%s\n"; | 130 | static const char snlfmt[] = "%s\n"; |
| @@ -256,14 +233,16 @@ raise_interrupt(void) | |||
| 256 | } | 233 | } |
| 257 | 234 | ||
| 258 | #if ENABLE_ASH_OPTIMIZE_FOR_SIZE | 235 | #if ENABLE_ASH_OPTIMIZE_FOR_SIZE |
| 259 | static void int_on(void) | 236 | static void |
| 237 | int_on(void) | ||
| 260 | { | 238 | { |
| 261 | if (--suppressint == 0 && intpending) { | 239 | if (--suppressint == 0 && intpending) { |
| 262 | raise_interrupt(); | 240 | raise_interrupt(); |
| 263 | } | 241 | } |
| 264 | } | 242 | } |
| 265 | #define INT_ON int_on() | 243 | #define INT_ON int_on() |
| 266 | static void force_int_on(void) | 244 | static void |
| 245 | force_int_on(void) | ||
| 267 | { | 246 | { |
| 268 | suppressint = 0; | 247 | suppressint = 0; |
| 269 | if (intpending) | 248 | if (intpending) |
| @@ -387,6 +366,485 @@ out2str(const char *p) | |||
| 387 | } | 366 | } |
| 388 | 367 | ||
| 389 | 368 | ||
| 369 | /* ============ Parsing structures */ | ||
| 370 | #define NCMD 0 | ||
| 371 | #define NPIPE 1 | ||
| 372 | #define NREDIR 2 | ||
| 373 | #define NBACKGND 3 | ||
| 374 | #define NSUBSHELL 4 | ||
| 375 | #define NAND 5 | ||
| 376 | #define NOR 6 | ||
| 377 | #define NSEMI 7 | ||
| 378 | #define NIF 8 | ||
| 379 | #define NWHILE 9 | ||
| 380 | #define NUNTIL 10 | ||
| 381 | #define NFOR 11 | ||
| 382 | #define NCASE 12 | ||
| 383 | #define NCLIST 13 | ||
| 384 | #define NDEFUN 14 | ||
| 385 | #define NARG 15 | ||
| 386 | #define NTO 16 | ||
| 387 | #define NCLOBBER 17 | ||
| 388 | #define NFROM 18 | ||
| 389 | #define NFROMTO 19 | ||
| 390 | #define NAPPEND 20 | ||
| 391 | #define NTOFD 21 | ||
| 392 | #define NFROMFD 22 | ||
| 393 | #define NHERE 23 | ||
| 394 | #define NXHERE 24 | ||
| 395 | #define NNOT 25 | ||
| 396 | |||
| 397 | union node; | ||
| 398 | |||
| 399 | struct ncmd { | ||
| 400 | int type; | ||
| 401 | union node *assign; | ||
| 402 | union node *args; | ||
| 403 | union node *redirect; | ||
| 404 | }; | ||
| 405 | |||
| 406 | struct npipe { | ||
| 407 | int type; | ||
| 408 | int backgnd; | ||
| 409 | struct nodelist *cmdlist; | ||
| 410 | }; | ||
| 411 | |||
| 412 | struct nredir { | ||
| 413 | int type; | ||
| 414 | union node *n; | ||
| 415 | union node *redirect; | ||
| 416 | }; | ||
| 417 | |||
| 418 | struct nbinary { | ||
| 419 | int type; | ||
| 420 | union node *ch1; | ||
| 421 | union node *ch2; | ||
| 422 | }; | ||
| 423 | |||
| 424 | struct nif { | ||
| 425 | int type; | ||
| 426 | union node *test; | ||
| 427 | union node *ifpart; | ||
| 428 | union node *elsepart; | ||
| 429 | }; | ||
| 430 | |||
| 431 | struct nfor { | ||
| 432 | int type; | ||
| 433 | union node *args; | ||
| 434 | union node *body; | ||
| 435 | char *var; | ||
| 436 | }; | ||
| 437 | |||
| 438 | struct ncase { | ||
| 439 | int type; | ||
| 440 | union node *expr; | ||
| 441 | union node *cases; | ||
| 442 | }; | ||
| 443 | |||
| 444 | struct nclist { | ||
| 445 | int type; | ||
| 446 | union node *next; | ||
| 447 | union node *pattern; | ||
| 448 | union node *body; | ||
| 449 | }; | ||
| 450 | |||
| 451 | struct narg { | ||
| 452 | int type; | ||
| 453 | union node *next; | ||
| 454 | char *text; | ||
| 455 | struct nodelist *backquote; | ||
| 456 | }; | ||
| 457 | |||
| 458 | struct nfile { | ||
| 459 | int type; | ||
| 460 | union node *next; | ||
| 461 | int fd; | ||
| 462 | union node *fname; | ||
| 463 | char *expfname; | ||
| 464 | }; | ||
| 465 | |||
| 466 | struct ndup { | ||
| 467 | int type; | ||
| 468 | union node *next; | ||
| 469 | int fd; | ||
| 470 | int dupfd; | ||
| 471 | union node *vname; | ||
| 472 | }; | ||
| 473 | |||
| 474 | struct nhere { | ||
| 475 | int type; | ||
| 476 | union node *next; | ||
| 477 | int fd; | ||
| 478 | union node *doc; | ||
| 479 | }; | ||
| 480 | |||
| 481 | struct nnot { | ||
| 482 | int type; | ||
| 483 | union node *com; | ||
| 484 | }; | ||
| 485 | |||
| 486 | union node { | ||
| 487 | int type; | ||
| 488 | struct ncmd ncmd; | ||
| 489 | struct npipe npipe; | ||
| 490 | struct nredir nredir; | ||
| 491 | struct nbinary nbinary; | ||
| 492 | struct nif nif; | ||
| 493 | struct nfor nfor; | ||
| 494 | struct ncase ncase; | ||
| 495 | struct nclist nclist; | ||
| 496 | struct narg narg; | ||
| 497 | struct nfile nfile; | ||
| 498 | struct ndup ndup; | ||
| 499 | struct nhere nhere; | ||
| 500 | struct nnot nnot; | ||
| 501 | }; | ||
| 502 | |||
| 503 | struct nodelist { | ||
| 504 | struct nodelist *next; | ||
| 505 | union node *n; | ||
| 506 | }; | ||
| 507 | |||
| 508 | struct funcnode { | ||
| 509 | int count; | ||
| 510 | union node n; | ||
| 511 | }; | ||
| 512 | |||
| 513 | |||
| 514 | /* ============ Debugging output */ | ||
| 515 | |||
| 516 | #if DEBUG | ||
| 517 | |||
| 518 | static FILE *tracefile; | ||
| 519 | |||
| 520 | static void | ||
| 521 | trace_printf(const char *fmt, ...) | ||
| 522 | { | ||
| 523 | va_list va; | ||
| 524 | |||
| 525 | if (debug != 1) | ||
| 526 | return; | ||
| 527 | va_start(va, fmt); | ||
| 528 | vfprintf(tracefile, fmt, va); | ||
| 529 | va_end(va); | ||
| 530 | } | ||
| 531 | |||
| 532 | static void | ||
| 533 | trace_vprintf(const char *fmt, va_list va) | ||
| 534 | { | ||
| 535 | if (debug != 1) | ||
| 536 | return; | ||
| 537 | vfprintf(tracefile, fmt, va); | ||
| 538 | } | ||
| 539 | |||
| 540 | static void | ||
| 541 | trace_puts(const char *s) | ||
| 542 | { | ||
| 543 | if (debug != 1) | ||
| 544 | return; | ||
| 545 | fputs(s, tracefile); | ||
| 546 | } | ||
| 547 | |||
| 548 | static void | ||
| 549 | trace_puts_quoted(char *s) | ||
| 550 | { | ||
| 551 | char *p; | ||
| 552 | char c; | ||
| 553 | |||
| 554 | if (debug != 1) | ||
| 555 | return; | ||
| 556 | putc('"', tracefile); | ||
| 557 | for (p = s; *p; p++) { | ||
| 558 | switch (*p) { | ||
| 559 | case '\n': c = 'n'; goto backslash; | ||
| 560 | case '\t': c = 't'; goto backslash; | ||
| 561 | case '\r': c = 'r'; goto backslash; | ||
| 562 | case '"': c = '"'; goto backslash; | ||
| 563 | case '\\': c = '\\'; goto backslash; | ||
| 564 | case CTLESC: c = 'e'; goto backslash; | ||
| 565 | case CTLVAR: c = 'v'; goto backslash; | ||
| 566 | case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; | ||
| 567 | case CTLBACKQ: c = 'q'; goto backslash; | ||
| 568 | case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; | ||
| 569 | backslash: | ||
| 570 | putc('\\', tracefile); | ||
| 571 | putc(c, tracefile); | ||
| 572 | break; | ||
| 573 | default: | ||
| 574 | if (*p >= ' ' && *p <= '~') | ||
| 575 | putc(*p, tracefile); | ||
| 576 | else { | ||
| 577 | putc('\\', tracefile); | ||
| 578 | putc(*p >> 6 & 03, tracefile); | ||
| 579 | putc(*p >> 3 & 07, tracefile); | ||
| 580 | putc(*p & 07, tracefile); | ||
| 581 | } | ||
| 582 | break; | ||
| 583 | } | ||
| 584 | } | ||
| 585 | putc('"', tracefile); | ||
| 586 | } | ||
| 587 | |||
| 588 | static void | ||
| 589 | trace_puts_args(char **ap) | ||
| 590 | { | ||
| 591 | if (debug != 1) | ||
| 592 | return; | ||
| 593 | if (!*ap) | ||
| 594 | return; | ||
| 595 | while (1) { | ||
| 596 | trace_puts_quoted(*ap); | ||
| 597 | if (!*++ap) { | ||
| 598 | putc('\n', tracefile); | ||
| 599 | break; | ||
| 600 | } | ||
| 601 | putc(' ', tracefile); | ||
| 602 | } | ||
| 603 | } | ||
| 604 | |||
| 605 | static void | ||
| 606 | opentrace(void) | ||
| 607 | { | ||
| 608 | char s[100]; | ||
| 609 | #ifdef O_APPEND | ||
| 610 | int flags; | ||
| 611 | #endif | ||
| 612 | |||
| 613 | if (debug != 1) { | ||
| 614 | if (tracefile) | ||
| 615 | fflush(tracefile); | ||
| 616 | /* leave open because libedit might be using it */ | ||
| 617 | return; | ||
| 618 | } | ||
| 619 | strcpy(s, "./trace"); | ||
| 620 | if (tracefile) { | ||
| 621 | if (!freopen(s, "a", tracefile)) { | ||
| 622 | fprintf(stderr, "Can't re-open %s\n", s); | ||
| 623 | debug = 0; | ||
| 624 | return; | ||
| 625 | } | ||
| 626 | } else { | ||
| 627 | tracefile = fopen(s, "a"); | ||
| 628 | if (tracefile == NULL) { | ||
| 629 | fprintf(stderr, "Can't open %s\n", s); | ||
| 630 | debug = 0; | ||
| 631 | return; | ||
| 632 | } | ||
| 633 | } | ||
| 634 | #ifdef O_APPEND | ||
| 635 | flags = fcntl(fileno(tracefile), F_GETFL, 0); | ||
| 636 | if (flags >= 0) | ||
| 637 | fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); | ||
| 638 | #endif | ||
| 639 | setlinebuf(tracefile); | ||
| 640 | fputs("\nTracing started.\n", tracefile); | ||
| 641 | } | ||
| 642 | |||
| 643 | static void | ||
| 644 | indent(int amount, char *pfx, FILE *fp) | ||
| 645 | { | ||
| 646 | int i; | ||
| 647 | |||
| 648 | for (i = 0; i < amount; i++) { | ||
| 649 | if (pfx && i == amount - 1) | ||
| 650 | fputs(pfx, fp); | ||
| 651 | putc('\t', fp); | ||
| 652 | } | ||
| 653 | } | ||
| 654 | |||
| 655 | /* little circular references here... */ | ||
| 656 | static void shtree(union node *n, int ind, char *pfx, FILE *fp); | ||
| 657 | |||
| 658 | static void | ||
| 659 | sharg(union node *arg, FILE *fp) | ||
| 660 | { | ||
| 661 | char *p; | ||
| 662 | struct nodelist *bqlist; | ||
| 663 | int subtype; | ||
| 664 | |||
| 665 | if (arg->type != NARG) { | ||
| 666 | out1fmt("<node type %d>\n", arg->type); | ||
| 667 | abort(); | ||
| 668 | } | ||
| 669 | bqlist = arg->narg.backquote; | ||
| 670 | for (p = arg->narg.text; *p; p++) { | ||
| 671 | switch (*p) { | ||
| 672 | case CTLESC: | ||
| 673 | putc(*++p, fp); | ||
| 674 | break; | ||
| 675 | case CTLVAR: | ||
| 676 | putc('$', fp); | ||
| 677 | putc('{', fp); | ||
| 678 | subtype = *++p; | ||
| 679 | if (subtype == VSLENGTH) | ||
| 680 | putc('#', fp); | ||
| 681 | |||
| 682 | while (*p != '=') | ||
| 683 | putc(*p++, fp); | ||
| 684 | |||
| 685 | if (subtype & VSNUL) | ||
| 686 | putc(':', fp); | ||
| 687 | |||
| 688 | switch (subtype & VSTYPE) { | ||
| 689 | case VSNORMAL: | ||
| 690 | putc('}', fp); | ||
| 691 | break; | ||
| 692 | case VSMINUS: | ||
| 693 | putc('-', fp); | ||
| 694 | break; | ||
| 695 | case VSPLUS: | ||
| 696 | putc('+', fp); | ||
| 697 | break; | ||
| 698 | case VSQUESTION: | ||
| 699 | putc('?', fp); | ||
| 700 | break; | ||
| 701 | case VSASSIGN: | ||
| 702 | putc('=', fp); | ||
| 703 | break; | ||
| 704 | case VSTRIMLEFT: | ||
| 705 | putc('#', fp); | ||
| 706 | break; | ||
| 707 | case VSTRIMLEFTMAX: | ||
| 708 | putc('#', fp); | ||
| 709 | putc('#', fp); | ||
| 710 | break; | ||
| 711 | case VSTRIMRIGHT: | ||
| 712 | putc('%', fp); | ||
| 713 | break; | ||
| 714 | case VSTRIMRIGHTMAX: | ||
| 715 | putc('%', fp); | ||
| 716 | putc('%', fp); | ||
| 717 | break; | ||
| 718 | case VSLENGTH: | ||
| 719 | break; | ||
| 720 | default: | ||
| 721 | out1fmt("<subtype %d>", subtype); | ||
| 722 | } | ||
| 723 | break; | ||
| 724 | case CTLENDVAR: | ||
| 725 | putc('}', fp); | ||
| 726 | break; | ||
| 727 | case CTLBACKQ: | ||
| 728 | case CTLBACKQ|CTLQUOTE: | ||
| 729 | putc('$', fp); | ||
| 730 | putc('(', fp); | ||
| 731 | shtree(bqlist->n, -1, NULL, fp); | ||
| 732 | putc(')', fp); | ||
| 733 | break; | ||
| 734 | default: | ||
| 735 | putc(*p, fp); | ||
| 736 | break; | ||
| 737 | } | ||
| 738 | } | ||
| 739 | } | ||
| 740 | |||
| 741 | static void | ||
| 742 | shcmd(union node *cmd, FILE *fp) | ||
| 743 | { | ||
| 744 | union node *np; | ||
| 745 | int first; | ||
| 746 | const char *s; | ||
| 747 | int dftfd; | ||
| 748 | |||
| 749 | first = 1; | ||
| 750 | for (np = cmd->ncmd.args; np; np = np->narg.next) { | ||
| 751 | if (! first) | ||
| 752 | putchar(' '); | ||
| 753 | sharg(np, fp); | ||
| 754 | first = 0; | ||
| 755 | } | ||
| 756 | for (np = cmd->ncmd.redirect; np; np = np->nfile.next) { | ||
| 757 | if (! first) | ||
| 758 | putchar(' '); | ||
| 759 | switch (np->nfile.type) { | ||
| 760 | case NTO: s = ">"; dftfd = 1; break; | ||
| 761 | case NCLOBBER: s = ">|"; dftfd = 1; break; | ||
| 762 | case NAPPEND: s = ">>"; dftfd = 1; break; | ||
| 763 | case NTOFD: s = ">&"; dftfd = 1; break; | ||
| 764 | case NFROM: s = "<"; dftfd = 0; break; | ||
| 765 | case NFROMFD: s = "<&"; dftfd = 0; break; | ||
| 766 | case NFROMTO: s = "<>"; dftfd = 0; break; | ||
| 767 | default: s = "*error*"; dftfd = 0; break; | ||
| 768 | } | ||
| 769 | if (np->nfile.fd != dftfd) | ||
| 770 | fprintf(fp, "%d", np->nfile.fd); | ||
| 771 | fputs(s, fp); | ||
| 772 | if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { | ||
| 773 | fprintf(fp, "%d", np->ndup.dupfd); | ||
| 774 | } else { | ||
| 775 | sharg(np->nfile.fname, fp); | ||
| 776 | } | ||
| 777 | first = 0; | ||
| 778 | } | ||
| 779 | } | ||
| 780 | |||
| 781 | static void | ||
| 782 | shtree(union node *n, int ind, char *pfx, FILE *fp) | ||
| 783 | { | ||
| 784 | struct nodelist *lp; | ||
| 785 | const char *s; | ||
| 786 | |||
| 787 | if (n == NULL) | ||
| 788 | return; | ||
| 789 | |||
| 790 | indent(ind, pfx, fp); | ||
| 791 | switch (n->type) { | ||
| 792 | case NSEMI: | ||
| 793 | s = "; "; | ||
| 794 | goto binop; | ||
| 795 | case NAND: | ||
| 796 | s = " && "; | ||
| 797 | goto binop; | ||
| 798 | case NOR: | ||
| 799 | s = " || "; | ||
| 800 | binop: | ||
| 801 | shtree(n->nbinary.ch1, ind, NULL, fp); | ||
| 802 | /* if (ind < 0) */ | ||
| 803 | fputs(s, fp); | ||
| 804 | shtree(n->nbinary.ch2, ind, NULL, fp); | ||
| 805 | break; | ||
| 806 | case NCMD: | ||
| 807 | shcmd(n, fp); | ||
| 808 | if (ind >= 0) | ||
| 809 | putc('\n', fp); | ||
| 810 | break; | ||
| 811 | case NPIPE: | ||
| 812 | for (lp = n->npipe.cmdlist; lp; lp = lp->next) { | ||
| 813 | shcmd(lp->n, fp); | ||
| 814 | if (lp->next) | ||
| 815 | fputs(" | ", fp); | ||
| 816 | } | ||
| 817 | if (n->npipe.backgnd) | ||
| 818 | fputs(" &", fp); | ||
| 819 | if (ind >= 0) | ||
| 820 | putc('\n', fp); | ||
| 821 | break; | ||
| 822 | default: | ||
| 823 | fprintf(fp, "<node type %d>", n->type); | ||
| 824 | if (ind >= 0) | ||
| 825 | putc('\n', fp); | ||
| 826 | break; | ||
| 827 | } | ||
| 828 | } | ||
| 829 | |||
| 830 | static void | ||
| 831 | showtree(union node *n) | ||
| 832 | { | ||
| 833 | trace_puts("showtree called\n"); | ||
| 834 | shtree(n, 1, NULL, stdout); | ||
| 835 | } | ||
| 836 | |||
| 837 | #define TRACE(param) trace_printf param | ||
| 838 | #define TRACEV(param) trace_vprintf param | ||
| 839 | |||
| 840 | #else | ||
| 841 | |||
| 842 | #define TRACE(param) | ||
| 843 | #define TRACEV(param) | ||
| 844 | |||
| 845 | #endif /* DEBUG */ | ||
| 846 | |||
| 847 | |||
| 390 | /* ============ Parser data | 848 | /* ============ Parser data |
| 391 | * | 849 | * |
| 392 | * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up. | 850 | * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up. |
| @@ -397,6 +855,15 @@ struct strlist { | |||
| 397 | char *text; | 855 | char *text; |
| 398 | }; | 856 | }; |
| 399 | 857 | ||
| 858 | #if ENABLE_ASH_ALIAS | ||
| 859 | #define ALIASINUSE 1 | ||
| 860 | #define ALIASDEAD 2 | ||
| 861 | struct alias; | ||
| 862 | static int aliascmd(int, char **); | ||
| 863 | static int unaliascmd(int, char **); | ||
| 864 | static void printalias(const struct alias *); | ||
| 865 | #endif | ||
| 866 | |||
| 400 | struct strpush { | 867 | struct strpush { |
| 401 | struct strpush *prev; /* preceding string on stack */ | 868 | struct strpush *prev; /* preceding string on stack */ |
| 402 | char *prevstring; | 869 | char *prevstring; |
| @@ -1882,7 +2349,6 @@ struct arglist { | |||
| 1882 | #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */ | 2349 | #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */ |
| 1883 | 2350 | ||
| 1884 | 2351 | ||
| 1885 | union node; | ||
| 1886 | static void expandarg(union node *, struct arglist *, int); | 2352 | static void expandarg(union node *, struct arglist *, int); |
| 1887 | #define rmescapes(p) _rmescapes((p), 0) | 2353 | #define rmescapes(p) _rmescapes((p), 0) |
| 1888 | static char *_rmescapes(char *, int); | 2354 | static char *_rmescapes(char *, int); |
| @@ -1903,152 +2369,6 @@ struct backcmd { /* result of evalbackcmd */ | |||
| 1903 | struct job *jp; /* job structure for command */ | 2369 | struct job *jp; /* job structure for command */ |
| 1904 | }; | 2370 | }; |
| 1905 | 2371 | ||
| 1906 | /* | ||
| 1907 | * This file was generated by the mknodes program. | ||
| 1908 | */ | ||
| 1909 | |||
| 1910 | #define NCMD 0 | ||
| 1911 | #define NPIPE 1 | ||
| 1912 | #define NREDIR 2 | ||
| 1913 | #define NBACKGND 3 | ||
| 1914 | #define NSUBSHELL 4 | ||
| 1915 | #define NAND 5 | ||
| 1916 | #define NOR 6 | ||
| 1917 | #define NSEMI 7 | ||
| 1918 | #define NIF 8 | ||
| 1919 | #define NWHILE 9 | ||
| 1920 | #define NUNTIL 10 | ||
| 1921 | #define NFOR 11 | ||
| 1922 | #define NCASE 12 | ||
| 1923 | #define NCLIST 13 | ||
| 1924 | #define NDEFUN 14 | ||
| 1925 | #define NARG 15 | ||
| 1926 | #define NTO 16 | ||
| 1927 | #define NCLOBBER 17 | ||
| 1928 | #define NFROM 18 | ||
| 1929 | #define NFROMTO 19 | ||
| 1930 | #define NAPPEND 20 | ||
| 1931 | #define NTOFD 21 | ||
| 1932 | #define NFROMFD 22 | ||
| 1933 | #define NHERE 23 | ||
| 1934 | #define NXHERE 24 | ||
| 1935 | #define NNOT 25 | ||
| 1936 | |||
| 1937 | |||
| 1938 | struct ncmd { | ||
| 1939 | int type; | ||
| 1940 | union node *assign; | ||
| 1941 | union node *args; | ||
| 1942 | union node *redirect; | ||
| 1943 | }; | ||
| 1944 | |||
| 1945 | struct npipe { | ||
| 1946 | int type; | ||
| 1947 | int backgnd; | ||
| 1948 | struct nodelist *cmdlist; | ||
| 1949 | }; | ||
| 1950 | |||
| 1951 | struct nredir { | ||
| 1952 | int type; | ||
| 1953 | union node *n; | ||
| 1954 | union node *redirect; | ||
| 1955 | }; | ||
| 1956 | |||
| 1957 | struct nbinary { | ||
| 1958 | int type; | ||
| 1959 | union node *ch1; | ||
| 1960 | union node *ch2; | ||
| 1961 | }; | ||
| 1962 | |||
| 1963 | struct nif { | ||
| 1964 | int type; | ||
| 1965 | union node *test; | ||
| 1966 | union node *ifpart; | ||
| 1967 | union node *elsepart; | ||
| 1968 | }; | ||
| 1969 | |||
| 1970 | struct nfor { | ||
| 1971 | int type; | ||
| 1972 | union node *args; | ||
| 1973 | union node *body; | ||
| 1974 | char *var; | ||
| 1975 | }; | ||
| 1976 | |||
| 1977 | struct ncase { | ||
| 1978 | int type; | ||
| 1979 | union node *expr; | ||
| 1980 | union node *cases; | ||
| 1981 | }; | ||
| 1982 | |||
| 1983 | struct nclist { | ||
| 1984 | int type; | ||
| 1985 | union node *next; | ||
| 1986 | union node *pattern; | ||
| 1987 | union node *body; | ||
| 1988 | }; | ||
| 1989 | |||
| 1990 | struct narg { | ||
| 1991 | int type; | ||
| 1992 | union node *next; | ||
| 1993 | char *text; | ||
| 1994 | struct nodelist *backquote; | ||
| 1995 | }; | ||
| 1996 | |||
| 1997 | struct nfile { | ||
| 1998 | int type; | ||
| 1999 | union node *next; | ||
| 2000 | int fd; | ||
| 2001 | union node *fname; | ||
| 2002 | char *expfname; | ||
| 2003 | }; | ||
| 2004 | |||
| 2005 | struct ndup { | ||
| 2006 | int type; | ||
| 2007 | union node *next; | ||
| 2008 | int fd; | ||
| 2009 | int dupfd; | ||
| 2010 | union node *vname; | ||
| 2011 | }; | ||
| 2012 | |||
| 2013 | struct nhere { | ||
| 2014 | int type; | ||
| 2015 | union node *next; | ||
| 2016 | int fd; | ||
| 2017 | union node *doc; | ||
| 2018 | }; | ||
| 2019 | |||
| 2020 | struct nnot { | ||
| 2021 | int type; | ||
| 2022 | union node *com; | ||
| 2023 | }; | ||
| 2024 | |||
| 2025 | union node { | ||
| 2026 | int type; | ||
| 2027 | struct ncmd ncmd; | ||
| 2028 | struct npipe npipe; | ||
| 2029 | struct nredir nredir; | ||
| 2030 | struct nbinary nbinary; | ||
| 2031 | struct nif nif; | ||
| 2032 | struct nfor nfor; | ||
| 2033 | struct ncase ncase; | ||
| 2034 | struct nclist nclist; | ||
| 2035 | struct narg narg; | ||
| 2036 | struct nfile nfile; | ||
| 2037 | struct ndup ndup; | ||
| 2038 | struct nhere nhere; | ||
| 2039 | struct nnot nnot; | ||
| 2040 | }; | ||
| 2041 | |||
| 2042 | struct nodelist { | ||
| 2043 | struct nodelist *next; | ||
| 2044 | union node *n; | ||
| 2045 | }; | ||
| 2046 | |||
| 2047 | struct funcnode { | ||
| 2048 | int count; | ||
| 2049 | union node n; | ||
| 2050 | }; | ||
| 2051 | |||
| 2052 | 2372 | ||
| 2053 | static void freefunc(struct funcnode *); | 2373 | static void freefunc(struct funcnode *); |
| 2054 | /* parser.h */ | 2374 | /* parser.h */ |
| @@ -2736,7 +3056,7 @@ static int funcnest; /* depth of function calls */ | |||
| 2736 | */ | 3056 | */ |
| 2737 | 3057 | ||
| 2738 | #if JOBS | 3058 | #if JOBS |
| 2739 | static int bgcmd(int, char **); | 3059 | static int fg_bgcmd(int, char **); |
| 2740 | #endif | 3060 | #endif |
| 2741 | static int breakcmd(int, char **); | 3061 | static int breakcmd(int, char **); |
| 2742 | static int cdcmd(int, char **); | 3062 | static int cdcmd(int, char **); |
| @@ -2755,9 +3075,6 @@ static int execcmd(int, char **); | |||
| 2755 | static int exitcmd(int, char **); | 3075 | static int exitcmd(int, char **); |
| 2756 | static int exportcmd(int, char **); | 3076 | static int exportcmd(int, char **); |
| 2757 | static int falsecmd(int, char **); | 3077 | static int falsecmd(int, char **); |
| 2758 | #if JOBS | ||
| 2759 | static int fgcmd(int, char **); | ||
| 2760 | #endif | ||
| 2761 | #if ENABLE_ASH_GETOPTS | 3078 | #if ENABLE_ASH_GETOPTS |
| 2762 | static int getoptscmd(int, char **); | 3079 | static int getoptscmd(int, char **); |
| 2763 | #endif | 3080 | #endif |
| @@ -2840,7 +3157,7 @@ static const struct builtincmd builtincmd[] = { | |||
| 2840 | { BUILTIN_REG_ASSG "alias", aliascmd }, | 3157 | { BUILTIN_REG_ASSG "alias", aliascmd }, |
| 2841 | #endif | 3158 | #endif |
| 2842 | #if JOBS | 3159 | #if JOBS |
| 2843 | { BUILTIN_REGULAR "bg", bgcmd }, | 3160 | { BUILTIN_REGULAR "bg", fg_bgcmd }, |
| 2844 | #endif | 3161 | #endif |
| 2845 | { BUILTIN_SPEC_REG "break", breakcmd }, | 3162 | { BUILTIN_SPEC_REG "break", breakcmd }, |
| 2846 | { BUILTIN_REGULAR "cd", cdcmd }, | 3163 | { BUILTIN_REGULAR "cd", cdcmd }, |
| @@ -2858,7 +3175,7 @@ static const struct builtincmd builtincmd[] = { | |||
| 2858 | { BUILTIN_SPEC_REG_ASSG "export", exportcmd }, | 3175 | { BUILTIN_SPEC_REG_ASSG "export", exportcmd }, |
| 2859 | { BUILTIN_REGULAR "false", falsecmd }, | 3176 | { BUILTIN_REGULAR "false", falsecmd }, |
| 2860 | #if JOBS | 3177 | #if JOBS |
| 2861 | { BUILTIN_REGULAR "fg", fgcmd }, | 3178 | { BUILTIN_REGULAR "fg", fg_bgcmd }, |
| 2862 | #endif | 3179 | #endif |
| 2863 | #if ENABLE_ASH_GETOPTS | 3180 | #if ENABLE_ASH_GETOPTS |
| 2864 | { BUILTIN_REGULAR "getopts", getoptscmd }, | 3181 | { BUILTIN_REGULAR "getopts", getoptscmd }, |
| @@ -3033,25 +3350,12 @@ static void setjobctl(int); | |||
| 3033 | static void showjobs(FILE *, int); | 3350 | static void showjobs(FILE *, int); |
| 3034 | #endif | 3351 | #endif |
| 3035 | 3352 | ||
| 3036 | /* main.h */ | ||
| 3037 | 3353 | ||
| 3354 | /* main.h */ | ||
| 3038 | 3355 | ||
| 3039 | static void readcmdfile(char *); | 3356 | static void readcmdfile(char *); |
| 3040 | 3357 | ||
| 3041 | 3358 | ||
| 3042 | /* mystring.h */ | ||
| 3043 | |||
| 3044 | |||
| 3045 | #define DOLATSTRLEN 4 | ||
| 3046 | |||
| 3047 | static char *prefix(const char *, const char *); | ||
| 3048 | static int number(const char *); | ||
| 3049 | static int is_number(const char *); | ||
| 3050 | static char *single_quote(const char *); | ||
| 3051 | |||
| 3052 | #define equal(s1, s2) (strcmp(s1, s2) == 0) | ||
| 3053 | #define scopy(s1, s2) ((void)strcpy(s2, s1)) | ||
| 3054 | |||
| 3055 | /* options.h */ | 3359 | /* options.h */ |
| 3056 | 3360 | ||
| 3057 | static char *minusc; /* argument to -c option */ | 3361 | static char *minusc; /* argument to -c option */ |
| @@ -3076,22 +3380,8 @@ static void clearredir(int); | |||
| 3076 | static int copyfd(int, int); | 3380 | static int copyfd(int, int); |
| 3077 | static int redirectsafe(union node *, int); | 3381 | static int redirectsafe(union node *, int); |
| 3078 | 3382 | ||
| 3079 | /* show.h */ | ||
| 3080 | |||
| 3081 | |||
| 3082 | #if DEBUG | ||
| 3083 | static void showtree(union node *); | ||
| 3084 | static void trace(const char *, ...); | ||
| 3085 | static void tracev(const char *, va_list); | ||
| 3086 | static void trargs(char **); | ||
| 3087 | static void trputc(int); | ||
| 3088 | static void trputs(const char *); | ||
| 3089 | static void opentrace(void); | ||
| 3090 | #endif | ||
| 3091 | |||
| 3092 | /* trap.h */ | 3383 | /* trap.h */ |
| 3093 | 3384 | ||
| 3094 | |||
| 3095 | static void clear_traps(void); | 3385 | static void clear_traps(void); |
| 3096 | static void setsignal(int); | 3386 | static void setsignal(int); |
| 3097 | static void ignoresig(int); | 3387 | static void ignoresig(int); |
| @@ -3137,11 +3427,67 @@ static int is_safe_applet(char *name) | |||
| 3137 | 3427 | ||
| 3138 | 3428 | ||
| 3139 | #if ENABLE_ASH_ALIAS | 3429 | #if ENABLE_ASH_ALIAS |
| 3430 | struct alias { | ||
| 3431 | struct alias *next; | ||
| 3432 | char *name; | ||
| 3433 | char *val; | ||
| 3434 | int flag; | ||
| 3435 | }; | ||
| 3436 | |||
| 3140 | static struct alias *atab[ATABSIZE]; | 3437 | static struct alias *atab[ATABSIZE]; |
| 3141 | 3438 | ||
| 3142 | static void setalias(const char *, const char *); | 3439 | static struct alias ** |
| 3143 | static struct alias *freealias(struct alias *); | 3440 | __lookupalias(const char *name) { |
| 3144 | static struct alias **__lookupalias(const char *); | 3441 | unsigned int hashval; |
| 3442 | struct alias **app; | ||
| 3443 | const char *p; | ||
| 3444 | unsigned int ch; | ||
| 3445 | |||
| 3446 | p = name; | ||
| 3447 | |||
| 3448 | ch = (unsigned char)*p; | ||
| 3449 | hashval = ch << 4; | ||
| 3450 | while (ch) { | ||
| 3451 | hashval += ch; | ||
| 3452 | ch = (unsigned char)*++p; | ||
| 3453 | } | ||
| 3454 | app = &atab[hashval % ATABSIZE]; | ||
| 3455 | |||
| 3456 | for (; *app; app = &(*app)->next) { | ||
| 3457 | if (strcmp(name, (*app)->name) == 0) { | ||
| 3458 | break; | ||
| 3459 | } | ||
| 3460 | } | ||
| 3461 | |||
| 3462 | return app; | ||
| 3463 | } | ||
| 3464 | |||
| 3465 | static struct alias * | ||
| 3466 | lookupalias(const char *name, int check) | ||
| 3467 | { | ||
| 3468 | struct alias *ap = *__lookupalias(name); | ||
| 3469 | |||
| 3470 | if (check && ap && (ap->flag & ALIASINUSE)) | ||
| 3471 | return NULL; | ||
| 3472 | return ap; | ||
| 3473 | } | ||
| 3474 | |||
| 3475 | static struct alias * | ||
| 3476 | freealias(struct alias *ap) | ||
| 3477 | { | ||
| 3478 | struct alias *next; | ||
| 3479 | |||
| 3480 | if (ap->flag & ALIASINUSE) { | ||
| 3481 | ap->flag |= ALIASDEAD; | ||
| 3482 | return ap; | ||
| 3483 | } | ||
| 3484 | |||
| 3485 | next = ap->next; | ||
| 3486 | free(ap->name); | ||
| 3487 | free(ap->val); | ||
| 3488 | free(ap); | ||
| 3489 | return next; | ||
| 3490 | } | ||
| 3145 | 3491 | ||
| 3146 | static void | 3492 | static void |
| 3147 | setalias(const char *name, const char *val) | 3493 | setalias(const char *name, const char *val) |
| @@ -3205,16 +3551,6 @@ rmaliases(void) | |||
| 3205 | INT_ON; | 3551 | INT_ON; |
| 3206 | } | 3552 | } |
| 3207 | 3553 | ||
| 3208 | static struct alias * | ||
| 3209 | lookupalias(const char *name, int check) | ||
| 3210 | { | ||
| 3211 | struct alias *ap = *__lookupalias(name); | ||
| 3212 | |||
| 3213 | if (check && ap && (ap->flag & ALIASINUSE)) | ||
| 3214 | return NULL; | ||
| 3215 | return ap; | ||
| 3216 | } | ||
| 3217 | |||
| 3218 | /* | 3554 | /* |
| 3219 | * TODO - sort output | 3555 | * TODO - sort output |
| 3220 | */ | 3556 | */ |
| @@ -3273,54 +3609,11 @@ unaliascmd(int argc, char **argv) | |||
| 3273 | return i; | 3609 | return i; |
| 3274 | } | 3610 | } |
| 3275 | 3611 | ||
| 3276 | static struct alias * | ||
| 3277 | freealias(struct alias *ap) | ||
| 3278 | { | ||
| 3279 | struct alias *next; | ||
| 3280 | |||
| 3281 | if (ap->flag & ALIASINUSE) { | ||
| 3282 | ap->flag |= ALIASDEAD; | ||
| 3283 | return ap; | ||
| 3284 | } | ||
| 3285 | |||
| 3286 | next = ap->next; | ||
| 3287 | free(ap->name); | ||
| 3288 | free(ap->val); | ||
| 3289 | free(ap); | ||
| 3290 | return next; | ||
| 3291 | } | ||
| 3292 | |||
| 3293 | static void | 3612 | static void |
| 3294 | printalias(const struct alias *ap) | 3613 | printalias(const struct alias *ap) |
| 3295 | { | 3614 | { |
| 3296 | out1fmt("%s=%s\n", ap->name, single_quote(ap->val)); | 3615 | out1fmt("%s=%s\n", ap->name, single_quote(ap->val)); |
| 3297 | } | 3616 | } |
| 3298 | |||
| 3299 | static struct alias ** | ||
| 3300 | __lookupalias(const char *name) { | ||
| 3301 | unsigned int hashval; | ||
| 3302 | struct alias **app; | ||
| 3303 | const char *p; | ||
| 3304 | unsigned int ch; | ||
| 3305 | |||
| 3306 | p = name; | ||
| 3307 | |||
| 3308 | ch = (unsigned char)*p; | ||
| 3309 | hashval = ch << 4; | ||
| 3310 | while (ch) { | ||
| 3311 | hashval += ch; | ||
| 3312 | ch = (unsigned char)*++p; | ||
| 3313 | } | ||
| 3314 | app = &atab[hashval % ATABSIZE]; | ||
| 3315 | |||
| 3316 | for (; *app; app = &(*app)->next) { | ||
| 3317 | if (equal(name, (*app)->name)) { | ||
| 3318 | break; | ||
| 3319 | } | ||
| 3320 | } | ||
| 3321 | |||
| 3322 | return app; | ||
| 3323 | } | ||
| 3324 | #endif /* ASH_ALIAS */ | 3617 | #endif /* ASH_ALIAS */ |
| 3325 | 3618 | ||
| 3326 | /* eval.c */ | 3619 | /* eval.c */ |
| @@ -3602,7 +3895,7 @@ evalsubshell(union node *n, int flags) | |||
| 3602 | flags |= EV_EXIT; | 3895 | flags |= EV_EXIT; |
| 3603 | if (backgnd) | 3896 | if (backgnd) |
| 3604 | flags &=~ EV_TESTED; | 3897 | flags &=~ EV_TESTED; |
| 3605 | nofork: | 3898 | nofork: |
| 3606 | redirect(n->nredir.redirect, 0); | 3899 | redirect(n->nredir.redirect, 0); |
| 3607 | evaltreenr(n->nredir.n, flags); | 3900 | evaltreenr(n->nredir.n, flags); |
| 3608 | /* never returns */ | 3901 | /* never returns */ |
| @@ -4789,7 +5082,7 @@ cmdlookup(const char *name, int add) | |||
| 4789 | hashval &= 0x7FFF; | 5082 | hashval &= 0x7FFF; |
| 4790 | pp = &cmdtable[hashval % CMDTABLESIZE]; | 5083 | pp = &cmdtable[hashval % CMDTABLESIZE]; |
| 4791 | for (cmdp = *pp; cmdp; cmdp = cmdp->next) { | 5084 | for (cmdp = *pp; cmdp; cmdp = cmdp->next) { |
| 4792 | if (equal(cmdp->cmdname, name)) | 5085 | if (strcmp(cmdp->cmdname, name) == 0) |
| 4793 | break; | 5086 | break; |
| 4794 | pp = &cmdp->next; | 5087 | pp = &cmdp->next; |
| 4795 | } | 5088 | } |
| @@ -5292,7 +5585,7 @@ argstr(char *p, int flag) | |||
| 5292 | /* "$@" syntax adherence hack */ | 5585 | /* "$@" syntax adherence hack */ |
| 5293 | if ( | 5586 | if ( |
| 5294 | !inquotes && | 5587 | !inquotes && |
| 5295 | !memcmp(p, dolatstr, DOLATSTRLEN) && | 5588 | !memcmp(p, dolatstr, 4) && |
| 5296 | (p[4] == CTLQUOTEMARK || ( | 5589 | (p[4] == CTLQUOTEMARK || ( |
| 5297 | p[4] == CTLENDVAR && | 5590 | p[4] == CTLENDVAR && |
| 5298 | p[5] == CTLQUOTEMARK | 5591 | p[5] == CTLQUOTEMARK |
| @@ -6274,7 +6567,7 @@ expmeta(char *enddir, char *name) | |||
| 6274 | continue; | 6567 | continue; |
| 6275 | if (pmatch(start, dp->d_name)) { | 6568 | if (pmatch(start, dp->d_name)) { |
| 6276 | if (atend) { | 6569 | if (atend) { |
| 6277 | scopy(dp->d_name, enddir); | 6570 | strcpy(enddir, dp->d_name); |
| 6278 | addfname(expdir); | 6571 | addfname(expdir); |
| 6279 | } else { | 6572 | } else { |
| 6280 | for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';) | 6573 | for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';) |
| @@ -7186,7 +7479,7 @@ jobno(const struct job *jp) | |||
| 7186 | 7479 | ||
| 7187 | #if JOBS | 7480 | #if JOBS |
| 7188 | static int | 7481 | static int |
| 7189 | fgcmd(int argc, char **argv) | 7482 | fg_bgcmd(int argc, char **argv) |
| 7190 | { | 7483 | { |
| 7191 | struct job *jp; | 7484 | struct job *jp; |
| 7192 | FILE *out; | 7485 | FILE *out; |
| @@ -7210,9 +7503,6 @@ fgcmd(int argc, char **argv) | |||
| 7210 | return retval; | 7503 | return retval; |
| 7211 | } | 7504 | } |
| 7212 | 7505 | ||
| 7213 | static int bgcmd(int, char **) __attribute__((__alias__("fgcmd"))); | ||
| 7214 | |||
| 7215 | |||
| 7216 | static int | 7506 | static int |
| 7217 | restartjob(struct job *jp, int mode) | 7507 | restartjob(struct job *jp, int mode) |
| 7218 | { | 7508 | { |
| @@ -7313,8 +7603,8 @@ showjob(FILE *out, struct job *jp, int mode) | |||
| 7313 | psend = ps + jp->nprocs; | 7603 | psend = ps + jp->nprocs; |
| 7314 | 7604 | ||
| 7315 | if (jp->state == JOBRUNNING) { | 7605 | if (jp->state == JOBRUNNING) { |
| 7316 | scopy("Running", s + col); | 7606 | strcpy(s + col, "Running"); |
| 7317 | col += strlen("Running"); | 7607 | col += sizeof("Running") - 1; |
| 7318 | } else { | 7608 | } else { |
| 7319 | int status = psend[-1].status; | 7609 | int status = psend[-1].status; |
| 7320 | #if JOBS | 7610 | #if JOBS |
| @@ -7359,19 +7649,20 @@ jobscmd(int argc, char **argv) | |||
| 7359 | FILE *out; | 7649 | FILE *out; |
| 7360 | 7650 | ||
| 7361 | mode = 0; | 7651 | mode = 0; |
| 7362 | while ((m = nextopt("lp"))) | 7652 | while ((m = nextopt("lp"))) { |
| 7363 | if (m == 'l') | 7653 | if (m == 'l') |
| 7364 | mode = SHOW_PID; | 7654 | mode = SHOW_PID; |
| 7365 | else | 7655 | else |
| 7366 | mode = SHOW_PGID; | 7656 | mode = SHOW_PGID; |
| 7657 | } | ||
| 7367 | 7658 | ||
| 7368 | out = stdout; | 7659 | out = stdout; |
| 7369 | argv = argptr; | 7660 | argv = argptr; |
| 7370 | if (*argv) | 7661 | if (*argv) { |
| 7371 | do | 7662 | do |
| 7372 | showjob(out, getjob(*argv,0), mode); | 7663 | showjob(out, getjob(*argv,0), mode); |
| 7373 | while (*++argv); | 7664 | while (*++argv); |
| 7374 | else | 7665 | } else |
| 7375 | showjobs(out, mode); | 7666 | showjobs(out, mode); |
| 7376 | 7667 | ||
| 7377 | return 0; | 7668 | return 0; |
| @@ -7515,7 +7806,8 @@ getjob(const char *name, int getctl) | |||
| 7515 | currentjob: | 7806 | currentjob: |
| 7516 | err_msg = "No current job"; | 7807 | err_msg = "No current job"; |
| 7517 | goto check; | 7808 | goto check; |
| 7518 | } else if (c == '-') { | 7809 | } |
| 7810 | if (c == '-') { | ||
| 7519 | if (jp) | 7811 | if (jp) |
| 7520 | jp = jp->prev_job; | 7812 | jp = jp->prev_job; |
| 7521 | err_msg = "No previous job"; | 7813 | err_msg = "No previous job"; |
| @@ -7571,7 +7863,6 @@ getjob(const char *name, int getctl) | |||
| 7571 | * Return a new job structure. | 7863 | * Return a new job structure. |
| 7572 | * Called with interrupts off. | 7864 | * Called with interrupts off. |
| 7573 | */ | 7865 | */ |
| 7574 | |||
| 7575 | static struct job * | 7866 | static struct job * |
| 7576 | makejob(union node *node, int nprocs) | 7867 | makejob(union node *node, int nprocs) |
| 7577 | { | 7868 | { |
| @@ -7720,7 +8011,7 @@ static void forkchild(struct job *jp, union node *n, int mode) | |||
| 7720 | 8011 | ||
| 7721 | static void forkparent(struct job *jp, union node *n, int mode, pid_t pid) | 8012 | static void forkparent(struct job *jp, union node *n, int mode, pid_t pid) |
| 7722 | { | 8013 | { |
| 7723 | TRACE(("In parent shell: child = %d\n", pid)); | 8014 | TRACE(("In parent shell: child = %d\n", pid)); |
| 7724 | if (!jp) { | 8015 | if (!jp) { |
| 7725 | while (jobless && dowait(DOWAIT_NORMAL, 0) > 0); | 8016 | while (jobless && dowait(DOWAIT_NORMAL, 0) > 0); |
| 7726 | jobless++; | 8017 | jobless++; |
| @@ -7735,7 +8026,7 @@ static void forkparent(struct job *jp, union node *n, int mode, pid_t pid) | |||
| 7735 | else | 8026 | else |
| 7736 | pgrp = jp->ps[0].pid; | 8027 | pgrp = jp->ps[0].pid; |
| 7737 | /* This can fail because we are doing it in the child also */ | 8028 | /* This can fail because we are doing it in the child also */ |
| 7738 | (void)setpgid(pid, pgrp); | 8029 | setpgid(pid, pgrp); |
| 7739 | } | 8030 | } |
| 7740 | #endif | 8031 | #endif |
| 7741 | if (mode == FORK_BG) { | 8032 | if (mode == FORK_BG) { |
| @@ -7854,7 +8145,8 @@ waitforjob(struct job *jp) | |||
| 7854 | * (as opposed to running a builtin command or just typing return), | 8145 | * (as opposed to running a builtin command or just typing return), |
| 7855 | * and the jobs command may give out of date information. | 8146 | * and the jobs command may give out of date information. |
| 7856 | */ | 8147 | */ |
| 7857 | static int waitproc(int block, int *status) | 8148 | static int |
| 8149 | waitproc(int block, int *status) | ||
| 7858 | { | 8150 | { |
| 7859 | int flags = 0; | 8151 | int flags = 0; |
| 7860 | 8152 | ||
| @@ -8147,10 +8439,9 @@ cmdtxt(union node *n) | |||
| 8147 | s[0] = n->ndup.dupfd + '0'; | 8439 | s[0] = n->ndup.dupfd + '0'; |
| 8148 | p = s; | 8440 | p = s; |
| 8149 | goto dotail2; | 8441 | goto dotail2; |
| 8150 | } else { | ||
| 8151 | n = n->nfile.fname; | ||
| 8152 | goto donode; | ||
| 8153 | } | 8442 | } |
| 8443 | n = n->nfile.fname; | ||
| 8444 | goto donode; | ||
| 8154 | } | 8445 | } |
| 8155 | } | 8446 | } |
| 8156 | 8447 | ||
| @@ -8178,6 +8469,7 @@ cmdputs(const char *s) | |||
| 8178 | "", "}", "-", "+", "?", "=", | 8469 | "", "}", "-", "+", "?", "=", |
| 8179 | "%", "%%", "#", "##" | 8470 | "%", "%%", "#", "##" |
| 8180 | }; | 8471 | }; |
| 8472 | |||
| 8181 | nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc); | 8473 | nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc); |
| 8182 | p = s; | 8474 | p = s; |
| 8183 | while ((c = *p++) != 0) { | 8475 | while ((c = *p++) != 0) { |
| @@ -8192,11 +8484,10 @@ cmdputs(const char *s) | |||
| 8192 | str = "${#"; | 8484 | str = "${#"; |
| 8193 | else | 8485 | else |
| 8194 | str = "${"; | 8486 | str = "${"; |
| 8195 | if (!(subtype & VSQUOTE) != !(quoted & 1)) { | 8487 | if (!(subtype & VSQUOTE) == !(quoted & 1)) |
| 8196 | quoted ^= 1; | ||
| 8197 | c = '"'; | ||
| 8198 | } else | ||
| 8199 | goto dostr; | 8488 | goto dostr; |
| 8489 | quoted ^= 1; | ||
| 8490 | c = '"'; | ||
| 8200 | break; | 8491 | break; |
| 8201 | case CTLENDVAR: | 8492 | case CTLENDVAR: |
| 8202 | str = "\"}" + !(quoted & 1); | 8493 | str = "\"}" + !(quoted & 1); |
| @@ -8650,7 +8941,7 @@ minus_o(char *name, int val) | |||
| 8650 | 8941 | ||
| 8651 | if (name) { | 8942 | if (name) { |
| 8652 | for (i = 0; i < NOPTS; i++) { | 8943 | for (i = 0; i < NOPTS; i++) { |
| 8653 | if (equal(name, optnames(i))) { | 8944 | if (strcmp(name, optnames(i)) == 0) { |
| 8654 | optlist[i] = val; | 8945 | optlist[i] = val; |
| 8655 | return; | 8946 | return; |
| 8656 | } | 8947 | } |
| @@ -8859,13 +9150,15 @@ setcmd(int argc, char **argv) | |||
| 8859 | 9150 | ||
| 8860 | 9151 | ||
| 8861 | #if ENABLE_LOCALE_SUPPORT | 9152 | #if ENABLE_LOCALE_SUPPORT |
| 8862 | static void change_lc_all(const char *value) | 9153 | static void |
| 9154 | change_lc_all(const char *value) | ||
| 8863 | { | 9155 | { |
| 8864 | if (value && *value != '\0') | 9156 | if (value && *value != '\0') |
| 8865 | setlocale(LC_ALL, value); | 9157 | setlocale(LC_ALL, value); |
| 8866 | } | 9158 | } |
| 8867 | 9159 | ||
| 8868 | static void change_lc_ctype(const char *value) | 9160 | static void |
| 9161 | change_lc_ctype(const char *value) | ||
| 8869 | { | 9162 | { |
| 8870 | if (value && *value != '\0') | 9163 | if (value && *value != '\0') |
| 8871 | setlocale(LC_CTYPE, value); | 9164 | setlocale(LC_CTYPE, value); |
| @@ -8874,7 +9167,8 @@ static void change_lc_ctype(const char *value) | |||
| 8874 | 9167 | ||
| 8875 | #if ENABLE_ASH_RANDOM_SUPPORT | 9168 | #if ENABLE_ASH_RANDOM_SUPPORT |
| 8876 | /* Roughly copied from bash.. */ | 9169 | /* Roughly copied from bash.. */ |
| 8877 | static void change_random(const char *value) | 9170 | static void |
| 9171 | change_random(const char *value) | ||
| 8878 | { | 9172 | { |
| 8879 | if (value == NULL) { | 9173 | if (value == NULL) { |
| 8880 | /* "get", generate */ | 9174 | /* "get", generate */ |
| @@ -11036,349 +11330,6 @@ redirectsafe(union node *redir, int flags) | |||
| 11036 | return err; | 11330 | return err; |
| 11037 | } | 11331 | } |
| 11038 | 11332 | ||
| 11039 | /* show.c */ | ||
| 11040 | |||
| 11041 | #if DEBUG | ||
| 11042 | static void shtree(union node *, int, char *, FILE*); | ||
| 11043 | static void shcmd(union node *, FILE *); | ||
| 11044 | static void sharg(union node *, FILE *); | ||
| 11045 | static void indent(int, char *, FILE *); | ||
| 11046 | static void trstring(char *); | ||
| 11047 | |||
| 11048 | static void | ||
| 11049 | showtree(union node *n) | ||
| 11050 | { | ||
| 11051 | trputs("showtree called\n"); | ||
| 11052 | shtree(n, 1, NULL, stdout); | ||
| 11053 | } | ||
| 11054 | |||
| 11055 | static void | ||
| 11056 | shtree(union node *n, int ind, char *pfx, FILE *fp) | ||
| 11057 | { | ||
| 11058 | struct nodelist *lp; | ||
| 11059 | const char *s; | ||
| 11060 | |||
| 11061 | if (n == NULL) | ||
| 11062 | return; | ||
| 11063 | |||
| 11064 | indent(ind, pfx, fp); | ||
| 11065 | switch (n->type) { | ||
| 11066 | case NSEMI: | ||
| 11067 | s = "; "; | ||
| 11068 | goto binop; | ||
| 11069 | case NAND: | ||
| 11070 | s = " && "; | ||
| 11071 | goto binop; | ||
| 11072 | case NOR: | ||
| 11073 | s = " || "; | ||
| 11074 | binop: | ||
| 11075 | shtree(n->nbinary.ch1, ind, NULL, fp); | ||
| 11076 | /* if (ind < 0) */ | ||
| 11077 | fputs(s, fp); | ||
| 11078 | shtree(n->nbinary.ch2, ind, NULL, fp); | ||
| 11079 | break; | ||
| 11080 | case NCMD: | ||
| 11081 | shcmd(n, fp); | ||
| 11082 | if (ind >= 0) | ||
| 11083 | putc('\n', fp); | ||
| 11084 | break; | ||
| 11085 | case NPIPE: | ||
| 11086 | for (lp = n->npipe.cmdlist; lp; lp = lp->next) { | ||
| 11087 | shcmd(lp->n, fp); | ||
| 11088 | if (lp->next) | ||
| 11089 | fputs(" | ", fp); | ||
| 11090 | } | ||
| 11091 | if (n->npipe.backgnd) | ||
| 11092 | fputs(" &", fp); | ||
| 11093 | if (ind >= 0) | ||
| 11094 | putc('\n', fp); | ||
| 11095 | break; | ||
| 11096 | default: | ||
| 11097 | fprintf(fp, "<node type %d>", n->type); | ||
| 11098 | if (ind >= 0) | ||
| 11099 | putc('\n', fp); | ||
| 11100 | break; | ||
| 11101 | } | ||
| 11102 | } | ||
| 11103 | |||
| 11104 | static void | ||
| 11105 | shcmd(union node *cmd, FILE *fp) | ||
| 11106 | { | ||
| 11107 | union node *np; | ||
| 11108 | int first; | ||
| 11109 | const char *s; | ||
| 11110 | int dftfd; | ||
| 11111 | |||
| 11112 | first = 1; | ||
| 11113 | for (np = cmd->ncmd.args; np; np = np->narg.next) { | ||
| 11114 | if (! first) | ||
| 11115 | putchar(' '); | ||
| 11116 | sharg(np, fp); | ||
| 11117 | first = 0; | ||
| 11118 | } | ||
| 11119 | for (np = cmd->ncmd.redirect; np; np = np->nfile.next) { | ||
| 11120 | if (! first) | ||
| 11121 | putchar(' '); | ||
| 11122 | switch (np->nfile.type) { | ||
| 11123 | case NTO: s = ">"; dftfd = 1; break; | ||
| 11124 | case NCLOBBER: s = ">|"; dftfd = 1; break; | ||
| 11125 | case NAPPEND: s = ">>"; dftfd = 1; break; | ||
| 11126 | case NTOFD: s = ">&"; dftfd = 1; break; | ||
| 11127 | case NFROM: s = "<"; dftfd = 0; break; | ||
| 11128 | case NFROMFD: s = "<&"; dftfd = 0; break; | ||
| 11129 | case NFROMTO: s = "<>"; dftfd = 0; break; | ||
| 11130 | default: s = "*error*"; dftfd = 0; break; | ||
| 11131 | } | ||
| 11132 | if (np->nfile.fd != dftfd) | ||
| 11133 | fprintf(fp, "%d", np->nfile.fd); | ||
| 11134 | fputs(s, fp); | ||
| 11135 | if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { | ||
| 11136 | fprintf(fp, "%d", np->ndup.dupfd); | ||
| 11137 | } else { | ||
| 11138 | sharg(np->nfile.fname, fp); | ||
| 11139 | } | ||
| 11140 | first = 0; | ||
| 11141 | } | ||
| 11142 | } | ||
| 11143 | |||
| 11144 | static void | ||
| 11145 | sharg(union node *arg, FILE *fp) | ||
| 11146 | { | ||
| 11147 | char *p; | ||
| 11148 | struct nodelist *bqlist; | ||
| 11149 | int subtype; | ||
| 11150 | |||
| 11151 | if (arg->type != NARG) { | ||
| 11152 | out1fmt("<node type %d>\n", arg->type); | ||
| 11153 | abort(); | ||
| 11154 | } | ||
| 11155 | bqlist = arg->narg.backquote; | ||
| 11156 | for (p = arg->narg.text; *p; p++) { | ||
| 11157 | switch (*p) { | ||
| 11158 | case CTLESC: | ||
| 11159 | putc(*++p, fp); | ||
| 11160 | break; | ||
| 11161 | case CTLVAR: | ||
| 11162 | putc('$', fp); | ||
| 11163 | putc('{', fp); | ||
| 11164 | subtype = *++p; | ||
| 11165 | if (subtype == VSLENGTH) | ||
| 11166 | putc('#', fp); | ||
| 11167 | |||
| 11168 | while (*p != '=') | ||
| 11169 | putc(*p++, fp); | ||
| 11170 | |||
| 11171 | if (subtype & VSNUL) | ||
| 11172 | putc(':', fp); | ||
| 11173 | |||
| 11174 | switch (subtype & VSTYPE) { | ||
| 11175 | case VSNORMAL: | ||
| 11176 | putc('}', fp); | ||
| 11177 | break; | ||
| 11178 | case VSMINUS: | ||
| 11179 | putc('-', fp); | ||
| 11180 | break; | ||
| 11181 | case VSPLUS: | ||
| 11182 | putc('+', fp); | ||
| 11183 | break; | ||
| 11184 | case VSQUESTION: | ||
| 11185 | putc('?', fp); | ||
| 11186 | break; | ||
| 11187 | case VSASSIGN: | ||
| 11188 | putc('=', fp); | ||
| 11189 | break; | ||
| 11190 | case VSTRIMLEFT: | ||
| 11191 | putc('#', fp); | ||
| 11192 | break; | ||
| 11193 | case VSTRIMLEFTMAX: | ||
| 11194 | putc('#', fp); | ||
| 11195 | putc('#', fp); | ||
| 11196 | break; | ||
| 11197 | case VSTRIMRIGHT: | ||
| 11198 | putc('%', fp); | ||
| 11199 | break; | ||
| 11200 | case VSTRIMRIGHTMAX: | ||
| 11201 | putc('%', fp); | ||
| 11202 | putc('%', fp); | ||
| 11203 | break; | ||
| 11204 | case VSLENGTH: | ||
| 11205 | break; | ||
| 11206 | default: | ||
| 11207 | out1fmt("<subtype %d>", subtype); | ||
| 11208 | } | ||
| 11209 | break; | ||
| 11210 | case CTLENDVAR: | ||
| 11211 | putc('}', fp); | ||
| 11212 | break; | ||
| 11213 | case CTLBACKQ: | ||
| 11214 | case CTLBACKQ|CTLQUOTE: | ||
| 11215 | putc('$', fp); | ||
| 11216 | putc('(', fp); | ||
| 11217 | shtree(bqlist->n, -1, NULL, fp); | ||
| 11218 | putc(')', fp); | ||
| 11219 | break; | ||
| 11220 | default: | ||
| 11221 | putc(*p, fp); | ||
| 11222 | break; | ||
| 11223 | } | ||
| 11224 | } | ||
| 11225 | } | ||
| 11226 | |||
| 11227 | |||
| 11228 | static void | ||
| 11229 | indent(int amount, char *pfx, FILE *fp) | ||
| 11230 | { | ||
| 11231 | int i; | ||
| 11232 | |||
| 11233 | for (i = 0; i < amount; i++) { | ||
| 11234 | if (pfx && i == amount - 1) | ||
| 11235 | fputs(pfx, fp); | ||
| 11236 | putc('\t', fp); | ||
| 11237 | } | ||
| 11238 | } | ||
| 11239 | |||
| 11240 | |||
| 11241 | /* | ||
| 11242 | * Debugging stuff. | ||
| 11243 | */ | ||
| 11244 | |||
| 11245 | |||
| 11246 | static FILE *tracefile; | ||
| 11247 | |||
| 11248 | |||
| 11249 | static void | ||
| 11250 | trputc(int c) | ||
| 11251 | { | ||
| 11252 | if (debug != 1) | ||
| 11253 | return; | ||
| 11254 | putc(c, tracefile); | ||
| 11255 | } | ||
| 11256 | |||
| 11257 | static void | ||
| 11258 | trace(const char *fmt, ...) | ||
| 11259 | { | ||
| 11260 | va_list va; | ||
| 11261 | |||
| 11262 | if (debug != 1) | ||
| 11263 | return; | ||
| 11264 | va_start(va, fmt); | ||
| 11265 | (void) vfprintf(tracefile, fmt, va); | ||
| 11266 | va_end(va); | ||
| 11267 | } | ||
| 11268 | |||
| 11269 | static void | ||
| 11270 | tracev(const char *fmt, va_list va) | ||
| 11271 | { | ||
| 11272 | if (debug != 1) | ||
| 11273 | return; | ||
| 11274 | (void) vfprintf(tracefile, fmt, va); | ||
| 11275 | } | ||
| 11276 | |||
| 11277 | |||
| 11278 | static void | ||
| 11279 | trputs(const char *s) | ||
| 11280 | { | ||
| 11281 | if (debug != 1) | ||
| 11282 | return; | ||
| 11283 | fputs(s, tracefile); | ||
| 11284 | } | ||
| 11285 | |||
| 11286 | |||
| 11287 | static void | ||
| 11288 | trstring(char *s) | ||
| 11289 | { | ||
| 11290 | char *p; | ||
| 11291 | char c; | ||
| 11292 | |||
| 11293 | if (debug != 1) | ||
| 11294 | return; | ||
| 11295 | putc('"', tracefile); | ||
| 11296 | for (p = s; *p; p++) { | ||
| 11297 | switch (*p) { | ||
| 11298 | case '\n': c = 'n'; goto backslash; | ||
| 11299 | case '\t': c = 't'; goto backslash; | ||
| 11300 | case '\r': c = 'r'; goto backslash; | ||
| 11301 | case '"': c = '"'; goto backslash; | ||
| 11302 | case '\\': c = '\\'; goto backslash; | ||
| 11303 | case CTLESC: c = 'e'; goto backslash; | ||
| 11304 | case CTLVAR: c = 'v'; goto backslash; | ||
| 11305 | case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; | ||
| 11306 | case CTLBACKQ: c = 'q'; goto backslash; | ||
| 11307 | case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; | ||
| 11308 | backslash: | ||
| 11309 | putc('\\', tracefile); | ||
| 11310 | putc(c, tracefile); | ||
| 11311 | break; | ||
| 11312 | default: | ||
| 11313 | if (*p >= ' ' && *p <= '~') | ||
| 11314 | putc(*p, tracefile); | ||
| 11315 | else { | ||
| 11316 | putc('\\', tracefile); | ||
| 11317 | putc(*p >> 6 & 03, tracefile); | ||
| 11318 | putc(*p >> 3 & 07, tracefile); | ||
| 11319 | putc(*p & 07, tracefile); | ||
| 11320 | } | ||
| 11321 | break; | ||
| 11322 | } | ||
| 11323 | } | ||
| 11324 | putc('"', tracefile); | ||
| 11325 | } | ||
| 11326 | |||
| 11327 | |||
| 11328 | static void | ||
| 11329 | trargs(char **ap) | ||
| 11330 | { | ||
| 11331 | if (debug != 1) | ||
| 11332 | return; | ||
| 11333 | while (*ap) { | ||
| 11334 | trstring(*ap++); | ||
| 11335 | if (*ap) | ||
| 11336 | putc(' ', tracefile); | ||
| 11337 | else | ||
| 11338 | putc('\n', tracefile); | ||
| 11339 | } | ||
| 11340 | } | ||
| 11341 | |||
| 11342 | |||
| 11343 | static void | ||
| 11344 | opentrace(void) | ||
| 11345 | { | ||
| 11346 | char s[100]; | ||
| 11347 | #ifdef O_APPEND | ||
| 11348 | int flags; | ||
| 11349 | #endif | ||
| 11350 | |||
| 11351 | if (debug != 1) { | ||
| 11352 | if (tracefile) | ||
| 11353 | fflush(tracefile); | ||
| 11354 | /* leave open because libedit might be using it */ | ||
| 11355 | return; | ||
| 11356 | } | ||
| 11357 | scopy("./trace", s); | ||
| 11358 | if (tracefile) { | ||
| 11359 | if (!freopen(s, "a", tracefile)) { | ||
| 11360 | fprintf(stderr, "Can't re-open %s\n", s); | ||
| 11361 | debug = 0; | ||
| 11362 | return; | ||
| 11363 | } | ||
| 11364 | } else { | ||
| 11365 | tracefile = fopen(s, "a"); | ||
| 11366 | if (tracefile == NULL) { | ||
| 11367 | fprintf(stderr, "Can't open %s\n", s); | ||
| 11368 | debug = 0; | ||
| 11369 | return; | ||
| 11370 | } | ||
| 11371 | } | ||
| 11372 | #ifdef O_APPEND | ||
| 11373 | flags = fcntl(fileno(tracefile), F_GETFL, 0); | ||
| 11374 | if (flags >= 0) | ||
| 11375 | fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); | ||
| 11376 | #endif | ||
| 11377 | setlinebuf(tracefile); | ||
| 11378 | fputs("\nTracing started.\n", tracefile); | ||
| 11379 | } | ||
| 11380 | #endif /* DEBUG */ | ||
| 11381 | |||
| 11382 | 11333 | ||
| 11383 | /* trap.c */ | 11334 | /* trap.c */ |
| 11384 | 11335 | ||
| @@ -13215,18 +13166,17 @@ int ash_main(int argc, char **argv) | |||
| 13215 | FORCE_INT_ON; /* enable interrupts */ | 13166 | FORCE_INT_ON; /* enable interrupts */ |
| 13216 | if (s == 1) | 13167 | if (s == 1) |
| 13217 | goto state1; | 13168 | goto state1; |
| 13218 | else if (s == 2) | 13169 | if (s == 2) |
| 13219 | goto state2; | 13170 | goto state2; |
| 13220 | else if (s == 3) | 13171 | if (s == 3) |
| 13221 | goto state3; | 13172 | goto state3; |
| 13222 | else | 13173 | goto state4; |
| 13223 | goto state4; | ||
| 13224 | } | 13174 | } |
| 13225 | exception_handler = &jmploc; | 13175 | exception_handler = &jmploc; |
| 13226 | #if DEBUG | 13176 | #if DEBUG |
| 13227 | opentrace(); | 13177 | opentrace(); |
| 13228 | trputs("Shell args: "); | 13178 | trace_puts("Shell args: "); |
| 13229 | trargs(argv); | 13179 | trace_puts_args(argv); |
| 13230 | #endif | 13180 | #endif |
| 13231 | rootpid = getpid(); | 13181 | rootpid = getpid(); |
| 13232 | 13182 | ||
