aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManuel Novoa III <mjn3@codepoet.org>2001-08-10 19:36:07 +0000
committerManuel Novoa III <mjn3@codepoet.org>2001-08-10 19:36:07 +0000
commit16815d4b45f6678bfed3fd6e75ef1313e7f4817b (patch)
treeaef7939e25cfef90cc88648a4ceb71e1595a5c77
parent80dd0863e2e7b2988dd1e30e83197f241be55e70 (diff)
downloadbusybox-w32-16815d4b45f6678bfed3fd6e75ef1313e7f4817b.tar.gz
busybox-w32-16815d4b45f6678bfed3fd6e75ef1313e7f4817b.tar.bz2
busybox-w32-16815d4b45f6678bfed3fd6e75ef1313e7f4817b.zip
A few bug fixes and significant size savings. Combined effort of
Vladimir N. Oleynik dzo@simtreas.ru, Aaron Lehmann aaronl@vitelus.com, and myself.
-rw-r--r--ash.c2241
-rw-r--r--shell/ash.c2241
2 files changed, 2126 insertions, 2356 deletions
diff --git a/ash.c b/ash.c
index 91b6241c6..bbde91cd1 100644
--- a/ash.c
+++ b/ash.c
@@ -58,7 +58,7 @@
58/* Getopts is used by shell procedures to parse positional parameters. 58/* Getopts is used by shell procedures to parse positional parameters.
59 * You probably want to leave this disabled, and use the busybox getopt 59 * You probably want to leave this disabled, and use the busybox getopt
60 * applet if you want to do this sort of thing. There are some scripts 60 * applet if you want to do this sort of thing. There are some scripts
61 * out there that use it, so if you need it, enable it. Most people will 61 * out there that use it, so it you need it, enable. Most people will
62 * leave this disabled. This adds 1k on an x86 system. */ 62 * leave this disabled. This adds 1k on an x86 system. */
63#undef ASH_GETOPTS 63#undef ASH_GETOPTS
64 64
@@ -81,6 +81,7 @@
81#undef GLOB_BROKEN 81#undef GLOB_BROKEN
82 82
83#include <assert.h> 83#include <assert.h>
84#include <stddef.h>
84#include <ctype.h> 85#include <ctype.h>
85#include <dirent.h> 86#include <dirent.h>
86#include <errno.h> 87#include <errno.h>
@@ -142,13 +143,6 @@
142#define CSPCL 13 /* these terminate a word */ 143#define CSPCL 13 /* these terminate a word */
143#define CIGN 14 /* character should be ignored */ 144#define CIGN 14 /* character should be ignored */
144 145
145/* Syntax classes for is_ functions */
146#define ISDIGIT 01 /* a digit */
147#define ISUPPER 02 /* an upper case letter */
148#define ISLOWER 04 /* a lower case letter */
149#define ISUNDER 010 /* an underscore */
150#define ISSPECL 020 /* the name of a special parameter */
151
152#define SYNBASE 130 146#define SYNBASE 130
153#define PEOF -130 147#define PEOF -130
154 148
@@ -156,18 +150,18 @@
156 150
157#define TEOF 0 151#define TEOF 0
158#define TNL 1 152#define TNL 1
159#define TSEMI 2 153#define TREDIR 2
160#define TBACKGND 3 154#define TWORD 3
161#define TAND 4 155#define TASSIGN 4
162#define TOR 5 156#define TSEMI 5
163#define TPIPE 6 157#define TBACKGND 6
164#define TLP 7 158#define TAND 7
165#define TRP 8 159#define TOR 8
166#define TENDCASE 9 160#define TPIPE 9
167#define TENDBQUOTE 10 161#define TLP 10
168#define TREDIR 11 162#define TRP 11
169#define TWORD 12 163#define TENDCASE 12
170#define TASSIGN 13 164#define TENDBQUOTE 13
171#define TNOT 14 165#define TNOT 14
172#define TCASE 15 166#define TCASE 15
173#define TDO 16 167#define TDO 16
@@ -186,10 +180,6 @@
186#define TEND 29 180#define TEND 29
187 181
188 182
189#define BASESYNTAX (basesyntax + SYNBASE)
190#define DQSYNTAX (dqsyntax + SYNBASE)
191#define SQSYNTAX (sqsyntax + SYNBASE)
192#define ARISYNTAX (arisyntax + SYNBASE)
193 183
194/* control characters in argument strings */ 184/* control characters in argument strings */
195#define CTLESC '\201' 185#define CTLESC '\201'
@@ -202,11 +192,19 @@
202#define CTLENDARI '\207' 192#define CTLENDARI '\207'
203#define CTLQUOTEMARK '\210' 193#define CTLQUOTEMARK '\210'
204 194
195
205#define is_digit(c) ((c)>='0' && (c)<='9') 196#define is_digit(c) ((c)>='0' && (c)<='9')
206#define is_alpha(c) (((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))
207#define is_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c)))) 197#define is_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
208#define is_in_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c)))) 198#define is_in_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
209#define is_special(c) ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT)) 199
200/*
201 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
202 * (assuming ascii char codes, as the original implementation did)
203 */
204#define is_special(c) \
205 ( (((unsigned int)c) - 33 < 32) \
206 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
207
210#define digit_val(c) ((c) - '0') 208#define digit_val(c) ((c) - '0')
211 209
212 210
@@ -688,6 +686,7 @@ static void out2fmt (const char *, ...)
688static int xwrite (int, const char *, int); 686static int xwrite (int, const char *, int);
689 687
690#define outstr(p,file) fputs(p, file) 688#define outstr(p,file) fputs(p, file)
689static void outstr (const char *p, FILE *file) { fputs(p, file); }
691static void out1str(const char *p) { outstr(p, stdout); } 690static void out1str(const char *p) { outstr(p, stdout); }
692static void out2str(const char *p) { outstr(p, stderr); } 691static void out2str(const char *p) { outstr(p, stderr); }
693 692
@@ -697,439 +696,398 @@ static void out2str(const char *p) { outstr(p, stderr); }
697static void out2c(int c) { putc(c, stderr); } 696static void out2c(int c) { putc(c, stderr); }
698#endif 697#endif
699 698
700/* syntax table used when not in quotes */
701static const char basesyntax[257] = {
702 CENDFILE, CSPCL, CWORD, CCTL,
703 CCTL, CCTL, CCTL, CCTL,
704 CCTL, CCTL, CCTL, CWORD,
705 CWORD, CWORD, CWORD, CWORD,
706 CWORD, CWORD, CWORD, CWORD,
707 CWORD, CWORD, CWORD, CWORD,
708 CWORD, CWORD, CWORD, CWORD,
709 CWORD, CWORD, CWORD, CWORD,
710 CWORD, CWORD, CWORD, CWORD,
711 CWORD, CWORD, CWORD, CWORD,
712 CWORD, CWORD, CWORD, CWORD,
713 CWORD, CWORD, CWORD, CWORD,
714 CWORD, CWORD, CWORD, CWORD,
715 CWORD, CWORD, CWORD, CWORD,
716 CWORD, CWORD, CWORD, CWORD,
717 CWORD, CWORD, CWORD, CWORD,
718 CWORD, CWORD, CWORD, CWORD,
719 CWORD, CWORD, CWORD, CWORD,
720 CWORD, CWORD, CWORD, CWORD,
721 CWORD, CWORD, CWORD, CWORD,
722 CWORD, CWORD, CWORD, CWORD,
723 CWORD, CWORD, CWORD, CWORD,
724 CWORD, CWORD, CWORD, CWORD,
725 CWORD, CWORD, CWORD, CWORD,
726 CWORD, CWORD, CWORD, CWORD,
727 CWORD, CWORD, CWORD, CWORD,
728 CWORD, CWORD, CWORD, CWORD,
729 CWORD, CWORD, CWORD, CWORD,
730 CWORD, CWORD, CWORD, CWORD,
731 CWORD, CWORD, CWORD, CWORD,
732 CWORD, CWORD, CWORD, CWORD,
733 CWORD, CWORD, CWORD, CWORD,
734 CWORD, CWORD, CWORD, CWORD,
735 CWORD, CWORD, CWORD, CWORD,
736 CWORD, CWORD, CWORD, CSPCL,
737 CNL, CWORD, CWORD, CWORD,
738 CWORD, CWORD, CWORD, CWORD,
739 CWORD, CWORD, CWORD, CWORD,
740 CWORD, CWORD, CWORD, CWORD,
741 CWORD, CWORD, CWORD, CWORD,
742 CWORD, CWORD, CSPCL, CWORD,
743 CDQUOTE, CWORD, CVAR, CWORD,
744 CSPCL, CSQUOTE, CSPCL, CSPCL,
745 CWORD, CWORD, CWORD, CWORD,
746 CWORD, CWORD, CWORD, CWORD,
747 CWORD, CWORD, CWORD, CWORD,
748 CWORD, CWORD, CWORD, CWORD,
749 CWORD, CSPCL, CSPCL, CWORD,
750 CSPCL, CWORD, CWORD, CWORD,
751 CWORD, CWORD, CWORD, CWORD,
752 CWORD, CWORD, CWORD, CWORD,
753 CWORD, CWORD, CWORD, CWORD,
754 CWORD, CWORD, CWORD, CWORD,
755 CWORD, CWORD, CWORD, CWORD,
756 CWORD, CWORD, CWORD, CWORD,
757 CWORD, CWORD, CBACK, CWORD,
758 CWORD, CWORD, CBQUOTE, CWORD,
759 CWORD, CWORD, CWORD, CWORD,
760 CWORD, CWORD, CWORD, CWORD,
761 CWORD, CWORD, CWORD, CWORD,
762 CWORD, CWORD, CWORD, CWORD,
763 CWORD, CWORD, CWORD, CWORD,
764 CWORD, CWORD, CWORD, CWORD,
765 CWORD, CWORD, CSPCL, CENDVAR,
766 CWORD
767};
768
769/* syntax table used when in double quotes */
770static const char dqsyntax[257] = {
771 CENDFILE, CIGN, CWORD, CCTL,
772 CCTL, CCTL, CCTL, CCTL,
773 CCTL, CCTL, CCTL, CWORD,
774 CWORD, CWORD, CWORD, CWORD,
775 CWORD, CWORD, CWORD, CWORD,
776 CWORD, CWORD, CWORD, CWORD,
777 CWORD, CWORD, CWORD, CWORD,
778 CWORD, CWORD, CWORD, CWORD,
779 CWORD, CWORD, CWORD, CWORD,
780 CWORD, CWORD, CWORD, CWORD,
781 CWORD, CWORD, CWORD, CWORD,
782 CWORD, CWORD, CWORD, CWORD,
783 CWORD, CWORD, CWORD, CWORD,
784 CWORD, CWORD, CWORD, CWORD,
785 CWORD, CWORD, CWORD, CWORD,
786 CWORD, CWORD, CWORD, CWORD,
787 CWORD, CWORD, CWORD, CWORD,
788 CWORD, CWORD, CWORD, CWORD,
789 CWORD, CWORD, CWORD, CWORD,
790 CWORD, CWORD, CWORD, CWORD,
791 CWORD, CWORD, CWORD, CWORD,
792 CWORD, CWORD, CWORD, CWORD,
793 CWORD, CWORD, CWORD, CWORD,
794 CWORD, CWORD, CWORD, CWORD,
795 CWORD, CWORD, CWORD, CWORD,
796 CWORD, CWORD, CWORD, CWORD,
797 CWORD, CWORD, CWORD, CWORD,
798 CWORD, CWORD, CWORD, CWORD,
799 CWORD, CWORD, CWORD, CWORD,
800 CWORD, CWORD, CWORD, CWORD,
801 CWORD, CWORD, CWORD, CWORD,
802 CWORD, CWORD, CWORD, CWORD,
803 CWORD, CWORD, CWORD, CWORD,
804 CWORD, CWORD, CWORD, CWORD,
805 CWORD, CWORD, CWORD, CWORD,
806 CNL, CWORD, CWORD, CWORD,
807 CWORD, CWORD, CWORD, CWORD,
808 CWORD, CWORD, CWORD, CWORD,
809 CWORD, CWORD, CWORD, CWORD,
810 CWORD, CWORD, CWORD, CWORD,
811 CWORD, CWORD, CWORD, CCTL,
812 CENDQUOTE,CWORD, CVAR, CWORD,
813 CWORD, CWORD, CWORD, CWORD,
814 CCTL, CWORD, CWORD, CCTL,
815 CWORD, CCTL, CWORD, CWORD,
816 CWORD, CWORD, CWORD, CWORD,
817 CWORD, CWORD, CWORD, CWORD,
818 CCTL, CWORD, CWORD, CCTL,
819 CWORD, CCTL, CWORD, CWORD,
820 CWORD, CWORD, CWORD, CWORD,
821 CWORD, CWORD, CWORD, CWORD,
822 CWORD, CWORD, CWORD, CWORD,
823 CWORD, CWORD, CWORD, CWORD,
824 CWORD, CWORD, CWORD, CWORD,
825 CWORD, CWORD, CWORD, CWORD,
826 CWORD, CCTL, CBACK, CCTL,
827 CWORD, CWORD, CBQUOTE, CWORD,
828 CWORD, CWORD, CWORD, CWORD,
829 CWORD, CWORD, CWORD, CWORD,
830 CWORD, CWORD, CWORD, CWORD,
831 CWORD, CWORD, CWORD, CWORD,
832 CWORD, CWORD, CWORD, CWORD,
833 CWORD, CWORD, CWORD, CWORD,
834 CWORD, CWORD, CWORD, CENDVAR,
835 CCTL
836};
837 699
838/* syntax table used when in single quotes */ 700#ifdef ASH_OPTIMIZE_FOR_SIZE
839static const char sqsyntax[257] = { 701#define USE_SIT_FUNCTION
840 CENDFILE, CIGN, CWORD, CCTL, 702#endif
841 CCTL, CCTL, CCTL, CCTL, 703
842 CCTL, CCTL, CCTL, CWORD, 704/* number syntax index */
843 CWORD, CWORD, CWORD, CWORD, 705#define BASESYNTAX 0 /* not in quotes */
844 CWORD, CWORD, CWORD, CWORD, 706#define DQSYNTAX 1 /* in double quotes */
845 CWORD, CWORD, CWORD, CWORD, 707#define SQSYNTAX 2 /* in single quotes */
846 CWORD, CWORD, CWORD, CWORD, 708#define ARISYNTAX 3 /* in arithmetic */
847 CWORD, CWORD, CWORD, CWORD, 709
848 CWORD, CWORD, CWORD, CWORD, 710static const char S_I_T[][4] = {
849 CWORD, CWORD, CWORD, CWORD, 711 /* 0 */ { CSPCL, CIGN, CIGN, CIGN }, /* PEOA */
850 CWORD, CWORD, CWORD, CWORD, 712 /* 1 */ { CSPCL, CWORD, CWORD, CWORD }, /* ' ' */
851 CWORD, CWORD, CWORD, CWORD, 713 /* 2 */ { CNL, CNL, CNL, CNL }, /* \n */
852 CWORD, CWORD, CWORD, CWORD, 714 /* 3 */ { CWORD, CCTL, CCTL, CWORD }, /* !*-/:=?[]~ */
853 CWORD, CWORD, CWORD, CWORD, 715 /* 4 */ { CDQUOTE, CENDQUOTE, CWORD, CDQUOTE }, /* '"' */
854 CWORD, CWORD, CWORD, CWORD, 716 /* 5 */ { CVAR, CVAR, CWORD, CVAR }, /* $ */
855 CWORD, CWORD, CWORD, CWORD, 717 /* 6 */ { CSQUOTE, CWORD, CENDQUOTE, CSQUOTE }, /* "'" */
856 CWORD, CWORD, CWORD, CWORD, 718 /* 7 */ { CSPCL, CWORD, CWORD, CLP }, /* ( */
857 CWORD, CWORD, CWORD, CWORD, 719 /* 8 */ { CSPCL, CWORD, CWORD, CRP }, /* ) */
858 CWORD, CWORD, CWORD, CWORD, 720 /* 9 */ { CBACK, CBACK, CCTL, CBACK }, /* \ */
859 CWORD, CWORD, CWORD, CWORD, 721 /* 10 */ { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* ` */
860 CWORD, CWORD, CWORD, CWORD, 722 /* 11 */ { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* } */
861 CWORD, CWORD, CWORD, CWORD, 723#ifndef USE_SIT_FUNCTION
862 CWORD, CWORD, CWORD, CWORD, 724 /* 12 */ { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* PEOF */
863 CWORD, CWORD, CWORD, CWORD, 725 /* 13 */ { CWORD, CWORD, CWORD, CWORD }, /* 0-9A-Za-z */
864 CWORD, CWORD, CWORD, CWORD, 726 /* 14 */ { CCTL, CCTL, CCTL, CCTL } /* CTLESC ... */
865 CWORD, CWORD, CWORD, CWORD, 727#endif
866 CWORD, CWORD, CWORD, CWORD,
867 CWORD, CWORD, CWORD, CWORD,
868 CWORD, CWORD, CWORD, CWORD,
869 CWORD, CWORD, CWORD, CWORD,
870 CWORD, CWORD, CWORD, CWORD,
871 CWORD, CWORD, CWORD, CWORD,
872 CWORD, CWORD, CWORD, CWORD,
873 CWORD, CWORD, CWORD, CWORD,
874 CWORD, CWORD, CWORD, CWORD,
875 CNL, CWORD, CWORD, CWORD,
876 CWORD, CWORD, CWORD, CWORD,
877 CWORD, CWORD, CWORD, CWORD,
878 CWORD, CWORD, CWORD, CWORD,
879 CWORD, CWORD, CWORD, CWORD,
880 CWORD, CWORD, CWORD, CCTL,
881 CWORD, CWORD, CWORD, CWORD,
882 CWORD, CENDQUOTE,CWORD, CWORD,
883 CCTL, CWORD, CWORD, CCTL,
884 CWORD, CCTL, CWORD, CWORD,
885 CWORD, CWORD, CWORD, CWORD,
886 CWORD, CWORD, CWORD, CWORD,
887 CCTL, CWORD, CWORD, CCTL,
888 CWORD, CCTL, CWORD, CWORD,
889 CWORD, CWORD, CWORD, CWORD,
890 CWORD, CWORD, CWORD, CWORD,
891 CWORD, CWORD, CWORD, CWORD,
892 CWORD, CWORD, CWORD, CWORD,
893 CWORD, CWORD, CWORD, CWORD,
894 CWORD, CWORD, CWORD, CWORD,
895 CWORD, CCTL, CCTL, CCTL,
896 CWORD, CWORD, CWORD, CWORD,
897 CWORD, CWORD, CWORD, CWORD,
898 CWORD, CWORD, CWORD, CWORD,
899 CWORD, CWORD, CWORD, CWORD,
900 CWORD, CWORD, CWORD, CWORD,
901 CWORD, CWORD, CWORD, CWORD,
902 CWORD, CWORD, CWORD, CWORD,
903 CWORD, CWORD, CWORD, CWORD,
904 CCTL
905};
906
907/* syntax table used when in arithmetic */
908static const char arisyntax[257] = {
909 CENDFILE, CIGN, CWORD, CCTL,
910 CCTL, CCTL, CCTL, CCTL,
911 CCTL, CCTL, CCTL, CWORD,
912 CWORD, CWORD, CWORD, CWORD,
913 CWORD, CWORD, CWORD, CWORD,
914 CWORD, CWORD, CWORD, CWORD,
915 CWORD, CWORD, CWORD, CWORD,
916 CWORD, CWORD, CWORD, CWORD,
917 CWORD, CWORD, CWORD, CWORD,
918 CWORD, CWORD, CWORD, CWORD,
919 CWORD, CWORD, CWORD, CWORD,
920 CWORD, CWORD, CWORD, CWORD,
921 CWORD, CWORD, CWORD, CWORD,
922 CWORD, CWORD, CWORD, CWORD,
923 CWORD, CWORD, CWORD, CWORD,
924 CWORD, CWORD, CWORD, CWORD,
925 CWORD, CWORD, CWORD, CWORD,
926 CWORD, CWORD, CWORD, CWORD,
927 CWORD, CWORD, CWORD, CWORD,
928 CWORD, CWORD, CWORD, CWORD,
929 CWORD, CWORD, CWORD, CWORD,
930 CWORD, CWORD, CWORD, CWORD,
931 CWORD, CWORD, CWORD, CWORD,
932 CWORD, CWORD, CWORD, CWORD,
933 CWORD, CWORD, CWORD, CWORD,
934 CWORD, CWORD, CWORD, CWORD,
935 CWORD, CWORD, CWORD, CWORD,
936 CWORD, CWORD, CWORD, CWORD,
937 CWORD, CWORD, CWORD, CWORD,
938 CWORD, CWORD, CWORD, CWORD,
939 CWORD, CWORD, CWORD, CWORD,
940 CWORD, CWORD, CWORD, CWORD,
941 CWORD, CWORD, CWORD, CWORD,
942 CWORD, CWORD, CWORD, CWORD,
943 CWORD, CWORD, CWORD, CWORD,
944 CNL, CWORD, CWORD, CWORD,
945 CWORD, CWORD, CWORD, CWORD,
946 CWORD, CWORD, CWORD, CWORD,
947 CWORD, CWORD, CWORD, CWORD,
948 CWORD, CWORD, CWORD, CWORD,
949 CWORD, CWORD, CWORD, CWORD,
950 CDQUOTE, CWORD, CVAR, CWORD,
951 CWORD, CSQUOTE, CLP, CRP,
952 CWORD, CWORD, CWORD, CWORD,
953 CWORD, CWORD, CWORD, CWORD,
954 CWORD, CWORD, CWORD, CWORD,
955 CWORD, CWORD, CWORD, CWORD,
956 CWORD, CWORD, CWORD, CWORD,
957 CWORD, CWORD, CWORD, CWORD,
958 CWORD, CWORD, CWORD, CWORD,
959 CWORD, CWORD, CWORD, CWORD,
960 CWORD, CWORD, CWORD, CWORD,
961 CWORD, CWORD, CWORD, CWORD,
962 CWORD, CWORD, CWORD, CWORD,
963 CWORD, CWORD, CWORD, CWORD,
964 CWORD, CWORD, CBACK, CWORD,
965 CWORD, CWORD, CBQUOTE, CWORD,
966 CWORD, CWORD, CWORD, CWORD,
967 CWORD, CWORD, CWORD, CWORD,
968 CWORD, CWORD, CWORD, CWORD,
969 CWORD, CWORD, CWORD, CWORD,
970 CWORD, CWORD, CWORD, CWORD,
971 CWORD, CWORD, CWORD, CWORD,
972 CWORD, CWORD, CWORD, CENDVAR,
973 CWORD
974}; 728};
975 729
976/* character classification table */ 730#ifdef USE_SIT_FUNCTION
977static const char is_type[257] = {
978 0, 0, 0, 0,
979 0, 0, 0, 0,
980 0, 0, 0, 0,
981 0, 0, 0, 0,
982 0, 0, 0, 0,
983 0, 0, 0, 0,
984 0, 0, 0, 0,
985 0, 0, 0, 0,
986 0, 0, 0, 0,
987 0, 0, 0, 0,
988 0, 0, 0, 0,
989 0, 0, 0, 0,
990 0, 0, 0, 0,
991 0, 0, 0, 0,
992 0, 0, 0, 0,
993 0, 0, 0, 0,
994 0, 0, 0, 0,
995 0, 0, 0, 0,
996 0, 0, 0, 0,
997 0, 0, 0, 0,
998 0, 0, 0, 0,
999 0, 0, 0, 0,
1000 0, 0, 0, 0,
1001 0, 0, 0, 0,
1002 0, 0, 0, 0,
1003 0, 0, 0, 0,
1004 0, 0, 0, 0,
1005 0, 0, 0, 0,
1006 0, 0, 0, 0,
1007 0, 0, 0, 0,
1008 0, 0, 0, 0,
1009 0, 0, 0, 0,
1010 0, 0, 0, 0,
1011 0, 0, 0, 0,
1012 0, 0, 0, 0,
1013 0, 0, 0, 0,
1014 0, 0, 0, 0,
1015 0, 0, 0, 0,
1016 0, 0, 0, 0,
1017 0, 0, 0, 0,
1018 0, 0, 0, ISSPECL,
1019 0, ISSPECL, ISSPECL, 0,
1020 0, 0, 0, 0,
1021 ISSPECL, 0, 0, ISSPECL,
1022 0, 0, ISDIGIT, ISDIGIT,
1023 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1024 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1025 0, 0, 0, 0,
1026 0, ISSPECL, ISSPECL, ISUPPER,
1027 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1028 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1029 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1030 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1031 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1032 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1033 ISUPPER, 0, 0, 0,
1034 0, ISUNDER, 0, ISLOWER,
1035 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1036 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1037 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1038 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1039 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1040 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1041 ISLOWER, 0, 0, 0,
1042 0
1043};
1044 731
1045/* Array indicating which tokens mark the end of a list */ 732#define U_C(c) ((unsigned char)(c))
1046static const char tokendlist[] = {
1047 1,
1048 0,
1049 0,
1050 0,
1051 0,
1052 0,
1053 0,
1054 0,
1055 1,
1056 1,
1057 1,
1058 0,
1059 0,
1060 0,
1061 0,
1062 0,
1063 1,
1064 1,
1065 1,
1066 1,
1067 1,
1068 1,
1069 0,
1070 0,
1071 0,
1072 1,
1073 0,
1074 0,
1075 0,
1076 1,
1077};
1078 733
1079static const char *const tokname[] = { 734static int SIT(int c, int syntax)
1080 "end of file", 735{
1081 "newline", 736 static const char spec_symbls[]="\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
1082 "\";\"", 737 static const char syntax_index_table [] = {
1083 "\"&\"", 738 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
1084 "\"&&\"", 739 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
1085 "\"||\"", 740 3, 1, 3, 3, 9, 3,10, 1, /* "=>?[\\]`|" */
1086 "\"|\"", 741 11,3 }; /* "}~" */
1087 "\"(\"", 742 const char *s;
1088 "\")\"", 743 int indx;
1089 "\";;\"", 744
1090 "\"`\"", 745 if(c==PEOF) /* 2^8+2 */
1091 "redirection", 746 return CENDFILE;
1092 "word", 747 if(c==PEOA) /* 2^8+1 */
1093 "assignment", 748 indx = 0;
1094 "\"!\"", 749 else if(U_C(c)>=U_C(CTLESC) && U_C(c)<=U_C(CTLQUOTEMARK))
1095 "\"case\"", 750 return CCTL;
1096 "\"do\"", 751 else {
1097 "\"done\"", 752 s = strchr(spec_symbls, c);
1098 "\"elif\"", 753 if(s==0)
1099 "\"else\"", 754 return CWORD;
1100 "\"esac\"", 755 indx = syntax_index_table[(s-spec_symbls)];
1101 "\"fi\"", 756 }
1102 "\"for\"", 757 return S_I_T[indx][syntax];
1103 "\"if\"", 758}
1104 "\"in\"", 759
1105 "\"then\"", 760#else /* USE_SIT_FUNCTION */
1106 "\"until\"", 761
1107 "\"while\"", 762#define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
1108 "\"{\"", 763
1109 "\"}\"", 764#define CSPCL_CIGN_CIGN_CIGN 0
765#define CSPCL_CWORD_CWORD_CWORD 1
766#define CNL_CNL_CNL_CNL 2
767#define CWORD_CCTL_CCTL_CWORD 3
768#define CDQUOTE_CENDQUOTE_CWORD_CDQUOTE 4
769#define CVAR_CVAR_CWORD_CVAR 5
770#define CSQUOTE_CWORD_CENDQUOTE_CSQUOTE 6
771#define CSPCL_CWORD_CWORD_CLP 7
772#define CSPCL_CWORD_CWORD_CRP 8
773#define CBACK_CBACK_CCTL_CBACK 9
774#define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
775#define CENDVAR_CENDVAR_CWORD_CENDVAR 11
776#define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
777#define CWORD_CWORD_CWORD_CWORD 13
778#define CCTL_CCTL_CCTL_CCTL 14
779
780static const char syntax_index_table[258] = {
781 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
782 /* 0 -130 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
783 /* 1 -129 PEOA */ CSPCL_CIGN_CIGN_CIGN,
784 /* 2 -128 0xff */ CWORD_CWORD_CWORD_CWORD,
785 /* 3 -127 */ CCTL_CCTL_CCTL_CCTL, /* CTLQUOTEMARK */
786 /* 4 -126 */ CCTL_CCTL_CCTL_CCTL,
787 /* 5 -125 */ CCTL_CCTL_CCTL_CCTL,
788 /* 6 -124 */ CCTL_CCTL_CCTL_CCTL,
789 /* 7 -123 */ CCTL_CCTL_CCTL_CCTL,
790 /* 8 -122 */ CCTL_CCTL_CCTL_CCTL,
791 /* 9 -121 */ CCTL_CCTL_CCTL_CCTL,
792 /* 10 -120 */ CCTL_CCTL_CCTL_CCTL, /* CTLESC */
793 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
794 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
795 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
796 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
797 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
798 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
799 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
800 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
801 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
802 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
803 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
804 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
805 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
806 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
807 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
808 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
809 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
810 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
811 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
812 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
813 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
814 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
815 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
816 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
817 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
818 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
819 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
820 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
821 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
822 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
823 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
824 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
825 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
826 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
827 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
828 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
829 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
830 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
831 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
832 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
833 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
834 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
835 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
836 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
837 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
838 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
839 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
840 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
841 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
842 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
843 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
844 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
845 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
846 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
847 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
848 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
849 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
850 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
851 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
852 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
853 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
854 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
855 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
856 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
857 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
858 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
859 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
860 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
861 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
862 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
863 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
864 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
865 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
866 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
867 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
868 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
869 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
870 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
871 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
872 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
873 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
874 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
875 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
876 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
877 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
878 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
879 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
880 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
881 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
882 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
883 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
884 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
885 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
886 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
887 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
888 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
889 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
890 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
891 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
892 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
893 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
894 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
895 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
896 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
897 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
898 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
899 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
900 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
901 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
902 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
903 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
904 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
905 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
906 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
907 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
908 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
909 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
910 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
911 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
912 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
913 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
914 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
915 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
916 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
917 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
918 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
919 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
920 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
921 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
922 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
923 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
924 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
925 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
926 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
927 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
928 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
929 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
930 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
931 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
932 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
933 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
934 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
935 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
936 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
937 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
938 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
939 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
940 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
941 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
942 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
943 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
944 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
945 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
946 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CDQUOTE,
947 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
948 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
949 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
950 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
951 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CSQUOTE,
952 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
953 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
954 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
955 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
956 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
957 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
958 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
959 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
960 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
961 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
962 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
963 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
964 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
965 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
966 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
967 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
968 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
969 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
970 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
971 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
972 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
973 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
974 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
975 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
976 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
977 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
978 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
979 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
980 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
981 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
982 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
983 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
984 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
985 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
986 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
987 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
988 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
989 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
990 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
991 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
992 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
993 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
994 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
995 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
996 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
997 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
998 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
999 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
1000 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
1001 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
1002 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
1003 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
1004 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
1005 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
1006 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
1007 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
1008 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1009 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
1010 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
1011 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
1012 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
1013 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
1014 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
1015 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
1016 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
1017 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
1018 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
1019 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
1020 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
1021 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
1022 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
1023 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
1024 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
1025 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
1026 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
1027 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
1028 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
1029 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
1030 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
1031 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
1032 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
1033 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
1034 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
1035 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
1036 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
1037 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1038 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
1039 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
1110}; 1040};
1111 1041
1042#endif /* USE_SIT_FUNCTION */
1043
1044
1045/* first char is indicating which tokens mark the end of a list */
1046static const char *const tokname_array[] = {
1047 "\1end of file",
1048 "\0newline",
1049 "\0redirection",
1050 "\0word",
1051 "\0assignment",
1052 "\0;",
1053 "\0&",
1054 "\0&&",
1055 "\0||",
1056 "\0|",
1057 "\0(",
1058 "\1)",
1059 "\1;;",
1060 "\1`",
1112#define KWDOFFSET 14 1061#define KWDOFFSET 14
1113 1062 /* the following are keywords */
1114static const char *const parsekwd[] = { 1063 "\0!",
1115 "!", 1064 "\0case",
1116 "case", 1065 "\1do",
1117 "do", 1066 "\1done",
1118 "done", 1067 "\1elif",
1119 "elif", 1068 "\1else",
1120 "else", 1069 "\1esac",
1121 "esac", 1070 "\1fi",
1122 "fi", 1071 "\0for",
1123 "for", 1072 "\0if",
1124 "if", 1073 "\0in",
1125 "in", 1074 "\1then",
1126 "then", 1075 "\0until",
1127 "until", 1076 "\0while",
1128 "while", 1077 "\0{",
1129 "{", 1078 "\1}",
1130 "}"
1131}; 1079};
1132 1080
1081static const char *tokname(int tok)
1082{
1083 static char buf[16];
1084
1085 if(tok>=TSEMI)
1086 buf[0] = '"';
1087 sprintf(buf+(tok>=TSEMI), "%s%c",
1088 tokname_array[tok]+1, (tok>=TSEMI ? '"' : 0));
1089 return buf;
1090}
1133 1091
1134static int plinno = 1; /* input line number */ 1092static int plinno = 1; /* input line number */
1135 1093
@@ -1562,8 +1520,8 @@ __lookupalias(const char *name) {
1562 1520
1563#ifdef ASH_MATH_SUPPORT 1521#ifdef ASH_MATH_SUPPORT
1564/* The generated file arith.c has been replaced with a custom hand 1522/* The generated file arith.c has been replaced with a custom hand
1565 * written implementation written by Aaron Lehmann <aaronl@vitelus.com>. 1523 * written implementation written by Aaron Lehmann <aaronl@vitelus.com>.
1566 * This is now part of libbb, so that it can be used by all the shells 1524 * This is now part of libbb, so that it can be used by all the shells
1567 * in busybox. */ 1525 * in busybox. */
1568#define ARITH_NUM 257 1526#define ARITH_NUM 257
1569#define ARITH_LPAREN 258 1527#define ARITH_LPAREN 258
@@ -1744,7 +1702,7 @@ static const struct builtincmd builtincmds[] = {
1744}; 1702};
1745#define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) ) 1703#define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) )
1746 1704
1747static const struct builtincmd *DOTCMD = &builtincmds[0]; 1705#define DOTCMD &builtincmds[0]
1748static struct builtincmd *BLTINCMD; 1706static struct builtincmd *BLTINCMD;
1749static struct builtincmd *EXECCMD; 1707static struct builtincmd *EXECCMD;
1750static struct builtincmd *EVALCMD; 1708static struct builtincmd *EVALCMD;
@@ -2165,7 +2123,7 @@ exverror(int cond, const char *msg, va_list ap)
2165} 2123}
2166 2124
2167 2125
2168static void 2126static void
2169error(const char *msg, ...) 2127error(const char *msg, ...)
2170{ 2128{
2171 va_list ap; 2129 va_list ap;
@@ -3690,7 +3648,7 @@ padvance(const char **path, const char *name)
3690static int 3648static int
3691pstrcmp(const void *a, const void *b) 3649pstrcmp(const void *a, const void *b)
3692{ 3650{
3693 return strcmp((const char *) a, *(const char *const *) b); 3651 return strcmp((const char *) a, (*(const char *const *) b) + 1);
3694} 3652}
3695 3653
3696/* 3654/*
@@ -3700,8 +3658,9 @@ pstrcmp(const void *a, const void *b)
3700static const char *const * 3658static const char *const *
3701findkwd(const char *s) 3659findkwd(const char *s)
3702{ 3660{
3703 return bsearch(s, parsekwd, sizeof(parsekwd) / sizeof(const char *), 3661 return bsearch(s, tokname_array + KWDOFFSET,
3704 sizeof(const char *), pstrcmp); 3662 (sizeof(tokname_array)/sizeof(const char *)) - KWDOFFSET,
3663 sizeof(const char *), pstrcmp);
3705} 3664}
3706 3665
3707 3666
@@ -4228,7 +4187,7 @@ delete_cmd_entry() {
4228 4187
4229 4188
4230 4189
4231static const short nodesize[26] = { 4190static const unsigned char nodesize[26] = {
4232 ALIGN(sizeof (struct nbinary)), 4191 ALIGN(sizeof (struct nbinary)),
4233 ALIGN(sizeof (struct ncmd)), 4192 ALIGN(sizeof (struct ncmd)),
4234 ALIGN(sizeof (struct npipe)), 4193 ALIGN(sizeof (struct npipe)),
@@ -4412,7 +4371,7 @@ static char *exptilde (char *, int);
4412static void expbackq (union node *, int, int); 4371static void expbackq (union node *, int, int);
4413static int subevalvar (char *, char *, int, int, int, int, int); 4372static int subevalvar (char *, char *, int, int, int, int, int);
4414static int varisset (char *, int); 4373static int varisset (char *, int);
4415static void strtodest (const char *, const char *, int); 4374static void strtodest (const char *, int, int);
4416static void varvalue (char *, int, int); 4375static void varvalue (char *, int, int);
4417static void recordregion (int, int, int); 4376static void recordregion (int, int, int);
4418static void removerecordregions (int); 4377static void removerecordregions (int);
@@ -4916,7 +4875,7 @@ expbackq(cmd, quoted, flag)
4916 struct nodelist *volatile saveargbackq; 4875 struct nodelist *volatile saveargbackq;
4917 char lastc; 4876 char lastc;
4918 int startloc = dest - stackblock(); 4877 int startloc = dest - stackblock();
4919 char const *syntax = quoted? DQSYNTAX : BASESYNTAX; 4878 int syntax = quoted ? DQSYNTAX : BASESYNTAX;
4920 volatile int saveherefd; 4879 volatile int saveherefd;
4921 int quotes = flag & (EXP_FULL | EXP_CASE); 4880 int quotes = flag & (EXP_FULL | EXP_CASE);
4922 struct jmploc jmploc; 4881 struct jmploc jmploc;
@@ -4973,7 +4932,7 @@ err1:
4973 } 4932 }
4974 lastc = *p++; 4933 lastc = *p++;
4975 if (lastc != '\0') { 4934 if (lastc != '\0') {
4976 if (quotes && syntax[(int)lastc] == CCTL) 4935 if (quotes && SIT(lastc, syntax) == CCTL)
4977 STPUTC(CTLESC, dest); 4936 STPUTC(CTLESC, dest);
4978 STPUTC(lastc, dest); 4937 STPUTC(lastc, dest);
4979 } 4938 }
@@ -5174,13 +5133,10 @@ varisset(name, nulok)
5174 */ 5133 */
5175 5134
5176static void 5135static void
5177strtodest(p, syntax, quotes) 5136strtodest(const char *p, int syntax, int quotes)
5178 const char *p;
5179 const char *syntax;
5180 int quotes;
5181{ 5137{
5182 while (*p) { 5138 while (*p) {
5183 if (quotes && syntax[(int) *p] == CCTL) 5139 if (quotes && SIT(*p,syntax) == CCTL)
5184 STPUTC(CTLESC, expdest); 5140 STPUTC(CTLESC, expdest);
5185 STPUTC(*p++, expdest); 5141 STPUTC(*p++, expdest);
5186 } 5142 }
@@ -5191,10 +5147,7 @@ strtodest(p, syntax, quotes)
5191 */ 5147 */
5192 5148
5193static void 5149static void
5194varvalue(name, quoted, flags) 5150varvalue(char *name, int quoted, int flags)
5195 char *name;
5196 int quoted;
5197 int flags;
5198{ 5151{
5199 int num; 5152 int num;
5200 char *p; 5153 char *p;
@@ -5202,7 +5155,7 @@ varvalue(name, quoted, flags)
5202 int sep; 5155 int sep;
5203 int sepq = 0; 5156 int sepq = 0;
5204 char **ap; 5157 char **ap;
5205 char const *syntax; 5158 int syntax;
5206 int allow_split = flags & EXP_FULL; 5159 int allow_split = flags & EXP_FULL;
5207 int quotes = flags & (EXP_FULL | EXP_CASE); 5160 int quotes = flags & (EXP_FULL | EXP_CASE);
5208 5161
@@ -5237,7 +5190,7 @@ numvar:
5237 case '*': 5190 case '*':
5238 sep = ifsset() ? ifsval()[0] : ' '; 5191 sep = ifsset() ? ifsval()[0] : ' ';
5239 if (quotes) { 5192 if (quotes) {
5240 sepq = syntax[(int) sep] == CCTL; 5193 sepq = SIT(sep,syntax) == CCTL;
5241 } 5194 }
5242param: 5195param:
5243 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { 5196 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
@@ -5572,7 +5525,7 @@ expmeta(enddir, name)
5572 break; 5525 break;
5573 } 5526 }
5574 } 5527 }
5575 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) { 5528 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) {
5576 metaflag = 1; 5529 metaflag = 1;
5577 } else if (*p == '\0') 5530 } else if (*p == '\0')
5578 break; 5531 break;
@@ -7341,10 +7294,219 @@ cmdputs(const char *s)
7341 cmdnextc = q; 7294 cmdnextc = q;
7342} 7295}
7343 7296
7297//#define CMDTXT_TABLE
7298#ifdef CMDTXT_TABLE
7299/*
7300 * To collect a lot of redundant code in cmdtxt() case statements, we
7301 * implement a mini language here. Each type of node struct has an
7302 * associated instruction sequence that operates on its members via
7303 * their offsets. The instruction are pack in unsigned chars with
7304 * format IIDDDDDE where the bits are
7305 * I : part of the instruction opcode, which are
7306 * 00 : member is a pointer to another node -- process it recursively
7307 * 40 : member is a pointer to a char string -- output it
7308 * 80 : output the string whose index is stored in the data field
7309 * CC : flag signaling that this case needs external processing
7310 * D : data - either the (shifted) index of a fixed string to output or
7311 * the actual offset of the member to operate on in the struct
7312 * (since we assume bit 0 is set, the offset is not shifted)
7313 * E : flag signaling end of instruction sequence
7314 *
7315 * WARNING: In order to handle larger offsets for 64bit archs, this code
7316 * assumes that no offset can be an odd number and stores the
7317 * end-of-instructions flag in bit 0.
7318 */
7319
7320#define CMDTXT_NOMORE 0x01 /* NOTE: no offset should be odd */
7321#define CMDTXT_CHARPTR 0x40
7322#define CMDTXT_STRING 0x80
7323#define CMDTXT_SPECIAL 0xC0
7324#define CMDTXT_OFFSETMASK 0x3E
7325
7326static const char * const cmdtxt_strings[] = {
7327 /* 0 1 2 3 4 5 6 7 */
7328 "; ", "(", ")", " && ", " || ", "if ", "; then ", "...",
7329 /* 8 9 10 11 12 13 */
7330 "while ", "; do ", "; done", "until ", "for ", " in ...",
7331 /* 14 15 16 17 */
7332 "case ", "???", "() ...", "<<..."
7333};
7334
7335static const char * const redir_strings[] = {
7336 ">", "<", "<>", ">>", ">|", ">&", "<&"
7337};
7338
7339static const unsigned char cmdtxt_ops[] = {
7340#define CMDTXT_NSEMI 0
7341 offsetof(union node, nbinary.ch1),
7342 0|CMDTXT_STRING,
7343 offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE,
7344#define CMDTXT_NCMD (CMDTXT_NSEMI + 3)
7345#define CMDTXT_NPIPE (CMDTXT_NCMD)
7346#define CMDTXT_NCASE (CMDTXT_NCMD)
7347#define CMDTXT_NTO (CMDTXT_NCMD)
7348#define CMDTXT_NFROM (CMDTXT_NCMD)
7349#define CMDTXT_NFROMTO (CMDTXT_NCMD)
7350#define CMDTXT_NAPPEND (CMDTXT_NCMD)
7351#define CMDTXT_NTOOV (CMDTXT_NCMD)
7352#define CMDTXT_NTOFD (CMDTXT_NCMD)
7353#define CMDTXT_NFROMFD (CMDTXT_NCMD)
7354 CMDTXT_SPECIAL,
7355#define CMDTXT_NREDIR (CMDTXT_NPIPE + 1)
7356#define CMDTXT_NBACKGND (CMDTXT_NREDIR)
7357 offsetof(union node, nredir.n)|CMDTXT_NOMORE,
7358#define CMDTXT_NSUBSHELL (CMDTXT_NBACKGND + 1)
7359 (1*2)|CMDTXT_STRING,
7360 offsetof(union node, nredir.n),
7361 (2*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7362#define CMDTXT_NAND (CMDTXT_NSUBSHELL + 3)
7363 offsetof(union node, nbinary.ch1),
7364 (3*2)|CMDTXT_STRING,
7365 offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE,
7366#define CMDTXT_NOR (CMDTXT_NAND + 3)
7367 offsetof(union node, nbinary.ch1),
7368 (4*2)|CMDTXT_STRING,
7369 offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE,
7370#define CMDTXT_NIF (CMDTXT_NOR + 3)
7371 (5*2)|CMDTXT_STRING,
7372 offsetof(union node, nif.test),
7373 (6*2)|CMDTXT_STRING,
7374 offsetof(union node, nif.ifpart),
7375 (7*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7376#define CMDTXT_NWHILE (CMDTXT_NIF + 5)
7377 (8*2)|CMDTXT_STRING,
7378 offsetof(union node, nbinary.ch1),
7379 (9*2)|CMDTXT_STRING,
7380 offsetof(union node, nbinary.ch2),
7381 (10*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7382#define CMDTXT_NUNTIL (CMDTXT_NWHILE + 5)
7383 (11*2)|CMDTXT_STRING,
7384 offsetof(union node, nbinary.ch1),
7385 (9*2)|CMDTXT_STRING,
7386 offsetof(union node, nbinary.ch2),
7387 (10*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7388#define CMDTXT_NFOR (CMDTXT_NUNTIL + 5)
7389 (12*2)|CMDTXT_STRING,
7390 offsetof(union node, nfor.var)|CMDTXT_CHARPTR,
7391 (13*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7392#define CMDTXT_NCLIST (CMDTXT_NFOR + 3) /* TODO: IS THIS CORRECT??? */
7393#define CMDTXT_NNOT (CMDTXT_NCLIST) /* TODO: IS THIS CORRECT??? */
7394 (15*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7395#define CMDTXT_NDEFUN (CMDTXT_NCLIST + 1)
7396 offsetof(union node, narg.text)|CMDTXT_CHARPTR,
7397 (16*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7398#define CMDTXT_NARG (CMDTXT_NDEFUN + 2)
7399 offsetof(union node, narg.text)|CMDTXT_CHARPTR|CMDTXT_NOMORE,
7400#define CMDTXT_NHERE (CMDTXT_NARG + 1)
7401#define CMDTXT_NXHERE (CMDTXT_NHERE)
7402 (17*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7403};
7404
7405#if CMDTXT_NXHERE != 36
7406#error CMDTXT_NXHERE
7407#endif
7408
7409static const unsigned char cmdtxt_ops_index[26] = {
7410 CMDTXT_NSEMI,
7411 CMDTXT_NCMD,
7412 CMDTXT_NPIPE,
7413 CMDTXT_NREDIR,
7414 CMDTXT_NBACKGND,
7415 CMDTXT_NSUBSHELL,
7416 CMDTXT_NAND,
7417 CMDTXT_NOR,
7418 CMDTXT_NIF,
7419 CMDTXT_NWHILE,
7420 CMDTXT_NUNTIL,
7421 CMDTXT_NFOR,
7422 CMDTXT_NCASE,
7423 CMDTXT_NCLIST,
7424 CMDTXT_NDEFUN,
7425 CMDTXT_NARG,
7426 CMDTXT_NTO,
7427 CMDTXT_NFROM,
7428 CMDTXT_NFROMTO,
7429 CMDTXT_NAPPEND,
7430 CMDTXT_NTOOV,
7431 CMDTXT_NTOFD,
7432 CMDTXT_NFROMFD,
7433 CMDTXT_NHERE,
7434 CMDTXT_NXHERE,
7435 CMDTXT_NNOT,
7436};
7344 7437
7345static void 7438static void
7346cmdtxt(const union node *n) 7439cmdtxt(const union node *n)
7347{ 7440{
7441 const char *p;
7442
7443 if (n == NULL)
7444 return;
7445
7446 p = cmdtxt_ops + (int) cmdtxt_ops_index[n->type];
7447 if ((*p & CMDTXT_SPECIAL) != CMDTXT_SPECIAL) { /* normal case */
7448 do {
7449 if (*p & CMDTXT_STRING) { /* output fixed string */
7450 cmdputs(cmdtxt_strings[((int)(*p & CMDTXT_OFFSETMASK) >> 1)]);
7451 } else if (*p & CMDTXT_CHARPTR) { /* output dynamic string */
7452 cmdputs(((const char *) n) + ((int)(*p & CMDTXT_OFFSETMASK)));
7453 } else { /* output field */
7454 cmdtxt((const union node *)
7455 (((const char *) n) + ((int)(*p & CMDTXT_OFFSETMASK))));
7456 }
7457 } while (!(*p++ & CMDTXT_NOMORE));
7458 } else if (n->type == NCMD) {
7459 union node *np;
7460 for (np = n->ncmd.args ; np ; np = np->narg.next) {
7461 cmdtxt(np);
7462 if (np->narg.next)
7463 cmdputs(spcstr);
7464 }
7465 for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
7466 cmdputs(spcstr);
7467 cmdtxt(np);
7468 }
7469 } else if (n->type == NPIPE) {
7470 struct nodelist *lp;
7471 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
7472 cmdtxt(lp->n);
7473 if (lp->next)
7474 cmdputs(" | ");
7475 }
7476 } else if (n->type == NCASE) {
7477 cmdputs(cmdtxt_strings[14]);
7478 cmdputs(n->ncase.expr->narg.text);
7479 cmdputs(cmdtxt_strings[13]);
7480 } else {
7481#if (NTO != 16) || (NFROM != 17) || (NFROMTO != 18) || (NAPPEND != 19) || (NTOOV != 20) || (NTOFD != 21) || (NFROMFD != 22)
7482#error Assumption violated regarding range and ordering of NTO ... NFROMFD!
7483#endif
7484 char s[2];
7485
7486#ifdef DEBUG
7487 assert((n->type >= NTO) && (n->type <= NFROMFD));
7488#endif
7489
7490 p = redir_strings[n->type - NTO];
7491 if (n->nfile.fd != ('>' == *p)) {
7492 s[0] = n->nfile.fd + '0';
7493 s[1] = '\0';
7494 cmdputs(s);
7495 }
7496 cmdputs(p);
7497 if (n->type >= NTOFD) {
7498 s[0] = n->ndup.dupfd + '0';
7499 s[1] = '\0';
7500 cmdputs(s);
7501 } else {
7502 cmdtxt(n->nfile.fname);
7503 }
7504 }
7505}
7506#else /* CMDTXT_TABLE */
7507static void
7508cmdtxt(const union node *n)
7509{
7348 union node *np; 7510 union node *np;
7349 struct nodelist *lp; 7511 struct nodelist *lp;
7350 const char *p; 7512 const char *p;
@@ -7469,7 +7631,7 @@ redir:
7469 break; 7631 break;
7470 } 7632 }
7471} 7633}
7472 7634#endif
7473 7635
7474static char * 7636static char *
7475commandtext(const union node *n) 7637commandtext(const union node *n)
@@ -7602,27 +7764,17 @@ ash_main(argc, argv)
7602 * exception EXSHELLPROC to clean up before executing 7764 * exception EXSHELLPROC to clean up before executing
7603 * the shell procedure. 7765 * the shell procedure.
7604 */ 7766 */
7605 switch (exception) { 7767 if (exception == EXSHELLPROC) {
7606 case EXSHELLPROC:
7607 rootpid = getpid(); 7768 rootpid = getpid();
7608 rootshell = 1; 7769 rootshell = 1;
7609 minusc = NULL; 7770 minusc = NULL;
7610 state = 3; 7771 state = 3;
7611 break; 7772 } else {
7612 7773 if (exception == EXEXEC) {
7613 case EXEXEC: 7774 exitstatus = exerrno;
7614 exitstatus = exerrno; 7775 } else if (exception == EXERROR) {
7615 break; 7776 exitstatus = 2;
7616 7777 }
7617 case EXERROR:
7618 exitstatus = 2;
7619 break;
7620
7621 default:
7622 break;
7623 }
7624
7625 if (exception != EXSHELLPROC) {
7626 if (state == 0 || iflag == 0 || ! rootshell) 7778 if (state == 0 || iflag == 0 || ! rootshell)
7627 exitshell(exitstatus); 7779 exitshell(exitstatus);
7628 } 7780 }
@@ -7673,14 +7825,14 @@ state2:
7673state3: 7825state3:
7674 state = 4; 7826 state = 4;
7675 if (sflag == 0 || minusc) { 7827 if (sflag == 0 || minusc) {
7676 static int sigs[] = { 7828 static const char sigs[] = {
7677 SIGINT, SIGQUIT, SIGHUP, 7829 SIGINT, SIGQUIT, SIGHUP,
7678#ifdef SIGTSTP 7830#ifdef SIGTSTP
7679 SIGTSTP, 7831 SIGTSTP,
7680#endif 7832#endif
7681 SIGPIPE 7833 SIGPIPE
7682 }; 7834 };
7683#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0])) 7835#define SIGSSIZE ((sizeof(sigs)/sizeof(sigs[0])) - 1) /* trailing nul */
7684 int i; 7836 int i;
7685 7837
7686 for (i = 0; i < SIGSSIZE; i++) 7838 for (i = 0; i < SIGSSIZE; i++)
@@ -7764,8 +7916,8 @@ read_profile(name)
7764 const char *name; 7916 const char *name;
7765{ 7917{
7766 int fd; 7918 int fd;
7767 int xflag_set = 0; 7919 int xflag_save;
7768 int vflag_set = 0; 7920 int vflag_save;
7769 7921
7770 INTOFF; 7922 INTOFF;
7771 if ((fd = open(name, O_RDONLY)) >= 0) 7923 if ((fd = open(name, O_RDONLY)) >= 0)
@@ -7774,19 +7926,15 @@ read_profile(name)
7774 if (fd < 0) 7926 if (fd < 0)
7775 return; 7927 return;
7776 /* -q turns off -x and -v just when executing init files */ 7928 /* -q turns off -x and -v just when executing init files */
7929 /* Note: Might do a little redundant work, but reduces code size. */
7930 xflag_save = xflag;
7931 vflag_save = vflag;
7777 if (qflag) { 7932 if (qflag) {
7778 if (xflag) 7933 vflag = xflag = 0;
7779 xflag = 0, xflag_set = 1;
7780 if (vflag)
7781 vflag = 0, vflag_set = 1;
7782 } 7934 }
7783 cmdloop(0); 7935 cmdloop(0);
7784 if (qflag) { 7936 xflag = xflag_save;
7785 if (xflag_set) 7937 vflag = vflag_save;
7786 xflag = 1;
7787 if (vflag_set)
7788 vflag = 1;
7789 }
7790 popfile(); 7938 popfile();
7791} 7939}
7792 7940
@@ -8089,11 +8237,6 @@ ungrabstackstr(char *s, char *p)
8089 8237
8090#undef rflag 8238#undef rflag
8091 8239
8092//#ifdef __GLIBC__
8093static mode_t getmode(const void *, mode_t);
8094static void *setmode(const char *);
8095//#endif
8096
8097#if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1 8240#if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
8098typedef long rlim_t; 8241typedef long rlim_t;
8099#endif 8242#endif
@@ -8108,9 +8251,7 @@ typedef long rlim_t;
8108 */ 8251 */
8109 8252
8110static int 8253static int
8111readcmd(argc, argv) 8254readcmd(int argc, char **argv)
8112 int argc;
8113 char **argv;
8114{ 8255{
8115 char **ap; 8256 char **ap;
8116 int backslash; 8257 int backslash;
@@ -8132,7 +8273,7 @@ readcmd(argc, argv)
8132 rflag = 1; 8273 rflag = 1;
8133 } 8274 }
8134 if (prompt && isatty(0)) { 8275 if (prompt && isatty(0)) {
8135 putprompt(prompt); 8276 out2str(prompt); /* read without cmdedit */
8136 flushall(); 8277 flushall();
8137 } 8278 }
8138 if (*(ap = argptr) == NULL) 8279 if (*(ap = argptr) == NULL)
@@ -8199,8 +8340,16 @@ umaskcmd(argc, argv)
8199 int argc; 8340 int argc;
8200 char **argv; 8341 char **argv;
8201{ 8342{
8343 static const char permuser[3] = "ugo";
8344 static const char permmode[3] = "rwx";
8345 static const short int permmask[] = {
8346 S_IRUSR, S_IWUSR, S_IXUSR,
8347 S_IRGRP, S_IWGRP, S_IXGRP,
8348 S_IROTH, S_IWOTH, S_IXOTH
8349 };
8350
8202 char *ap; 8351 char *ap;
8203 int mask; 8352 mode_t mask;
8204 int i; 8353 int i;
8205 int symbolic_mode = 0; 8354 int symbolic_mode = 0;
8206 8355
@@ -8215,36 +8364,21 @@ umaskcmd(argc, argv)
8215 8364
8216 if ((ap = *argptr) == NULL) { 8365 if ((ap = *argptr) == NULL) {
8217 if (symbolic_mode) { 8366 if (symbolic_mode) {
8218 char u[4], g[4], o[4]; 8367 char buf[18];
8219 8368 char *p = buf;
8220 i = 0; 8369 for (i=0 ; i<3 ; i++) {
8221 if ((mask & S_IRUSR) == 0) 8370 int j;
8222 u[i++] = 'r'; 8371 *p++ = permuser[i];
8223 if ((mask & S_IWUSR) == 0) 8372 *p++ = '=';
8224 u[i++] = 'w'; 8373 for (j=0 ; j<3 ; j++) {
8225 if ((mask & S_IXUSR) == 0) 8374 if ((mask & permmask[3*i+j]) == 0) {
8226 u[i++] = 'x'; 8375 *p++ = permmode[j];
8227 u[i] = '\0'; 8376 }
8228 8377 }
8229 i = 0; 8378 *p++ = ',';
8230 if ((mask & S_IRGRP) == 0) 8379 }
8231 g[i++] = 'r'; 8380 *--p = 0;
8232 if ((mask & S_IWGRP) == 0) 8381 puts(buf);
8233 g[i++] = 'w';
8234 if ((mask & S_IXGRP) == 0)
8235 g[i++] = 'x';
8236 g[i] = '\0';
8237
8238 i = 0;
8239 if ((mask & S_IROTH) == 0)
8240 o[i++] = 'r';
8241 if ((mask & S_IWOTH) == 0)
8242 o[i++] = 'w';
8243 if ((mask & S_IXOTH) == 0)
8244 o[i++] = 'x';
8245 o[i] = '\0';
8246
8247 printf("u=%s,g=%s,o=%s\n", u, g, o);
8248 } else { 8382 } else {
8249 printf("%.4o\n", mask); 8383 printf("%.4o\n", mask);
8250 } 8384 }
@@ -8258,17 +8392,10 @@ umaskcmd(argc, argv)
8258 } while (*++ap != '\0'); 8392 } while (*++ap != '\0');
8259 umask(mask); 8393 umask(mask);
8260 } else { 8394 } else {
8261 void *set; 8395 mask = ~mask & 0777;
8262 8396 if (parse_mode(ap, &mask) == FALSE) {
8263 INTOFF;
8264 if ((set = setmode(ap)) != 0) {
8265 mask = getmode(set, ~mask & 0777);
8266 ckfree(set);
8267 }
8268 INTON;
8269 if (!set)
8270 error("Illegal mode: %s", ap); 8397 error("Illegal mode: %s", ap);
8271 8398 }
8272 umask(~mask & 0777); 8399 umask(~mask & 0777);
8273 } 8400 }
8274 } 8401 }
@@ -8287,46 +8414,45 @@ umaskcmd(argc, argv)
8287 8414
8288struct limits { 8415struct limits {
8289 const char *name; 8416 const char *name;
8290 int cmd; 8417 short cmd;
8291 int factor; /* multiply by to get rlim_{cur,max} values */ 8418 short factor; /* multiply by to get rlim_{cur,max} values */
8292 char option;
8293}; 8419};
8294 8420
8295static const struct limits limits[] = { 8421static const struct limits limits[] = {
8296#ifdef RLIMIT_CPU 8422#ifdef RLIMIT_CPU
8297 { "time(seconds)", RLIMIT_CPU, 1, 't' }, 8423 { "time(seconds)", RLIMIT_CPU, 1 },
8298#endif 8424#endif
8299#ifdef RLIMIT_FSIZE 8425#ifdef RLIMIT_FSIZE
8300 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' }, 8426 { "file(blocks)", RLIMIT_FSIZE, 512 },
8301#endif 8427#endif
8302#ifdef RLIMIT_DATA 8428#ifdef RLIMIT_DATA
8303 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' }, 8429 { "data(kbytes)", RLIMIT_DATA, 1024 },
8304#endif 8430#endif
8305#ifdef RLIMIT_STACK 8431#ifdef RLIMIT_STACK
8306 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' }, 8432 { "stack(kbytes)", RLIMIT_STACK, 1024 },
8307#endif 8433#endif
8308#ifdef RLIMIT_CORE 8434#ifdef RLIMIT_CORE
8309 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' }, 8435 { "coredump(blocks)", RLIMIT_CORE, 512 },
8310#endif 8436#endif
8311#ifdef RLIMIT_RSS 8437#ifdef RLIMIT_RSS
8312 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' }, 8438 { "memory(kbytes)", RLIMIT_RSS, 1024 },
8313#endif 8439#endif
8314#ifdef RLIMIT_MEMLOCK 8440#ifdef RLIMIT_MEMLOCK
8315 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' }, 8441 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024 },
8316#endif 8442#endif
8317#ifdef RLIMIT_NPROC 8443#ifdef RLIMIT_NPROC
8318 { "process(processes)", RLIMIT_NPROC, 1, 'p' }, 8444 { "process(processes)", RLIMIT_NPROC, 1 },
8319#endif 8445#endif
8320#ifdef RLIMIT_NOFILE 8446#ifdef RLIMIT_NOFILE
8321 { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' }, 8447 { "nofiles(descriptors)", RLIMIT_NOFILE, 1 },
8322#endif 8448#endif
8323#ifdef RLIMIT_VMEM 8449#ifdef RLIMIT_VMEM
8324 { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' }, 8450 { "vmemory(kbytes)", RLIMIT_VMEM, 1024 },
8325#endif 8451#endif
8326#ifdef RLIMIT_SWAP 8452#ifdef RLIMIT_SWAP
8327 { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' }, 8453 { "swap(kbytes)", RLIMIT_SWAP, 1024 },
8328#endif 8454#endif
8329 { (char *) 0, 0, 0, '\0' } 8455 { NULL, 0, 0 }
8330}; 8456};
8331 8457
8332static int 8458static int
@@ -8334,6 +8460,7 @@ ulimitcmd(argc, argv)
8334 int argc; 8460 int argc;
8335 char **argv; 8461 char **argv;
8336{ 8462{
8463 static const char unlimited_string[] = "unlimited";
8337 int c; 8464 int c;
8338 rlim_t val = 0; 8465 rlim_t val = 0;
8339 enum { SOFT = 0x1, HARD = 0x2 } 8466 enum { SOFT = 0x1, HARD = 0x2 }
@@ -8344,25 +8471,59 @@ ulimitcmd(argc, argv)
8344 struct rlimit limit; 8471 struct rlimit limit;
8345 8472
8346 what = 'f'; 8473 what = 'f';
8347 while ((optc = nextopt("HSatfdsmcnpl")) != '\0') 8474
8348 switch (optc) { 8475 while ((optc = nextopt("HSa"
8349 case 'H': 8476#ifdef RLIMIT_CPU
8477 "t"
8478#endif
8479#ifdef RLIMIT_FSIZE
8480 "f"
8481#endif
8482#ifdef RLIMIT_DATA
8483 "d"
8484#endif
8485#ifdef RLIMIT_STACK
8486 "s"
8487#endif
8488#ifdef RLIMIT_CORE
8489 "c"
8490#endif
8491#ifdef RLIMIT_RSS
8492 "m"
8493#endif
8494#ifdef RLIMIT_MEMLOCK
8495 "l"
8496#endif
8497#ifdef RLIMIT_NPROC
8498 "p"
8499#endif
8500#ifdef RLIMIT_NOFILE
8501 "n"
8502#endif
8503#ifdef RLIMIT_VMEM
8504 "v"
8505#endif
8506#ifdef RLIMIT_SWAP
8507 "w"
8508#endif
8509 )) != '\0') {
8510 if (optc == 'H') {
8350 how = HARD; 8511 how = HARD;
8351 break; 8512 } else if (optc == 'S') {
8352 case 'S':
8353 how = SOFT; 8513 how = SOFT;
8354 break; 8514 } else if (optc == 'a') {
8355 case 'a':
8356 all = 1; 8515 all = 1;
8357 break; 8516 } else {
8358 default:
8359 what = optc; 8517 what = optc;
8360 } 8518 }
8519 }
8361 8520
8362 for (l = limits; l->name && l->option != what; l++) 8521 for (l = limits; l->name; l++) {
8363 ; 8522 if(l->name[0] == what)
8364 if (!l->name) 8523 break;
8365 error("internal error (%c)", what); 8524 if(l->name[1]=='w' && what=='w')
8525 break;
8526 }
8366 8527
8367 set = *argptr ? 1 : 0; 8528 set = *argptr ? 1 : 0;
8368 if (set) { 8529 if (set) {
@@ -8370,7 +8531,7 @@ ulimitcmd(argc, argv)
8370 8531
8371 if (all || argptr[1]) 8532 if (all || argptr[1])
8372 error("too many arguments"); 8533 error("too many arguments");
8373 if (strcmp(p, "unlimited") == 0) 8534 if (strcmp(p, unlimited_string) == 0)
8374 val = RLIM_INFINITY; 8535 val = RLIM_INFINITY;
8375 else { 8536 else {
8376 val = (rlim_t) 0; 8537 val = (rlim_t) 0;
@@ -8386,48 +8547,42 @@ ulimitcmd(argc, argv)
8386 val *= l->factor; 8547 val *= l->factor;
8387 } 8548 }
8388 } 8549 }
8550
8389 if (all) { 8551 if (all) {
8390 for (l = limits; l->name; l++) { 8552 for (l = limits; l->name; l++) {
8553 printf("%-20s ", l->name);
8391 getrlimit(l->cmd, &limit); 8554 getrlimit(l->cmd, &limit);
8555 OUTPUT_LIMIT:
8392 if (how & SOFT) 8556 if (how & SOFT)
8393 val = limit.rlim_cur; 8557 val = limit.rlim_cur;
8394 else if (how & HARD) 8558 else if (how & HARD)
8395 val = limit.rlim_max; 8559 val = limit.rlim_max;
8396 8560
8397 printf("%-20s ", l->name);
8398 if (val == RLIM_INFINITY) 8561 if (val == RLIM_INFINITY)
8399 printf("unlimited\n"); 8562 puts(unlimited_string);
8400 else 8563 else
8401 { 8564 {
8402 val /= l->factor; 8565 val /= l->factor;
8403 printf("%lld\n", (long long) val); 8566 printf("%lld\n", (long long) val);
8404 } 8567 }
8568 if (!all) {
8569 break;
8570 }
8405 } 8571 }
8406 return 0; 8572 return 0;
8407 } 8573 }
8408 8574
8409 getrlimit(l->cmd, &limit); 8575 if (!set) {
8410 if (set) { 8576 goto OUTPUT_LIMIT;
8411 if (how & HARD)
8412 limit.rlim_max = val;
8413 if (how & SOFT)
8414 limit.rlim_cur = val;
8415 if (setrlimit(l->cmd, &limit) < 0)
8416 error("error setting limit (%m)");
8417 } else {
8418 if (how & SOFT)
8419 val = limit.rlim_cur;
8420 else if (how & HARD)
8421 val = limit.rlim_max;
8422
8423 if (val == RLIM_INFINITY)
8424 printf("unlimited\n");
8425 else
8426 {
8427 val /= l->factor;
8428 printf("%lld\n", (long long) val);
8429 }
8430 } 8577 }
8578
8579 getrlimit(l->cmd, &limit);
8580 if (how & HARD)
8581 limit.rlim_max = val;
8582 if (how & SOFT)
8583 limit.rlim_cur = val;
8584 if (setrlimit(l->cmd, &limit) < 0)
8585 error("error setting limit (%m)");
8431 return 0; 8586 return 0;
8432} 8587}
8433/* 8588/*
@@ -8499,16 +8654,7 @@ single_quote(const char *s) {
8499 len2 = strspn(s + len1, "'"); 8654 len2 = strspn(s + len1, "'");
8500 8655
8501 len1p = len1 ? len1 + 2 : len1; 8656 len1p = len1 ? len1 + 2 : len1;
8502 switch (len2) { 8657 len2p = len2 + ((len2 < 2) ? len2 : 2);
8503 case 0:
8504 len2p = 0;
8505 break;
8506 case 1:
8507 len2p = 2;
8508 break;
8509 default:
8510 len2p = len2 + 2;
8511 }
8512 8658
8513 CHECKSTRSPACE(len1p + len2p + 1, p); 8659 CHECKSTRSPACE(len1p + len2p + 1, p);
8514 8660
@@ -8520,20 +8666,16 @@ single_quote(const char *s) {
8520 s += len1; 8666 s += len1;
8521 } 8667 }
8522 8668
8523 switch (len2) { 8669 if (len2 > 1) {
8524 case 0:
8525 break;
8526 case 1:
8527 *q++ = '\\';
8528 *q = '\'';
8529 s++;
8530 break;
8531 default:
8532 *q = '"'; 8670 *q = '"';
8533 q += 1 + len2; 8671 q += 1 + len2;
8534 memcpy(q + 1, s, len2); 8672 memcpy(q + 1, s, len2);
8535 *q = '"'; 8673 *q = '"';
8536 s += len2; 8674 s += len2;
8675 } else if (len2 == 1) {
8676 *q++ = '\\';
8677 *q = '\'';
8678 s++;
8537 } 8679 }
8538 8680
8539 STADJUST(len1p + len2p, p); 8681 STADJUST(len1p + len2p, p);
@@ -8565,182 +8707,357 @@ static void sizenodelist (const struct nodelist *);
8565static struct nodelist *copynodelist (const struct nodelist *); 8707static struct nodelist *copynodelist (const struct nodelist *);
8566static char *nodesavestr (const char *); 8708static char *nodesavestr (const char *);
8567 8709
8568static void 8710//#define CALCSIZE_TABLE
8569calcsize(const union node *n) 8711//#define COPYNODE_TABLE
8712#if defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE)
8713/*
8714 * To collect a lot of redundant code in case statements for copynode()
8715 * and calcsize(), we implement a mini language here. Each type of node
8716 * struct has an associated instruction sequence that operates on its
8717 * members via their offsets. The instruction are pack in unsigned chars
8718 * with format IIDDDDDE where the bits are
8719 * I : part of the instruction opcode, which are
8720 * 00 : member is a pointer to another node
8721 * 40 : member is an integer
8722 * 80 : member is a pointer to a nodelist
8723 * CC : member is a pointer to a char string
8724 * D : data - the actual offset of the member to operate on in the struct
8725 * (since we assume bit 0 is set, it is not shifted)
8726 * E : flag signaling end of instruction sequence
8727 *
8728 * WARNING: In order to handle larger offsets for 64bit archs, this code
8729 * assumes that no offset can be an odd number and stores the
8730 * end-of-instructions flag in bit 0.
8731 */
8732
8733#define NODE_INTEGER 0x40
8734#define NODE_NODELIST 0x80
8735#define NODE_CHARPTR 0xC0
8736#define NODE_NOMORE 0x01 /* Note: no offset should be odd (aligned)*/
8737#define NODE_MBRMASK 0xC0
8738#define NODE_OFFSETMASK 0x3E
8739
8740static const unsigned char copynode_ops[35] = {
8741#define COPYNODE_OPS0 0
8742 offsetof(union node, nbinary.ch2),
8743 offsetof(union node, nbinary.ch1)|NODE_NOMORE,
8744#define COPYNODE_OPS1 (COPYNODE_OPS0 + 2)
8745 offsetof(union node, ncmd.redirect),
8746 offsetof(union node, ncmd.args),
8747 offsetof(union node, ncmd.assign),
8748 offsetof(union node, ncmd.backgnd)|NODE_INTEGER|NODE_NOMORE,
8749#define COPYNODE_OPS2 (COPYNODE_OPS1 + 4)
8750 offsetof(union node, npipe.cmdlist)|NODE_NODELIST,
8751 offsetof(union node, npipe.backgnd)|NODE_INTEGER|NODE_NOMORE,
8752#define COPYNODE_OPS3 (COPYNODE_OPS2 + 2)
8753 offsetof(union node, nredir.redirect),
8754 offsetof(union node, nredir.n)|NODE_NOMORE,
8755#define COPYNODE_OPS4 (COPYNODE_OPS3 + 2)
8756 offsetof(union node, nif.elsepart),
8757 offsetof(union node, nif.ifpart),
8758 offsetof(union node, nif.test)|NODE_NOMORE,
8759#define COPYNODE_OPS5 (COPYNODE_OPS4 + 3)
8760 offsetof(union node, nfor.var)|NODE_CHARPTR,
8761 offsetof(union node, nfor.body),
8762 offsetof(union node, nfor.args)|NODE_NOMORE,
8763#define COPYNODE_OPS6 (COPYNODE_OPS5 + 3)
8764 offsetof(union node, ncase.cases),
8765 offsetof(union node, ncase.expr)|NODE_NOMORE,
8766#define COPYNODE_OPS7 (COPYNODE_OPS6 + 2)
8767 offsetof(union node, nclist.body),
8768 offsetof(union node, nclist.pattern),
8769 offsetof(union node, nclist.next)|NODE_NOMORE,
8770#define COPYNODE_OPS8 (COPYNODE_OPS7 + 3)
8771 offsetof(union node, narg.backquote)|NODE_NODELIST,
8772 offsetof(union node, narg.text)|NODE_CHARPTR,
8773 offsetof(union node, narg.next)|NODE_NOMORE,
8774#define COPYNODE_OPS9 (COPYNODE_OPS8 + 3)
8775 offsetof(union node, nfile.fname),
8776 offsetof(union node, nfile.fd)|NODE_INTEGER,
8777 offsetof(union node, nfile.next)|NODE_NOMORE,
8778#define COPYNODE_OPS10 (COPYNODE_OPS9 + 3)
8779 offsetof(union node, ndup.vname),
8780 offsetof(union node, ndup.dupfd)|NODE_INTEGER,
8781 offsetof(union node, ndup.fd)|NODE_INTEGER,
8782 offsetof(union node, ndup.next)|NODE_NOMORE,
8783#define COPYNODE_OPS11 (COPYNODE_OPS10 + 4)
8784 offsetof(union node, nhere.doc),
8785 offsetof(union node, nhere.fd)|NODE_INTEGER,
8786 offsetof(union node, nhere.next)|NODE_NOMORE,
8787#define COPYNODE_OPS12 (COPYNODE_OPS11 + 3)
8788 offsetof(union node, nnot.com)|NODE_NOMORE,
8789};
8790
8791#if COPYNODE_OPS12 != 34
8792#error COPYNODE_OPS12 is incorrect
8793#endif
8794
8795static const unsigned char copynode_ops_index[26] = {
8796 COPYNODE_OPS0, /* NSEMI */
8797 COPYNODE_OPS1, /* NCMD */
8798 COPYNODE_OPS2, /* NPIPE */
8799 COPYNODE_OPS3, /* NREDIR */
8800 COPYNODE_OPS3, /* NBACKGND */
8801 COPYNODE_OPS3, /* NSUBSHELL */
8802 COPYNODE_OPS0, /* NAND */
8803 COPYNODE_OPS0, /* NOR */
8804 COPYNODE_OPS4, /* NIF */
8805 COPYNODE_OPS0, /* NWHILE */
8806 COPYNODE_OPS0, /* NUNTIL */
8807 COPYNODE_OPS5, /* NFOR */
8808 COPYNODE_OPS6, /* NCASE */
8809 COPYNODE_OPS7, /* NCLIST */
8810 COPYNODE_OPS8, /* NDEFUN */
8811 COPYNODE_OPS8, /* NARG */
8812 COPYNODE_OPS9, /* NTO */
8813 COPYNODE_OPS9, /* NFROM */
8814 COPYNODE_OPS9, /* NFROMTO */
8815 COPYNODE_OPS9, /* NAPPEND */
8816 COPYNODE_OPS9, /* NTOOV */
8817 COPYNODE_OPS10, /* NTOFD */
8818 COPYNODE_OPS10, /* NFROMFD */
8819 COPYNODE_OPS11, /* NHERE */
8820 COPYNODE_OPS11, /* NXHERE */
8821 COPYNODE_OPS12, /* NNOT */
8822};
8823
8824#if NODE_CHARPTR != NODE_MBRMASK
8825#error NODE_CHARPTR != NODE_MBRMASK!!!
8826#endif
8827#endif /* defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE) */
8828
8829#ifdef COPYNODE_TABLE
8830static union node *
8831copynode(const union node *n)
8570{ 8832{
8833 union node *new;
8834 const unsigned char *p;
8835
8571 if (n == NULL) 8836 if (n == NULL)
8572 return; 8837 return NULL;
8573 funcblocksize += nodesize[n->type]; 8838 new = funcblock;
8839 new->type = n->type;
8840 funcblock = (char *) funcblock + (int) nodesize[n->type];
8841 p = copynode_ops + (int) copynode_ops_index[n->type];
8842 do {
8843 char *nn = ((char *) new) + ((int)(*p & NODE_OFFSETMASK));
8844 const char *no = ((const char *) n) + ((int)(*p & NODE_OFFSETMASK));
8845
8846 if (!(*p & NODE_MBRMASK)) { /* standard node */
8847 (union node *) nn = copynode((const union node *) no);
8848 } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8849 nn = nodesavestr(no);
8850 } else if (*p & NODE_NODELIST) { /* nodelist */
8851 (struct nodelist *) nn
8852 = copynodelist((const struct nodelist *) no);
8853 } else { /* integer */
8854 *((int *) nn) = *((int *) no);
8855 }
8856 } while (!(*p++ & NODE_NOMORE));
8857 return new;
8858}
8859#else /* COPYNODE_TABLE */
8860static union node *
8861copynode(const union node *n)
8862{
8863 union node *new;
8864
8865 if (n == NULL)
8866 return NULL;
8867 new = funcblock;
8868 funcblock = (char *) funcblock + nodesize[n->type];
8574 switch (n->type) { 8869 switch (n->type) {
8575 case NSEMI: 8870 case NSEMI:
8576 case NAND: 8871 case NAND:
8577 case NOR: 8872 case NOR:
8578 case NWHILE: 8873 case NWHILE:
8579 case NUNTIL: 8874 case NUNTIL:
8580 calcsize(n->nbinary.ch2); 8875 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8581 calcsize(n->nbinary.ch1); 8876 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8582 break; 8877 break;
8583 case NCMD: 8878 case NCMD:
8584 calcsize(n->ncmd.redirect); 8879 new->ncmd.redirect = copynode(n->ncmd.redirect);
8585 calcsize(n->ncmd.args); 8880 new->ncmd.args = copynode(n->ncmd.args);
8586 calcsize(n->ncmd.assign); 8881 new->ncmd.assign = copynode(n->ncmd.assign);
8882 new->ncmd.backgnd = n->ncmd.backgnd;
8587 break; 8883 break;
8588 case NPIPE: 8884 case NPIPE:
8589 sizenodelist(n->npipe.cmdlist); 8885 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8886 new->npipe.backgnd = n->npipe.backgnd;
8590 break; 8887 break;
8591 case NREDIR: 8888 case NREDIR:
8592 case NBACKGND: 8889 case NBACKGND:
8593 case NSUBSHELL: 8890 case NSUBSHELL:
8594 calcsize(n->nredir.redirect); 8891 new->nredir.redirect = copynode(n->nredir.redirect);
8595 calcsize(n->nredir.n); 8892 new->nredir.n = copynode(n->nredir.n);
8596 break; 8893 break;
8597 case NIF: 8894 case NIF:
8598 calcsize(n->nif.elsepart); 8895 new->nif.elsepart = copynode(n->nif.elsepart);
8599 calcsize(n->nif.ifpart); 8896 new->nif.ifpart = copynode(n->nif.ifpart);
8600 calcsize(n->nif.test); 8897 new->nif.test = copynode(n->nif.test);
8601 break; 8898 break;
8602 case NFOR: 8899 case NFOR:
8603 funcstringsize += strlen(n->nfor.var) + 1; 8900 new->nfor.var = nodesavestr(n->nfor.var);
8604 calcsize(n->nfor.body); 8901 new->nfor.body = copynode(n->nfor.body);
8605 calcsize(n->nfor.args); 8902 new->nfor.args = copynode(n->nfor.args);
8606 break; 8903 break;
8607 case NCASE: 8904 case NCASE:
8608 calcsize(n->ncase.cases); 8905 new->ncase.cases = copynode(n->ncase.cases);
8609 calcsize(n->ncase.expr); 8906 new->ncase.expr = copynode(n->ncase.expr);
8610 break; 8907 break;
8611 case NCLIST: 8908 case NCLIST:
8612 calcsize(n->nclist.body); 8909 new->nclist.body = copynode(n->nclist.body);
8613 calcsize(n->nclist.pattern); 8910 new->nclist.pattern = copynode(n->nclist.pattern);
8614 calcsize(n->nclist.next); 8911 new->nclist.next = copynode(n->nclist.next);
8615 break; 8912 break;
8616 case NDEFUN: 8913 case NDEFUN:
8617 case NARG: 8914 case NARG:
8618 sizenodelist(n->narg.backquote); 8915 new->narg.backquote = copynodelist(n->narg.backquote);
8619 funcstringsize += strlen(n->narg.text) + 1; 8916 new->narg.text = nodesavestr(n->narg.text);
8620 calcsize(n->narg.next); 8917 new->narg.next = copynode(n->narg.next);
8621 break; 8918 break;
8622 case NTO: 8919 case NTO:
8623 case NFROM: 8920 case NFROM:
8624 case NFROMTO: 8921 case NFROMTO:
8625 case NAPPEND: 8922 case NAPPEND:
8626 case NTOOV: 8923 case NTOOV:
8627 calcsize(n->nfile.fname); 8924 new->nfile.fname = copynode(n->nfile.fname);
8628 calcsize(n->nfile.next); 8925 new->nfile.fd = n->nfile.fd;
8926 new->nfile.next = copynode(n->nfile.next);
8629 break; 8927 break;
8630 case NTOFD: 8928 case NTOFD:
8631 case NFROMFD: 8929 case NFROMFD:
8632 calcsize(n->ndup.vname); 8930 new->ndup.vname = copynode(n->ndup.vname);
8633 calcsize(n->ndup.next); 8931 new->ndup.dupfd = n->ndup.dupfd;
8932 new->ndup.fd = n->ndup.fd;
8933 new->ndup.next = copynode(n->ndup.next);
8634 break; 8934 break;
8635 case NHERE: 8935 case NHERE:
8636 case NXHERE: 8936 case NXHERE:
8637 calcsize(n->nhere.doc); 8937 new->nhere.doc = copynode(n->nhere.doc);
8638 calcsize(n->nhere.next); 8938 new->nhere.fd = n->nhere.fd;
8939 new->nhere.next = copynode(n->nhere.next);
8639 break; 8940 break;
8640 case NNOT: 8941 case NNOT:
8641 calcsize(n->nnot.com); 8942 new->nnot.com = copynode(n->nnot.com);
8642 break; 8943 break;
8643 }; 8944 };
8945 new->type = n->type;
8946 return new;
8644} 8947}
8948#endif /* COPYNODE_TABLE */
8645 8949
8950#ifdef CALCSIZE_TABLE
8646static void 8951static void
8647sizenodelist(const struct nodelist *lp) 8952calcsize(const union node *n)
8648{ 8953{
8649 while (lp) { 8954 const unsigned char *p;
8650 funcblocksize += ALIGN(sizeof(struct nodelist));
8651 calcsize(lp->n);
8652 lp = lp->next;
8653 }
8654}
8655
8656 8955
8657static union node * 8956 if (n == NULL)
8658copynode(const union node *n) 8957 return;
8958 funcblocksize += (int) nodesize[n->type];
8959
8960 p = copynode_ops + (int) copynode_ops_index[n->type];
8961 do {
8962 const char *no = ((const char *) n) + ((int)(*p & NODE_OFFSETMASK));
8963
8964 if (!(*p & NODE_MBRMASK)) { /* standard node */
8965 calcsize((const union node *) no);
8966 } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8967 funcstringsize += strlen(no) + 1;
8968 } else if (*p & NODE_NODELIST) { /* nodelist */
8969 sizenodelist((const struct nodelist *) no);
8970 }
8971 } while (!(*p++ & NODE_NOMORE));
8972}
8973#else /* CALCSIZE_TABLE */
8974static void
8975calcsize(const union node *n)
8659{ 8976{
8660 union node *new;
8661
8662 if (n == NULL) 8977 if (n == NULL)
8663 return NULL; 8978 return;
8664 new = funcblock; 8979 funcblocksize += nodesize[n->type];
8665 funcblock = (char *) funcblock + nodesize[n->type];
8666 switch (n->type) { 8980 switch (n->type) {
8667 case NSEMI: 8981 case NSEMI:
8668 case NAND: 8982 case NAND:
8669 case NOR: 8983 case NOR:
8670 case NWHILE: 8984 case NWHILE:
8671 case NUNTIL: 8985 case NUNTIL:
8672 new->nbinary.ch2 = copynode(n->nbinary.ch2); 8986 calcsize(n->nbinary.ch2);
8673 new->nbinary.ch1 = copynode(n->nbinary.ch1); 8987 calcsize(n->nbinary.ch1);
8674 break; 8988 break;
8675 case NCMD: 8989 case NCMD:
8676 new->ncmd.redirect = copynode(n->ncmd.redirect); 8990 calcsize(n->ncmd.redirect);
8677 new->ncmd.args = copynode(n->ncmd.args); 8991 calcsize(n->ncmd.args);
8678 new->ncmd.assign = copynode(n->ncmd.assign); 8992 calcsize(n->ncmd.assign);
8679 new->ncmd.backgnd = n->ncmd.backgnd;
8680 break; 8993 break;
8681 case NPIPE: 8994 case NPIPE:
8682 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist); 8995 sizenodelist(n->npipe.cmdlist);
8683 new->npipe.backgnd = n->npipe.backgnd;
8684 break; 8996 break;
8685 case NREDIR: 8997 case NREDIR:
8686 case NBACKGND: 8998 case NBACKGND:
8687 case NSUBSHELL: 8999 case NSUBSHELL:
8688 new->nredir.redirect = copynode(n->nredir.redirect); 9000 calcsize(n->nredir.redirect);
8689 new->nredir.n = copynode(n->nredir.n); 9001 calcsize(n->nredir.n);
8690 break; 9002 break;
8691 case NIF: 9003 case NIF:
8692 new->nif.elsepart = copynode(n->nif.elsepart); 9004 calcsize(n->nif.elsepart);
8693 new->nif.ifpart = copynode(n->nif.ifpart); 9005 calcsize(n->nif.ifpart);
8694 new->nif.test = copynode(n->nif.test); 9006 calcsize(n->nif.test);
8695 break; 9007 break;
8696 case NFOR: 9008 case NFOR:
8697 new->nfor.var = nodesavestr(n->nfor.var); 9009 funcstringsize += strlen(n->nfor.var) + 1;
8698 new->nfor.body = copynode(n->nfor.body); 9010 calcsize(n->nfor.body);
8699 new->nfor.args = copynode(n->nfor.args); 9011 calcsize(n->nfor.args);
8700 break; 9012 break;
8701 case NCASE: 9013 case NCASE:
8702 new->ncase.cases = copynode(n->ncase.cases); 9014 calcsize(n->ncase.cases);
8703 new->ncase.expr = copynode(n->ncase.expr); 9015 calcsize(n->ncase.expr);
8704 break; 9016 break;
8705 case NCLIST: 9017 case NCLIST:
8706 new->nclist.body = copynode(n->nclist.body); 9018 calcsize(n->nclist.body);
8707 new->nclist.pattern = copynode(n->nclist.pattern); 9019 calcsize(n->nclist.pattern);
8708 new->nclist.next = copynode(n->nclist.next); 9020 calcsize(n->nclist.next);
8709 break; 9021 break;
8710 case NDEFUN: 9022 case NDEFUN:
8711 case NARG: 9023 case NARG:
8712 new->narg.backquote = copynodelist(n->narg.backquote); 9024 sizenodelist(n->narg.backquote);
8713 new->narg.text = nodesavestr(n->narg.text); 9025 funcstringsize += strlen(n->narg.text) + 1;
8714 new->narg.next = copynode(n->narg.next); 9026 calcsize(n->narg.next);
8715 break; 9027 break;
8716 case NTO: 9028 case NTO:
8717 case NFROM: 9029 case NFROM:
8718 case NFROMTO: 9030 case NFROMTO:
8719 case NAPPEND: 9031 case NAPPEND:
8720 case NTOOV: 9032 case NTOOV:
8721 new->nfile.fname = copynode(n->nfile.fname); 9033 calcsize(n->nfile.fname);
8722 new->nfile.fd = n->nfile.fd; 9034 calcsize(n->nfile.next);
8723 new->nfile.next = copynode(n->nfile.next);
8724 break; 9035 break;
8725 case NTOFD: 9036 case NTOFD:
8726 case NFROMFD: 9037 case NFROMFD:
8727 new->ndup.vname = copynode(n->ndup.vname); 9038 calcsize(n->ndup.vname);
8728 new->ndup.dupfd = n->ndup.dupfd; 9039 calcsize(n->ndup.next);
8729 new->ndup.fd = n->ndup.fd;
8730 new->ndup.next = copynode(n->ndup.next);
8731 break; 9040 break;
8732 case NHERE: 9041 case NHERE:
8733 case NXHERE: 9042 case NXHERE:
8734 new->nhere.doc = copynode(n->nhere.doc); 9043 calcsize(n->nhere.doc);
8735 new->nhere.fd = n->nhere.fd; 9044 calcsize(n->nhere.next);
8736 new->nhere.next = copynode(n->nhere.next);
8737 break; 9045 break;
8738 case NNOT: 9046 case NNOT:
8739 new->nnot.com = copynode(n->nnot.com); 9047 calcsize(n->nnot.com);
8740 break; 9048 break;
8741 }; 9049 };
8742 new->type = n->type; 9050}
8743 return new; 9051#endif /* CALCSIZE_TABLE */
9052
9053static void
9054sizenodelist(const struct nodelist *lp)
9055{
9056 while (lp) {
9057 funcblocksize += ALIGN(sizeof(struct nodelist));
9058 calcsize(lp->n);
9059 lp = lp->next;
9060 }
8744} 9061}
8745 9062
8746 9063
@@ -9346,10 +9663,10 @@ static union node *command (void);
9346static union node *simplecmd (void); 9663static union node *simplecmd (void);
9347static void parsefname (void); 9664static void parsefname (void);
9348static void parseheredoc (void); 9665static void parseheredoc (void);
9349static int peektoken (void); 9666static char peektoken (void);
9350static int readtoken (void); 9667static int readtoken (void);
9351static int xxreadtoken (void); 9668static int xxreadtoken (void);
9352static int readtoken1 (int, char const *, char *, int); 9669static int readtoken1 (int, int, const char *, int);
9353static int noexpand (char *); 9670static int noexpand (char *);
9354static void synexpect (int) __attribute__((noreturn)); 9671static void synexpect (int) __attribute__((noreturn));
9355static void synerror (const char *) __attribute__((noreturn)); 9672static void synerror (const char *) __attribute__((noreturn));
@@ -9391,7 +9708,7 @@ list(nlflag)
9391 int tok; 9708 int tok;
9392 9709
9393 checkkwd = 2; 9710 checkkwd = 2;
9394 if (nlflag == 0 && tokendlist[peektoken()]) 9711 if (nlflag == 0 && peektoken())
9395 return NULL; 9712 return NULL;
9396 n1 = NULL; 9713 n1 = NULL;
9397 for (;;) { 9714 for (;;) {
@@ -9434,7 +9751,7 @@ list(nlflag)
9434 tokpushback++; 9751 tokpushback++;
9435 } 9752 }
9436 checkkwd = 2; 9753 checkkwd = 2;
9437 if (tokendlist[peektoken()]) 9754 if (peektoken())
9438 return n1; 9755 return n1;
9439 break; 9756 break;
9440 case TEOF: 9757 case TEOF:
@@ -9572,7 +9889,7 @@ command() {
9572 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL; 9889 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9573 n1->nbinary.ch1 = list(0); 9890 n1->nbinary.ch1 = list(0);
9574 if ((got=readtoken()) != TDO) { 9891 if ((got=readtoken()) != TDO) {
9575TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); 9892TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9576 synexpect(TDO); 9893 synexpect(TDO);
9577 } 9894 }
9578 n1->nbinary.ch2 = list(0); 9895 n1->nbinary.ch2 = list(0);
@@ -9901,13 +10218,13 @@ parseheredoc() {
9901 } 10218 }
9902} 10219}
9903 10220
9904static int 10221static char
9905peektoken() { 10222peektoken() {
9906 int t; 10223 int t;
9907 10224
9908 t = readtoken(); 10225 t = readtoken();
9909 tokpushback++; 10226 tokpushback++;
9910 return (t); 10227 return tokname_array[t][0];
9911} 10228}
9912 10229
9913static int 10230static int
@@ -9954,8 +10271,8 @@ top:
9954 const char *const *pp; 10271 const char *const *pp;
9955 10272
9956 if ((pp = findkwd(wordtext))) { 10273 if ((pp = findkwd(wordtext))) {
9957 lasttoken = t = pp - parsekwd + KWDOFFSET; 10274 lasttoken = t = pp - tokname_array;
9958 TRACE(("keyword %s recognized\n", tokname[t])); 10275 TRACE(("keyword %s recognized\n", tokname(t)));
9959 goto out; 10276 goto out;
9960 } 10277 }
9961 } 10278 }
@@ -9983,9 +10300,9 @@ top:
9983out: 10300out:
9984#ifdef DEBUG 10301#ifdef DEBUG
9985 if (!alreadyseen) 10302 if (!alreadyseen)
9986 TRACE(("token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : "")); 10303 TRACE(("token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : ""));
9987 else 10304 else
9988 TRACE(("reread token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : "")); 10305 TRACE(("reread token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : ""));
9989#endif 10306#endif
9990 return (t); 10307 return (t);
9991} 10308}
@@ -10103,12 +10420,8 @@ breakloop:
10103#define PARSEARITH() {goto parsearith; parsearith_return:;} 10420#define PARSEARITH() {goto parsearith; parsearith_return:;}
10104 10421
10105static int 10422static int
10106readtoken1(firstc, syntax, eofmark, striptabs) 10423readtoken1(int firstc, int syntax, const char *eofmark, int striptabs)
10107 int firstc; 10424{
10108 char const *syntax;
10109 char *eofmark;
10110 int striptabs;
10111 {
10112 int c = firstc; 10425 int c = firstc;
10113 char *out; 10426 char *out;
10114 int len; 10427 int len;
@@ -10121,7 +10434,7 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10121 int parenlevel; /* levels of parens in arithmetic */ 10434 int parenlevel; /* levels of parens in arithmetic */
10122 int dqvarnest; /* levels of variables expansion within double quotes */ 10435 int dqvarnest; /* levels of variables expansion within double quotes */
10123 int oldstyle; 10436 int oldstyle;
10124 char const *prevsyntax; /* syntax before arithmetic */ 10437 int prevsyntax; /* syntax before arithmetic */
10125#if __GNUC__ 10438#if __GNUC__
10126 /* Avoid longjmp clobbering */ 10439 /* Avoid longjmp clobbering */
10127 (void) &out; 10440 (void) &out;
@@ -10152,7 +10465,7 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10152 CHECKEND(); /* set c to PEOF if at end of here document */ 10465 CHECKEND(); /* set c to PEOF if at end of here document */
10153 for (;;) { /* until end of line or end of word */ 10466 for (;;) { /* until end of line or end of word */
10154 CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */ 10467 CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
10155 switch(syntax[c]) { 10468 switch(SIT(c,syntax)) {
10156 case CNL: /* '\n' */ 10469 case CNL: /* '\n' */
10157 if (syntax == BASESYNTAX) 10470 if (syntax == BASESYNTAX)
10158 goto endword; /* exit outer loop */ 10471 goto endword; /* exit outer loop */
@@ -10187,7 +10500,7 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10187 if (dblquote && c != '\\' && c != '`' && c != '$' 10500 if (dblquote && c != '\\' && c != '`' && c != '$'
10188 && (c != '"' || eofmark != NULL)) 10501 && (c != '"' || eofmark != NULL))
10189 USTPUTC('\\', out); 10502 USTPUTC('\\', out);
10190 if (SQSYNTAX[c] == CCTL) 10503 if (SIT(c,SQSYNTAX) == CCTL)
10191 USTPUTC(CTLESC, out); 10504 USTPUTC(CTLESC, out);
10192 else if (eofmark == NULL) 10505 else if (eofmark == NULL)
10193 USTPUTC(CTLQUOTEMARK, out); 10506 USTPUTC(CTLQUOTEMARK, out);
@@ -10338,7 +10651,7 @@ checkend: {
10338 } 10651 }
10339 if (c == *eofmark) { 10652 if (c == *eofmark) {
10340 if (pfgets(line, sizeof line) != NULL) { 10653 if (pfgets(line, sizeof line) != NULL) {
10341 char *p, *q; 10654 const char *p, *q;
10342 10655
10343 p = line; 10656 p = line;
10344 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++); 10657 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
@@ -10728,7 +11041,7 @@ noexpand(text)
10728 continue; 11041 continue;
10729 if (c == CTLESC) 11042 if (c == CTLESC)
10730 p++; 11043 p++;
10731 else if (BASESYNTAX[(int)c] == CCTL) 11044 else if (SIT(c,BASESYNTAX) == CCTL)
10732 return 0; 11045 return 0;
10733 } 11046 }
10734 return 1; 11047 return 1;
@@ -10767,13 +11080,11 @@ synexpect(token)
10767 int token; 11080 int token;
10768{ 11081{
10769 char msg[64]; 11082 char msg[64];
11083 int l;
10770 11084
10771 if (token >= 0) { 11085 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10772 snprintf(msg, 64, "%s unexpected (expecting %s)", 11086 if (token >= 0)
10773 tokname[lasttoken], tokname[token]); 11087 sprintf(msg+l, " (expecting %s)", tokname(token));
10774 } else {
10775 snprintf(msg, 64, "%s unexpected", tokname[lasttoken]);
10776 }
10777 synerror(msg); 11088 synerror(msg);
10778 /* NOTREACHED */ 11089 /* NOTREACHED */
10779} 11090}
@@ -11162,435 +11473,6 @@ dup_as_newfd(from, to)
11162 return newfd; 11473 return newfd;
11163} 11474}
11164 11475
11165/*#ifdef __weak_alias
11166__weak_alias(getmode,_getmode)
11167__weak_alias(setmode,_setmode)
11168#endif*/
11169
11170#ifndef S_ISTXT
11171#if defined(__GLIBC__) && __GLIBC__ >= 2
11172#define S_ISTXT __S_ISVTX
11173#else
11174#define S_ISTXT S_ISVTX
11175#endif
11176#endif
11177
11178#define SET_LEN 6 /* initial # of bitcmd struct to malloc */
11179#define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */
11180
11181typedef struct bitcmd {
11182 char cmd;
11183 char cmd2;
11184 mode_t bits;
11185} BITCMD;
11186
11187#define CMD2_CLR 0x01
11188#define CMD2_SET 0x02
11189#define CMD2_GBITS 0x04
11190#define CMD2_OBITS 0x08
11191#define CMD2_UBITS 0x10
11192
11193static BITCMD *addcmd (BITCMD *, int, int, int, u_int);
11194static void compress_mode (BITCMD *);
11195#ifdef SETMODE_DEBUG
11196static void dumpmode (BITCMD *);
11197#endif
11198
11199/*
11200 * Given the old mode and an array of bitcmd structures, apply the operations
11201 * described in the bitcmd structures to the old mode, and return the new mode.
11202 * Note that there is no '=' command; a strict assignment is just a '-' (clear
11203 * bits) followed by a '+' (set bits).
11204 */
11205static mode_t
11206getmode(bbox, omode)
11207 const void *bbox;
11208 mode_t omode;
11209{
11210 const BITCMD *set;
11211 mode_t clrval, newmode, value;
11212
11213 _DIAGASSERT(bbox != NULL);
11214
11215 set = (const BITCMD *)bbox;
11216 newmode = omode;
11217 for (value = 0;; set++)
11218 switch(set->cmd) {
11219 /*
11220 * When copying the user, group or other bits around, we "know"
11221 * where the bits are in the mode so that we can do shifts to
11222 * copy them around. If we don't use shifts, it gets real
11223 * grundgy with lots of single bit checks and bit sets.
11224 */
11225 case 'u':
11226 value = (newmode & S_IRWXU) >> 6;
11227 goto common;
11228
11229 case 'g':
11230 value = (newmode & S_IRWXG) >> 3;
11231 goto common;
11232
11233 case 'o':
11234 value = newmode & S_IRWXO;
11235common: if (set->cmd2 & CMD2_CLR) {
11236 clrval =
11237 (set->cmd2 & CMD2_SET) ? S_IRWXO : value;
11238 if (set->cmd2 & CMD2_UBITS)
11239 newmode &= ~((clrval<<6) & set->bits);
11240 if (set->cmd2 & CMD2_GBITS)
11241 newmode &= ~((clrval<<3) & set->bits);
11242 if (set->cmd2 & CMD2_OBITS)
11243 newmode &= ~(clrval & set->bits);
11244 }
11245 if (set->cmd2 & CMD2_SET) {
11246 if (set->cmd2 & CMD2_UBITS)
11247 newmode |= (value<<6) & set->bits;
11248 if (set->cmd2 & CMD2_GBITS)
11249 newmode |= (value<<3) & set->bits;
11250 if (set->cmd2 & CMD2_OBITS)
11251 newmode |= value & set->bits;
11252 }
11253 break;
11254
11255 case '+':
11256 newmode |= set->bits;
11257 break;
11258
11259 case '-':
11260 newmode &= ~set->bits;
11261 break;
11262
11263 case 'X':
11264 if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
11265 newmode |= set->bits;
11266 break;
11267
11268 case '\0':
11269 default:
11270#ifdef SETMODE_DEBUG
11271 (void)printf("getmode:%04o -> %04o\n", omode, newmode);
11272#endif
11273 return (newmode);
11274 }
11275}
11276
11277#define ADDCMD(a, b, c, d) do { \
11278 if (set >= endset) { \
11279 BITCMD *newset; \
11280 setlen += SET_LEN_INCR; \
11281 newset = realloc(saveset, sizeof(BITCMD) * setlen); \
11282 if (newset == NULL) { \
11283 free(saveset); \
11284 return (NULL); \
11285 } \
11286 set = newset + (set - saveset); \
11287 saveset = newset; \
11288 endset = newset + (setlen - 2); \
11289 } \
11290 set = addcmd(set, (a), (b), (c), (d)); \
11291} while (/*CONSTCOND*/0)
11292
11293#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
11294
11295static void *
11296setmode(p)
11297 const char *p;
11298{
11299 int perm, who;
11300 char op, *ep;
11301 BITCMD *set, *saveset, *endset;
11302 sigset_t mysigset, sigoset;
11303 mode_t mask;
11304 int equalopdone = 0; /* pacify gcc */
11305 int permXbits, setlen;
11306
11307 if (!*p)
11308 return (NULL);
11309
11310 /*
11311 * Get a copy of the mask for the permissions that are mask relative.
11312 * Flip the bits, we want what's not set. Since it's possible that
11313 * the caller is opening files inside a signal handler, protect them
11314 * as best we can.
11315 */
11316 sigfillset(&mysigset);
11317 (void)sigprocmask(SIG_BLOCK, &mysigset, &sigoset);
11318 (void)umask(mask = umask(0));
11319 mask = ~mask;
11320 (void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
11321
11322 setlen = SET_LEN + 2;
11323
11324 if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
11325 return (NULL);
11326 saveset = set;
11327 endset = set + (setlen - 2);
11328
11329 /*
11330 * If an absolute number, get it and return; disallow non-octal digits
11331 * or illegal bits.
11332 */
11333 if (is_digit((unsigned char)*p)) {
11334 perm = (mode_t)strtol(p, &ep, 8);
11335 if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) {
11336 free(saveset);
11337 return (NULL);
11338 }
11339 ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
11340 set->cmd = 0;
11341 return (saveset);
11342 }
11343
11344 /*
11345 * Build list of structures to set/clear/copy bits as described by
11346 * each clause of the symbolic mode.
11347 */
11348 for (;;) {
11349 /* First, find out which bits might be modified. */
11350 for (who = 0;; ++p) {
11351 switch (*p) {
11352 case 'a':
11353 who |= STANDARD_BITS;
11354 break;
11355 case 'u':
11356 who |= S_ISUID|S_IRWXU;
11357 break;
11358 case 'g':
11359 who |= S_ISGID|S_IRWXG;
11360 break;
11361 case 'o':
11362 who |= S_IRWXO;
11363 break;
11364 default:
11365 goto getop;
11366 }
11367 }
11368
11369getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
11370 free(saveset);
11371 return (NULL);
11372 }
11373 if (op == '=')
11374 equalopdone = 0;
11375
11376 who &= ~S_ISTXT;
11377 for (perm = 0, permXbits = 0;; ++p) {
11378 switch (*p) {
11379 case 'r':
11380 perm |= S_IRUSR|S_IRGRP|S_IROTH;
11381 break;
11382 case 's':
11383 /*
11384 * If specific bits where requested and
11385 * only "other" bits ignore set-id.
11386 */
11387 if (who == 0 || (who & ~S_IRWXO))
11388 perm |= S_ISUID|S_ISGID;
11389 break;
11390 case 't':
11391 /*
11392 * If specific bits where requested and
11393 * only "other" bits ignore set-id.
11394 */
11395 if (who == 0 || (who & ~S_IRWXO)) {
11396 who |= S_ISTXT;
11397 perm |= S_ISTXT;
11398 }
11399 break;
11400 case 'w':
11401 perm |= S_IWUSR|S_IWGRP|S_IWOTH;
11402 break;
11403 case 'X':
11404 permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
11405 break;
11406 case 'x':
11407 perm |= S_IXUSR|S_IXGRP|S_IXOTH;
11408 break;
11409 case 'u':
11410 case 'g':
11411 case 'o':
11412 /*
11413 * When ever we hit 'u', 'g', or 'o', we have
11414 * to flush out any partial mode that we have,
11415 * and then do the copying of the mode bits.
11416 */
11417 if (perm) {
11418 ADDCMD(op, who, perm, mask);
11419 perm = 0;
11420 }
11421 if (op == '=')
11422 equalopdone = 1;
11423 if (op == '+' && permXbits) {
11424 ADDCMD('X', who, permXbits, mask);
11425 permXbits = 0;
11426 }
11427 ADDCMD(*p, who, op, mask);
11428 break;
11429
11430 default:
11431 /*
11432 * Add any permissions that we haven't already
11433 * done.
11434 */
11435 if (perm || (op == '=' && !equalopdone)) {
11436 if (op == '=')
11437 equalopdone = 1;
11438 ADDCMD(op, who, perm, mask);
11439 perm = 0;
11440 }
11441 if (permXbits) {
11442 ADDCMD('X', who, permXbits, mask);
11443 permXbits = 0;
11444 }
11445 goto apply;
11446 }
11447 }
11448
11449apply: if (!*p)
11450 break;
11451 if (*p != ',')
11452 goto getop;
11453 ++p;
11454 }
11455 set->cmd = 0;
11456#ifdef SETMODE_DEBUG
11457 (void)printf("Before compress_mode()\n");
11458 dumpmode(saveset);
11459#endif
11460 compress_mode(saveset);
11461#ifdef SETMODE_DEBUG
11462 (void)printf("After compress_mode()\n");
11463 dumpmode(saveset);
11464#endif
11465 return (saveset);
11466}
11467
11468static BITCMD *
11469addcmd(set, op, who, oparg, mask)
11470 BITCMD *set;
11471 int oparg, who;
11472 int op;
11473 u_int mask;
11474{
11475
11476 _DIAGASSERT(set != NULL);
11477
11478 switch (op) {
11479 case '=':
11480 set->cmd = '-';
11481 set->bits = who ? who : STANDARD_BITS;
11482 set++;
11483
11484 op = '+';
11485 /* FALLTHROUGH */
11486 case '+':
11487 case '-':
11488 case 'X':
11489 set->cmd = op;
11490 set->bits = (who ? who : mask) & oparg;
11491 break;
11492
11493 case 'u':
11494 case 'g':
11495 case 'o':
11496 set->cmd = op;
11497 if (who) {
11498 set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
11499 ((who & S_IRGRP) ? CMD2_GBITS : 0) |
11500 ((who & S_IROTH) ? CMD2_OBITS : 0);
11501 set->bits = (mode_t)~0;
11502 } else {
11503 set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
11504 set->bits = mask;
11505 }
11506
11507 if (oparg == '+')
11508 set->cmd2 |= CMD2_SET;
11509 else if (oparg == '-')
11510 set->cmd2 |= CMD2_CLR;
11511 else if (oparg == '=')
11512 set->cmd2 |= CMD2_SET|CMD2_CLR;
11513 break;
11514 }
11515 return (set + 1);
11516}
11517
11518#ifdef SETMODE_DEBUG
11519static void
11520dumpmode(set)
11521 BITCMD *set;
11522{
11523
11524 _DIAGASSERT(set != NULL);
11525
11526 for (; set->cmd; ++set)
11527 (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
11528 set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
11529 set->cmd2 & CMD2_CLR ? " CLR" : "",
11530 set->cmd2 & CMD2_SET ? " SET" : "",
11531 set->cmd2 & CMD2_UBITS ? " UBITS" : "",
11532 set->cmd2 & CMD2_GBITS ? " GBITS" : "",
11533 set->cmd2 & CMD2_OBITS ? " OBITS" : "");
11534}
11535#endif
11536
11537/*
11538 * Given an array of bitcmd structures, compress by compacting consecutive
11539 * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
11540 * 'g' and 'o' commands continue to be separate. They could probably be
11541 * compacted, but it's not worth the effort.
11542 */
11543static void
11544compress_mode(set)
11545 BITCMD *set;
11546{
11547 BITCMD *nset;
11548 int setbits, clrbits, Xbits, op;
11549
11550 _DIAGASSERT(set != NULL);
11551
11552 for (nset = set;;) {
11553 /* Copy over any 'u', 'g' and 'o' commands. */
11554 while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
11555 *set++ = *nset++;
11556 if (!op)
11557 return;
11558 }
11559
11560 for (setbits = clrbits = Xbits = 0;; nset++) {
11561 if ((op = nset->cmd) == '-') {
11562 clrbits |= nset->bits;
11563 setbits &= ~nset->bits;
11564 Xbits &= ~nset->bits;
11565 } else if (op == '+') {
11566 setbits |= nset->bits;
11567 clrbits &= ~nset->bits;
11568 Xbits &= ~nset->bits;
11569 } else if (op == 'X')
11570 Xbits |= nset->bits & ~setbits;
11571 else
11572 break;
11573 }
11574 if (clrbits) {
11575 set->cmd = '-';
11576 set->cmd2 = 0;
11577 set->bits = clrbits;
11578 set++;
11579 }
11580 if (setbits) {
11581 set->cmd = '+';
11582 set->cmd2 = 0;
11583 set->bits = setbits;
11584 set++;
11585 }
11586 if (Xbits) {
11587 set->cmd = 'X';
11588 set->cmd2 = 0;
11589 set->bits = Xbits;
11590 set++;
11591 }
11592 }
11593}
11594#ifdef DEBUG 11476#ifdef DEBUG
11595static void shtree (union node *, int, char *, FILE*); 11477static void shtree (union node *, int, char *, FILE*);
11596static void shcmd (union node *, FILE *); 11478static void shcmd (union node *, FILE *);
@@ -11683,6 +11565,16 @@ shcmd(cmd, fp)
11683 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { 11565 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11684 if (! first) 11566 if (! first)
11685 putchar(' '); 11567 putchar(' ');
11568#if 1
11569 s = "*error*";
11570 dftfd = 0;
11571 if ((np->nfile.type <= NFROMFD) && (np->nfile.type >= NTO)) {
11572 s = redir_strings[np->nfile.type - NTO];
11573 if (*s == '>') {
11574 dftfd = 1;
11575 }
11576 }
11577#else
11686 switch (np->nfile.type) { 11578 switch (np->nfile.type) {
11687 case NTO: s = ">"; dftfd = 1; break; 11579 case NTO: s = ">"; dftfd = 1; break;
11688 case NAPPEND: s = ">>"; dftfd = 1; break; 11580 case NAPPEND: s = ">>"; dftfd = 1; break;
@@ -11693,6 +11585,7 @@ shcmd(cmd, fp)
11693 case NFROMTO: s = "<>"; dftfd = 0; break; 11585 case NFROMTO: s = "<>"; dftfd = 0; break;
11694 default: s = "*error*"; dftfd = 0; break; 11586 default: s = "*error*"; dftfd = 0; break;
11695 } 11587 }
11588#endif
11696 if (np->nfile.fd != dftfd) 11589 if (np->nfile.fd != dftfd)
11697 fprintf(fp, "%d", np->nfile.fd); 11590 fprintf(fp, "%d", np->nfile.fd);
11698 fputs(s, fp); 11591 fputs(s, fp);
@@ -12094,16 +11987,8 @@ setsignal(int signo)
12094 } 11987 }
12095 if (*t == S_HARD_IGN || *t == action) 11988 if (*t == S_HARD_IGN || *t == action)
12096 return; 11989 return;
12097 switch (action) { 11990 act.sa_handler = ((action == S_CATCH) ? onsig
12098 case S_CATCH: 11991 : ((action == S_IGN) ? SIG_IGN : SIG_DFL));
12099 act.sa_handler = onsig;
12100 break;
12101 case S_IGN:
12102 act.sa_handler = SIG_IGN;
12103 break;
12104 default:
12105 act.sa_handler = SIG_DFL;
12106 }
12107 *t = action; 11992 *t = action;
12108 act.sa_flags = 0; 11993 act.sa_flags = 0;
12109 sigemptyset(&act.sa_mask); 11994 sigemptyset(&act.sa_mask);
@@ -12785,7 +12670,7 @@ findvar(struct var **vpp, const char *name)
12785/* 12670/*
12786 * Copyright (c) 1999 Herbert Xu <herbert@debian.org> 12671 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12787 * This file contains code for the times builtin. 12672 * This file contains code for the times builtin.
12788 * $Id: ash.c,v 1.19 2001/08/10 18:42:04 andersen Exp $ 12673 * $Id: ash.c,v 1.20 2001/08/10 19:36:07 mjn3 Exp $
12789 */ 12674 */
12790static int timescmd (int argc, char **argv) 12675static int timescmd (int argc, char **argv)
12791{ 12676{
diff --git a/shell/ash.c b/shell/ash.c
index 91b6241c6..bbde91cd1 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -58,7 +58,7 @@
58/* Getopts is used by shell procedures to parse positional parameters. 58/* Getopts is used by shell procedures to parse positional parameters.
59 * You probably want to leave this disabled, and use the busybox getopt 59 * You probably want to leave this disabled, and use the busybox getopt
60 * applet if you want to do this sort of thing. There are some scripts 60 * applet if you want to do this sort of thing. There are some scripts
61 * out there that use it, so if you need it, enable it. Most people will 61 * out there that use it, so it you need it, enable. Most people will
62 * leave this disabled. This adds 1k on an x86 system. */ 62 * leave this disabled. This adds 1k on an x86 system. */
63#undef ASH_GETOPTS 63#undef ASH_GETOPTS
64 64
@@ -81,6 +81,7 @@
81#undef GLOB_BROKEN 81#undef GLOB_BROKEN
82 82
83#include <assert.h> 83#include <assert.h>
84#include <stddef.h>
84#include <ctype.h> 85#include <ctype.h>
85#include <dirent.h> 86#include <dirent.h>
86#include <errno.h> 87#include <errno.h>
@@ -142,13 +143,6 @@
142#define CSPCL 13 /* these terminate a word */ 143#define CSPCL 13 /* these terminate a word */
143#define CIGN 14 /* character should be ignored */ 144#define CIGN 14 /* character should be ignored */
144 145
145/* Syntax classes for is_ functions */
146#define ISDIGIT 01 /* a digit */
147#define ISUPPER 02 /* an upper case letter */
148#define ISLOWER 04 /* a lower case letter */
149#define ISUNDER 010 /* an underscore */
150#define ISSPECL 020 /* the name of a special parameter */
151
152#define SYNBASE 130 146#define SYNBASE 130
153#define PEOF -130 147#define PEOF -130
154 148
@@ -156,18 +150,18 @@
156 150
157#define TEOF 0 151#define TEOF 0
158#define TNL 1 152#define TNL 1
159#define TSEMI 2 153#define TREDIR 2
160#define TBACKGND 3 154#define TWORD 3
161#define TAND 4 155#define TASSIGN 4
162#define TOR 5 156#define TSEMI 5
163#define TPIPE 6 157#define TBACKGND 6
164#define TLP 7 158#define TAND 7
165#define TRP 8 159#define TOR 8
166#define TENDCASE 9 160#define TPIPE 9
167#define TENDBQUOTE 10 161#define TLP 10
168#define TREDIR 11 162#define TRP 11
169#define TWORD 12 163#define TENDCASE 12
170#define TASSIGN 13 164#define TENDBQUOTE 13
171#define TNOT 14 165#define TNOT 14
172#define TCASE 15 166#define TCASE 15
173#define TDO 16 167#define TDO 16
@@ -186,10 +180,6 @@
186#define TEND 29 180#define TEND 29
187 181
188 182
189#define BASESYNTAX (basesyntax + SYNBASE)
190#define DQSYNTAX (dqsyntax + SYNBASE)
191#define SQSYNTAX (sqsyntax + SYNBASE)
192#define ARISYNTAX (arisyntax + SYNBASE)
193 183
194/* control characters in argument strings */ 184/* control characters in argument strings */
195#define CTLESC '\201' 185#define CTLESC '\201'
@@ -202,11 +192,19 @@
202#define CTLENDARI '\207' 192#define CTLENDARI '\207'
203#define CTLQUOTEMARK '\210' 193#define CTLQUOTEMARK '\210'
204 194
195
205#define is_digit(c) ((c)>='0' && (c)<='9') 196#define is_digit(c) ((c)>='0' && (c)<='9')
206#define is_alpha(c) (((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))
207#define is_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c)))) 197#define is_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
208#define is_in_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c)))) 198#define is_in_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
209#define is_special(c) ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT)) 199
200/*
201 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
202 * (assuming ascii char codes, as the original implementation did)
203 */
204#define is_special(c) \
205 ( (((unsigned int)c) - 33 < 32) \
206 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
207
210#define digit_val(c) ((c) - '0') 208#define digit_val(c) ((c) - '0')
211 209
212 210
@@ -688,6 +686,7 @@ static void out2fmt (const char *, ...)
688static int xwrite (int, const char *, int); 686static int xwrite (int, const char *, int);
689 687
690#define outstr(p,file) fputs(p, file) 688#define outstr(p,file) fputs(p, file)
689static void outstr (const char *p, FILE *file) { fputs(p, file); }
691static void out1str(const char *p) { outstr(p, stdout); } 690static void out1str(const char *p) { outstr(p, stdout); }
692static void out2str(const char *p) { outstr(p, stderr); } 691static void out2str(const char *p) { outstr(p, stderr); }
693 692
@@ -697,439 +696,398 @@ static void out2str(const char *p) { outstr(p, stderr); }
697static void out2c(int c) { putc(c, stderr); } 696static void out2c(int c) { putc(c, stderr); }
698#endif 697#endif
699 698
700/* syntax table used when not in quotes */
701static const char basesyntax[257] = {
702 CENDFILE, CSPCL, CWORD, CCTL,
703 CCTL, CCTL, CCTL, CCTL,
704 CCTL, CCTL, CCTL, CWORD,
705 CWORD, CWORD, CWORD, CWORD,
706 CWORD, CWORD, CWORD, CWORD,
707 CWORD, CWORD, CWORD, CWORD,
708 CWORD, CWORD, CWORD, CWORD,
709 CWORD, CWORD, CWORD, CWORD,
710 CWORD, CWORD, CWORD, CWORD,
711 CWORD, CWORD, CWORD, CWORD,
712 CWORD, CWORD, CWORD, CWORD,
713 CWORD, CWORD, CWORD, CWORD,
714 CWORD, CWORD, CWORD, CWORD,
715 CWORD, CWORD, CWORD, CWORD,
716 CWORD, CWORD, CWORD, CWORD,
717 CWORD, CWORD, CWORD, CWORD,
718 CWORD, CWORD, CWORD, CWORD,
719 CWORD, CWORD, CWORD, CWORD,
720 CWORD, CWORD, CWORD, CWORD,
721 CWORD, CWORD, CWORD, CWORD,
722 CWORD, CWORD, CWORD, CWORD,
723 CWORD, CWORD, CWORD, CWORD,
724 CWORD, CWORD, CWORD, CWORD,
725 CWORD, CWORD, CWORD, CWORD,
726 CWORD, CWORD, CWORD, CWORD,
727 CWORD, CWORD, CWORD, CWORD,
728 CWORD, CWORD, CWORD, CWORD,
729 CWORD, CWORD, CWORD, CWORD,
730 CWORD, CWORD, CWORD, CWORD,
731 CWORD, CWORD, CWORD, CWORD,
732 CWORD, CWORD, CWORD, CWORD,
733 CWORD, CWORD, CWORD, CWORD,
734 CWORD, CWORD, CWORD, CWORD,
735 CWORD, CWORD, CWORD, CWORD,
736 CWORD, CWORD, CWORD, CSPCL,
737 CNL, CWORD, CWORD, CWORD,
738 CWORD, CWORD, CWORD, CWORD,
739 CWORD, CWORD, CWORD, CWORD,
740 CWORD, CWORD, CWORD, CWORD,
741 CWORD, CWORD, CWORD, CWORD,
742 CWORD, CWORD, CSPCL, CWORD,
743 CDQUOTE, CWORD, CVAR, CWORD,
744 CSPCL, CSQUOTE, CSPCL, CSPCL,
745 CWORD, CWORD, CWORD, CWORD,
746 CWORD, CWORD, CWORD, CWORD,
747 CWORD, CWORD, CWORD, CWORD,
748 CWORD, CWORD, CWORD, CWORD,
749 CWORD, CSPCL, CSPCL, CWORD,
750 CSPCL, CWORD, CWORD, CWORD,
751 CWORD, CWORD, CWORD, CWORD,
752 CWORD, CWORD, CWORD, CWORD,
753 CWORD, CWORD, CWORD, CWORD,
754 CWORD, CWORD, CWORD, CWORD,
755 CWORD, CWORD, CWORD, CWORD,
756 CWORD, CWORD, CWORD, CWORD,
757 CWORD, CWORD, CBACK, CWORD,
758 CWORD, CWORD, CBQUOTE, CWORD,
759 CWORD, CWORD, CWORD, CWORD,
760 CWORD, CWORD, CWORD, CWORD,
761 CWORD, CWORD, CWORD, CWORD,
762 CWORD, CWORD, CWORD, CWORD,
763 CWORD, CWORD, CWORD, CWORD,
764 CWORD, CWORD, CWORD, CWORD,
765 CWORD, CWORD, CSPCL, CENDVAR,
766 CWORD
767};
768
769/* syntax table used when in double quotes */
770static const char dqsyntax[257] = {
771 CENDFILE, CIGN, CWORD, CCTL,
772 CCTL, CCTL, CCTL, CCTL,
773 CCTL, CCTL, CCTL, CWORD,
774 CWORD, CWORD, CWORD, CWORD,
775 CWORD, CWORD, CWORD, CWORD,
776 CWORD, CWORD, CWORD, CWORD,
777 CWORD, CWORD, CWORD, CWORD,
778 CWORD, CWORD, CWORD, CWORD,
779 CWORD, CWORD, CWORD, CWORD,
780 CWORD, CWORD, CWORD, CWORD,
781 CWORD, CWORD, CWORD, CWORD,
782 CWORD, CWORD, CWORD, CWORD,
783 CWORD, CWORD, CWORD, CWORD,
784 CWORD, CWORD, CWORD, CWORD,
785 CWORD, CWORD, CWORD, CWORD,
786 CWORD, CWORD, CWORD, CWORD,
787 CWORD, CWORD, CWORD, CWORD,
788 CWORD, CWORD, CWORD, CWORD,
789 CWORD, CWORD, CWORD, CWORD,
790 CWORD, CWORD, CWORD, CWORD,
791 CWORD, CWORD, CWORD, CWORD,
792 CWORD, CWORD, CWORD, CWORD,
793 CWORD, CWORD, CWORD, CWORD,
794 CWORD, CWORD, CWORD, CWORD,
795 CWORD, CWORD, CWORD, CWORD,
796 CWORD, CWORD, CWORD, CWORD,
797 CWORD, CWORD, CWORD, CWORD,
798 CWORD, CWORD, CWORD, CWORD,
799 CWORD, CWORD, CWORD, CWORD,
800 CWORD, CWORD, CWORD, CWORD,
801 CWORD, CWORD, CWORD, CWORD,
802 CWORD, CWORD, CWORD, CWORD,
803 CWORD, CWORD, CWORD, CWORD,
804 CWORD, CWORD, CWORD, CWORD,
805 CWORD, CWORD, CWORD, CWORD,
806 CNL, CWORD, CWORD, CWORD,
807 CWORD, CWORD, CWORD, CWORD,
808 CWORD, CWORD, CWORD, CWORD,
809 CWORD, CWORD, CWORD, CWORD,
810 CWORD, CWORD, CWORD, CWORD,
811 CWORD, CWORD, CWORD, CCTL,
812 CENDQUOTE,CWORD, CVAR, CWORD,
813 CWORD, CWORD, CWORD, CWORD,
814 CCTL, CWORD, CWORD, CCTL,
815 CWORD, CCTL, CWORD, CWORD,
816 CWORD, CWORD, CWORD, CWORD,
817 CWORD, CWORD, CWORD, CWORD,
818 CCTL, CWORD, CWORD, CCTL,
819 CWORD, CCTL, CWORD, CWORD,
820 CWORD, CWORD, CWORD, CWORD,
821 CWORD, CWORD, CWORD, CWORD,
822 CWORD, CWORD, CWORD, CWORD,
823 CWORD, CWORD, CWORD, CWORD,
824 CWORD, CWORD, CWORD, CWORD,
825 CWORD, CWORD, CWORD, CWORD,
826 CWORD, CCTL, CBACK, CCTL,
827 CWORD, CWORD, CBQUOTE, CWORD,
828 CWORD, CWORD, CWORD, CWORD,
829 CWORD, CWORD, CWORD, CWORD,
830 CWORD, CWORD, CWORD, CWORD,
831 CWORD, CWORD, CWORD, CWORD,
832 CWORD, CWORD, CWORD, CWORD,
833 CWORD, CWORD, CWORD, CWORD,
834 CWORD, CWORD, CWORD, CENDVAR,
835 CCTL
836};
837 699
838/* syntax table used when in single quotes */ 700#ifdef ASH_OPTIMIZE_FOR_SIZE
839static const char sqsyntax[257] = { 701#define USE_SIT_FUNCTION
840 CENDFILE, CIGN, CWORD, CCTL, 702#endif
841 CCTL, CCTL, CCTL, CCTL, 703
842 CCTL, CCTL, CCTL, CWORD, 704/* number syntax index */
843 CWORD, CWORD, CWORD, CWORD, 705#define BASESYNTAX 0 /* not in quotes */
844 CWORD, CWORD, CWORD, CWORD, 706#define DQSYNTAX 1 /* in double quotes */
845 CWORD, CWORD, CWORD, CWORD, 707#define SQSYNTAX 2 /* in single quotes */
846 CWORD, CWORD, CWORD, CWORD, 708#define ARISYNTAX 3 /* in arithmetic */
847 CWORD, CWORD, CWORD, CWORD, 709
848 CWORD, CWORD, CWORD, CWORD, 710static const char S_I_T[][4] = {
849 CWORD, CWORD, CWORD, CWORD, 711 /* 0 */ { CSPCL, CIGN, CIGN, CIGN }, /* PEOA */
850 CWORD, CWORD, CWORD, CWORD, 712 /* 1 */ { CSPCL, CWORD, CWORD, CWORD }, /* ' ' */
851 CWORD, CWORD, CWORD, CWORD, 713 /* 2 */ { CNL, CNL, CNL, CNL }, /* \n */
852 CWORD, CWORD, CWORD, CWORD, 714 /* 3 */ { CWORD, CCTL, CCTL, CWORD }, /* !*-/:=?[]~ */
853 CWORD, CWORD, CWORD, CWORD, 715 /* 4 */ { CDQUOTE, CENDQUOTE, CWORD, CDQUOTE }, /* '"' */
854 CWORD, CWORD, CWORD, CWORD, 716 /* 5 */ { CVAR, CVAR, CWORD, CVAR }, /* $ */
855 CWORD, CWORD, CWORD, CWORD, 717 /* 6 */ { CSQUOTE, CWORD, CENDQUOTE, CSQUOTE }, /* "'" */
856 CWORD, CWORD, CWORD, CWORD, 718 /* 7 */ { CSPCL, CWORD, CWORD, CLP }, /* ( */
857 CWORD, CWORD, CWORD, CWORD, 719 /* 8 */ { CSPCL, CWORD, CWORD, CRP }, /* ) */
858 CWORD, CWORD, CWORD, CWORD, 720 /* 9 */ { CBACK, CBACK, CCTL, CBACK }, /* \ */
859 CWORD, CWORD, CWORD, CWORD, 721 /* 10 */ { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* ` */
860 CWORD, CWORD, CWORD, CWORD, 722 /* 11 */ { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* } */
861 CWORD, CWORD, CWORD, CWORD, 723#ifndef USE_SIT_FUNCTION
862 CWORD, CWORD, CWORD, CWORD, 724 /* 12 */ { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* PEOF */
863 CWORD, CWORD, CWORD, CWORD, 725 /* 13 */ { CWORD, CWORD, CWORD, CWORD }, /* 0-9A-Za-z */
864 CWORD, CWORD, CWORD, CWORD, 726 /* 14 */ { CCTL, CCTL, CCTL, CCTL } /* CTLESC ... */
865 CWORD, CWORD, CWORD, CWORD, 727#endif
866 CWORD, CWORD, CWORD, CWORD,
867 CWORD, CWORD, CWORD, CWORD,
868 CWORD, CWORD, CWORD, CWORD,
869 CWORD, CWORD, CWORD, CWORD,
870 CWORD, CWORD, CWORD, CWORD,
871 CWORD, CWORD, CWORD, CWORD,
872 CWORD, CWORD, CWORD, CWORD,
873 CWORD, CWORD, CWORD, CWORD,
874 CWORD, CWORD, CWORD, CWORD,
875 CNL, CWORD, CWORD, CWORD,
876 CWORD, CWORD, CWORD, CWORD,
877 CWORD, CWORD, CWORD, CWORD,
878 CWORD, CWORD, CWORD, CWORD,
879 CWORD, CWORD, CWORD, CWORD,
880 CWORD, CWORD, CWORD, CCTL,
881 CWORD, CWORD, CWORD, CWORD,
882 CWORD, CENDQUOTE,CWORD, CWORD,
883 CCTL, CWORD, CWORD, CCTL,
884 CWORD, CCTL, CWORD, CWORD,
885 CWORD, CWORD, CWORD, CWORD,
886 CWORD, CWORD, CWORD, CWORD,
887 CCTL, CWORD, CWORD, CCTL,
888 CWORD, CCTL, CWORD, CWORD,
889 CWORD, CWORD, CWORD, CWORD,
890 CWORD, CWORD, CWORD, CWORD,
891 CWORD, CWORD, CWORD, CWORD,
892 CWORD, CWORD, CWORD, CWORD,
893 CWORD, CWORD, CWORD, CWORD,
894 CWORD, CWORD, CWORD, CWORD,
895 CWORD, CCTL, CCTL, CCTL,
896 CWORD, CWORD, CWORD, CWORD,
897 CWORD, CWORD, CWORD, CWORD,
898 CWORD, CWORD, CWORD, CWORD,
899 CWORD, CWORD, CWORD, CWORD,
900 CWORD, CWORD, CWORD, CWORD,
901 CWORD, CWORD, CWORD, CWORD,
902 CWORD, CWORD, CWORD, CWORD,
903 CWORD, CWORD, CWORD, CWORD,
904 CCTL
905};
906
907/* syntax table used when in arithmetic */
908static const char arisyntax[257] = {
909 CENDFILE, CIGN, CWORD, CCTL,
910 CCTL, CCTL, CCTL, CCTL,
911 CCTL, CCTL, CCTL, CWORD,
912 CWORD, CWORD, CWORD, CWORD,
913 CWORD, CWORD, CWORD, CWORD,
914 CWORD, CWORD, CWORD, CWORD,
915 CWORD, CWORD, CWORD, CWORD,
916 CWORD, CWORD, CWORD, CWORD,
917 CWORD, CWORD, CWORD, CWORD,
918 CWORD, CWORD, CWORD, CWORD,
919 CWORD, CWORD, CWORD, CWORD,
920 CWORD, CWORD, CWORD, CWORD,
921 CWORD, CWORD, CWORD, CWORD,
922 CWORD, CWORD, CWORD, CWORD,
923 CWORD, CWORD, CWORD, CWORD,
924 CWORD, CWORD, CWORD, CWORD,
925 CWORD, CWORD, CWORD, CWORD,
926 CWORD, CWORD, CWORD, CWORD,
927 CWORD, CWORD, CWORD, CWORD,
928 CWORD, CWORD, CWORD, CWORD,
929 CWORD, CWORD, CWORD, CWORD,
930 CWORD, CWORD, CWORD, CWORD,
931 CWORD, CWORD, CWORD, CWORD,
932 CWORD, CWORD, CWORD, CWORD,
933 CWORD, CWORD, CWORD, CWORD,
934 CWORD, CWORD, CWORD, CWORD,
935 CWORD, CWORD, CWORD, CWORD,
936 CWORD, CWORD, CWORD, CWORD,
937 CWORD, CWORD, CWORD, CWORD,
938 CWORD, CWORD, CWORD, CWORD,
939 CWORD, CWORD, CWORD, CWORD,
940 CWORD, CWORD, CWORD, CWORD,
941 CWORD, CWORD, CWORD, CWORD,
942 CWORD, CWORD, CWORD, CWORD,
943 CWORD, CWORD, CWORD, CWORD,
944 CNL, CWORD, CWORD, CWORD,
945 CWORD, CWORD, CWORD, CWORD,
946 CWORD, CWORD, CWORD, CWORD,
947 CWORD, CWORD, CWORD, CWORD,
948 CWORD, CWORD, CWORD, CWORD,
949 CWORD, CWORD, CWORD, CWORD,
950 CDQUOTE, CWORD, CVAR, CWORD,
951 CWORD, CSQUOTE, CLP, CRP,
952 CWORD, CWORD, CWORD, CWORD,
953 CWORD, CWORD, CWORD, CWORD,
954 CWORD, CWORD, CWORD, CWORD,
955 CWORD, CWORD, CWORD, CWORD,
956 CWORD, CWORD, CWORD, CWORD,
957 CWORD, CWORD, CWORD, CWORD,
958 CWORD, CWORD, CWORD, CWORD,
959 CWORD, CWORD, CWORD, CWORD,
960 CWORD, CWORD, CWORD, CWORD,
961 CWORD, CWORD, CWORD, CWORD,
962 CWORD, CWORD, CWORD, CWORD,
963 CWORD, CWORD, CWORD, CWORD,
964 CWORD, CWORD, CBACK, CWORD,
965 CWORD, CWORD, CBQUOTE, CWORD,
966 CWORD, CWORD, CWORD, CWORD,
967 CWORD, CWORD, CWORD, CWORD,
968 CWORD, CWORD, CWORD, CWORD,
969 CWORD, CWORD, CWORD, CWORD,
970 CWORD, CWORD, CWORD, CWORD,
971 CWORD, CWORD, CWORD, CWORD,
972 CWORD, CWORD, CWORD, CENDVAR,
973 CWORD
974}; 728};
975 729
976/* character classification table */ 730#ifdef USE_SIT_FUNCTION
977static const char is_type[257] = {
978 0, 0, 0, 0,
979 0, 0, 0, 0,
980 0, 0, 0, 0,
981 0, 0, 0, 0,
982 0, 0, 0, 0,
983 0, 0, 0, 0,
984 0, 0, 0, 0,
985 0, 0, 0, 0,
986 0, 0, 0, 0,
987 0, 0, 0, 0,
988 0, 0, 0, 0,
989 0, 0, 0, 0,
990 0, 0, 0, 0,
991 0, 0, 0, 0,
992 0, 0, 0, 0,
993 0, 0, 0, 0,
994 0, 0, 0, 0,
995 0, 0, 0, 0,
996 0, 0, 0, 0,
997 0, 0, 0, 0,
998 0, 0, 0, 0,
999 0, 0, 0, 0,
1000 0, 0, 0, 0,
1001 0, 0, 0, 0,
1002 0, 0, 0, 0,
1003 0, 0, 0, 0,
1004 0, 0, 0, 0,
1005 0, 0, 0, 0,
1006 0, 0, 0, 0,
1007 0, 0, 0, 0,
1008 0, 0, 0, 0,
1009 0, 0, 0, 0,
1010 0, 0, 0, 0,
1011 0, 0, 0, 0,
1012 0, 0, 0, 0,
1013 0, 0, 0, 0,
1014 0, 0, 0, 0,
1015 0, 0, 0, 0,
1016 0, 0, 0, 0,
1017 0, 0, 0, 0,
1018 0, 0, 0, ISSPECL,
1019 0, ISSPECL, ISSPECL, 0,
1020 0, 0, 0, 0,
1021 ISSPECL, 0, 0, ISSPECL,
1022 0, 0, ISDIGIT, ISDIGIT,
1023 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1024 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1025 0, 0, 0, 0,
1026 0, ISSPECL, ISSPECL, ISUPPER,
1027 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1028 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1029 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1030 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1031 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1032 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1033 ISUPPER, 0, 0, 0,
1034 0, ISUNDER, 0, ISLOWER,
1035 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1036 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1037 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1038 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1039 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1040 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1041 ISLOWER, 0, 0, 0,
1042 0
1043};
1044 731
1045/* Array indicating which tokens mark the end of a list */ 732#define U_C(c) ((unsigned char)(c))
1046static const char tokendlist[] = {
1047 1,
1048 0,
1049 0,
1050 0,
1051 0,
1052 0,
1053 0,
1054 0,
1055 1,
1056 1,
1057 1,
1058 0,
1059 0,
1060 0,
1061 0,
1062 0,
1063 1,
1064 1,
1065 1,
1066 1,
1067 1,
1068 1,
1069 0,
1070 0,
1071 0,
1072 1,
1073 0,
1074 0,
1075 0,
1076 1,
1077};
1078 733
1079static const char *const tokname[] = { 734static int SIT(int c, int syntax)
1080 "end of file", 735{
1081 "newline", 736 static const char spec_symbls[]="\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
1082 "\";\"", 737 static const char syntax_index_table [] = {
1083 "\"&\"", 738 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
1084 "\"&&\"", 739 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
1085 "\"||\"", 740 3, 1, 3, 3, 9, 3,10, 1, /* "=>?[\\]`|" */
1086 "\"|\"", 741 11,3 }; /* "}~" */
1087 "\"(\"", 742 const char *s;
1088 "\")\"", 743 int indx;
1089 "\";;\"", 744
1090 "\"`\"", 745 if(c==PEOF) /* 2^8+2 */
1091 "redirection", 746 return CENDFILE;
1092 "word", 747 if(c==PEOA) /* 2^8+1 */
1093 "assignment", 748 indx = 0;
1094 "\"!\"", 749 else if(U_C(c)>=U_C(CTLESC) && U_C(c)<=U_C(CTLQUOTEMARK))
1095 "\"case\"", 750 return CCTL;
1096 "\"do\"", 751 else {
1097 "\"done\"", 752 s = strchr(spec_symbls, c);
1098 "\"elif\"", 753 if(s==0)
1099 "\"else\"", 754 return CWORD;
1100 "\"esac\"", 755 indx = syntax_index_table[(s-spec_symbls)];
1101 "\"fi\"", 756 }
1102 "\"for\"", 757 return S_I_T[indx][syntax];
1103 "\"if\"", 758}
1104 "\"in\"", 759
1105 "\"then\"", 760#else /* USE_SIT_FUNCTION */
1106 "\"until\"", 761
1107 "\"while\"", 762#define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
1108 "\"{\"", 763
1109 "\"}\"", 764#define CSPCL_CIGN_CIGN_CIGN 0
765#define CSPCL_CWORD_CWORD_CWORD 1
766#define CNL_CNL_CNL_CNL 2
767#define CWORD_CCTL_CCTL_CWORD 3
768#define CDQUOTE_CENDQUOTE_CWORD_CDQUOTE 4
769#define CVAR_CVAR_CWORD_CVAR 5
770#define CSQUOTE_CWORD_CENDQUOTE_CSQUOTE 6
771#define CSPCL_CWORD_CWORD_CLP 7
772#define CSPCL_CWORD_CWORD_CRP 8
773#define CBACK_CBACK_CCTL_CBACK 9
774#define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
775#define CENDVAR_CENDVAR_CWORD_CENDVAR 11
776#define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
777#define CWORD_CWORD_CWORD_CWORD 13
778#define CCTL_CCTL_CCTL_CCTL 14
779
780static const char syntax_index_table[258] = {
781 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
782 /* 0 -130 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
783 /* 1 -129 PEOA */ CSPCL_CIGN_CIGN_CIGN,
784 /* 2 -128 0xff */ CWORD_CWORD_CWORD_CWORD,
785 /* 3 -127 */ CCTL_CCTL_CCTL_CCTL, /* CTLQUOTEMARK */
786 /* 4 -126 */ CCTL_CCTL_CCTL_CCTL,
787 /* 5 -125 */ CCTL_CCTL_CCTL_CCTL,
788 /* 6 -124 */ CCTL_CCTL_CCTL_CCTL,
789 /* 7 -123 */ CCTL_CCTL_CCTL_CCTL,
790 /* 8 -122 */ CCTL_CCTL_CCTL_CCTL,
791 /* 9 -121 */ CCTL_CCTL_CCTL_CCTL,
792 /* 10 -120 */ CCTL_CCTL_CCTL_CCTL, /* CTLESC */
793 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
794 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
795 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
796 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
797 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
798 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
799 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
800 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
801 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
802 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
803 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
804 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
805 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
806 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
807 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
808 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
809 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
810 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
811 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
812 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
813 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
814 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
815 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
816 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
817 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
818 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
819 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
820 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
821 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
822 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
823 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
824 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
825 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
826 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
827 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
828 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
829 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
830 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
831 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
832 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
833 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
834 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
835 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
836 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
837 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
838 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
839 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
840 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
841 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
842 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
843 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
844 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
845 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
846 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
847 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
848 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
849 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
850 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
851 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
852 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
853 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
854 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
855 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
856 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
857 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
858 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
859 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
860 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
861 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
862 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
863 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
864 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
865 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
866 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
867 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
868 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
869 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
870 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
871 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
872 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
873 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
874 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
875 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
876 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
877 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
878 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
879 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
880 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
881 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
882 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
883 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
884 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
885 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
886 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
887 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
888 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
889 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
890 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
891 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
892 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
893 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
894 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
895 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
896 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
897 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
898 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
899 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
900 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
901 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
902 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
903 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
904 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
905 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
906 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
907 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
908 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
909 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
910 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
911 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
912 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
913 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
914 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
915 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
916 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
917 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
918 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
919 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
920 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
921 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
922 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
923 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
924 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
925 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
926 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
927 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
928 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
929 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
930 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
931 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
932 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
933 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
934 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
935 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
936 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
937 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
938 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
939 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
940 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
941 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
942 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
943 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
944 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
945 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
946 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CDQUOTE,
947 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
948 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
949 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
950 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
951 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CSQUOTE,
952 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
953 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
954 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
955 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
956 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
957 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
958 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
959 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
960 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
961 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
962 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
963 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
964 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
965 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
966 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
967 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
968 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
969 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
970 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
971 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
972 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
973 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
974 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
975 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
976 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
977 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
978 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
979 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
980 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
981 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
982 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
983 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
984 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
985 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
986 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
987 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
988 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
989 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
990 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
991 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
992 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
993 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
994 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
995 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
996 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
997 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
998 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
999 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
1000 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
1001 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
1002 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
1003 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
1004 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
1005 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
1006 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
1007 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
1008 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1009 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
1010 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
1011 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
1012 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
1013 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
1014 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
1015 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
1016 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
1017 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
1018 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
1019 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
1020 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
1021 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
1022 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
1023 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
1024 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
1025 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
1026 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
1027 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
1028 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
1029 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
1030 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
1031 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
1032 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
1033 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
1034 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
1035 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
1036 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
1037 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1038 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
1039 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
1110}; 1040};
1111 1041
1042#endif /* USE_SIT_FUNCTION */
1043
1044
1045/* first char is indicating which tokens mark the end of a list */
1046static const char *const tokname_array[] = {
1047 "\1end of file",
1048 "\0newline",
1049 "\0redirection",
1050 "\0word",
1051 "\0assignment",
1052 "\0;",
1053 "\0&",
1054 "\0&&",
1055 "\0||",
1056 "\0|",
1057 "\0(",
1058 "\1)",
1059 "\1;;",
1060 "\1`",
1112#define KWDOFFSET 14 1061#define KWDOFFSET 14
1113 1062 /* the following are keywords */
1114static const char *const parsekwd[] = { 1063 "\0!",
1115 "!", 1064 "\0case",
1116 "case", 1065 "\1do",
1117 "do", 1066 "\1done",
1118 "done", 1067 "\1elif",
1119 "elif", 1068 "\1else",
1120 "else", 1069 "\1esac",
1121 "esac", 1070 "\1fi",
1122 "fi", 1071 "\0for",
1123 "for", 1072 "\0if",
1124 "if", 1073 "\0in",
1125 "in", 1074 "\1then",
1126 "then", 1075 "\0until",
1127 "until", 1076 "\0while",
1128 "while", 1077 "\0{",
1129 "{", 1078 "\1}",
1130 "}"
1131}; 1079};
1132 1080
1081static const char *tokname(int tok)
1082{
1083 static char buf[16];
1084
1085 if(tok>=TSEMI)
1086 buf[0] = '"';
1087 sprintf(buf+(tok>=TSEMI), "%s%c",
1088 tokname_array[tok]+1, (tok>=TSEMI ? '"' : 0));
1089 return buf;
1090}
1133 1091
1134static int plinno = 1; /* input line number */ 1092static int plinno = 1; /* input line number */
1135 1093
@@ -1562,8 +1520,8 @@ __lookupalias(const char *name) {
1562 1520
1563#ifdef ASH_MATH_SUPPORT 1521#ifdef ASH_MATH_SUPPORT
1564/* The generated file arith.c has been replaced with a custom hand 1522/* The generated file arith.c has been replaced with a custom hand
1565 * written implementation written by Aaron Lehmann <aaronl@vitelus.com>. 1523 * written implementation written by Aaron Lehmann <aaronl@vitelus.com>.
1566 * This is now part of libbb, so that it can be used by all the shells 1524 * This is now part of libbb, so that it can be used by all the shells
1567 * in busybox. */ 1525 * in busybox. */
1568#define ARITH_NUM 257 1526#define ARITH_NUM 257
1569#define ARITH_LPAREN 258 1527#define ARITH_LPAREN 258
@@ -1744,7 +1702,7 @@ static const struct builtincmd builtincmds[] = {
1744}; 1702};
1745#define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) ) 1703#define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) )
1746 1704
1747static const struct builtincmd *DOTCMD = &builtincmds[0]; 1705#define DOTCMD &builtincmds[0]
1748static struct builtincmd *BLTINCMD; 1706static struct builtincmd *BLTINCMD;
1749static struct builtincmd *EXECCMD; 1707static struct builtincmd *EXECCMD;
1750static struct builtincmd *EVALCMD; 1708static struct builtincmd *EVALCMD;
@@ -2165,7 +2123,7 @@ exverror(int cond, const char *msg, va_list ap)
2165} 2123}
2166 2124
2167 2125
2168static void 2126static void
2169error(const char *msg, ...) 2127error(const char *msg, ...)
2170{ 2128{
2171 va_list ap; 2129 va_list ap;
@@ -3690,7 +3648,7 @@ padvance(const char **path, const char *name)
3690static int 3648static int
3691pstrcmp(const void *a, const void *b) 3649pstrcmp(const void *a, const void *b)
3692{ 3650{
3693 return strcmp((const char *) a, *(const char *const *) b); 3651 return strcmp((const char *) a, (*(const char *const *) b) + 1);
3694} 3652}
3695 3653
3696/* 3654/*
@@ -3700,8 +3658,9 @@ pstrcmp(const void *a, const void *b)
3700static const char *const * 3658static const char *const *
3701findkwd(const char *s) 3659findkwd(const char *s)
3702{ 3660{
3703 return bsearch(s, parsekwd, sizeof(parsekwd) / sizeof(const char *), 3661 return bsearch(s, tokname_array + KWDOFFSET,
3704 sizeof(const char *), pstrcmp); 3662 (sizeof(tokname_array)/sizeof(const char *)) - KWDOFFSET,
3663 sizeof(const char *), pstrcmp);
3705} 3664}
3706 3665
3707 3666
@@ -4228,7 +4187,7 @@ delete_cmd_entry() {
4228 4187
4229 4188
4230 4189
4231static const short nodesize[26] = { 4190static const unsigned char nodesize[26] = {
4232 ALIGN(sizeof (struct nbinary)), 4191 ALIGN(sizeof (struct nbinary)),
4233 ALIGN(sizeof (struct ncmd)), 4192 ALIGN(sizeof (struct ncmd)),
4234 ALIGN(sizeof (struct npipe)), 4193 ALIGN(sizeof (struct npipe)),
@@ -4412,7 +4371,7 @@ static char *exptilde (char *, int);
4412static void expbackq (union node *, int, int); 4371static void expbackq (union node *, int, int);
4413static int subevalvar (char *, char *, int, int, int, int, int); 4372static int subevalvar (char *, char *, int, int, int, int, int);
4414static int varisset (char *, int); 4373static int varisset (char *, int);
4415static void strtodest (const char *, const char *, int); 4374static void strtodest (const char *, int, int);
4416static void varvalue (char *, int, int); 4375static void varvalue (char *, int, int);
4417static void recordregion (int, int, int); 4376static void recordregion (int, int, int);
4418static void removerecordregions (int); 4377static void removerecordregions (int);
@@ -4916,7 +4875,7 @@ expbackq(cmd, quoted, flag)
4916 struct nodelist *volatile saveargbackq; 4875 struct nodelist *volatile saveargbackq;
4917 char lastc; 4876 char lastc;
4918 int startloc = dest - stackblock(); 4877 int startloc = dest - stackblock();
4919 char const *syntax = quoted? DQSYNTAX : BASESYNTAX; 4878 int syntax = quoted ? DQSYNTAX : BASESYNTAX;
4920 volatile int saveherefd; 4879 volatile int saveherefd;
4921 int quotes = flag & (EXP_FULL | EXP_CASE); 4880 int quotes = flag & (EXP_FULL | EXP_CASE);
4922 struct jmploc jmploc; 4881 struct jmploc jmploc;
@@ -4973,7 +4932,7 @@ err1:
4973 } 4932 }
4974 lastc = *p++; 4933 lastc = *p++;
4975 if (lastc != '\0') { 4934 if (lastc != '\0') {
4976 if (quotes && syntax[(int)lastc] == CCTL) 4935 if (quotes && SIT(lastc, syntax) == CCTL)
4977 STPUTC(CTLESC, dest); 4936 STPUTC(CTLESC, dest);
4978 STPUTC(lastc, dest); 4937 STPUTC(lastc, dest);
4979 } 4938 }
@@ -5174,13 +5133,10 @@ varisset(name, nulok)
5174 */ 5133 */
5175 5134
5176static void 5135static void
5177strtodest(p, syntax, quotes) 5136strtodest(const char *p, int syntax, int quotes)
5178 const char *p;
5179 const char *syntax;
5180 int quotes;
5181{ 5137{
5182 while (*p) { 5138 while (*p) {
5183 if (quotes && syntax[(int) *p] == CCTL) 5139 if (quotes && SIT(*p,syntax) == CCTL)
5184 STPUTC(CTLESC, expdest); 5140 STPUTC(CTLESC, expdest);
5185 STPUTC(*p++, expdest); 5141 STPUTC(*p++, expdest);
5186 } 5142 }
@@ -5191,10 +5147,7 @@ strtodest(p, syntax, quotes)
5191 */ 5147 */
5192 5148
5193static void 5149static void
5194varvalue(name, quoted, flags) 5150varvalue(char *name, int quoted, int flags)
5195 char *name;
5196 int quoted;
5197 int flags;
5198{ 5151{
5199 int num; 5152 int num;
5200 char *p; 5153 char *p;
@@ -5202,7 +5155,7 @@ varvalue(name, quoted, flags)
5202 int sep; 5155 int sep;
5203 int sepq = 0; 5156 int sepq = 0;
5204 char **ap; 5157 char **ap;
5205 char const *syntax; 5158 int syntax;
5206 int allow_split = flags & EXP_FULL; 5159 int allow_split = flags & EXP_FULL;
5207 int quotes = flags & (EXP_FULL | EXP_CASE); 5160 int quotes = flags & (EXP_FULL | EXP_CASE);
5208 5161
@@ -5237,7 +5190,7 @@ numvar:
5237 case '*': 5190 case '*':
5238 sep = ifsset() ? ifsval()[0] : ' '; 5191 sep = ifsset() ? ifsval()[0] : ' ';
5239 if (quotes) { 5192 if (quotes) {
5240 sepq = syntax[(int) sep] == CCTL; 5193 sepq = SIT(sep,syntax) == CCTL;
5241 } 5194 }
5242param: 5195param:
5243 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { 5196 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
@@ -5572,7 +5525,7 @@ expmeta(enddir, name)
5572 break; 5525 break;
5573 } 5526 }
5574 } 5527 }
5575 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) { 5528 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) {
5576 metaflag = 1; 5529 metaflag = 1;
5577 } else if (*p == '\0') 5530 } else if (*p == '\0')
5578 break; 5531 break;
@@ -7341,10 +7294,219 @@ cmdputs(const char *s)
7341 cmdnextc = q; 7294 cmdnextc = q;
7342} 7295}
7343 7296
7297//#define CMDTXT_TABLE
7298#ifdef CMDTXT_TABLE
7299/*
7300 * To collect a lot of redundant code in cmdtxt() case statements, we
7301 * implement a mini language here. Each type of node struct has an
7302 * associated instruction sequence that operates on its members via
7303 * their offsets. The instruction are pack in unsigned chars with
7304 * format IIDDDDDE where the bits are
7305 * I : part of the instruction opcode, which are
7306 * 00 : member is a pointer to another node -- process it recursively
7307 * 40 : member is a pointer to a char string -- output it
7308 * 80 : output the string whose index is stored in the data field
7309 * CC : flag signaling that this case needs external processing
7310 * D : data - either the (shifted) index of a fixed string to output or
7311 * the actual offset of the member to operate on in the struct
7312 * (since we assume bit 0 is set, the offset is not shifted)
7313 * E : flag signaling end of instruction sequence
7314 *
7315 * WARNING: In order to handle larger offsets for 64bit archs, this code
7316 * assumes that no offset can be an odd number and stores the
7317 * end-of-instructions flag in bit 0.
7318 */
7319
7320#define CMDTXT_NOMORE 0x01 /* NOTE: no offset should be odd */
7321#define CMDTXT_CHARPTR 0x40
7322#define CMDTXT_STRING 0x80
7323#define CMDTXT_SPECIAL 0xC0
7324#define CMDTXT_OFFSETMASK 0x3E
7325
7326static const char * const cmdtxt_strings[] = {
7327 /* 0 1 2 3 4 5 6 7 */
7328 "; ", "(", ")", " && ", " || ", "if ", "; then ", "...",
7329 /* 8 9 10 11 12 13 */
7330 "while ", "; do ", "; done", "until ", "for ", " in ...",
7331 /* 14 15 16 17 */
7332 "case ", "???", "() ...", "<<..."
7333};
7334
7335static const char * const redir_strings[] = {
7336 ">", "<", "<>", ">>", ">|", ">&", "<&"
7337};
7338
7339static const unsigned char cmdtxt_ops[] = {
7340#define CMDTXT_NSEMI 0
7341 offsetof(union node, nbinary.ch1),
7342 0|CMDTXT_STRING,
7343 offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE,
7344#define CMDTXT_NCMD (CMDTXT_NSEMI + 3)
7345#define CMDTXT_NPIPE (CMDTXT_NCMD)
7346#define CMDTXT_NCASE (CMDTXT_NCMD)
7347#define CMDTXT_NTO (CMDTXT_NCMD)
7348#define CMDTXT_NFROM (CMDTXT_NCMD)
7349#define CMDTXT_NFROMTO (CMDTXT_NCMD)
7350#define CMDTXT_NAPPEND (CMDTXT_NCMD)
7351#define CMDTXT_NTOOV (CMDTXT_NCMD)
7352#define CMDTXT_NTOFD (CMDTXT_NCMD)
7353#define CMDTXT_NFROMFD (CMDTXT_NCMD)
7354 CMDTXT_SPECIAL,
7355#define CMDTXT_NREDIR (CMDTXT_NPIPE + 1)
7356#define CMDTXT_NBACKGND (CMDTXT_NREDIR)
7357 offsetof(union node, nredir.n)|CMDTXT_NOMORE,
7358#define CMDTXT_NSUBSHELL (CMDTXT_NBACKGND + 1)
7359 (1*2)|CMDTXT_STRING,
7360 offsetof(union node, nredir.n),
7361 (2*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7362#define CMDTXT_NAND (CMDTXT_NSUBSHELL + 3)
7363 offsetof(union node, nbinary.ch1),
7364 (3*2)|CMDTXT_STRING,
7365 offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE,
7366#define CMDTXT_NOR (CMDTXT_NAND + 3)
7367 offsetof(union node, nbinary.ch1),
7368 (4*2)|CMDTXT_STRING,
7369 offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE,
7370#define CMDTXT_NIF (CMDTXT_NOR + 3)
7371 (5*2)|CMDTXT_STRING,
7372 offsetof(union node, nif.test),
7373 (6*2)|CMDTXT_STRING,
7374 offsetof(union node, nif.ifpart),
7375 (7*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7376#define CMDTXT_NWHILE (CMDTXT_NIF + 5)
7377 (8*2)|CMDTXT_STRING,
7378 offsetof(union node, nbinary.ch1),
7379 (9*2)|CMDTXT_STRING,
7380 offsetof(union node, nbinary.ch2),
7381 (10*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7382#define CMDTXT_NUNTIL (CMDTXT_NWHILE + 5)
7383 (11*2)|CMDTXT_STRING,
7384 offsetof(union node, nbinary.ch1),
7385 (9*2)|CMDTXT_STRING,
7386 offsetof(union node, nbinary.ch2),
7387 (10*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7388#define CMDTXT_NFOR (CMDTXT_NUNTIL + 5)
7389 (12*2)|CMDTXT_STRING,
7390 offsetof(union node, nfor.var)|CMDTXT_CHARPTR,
7391 (13*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7392#define CMDTXT_NCLIST (CMDTXT_NFOR + 3) /* TODO: IS THIS CORRECT??? */
7393#define CMDTXT_NNOT (CMDTXT_NCLIST) /* TODO: IS THIS CORRECT??? */
7394 (15*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7395#define CMDTXT_NDEFUN (CMDTXT_NCLIST + 1)
7396 offsetof(union node, narg.text)|CMDTXT_CHARPTR,
7397 (16*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7398#define CMDTXT_NARG (CMDTXT_NDEFUN + 2)
7399 offsetof(union node, narg.text)|CMDTXT_CHARPTR|CMDTXT_NOMORE,
7400#define CMDTXT_NHERE (CMDTXT_NARG + 1)
7401#define CMDTXT_NXHERE (CMDTXT_NHERE)
7402 (17*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7403};
7404
7405#if CMDTXT_NXHERE != 36
7406#error CMDTXT_NXHERE
7407#endif
7408
7409static const unsigned char cmdtxt_ops_index[26] = {
7410 CMDTXT_NSEMI,
7411 CMDTXT_NCMD,
7412 CMDTXT_NPIPE,
7413 CMDTXT_NREDIR,
7414 CMDTXT_NBACKGND,
7415 CMDTXT_NSUBSHELL,
7416 CMDTXT_NAND,
7417 CMDTXT_NOR,
7418 CMDTXT_NIF,
7419 CMDTXT_NWHILE,
7420 CMDTXT_NUNTIL,
7421 CMDTXT_NFOR,
7422 CMDTXT_NCASE,
7423 CMDTXT_NCLIST,
7424 CMDTXT_NDEFUN,
7425 CMDTXT_NARG,
7426 CMDTXT_NTO,
7427 CMDTXT_NFROM,
7428 CMDTXT_NFROMTO,
7429 CMDTXT_NAPPEND,
7430 CMDTXT_NTOOV,
7431 CMDTXT_NTOFD,
7432 CMDTXT_NFROMFD,
7433 CMDTXT_NHERE,
7434 CMDTXT_NXHERE,
7435 CMDTXT_NNOT,
7436};
7344 7437
7345static void 7438static void
7346cmdtxt(const union node *n) 7439cmdtxt(const union node *n)
7347{ 7440{
7441 const char *p;
7442
7443 if (n == NULL)
7444 return;
7445
7446 p = cmdtxt_ops + (int) cmdtxt_ops_index[n->type];
7447 if ((*p & CMDTXT_SPECIAL) != CMDTXT_SPECIAL) { /* normal case */
7448 do {
7449 if (*p & CMDTXT_STRING) { /* output fixed string */
7450 cmdputs(cmdtxt_strings[((int)(*p & CMDTXT_OFFSETMASK) >> 1)]);
7451 } else if (*p & CMDTXT_CHARPTR) { /* output dynamic string */
7452 cmdputs(((const char *) n) + ((int)(*p & CMDTXT_OFFSETMASK)));
7453 } else { /* output field */
7454 cmdtxt((const union node *)
7455 (((const char *) n) + ((int)(*p & CMDTXT_OFFSETMASK))));
7456 }
7457 } while (!(*p++ & CMDTXT_NOMORE));
7458 } else if (n->type == NCMD) {
7459 union node *np;
7460 for (np = n->ncmd.args ; np ; np = np->narg.next) {
7461 cmdtxt(np);
7462 if (np->narg.next)
7463 cmdputs(spcstr);
7464 }
7465 for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
7466 cmdputs(spcstr);
7467 cmdtxt(np);
7468 }
7469 } else if (n->type == NPIPE) {
7470 struct nodelist *lp;
7471 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
7472 cmdtxt(lp->n);
7473 if (lp->next)
7474 cmdputs(" | ");
7475 }
7476 } else if (n->type == NCASE) {
7477 cmdputs(cmdtxt_strings[14]);
7478 cmdputs(n->ncase.expr->narg.text);
7479 cmdputs(cmdtxt_strings[13]);
7480 } else {
7481#if (NTO != 16) || (NFROM != 17) || (NFROMTO != 18) || (NAPPEND != 19) || (NTOOV != 20) || (NTOFD != 21) || (NFROMFD != 22)
7482#error Assumption violated regarding range and ordering of NTO ... NFROMFD!
7483#endif
7484 char s[2];
7485
7486#ifdef DEBUG
7487 assert((n->type >= NTO) && (n->type <= NFROMFD));
7488#endif
7489
7490 p = redir_strings[n->type - NTO];
7491 if (n->nfile.fd != ('>' == *p)) {
7492 s[0] = n->nfile.fd + '0';
7493 s[1] = '\0';
7494 cmdputs(s);
7495 }
7496 cmdputs(p);
7497 if (n->type >= NTOFD) {
7498 s[0] = n->ndup.dupfd + '0';
7499 s[1] = '\0';
7500 cmdputs(s);
7501 } else {
7502 cmdtxt(n->nfile.fname);
7503 }
7504 }
7505}
7506#else /* CMDTXT_TABLE */
7507static void
7508cmdtxt(const union node *n)
7509{
7348 union node *np; 7510 union node *np;
7349 struct nodelist *lp; 7511 struct nodelist *lp;
7350 const char *p; 7512 const char *p;
@@ -7469,7 +7631,7 @@ redir:
7469 break; 7631 break;
7470 } 7632 }
7471} 7633}
7472 7634#endif
7473 7635
7474static char * 7636static char *
7475commandtext(const union node *n) 7637commandtext(const union node *n)
@@ -7602,27 +7764,17 @@ ash_main(argc, argv)
7602 * exception EXSHELLPROC to clean up before executing 7764 * exception EXSHELLPROC to clean up before executing
7603 * the shell procedure. 7765 * the shell procedure.
7604 */ 7766 */
7605 switch (exception) { 7767 if (exception == EXSHELLPROC) {
7606 case EXSHELLPROC:
7607 rootpid = getpid(); 7768 rootpid = getpid();
7608 rootshell = 1; 7769 rootshell = 1;
7609 minusc = NULL; 7770 minusc = NULL;
7610 state = 3; 7771 state = 3;
7611 break; 7772 } else {
7612 7773 if (exception == EXEXEC) {
7613 case EXEXEC: 7774 exitstatus = exerrno;
7614 exitstatus = exerrno; 7775 } else if (exception == EXERROR) {
7615 break; 7776 exitstatus = 2;
7616 7777 }
7617 case EXERROR:
7618 exitstatus = 2;
7619 break;
7620
7621 default:
7622 break;
7623 }
7624
7625 if (exception != EXSHELLPROC) {
7626 if (state == 0 || iflag == 0 || ! rootshell) 7778 if (state == 0 || iflag == 0 || ! rootshell)
7627 exitshell(exitstatus); 7779 exitshell(exitstatus);
7628 } 7780 }
@@ -7673,14 +7825,14 @@ state2:
7673state3: 7825state3:
7674 state = 4; 7826 state = 4;
7675 if (sflag == 0 || minusc) { 7827 if (sflag == 0 || minusc) {
7676 static int sigs[] = { 7828 static const char sigs[] = {
7677 SIGINT, SIGQUIT, SIGHUP, 7829 SIGINT, SIGQUIT, SIGHUP,
7678#ifdef SIGTSTP 7830#ifdef SIGTSTP
7679 SIGTSTP, 7831 SIGTSTP,
7680#endif 7832#endif
7681 SIGPIPE 7833 SIGPIPE
7682 }; 7834 };
7683#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0])) 7835#define SIGSSIZE ((sizeof(sigs)/sizeof(sigs[0])) - 1) /* trailing nul */
7684 int i; 7836 int i;
7685 7837
7686 for (i = 0; i < SIGSSIZE; i++) 7838 for (i = 0; i < SIGSSIZE; i++)
@@ -7764,8 +7916,8 @@ read_profile(name)
7764 const char *name; 7916 const char *name;
7765{ 7917{
7766 int fd; 7918 int fd;
7767 int xflag_set = 0; 7919 int xflag_save;
7768 int vflag_set = 0; 7920 int vflag_save;
7769 7921
7770 INTOFF; 7922 INTOFF;
7771 if ((fd = open(name, O_RDONLY)) >= 0) 7923 if ((fd = open(name, O_RDONLY)) >= 0)
@@ -7774,19 +7926,15 @@ read_profile(name)
7774 if (fd < 0) 7926 if (fd < 0)
7775 return; 7927 return;
7776 /* -q turns off -x and -v just when executing init files */ 7928 /* -q turns off -x and -v just when executing init files */
7929 /* Note: Might do a little redundant work, but reduces code size. */
7930 xflag_save = xflag;
7931 vflag_save = vflag;
7777 if (qflag) { 7932 if (qflag) {
7778 if (xflag) 7933 vflag = xflag = 0;
7779 xflag = 0, xflag_set = 1;
7780 if (vflag)
7781 vflag = 0, vflag_set = 1;
7782 } 7934 }
7783 cmdloop(0); 7935 cmdloop(0);
7784 if (qflag) { 7936 xflag = xflag_save;
7785 if (xflag_set) 7937 vflag = vflag_save;
7786 xflag = 1;
7787 if (vflag_set)
7788 vflag = 1;
7789 }
7790 popfile(); 7938 popfile();
7791} 7939}
7792 7940
@@ -8089,11 +8237,6 @@ ungrabstackstr(char *s, char *p)
8089 8237
8090#undef rflag 8238#undef rflag
8091 8239
8092//#ifdef __GLIBC__
8093static mode_t getmode(const void *, mode_t);
8094static void *setmode(const char *);
8095//#endif
8096
8097#if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1 8240#if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
8098typedef long rlim_t; 8241typedef long rlim_t;
8099#endif 8242#endif
@@ -8108,9 +8251,7 @@ typedef long rlim_t;
8108 */ 8251 */
8109 8252
8110static int 8253static int
8111readcmd(argc, argv) 8254readcmd(int argc, char **argv)
8112 int argc;
8113 char **argv;
8114{ 8255{
8115 char **ap; 8256 char **ap;
8116 int backslash; 8257 int backslash;
@@ -8132,7 +8273,7 @@ readcmd(argc, argv)
8132 rflag = 1; 8273 rflag = 1;
8133 } 8274 }
8134 if (prompt && isatty(0)) { 8275 if (prompt && isatty(0)) {
8135 putprompt(prompt); 8276 out2str(prompt); /* read without cmdedit */
8136 flushall(); 8277 flushall();
8137 } 8278 }
8138 if (*(ap = argptr) == NULL) 8279 if (*(ap = argptr) == NULL)
@@ -8199,8 +8340,16 @@ umaskcmd(argc, argv)
8199 int argc; 8340 int argc;
8200 char **argv; 8341 char **argv;
8201{ 8342{
8343 static const char permuser[3] = "ugo";
8344 static const char permmode[3] = "rwx";
8345 static const short int permmask[] = {
8346 S_IRUSR, S_IWUSR, S_IXUSR,
8347 S_IRGRP, S_IWGRP, S_IXGRP,
8348 S_IROTH, S_IWOTH, S_IXOTH
8349 };
8350
8202 char *ap; 8351 char *ap;
8203 int mask; 8352 mode_t mask;
8204 int i; 8353 int i;
8205 int symbolic_mode = 0; 8354 int symbolic_mode = 0;
8206 8355
@@ -8215,36 +8364,21 @@ umaskcmd(argc, argv)
8215 8364
8216 if ((ap = *argptr) == NULL) { 8365 if ((ap = *argptr) == NULL) {
8217 if (symbolic_mode) { 8366 if (symbolic_mode) {
8218 char u[4], g[4], o[4]; 8367 char buf[18];
8219 8368 char *p = buf;
8220 i = 0; 8369 for (i=0 ; i<3 ; i++) {
8221 if ((mask & S_IRUSR) == 0) 8370 int j;
8222 u[i++] = 'r'; 8371 *p++ = permuser[i];
8223 if ((mask & S_IWUSR) == 0) 8372 *p++ = '=';
8224 u[i++] = 'w'; 8373 for (j=0 ; j<3 ; j++) {
8225 if ((mask & S_IXUSR) == 0) 8374 if ((mask & permmask[3*i+j]) == 0) {
8226 u[i++] = 'x'; 8375 *p++ = permmode[j];
8227 u[i] = '\0'; 8376 }
8228 8377 }
8229 i = 0; 8378 *p++ = ',';
8230 if ((mask & S_IRGRP) == 0) 8379 }
8231 g[i++] = 'r'; 8380 *--p = 0;
8232 if ((mask & S_IWGRP) == 0) 8381 puts(buf);
8233 g[i++] = 'w';
8234 if ((mask & S_IXGRP) == 0)
8235 g[i++] = 'x';
8236 g[i] = '\0';
8237
8238 i = 0;
8239 if ((mask & S_IROTH) == 0)
8240 o[i++] = 'r';
8241 if ((mask & S_IWOTH) == 0)
8242 o[i++] = 'w';
8243 if ((mask & S_IXOTH) == 0)
8244 o[i++] = 'x';
8245 o[i] = '\0';
8246
8247 printf("u=%s,g=%s,o=%s\n", u, g, o);
8248 } else { 8382 } else {
8249 printf("%.4o\n", mask); 8383 printf("%.4o\n", mask);
8250 } 8384 }
@@ -8258,17 +8392,10 @@ umaskcmd(argc, argv)
8258 } while (*++ap != '\0'); 8392 } while (*++ap != '\0');
8259 umask(mask); 8393 umask(mask);
8260 } else { 8394 } else {
8261 void *set; 8395 mask = ~mask & 0777;
8262 8396 if (parse_mode(ap, &mask) == FALSE) {
8263 INTOFF;
8264 if ((set = setmode(ap)) != 0) {
8265 mask = getmode(set, ~mask & 0777);
8266 ckfree(set);
8267 }
8268 INTON;
8269 if (!set)
8270 error("Illegal mode: %s", ap); 8397 error("Illegal mode: %s", ap);
8271 8398 }
8272 umask(~mask & 0777); 8399 umask(~mask & 0777);
8273 } 8400 }
8274 } 8401 }
@@ -8287,46 +8414,45 @@ umaskcmd(argc, argv)
8287 8414
8288struct limits { 8415struct limits {
8289 const char *name; 8416 const char *name;
8290 int cmd; 8417 short cmd;
8291 int factor; /* multiply by to get rlim_{cur,max} values */ 8418 short factor; /* multiply by to get rlim_{cur,max} values */
8292 char option;
8293}; 8419};
8294 8420
8295static const struct limits limits[] = { 8421static const struct limits limits[] = {
8296#ifdef RLIMIT_CPU 8422#ifdef RLIMIT_CPU
8297 { "time(seconds)", RLIMIT_CPU, 1, 't' }, 8423 { "time(seconds)", RLIMIT_CPU, 1 },
8298#endif 8424#endif
8299#ifdef RLIMIT_FSIZE 8425#ifdef RLIMIT_FSIZE
8300 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' }, 8426 { "file(blocks)", RLIMIT_FSIZE, 512 },
8301#endif 8427#endif
8302#ifdef RLIMIT_DATA 8428#ifdef RLIMIT_DATA
8303 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' }, 8429 { "data(kbytes)", RLIMIT_DATA, 1024 },
8304#endif 8430#endif
8305#ifdef RLIMIT_STACK 8431#ifdef RLIMIT_STACK
8306 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' }, 8432 { "stack(kbytes)", RLIMIT_STACK, 1024 },
8307#endif 8433#endif
8308#ifdef RLIMIT_CORE 8434#ifdef RLIMIT_CORE
8309 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' }, 8435 { "coredump(blocks)", RLIMIT_CORE, 512 },
8310#endif 8436#endif
8311#ifdef RLIMIT_RSS 8437#ifdef RLIMIT_RSS
8312 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' }, 8438 { "memory(kbytes)", RLIMIT_RSS, 1024 },
8313#endif 8439#endif
8314#ifdef RLIMIT_MEMLOCK 8440#ifdef RLIMIT_MEMLOCK
8315 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' }, 8441 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024 },
8316#endif 8442#endif
8317#ifdef RLIMIT_NPROC 8443#ifdef RLIMIT_NPROC
8318 { "process(processes)", RLIMIT_NPROC, 1, 'p' }, 8444 { "process(processes)", RLIMIT_NPROC, 1 },
8319#endif 8445#endif
8320#ifdef RLIMIT_NOFILE 8446#ifdef RLIMIT_NOFILE
8321 { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' }, 8447 { "nofiles(descriptors)", RLIMIT_NOFILE, 1 },
8322#endif 8448#endif
8323#ifdef RLIMIT_VMEM 8449#ifdef RLIMIT_VMEM
8324 { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' }, 8450 { "vmemory(kbytes)", RLIMIT_VMEM, 1024 },
8325#endif 8451#endif
8326#ifdef RLIMIT_SWAP 8452#ifdef RLIMIT_SWAP
8327 { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' }, 8453 { "swap(kbytes)", RLIMIT_SWAP, 1024 },
8328#endif 8454#endif
8329 { (char *) 0, 0, 0, '\0' } 8455 { NULL, 0, 0 }
8330}; 8456};
8331 8457
8332static int 8458static int
@@ -8334,6 +8460,7 @@ ulimitcmd(argc, argv)
8334 int argc; 8460 int argc;
8335 char **argv; 8461 char **argv;
8336{ 8462{
8463 static const char unlimited_string[] = "unlimited";
8337 int c; 8464 int c;
8338 rlim_t val = 0; 8465 rlim_t val = 0;
8339 enum { SOFT = 0x1, HARD = 0x2 } 8466 enum { SOFT = 0x1, HARD = 0x2 }
@@ -8344,25 +8471,59 @@ ulimitcmd(argc, argv)
8344 struct rlimit limit; 8471 struct rlimit limit;
8345 8472
8346 what = 'f'; 8473 what = 'f';
8347 while ((optc = nextopt("HSatfdsmcnpl")) != '\0') 8474
8348 switch (optc) { 8475 while ((optc = nextopt("HSa"
8349 case 'H': 8476#ifdef RLIMIT_CPU
8477 "t"
8478#endif
8479#ifdef RLIMIT_FSIZE
8480 "f"
8481#endif
8482#ifdef RLIMIT_DATA
8483 "d"
8484#endif
8485#ifdef RLIMIT_STACK
8486 "s"
8487#endif
8488#ifdef RLIMIT_CORE
8489 "c"
8490#endif
8491#ifdef RLIMIT_RSS
8492 "m"
8493#endif
8494#ifdef RLIMIT_MEMLOCK
8495 "l"
8496#endif
8497#ifdef RLIMIT_NPROC
8498 "p"
8499#endif
8500#ifdef RLIMIT_NOFILE
8501 "n"
8502#endif
8503#ifdef RLIMIT_VMEM
8504 "v"
8505#endif
8506#ifdef RLIMIT_SWAP
8507 "w"
8508#endif
8509 )) != '\0') {
8510 if (optc == 'H') {
8350 how = HARD; 8511 how = HARD;
8351 break; 8512 } else if (optc == 'S') {
8352 case 'S':
8353 how = SOFT; 8513 how = SOFT;
8354 break; 8514 } else if (optc == 'a') {
8355 case 'a':
8356 all = 1; 8515 all = 1;
8357 break; 8516 } else {
8358 default:
8359 what = optc; 8517 what = optc;
8360 } 8518 }
8519 }
8361 8520
8362 for (l = limits; l->name && l->option != what; l++) 8521 for (l = limits; l->name; l++) {
8363 ; 8522 if(l->name[0] == what)
8364 if (!l->name) 8523 break;
8365 error("internal error (%c)", what); 8524 if(l->name[1]=='w' && what=='w')
8525 break;
8526 }
8366 8527
8367 set = *argptr ? 1 : 0; 8528 set = *argptr ? 1 : 0;
8368 if (set) { 8529 if (set) {
@@ -8370,7 +8531,7 @@ ulimitcmd(argc, argv)
8370 8531
8371 if (all || argptr[1]) 8532 if (all || argptr[1])
8372 error("too many arguments"); 8533 error("too many arguments");
8373 if (strcmp(p, "unlimited") == 0) 8534 if (strcmp(p, unlimited_string) == 0)
8374 val = RLIM_INFINITY; 8535 val = RLIM_INFINITY;
8375 else { 8536 else {
8376 val = (rlim_t) 0; 8537 val = (rlim_t) 0;
@@ -8386,48 +8547,42 @@ ulimitcmd(argc, argv)
8386 val *= l->factor; 8547 val *= l->factor;
8387 } 8548 }
8388 } 8549 }
8550
8389 if (all) { 8551 if (all) {
8390 for (l = limits; l->name; l++) { 8552 for (l = limits; l->name; l++) {
8553 printf("%-20s ", l->name);
8391 getrlimit(l->cmd, &limit); 8554 getrlimit(l->cmd, &limit);
8555 OUTPUT_LIMIT:
8392 if (how & SOFT) 8556 if (how & SOFT)
8393 val = limit.rlim_cur; 8557 val = limit.rlim_cur;
8394 else if (how & HARD) 8558 else if (how & HARD)
8395 val = limit.rlim_max; 8559 val = limit.rlim_max;
8396 8560
8397 printf("%-20s ", l->name);
8398 if (val == RLIM_INFINITY) 8561 if (val == RLIM_INFINITY)
8399 printf("unlimited\n"); 8562 puts(unlimited_string);
8400 else 8563 else
8401 { 8564 {
8402 val /= l->factor; 8565 val /= l->factor;
8403 printf("%lld\n", (long long) val); 8566 printf("%lld\n", (long long) val);
8404 } 8567 }
8568 if (!all) {
8569 break;
8570 }
8405 } 8571 }
8406 return 0; 8572 return 0;
8407 } 8573 }
8408 8574
8409 getrlimit(l->cmd, &limit); 8575 if (!set) {
8410 if (set) { 8576 goto OUTPUT_LIMIT;
8411 if (how & HARD)
8412 limit.rlim_max = val;
8413 if (how & SOFT)
8414 limit.rlim_cur = val;
8415 if (setrlimit(l->cmd, &limit) < 0)
8416 error("error setting limit (%m)");
8417 } else {
8418 if (how & SOFT)
8419 val = limit.rlim_cur;
8420 else if (how & HARD)
8421 val = limit.rlim_max;
8422
8423 if (val == RLIM_INFINITY)
8424 printf("unlimited\n");
8425 else
8426 {
8427 val /= l->factor;
8428 printf("%lld\n", (long long) val);
8429 }
8430 } 8577 }
8578
8579 getrlimit(l->cmd, &limit);
8580 if (how & HARD)
8581 limit.rlim_max = val;
8582 if (how & SOFT)
8583 limit.rlim_cur = val;
8584 if (setrlimit(l->cmd, &limit) < 0)
8585 error("error setting limit (%m)");
8431 return 0; 8586 return 0;
8432} 8587}
8433/* 8588/*
@@ -8499,16 +8654,7 @@ single_quote(const char *s) {
8499 len2 = strspn(s + len1, "'"); 8654 len2 = strspn(s + len1, "'");
8500 8655
8501 len1p = len1 ? len1 + 2 : len1; 8656 len1p = len1 ? len1 + 2 : len1;
8502 switch (len2) { 8657 len2p = len2 + ((len2 < 2) ? len2 : 2);
8503 case 0:
8504 len2p = 0;
8505 break;
8506 case 1:
8507 len2p = 2;
8508 break;
8509 default:
8510 len2p = len2 + 2;
8511 }
8512 8658
8513 CHECKSTRSPACE(len1p + len2p + 1, p); 8659 CHECKSTRSPACE(len1p + len2p + 1, p);
8514 8660
@@ -8520,20 +8666,16 @@ single_quote(const char *s) {
8520 s += len1; 8666 s += len1;
8521 } 8667 }
8522 8668
8523 switch (len2) { 8669 if (len2 > 1) {
8524 case 0:
8525 break;
8526 case 1:
8527 *q++ = '\\';
8528 *q = '\'';
8529 s++;
8530 break;
8531 default:
8532 *q = '"'; 8670 *q = '"';
8533 q += 1 + len2; 8671 q += 1 + len2;
8534 memcpy(q + 1, s, len2); 8672 memcpy(q + 1, s, len2);
8535 *q = '"'; 8673 *q = '"';
8536 s += len2; 8674 s += len2;
8675 } else if (len2 == 1) {
8676 *q++ = '\\';
8677 *q = '\'';
8678 s++;
8537 } 8679 }
8538 8680
8539 STADJUST(len1p + len2p, p); 8681 STADJUST(len1p + len2p, p);
@@ -8565,182 +8707,357 @@ static void sizenodelist (const struct nodelist *);
8565static struct nodelist *copynodelist (const struct nodelist *); 8707static struct nodelist *copynodelist (const struct nodelist *);
8566static char *nodesavestr (const char *); 8708static char *nodesavestr (const char *);
8567 8709
8568static void 8710//#define CALCSIZE_TABLE
8569calcsize(const union node *n) 8711//#define COPYNODE_TABLE
8712#if defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE)
8713/*
8714 * To collect a lot of redundant code in case statements for copynode()
8715 * and calcsize(), we implement a mini language here. Each type of node
8716 * struct has an associated instruction sequence that operates on its
8717 * members via their offsets. The instruction are pack in unsigned chars
8718 * with format IIDDDDDE where the bits are
8719 * I : part of the instruction opcode, which are
8720 * 00 : member is a pointer to another node
8721 * 40 : member is an integer
8722 * 80 : member is a pointer to a nodelist
8723 * CC : member is a pointer to a char string
8724 * D : data - the actual offset of the member to operate on in the struct
8725 * (since we assume bit 0 is set, it is not shifted)
8726 * E : flag signaling end of instruction sequence
8727 *
8728 * WARNING: In order to handle larger offsets for 64bit archs, this code
8729 * assumes that no offset can be an odd number and stores the
8730 * end-of-instructions flag in bit 0.
8731 */
8732
8733#define NODE_INTEGER 0x40
8734#define NODE_NODELIST 0x80
8735#define NODE_CHARPTR 0xC0
8736#define NODE_NOMORE 0x01 /* Note: no offset should be odd (aligned)*/
8737#define NODE_MBRMASK 0xC0
8738#define NODE_OFFSETMASK 0x3E
8739
8740static const unsigned char copynode_ops[35] = {
8741#define COPYNODE_OPS0 0
8742 offsetof(union node, nbinary.ch2),
8743 offsetof(union node, nbinary.ch1)|NODE_NOMORE,
8744#define COPYNODE_OPS1 (COPYNODE_OPS0 + 2)
8745 offsetof(union node, ncmd.redirect),
8746 offsetof(union node, ncmd.args),
8747 offsetof(union node, ncmd.assign),
8748 offsetof(union node, ncmd.backgnd)|NODE_INTEGER|NODE_NOMORE,
8749#define COPYNODE_OPS2 (COPYNODE_OPS1 + 4)
8750 offsetof(union node, npipe.cmdlist)|NODE_NODELIST,
8751 offsetof(union node, npipe.backgnd)|NODE_INTEGER|NODE_NOMORE,
8752#define COPYNODE_OPS3 (COPYNODE_OPS2 + 2)
8753 offsetof(union node, nredir.redirect),
8754 offsetof(union node, nredir.n)|NODE_NOMORE,
8755#define COPYNODE_OPS4 (COPYNODE_OPS3 + 2)
8756 offsetof(union node, nif.elsepart),
8757 offsetof(union node, nif.ifpart),
8758 offsetof(union node, nif.test)|NODE_NOMORE,
8759#define COPYNODE_OPS5 (COPYNODE_OPS4 + 3)
8760 offsetof(union node, nfor.var)|NODE_CHARPTR,
8761 offsetof(union node, nfor.body),
8762 offsetof(union node, nfor.args)|NODE_NOMORE,
8763#define COPYNODE_OPS6 (COPYNODE_OPS5 + 3)
8764 offsetof(union node, ncase.cases),
8765 offsetof(union node, ncase.expr)|NODE_NOMORE,
8766#define COPYNODE_OPS7 (COPYNODE_OPS6 + 2)
8767 offsetof(union node, nclist.body),
8768 offsetof(union node, nclist.pattern),
8769 offsetof(union node, nclist.next)|NODE_NOMORE,
8770#define COPYNODE_OPS8 (COPYNODE_OPS7 + 3)
8771 offsetof(union node, narg.backquote)|NODE_NODELIST,
8772 offsetof(union node, narg.text)|NODE_CHARPTR,
8773 offsetof(union node, narg.next)|NODE_NOMORE,
8774#define COPYNODE_OPS9 (COPYNODE_OPS8 + 3)
8775 offsetof(union node, nfile.fname),
8776 offsetof(union node, nfile.fd)|NODE_INTEGER,
8777 offsetof(union node, nfile.next)|NODE_NOMORE,
8778#define COPYNODE_OPS10 (COPYNODE_OPS9 + 3)
8779 offsetof(union node, ndup.vname),
8780 offsetof(union node, ndup.dupfd)|NODE_INTEGER,
8781 offsetof(union node, ndup.fd)|NODE_INTEGER,
8782 offsetof(union node, ndup.next)|NODE_NOMORE,
8783#define COPYNODE_OPS11 (COPYNODE_OPS10 + 4)
8784 offsetof(union node, nhere.doc),
8785 offsetof(union node, nhere.fd)|NODE_INTEGER,
8786 offsetof(union node, nhere.next)|NODE_NOMORE,
8787#define COPYNODE_OPS12 (COPYNODE_OPS11 + 3)
8788 offsetof(union node, nnot.com)|NODE_NOMORE,
8789};
8790
8791#if COPYNODE_OPS12 != 34
8792#error COPYNODE_OPS12 is incorrect
8793#endif
8794
8795static const unsigned char copynode_ops_index[26] = {
8796 COPYNODE_OPS0, /* NSEMI */
8797 COPYNODE_OPS1, /* NCMD */
8798 COPYNODE_OPS2, /* NPIPE */
8799 COPYNODE_OPS3, /* NREDIR */
8800 COPYNODE_OPS3, /* NBACKGND */
8801 COPYNODE_OPS3, /* NSUBSHELL */
8802 COPYNODE_OPS0, /* NAND */
8803 COPYNODE_OPS0, /* NOR */
8804 COPYNODE_OPS4, /* NIF */
8805 COPYNODE_OPS0, /* NWHILE */
8806 COPYNODE_OPS0, /* NUNTIL */
8807 COPYNODE_OPS5, /* NFOR */
8808 COPYNODE_OPS6, /* NCASE */
8809 COPYNODE_OPS7, /* NCLIST */
8810 COPYNODE_OPS8, /* NDEFUN */
8811 COPYNODE_OPS8, /* NARG */
8812 COPYNODE_OPS9, /* NTO */
8813 COPYNODE_OPS9, /* NFROM */
8814 COPYNODE_OPS9, /* NFROMTO */
8815 COPYNODE_OPS9, /* NAPPEND */
8816 COPYNODE_OPS9, /* NTOOV */
8817 COPYNODE_OPS10, /* NTOFD */
8818 COPYNODE_OPS10, /* NFROMFD */
8819 COPYNODE_OPS11, /* NHERE */
8820 COPYNODE_OPS11, /* NXHERE */
8821 COPYNODE_OPS12, /* NNOT */
8822};
8823
8824#if NODE_CHARPTR != NODE_MBRMASK
8825#error NODE_CHARPTR != NODE_MBRMASK!!!
8826#endif
8827#endif /* defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE) */
8828
8829#ifdef COPYNODE_TABLE
8830static union node *
8831copynode(const union node *n)
8570{ 8832{
8833 union node *new;
8834 const unsigned char *p;
8835
8571 if (n == NULL) 8836 if (n == NULL)
8572 return; 8837 return NULL;
8573 funcblocksize += nodesize[n->type]; 8838 new = funcblock;
8839 new->type = n->type;
8840 funcblock = (char *) funcblock + (int) nodesize[n->type];
8841 p = copynode_ops + (int) copynode_ops_index[n->type];
8842 do {
8843 char *nn = ((char *) new) + ((int)(*p & NODE_OFFSETMASK));
8844 const char *no = ((const char *) n) + ((int)(*p & NODE_OFFSETMASK));
8845
8846 if (!(*p & NODE_MBRMASK)) { /* standard node */
8847 (union node *) nn = copynode((const union node *) no);
8848 } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8849 nn = nodesavestr(no);
8850 } else if (*p & NODE_NODELIST) { /* nodelist */
8851 (struct nodelist *) nn
8852 = copynodelist((const struct nodelist *) no);
8853 } else { /* integer */
8854 *((int *) nn) = *((int *) no);
8855 }
8856 } while (!(*p++ & NODE_NOMORE));
8857 return new;
8858}
8859#else /* COPYNODE_TABLE */
8860static union node *
8861copynode(const union node *n)
8862{
8863 union node *new;
8864
8865 if (n == NULL)
8866 return NULL;
8867 new = funcblock;
8868 funcblock = (char *) funcblock + nodesize[n->type];
8574 switch (n->type) { 8869 switch (n->type) {
8575 case NSEMI: 8870 case NSEMI:
8576 case NAND: 8871 case NAND:
8577 case NOR: 8872 case NOR:
8578 case NWHILE: 8873 case NWHILE:
8579 case NUNTIL: 8874 case NUNTIL:
8580 calcsize(n->nbinary.ch2); 8875 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8581 calcsize(n->nbinary.ch1); 8876 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8582 break; 8877 break;
8583 case NCMD: 8878 case NCMD:
8584 calcsize(n->ncmd.redirect); 8879 new->ncmd.redirect = copynode(n->ncmd.redirect);
8585 calcsize(n->ncmd.args); 8880 new->ncmd.args = copynode(n->ncmd.args);
8586 calcsize(n->ncmd.assign); 8881 new->ncmd.assign = copynode(n->ncmd.assign);
8882 new->ncmd.backgnd = n->ncmd.backgnd;
8587 break; 8883 break;
8588 case NPIPE: 8884 case NPIPE:
8589 sizenodelist(n->npipe.cmdlist); 8885 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8886 new->npipe.backgnd = n->npipe.backgnd;
8590 break; 8887 break;
8591 case NREDIR: 8888 case NREDIR:
8592 case NBACKGND: 8889 case NBACKGND:
8593 case NSUBSHELL: 8890 case NSUBSHELL:
8594 calcsize(n->nredir.redirect); 8891 new->nredir.redirect = copynode(n->nredir.redirect);
8595 calcsize(n->nredir.n); 8892 new->nredir.n = copynode(n->nredir.n);
8596 break; 8893 break;
8597 case NIF: 8894 case NIF:
8598 calcsize(n->nif.elsepart); 8895 new->nif.elsepart = copynode(n->nif.elsepart);
8599 calcsize(n->nif.ifpart); 8896 new->nif.ifpart = copynode(n->nif.ifpart);
8600 calcsize(n->nif.test); 8897 new->nif.test = copynode(n->nif.test);
8601 break; 8898 break;
8602 case NFOR: 8899 case NFOR:
8603 funcstringsize += strlen(n->nfor.var) + 1; 8900 new->nfor.var = nodesavestr(n->nfor.var);
8604 calcsize(n->nfor.body); 8901 new->nfor.body = copynode(n->nfor.body);
8605 calcsize(n->nfor.args); 8902 new->nfor.args = copynode(n->nfor.args);
8606 break; 8903 break;
8607 case NCASE: 8904 case NCASE:
8608 calcsize(n->ncase.cases); 8905 new->ncase.cases = copynode(n->ncase.cases);
8609 calcsize(n->ncase.expr); 8906 new->ncase.expr = copynode(n->ncase.expr);
8610 break; 8907 break;
8611 case NCLIST: 8908 case NCLIST:
8612 calcsize(n->nclist.body); 8909 new->nclist.body = copynode(n->nclist.body);
8613 calcsize(n->nclist.pattern); 8910 new->nclist.pattern = copynode(n->nclist.pattern);
8614 calcsize(n->nclist.next); 8911 new->nclist.next = copynode(n->nclist.next);
8615 break; 8912 break;
8616 case NDEFUN: 8913 case NDEFUN:
8617 case NARG: 8914 case NARG:
8618 sizenodelist(n->narg.backquote); 8915 new->narg.backquote = copynodelist(n->narg.backquote);
8619 funcstringsize += strlen(n->narg.text) + 1; 8916 new->narg.text = nodesavestr(n->narg.text);
8620 calcsize(n->narg.next); 8917 new->narg.next = copynode(n->narg.next);
8621 break; 8918 break;
8622 case NTO: 8919 case NTO:
8623 case NFROM: 8920 case NFROM:
8624 case NFROMTO: 8921 case NFROMTO:
8625 case NAPPEND: 8922 case NAPPEND:
8626 case NTOOV: 8923 case NTOOV:
8627 calcsize(n->nfile.fname); 8924 new->nfile.fname = copynode(n->nfile.fname);
8628 calcsize(n->nfile.next); 8925 new->nfile.fd = n->nfile.fd;
8926 new->nfile.next = copynode(n->nfile.next);
8629 break; 8927 break;
8630 case NTOFD: 8928 case NTOFD:
8631 case NFROMFD: 8929 case NFROMFD:
8632 calcsize(n->ndup.vname); 8930 new->ndup.vname = copynode(n->ndup.vname);
8633 calcsize(n->ndup.next); 8931 new->ndup.dupfd = n->ndup.dupfd;
8932 new->ndup.fd = n->ndup.fd;
8933 new->ndup.next = copynode(n->ndup.next);
8634 break; 8934 break;
8635 case NHERE: 8935 case NHERE:
8636 case NXHERE: 8936 case NXHERE:
8637 calcsize(n->nhere.doc); 8937 new->nhere.doc = copynode(n->nhere.doc);
8638 calcsize(n->nhere.next); 8938 new->nhere.fd = n->nhere.fd;
8939 new->nhere.next = copynode(n->nhere.next);
8639 break; 8940 break;
8640 case NNOT: 8941 case NNOT:
8641 calcsize(n->nnot.com); 8942 new->nnot.com = copynode(n->nnot.com);
8642 break; 8943 break;
8643 }; 8944 };
8945 new->type = n->type;
8946 return new;
8644} 8947}
8948#endif /* COPYNODE_TABLE */
8645 8949
8950#ifdef CALCSIZE_TABLE
8646static void 8951static void
8647sizenodelist(const struct nodelist *lp) 8952calcsize(const union node *n)
8648{ 8953{
8649 while (lp) { 8954 const unsigned char *p;
8650 funcblocksize += ALIGN(sizeof(struct nodelist));
8651 calcsize(lp->n);
8652 lp = lp->next;
8653 }
8654}
8655
8656 8955
8657static union node * 8956 if (n == NULL)
8658copynode(const union node *n) 8957 return;
8958 funcblocksize += (int) nodesize[n->type];
8959
8960 p = copynode_ops + (int) copynode_ops_index[n->type];
8961 do {
8962 const char *no = ((const char *) n) + ((int)(*p & NODE_OFFSETMASK));
8963
8964 if (!(*p & NODE_MBRMASK)) { /* standard node */
8965 calcsize((const union node *) no);
8966 } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8967 funcstringsize += strlen(no) + 1;
8968 } else if (*p & NODE_NODELIST) { /* nodelist */
8969 sizenodelist((const struct nodelist *) no);
8970 }
8971 } while (!(*p++ & NODE_NOMORE));
8972}
8973#else /* CALCSIZE_TABLE */
8974static void
8975calcsize(const union node *n)
8659{ 8976{
8660 union node *new;
8661
8662 if (n == NULL) 8977 if (n == NULL)
8663 return NULL; 8978 return;
8664 new = funcblock; 8979 funcblocksize += nodesize[n->type];
8665 funcblock = (char *) funcblock + nodesize[n->type];
8666 switch (n->type) { 8980 switch (n->type) {
8667 case NSEMI: 8981 case NSEMI:
8668 case NAND: 8982 case NAND:
8669 case NOR: 8983 case NOR:
8670 case NWHILE: 8984 case NWHILE:
8671 case NUNTIL: 8985 case NUNTIL:
8672 new->nbinary.ch2 = copynode(n->nbinary.ch2); 8986 calcsize(n->nbinary.ch2);
8673 new->nbinary.ch1 = copynode(n->nbinary.ch1); 8987 calcsize(n->nbinary.ch1);
8674 break; 8988 break;
8675 case NCMD: 8989 case NCMD:
8676 new->ncmd.redirect = copynode(n->ncmd.redirect); 8990 calcsize(n->ncmd.redirect);
8677 new->ncmd.args = copynode(n->ncmd.args); 8991 calcsize(n->ncmd.args);
8678 new->ncmd.assign = copynode(n->ncmd.assign); 8992 calcsize(n->ncmd.assign);
8679 new->ncmd.backgnd = n->ncmd.backgnd;
8680 break; 8993 break;
8681 case NPIPE: 8994 case NPIPE:
8682 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist); 8995 sizenodelist(n->npipe.cmdlist);
8683 new->npipe.backgnd = n->npipe.backgnd;
8684 break; 8996 break;
8685 case NREDIR: 8997 case NREDIR:
8686 case NBACKGND: 8998 case NBACKGND:
8687 case NSUBSHELL: 8999 case NSUBSHELL:
8688 new->nredir.redirect = copynode(n->nredir.redirect); 9000 calcsize(n->nredir.redirect);
8689 new->nredir.n = copynode(n->nredir.n); 9001 calcsize(n->nredir.n);
8690 break; 9002 break;
8691 case NIF: 9003 case NIF:
8692 new->nif.elsepart = copynode(n->nif.elsepart); 9004 calcsize(n->nif.elsepart);
8693 new->nif.ifpart = copynode(n->nif.ifpart); 9005 calcsize(n->nif.ifpart);
8694 new->nif.test = copynode(n->nif.test); 9006 calcsize(n->nif.test);
8695 break; 9007 break;
8696 case NFOR: 9008 case NFOR:
8697 new->nfor.var = nodesavestr(n->nfor.var); 9009 funcstringsize += strlen(n->nfor.var) + 1;
8698 new->nfor.body = copynode(n->nfor.body); 9010 calcsize(n->nfor.body);
8699 new->nfor.args = copynode(n->nfor.args); 9011 calcsize(n->nfor.args);
8700 break; 9012 break;
8701 case NCASE: 9013 case NCASE:
8702 new->ncase.cases = copynode(n->ncase.cases); 9014 calcsize(n->ncase.cases);
8703 new->ncase.expr = copynode(n->ncase.expr); 9015 calcsize(n->ncase.expr);
8704 break; 9016 break;
8705 case NCLIST: 9017 case NCLIST:
8706 new->nclist.body = copynode(n->nclist.body); 9018 calcsize(n->nclist.body);
8707 new->nclist.pattern = copynode(n->nclist.pattern); 9019 calcsize(n->nclist.pattern);
8708 new->nclist.next = copynode(n->nclist.next); 9020 calcsize(n->nclist.next);
8709 break; 9021 break;
8710 case NDEFUN: 9022 case NDEFUN:
8711 case NARG: 9023 case NARG:
8712 new->narg.backquote = copynodelist(n->narg.backquote); 9024 sizenodelist(n->narg.backquote);
8713 new->narg.text = nodesavestr(n->narg.text); 9025 funcstringsize += strlen(n->narg.text) + 1;
8714 new->narg.next = copynode(n->narg.next); 9026 calcsize(n->narg.next);
8715 break; 9027 break;
8716 case NTO: 9028 case NTO:
8717 case NFROM: 9029 case NFROM:
8718 case NFROMTO: 9030 case NFROMTO:
8719 case NAPPEND: 9031 case NAPPEND:
8720 case NTOOV: 9032 case NTOOV:
8721 new->nfile.fname = copynode(n->nfile.fname); 9033 calcsize(n->nfile.fname);
8722 new->nfile.fd = n->nfile.fd; 9034 calcsize(n->nfile.next);
8723 new->nfile.next = copynode(n->nfile.next);
8724 break; 9035 break;
8725 case NTOFD: 9036 case NTOFD:
8726 case NFROMFD: 9037 case NFROMFD:
8727 new->ndup.vname = copynode(n->ndup.vname); 9038 calcsize(n->ndup.vname);
8728 new->ndup.dupfd = n->ndup.dupfd; 9039 calcsize(n->ndup.next);
8729 new->ndup.fd = n->ndup.fd;
8730 new->ndup.next = copynode(n->ndup.next);
8731 break; 9040 break;
8732 case NHERE: 9041 case NHERE:
8733 case NXHERE: 9042 case NXHERE:
8734 new->nhere.doc = copynode(n->nhere.doc); 9043 calcsize(n->nhere.doc);
8735 new->nhere.fd = n->nhere.fd; 9044 calcsize(n->nhere.next);
8736 new->nhere.next = copynode(n->nhere.next);
8737 break; 9045 break;
8738 case NNOT: 9046 case NNOT:
8739 new->nnot.com = copynode(n->nnot.com); 9047 calcsize(n->nnot.com);
8740 break; 9048 break;
8741 }; 9049 };
8742 new->type = n->type; 9050}
8743 return new; 9051#endif /* CALCSIZE_TABLE */
9052
9053static void
9054sizenodelist(const struct nodelist *lp)
9055{
9056 while (lp) {
9057 funcblocksize += ALIGN(sizeof(struct nodelist));
9058 calcsize(lp->n);
9059 lp = lp->next;
9060 }
8744} 9061}
8745 9062
8746 9063
@@ -9346,10 +9663,10 @@ static union node *command (void);
9346static union node *simplecmd (void); 9663static union node *simplecmd (void);
9347static void parsefname (void); 9664static void parsefname (void);
9348static void parseheredoc (void); 9665static void parseheredoc (void);
9349static int peektoken (void); 9666static char peektoken (void);
9350static int readtoken (void); 9667static int readtoken (void);
9351static int xxreadtoken (void); 9668static int xxreadtoken (void);
9352static int readtoken1 (int, char const *, char *, int); 9669static int readtoken1 (int, int, const char *, int);
9353static int noexpand (char *); 9670static int noexpand (char *);
9354static void synexpect (int) __attribute__((noreturn)); 9671static void synexpect (int) __attribute__((noreturn));
9355static void synerror (const char *) __attribute__((noreturn)); 9672static void synerror (const char *) __attribute__((noreturn));
@@ -9391,7 +9708,7 @@ list(nlflag)
9391 int tok; 9708 int tok;
9392 9709
9393 checkkwd = 2; 9710 checkkwd = 2;
9394 if (nlflag == 0 && tokendlist[peektoken()]) 9711 if (nlflag == 0 && peektoken())
9395 return NULL; 9712 return NULL;
9396 n1 = NULL; 9713 n1 = NULL;
9397 for (;;) { 9714 for (;;) {
@@ -9434,7 +9751,7 @@ list(nlflag)
9434 tokpushback++; 9751 tokpushback++;
9435 } 9752 }
9436 checkkwd = 2; 9753 checkkwd = 2;
9437 if (tokendlist[peektoken()]) 9754 if (peektoken())
9438 return n1; 9755 return n1;
9439 break; 9756 break;
9440 case TEOF: 9757 case TEOF:
@@ -9572,7 +9889,7 @@ command() {
9572 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL; 9889 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9573 n1->nbinary.ch1 = list(0); 9890 n1->nbinary.ch1 = list(0);
9574 if ((got=readtoken()) != TDO) { 9891 if ((got=readtoken()) != TDO) {
9575TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); 9892TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9576 synexpect(TDO); 9893 synexpect(TDO);
9577 } 9894 }
9578 n1->nbinary.ch2 = list(0); 9895 n1->nbinary.ch2 = list(0);
@@ -9901,13 +10218,13 @@ parseheredoc() {
9901 } 10218 }
9902} 10219}
9903 10220
9904static int 10221static char
9905peektoken() { 10222peektoken() {
9906 int t; 10223 int t;
9907 10224
9908 t = readtoken(); 10225 t = readtoken();
9909 tokpushback++; 10226 tokpushback++;
9910 return (t); 10227 return tokname_array[t][0];
9911} 10228}
9912 10229
9913static int 10230static int
@@ -9954,8 +10271,8 @@ top:
9954 const char *const *pp; 10271 const char *const *pp;
9955 10272
9956 if ((pp = findkwd(wordtext))) { 10273 if ((pp = findkwd(wordtext))) {
9957 lasttoken = t = pp - parsekwd + KWDOFFSET; 10274 lasttoken = t = pp - tokname_array;
9958 TRACE(("keyword %s recognized\n", tokname[t])); 10275 TRACE(("keyword %s recognized\n", tokname(t)));
9959 goto out; 10276 goto out;
9960 } 10277 }
9961 } 10278 }
@@ -9983,9 +10300,9 @@ top:
9983out: 10300out:
9984#ifdef DEBUG 10301#ifdef DEBUG
9985 if (!alreadyseen) 10302 if (!alreadyseen)
9986 TRACE(("token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : "")); 10303 TRACE(("token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : ""));
9987 else 10304 else
9988 TRACE(("reread token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : "")); 10305 TRACE(("reread token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : ""));
9989#endif 10306#endif
9990 return (t); 10307 return (t);
9991} 10308}
@@ -10103,12 +10420,8 @@ breakloop:
10103#define PARSEARITH() {goto parsearith; parsearith_return:;} 10420#define PARSEARITH() {goto parsearith; parsearith_return:;}
10104 10421
10105static int 10422static int
10106readtoken1(firstc, syntax, eofmark, striptabs) 10423readtoken1(int firstc, int syntax, const char *eofmark, int striptabs)
10107 int firstc; 10424{
10108 char const *syntax;
10109 char *eofmark;
10110 int striptabs;
10111 {
10112 int c = firstc; 10425 int c = firstc;
10113 char *out; 10426 char *out;
10114 int len; 10427 int len;
@@ -10121,7 +10434,7 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10121 int parenlevel; /* levels of parens in arithmetic */ 10434 int parenlevel; /* levels of parens in arithmetic */
10122 int dqvarnest; /* levels of variables expansion within double quotes */ 10435 int dqvarnest; /* levels of variables expansion within double quotes */
10123 int oldstyle; 10436 int oldstyle;
10124 char const *prevsyntax; /* syntax before arithmetic */ 10437 int prevsyntax; /* syntax before arithmetic */
10125#if __GNUC__ 10438#if __GNUC__
10126 /* Avoid longjmp clobbering */ 10439 /* Avoid longjmp clobbering */
10127 (void) &out; 10440 (void) &out;
@@ -10152,7 +10465,7 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10152 CHECKEND(); /* set c to PEOF if at end of here document */ 10465 CHECKEND(); /* set c to PEOF if at end of here document */
10153 for (;;) { /* until end of line or end of word */ 10466 for (;;) { /* until end of line or end of word */
10154 CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */ 10467 CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
10155 switch(syntax[c]) { 10468 switch(SIT(c,syntax)) {
10156 case CNL: /* '\n' */ 10469 case CNL: /* '\n' */
10157 if (syntax == BASESYNTAX) 10470 if (syntax == BASESYNTAX)
10158 goto endword; /* exit outer loop */ 10471 goto endword; /* exit outer loop */
@@ -10187,7 +10500,7 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10187 if (dblquote && c != '\\' && c != '`' && c != '$' 10500 if (dblquote && c != '\\' && c != '`' && c != '$'
10188 && (c != '"' || eofmark != NULL)) 10501 && (c != '"' || eofmark != NULL))
10189 USTPUTC('\\', out); 10502 USTPUTC('\\', out);
10190 if (SQSYNTAX[c] == CCTL) 10503 if (SIT(c,SQSYNTAX) == CCTL)
10191 USTPUTC(CTLESC, out); 10504 USTPUTC(CTLESC, out);
10192 else if (eofmark == NULL) 10505 else if (eofmark == NULL)
10193 USTPUTC(CTLQUOTEMARK, out); 10506 USTPUTC(CTLQUOTEMARK, out);
@@ -10338,7 +10651,7 @@ checkend: {
10338 } 10651 }
10339 if (c == *eofmark) { 10652 if (c == *eofmark) {
10340 if (pfgets(line, sizeof line) != NULL) { 10653 if (pfgets(line, sizeof line) != NULL) {
10341 char *p, *q; 10654 const char *p, *q;
10342 10655
10343 p = line; 10656 p = line;
10344 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++); 10657 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
@@ -10728,7 +11041,7 @@ noexpand(text)
10728 continue; 11041 continue;
10729 if (c == CTLESC) 11042 if (c == CTLESC)
10730 p++; 11043 p++;
10731 else if (BASESYNTAX[(int)c] == CCTL) 11044 else if (SIT(c,BASESYNTAX) == CCTL)
10732 return 0; 11045 return 0;
10733 } 11046 }
10734 return 1; 11047 return 1;
@@ -10767,13 +11080,11 @@ synexpect(token)
10767 int token; 11080 int token;
10768{ 11081{
10769 char msg[64]; 11082 char msg[64];
11083 int l;
10770 11084
10771 if (token >= 0) { 11085 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10772 snprintf(msg, 64, "%s unexpected (expecting %s)", 11086 if (token >= 0)
10773 tokname[lasttoken], tokname[token]); 11087 sprintf(msg+l, " (expecting %s)", tokname(token));
10774 } else {
10775 snprintf(msg, 64, "%s unexpected", tokname[lasttoken]);
10776 }
10777 synerror(msg); 11088 synerror(msg);
10778 /* NOTREACHED */ 11089 /* NOTREACHED */
10779} 11090}
@@ -11162,435 +11473,6 @@ dup_as_newfd(from, to)
11162 return newfd; 11473 return newfd;
11163} 11474}
11164 11475
11165/*#ifdef __weak_alias
11166__weak_alias(getmode,_getmode)
11167__weak_alias(setmode,_setmode)
11168#endif*/
11169
11170#ifndef S_ISTXT
11171#if defined(__GLIBC__) && __GLIBC__ >= 2
11172#define S_ISTXT __S_ISVTX
11173#else
11174#define S_ISTXT S_ISVTX
11175#endif
11176#endif
11177
11178#define SET_LEN 6 /* initial # of bitcmd struct to malloc */
11179#define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */
11180
11181typedef struct bitcmd {
11182 char cmd;
11183 char cmd2;
11184 mode_t bits;
11185} BITCMD;
11186
11187#define CMD2_CLR 0x01
11188#define CMD2_SET 0x02
11189#define CMD2_GBITS 0x04
11190#define CMD2_OBITS 0x08
11191#define CMD2_UBITS 0x10
11192
11193static BITCMD *addcmd (BITCMD *, int, int, int, u_int);
11194static void compress_mode (BITCMD *);
11195#ifdef SETMODE_DEBUG
11196static void dumpmode (BITCMD *);
11197#endif
11198
11199/*
11200 * Given the old mode and an array of bitcmd structures, apply the operations
11201 * described in the bitcmd structures to the old mode, and return the new mode.
11202 * Note that there is no '=' command; a strict assignment is just a '-' (clear
11203 * bits) followed by a '+' (set bits).
11204 */
11205static mode_t
11206getmode(bbox, omode)
11207 const void *bbox;
11208 mode_t omode;
11209{
11210 const BITCMD *set;
11211 mode_t clrval, newmode, value;
11212
11213 _DIAGASSERT(bbox != NULL);
11214
11215 set = (const BITCMD *)bbox;
11216 newmode = omode;
11217 for (value = 0;; set++)
11218 switch(set->cmd) {
11219 /*
11220 * When copying the user, group or other bits around, we "know"
11221 * where the bits are in the mode so that we can do shifts to
11222 * copy them around. If we don't use shifts, it gets real
11223 * grundgy with lots of single bit checks and bit sets.
11224 */
11225 case 'u':
11226 value = (newmode & S_IRWXU) >> 6;
11227 goto common;
11228
11229 case 'g':
11230 value = (newmode & S_IRWXG) >> 3;
11231 goto common;
11232
11233 case 'o':
11234 value = newmode & S_IRWXO;
11235common: if (set->cmd2 & CMD2_CLR) {
11236 clrval =
11237 (set->cmd2 & CMD2_SET) ? S_IRWXO : value;
11238 if (set->cmd2 & CMD2_UBITS)
11239 newmode &= ~((clrval<<6) & set->bits);
11240 if (set->cmd2 & CMD2_GBITS)
11241 newmode &= ~((clrval<<3) & set->bits);
11242 if (set->cmd2 & CMD2_OBITS)
11243 newmode &= ~(clrval & set->bits);
11244 }
11245 if (set->cmd2 & CMD2_SET) {
11246 if (set->cmd2 & CMD2_UBITS)
11247 newmode |= (value<<6) & set->bits;
11248 if (set->cmd2 & CMD2_GBITS)
11249 newmode |= (value<<3) & set->bits;
11250 if (set->cmd2 & CMD2_OBITS)
11251 newmode |= value & set->bits;
11252 }
11253 break;
11254
11255 case '+':
11256 newmode |= set->bits;
11257 break;
11258
11259 case '-':
11260 newmode &= ~set->bits;
11261 break;
11262
11263 case 'X':
11264 if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
11265 newmode |= set->bits;
11266 break;
11267
11268 case '\0':
11269 default:
11270#ifdef SETMODE_DEBUG
11271 (void)printf("getmode:%04o -> %04o\n", omode, newmode);
11272#endif
11273 return (newmode);
11274 }
11275}
11276
11277#define ADDCMD(a, b, c, d) do { \
11278 if (set >= endset) { \
11279 BITCMD *newset; \
11280 setlen += SET_LEN_INCR; \
11281 newset = realloc(saveset, sizeof(BITCMD) * setlen); \
11282 if (newset == NULL) { \
11283 free(saveset); \
11284 return (NULL); \
11285 } \
11286 set = newset + (set - saveset); \
11287 saveset = newset; \
11288 endset = newset + (setlen - 2); \
11289 } \
11290 set = addcmd(set, (a), (b), (c), (d)); \
11291} while (/*CONSTCOND*/0)
11292
11293#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
11294
11295static void *
11296setmode(p)
11297 const char *p;
11298{
11299 int perm, who;
11300 char op, *ep;
11301 BITCMD *set, *saveset, *endset;
11302 sigset_t mysigset, sigoset;
11303 mode_t mask;
11304 int equalopdone = 0; /* pacify gcc */
11305 int permXbits, setlen;
11306
11307 if (!*p)
11308 return (NULL);
11309
11310 /*
11311 * Get a copy of the mask for the permissions that are mask relative.
11312 * Flip the bits, we want what's not set. Since it's possible that
11313 * the caller is opening files inside a signal handler, protect them
11314 * as best we can.
11315 */
11316 sigfillset(&mysigset);
11317 (void)sigprocmask(SIG_BLOCK, &mysigset, &sigoset);
11318 (void)umask(mask = umask(0));
11319 mask = ~mask;
11320 (void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
11321
11322 setlen = SET_LEN + 2;
11323
11324 if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
11325 return (NULL);
11326 saveset = set;
11327 endset = set + (setlen - 2);
11328
11329 /*
11330 * If an absolute number, get it and return; disallow non-octal digits
11331 * or illegal bits.
11332 */
11333 if (is_digit((unsigned char)*p)) {
11334 perm = (mode_t)strtol(p, &ep, 8);
11335 if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) {
11336 free(saveset);
11337 return (NULL);
11338 }
11339 ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
11340 set->cmd = 0;
11341 return (saveset);
11342 }
11343
11344 /*
11345 * Build list of structures to set/clear/copy bits as described by
11346 * each clause of the symbolic mode.
11347 */
11348 for (;;) {
11349 /* First, find out which bits might be modified. */
11350 for (who = 0;; ++p) {
11351 switch (*p) {
11352 case 'a':
11353 who |= STANDARD_BITS;
11354 break;
11355 case 'u':
11356 who |= S_ISUID|S_IRWXU;
11357 break;
11358 case 'g':
11359 who |= S_ISGID|S_IRWXG;
11360 break;
11361 case 'o':
11362 who |= S_IRWXO;
11363 break;
11364 default:
11365 goto getop;
11366 }
11367 }
11368
11369getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
11370 free(saveset);
11371 return (NULL);
11372 }
11373 if (op == '=')
11374 equalopdone = 0;
11375
11376 who &= ~S_ISTXT;
11377 for (perm = 0, permXbits = 0;; ++p) {
11378 switch (*p) {
11379 case 'r':
11380 perm |= S_IRUSR|S_IRGRP|S_IROTH;
11381 break;
11382 case 's':
11383 /*
11384 * If specific bits where requested and
11385 * only "other" bits ignore set-id.
11386 */
11387 if (who == 0 || (who & ~S_IRWXO))
11388 perm |= S_ISUID|S_ISGID;
11389 break;
11390 case 't':
11391 /*
11392 * If specific bits where requested and
11393 * only "other" bits ignore set-id.
11394 */
11395 if (who == 0 || (who & ~S_IRWXO)) {
11396 who |= S_ISTXT;
11397 perm |= S_ISTXT;
11398 }
11399 break;
11400 case 'w':
11401 perm |= S_IWUSR|S_IWGRP|S_IWOTH;
11402 break;
11403 case 'X':
11404 permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
11405 break;
11406 case 'x':
11407 perm |= S_IXUSR|S_IXGRP|S_IXOTH;
11408 break;
11409 case 'u':
11410 case 'g':
11411 case 'o':
11412 /*
11413 * When ever we hit 'u', 'g', or 'o', we have
11414 * to flush out any partial mode that we have,
11415 * and then do the copying of the mode bits.
11416 */
11417 if (perm) {
11418 ADDCMD(op, who, perm, mask);
11419 perm = 0;
11420 }
11421 if (op == '=')
11422 equalopdone = 1;
11423 if (op == '+' && permXbits) {
11424 ADDCMD('X', who, permXbits, mask);
11425 permXbits = 0;
11426 }
11427 ADDCMD(*p, who, op, mask);
11428 break;
11429
11430 default:
11431 /*
11432 * Add any permissions that we haven't already
11433 * done.
11434 */
11435 if (perm || (op == '=' && !equalopdone)) {
11436 if (op == '=')
11437 equalopdone = 1;
11438 ADDCMD(op, who, perm, mask);
11439 perm = 0;
11440 }
11441 if (permXbits) {
11442 ADDCMD('X', who, permXbits, mask);
11443 permXbits = 0;
11444 }
11445 goto apply;
11446 }
11447 }
11448
11449apply: if (!*p)
11450 break;
11451 if (*p != ',')
11452 goto getop;
11453 ++p;
11454 }
11455 set->cmd = 0;
11456#ifdef SETMODE_DEBUG
11457 (void)printf("Before compress_mode()\n");
11458 dumpmode(saveset);
11459#endif
11460 compress_mode(saveset);
11461#ifdef SETMODE_DEBUG
11462 (void)printf("After compress_mode()\n");
11463 dumpmode(saveset);
11464#endif
11465 return (saveset);
11466}
11467
11468static BITCMD *
11469addcmd(set, op, who, oparg, mask)
11470 BITCMD *set;
11471 int oparg, who;
11472 int op;
11473 u_int mask;
11474{
11475
11476 _DIAGASSERT(set != NULL);
11477
11478 switch (op) {
11479 case '=':
11480 set->cmd = '-';
11481 set->bits = who ? who : STANDARD_BITS;
11482 set++;
11483
11484 op = '+';
11485 /* FALLTHROUGH */
11486 case '+':
11487 case '-':
11488 case 'X':
11489 set->cmd = op;
11490 set->bits = (who ? who : mask) & oparg;
11491 break;
11492
11493 case 'u':
11494 case 'g':
11495 case 'o':
11496 set->cmd = op;
11497 if (who) {
11498 set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
11499 ((who & S_IRGRP) ? CMD2_GBITS : 0) |
11500 ((who & S_IROTH) ? CMD2_OBITS : 0);
11501 set->bits = (mode_t)~0;
11502 } else {
11503 set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
11504 set->bits = mask;
11505 }
11506
11507 if (oparg == '+')
11508 set->cmd2 |= CMD2_SET;
11509 else if (oparg == '-')
11510 set->cmd2 |= CMD2_CLR;
11511 else if (oparg == '=')
11512 set->cmd2 |= CMD2_SET|CMD2_CLR;
11513 break;
11514 }
11515 return (set + 1);
11516}
11517
11518#ifdef SETMODE_DEBUG
11519static void
11520dumpmode(set)
11521 BITCMD *set;
11522{
11523
11524 _DIAGASSERT(set != NULL);
11525
11526 for (; set->cmd; ++set)
11527 (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
11528 set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
11529 set->cmd2 & CMD2_CLR ? " CLR" : "",
11530 set->cmd2 & CMD2_SET ? " SET" : "",
11531 set->cmd2 & CMD2_UBITS ? " UBITS" : "",
11532 set->cmd2 & CMD2_GBITS ? " GBITS" : "",
11533 set->cmd2 & CMD2_OBITS ? " OBITS" : "");
11534}
11535#endif
11536
11537/*
11538 * Given an array of bitcmd structures, compress by compacting consecutive
11539 * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
11540 * 'g' and 'o' commands continue to be separate. They could probably be
11541 * compacted, but it's not worth the effort.
11542 */
11543static void
11544compress_mode(set)
11545 BITCMD *set;
11546{
11547 BITCMD *nset;
11548 int setbits, clrbits, Xbits, op;
11549
11550 _DIAGASSERT(set != NULL);
11551
11552 for (nset = set;;) {
11553 /* Copy over any 'u', 'g' and 'o' commands. */
11554 while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
11555 *set++ = *nset++;
11556 if (!op)
11557 return;
11558 }
11559
11560 for (setbits = clrbits = Xbits = 0;; nset++) {
11561 if ((op = nset->cmd) == '-') {
11562 clrbits |= nset->bits;
11563 setbits &= ~nset->bits;
11564 Xbits &= ~nset->bits;
11565 } else if (op == '+') {
11566 setbits |= nset->bits;
11567 clrbits &= ~nset->bits;
11568 Xbits &= ~nset->bits;
11569 } else if (op == 'X')
11570 Xbits |= nset->bits & ~setbits;
11571 else
11572 break;
11573 }
11574 if (clrbits) {
11575 set->cmd = '-';
11576 set->cmd2 = 0;
11577 set->bits = clrbits;
11578 set++;
11579 }
11580 if (setbits) {
11581 set->cmd = '+';
11582 set->cmd2 = 0;
11583 set->bits = setbits;
11584 set++;
11585 }
11586 if (Xbits) {
11587 set->cmd = 'X';
11588 set->cmd2 = 0;
11589 set->bits = Xbits;
11590 set++;
11591 }
11592 }
11593}
11594#ifdef DEBUG 11476#ifdef DEBUG
11595static void shtree (union node *, int, char *, FILE*); 11477static void shtree (union node *, int, char *, FILE*);
11596static void shcmd (union node *, FILE *); 11478static void shcmd (union node *, FILE *);
@@ -11683,6 +11565,16 @@ shcmd(cmd, fp)
11683 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { 11565 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11684 if (! first) 11566 if (! first)
11685 putchar(' '); 11567 putchar(' ');
11568#if 1
11569 s = "*error*";
11570 dftfd = 0;
11571 if ((np->nfile.type <= NFROMFD) && (np->nfile.type >= NTO)) {
11572 s = redir_strings[np->nfile.type - NTO];
11573 if (*s == '>') {
11574 dftfd = 1;
11575 }
11576 }
11577#else
11686 switch (np->nfile.type) { 11578 switch (np->nfile.type) {
11687 case NTO: s = ">"; dftfd = 1; break; 11579 case NTO: s = ">"; dftfd = 1; break;
11688 case NAPPEND: s = ">>"; dftfd = 1; break; 11580 case NAPPEND: s = ">>"; dftfd = 1; break;
@@ -11693,6 +11585,7 @@ shcmd(cmd, fp)
11693 case NFROMTO: s = "<>"; dftfd = 0; break; 11585 case NFROMTO: s = "<>"; dftfd = 0; break;
11694 default: s = "*error*"; dftfd = 0; break; 11586 default: s = "*error*"; dftfd = 0; break;
11695 } 11587 }
11588#endif
11696 if (np->nfile.fd != dftfd) 11589 if (np->nfile.fd != dftfd)
11697 fprintf(fp, "%d", np->nfile.fd); 11590 fprintf(fp, "%d", np->nfile.fd);
11698 fputs(s, fp); 11591 fputs(s, fp);
@@ -12094,16 +11987,8 @@ setsignal(int signo)
12094 } 11987 }
12095 if (*t == S_HARD_IGN || *t == action) 11988 if (*t == S_HARD_IGN || *t == action)
12096 return; 11989 return;
12097 switch (action) { 11990 act.sa_handler = ((action == S_CATCH) ? onsig
12098 case S_CATCH: 11991 : ((action == S_IGN) ? SIG_IGN : SIG_DFL));
12099 act.sa_handler = onsig;
12100 break;
12101 case S_IGN:
12102 act.sa_handler = SIG_IGN;
12103 break;
12104 default:
12105 act.sa_handler = SIG_DFL;
12106 }
12107 *t = action; 11992 *t = action;
12108 act.sa_flags = 0; 11993 act.sa_flags = 0;
12109 sigemptyset(&act.sa_mask); 11994 sigemptyset(&act.sa_mask);
@@ -12785,7 +12670,7 @@ findvar(struct var **vpp, const char *name)
12785/* 12670/*
12786 * Copyright (c) 1999 Herbert Xu <herbert@debian.org> 12671 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12787 * This file contains code for the times builtin. 12672 * This file contains code for the times builtin.
12788 * $Id: ash.c,v 1.19 2001/08/10 18:42:04 andersen Exp $ 12673 * $Id: ash.c,v 1.20 2001/08/10 19:36:07 mjn3 Exp $
12789 */ 12674 */
12790static int timescmd (int argc, char **argv) 12675static int timescmd (int argc, char **argv)
12791{ 12676{