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-2012 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"
38 #include "bashgetopt.h"
40 extern int posixly_correct;
41 extern int array_needs_making;
42 extern char *this_command_name;
43 extern sh_builtin_func_t *this_shell_builtin;
46 extern int declare_builtin __P((WORD_LIST *));
49 #define READONLY_OR_EXPORT \
50 (this_shell_builtin == readonly_builtin || this_shell_builtin == export_builtin)
53 $FUNCTION export_builtin
54 $SHORT_DOC export [-fn] [name[=value] ...] or export -p
55 Set export attribute for shell variables.
57 Marks each NAME for automatic export to the environment of subsequently
58 executed commands. If VALUE is supplied, assign VALUE before exporting.
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
65 An argument of `--' disables further option processing.
68 Returns success unless an invalid option is given or NAME is invalid.
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. */
78 register WORD_LIST *list;
80 return (set_or_show_attributes (list, att_exported, 0));
84 $FUNCTION readonly_builtin
85 $SHORT_DOC readonly [-aAf] [name[=value] ...] or readonly -p
86 Mark shell variables as unchangeable.
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.
93 -a refer to indexed array variables
94 -A refer to associative array variables
95 -f refer to shell functions
96 -p display a list of all readonly variables or functions, depending on
97 whether or not the -f option is given
99 An argument of `--' disables further option processing.
102 Returns success unless an invalid option is given or NAME is invalid.
105 /* For each variable name in LIST, make that variable readonly. Given an
106 empty LIST, print out all existing readonly variables. */
108 readonly_builtin (list)
109 register WORD_LIST *list;
111 return (set_or_show_attributes (list, att_readonly, 0));
114 #if defined (ARRAY_VARS)
115 # define ATTROPTS "aAfnp"
117 # define ATTROPTS "fnp"
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
122 remaining names in LIST (doesn't work for readonly). */
124 set_or_show_attributes (list, attribute, nodefs)
125 register WORD_LIST *list;
126 int attribute, nodefs;
128 register SHELL_VAR *var;
129 int assign, undo, any_failed, assign_error, opt;
130 int functions_only, arrays_only, assoc_only;
133 #if defined (ARRAY_VARS)
134 WORD_LIST *nlist, *tlist;
138 functions_only = arrays_only = assoc_only = 0;
139 undo = any_failed = assign_error = 0;
140 /* Read arguments from the front of the list. */
141 reset_internal_getopt ();
142 while ((opt = internal_getopt (list, ATTROPTS)) != -1)
152 #if defined (ARRAY_VARS)
171 if (attribute & att_exported)
172 array_needs_making = 1;
174 /* Cannot undo readonly status, silently disallowed. */
175 if (undo && (attribute & att_readonly))
176 attribute &= ~att_readonly;
180 name = list->word->word;
182 if (functions_only) /* xxx -f name */
184 var = find_function (name);
187 builtin_error (_("%s: not a function"), name);
191 SETVARATTR (var, attribute, undo);
197 /* xxx [-np] name[=value] */
198 assign = assignment (name, 0);
204 if (name[assign - 1] == '+')
206 aflags |= ASS_APPEND;
207 name[assign - 1] = '\0';
211 if (legal_identifier (name) == 0)
222 if (assign) /* xxx [-np] name=value */
225 if (aflags & ASS_APPEND)
226 name[assign - 1] = '+';
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. */
230 if (arrays_only || assoc_only)
233 list->next = (WORD_LIST *)NULL;
234 w = arrays_only ? make_word ("-ra") : make_word ("-rA");
235 nlist = make_word_list (w, list);
236 opt = declare_builtin (nlist);
237 if (opt != EXECUTION_SUCCESS)
245 /* This word has already been expanded once with command
246 and parameter expansion. Call do_assignment_no_expand (),
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)
252 if (aflags & ASS_APPEND)
253 name[assign - 1] = '\0';
256 set_var_attribute (name, attribute, undo);
262 SHELL_VAR **variable_list;
265 if ((attribute & att_function) || functions_only)
267 variable_list = all_shell_functions ();
268 if (attribute != att_function)
269 attribute &= ~att_function; /* so declare -xf works, for example */
272 variable_list = all_shell_variables ();
274 #if defined (ARRAY_VARS)
275 if (attribute & att_array)
278 if (attribute != att_array)
279 attribute &= ~att_array;
281 else if (attribute & att_assoc)
284 if (attribute != att_assoc)
285 attribute &= ~att_assoc;
291 for (i = 0; var = variable_list[i]; i++)
293 #if defined (ARRAY_VARS)
294 if (arrays_only && array_p (var) == 0)
296 else if (assoc_only && assoc_p (var) == 0)
299 if ((var->attributes & attribute))
301 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
302 if (any_failed = sh_chkwrite (any_failed))
306 free (variable_list);
310 return (assign_error ? EX_BADASSIGN
311 : ((any_failed == 0) ? EXECUTION_SUCCESS
312 : EXECUTION_FAILURE));
315 /* Show all variable variables (v == 1) or functions (v == 0) with
318 show_all_var_attributes (v, nodefs)
321 SHELL_VAR **variable_list, *var;
325 variable_list = v ? all_shell_variables () : all_shell_functions ();
326 if (variable_list == 0)
327 return (EXECUTION_SUCCESS);
329 for (i = any_failed = 0; var = variable_list[i]; i++)
331 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
332 if (any_failed = sh_chkwrite (any_failed))
335 free (variable_list);
336 return (any_failed == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
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'. */
346 show_var_attributes (var, pattr, nodefs)
355 /* pattr == 0 means we are called from `declare'. */
356 if (pattr == 0 || posixly_correct == 0)
358 #if defined (ARRAY_VARS)
366 if (function_p (var))
375 if (readonly_p (var))
381 if (exported_p (var))
387 if (lowercase_p (var))
390 if (uppercase_p (var))
395 #if defined (ARRAY_VARS)
403 if (function_p (var))
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))
414 printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
416 if (pattr == 0 && i == 1 && flags[0] == 'f')
417 return 0; /* don't print `declare -f name' */
420 if (pattr == 0 || posixly_correct == 0)
421 printf ("declare -%s ", i ? flags : "-");
423 printf ("%s -%s ", this_command_name, flags);
425 printf ("%s ", this_command_name);
427 #if defined (ARRAY_VARS)
429 print_array_assignment (var, 1);
430 else if (assoc_p (var))
431 print_assoc_assignment (var, 1);
434 /* force `readonly' and `export' to not print out function definitions
435 when in POSIX mode. */
436 if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
437 printf ("%s\n", var->name);
438 else if (function_p (var))
439 printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
440 else if (invisible_p (var) || var_isset (var) == 0)
441 printf ("%s\n", var->name);
444 x = sh_double_quote (value_cell (var));
445 printf ("%s=%s\n", var->name, x);
452 show_name_attributes (name, nodefs)
459 var = find_variable_tempenv (name);
461 var = find_variable_noref (name);
464 if (var && invisible_p (var) == 0)
466 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
474 show_func_attributes (name, nodefs)
480 var = find_function (name);
484 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
492 set_var_attribute (name, attribute, undo)
496 SHELL_VAR *var, *tv, *v;
500 var = find_variable (name);
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))
509 tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring ("");
511 var = bind_variable (tv->name, tvalue, 0);
512 var->attributes |= tv->attributes & ~att_tempvar;
513 /* This avoids an error message when propagating a read-only var
515 if (var->context == 0 && (attribute & att_readonly))
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);
521 VSETATTR (tv, att_propagate);
524 VSETATTR (tv, att_propagate);
525 if (var->context != 0)
526 VSETATTR (var, att_propagate);
527 SETVARATTR (tv, attribute, undo); /* XXX */
529 stupidly_hack_special_variables (tv->name);
535 var = find_variable_notempenv (name);
538 var = bind_variable (name, (char *)NULL, 0);
539 VSETATTR (var, att_invisible);
541 else if (var->context != 0)
542 VSETATTR (var, att_propagate);
547 SETVARATTR (var, attribute, undo);
549 if (var && (exported_p (var) || (attribute & att_exported)))
550 array_needs_making++; /* XXX */