diff options
author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-02-23 01:04:50 +0000 |
---|---|---|
committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-02-23 01:04:50 +0000 |
commit | 487a5f166d47cbc76877bb58240c1609bfcd8319 (patch) | |
tree | b115c56533abb69ddac5f790835322a705678ede /shell | |
parent | 79702e13b401e175c385384c51c5b8524370d227 (diff) | |
download | busybox-w32-487a5f166d47cbc76877bb58240c1609bfcd8319.tar.gz busybox-w32-487a5f166d47cbc76877bb58240c1609bfcd8319.tar.bz2 busybox-w32-487a5f166d47cbc76877bb58240c1609bfcd8319.zip |
ash: cleanup part 4
git-svn-id: svn://busybox.net/trunk/busybox@17956 69ca8d6d-28ef-0310-b511-8ec308f3f277
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 | ||