]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/setattr.def
bash-4.3-beta overlay
[thirdparty/bash.git] / builtins / setattr.def
CommitLineData
726f6388
JA
1This file is setattr.def, from which is created setattr.c.
2It implements the builtins "export" and "readonly", in Bash.
3
d42cb8c1 4Copyright (C) 1987-2012 Free Software Foundation, Inc.
726f6388
JA
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
2e4498b3
CR
8Bash 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.
12
13Bash 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.
17
18You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
726f6388
JA
20
21$PRODUCES setattr.c
22
ccc6cda3
JA
23#include <config.h>
24
25#if defined (HAVE_UNISTD_H)
cce855bc
JA
26# ifdef _MINIX
27# include <sys/types.h>
28# endif
ccc6cda3
JA
29# include <unistd.h>
30#endif
31
32#include <stdio.h>
33#include "../bashansi.h"
5e13499c 34#include "../bashintl.h"
ccc6cda3 35
726f6388
JA
36#include "../shell.h"
37#include "common.h"
38#include "bashgetopt.h"
39
d166f048 40extern int posixly_correct;
726f6388
JA
41extern int array_needs_making;
42extern char *this_command_name;
f73dda09 43extern sh_builtin_func_t *this_shell_builtin;
d166f048
JA
44
45#ifdef ARRAY_VARS
7117c2d2 46extern int declare_builtin __P((WORD_LIST *));
d166f048
JA
47#endif
48
49#define READONLY_OR_EXPORT \
50 (this_shell_builtin == readonly_builtin || this_shell_builtin == export_builtin)
726f6388
JA
51
52$BUILTIN export
53$FUNCTION export_builtin
d3ad40de 54$SHORT_DOC export [-fn] [name[=value] ...] or export -p
6a8fd0ed
CR
55Set export attribute for shell variables.
56
9cbcc93b
CR
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.
6a8fd0ed
CR
66
67Exit Status:
68Returns success unless an invalid option is given or NAME is invalid.
726f6388
JA
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. */
ccc6cda3 76int
726f6388
JA
77export_builtin (list)
78 register WORD_LIST *list;
79{
ccc6cda3 80 return (set_or_show_attributes (list, att_exported, 0));
726f6388
JA
81}
82
83$BUILTIN readonly
84$FUNCTION readonly_builtin
54a1fa7c 85$SHORT_DOC readonly [-aAf] [name[=value] ...] or readonly -p
6a8fd0ed
CR
86Mark shell variables as unchangeable.
87
9cbcc93b
CR
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:
fdf670ea
CR
93 -a refer to indexed array variables
94 -A refer to associative array variables
9cbcc93b 95 -f refer to shell functions
c677e9e0
CR
96 -p display a list of all readonly variables or functions, depending on
97 whether or not the -f option is given
9cbcc93b
CR
98
99An argument of `--' disables further option processing.
6a8fd0ed
CR
100
101Exit Status:
102Returns success unless an invalid option is given or NAME is invalid.
726f6388
JA
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. */
ccc6cda3 107int
726f6388
JA
108readonly_builtin (list)
109 register WORD_LIST *list;
110{
ccc6cda3 111 return (set_or_show_attributes (list, att_readonly, 0));
726f6388
JA
112}
113
7117c2d2 114#if defined (ARRAY_VARS)
fdf670ea 115# define ATTROPTS "aAfnp"
7117c2d2
JA
116#else
117# define ATTROPTS "fnp"
118#endif
119
726f6388
JA
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
d3a24ed2 122 remaining names in LIST (doesn't work for readonly). */
726f6388 123int
ccc6cda3 124set_or_show_attributes (list, attribute, nodefs)
726f6388 125 register WORD_LIST *list;
ccc6cda3 126 int attribute, nodefs;
726f6388
JA
127{
128 register SHELL_VAR *var;
fdf670ea
CR
129 int assign, undo, any_failed, assign_error, opt;
130 int functions_only, arrays_only, assoc_only;
d11b8b46 131 int aflags;
ccc6cda3 132 char *name;
d166f048
JA
133#if defined (ARRAY_VARS)
134 WORD_LIST *nlist, *tlist;
135 WORD_DESC *w;
136#endif
726f6388 137
fdf670ea
CR
138 functions_only = arrays_only = assoc_only = 0;
139 undo = any_failed = assign_error = 0;
726f6388
JA
140 /* Read arguments from the front of the list. */
141 reset_internal_getopt ();
7117c2d2 142 while ((opt = internal_getopt (list, ATTROPTS)) != -1)
726f6388
JA
143 {
144 switch (opt)
145 {
146 case 'n':
147 undo = 1;
148 break;
149 case 'f':
150 functions_only = 1;
151 break;
ccc6cda3
JA
152#if defined (ARRAY_VARS)
153 case 'a':
fdf670ea
CR
154 arrays_only = 1;
155 break;
156 case 'A':
157 assoc_only = 1;
158 break;
ccc6cda3 159#endif
726f6388
JA
160 case 'p':
161 break;
162 default:
ccc6cda3 163 builtin_usage ();
726f6388
JA
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
ccc6cda3 174 /* Cannot undo readonly status, silently disallowed. */
726f6388
JA
175 if (undo && (attribute & att_readonly))
176 attribute &= ~att_readonly;
177
178 while (list)
179 {
ccc6cda3 180 name = list->word->word;
726f6388 181
ccc6cda3 182 if (functions_only) /* xxx -f name */
726f6388
JA
183 {
184 var = find_function (name);
ccc6cda3 185 if (var == 0)
726f6388 186 {
5e13499c 187 builtin_error (_("%s: not a function"), name);
726f6388
JA
188 any_failed++;
189 }
190 else
ccc6cda3
JA
191 SETVARATTR (var, attribute, undo);
192
726f6388 193 list = list->next;
726f6388
JA
194 continue;
195 }
196
ccc6cda3 197 /* xxx [-np] name[=value] */
5e13499c 198 assign = assignment (name, 0);
726f6388 199
d11b8b46 200 aflags = 0;
28ef6c31 201 if (assign)
d11b8b46
CR
202 {
203 name[assign] = '\0';
204 if (name[assign - 1] == '+')
205 {
206 aflags |= ASS_APPEND;
207 name[assign - 1] = '\0';
208 }
209 }
ccc6cda3 210
726f6388
JA
211 if (legal_identifier (name) == 0)
212 {
7117c2d2 213 sh_invalidid (name);
d166f048
JA
214 if (assign)
215 assign_error++;
216 else
217 any_failed++;
726f6388
JA
218 list = list->next;
219 continue;
220 }
221
ccc6cda3 222 if (assign) /* xxx [-np] name=value */
726f6388
JA
223 {
224 name[assign] = '=';
d11b8b46
CR
225 if (aflags & ASS_APPEND)
226 name[assign - 1] = '+';
d166f048
JA
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. */
fdf670ea 230 if (arrays_only || assoc_only)
d166f048
JA
231 {
232 tlist = list->next;
233 list->next = (WORD_LIST *)NULL;
fdf670ea 234 w = arrays_only ? make_word ("-ra") : make_word ("-rA");
d166f048
JA
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
726f6388
JA
245 /* This word has already been expanded once with command
246 and parameter expansion. Call do_assignment_no_expand (),
ccc6cda3
JA
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++;
726f6388 251 name[assign] = '\0';
d11b8b46
CR
252 if (aflags & ASS_APPEND)
253 name[assign - 1] = '\0';
726f6388
JA
254 }
255
ccc6cda3 256 set_var_attribute (name, attribute, undo);
726f6388
JA
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
ccc6cda3
JA
274#if defined (ARRAY_VARS)
275 if (attribute & att_array)
28ef6c31
JA
276 {
277 arrays_only++;
278 if (attribute != att_array)
ccc6cda3 279 attribute &= ~att_array;
28ef6c31 280 }
fdf670ea
CR
281 else if (attribute & att_assoc)
282 {
283 assoc_only++;
284 if (attribute != att_assoc)
285 attribute &= ~att_assoc;
286 }
ccc6cda3
JA
287#endif
288
726f6388
JA
289 if (variable_list)
290 {
291 for (i = 0; var = variable_list[i]; i++)
292 {
ccc6cda3
JA
293#if defined (ARRAY_VARS)
294 if (arrays_only && array_p (var) == 0)
28ef6c31 295 continue;
fdf670ea
CR
296 else if (assoc_only && assoc_p (var) == 0)
297 continue;
ccc6cda3 298#endif
f73dda09 299 if ((var->attributes & attribute))
641d8f00
CR
300 {
301 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
302 if (any_failed = sh_chkwrite (any_failed))
303 break;
304 }
ccc6cda3
JA
305 }
306 free (variable_list);
307 }
308 }
309
310 return (assign_error ? EX_BADASSIGN
311 : ((any_failed == 0) ? EXECUTION_SUCCESS
312 : EXECUTION_FAILURE));
313}
314
6fbe7620
CR
315/* 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
d166f048
JA
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'. */
ccc6cda3 345int
d166f048 346show_var_attributes (var, pattr, nodefs)
ccc6cda3 347 SHELL_VAR *var;
d166f048 348 int pattr, nodefs;
ccc6cda3 349{
6a8fd0ed 350 char flags[16], *x;
ccc6cda3 351 int i;
726f6388 352
ccc6cda3 353 i = 0;
726f6388 354
d166f048
JA
355 /* pattr == 0 means we are called from `declare'. */
356 if (pattr == 0 || posixly_correct == 0)
357 {
ccc6cda3 358#if defined (ARRAY_VARS)
d166f048
JA
359 if (array_p (var))
360 flags[i++] = 'a';
fdf670ea
CR
361
362 if (assoc_p (var))
363 flags[i++] = 'A';
ccc6cda3 364#endif
726f6388 365
d166f048 366 if (function_p (var))
28ef6c31 367 flags[i++] = 'f';
726f6388 368
d166f048 369 if (integer_p (var))
28ef6c31 370 flags[i++] = 'i';
726f6388 371
d42cb8c1
CR
372 if (nameref_p (var))
373 flags[i++] = 'n';
374
d166f048 375 if (readonly_p (var))
28ef6c31 376 flags[i++] = 'r';
726f6388 377
7117c2d2
JA
378 if (trace_p (var))
379 flags[i++] = 't';
380
d166f048 381 if (exported_p (var))
28ef6c31 382 flags[i++] = 'x';
09767ff0
CR
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';
d166f048
JA
392 }
393 else
394 {
395#if defined (ARRAY_VARS)
396 if (array_p (var))
397 flags[i++] = 'a';
fdf670ea
CR
398
399 if (assoc_p (var))
400 flags[i++] = 'A';
d166f048
JA
401#endif
402
403 if (function_p (var))
28ef6c31 404 flags[i++] = 'f';
d166f048 405 }
726f6388 406
ccc6cda3 407 flags[i] = '\0';
726f6388 408
7117c2d2
JA
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 {
b0c16657 414 printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
7117c2d2
JA
415 nodefs++;
416 if (pattr == 0 && i == 1 && flags[0] == 'f')
417 return 0; /* don't print `declare -f name' */
418 }
419
d166f048
JA
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);
ccc6cda3
JA
426
427#if defined (ARRAY_VARS)
fdf670ea 428 if (array_p (var))
ccc6cda3 429 print_array_assignment (var, 1);
fdf670ea
CR
430 else if (assoc_p (var))
431 print_assoc_assignment (var, 1);
ccc6cda3
JA
432 else
433#endif
7117c2d2 434 /* force `readonly' and `export' to not print out function definitions
d166f048
JA
435 when in POSIX mode. */
436 if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
ccc6cda3
JA
437 printf ("%s\n", var->name);
438 else if (function_p (var))
b0c16657 439 printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
68dfe178 440 else if (invisible_p (var) || var_isset (var) == 0)
f73dda09 441 printf ("%s\n", var->name);
ccc6cda3
JA
442 else
443 {
68dfe178 444 x = sh_double_quote (value_cell (var));
ccc6cda3
JA
445 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
348a457e 458 var = find_variable_tempenv (name);
ccc6cda3
JA
459
460 if (var && invisible_p (var) == 0)
461 {
d166f048 462 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
ccc6cda3
JA
463 return (0);
464 }
465 else
466 return (1);
467}
468
1442f67c
CR
469int
470show_func_attributes (name, nodefs)
471 char *name;
472 int nodefs;
473{
474 SHELL_VAR *var;
475
476 var = find_function (name);
477
478 if (var)
479 {
480 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
481 return (0);
482 }
483 else
484 return (1);
485}
486
ccc6cda3
JA
487void
488set_var_attribute (name, attribute, undo)
489 char *name;
490 int attribute, undo;
491{
208fdb50 492 SHELL_VAR *var, *tv, *v;
7117c2d2 493 char *tvalue;
ccc6cda3
JA
494
495 if (undo)
496 var = find_variable (name);
497 else
498 {
7117c2d2
JA
499 tv = find_tempenv_variable (name);
500 /* XXX -- need to handle case where tv is a temp variable in a
501 function-scope context, since function_env has been merged into
502 the local variables table. */
503 if (tv && tempvar_p (tv))
ccc6cda3 504 {
7117c2d2
JA
505 tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring ("");
506
d11b8b46 507 var = bind_variable (tv->name, tvalue, 0);
7117c2d2 508 var->attributes |= tv->attributes & ~att_tempvar;
208fdb50
CR
509 /* This avoids an error message when propagating a read-only var
510 later on. */
511 if (var->context == 0 && (attribute & att_readonly))
512 {
513 /* Don't bother to set the `propagate to the global variables
514 table' flag if we've just bound the variable in that table */
515 v = find_global_variable (tv->name);
516 if (v != var)
517 VSETATTR (tv, att_propagate);
518 }
519 else
520 VSETATTR (tv, att_propagate);
7117c2d2
JA
521 if (var->context != 0)
522 VSETATTR (var, att_propagate);
523 SETVARATTR (tv, attribute, undo); /* XXX */
524
055a1bf5
CR
525 stupidly_hack_special_variables (tv->name);
526
7117c2d2 527 free (tvalue);
ccc6cda3
JA
528 }
529 else
ccc6cda3 530 {
348a457e 531 var = find_variable_notempenv (name);
7117c2d2
JA
532 if (var == 0)
533 {
d11b8b46 534 var = bind_variable (name, (char *)NULL, 0);
7117c2d2
JA
535 VSETATTR (var, att_invisible);
536 }
537 else if (var->context != 0)
538 VSETATTR (var, att_propagate);
726f6388
JA
539 }
540 }
ccc6cda3
JA
541
542 if (var)
543 SETVARATTR (var, attribute, undo);
544
bb70624e 545 if (var && (exported_p (var) || (attribute & att_exported)))
ccc6cda3 546 array_needs_making++; /* XXX */
726f6388 547}