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-2009 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 [-af] [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 and functions
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;
137 functions_only = arrays_only = assoc_only = 0;
138 undo = any_failed = assign_error = 0;
139 /* Read arguments from the front of the list. */
140 reset_internal_getopt ();
141 while ((opt = internal_getopt (list, ATTROPTS)) != -1)
151 #if defined (ARRAY_VARS)
170 if (attribute & att_exported)
171 array_needs_making = 1;
173 /* Cannot undo readonly status, silently disallowed. */
174 if (undo && (attribute & att_readonly))
175 attribute &= ~att_readonly;
179 name = list->word->word;
181 if (functions_only) /* xxx -f name */
183 var = find_function (name);
186 builtin_error (_("%s: not a function"), name);
190 SETVARATTR (var, attribute, undo);
196 /* xxx [-np] name[=value] */
197 assign = assignment (name, 0);
203 if (name[assign - 1] == '+')
205 aflags |= ASS_APPEND;
206 name[assign - 1] = '\0';
210 if (legal_identifier (name) == 0)
221 if (assign) /* xxx [-np] name=value */
224 if (aflags & ASS_APPEND)
225 name[assign - 1] = '+';
226 #if defined (ARRAY_VARS)
227 /* Let's try something here. Turn readonly -a xxx=yyy into
228 declare -ra xxx=yyy and see what that gets us. */
229 if (arrays_only || assoc_only)
232 list->next = (WORD_LIST *)NULL;
233 w = arrays_only ? make_word ("-ra") : make_word ("-rA");
234 nlist = make_word_list (w, list);
235 opt = declare_builtin (nlist);
236 if (opt != EXECUTION_SUCCESS)
244 /* This word has already been expanded once with command
245 and parameter expansion. Call do_assignment_no_expand (),
246 which does not do command or parameter substitution. If
247 the assignment is not performed correctly, flag an error. */
248 if (do_assignment_no_expand (name) == 0)
251 if (aflags & ASS_APPEND)
252 name[assign - 1] = '\0';
255 set_var_attribute (name, attribute, undo);
261 SHELL_VAR **variable_list;
264 if ((attribute & att_function) || functions_only)
266 variable_list = all_shell_functions ();
267 if (attribute != att_function)
268 attribute &= ~att_function; /* so declare -xf works, for example */
271 variable_list = all_shell_variables ();
273 #if defined (ARRAY_VARS)
274 if (attribute & att_array)
277 if (attribute != att_array)
278 attribute &= ~att_array;
280 else if (attribute & att_assoc)
283 if (attribute != att_assoc)
284 attribute &= ~att_assoc;
290 for (i = 0; var = variable_list[i]; i++)
292 #if defined (ARRAY_VARS)
293 if (arrays_only && array_p (var) == 0)
295 else if (assoc_only && assoc_p (var) == 0)
298 if ((var->attributes & attribute))
300 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
301 if (any_failed = sh_chkwrite (any_failed))
305 free (variable_list);
309 return (assign_error ? EX_BADASSIGN
310 : ((any_failed == 0) ? EXECUTION_SUCCESS
311 : EXECUTION_FAILURE));
314 /* Show all variable variables (v == 1) or functions (v == 0) with
317 show_all_var_attributes (v, nodefs)
320 SHELL_VAR **variable_list, *var;
324 variable_list = v ? all_shell_variables () : all_shell_functions ();
325 if (variable_list == 0)
326 return (EXECUTION_SUCCESS);
328 for (i = any_failed = 0; var = variable_list[i]; i++)
330 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
331 if (any_failed = sh_chkwrite (any_failed))
334 free (variable_list);
335 return (any_failed == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
338 /* Show the attributes for shell variable VAR. If NODEFS is non-zero,
339 don't show function definitions along with the name. If PATTR is
340 non-zero, it indicates we're being called from `export' or `readonly'.
341 In POSIX mode, this prints the name of the calling builtin (`export'
342 or `readonly') instead of `declare', and doesn't print function defs
343 when called by `export' or `readonly'. */
345 show_var_attributes (var, pattr, nodefs)
354 /* pattr == 0 means we are called from `declare'. */
355 if (pattr == 0 || posixly_correct == 0)
357 #if defined (ARRAY_VARS)
365 if (function_p (var))
371 if (readonly_p (var))
377 if (exported_p (var))
383 if (lowercase_p (var))
386 if (uppercase_p (var))
391 #if defined (ARRAY_VARS)
399 if (function_p (var))
405 /* If we're printing functions with definitions, print the function def
406 first, then the attributes, instead of printing output that can't be
407 reused as input to recreate the current state. */
408 if (function_p (var) && nodefs == 0 && (pattr == 0 || posixly_correct == 0))
410 printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
412 if (pattr == 0 && i == 1 && flags[0] == 'f')
413 return 0; /* don't print `declare -f name' */
416 if (pattr == 0 || posixly_correct == 0)
417 printf ("declare -%s ", i ? flags : "-");
419 printf ("%s -%s ", this_command_name, flags);
421 printf ("%s ", this_command_name);
423 #if defined (ARRAY_VARS)
425 print_array_assignment (var, 1);
426 else if (assoc_p (var))
427 print_assoc_assignment (var, 1);
430 /* force `readonly' and `export' to not print out function definitions
431 when in POSIX mode. */
432 if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
433 printf ("%s\n", var->name);
434 else if (function_p (var))
435 printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
436 else if (invisible_p (var))
437 printf ("%s\n", var->name);
440 x = sh_double_quote (var_isset (var) ? value_cell (var) : "");
441 printf ("%s=%s\n", var->name, x);
448 show_name_attributes (name, nodefs)
454 var = find_variable_internal (name, 1);
456 if (var && invisible_p (var) == 0)
458 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
466 set_var_attribute (name, attribute, undo)
474 var = find_variable (name);
477 tv = find_tempenv_variable (name);
478 /* XXX -- need to handle case where tv is a temp variable in a
479 function-scope context, since function_env has been merged into
480 the local variables table. */
481 if (tv && tempvar_p (tv))
483 tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring ("");
485 var = bind_variable (tv->name, tvalue, 0);
486 var->attributes |= tv->attributes & ~att_tempvar;
487 VSETATTR (tv, att_propagate);
488 if (var->context != 0)
489 VSETATTR (var, att_propagate);
490 SETVARATTR (tv, attribute, undo); /* XXX */
492 stupidly_hack_special_variables (tv->name);
498 var = find_variable_internal (name, 0);
501 var = bind_variable (name, (char *)NULL, 0);
502 VSETATTR (var, att_invisible);
504 else if (var->context != 0)
505 VSETATTR (var, att_propagate);
510 SETVARATTR (var, attribute, undo);
512 if (var && (exported_p (var) || (attribute & att_exported)))
513 array_needs_making++; /* XXX */