1 This file is setattr.def, from which is created setattr.c.
2 It implements the builtins "export" and "readonly", in Bash.
4 Copyright (C) 1987-2015 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
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.
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.
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/>.
25 #if defined (HAVE_UNISTD_H)
27 # include <sys/types.h>
33 #include "../bashansi.h"
34 #include "../bashintl.h"
37 #include "../execute_cmd.h"
40 #include "bashgetopt.h"
42 extern sh_builtin_func_t *this_shell_builtin;
45 extern int declare_builtin __P((WORD_LIST *));
48 #define READONLY_OR_EXPORT \
49 (this_shell_builtin == readonly_builtin || this_shell_builtin == export_builtin)
52 $FUNCTION export_builtin
53 $SHORT_DOC export [-fn] [name[=value] ...] or export -p
54 Set export attribute for shell variables.
56 Marks each NAME for automatic export to the environment of subsequently
57 executed commands. If VALUE is supplied, assign VALUE before exporting.
60 -f refer to shell functions
61 -n remove the export property from each NAME
62 -p display a list of all exported variables and functions
64 An argument of `--' disables further option processing.
67 Returns success unless an invalid option is given or NAME is invalid.
70 /* For each variable name in LIST, make that variable appear in the
71 environment passed to simple commands. If there is no LIST, then
72 print all such variables. An argument of `-n' says to remove the
73 exported attribute from variables named in LIST. An argument of
74 -f indicates that the names present in LIST refer to functions. */
77 register WORD_LIST *list;
79 return (set_or_show_attributes (list, att_exported, 0));
83 $FUNCTION readonly_builtin
84 $SHORT_DOC readonly [-aAf] [name[=value] ...] or readonly -p
85 Mark shell variables as unchangeable.
87 Mark each NAME as read-only; the values of these NAMEs may not be
88 changed by subsequent assignment. If VALUE is supplied, assign VALUE
89 before marking as read-only.
92 -a refer to indexed array variables
93 -A refer to associative array variables
94 -f refer to shell functions
95 -p display a list of all readonly variables or functions,
96 depending on whether or not the -f option is given
98 An argument of `--' disables further option processing.
101 Returns success unless an invalid option is given or NAME is invalid.
104 /* For each variable name in LIST, make that variable readonly. Given an
105 empty LIST, print out all existing readonly variables. */
107 readonly_builtin (list)
108 register WORD_LIST *list;
110 return (set_or_show_attributes (list, att_readonly, 0));
113 #if defined (ARRAY_VARS)
114 # define ATTROPTS "aAfnp"
116 # define ATTROPTS "fnp"
119 /* For each variable name in LIST, make that variable have the specified
120 ATTRIBUTE. An arg of `-n' says to remove the attribute from the the
121 remaining names in LIST (doesn't work for readonly). */
123 set_or_show_attributes (list, attribute, nodefs)
124 register WORD_LIST *list;
125 int attribute, nodefs;
127 register SHELL_VAR *var;
128 int assign, undo, any_failed, assign_error, opt;
129 int functions_only, arrays_only, assoc_only;
132 #if defined (ARRAY_VARS)
133 WORD_LIST *nlist, *tlist;
139 functions_only = arrays_only = assoc_only = 0;
140 undo = any_failed = assign_error = 0;
141 /* Read arguments from the front of the list. */
142 reset_internal_getopt ();
143 while ((opt = internal_getopt (list, ATTROPTS)) != -1)
153 #if defined (ARRAY_VARS)
173 if (attribute & att_exported)
174 array_needs_making = 1;
176 /* Cannot undo readonly status, silently disallowed. */
177 if (undo && (attribute & att_readonly))
178 attribute &= ~att_readonly;
182 name = list->word->word;
184 if (functions_only) /* xxx -f name */
186 var = find_function (name);
189 builtin_error (_("%s: not a function"), name);
192 else if ((attribute & att_exported) && undo == 0 && exportable_function_name (name) == 0)
194 builtin_error (_("%s: cannot export"), name);
198 SETVARATTR (var, attribute, undo);
204 /* xxx [-np] name[=value] */
205 assign = assignment (name, 0);
211 if (name[assign - 1] == '+')
213 aflags |= ASS_APPEND;
214 name[assign - 1] = '\0';
218 if (legal_identifier (name) == 0)
229 if (assign) /* xxx [-np] name=value */
232 if (aflags & ASS_APPEND)
233 name[assign - 1] = '+';
234 #if defined (ARRAY_VARS)
235 /* Let's try something here. Turn readonly -a xxx=yyy into
236 declare -ra xxx=yyy and see what that gets us. */
237 if (arrays_only || assoc_only)
240 list->next = (WORD_LIST *)NULL;
241 /* Add -g to avoid readonly/export creating local variables:
242 only local/declare/typeset create local variables */
246 if (attribute & att_readonly)
248 if (attribute & att_exported)
256 w = make_word (optw);
257 nlist = make_word_list (w, list);
259 opt = declare_builtin (nlist);
260 if (opt != EXECUTION_SUCCESS)
268 /* This word has already been expanded once with command
269 and parameter expansion. Call do_assignment_no_expand (),
270 which does not do command or parameter substitution. If
271 the assignment is not performed correctly, flag an error. */
272 if (do_assignment_no_expand (name) == 0)
275 if (aflags & ASS_APPEND)
276 name[assign - 1] = '\0';
279 set_var_attribute (name, attribute, undo);
280 if (assign) /* restore word */
283 if (aflags & ASS_APPEND)
284 name[assign-1] = '+';
291 SHELL_VAR **variable_list;
294 if ((attribute & att_function) || functions_only)
296 variable_list = all_shell_functions ();
297 if (attribute != att_function)
298 attribute &= ~att_function; /* so declare -xf works, for example */
301 variable_list = all_shell_variables ();
303 #if defined (ARRAY_VARS)
304 if (attribute & att_array)
307 if (attribute != att_array)
308 attribute &= ~att_array;
310 else if (attribute & att_assoc)
313 if (attribute != att_assoc)
314 attribute &= ~att_assoc;
320 for (i = 0; var = variable_list[i]; i++)
322 #if defined (ARRAY_VARS)
323 if (arrays_only && array_p (var) == 0)
325 else if (assoc_only && assoc_p (var) == 0)
329 /* If we imported a variable that's not a valid identifier, don't
330 show it in any lists. */
331 if ((var->attributes & (att_invisible|att_imported)) == (att_invisible|att_imported))
334 if ((var->attributes & attribute))
336 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
337 if (any_failed = sh_chkwrite (any_failed))
341 free (variable_list);
345 return (assign_error ? EX_BADASSIGN
346 : ((any_failed == 0) ? EXECUTION_SUCCESS
347 : EXECUTION_FAILURE));
350 /* Show all variable variables (v == 1) or functions (v == 0) with
353 show_all_var_attributes (v, nodefs)
356 SHELL_VAR **variable_list, *var;
360 variable_list = v ? all_shell_variables () : all_shell_functions ();
361 if (variable_list == 0)
362 return (EXECUTION_SUCCESS);
364 for (i = any_failed = 0; var = variable_list[i]; i++)
366 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
367 if (any_failed = sh_chkwrite (any_failed))
370 free (variable_list);
371 return (any_failed == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
375 var_attribute_string (var, pattr, flags)
378 char *flags; /* filled in with attributes */
384 /* pattr == 0 means we are called from `declare'. */
385 if (pattr == 0 || posixly_correct == 0)
387 #if defined (ARRAY_VARS)
395 if (function_p (var))
404 if (readonly_p (var))
410 if (exported_p (var))
416 if (lowercase_p (var))
419 if (uppercase_p (var))
424 #if defined (ARRAY_VARS)
432 if (function_p (var))
440 /* Show the attributes for shell variable VAR. If NODEFS is non-zero,
441 don't show function definitions along with the name. If PATTR is
442 non-zero, it indicates we're being called from `export' or `readonly'.
443 In POSIX mode, this prints the name of the calling builtin (`export'
444 or `readonly') instead of `declare', and doesn't print function defs
445 when called by `export' or `readonly'. */
447 show_var_attributes (var, pattr, nodefs)
451 char flags[MAX_ATTRIBUTES], *x;
454 i = var_attribute_string (var, pattr, flags);
456 /* If we're printing functions with definitions, print the function def
457 first, then the attributes, instead of printing output that can't be
458 reused as input to recreate the current state. */
459 if (function_p (var) && nodefs == 0 && (pattr == 0 || posixly_correct == 0))
461 printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
463 if (pattr == 0 && i == 1 && flags[0] == 'f')
464 return 0; /* don't print `declare -f name' */
467 if (pattr == 0 || posixly_correct == 0)
468 printf ("declare -%s ", i ? flags : "-");
470 printf ("%s -%s ", this_command_name, flags);
472 printf ("%s ", this_command_name);
474 #if defined (ARRAY_VARS)
475 if (invisible_p (var) && (array_p (var) || assoc_p (var)))
476 printf ("%s\n", var->name);
477 else if (array_p (var))
478 print_array_assignment (var, 0);
479 else if (assoc_p (var))
480 print_assoc_assignment (var, 0);
483 /* force `readonly' and `export' to not print out function definitions
484 when in POSIX mode. */
485 if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
486 printf ("%s\n", var->name);
487 else if (function_p (var))
488 printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
489 else if (invisible_p (var) || var_isset (var) == 0)
490 printf ("%s\n", var->name);
493 x = sh_double_quote (value_cell (var));
494 printf ("%s=%s\n", var->name, x);
501 show_name_attributes (name, nodefs)
508 var = find_variable_tempenv (name);
510 var = find_variable_noref (name);
513 if (var /* && invisible_p (var) == 0 */)
515 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
523 show_func_attributes (name, nodefs)
529 var = find_function (name);
533 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
541 set_var_attribute (name, attribute, undo)
545 SHELL_VAR *var, *tv, *v, *refvar;
549 var = find_variable (name);
552 tv = find_tempenv_variable (name);
553 /* XXX -- need to handle case where tv is a temp variable in a
554 function-scope context, since function_env has been merged into
555 the local variables table. */
556 if (tv && tempvar_p (tv))
558 tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring ("");
560 var = bind_variable (tv->name, tvalue, 0);
564 return; /* XXX - no error message here */
566 var->attributes |= tv->attributes & ~att_tempvar;
567 /* This avoids an error message when propagating a read-only var
569 if (posixly_correct || shell_compatibility_level <= 44)
571 if (var->context == 0 && (attribute & att_readonly))
573 /* Don't bother to set the `propagate to the global variables
574 table' flag if we've just bound the variable in that
576 v = find_global_variable (tv->name);
578 VSETATTR (tv, att_propagate);
581 VSETATTR (tv, att_propagate);
582 if (var->context != 0)
583 VSETATTR (var, att_propagate);
586 SETVARATTR (tv, attribute, undo); /* XXX */
588 stupidly_hack_special_variables (tv->name);
594 var = find_variable_notempenv (name);
597 /* We might have a nameref pointing to something that we can't
598 resolve to a shell variable. If we do, skip it. We do a little
599 checking just so we can print an error message. */
600 refvar = find_variable_nameref_for_create (name, 0);
601 if (refvar == INVALID_NAMEREF_VALUE)
603 /* Otherwise we probably have a nameref pointing to a variable
604 that hasn't been created yet. bind_variable will take care
609 var = bind_variable (name, (char *)NULL, 0);
610 if (var && no_invisible_vars == 0)
611 VSETATTR (var, att_invisible);
613 else if (var->context != 0)
614 VSETATTR (var, att_propagate);
619 SETVARATTR (var, attribute, undo);
621 if (var && (exported_p (var) || (attribute & att_exported)))
622 array_needs_making++; /* XXX */