aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2009-03-30 06:50:54 +0000
committerMike Frysinger <vapier@gentoo.org>2009-03-30 06:50:54 +0000
commitd690f68554f1c1301975bc0ab0e479e6870b3589 (patch)
treeedf70533e5a6d316f618fcb1002d14b02dcb3cfe
parent5f9f1506ad298c94e816780a3e2d5692d002fb81 (diff)
downloadbusybox-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.c44
-rw-r--r--shell/hush_test/hush-vars/unset.right19
-rwxr-xr-xshell/hush_test/hush-vars/unset.tests36
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
1003static void unset_local_var(const char *name) 1003static 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 */
5028static int builtin_unset(char **argv) 5030static 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 @@
1hush: unset: -: invalid option
21
3hush: unset: -m: invalid option
41
50
6___
70 f g
80 g
90
10___
110 f g
120
130 f g
140
15___
16hush: HUSH_VERSION: readonly variable
171 f g
18hush: HUSH_VERSION: readonly variable
191
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
2unset -
3echo $?
4unset -m a b c
5echo $?
6
7# check funky usage
8unset
9echo $?
10
11# check normal usage
12echo ___
13f=f g=g
14echo $? $f $g
15unset f
16echo $? $f $g
17unset g
18echo $? $f $g
19
20echo ___
21f=f g=g
22echo $? $f $g
23unset f g
24echo $? $f $g
25f=f g=g
26echo $? $f $g
27unset -v f g
28echo $? $f $g
29
30# check read only vars
31echo ___
32f=f g=g
33unset HUSH_VERSION
34echo $? $f $g
35unset f HUSH_VERSION g
36echo $? $f $g