Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 1 | This file is setattr.def, from which is created setattr.c. |
| 2 | It implements the builtins "export" and "readonly", in Bash. |
| 3 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 4 | Copyright (C) 1987-2012 Free Software Foundation, Inc. |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 5 | |
| 6 | This file is part of GNU Bash, the Bourne Again SHell. |
| 7 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 8 | Bash is free software: you can redistribute it and/or modify |
| 9 | it under the terms of the GNU General Public License as published by |
| 10 | the Free Software Foundation, either version 3 of the License, or |
| 11 | (at your option) any later version. |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 12 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 13 | Bash is distributed in the hope that it will be useful, |
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | GNU General Public License for more details. |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 17 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 18 | You should have received a copy of the GNU General Public License |
| 19 | along with Bash. If not, see <http://www.gnu.org/licenses/>. |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 20 | |
| 21 | $PRODUCES setattr.c |
| 22 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 23 | #include <config.h> |
| 24 | |
| 25 | #if defined (HAVE_UNISTD_H) |
Jari Aalto | cce855b | 1998-04-17 19:52:44 +0000 | [diff] [blame] | 26 | # ifdef _MINIX |
| 27 | # include <sys/types.h> |
| 28 | # endif |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 29 | # include <unistd.h> |
| 30 | #endif |
| 31 | |
| 32 | #include <stdio.h> |
| 33 | #include "../bashansi.h" |
Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 34 | #include "../bashintl.h" |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 35 | |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 36 | #include "../shell.h" |
| 37 | #include "common.h" |
| 38 | #include "bashgetopt.h" |
| 39 | |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 40 | extern int posixly_correct; |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 41 | extern int array_needs_making; |
| 42 | extern char *this_command_name; |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 43 | extern sh_builtin_func_t *this_shell_builtin; |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 44 | |
| 45 | #ifdef ARRAY_VARS |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 46 | extern int declare_builtin __P((WORD_LIST *)); |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 47 | #endif |
| 48 | |
| 49 | #define READONLY_OR_EXPORT \ |
| 50 | (this_shell_builtin == readonly_builtin || this_shell_builtin == export_builtin) |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 51 | |
| 52 | $BUILTIN export |
| 53 | $FUNCTION export_builtin |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 54 | $SHORT_DOC export [-fn] [name[=value] ...] or export -p |
| 55 | Set export attribute for shell variables. |
| 56 | |
| 57 | Marks each NAME for automatic export to the environment of subsequently |
| 58 | executed commands. If VALUE is supplied, assign VALUE before exporting. |
| 59 | |
| 60 | Options: |
| 61 | -f refer to shell functions |
| 62 | -n remove the export property from each NAME |
| 63 | -p display a list of all exported variables and functions |
| 64 | |
| 65 | An argument of `--' disables further option processing. |
| 66 | |
| 67 | Exit Status: |
| 68 | Returns success unless an invalid option is given or NAME is invalid. |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 69 | $END |
| 70 | |
| 71 | /* For each variable name in LIST, make that variable appear in the |
| 72 | environment passed to simple commands. If there is no LIST, then |
| 73 | print all such variables. An argument of `-n' says to remove the |
| 74 | exported attribute from variables named in LIST. An argument of |
| 75 | -f indicates that the names present in LIST refer to functions. */ |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 76 | int |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 77 | export_builtin (list) |
| 78 | register WORD_LIST *list; |
| 79 | { |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 80 | return (set_or_show_attributes (list, att_exported, 0)); |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | $BUILTIN readonly |
| 84 | $FUNCTION readonly_builtin |
Chet Ramey | 495aee4 | 2011-11-22 19:11:26 -0500 | [diff] [blame] | 85 | $SHORT_DOC readonly [-aAf] [name[=value] ...] or readonly -p |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 86 | Mark shell variables as unchangeable. |
| 87 | |
| 88 | Mark each NAME as read-only; the values of these NAMEs may not be |
| 89 | changed by subsequent assignment. If VALUE is supplied, assign VALUE |
| 90 | before marking as read-only. |
| 91 | |
| 92 | Options: |
| 93 | -a refer to indexed array variables |
| 94 | -A refer to associative array variables |
| 95 | -f refer to shell functions |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 96 | -p display a list of all readonly variables or functions, depending on |
| 97 | whether or not the -f option is given |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 98 | |
| 99 | An argument of `--' disables further option processing. |
| 100 | |
| 101 | Exit Status: |
| 102 | Returns success unless an invalid option is given or NAME is invalid. |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 103 | $END |
| 104 | |
| 105 | /* For each variable name in LIST, make that variable readonly. Given an |
| 106 | empty LIST, print out all existing readonly variables. */ |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 107 | int |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 108 | readonly_builtin (list) |
| 109 | register WORD_LIST *list; |
| 110 | { |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 111 | return (set_or_show_attributes (list, att_readonly, 0)); |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 112 | } |
| 113 | |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 114 | #if defined (ARRAY_VARS) |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 115 | # define ATTROPTS "aAfnp" |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 116 | #else |
| 117 | # define ATTROPTS "fnp" |
| 118 | #endif |
| 119 | |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 120 | /* For each variable name in LIST, make that variable have the specified |
| 121 | ATTRIBUTE. An arg of `-n' says to remove the attribute from the the |
Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 122 | remaining names in LIST (doesn't work for readonly). */ |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 123 | int |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 124 | set_or_show_attributes (list, attribute, nodefs) |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 125 | register WORD_LIST *list; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 126 | int attribute, nodefs; |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 127 | { |
| 128 | register SHELL_VAR *var; |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 129 | int assign, undo, any_failed, assign_error, opt; |
| 130 | int functions_only, arrays_only, assoc_only; |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 131 | int aflags; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 132 | char *name; |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 133 | #if defined (ARRAY_VARS) |
| 134 | WORD_LIST *nlist, *tlist; |
| 135 | WORD_DESC *w; |
| 136 | #endif |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 137 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 138 | functions_only = arrays_only = assoc_only = 0; |
| 139 | undo = any_failed = assign_error = 0; |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 140 | /* Read arguments from the front of the list. */ |
| 141 | reset_internal_getopt (); |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 142 | while ((opt = internal_getopt (list, ATTROPTS)) != -1) |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 143 | { |
| 144 | switch (opt) |
| 145 | { |
| 146 | case 'n': |
| 147 | undo = 1; |
| 148 | break; |
| 149 | case 'f': |
| 150 | functions_only = 1; |
| 151 | break; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 152 | #if defined (ARRAY_VARS) |
| 153 | case 'a': |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 154 | arrays_only = 1; |
| 155 | break; |
| 156 | case 'A': |
| 157 | assoc_only = 1; |
| 158 | break; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 159 | #endif |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 160 | case 'p': |
| 161 | break; |
| 162 | default: |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 163 | builtin_usage (); |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 164 | return (EX_USAGE); |
| 165 | } |
| 166 | } |
| 167 | list = loptend; |
| 168 | |
| 169 | if (list) |
| 170 | { |
| 171 | if (attribute & att_exported) |
| 172 | array_needs_making = 1; |
| 173 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 174 | /* Cannot undo readonly status, silently disallowed. */ |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 175 | if (undo && (attribute & att_readonly)) |
| 176 | attribute &= ~att_readonly; |
| 177 | |
| 178 | while (list) |
| 179 | { |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 180 | name = list->word->word; |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 181 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 182 | if (functions_only) /* xxx -f name */ |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 183 | { |
| 184 | var = find_function (name); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 185 | if (var == 0) |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 186 | { |
Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 187 | builtin_error (_("%s: not a function"), name); |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 188 | any_failed++; |
| 189 | } |
| 190 | else |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 191 | SETVARATTR (var, attribute, undo); |
| 192 | |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 193 | list = list->next; |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 194 | continue; |
| 195 | } |
| 196 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 197 | /* xxx [-np] name[=value] */ |
Jari Aalto | b80f644 | 2004-07-27 13:29:18 +0000 | [diff] [blame] | 198 | assign = assignment (name, 0); |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 199 | |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 200 | aflags = 0; |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 201 | if (assign) |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 202 | { |
| 203 | name[assign] = '\0'; |
| 204 | if (name[assign - 1] == '+') |
| 205 | { |
| 206 | aflags |= ASS_APPEND; |
| 207 | name[assign - 1] = '\0'; |
| 208 | } |
| 209 | } |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 210 | |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 211 | if (legal_identifier (name) == 0) |
| 212 | { |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 213 | sh_invalidid (name); |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 214 | if (assign) |
| 215 | assign_error++; |
| 216 | else |
| 217 | any_failed++; |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 218 | list = list->next; |
| 219 | continue; |
| 220 | } |
| 221 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 222 | if (assign) /* xxx [-np] name=value */ |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 223 | { |
| 224 | name[assign] = '='; |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 225 | if (aflags & ASS_APPEND) |
| 226 | name[assign - 1] = '+'; |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 227 | #if defined (ARRAY_VARS) |
| 228 | /* Let's try something here. Turn readonly -a xxx=yyy into |
| 229 | declare -ra xxx=yyy and see what that gets us. */ |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 230 | if (arrays_only || assoc_only) |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 231 | { |
| 232 | tlist = list->next; |
| 233 | list->next = (WORD_LIST *)NULL; |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 234 | w = arrays_only ? make_word ("-ra") : make_word ("-rA"); |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 235 | nlist = make_word_list (w, list); |
| 236 | opt = declare_builtin (nlist); |
| 237 | if (opt != EXECUTION_SUCCESS) |
| 238 | assign_error++; |
| 239 | list->next = tlist; |
| 240 | dispose_word (w); |
| 241 | free (nlist); |
| 242 | } |
| 243 | else |
| 244 | #endif |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 245 | /* This word has already been expanded once with command |
| 246 | and parameter expansion. Call do_assignment_no_expand (), |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 247 | which does not do command or parameter substitution. If |
| 248 | the assignment is not performed correctly, flag an error. */ |
| 249 | if (do_assignment_no_expand (name) == 0) |
| 250 | assign_error++; |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 251 | name[assign] = '\0'; |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 252 | if (aflags & ASS_APPEND) |
| 253 | name[assign - 1] = '\0'; |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 254 | } |
| 255 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 256 | set_var_attribute (name, attribute, undo); |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 257 | list = list->next; |
| 258 | } |
| 259 | } |
| 260 | else |
| 261 | { |
| 262 | SHELL_VAR **variable_list; |
| 263 | register int i; |
| 264 | |
| 265 | if ((attribute & att_function) || functions_only) |
| 266 | { |
| 267 | variable_list = all_shell_functions (); |
| 268 | if (attribute != att_function) |
| 269 | attribute &= ~att_function; /* so declare -xf works, for example */ |
| 270 | } |
| 271 | else |
| 272 | variable_list = all_shell_variables (); |
| 273 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 274 | #if defined (ARRAY_VARS) |
| 275 | if (attribute & att_array) |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 276 | { |
| 277 | arrays_only++; |
| 278 | if (attribute != att_array) |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 279 | attribute &= ~att_array; |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 280 | } |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 281 | else if (attribute & att_assoc) |
| 282 | { |
| 283 | assoc_only++; |
| 284 | if (attribute != att_assoc) |
| 285 | attribute &= ~att_assoc; |
| 286 | } |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 287 | #endif |
| 288 | |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 289 | if (variable_list) |
| 290 | { |
| 291 | for (i = 0; var = variable_list[i]; i++) |
| 292 | { |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 293 | #if defined (ARRAY_VARS) |
| 294 | if (arrays_only && array_p (var) == 0) |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 295 | continue; |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 296 | else if (assoc_only && assoc_p (var) == 0) |
| 297 | continue; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 298 | #endif |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 299 | if ((var->attributes & attribute)) |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 300 | { |
| 301 | show_var_attributes (var, READONLY_OR_EXPORT, nodefs); |
| 302 | if (any_failed = sh_chkwrite (any_failed)) |
| 303 | break; |
| 304 | } |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 305 | } |
| 306 | free (variable_list); |
| 307 | } |
| 308 | } |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 309 | |
| 310 | return (assign_error ? EX_BADASSIGN |
| 311 | : ((any_failed == 0) ? EXECUTION_SUCCESS |
| 312 | : EXECUTION_FAILURE)); |
| 313 | } |
| 314 | |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 315 | /* Show all variable variables (v == 1) or functions (v == 0) with |
| 316 | attributes. */ |
| 317 | int |
| 318 | show_all_var_attributes (v, nodefs) |
| 319 | int v, nodefs; |
| 320 | { |
| 321 | SHELL_VAR **variable_list, *var; |
| 322 | int any_failed; |
| 323 | register int i; |
| 324 | |
| 325 | variable_list = v ? all_shell_variables () : all_shell_functions (); |
| 326 | if (variable_list == 0) |
| 327 | return (EXECUTION_SUCCESS); |
| 328 | |
| 329 | for (i = any_failed = 0; var = variable_list[i]; i++) |
| 330 | { |
| 331 | show_var_attributes (var, READONLY_OR_EXPORT, nodefs); |
| 332 | if (any_failed = sh_chkwrite (any_failed)) |
| 333 | break; |
| 334 | } |
| 335 | free (variable_list); |
| 336 | return (any_failed == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE); |
| 337 | } |
| 338 | |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 339 | /* Show the attributes for shell variable VAR. If NODEFS is non-zero, |
| 340 | don't show function definitions along with the name. If PATTR is |
| 341 | non-zero, it indicates we're being called from `export' or `readonly'. |
| 342 | In POSIX mode, this prints the name of the calling builtin (`export' |
| 343 | or `readonly') instead of `declare', and doesn't print function defs |
| 344 | when called by `export' or `readonly'. */ |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 345 | int |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 346 | show_var_attributes (var, pattr, nodefs) |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 347 | SHELL_VAR *var; |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 348 | int pattr, nodefs; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 349 | { |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 350 | char flags[16], *x; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 351 | int i; |
| 352 | |
| 353 | i = 0; |
| 354 | |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 355 | /* pattr == 0 means we are called from `declare'. */ |
| 356 | if (pattr == 0 || posixly_correct == 0) |
| 357 | { |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 358 | #if defined (ARRAY_VARS) |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 359 | if (array_p (var)) |
| 360 | flags[i++] = 'a'; |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 361 | |
| 362 | if (assoc_p (var)) |
| 363 | flags[i++] = 'A'; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 364 | #endif |
| 365 | |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 366 | if (function_p (var)) |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 367 | flags[i++] = 'f'; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 368 | |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 369 | if (integer_p (var)) |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 370 | flags[i++] = 'i'; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 371 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 372 | if (nameref_p (var)) |
| 373 | flags[i++] = 'n'; |
| 374 | |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 375 | if (readonly_p (var)) |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 376 | flags[i++] = 'r'; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 377 | |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 378 | if (trace_p (var)) |
| 379 | flags[i++] = 't'; |
| 380 | |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 381 | if (exported_p (var)) |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 382 | flags[i++] = 'x'; |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 383 | |
| 384 | if (capcase_p (var)) |
| 385 | flags[i++] = 'c'; |
| 386 | |
| 387 | if (lowercase_p (var)) |
| 388 | flags[i++] = 'l'; |
| 389 | |
| 390 | if (uppercase_p (var)) |
| 391 | flags[i++] = 'u'; |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 392 | } |
| 393 | else |
| 394 | { |
| 395 | #if defined (ARRAY_VARS) |
| 396 | if (array_p (var)) |
| 397 | flags[i++] = 'a'; |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 398 | |
| 399 | if (assoc_p (var)) |
| 400 | flags[i++] = 'A'; |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 401 | #endif |
| 402 | |
| 403 | if (function_p (var)) |
Jari Aalto | 28ef6c3 | 2001-04-06 19:14:31 +0000 | [diff] [blame] | 404 | flags[i++] = 'f'; |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 405 | } |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 406 | |
| 407 | flags[i] = '\0'; |
| 408 | |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 409 | /* If we're printing functions with definitions, print the function def |
| 410 | first, then the attributes, instead of printing output that can't be |
| 411 | reused as input to recreate the current state. */ |
| 412 | if (function_p (var) && nodefs == 0 && (pattr == 0 || posixly_correct == 0)) |
| 413 | { |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 414 | printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL)); |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 415 | nodefs++; |
| 416 | if (pattr == 0 && i == 1 && flags[0] == 'f') |
| 417 | return 0; /* don't print `declare -f name' */ |
| 418 | } |
| 419 | |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 420 | if (pattr == 0 || posixly_correct == 0) |
| 421 | printf ("declare -%s ", i ? flags : "-"); |
| 422 | else if (i) |
| 423 | printf ("%s -%s ", this_command_name, flags); |
| 424 | else |
| 425 | printf ("%s ", this_command_name); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 426 | |
| 427 | #if defined (ARRAY_VARS) |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 428 | if (array_p (var)) |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 429 | print_array_assignment (var, 1); |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 430 | else if (assoc_p (var)) |
| 431 | print_assoc_assignment (var, 1); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 432 | else |
| 433 | #endif |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 434 | /* force `readonly' and `export' to not print out function definitions |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 435 | when in POSIX mode. */ |
| 436 | if (nodefs || (function_p (var) && pattr != 0 && posixly_correct)) |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 437 | printf ("%s\n", var->name); |
| 438 | else if (function_p (var)) |
Jari Aalto | 3185942 | 2009-01-12 13:36:28 +0000 | [diff] [blame] | 439 | printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL)); |
Chet Ramey | 495aee4 | 2011-11-22 19:11:26 -0500 | [diff] [blame] | 440 | else if (invisible_p (var) || var_isset (var) == 0) |
Jari Aalto | f73dda0 | 2001-11-13 17:56:06 +0000 | [diff] [blame] | 441 | printf ("%s\n", var->name); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 442 | else |
| 443 | { |
Chet Ramey | 495aee4 | 2011-11-22 19:11:26 -0500 | [diff] [blame] | 444 | x = sh_double_quote (value_cell (var)); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 445 | printf ("%s=%s\n", var->name, x); |
| 446 | free (x); |
| 447 | } |
| 448 | return (0); |
| 449 | } |
| 450 | |
| 451 | int |
| 452 | show_name_attributes (name, nodefs) |
| 453 | char *name; |
| 454 | int nodefs; |
| 455 | { |
| 456 | SHELL_VAR *var; |
| 457 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 458 | #if 0 |
| 459 | var = find_variable_tempenv (name); |
| 460 | #else |
| 461 | var = find_variable_noref (name); |
| 462 | #endif |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 463 | |
| 464 | if (var && invisible_p (var) == 0) |
| 465 | { |
Jari Aalto | d166f04 | 1997-06-05 14:59:13 +0000 | [diff] [blame] | 466 | show_var_attributes (var, READONLY_OR_EXPORT, nodefs); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 467 | return (0); |
| 468 | } |
| 469 | else |
| 470 | return (1); |
| 471 | } |
| 472 | |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 473 | int |
| 474 | show_func_attributes (name, nodefs) |
| 475 | char *name; |
| 476 | int nodefs; |
| 477 | { |
| 478 | SHELL_VAR *var; |
| 479 | |
| 480 | var = find_function (name); |
| 481 | |
| 482 | if (var) |
| 483 | { |
| 484 | show_var_attributes (var, READONLY_OR_EXPORT, nodefs); |
| 485 | return (0); |
| 486 | } |
| 487 | else |
| 488 | return (1); |
| 489 | } |
| 490 | |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 491 | void |
| 492 | set_var_attribute (name, attribute, undo) |
| 493 | char *name; |
| 494 | int attribute, undo; |
| 495 | { |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 496 | SHELL_VAR *var, *tv, *v; |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 497 | char *tvalue; |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 498 | |
| 499 | if (undo) |
| 500 | var = find_variable (name); |
| 501 | else |
| 502 | { |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 503 | tv = find_tempenv_variable (name); |
| 504 | /* XXX -- need to handle case where tv is a temp variable in a |
| 505 | function-scope context, since function_env has been merged into |
| 506 | the local variables table. */ |
| 507 | if (tv && tempvar_p (tv)) |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 508 | { |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 509 | tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring (""); |
| 510 | |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 511 | var = bind_variable (tv->name, tvalue, 0); |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 512 | var->attributes |= tv->attributes & ~att_tempvar; |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 513 | /* This avoids an error message when propagating a read-only var |
| 514 | later on. */ |
| 515 | if (var->context == 0 && (attribute & att_readonly)) |
| 516 | { |
| 517 | /* Don't bother to set the `propagate to the global variables |
| 518 | table' flag if we've just bound the variable in that table */ |
| 519 | v = find_global_variable (tv->name); |
| 520 | if (v != var) |
| 521 | VSETATTR (tv, att_propagate); |
| 522 | } |
| 523 | else |
| 524 | VSETATTR (tv, att_propagate); |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 525 | if (var->context != 0) |
| 526 | VSETATTR (var, att_propagate); |
| 527 | SETVARATTR (tv, attribute, undo); /* XXX */ |
| 528 | |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 529 | stupidly_hack_special_variables (tv->name); |
| 530 | |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 531 | free (tvalue); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 532 | } |
| 533 | else |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 534 | { |
Chet Ramey | ac50fba | 2014-02-26 09:36:43 -0500 | [diff] [blame] | 535 | var = find_variable_notempenv (name); |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 536 | if (var == 0) |
| 537 | { |
Jari Aalto | 95732b4 | 2005-12-07 14:08:12 +0000 | [diff] [blame] | 538 | var = bind_variable (name, (char *)NULL, 0); |
Jari Aalto | 7117c2d | 2002-07-17 14:10:11 +0000 | [diff] [blame] | 539 | VSETATTR (var, att_invisible); |
| 540 | } |
| 541 | else if (var->context != 0) |
| 542 | VSETATTR (var, att_propagate); |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 543 | } |
| 544 | } |
| 545 | |
| 546 | if (var) |
| 547 | SETVARATTR (var, attribute, undo); |
| 548 | |
Jari Aalto | bb70624 | 2000-03-17 21:46:59 +0000 | [diff] [blame] | 549 | if (var && (exported_p (var) || (attribute & att_exported))) |
Jari Aalto | ccc6cda | 1996-12-23 17:02:34 +0000 | [diff] [blame] | 550 | array_needs_making++; /* XXX */ |
Jari Aalto | 726f638 | 1996-08-26 18:22:31 +0000 | [diff] [blame] | 551 | } |