blob: 3be31896ef272f8e4fbac76acaa4bfc0b68a164e [file] [log] [blame]
Jari Aalto726f6381996-08-26 18:22:31 +00001This file is setattr.def, from which is created setattr.c.
2It implements the builtins "export" and "readonly", in Bash.
3
Chet Rameyac50fba2014-02-26 09:36:43 -05004Copyright (C) 1987-2012 Free Software Foundation, Inc.
Jari Aalto726f6381996-08-26 18:22:31 +00005
6This file is part of GNU Bash, the Bourne Again SHell.
7
Jari Aalto31859422009-01-12 13:36:28 +00008Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
Jari Aalto726f6381996-08-26 18:22:31 +000012
Jari Aalto31859422009-01-12 13:36:28 +000013Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
Jari Aalto726f6381996-08-26 18:22:31 +000017
Jari Aalto31859422009-01-12 13:36:28 +000018You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
Jari Aalto726f6381996-08-26 18:22:31 +000020
21$PRODUCES setattr.c
22
Jari Aaltoccc6cda1996-12-23 17:02:34 +000023#include <config.h>
24
25#if defined (HAVE_UNISTD_H)
Jari Aaltocce855b1998-04-17 19:52:44 +000026# ifdef _MINIX
27# include <sys/types.h>
28# endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000029# include <unistd.h>
30#endif
31
32#include <stdio.h>
33#include "../bashansi.h"
Jari Aaltob80f6442004-07-27 13:29:18 +000034#include "../bashintl.h"
Jari Aaltoccc6cda1996-12-23 17:02:34 +000035
Jari Aalto726f6381996-08-26 18:22:31 +000036#include "../shell.h"
37#include "common.h"
38#include "bashgetopt.h"
39
Jari Aaltod166f041997-06-05 14:59:13 +000040extern int posixly_correct;
Jari Aalto726f6381996-08-26 18:22:31 +000041extern int array_needs_making;
42extern char *this_command_name;
Jari Aaltof73dda02001-11-13 17:56:06 +000043extern sh_builtin_func_t *this_shell_builtin;
Jari Aaltod166f041997-06-05 14:59:13 +000044
45#ifdef ARRAY_VARS
Jari Aalto7117c2d2002-07-17 14:10:11 +000046extern int declare_builtin __P((WORD_LIST *));
Jari Aaltod166f041997-06-05 14:59:13 +000047#endif
48
49#define READONLY_OR_EXPORT \
50 (this_shell_builtin == readonly_builtin || this_shell_builtin == export_builtin)
Jari Aalto726f6381996-08-26 18:22:31 +000051
52$BUILTIN export
53$FUNCTION export_builtin
Jari Aalto31859422009-01-12 13:36:28 +000054$SHORT_DOC export [-fn] [name[=value] ...] or export -p
55Set export attribute for shell variables.
56
57Marks each NAME for automatic export to the environment of subsequently
58executed commands. If VALUE is supplied, assign VALUE before exporting.
59
60Options:
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
65An argument of `--' disables further option processing.
66
67Exit Status:
68Returns success unless an invalid option is given or NAME is invalid.
Jari Aalto726f6381996-08-26 18:22:31 +000069$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 Aaltoccc6cda1996-12-23 17:02:34 +000076int
Jari Aalto726f6381996-08-26 18:22:31 +000077export_builtin (list)
78 register WORD_LIST *list;
79{
Jari Aaltoccc6cda1996-12-23 17:02:34 +000080 return (set_or_show_attributes (list, att_exported, 0));
Jari Aalto726f6381996-08-26 18:22:31 +000081}
82
83$BUILTIN readonly
84$FUNCTION readonly_builtin
Chet Ramey495aee42011-11-22 19:11:26 -050085$SHORT_DOC readonly [-aAf] [name[=value] ...] or readonly -p
Jari Aalto31859422009-01-12 13:36:28 +000086Mark shell variables as unchangeable.
87
88Mark each NAME as read-only; the values of these NAMEs may not be
89changed by subsequent assignment. If VALUE is supplied, assign VALUE
90before marking as read-only.
91
92Options:
93 -a refer to indexed array variables
94 -A refer to associative array variables
95 -f refer to shell functions
Chet Rameyac50fba2014-02-26 09:36:43 -050096 -p display a list of all readonly variables or functions, depending on
97 whether or not the -f option is given
Jari Aalto31859422009-01-12 13:36:28 +000098
99An argument of `--' disables further option processing.
100
101Exit Status:
102Returns success unless an invalid option is given or NAME is invalid.
Jari Aalto726f6381996-08-26 18:22:31 +0000103$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 Aaltoccc6cda1996-12-23 17:02:34 +0000107int
Jari Aalto726f6381996-08-26 18:22:31 +0000108readonly_builtin (list)
109 register WORD_LIST *list;
110{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000111 return (set_or_show_attributes (list, att_readonly, 0));
Jari Aalto726f6381996-08-26 18:22:31 +0000112}
113
Jari Aalto7117c2d2002-07-17 14:10:11 +0000114#if defined (ARRAY_VARS)
Jari Aalto31859422009-01-12 13:36:28 +0000115# define ATTROPTS "aAfnp"
Jari Aalto7117c2d2002-07-17 14:10:11 +0000116#else
117# define ATTROPTS "fnp"
118#endif
119
Jari Aalto726f6381996-08-26 18:22:31 +0000120/* 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 Aaltob80f6442004-07-27 13:29:18 +0000122 remaining names in LIST (doesn't work for readonly). */
Jari Aalto726f6381996-08-26 18:22:31 +0000123int
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000124set_or_show_attributes (list, attribute, nodefs)
Jari Aalto726f6381996-08-26 18:22:31 +0000125 register WORD_LIST *list;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000126 int attribute, nodefs;
Jari Aalto726f6381996-08-26 18:22:31 +0000127{
128 register SHELL_VAR *var;
Jari Aalto31859422009-01-12 13:36:28 +0000129 int assign, undo, any_failed, assign_error, opt;
130 int functions_only, arrays_only, assoc_only;
Jari Aalto95732b42005-12-07 14:08:12 +0000131 int aflags;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000132 char *name;
Jari Aaltod166f041997-06-05 14:59:13 +0000133#if defined (ARRAY_VARS)
134 WORD_LIST *nlist, *tlist;
135 WORD_DESC *w;
136#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000137
Jari Aalto31859422009-01-12 13:36:28 +0000138 functions_only = arrays_only = assoc_only = 0;
139 undo = any_failed = assign_error = 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000140 /* Read arguments from the front of the list. */
141 reset_internal_getopt ();
Jari Aalto7117c2d2002-07-17 14:10:11 +0000142 while ((opt = internal_getopt (list, ATTROPTS)) != -1)
Jari Aalto726f6381996-08-26 18:22:31 +0000143 {
144 switch (opt)
145 {
146 case 'n':
147 undo = 1;
148 break;
149 case 'f':
150 functions_only = 1;
151 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000152#if defined (ARRAY_VARS)
153 case 'a':
Jari Aalto31859422009-01-12 13:36:28 +0000154 arrays_only = 1;
155 break;
156 case 'A':
157 assoc_only = 1;
158 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000159#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000160 case 'p':
161 break;
162 default:
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000163 builtin_usage ();
Jari Aalto726f6381996-08-26 18:22:31 +0000164 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 Aaltoccc6cda1996-12-23 17:02:34 +0000174 /* Cannot undo readonly status, silently disallowed. */
Jari Aalto726f6381996-08-26 18:22:31 +0000175 if (undo && (attribute & att_readonly))
176 attribute &= ~att_readonly;
177
178 while (list)
179 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000180 name = list->word->word;
Jari Aalto726f6381996-08-26 18:22:31 +0000181
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000182 if (functions_only) /* xxx -f name */
Jari Aalto726f6381996-08-26 18:22:31 +0000183 {
184 var = find_function (name);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000185 if (var == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000186 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000187 builtin_error (_("%s: not a function"), name);
Jari Aalto726f6381996-08-26 18:22:31 +0000188 any_failed++;
189 }
190 else
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000191 SETVARATTR (var, attribute, undo);
192
Jari Aalto726f6381996-08-26 18:22:31 +0000193 list = list->next;
Jari Aalto726f6381996-08-26 18:22:31 +0000194 continue;
195 }
196
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000197 /* xxx [-np] name[=value] */
Jari Aaltob80f6442004-07-27 13:29:18 +0000198 assign = assignment (name, 0);
Jari Aalto726f6381996-08-26 18:22:31 +0000199
Jari Aalto95732b42005-12-07 14:08:12 +0000200 aflags = 0;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000201 if (assign)
Jari Aalto95732b42005-12-07 14:08:12 +0000202 {
203 name[assign] = '\0';
204 if (name[assign - 1] == '+')
205 {
206 aflags |= ASS_APPEND;
207 name[assign - 1] = '\0';
208 }
209 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000210
Jari Aalto726f6381996-08-26 18:22:31 +0000211 if (legal_identifier (name) == 0)
212 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000213 sh_invalidid (name);
Jari Aaltod166f041997-06-05 14:59:13 +0000214 if (assign)
215 assign_error++;
216 else
217 any_failed++;
Jari Aalto726f6381996-08-26 18:22:31 +0000218 list = list->next;
219 continue;
220 }
221
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000222 if (assign) /* xxx [-np] name=value */
Jari Aalto726f6381996-08-26 18:22:31 +0000223 {
224 name[assign] = '=';
Jari Aalto95732b42005-12-07 14:08:12 +0000225 if (aflags & ASS_APPEND)
226 name[assign - 1] = '+';
Jari Aaltod166f041997-06-05 14:59:13 +0000227#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 Aalto31859422009-01-12 13:36:28 +0000230 if (arrays_only || assoc_only)
Jari Aaltod166f041997-06-05 14:59:13 +0000231 {
232 tlist = list->next;
233 list->next = (WORD_LIST *)NULL;
Jari Aalto31859422009-01-12 13:36:28 +0000234 w = arrays_only ? make_word ("-ra") : make_word ("-rA");
Jari Aaltod166f041997-06-05 14:59:13 +0000235 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 Aalto726f6381996-08-26 18:22:31 +0000245 /* This word has already been expanded once with command
246 and parameter expansion. Call do_assignment_no_expand (),
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000247 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 Aalto726f6381996-08-26 18:22:31 +0000251 name[assign] = '\0';
Jari Aalto95732b42005-12-07 14:08:12 +0000252 if (aflags & ASS_APPEND)
253 name[assign - 1] = '\0';
Jari Aalto726f6381996-08-26 18:22:31 +0000254 }
255
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000256 set_var_attribute (name, attribute, undo);
Jari Aalto726f6381996-08-26 18:22:31 +0000257 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 Aaltoccc6cda1996-12-23 17:02:34 +0000274#if defined (ARRAY_VARS)
275 if (attribute & att_array)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000276 {
277 arrays_only++;
278 if (attribute != att_array)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000279 attribute &= ~att_array;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000280 }
Jari Aalto31859422009-01-12 13:36:28 +0000281 else if (attribute & att_assoc)
282 {
283 assoc_only++;
284 if (attribute != att_assoc)
285 attribute &= ~att_assoc;
286 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000287#endif
288
Jari Aalto726f6381996-08-26 18:22:31 +0000289 if (variable_list)
290 {
291 for (i = 0; var = variable_list[i]; i++)
292 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000293#if defined (ARRAY_VARS)
294 if (arrays_only && array_p (var) == 0)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000295 continue;
Jari Aalto31859422009-01-12 13:36:28 +0000296 else if (assoc_only && assoc_p (var) == 0)
297 continue;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000298#endif
Jari Aaltof73dda02001-11-13 17:56:06 +0000299 if ((var->attributes & attribute))
Jari Aalto31859422009-01-12 13:36:28 +0000300 {
301 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
302 if (any_failed = sh_chkwrite (any_failed))
303 break;
304 }
Jari Aalto726f6381996-08-26 18:22:31 +0000305 }
306 free (variable_list);
307 }
308 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000309
310 return (assign_error ? EX_BADASSIGN
311 : ((any_failed == 0) ? EXECUTION_SUCCESS
312 : EXECUTION_FAILURE));
313}
314
Jari Aalto31859422009-01-12 13:36:28 +0000315/* Show all variable variables (v == 1) or functions (v == 0) with
316 attributes. */
317int
318show_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 Aaltod166f041997-06-05 14:59:13 +0000339/* 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 Aaltoccc6cda1996-12-23 17:02:34 +0000345int
Jari Aaltod166f041997-06-05 14:59:13 +0000346show_var_attributes (var, pattr, nodefs)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000347 SHELL_VAR *var;
Jari Aaltod166f041997-06-05 14:59:13 +0000348 int pattr, nodefs;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000349{
Jari Aalto31859422009-01-12 13:36:28 +0000350 char flags[16], *x;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000351 int i;
352
353 i = 0;
354
Jari Aaltod166f041997-06-05 14:59:13 +0000355 /* pattr == 0 means we are called from `declare'. */
356 if (pattr == 0 || posixly_correct == 0)
357 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000358#if defined (ARRAY_VARS)
Jari Aaltod166f041997-06-05 14:59:13 +0000359 if (array_p (var))
360 flags[i++] = 'a';
Jari Aalto31859422009-01-12 13:36:28 +0000361
362 if (assoc_p (var))
363 flags[i++] = 'A';
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000364#endif
365
Jari Aaltod166f041997-06-05 14:59:13 +0000366 if (function_p (var))
Jari Aalto28ef6c32001-04-06 19:14:31 +0000367 flags[i++] = 'f';
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000368
Jari Aaltod166f041997-06-05 14:59:13 +0000369 if (integer_p (var))
Jari Aalto28ef6c32001-04-06 19:14:31 +0000370 flags[i++] = 'i';
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000371
Chet Rameyac50fba2014-02-26 09:36:43 -0500372 if (nameref_p (var))
373 flags[i++] = 'n';
374
Jari Aaltod166f041997-06-05 14:59:13 +0000375 if (readonly_p (var))
Jari Aalto28ef6c32001-04-06 19:14:31 +0000376 flags[i++] = 'r';
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000377
Jari Aalto7117c2d2002-07-17 14:10:11 +0000378 if (trace_p (var))
379 flags[i++] = 't';
380
Jari Aaltod166f041997-06-05 14:59:13 +0000381 if (exported_p (var))
Jari Aalto28ef6c32001-04-06 19:14:31 +0000382 flags[i++] = 'x';
Jari Aalto31859422009-01-12 13:36:28 +0000383
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 Aaltod166f041997-06-05 14:59:13 +0000392 }
393 else
394 {
395#if defined (ARRAY_VARS)
396 if (array_p (var))
397 flags[i++] = 'a';
Jari Aalto31859422009-01-12 13:36:28 +0000398
399 if (assoc_p (var))
400 flags[i++] = 'A';
Jari Aaltod166f041997-06-05 14:59:13 +0000401#endif
402
403 if (function_p (var))
Jari Aalto28ef6c32001-04-06 19:14:31 +0000404 flags[i++] = 'f';
Jari Aaltod166f041997-06-05 14:59:13 +0000405 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000406
407 flags[i] = '\0';
408
Jari Aalto7117c2d2002-07-17 14:10:11 +0000409 /* 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 Aalto31859422009-01-12 13:36:28 +0000414 printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
Jari Aalto7117c2d2002-07-17 14:10:11 +0000415 nodefs++;
416 if (pattr == 0 && i == 1 && flags[0] == 'f')
417 return 0; /* don't print `declare -f name' */
418 }
419
Jari Aaltod166f041997-06-05 14:59:13 +0000420 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 Aaltoccc6cda1996-12-23 17:02:34 +0000426
427#if defined (ARRAY_VARS)
Jari Aalto31859422009-01-12 13:36:28 +0000428 if (array_p (var))
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000429 print_array_assignment (var, 1);
Jari Aalto31859422009-01-12 13:36:28 +0000430 else if (assoc_p (var))
431 print_assoc_assignment (var, 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000432 else
433#endif
Jari Aalto7117c2d2002-07-17 14:10:11 +0000434 /* force `readonly' and `export' to not print out function definitions
Jari Aaltod166f041997-06-05 14:59:13 +0000435 when in POSIX mode. */
436 if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000437 printf ("%s\n", var->name);
438 else if (function_p (var))
Jari Aalto31859422009-01-12 13:36:28 +0000439 printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
Chet Ramey495aee42011-11-22 19:11:26 -0500440 else if (invisible_p (var) || var_isset (var) == 0)
Jari Aaltof73dda02001-11-13 17:56:06 +0000441 printf ("%s\n", var->name);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000442 else
443 {
Chet Ramey495aee42011-11-22 19:11:26 -0500444 x = sh_double_quote (value_cell (var));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000445 printf ("%s=%s\n", var->name, x);
446 free (x);
447 }
448 return (0);
449}
450
451int
452show_name_attributes (name, nodefs)
453 char *name;
454 int nodefs;
455{
456 SHELL_VAR *var;
457
Chet Rameyac50fba2014-02-26 09:36:43 -0500458#if 0
459 var = find_variable_tempenv (name);
460#else
461 var = find_variable_noref (name);
462#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000463
464 if (var && invisible_p (var) == 0)
465 {
Jari Aaltod166f041997-06-05 14:59:13 +0000466 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000467 return (0);
468 }
469 else
470 return (1);
471}
472
Chet Rameyac50fba2014-02-26 09:36:43 -0500473int
474show_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 Aaltoccc6cda1996-12-23 17:02:34 +0000491void
492set_var_attribute (name, attribute, undo)
493 char *name;
494 int attribute, undo;
495{
Chet Rameyac50fba2014-02-26 09:36:43 -0500496 SHELL_VAR *var, *tv, *v;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000497 char *tvalue;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000498
499 if (undo)
500 var = find_variable (name);
501 else
502 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000503 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 Aaltoccc6cda1996-12-23 17:02:34 +0000508 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000509 tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring ("");
510
Jari Aalto95732b42005-12-07 14:08:12 +0000511 var = bind_variable (tv->name, tvalue, 0);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000512 var->attributes |= tv->attributes & ~att_tempvar;
Chet Rameyac50fba2014-02-26 09:36:43 -0500513 /* 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 Aalto7117c2d2002-07-17 14:10:11 +0000525 if (var->context != 0)
526 VSETATTR (var, att_propagate);
527 SETVARATTR (tv, attribute, undo); /* XXX */
528
Jari Aalto95732b42005-12-07 14:08:12 +0000529 stupidly_hack_special_variables (tv->name);
530
Jari Aalto7117c2d2002-07-17 14:10:11 +0000531 free (tvalue);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000532 }
533 else
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000534 {
Chet Rameyac50fba2014-02-26 09:36:43 -0500535 var = find_variable_notempenv (name);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000536 if (var == 0)
537 {
Jari Aalto95732b42005-12-07 14:08:12 +0000538 var = bind_variable (name, (char *)NULL, 0);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000539 VSETATTR (var, att_invisible);
540 }
541 else if (var->context != 0)
542 VSETATTR (var, att_propagate);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000543 }
544 }
545
546 if (var)
547 SETVARATTR (var, attribute, undo);
548
Jari Aaltobb706242000-03-17 21:46:59 +0000549 if (var && (exported_p (var) || (attribute & att_exported)))
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000550 array_needs_making++; /* XXX */
Jari Aalto726f6381996-08-26 18:22:31 +0000551}