aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2016-10-02 21:12:02 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2016-10-02 21:12:02 +0200
commit61508d9624703f2d0da8776e6a5e2333eadd5be9 (patch)
tree46ff0e0f9558af9b50011b4dfa07fecafa89d5a2
parentebedb9478d0d91d8aecf28531907e3a277450d0d (diff)
downloadbusybox-w32-61508d9624703f2d0da8776e6a5e2333eadd5be9.tar.gz
busybox-w32-61508d9624703f2d0da8776e6a5e2333eadd5be9.tar.bz2
busybox-w32-61508d9624703f2d0da8776e6a5e2333eadd5be9.zip
hush: fix var3.tests
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/hush.c420
-rw-r--r--shell/hush_test/hush-vars/var3.is.in.bugs0
-rw-r--r--shell/hush_test/hush-vars/var3.right (renamed from shell/hush_test/hush-bugs/var3.right)0
-rwxr-xr-xshell/hush_test/hush-vars/var3.tests (renamed from shell/hush_test/hush-bugs/var3.tests)0
4 files changed, 214 insertions, 206 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 8054d1d45..5990d690c 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -8733,6 +8733,14 @@ static void helper_export_local(char **argv, int exp, int lvl)
8733 continue; 8733 continue;
8734 } 8734 }
8735 } 8735 }
8736#if ENABLE_HUSH_LOCAL
8737 if (exp == 0 /* local? */
8738 && var && var->func_nest_level == lvl
8739 ) {
8740 /* "local x=abc; ...; local x" - ignore second local decl */
8741 continue;
8742 }
8743#endif
8736 /* Exporting non-existing variable. 8744 /* Exporting non-existing variable.
8737 * bash does not put it in environment, 8745 * bash does not put it in environment,
8738 * but remembers that it is exported, 8746 * but remembers that it is exported,
@@ -8807,6 +8815,212 @@ static int FAST_FUNC builtin_local(char **argv)
8807} 8815}
8808#endif 8816#endif
8809 8817
8818/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */
8819static int FAST_FUNC builtin_unset(char **argv)
8820{
8821 int ret;
8822 unsigned opts;
8823
8824 /* "!": do not abort on errors */
8825 /* "+": stop at 1st non-option */
8826 opts = getopt32(argv, "!+vf");
8827 if (opts == (unsigned)-1)
8828 return EXIT_FAILURE;
8829 if (opts == 3) {
8830 bb_error_msg("unset: -v and -f are exclusive");
8831 return EXIT_FAILURE;
8832 }
8833 argv += optind;
8834
8835 ret = EXIT_SUCCESS;
8836 while (*argv) {
8837 if (!(opts & 2)) { /* not -f */
8838 if (unset_local_var(*argv)) {
8839 /* unset <nonexistent_var> doesn't fail.
8840 * Error is when one tries to unset RO var.
8841 * Message was printed by unset_local_var. */
8842 ret = EXIT_FAILURE;
8843 }
8844 }
8845#if ENABLE_HUSH_FUNCTIONS
8846 else {
8847 unset_func(*argv);
8848 }
8849#endif
8850 argv++;
8851 }
8852 return ret;
8853}
8854
8855/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set
8856 * built-in 'set' handler
8857 * SUSv3 says:
8858 * set [-abCefhmnuvx] [-o option] [argument...]
8859 * set [+abCefhmnuvx] [+o option] [argument...]
8860 * set -- [argument...]
8861 * set -o
8862 * set +o
8863 * Implementations shall support the options in both their hyphen and
8864 * plus-sign forms. These options can also be specified as options to sh.
8865 * Examples:
8866 * Write out all variables and their values: set
8867 * Set $1, $2, and $3 and set "$#" to 3: set c a b
8868 * Turn on the -x and -v options: set -xv
8869 * Unset all positional parameters: set --
8870 * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x"
8871 * Set the positional parameters to the expansion of x, even if x expands
8872 * with a leading '-' or '+': set -- $x
8873 *
8874 * So far, we only support "set -- [argument...]" and some of the short names.
8875 */
8876static int FAST_FUNC builtin_set(char **argv)
8877{
8878 int n;
8879 char **pp, **g_argv;
8880 char *arg = *++argv;
8881
8882 if (arg == NULL) {
8883 struct variable *e;
8884 for (e = G.top_var; e; e = e->next)
8885 puts(e->varstr);
8886 return EXIT_SUCCESS;
8887 }
8888
8889 do {
8890 if (strcmp(arg, "--") == 0) {
8891 ++argv;
8892 goto set_argv;
8893 }
8894 if (arg[0] != '+' && arg[0] != '-')
8895 break;
8896 for (n = 1; arg[n]; ++n) {
8897 if (set_mode((arg[0] == '-'), arg[n], argv[1]))
8898 goto error;
8899 if (arg[n] == 'o' && argv[1])
8900 argv++;
8901 }
8902 } while ((arg = *++argv) != NULL);
8903 /* Now argv[0] is 1st argument */
8904
8905 if (arg == NULL)
8906 return EXIT_SUCCESS;
8907 set_argv:
8908
8909 /* NB: G.global_argv[0] ($0) is never freed/changed */
8910 g_argv = G.global_argv;
8911 if (G.global_args_malloced) {
8912 pp = g_argv;
8913 while (*++pp)
8914 free(*pp);
8915 g_argv[1] = NULL;
8916 } else {
8917 G.global_args_malloced = 1;
8918 pp = xzalloc(sizeof(pp[0]) * 2);
8919 pp[0] = g_argv[0]; /* retain $0 */
8920 g_argv = pp;
8921 }
8922 /* This realloc's G.global_argv */
8923 G.global_argv = pp = add_strings_to_strings(g_argv, argv, /*dup:*/ 1);
8924
8925 n = 1;
8926 while (*++pp)
8927 n++;
8928 G.global_argc = n;
8929
8930 return EXIT_SUCCESS;
8931
8932 /* Nothing known, so abort */
8933 error:
8934 bb_error_msg("set: %s: invalid option", arg);
8935 return EXIT_FAILURE;
8936}
8937
8938static int FAST_FUNC builtin_shift(char **argv)
8939{
8940 int n = 1;
8941 argv = skip_dash_dash(argv);
8942 if (argv[0]) {
8943 n = atoi(argv[0]);
8944 }
8945 if (n >= 0 && n < G.global_argc) {
8946 if (G.global_args_malloced) {
8947 int m = 1;
8948 while (m <= n)
8949 free(G.global_argv[m++]);
8950 }
8951 G.global_argc -= n;
8952 memmove(&G.global_argv[1], &G.global_argv[n+1],
8953 G.global_argc * sizeof(G.global_argv[0]));
8954 return EXIT_SUCCESS;
8955 }
8956 return EXIT_FAILURE;
8957}
8958
8959/* Interruptibility of read builtin in bash
8960 * (tested on bash-4.2.8 by sending signals (not by ^C)):
8961 *
8962 * Empty trap makes read ignore corresponding signal, for any signal.
8963 *
8964 * SIGINT:
8965 * - terminates non-interactive shell;
8966 * - interrupts read in interactive shell;
8967 * if it has non-empty trap:
8968 * - executes trap and returns to command prompt in interactive shell;
8969 * - executes trap and returns to read in non-interactive shell;
8970 * SIGTERM:
8971 * - is ignored (does not interrupt) read in interactive shell;
8972 * - terminates non-interactive shell;
8973 * if it has non-empty trap:
8974 * - executes trap and returns to read;
8975 * SIGHUP:
8976 * - terminates shell (regardless of interactivity);
8977 * if it has non-empty trap:
8978 * - executes trap and returns to read;
8979 */
8980static int FAST_FUNC builtin_read(char **argv)
8981{
8982 const char *r;
8983 char *opt_n = NULL;
8984 char *opt_p = NULL;
8985 char *opt_t = NULL;
8986 char *opt_u = NULL;
8987 const char *ifs;
8988 int read_flags;
8989
8990 /* "!": do not abort on errors.
8991 * Option string must start with "sr" to match BUILTIN_READ_xxx
8992 */
8993 read_flags = getopt32(argv, "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u);
8994 if (read_flags == (uint32_t)-1)
8995 return EXIT_FAILURE;
8996 argv += optind;
8997 ifs = get_local_var_value("IFS"); /* can be NULL */
8998
8999 again:
9000 r = shell_builtin_read(set_local_var_from_halves,
9001 argv,
9002 ifs,
9003 read_flags,
9004 opt_n,
9005 opt_p,
9006 opt_t,
9007 opt_u
9008 );
9009
9010 if ((uintptr_t)r == 1 && errno == EINTR) {
9011 unsigned sig = check_and_run_traps();
9012 if (sig && sig != SIGINT)
9013 goto again;
9014 }
9015
9016 if ((uintptr_t)r > 1) {
9017 bb_error_msg("%s", r);
9018 r = (char*)(uintptr_t)1;
9019 }
9020
9021 return (uintptr_t)r;
9022}
9023
8810static int FAST_FUNC builtin_trap(char **argv) 9024static int FAST_FUNC builtin_trap(char **argv)
8811{ 9025{
8812 int sig; 9026 int sig;
@@ -9075,175 +9289,6 @@ static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM)
9075 return EXIT_SUCCESS; 9289 return EXIT_SUCCESS;
9076} 9290}
9077 9291
9078/* Interruptibility of read builtin in bash
9079 * (tested on bash-4.2.8 by sending signals (not by ^C)):
9080 *
9081 * Empty trap makes read ignore corresponding signal, for any signal.
9082 *
9083 * SIGINT:
9084 * - terminates non-interactive shell;
9085 * - interrupts read in interactive shell;
9086 * if it has non-empty trap:
9087 * - executes trap and returns to command prompt in interactive shell;
9088 * - executes trap and returns to read in non-interactive shell;
9089 * SIGTERM:
9090 * - is ignored (does not interrupt) read in interactive shell;
9091 * - terminates non-interactive shell;
9092 * if it has non-empty trap:
9093 * - executes trap and returns to read;
9094 * SIGHUP:
9095 * - terminates shell (regardless of interactivity);
9096 * if it has non-empty trap:
9097 * - executes trap and returns to read;
9098 */
9099static int FAST_FUNC builtin_read(char **argv)
9100{
9101 const char *r;
9102 char *opt_n = NULL;
9103 char *opt_p = NULL;
9104 char *opt_t = NULL;
9105 char *opt_u = NULL;
9106 const char *ifs;
9107 int read_flags;
9108
9109 /* "!": do not abort on errors.
9110 * Option string must start with "sr" to match BUILTIN_READ_xxx
9111 */
9112 read_flags = getopt32(argv, "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u);
9113 if (read_flags == (uint32_t)-1)
9114 return EXIT_FAILURE;
9115 argv += optind;
9116 ifs = get_local_var_value("IFS"); /* can be NULL */
9117
9118 again:
9119 r = shell_builtin_read(set_local_var_from_halves,
9120 argv,
9121 ifs,
9122 read_flags,
9123 opt_n,
9124 opt_p,
9125 opt_t,
9126 opt_u
9127 );
9128
9129 if ((uintptr_t)r == 1 && errno == EINTR) {
9130 unsigned sig = check_and_run_traps();
9131 if (sig && sig != SIGINT)
9132 goto again;
9133 }
9134
9135 if ((uintptr_t)r > 1) {
9136 bb_error_msg("%s", r);
9137 r = (char*)(uintptr_t)1;
9138 }
9139
9140 return (uintptr_t)r;
9141}
9142
9143/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set
9144 * built-in 'set' handler
9145 * SUSv3 says:
9146 * set [-abCefhmnuvx] [-o option] [argument...]
9147 * set [+abCefhmnuvx] [+o option] [argument...]
9148 * set -- [argument...]
9149 * set -o
9150 * set +o
9151 * Implementations shall support the options in both their hyphen and
9152 * plus-sign forms. These options can also be specified as options to sh.
9153 * Examples:
9154 * Write out all variables and their values: set
9155 * Set $1, $2, and $3 and set "$#" to 3: set c a b
9156 * Turn on the -x and -v options: set -xv
9157 * Unset all positional parameters: set --
9158 * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x"
9159 * Set the positional parameters to the expansion of x, even if x expands
9160 * with a leading '-' or '+': set -- $x
9161 *
9162 * So far, we only support "set -- [argument...]" and some of the short names.
9163 */
9164static int FAST_FUNC builtin_set(char **argv)
9165{
9166 int n;
9167 char **pp, **g_argv;
9168 char *arg = *++argv;
9169
9170 if (arg == NULL) {
9171 struct variable *e;
9172 for (e = G.top_var; e; e = e->next)
9173 puts(e->varstr);
9174 return EXIT_SUCCESS;
9175 }
9176
9177 do {
9178 if (strcmp(arg, "--") == 0) {
9179 ++argv;
9180 goto set_argv;
9181 }
9182 if (arg[0] != '+' && arg[0] != '-')
9183 break;
9184 for (n = 1; arg[n]; ++n) {
9185 if (set_mode((arg[0] == '-'), arg[n], argv[1]))
9186 goto error;
9187 if (arg[n] == 'o' && argv[1])
9188 argv++;
9189 }
9190 } while ((arg = *++argv) != NULL);
9191 /* Now argv[0] is 1st argument */
9192
9193 if (arg == NULL)
9194 return EXIT_SUCCESS;
9195 set_argv:
9196
9197 /* NB: G.global_argv[0] ($0) is never freed/changed */
9198 g_argv = G.global_argv;
9199 if (G.global_args_malloced) {
9200 pp = g_argv;
9201 while (*++pp)
9202 free(*pp);
9203 g_argv[1] = NULL;
9204 } else {
9205 G.global_args_malloced = 1;
9206 pp = xzalloc(sizeof(pp[0]) * 2);
9207 pp[0] = g_argv[0]; /* retain $0 */
9208 g_argv = pp;
9209 }
9210 /* This realloc's G.global_argv */
9211 G.global_argv = pp = add_strings_to_strings(g_argv, argv, /*dup:*/ 1);
9212
9213 n = 1;
9214 while (*++pp)
9215 n++;
9216 G.global_argc = n;
9217
9218 return EXIT_SUCCESS;
9219
9220 /* Nothing known, so abort */
9221 error:
9222 bb_error_msg("set: %s: invalid option", arg);
9223 return EXIT_FAILURE;
9224}
9225
9226static int FAST_FUNC builtin_shift(char **argv)
9227{
9228 int n = 1;
9229 argv = skip_dash_dash(argv);
9230 if (argv[0]) {
9231 n = atoi(argv[0]);
9232 }
9233 if (n >= 0 && n < G.global_argc) {
9234 if (G.global_args_malloced) {
9235 int m = 1;
9236 while (m <= n)
9237 free(G.global_argv[m++]);
9238 }
9239 G.global_argc -= n;
9240 memmove(&G.global_argv[1], &G.global_argv[n+1],
9241 G.global_argc * sizeof(G.global_argv[0]));
9242 return EXIT_SUCCESS;
9243 }
9244 return EXIT_FAILURE;
9245}
9246
9247static int FAST_FUNC builtin_source(char **argv) 9292static int FAST_FUNC builtin_source(char **argv)
9248{ 9293{
9249 char *arg_path, *filename; 9294 char *arg_path, *filename;
@@ -9334,43 +9379,6 @@ static int FAST_FUNC builtin_umask(char **argv)
9334 return !rc; /* rc != 0 - success */ 9379 return !rc; /* rc != 0 - success */
9335} 9380}
9336 9381
9337/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */
9338static int FAST_FUNC builtin_unset(char **argv)
9339{
9340 int ret;
9341 unsigned opts;
9342
9343 /* "!": do not abort on errors */
9344 /* "+": stop at 1st non-option */
9345 opts = getopt32(argv, "!+vf");
9346 if (opts == (unsigned)-1)
9347 return EXIT_FAILURE;
9348 if (opts == 3) {
9349 bb_error_msg("unset: -v and -f are exclusive");
9350 return EXIT_FAILURE;
9351 }
9352 argv += optind;
9353
9354 ret = EXIT_SUCCESS;
9355 while (*argv) {
9356 if (!(opts & 2)) { /* not -f */
9357 if (unset_local_var(*argv)) {
9358 /* unset <nonexistent_var> doesn't fail.
9359 * Error is when one tries to unset RO var.
9360 * Message was printed by unset_local_var. */
9361 ret = EXIT_FAILURE;
9362 }
9363 }
9364#if ENABLE_HUSH_FUNCTIONS
9365 else {
9366 unset_func(*argv);
9367 }
9368#endif
9369 argv++;
9370 }
9371 return ret;
9372}
9373
9374/* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */ 9382/* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */
9375static int FAST_FUNC builtin_wait(char **argv) 9383static int FAST_FUNC builtin_wait(char **argv)
9376{ 9384{
diff --git a/shell/hush_test/hush-vars/var3.is.in.bugs b/shell/hush_test/hush-vars/var3.is.in.bugs
deleted file mode 100644
index e69de29bb..000000000
--- a/shell/hush_test/hush-vars/var3.is.in.bugs
+++ /dev/null
diff --git a/shell/hush_test/hush-bugs/var3.right b/shell/hush_test/hush-vars/var3.right
index 8eb0e3337..8eb0e3337 100644
--- a/shell/hush_test/hush-bugs/var3.right
+++ b/shell/hush_test/hush-vars/var3.right
diff --git a/shell/hush_test/hush-bugs/var3.tests b/shell/hush_test/hush-vars/var3.tests
index 97b102cbe..97b102cbe 100755
--- a/shell/hush_test/hush-bugs/var3.tests
+++ b/shell/hush_test/hush-vars/var3.tests