diff options
author | Mike Frysinger <vapier@gentoo.org> | 2009-03-30 06:50:54 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2009-03-30 06:50:54 +0000 |
commit | d690f68554f1c1301975bc0ab0e479e6870b3589 (patch) | |
tree | edf70533e5a6d316f618fcb1002d14b02dcb3cfe | |
parent | 5f9f1506ad298c94e816780a3e2d5692d002fb81 (diff) | |
download | busybox-w32-d690f68554f1c1301975bc0ab0e479e6870b3589.tar.gz busybox-w32-d690f68554f1c1301975bc0ab0e479e6870b3589.tar.bz2 busybox-w32-d690f68554f1c1301975bc0ab0e479e6870b3589.zip |
implement `unset` semantics as required by POSIX
-rw-r--r-- | shell/hush.c | 44 | ||||
-rw-r--r-- | shell/hush_test/hush-vars/unset.right | 19 | ||||
-rwxr-xr-x | shell/hush_test/hush-vars/unset.tests | 36 |
3 files changed, 92 insertions, 7 deletions
diff --git a/shell/hush.c b/shell/hush.c index a7aa32abe..cd6e12b11 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -1000,21 +1000,21 @@ static int set_local_var(char *str, int flg_export) | |||
1000 | return 0; | 1000 | return 0; |
1001 | } | 1001 | } |
1002 | 1002 | ||
1003 | static void unset_local_var(const char *name) | 1003 | static int unset_local_var(const char *name) |
1004 | { | 1004 | { |
1005 | struct variable *cur; | 1005 | struct variable *cur; |
1006 | struct variable *prev = prev; /* for gcc */ | 1006 | struct variable *prev = prev; /* for gcc */ |
1007 | int name_len; | 1007 | int name_len; |
1008 | 1008 | ||
1009 | if (!name) | 1009 | if (!name) |
1010 | return; | 1010 | return EXIT_SUCCESS; |
1011 | name_len = strlen(name); | 1011 | name_len = strlen(name); |
1012 | cur = G.top_var; | 1012 | cur = G.top_var; |
1013 | while (cur) { | 1013 | while (cur) { |
1014 | if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') { | 1014 | if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') { |
1015 | if (cur->flg_read_only) { | 1015 | if (cur->flg_read_only) { |
1016 | bb_error_msg("%s: readonly variable", name); | 1016 | bb_error_msg("%s: readonly variable", name); |
1017 | return; | 1017 | return EXIT_FAILURE; |
1018 | } | 1018 | } |
1019 | /* prev is ok to use here because 1st variable, HUSH_VERSION, | 1019 | /* prev is ok to use here because 1st variable, HUSH_VERSION, |
1020 | * is ro, and we cannot reach this code on the 1st pass */ | 1020 | * is ro, and we cannot reach this code on the 1st pass */ |
@@ -1024,11 +1024,12 @@ static void unset_local_var(const char *name) | |||
1024 | if (!cur->max_len) | 1024 | if (!cur->max_len) |
1025 | free(cur->varstr); | 1025 | free(cur->varstr); |
1026 | free(cur); | 1026 | free(cur); |
1027 | return; | 1027 | return EXIT_SUCCESS; |
1028 | } | 1028 | } |
1029 | prev = cur; | 1029 | prev = cur; |
1030 | cur = cur->next; | 1030 | cur = cur->next; |
1031 | } | 1031 | } |
1032 | return EXIT_SUCCESS; | ||
1032 | } | 1033 | } |
1033 | 1034 | ||
1034 | 1035 | ||
@@ -5025,11 +5026,40 @@ static int builtin_umask(char **argv) | |||
5025 | return EXIT_SUCCESS; | 5026 | return EXIT_SUCCESS; |
5026 | } | 5027 | } |
5027 | 5028 | ||
5029 | /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */ | ||
5028 | static int builtin_unset(char **argv) | 5030 | static int builtin_unset(char **argv) |
5029 | { | 5031 | { |
5030 | /* bash always returns true */ | 5032 | size_t i; |
5031 | unset_local_var(argv[1]); | 5033 | int ret; |
5032 | return EXIT_SUCCESS; | 5034 | bool var = true; |
5035 | |||
5036 | if (!argv[1]) | ||
5037 | return EXIT_SUCCESS; | ||
5038 | |||
5039 | i = 0; | ||
5040 | if (argv[1][0] == '-') { | ||
5041 | switch (argv[1][1]) { | ||
5042 | case 'v': break; | ||
5043 | case 'f': if (ENABLE_HUSH_FUNCTIONS) { var = false; break; } | ||
5044 | default: | ||
5045 | bb_error_msg("unset: %s: invalid option", argv[1]); | ||
5046 | return EXIT_FAILURE; | ||
5047 | } | ||
5048 | ++i; | ||
5049 | } | ||
5050 | |||
5051 | ret = EXIT_SUCCESS; | ||
5052 | while (argv[++i]) { | ||
5053 | if (var) { | ||
5054 | if (unset_local_var(argv[i])) | ||
5055 | ret = EXIT_FAILURE; | ||
5056 | } | ||
5057 | #if ENABLE_HUSH_FUNCTIONS | ||
5058 | else | ||
5059 | unset_local_func(argv[i]); | ||
5060 | #endif | ||
5061 | } | ||
5062 | return ret; | ||
5033 | } | 5063 | } |
5034 | 5064 | ||
5035 | /* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */ | 5065 | /* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */ |
diff --git a/shell/hush_test/hush-vars/unset.right b/shell/hush_test/hush-vars/unset.right new file mode 100644 index 000000000..8dea7c40d --- /dev/null +++ b/shell/hush_test/hush-vars/unset.right | |||
@@ -0,0 +1,19 @@ | |||
1 | hush: unset: -: invalid option | ||
2 | 1 | ||
3 | hush: unset: -m: invalid option | ||
4 | 1 | ||
5 | 0 | ||
6 | ___ | ||
7 | 0 f g | ||
8 | 0 g | ||
9 | 0 | ||
10 | ___ | ||
11 | 0 f g | ||
12 | 0 | ||
13 | 0 f g | ||
14 | 0 | ||
15 | ___ | ||
16 | hush: HUSH_VERSION: readonly variable | ||
17 | 1 f g | ||
18 | hush: HUSH_VERSION: readonly variable | ||
19 | 1 | ||
diff --git a/shell/hush_test/hush-vars/unset.tests b/shell/hush_test/hush-vars/unset.tests new file mode 100755 index 000000000..f59ce5923 --- /dev/null +++ b/shell/hush_test/hush-vars/unset.tests | |||
@@ -0,0 +1,36 @@ | |||
1 | # check invalid options are rejected | ||
2 | unset - | ||
3 | echo $? | ||
4 | unset -m a b c | ||
5 | echo $? | ||
6 | |||
7 | # check funky usage | ||
8 | unset | ||
9 | echo $? | ||
10 | |||
11 | # check normal usage | ||
12 | echo ___ | ||
13 | f=f g=g | ||
14 | echo $? $f $g | ||
15 | unset f | ||
16 | echo $? $f $g | ||
17 | unset g | ||
18 | echo $? $f $g | ||
19 | |||
20 | echo ___ | ||
21 | f=f g=g | ||
22 | echo $? $f $g | ||
23 | unset f g | ||
24 | echo $? $f $g | ||
25 | f=f g=g | ||
26 | echo $? $f $g | ||
27 | unset -v f g | ||
28 | echo $? $f $g | ||
29 | |||
30 | # check read only vars | ||
31 | echo ___ | ||
32 | f=f g=g | ||
33 | unset HUSH_VERSION | ||
34 | echo $? $f $g | ||
35 | unset f HUSH_VERSION g | ||
36 | echo $? $f $g | ||