]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/setattr.def
Bash-4.2 distribution sources and documentation
[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
495aee44 4Copyright (C) 1987-2010 Free Software Foundation, Inc.
726f6388
JA
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
3185942a
JA
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.
726f6388 12
3185942a
JA
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.
726f6388 17
3185942a
JA
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"
b80f6443 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
3185942a
JA
54$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.
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
495aee44 85$SHORT_DOC readonly [-aAf] [name[=value] ...] or readonly -p
3185942a
JA
86Mark 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
96 -p display a list of all readonly variables and functions
97
98An argument of `--' disables further option processing.
99
100Exit Status:
101Returns success unless an invalid option is given or NAME is invalid.
726f6388
JA
102$END
103
104/* For each variable name in LIST, make that variable readonly. Given an
105 empty LIST, print out all existing readonly variables. */
ccc6cda3 106int
726f6388
JA
107readonly_builtin (list)
108 register WORD_LIST *list;
109{
ccc6cda3 110 return (set_or_show_attributes (list, att_readonly, 0));
726f6388
JA
111}
112
7117c2d2 113#if defined (ARRAY_VARS)
3185942a 114# define ATTROPTS "aAfnp"
7117c2d2
JA
115#else
116# define ATTROPTS "fnp"
117#endif
118
726f6388
JA
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
b80f6443 121 remaining names in LIST (doesn't work for readonly). */
726f6388 122int
ccc6cda3 123set_or_show_attributes (list, attribute, nodefs)
726f6388 124 register WORD_LIST *list;
ccc6cda3 125 int attribute, nodefs;
726f6388
JA
126{
127 register SHELL_VAR *var;
3185942a
JA
128 int assign, undo, any_failed, assign_error, opt;
129 int functions_only, arrays_only, assoc_only;
95732b49 130 int aflags;
ccc6cda3 131 char *name;
d166f048
JA
132#if defined (ARRAY_VARS)
133 WORD_LIST *nlist, *tlist;
134 WORD_DESC *w;
135#endif
726f6388 136
3185942a
JA
137 functions_only = arrays_only = assoc_only = 0;
138 undo = any_failed = assign_error = 0;
726f6388
JA
139 /* Read arguments from the front of the list. */
140 reset_internal_getopt ();
7117c2d2 141 while ((opt = internal_getopt (list, ATTROPTS)) != -1)
726f6388
JA
142 {
143 switch (opt)
144 {
145 case 'n':
146 undo = 1;
147 break;
148 case 'f':
149 functions_only = 1;
150 break;
ccc6cda3
JA
151#if defined (ARRAY_VARS)
152 case 'a':
3185942a
JA
153 arrays_only = 1;
154 break;
155 case 'A':
156 assoc_only = 1;
157 break;
ccc6cda3 158#endif
726f6388
JA
159 case 'p':
160 break;
161 default:
ccc6cda3 162 builtin_usage ();
726f6388
JA
163 return (EX_USAGE);
164 }
165 }
166 list = loptend;
167
168 if (list)
169 {
170 if (attribute & att_exported)
171 array_needs_making = 1;
172
ccc6cda3 173 /* Cannot undo readonly status, silently disallowed. */
726f6388
JA
174 if (undo && (attribute & att_readonly))
175 attribute &= ~att_readonly;
176
177 while (list)
178 {
ccc6cda3 179 name = list->word->word;
726f6388 180
ccc6cda3 181 if (functions_only) /* xxx -f name */
726f6388
JA
182 {
183 var = find_function (name);
ccc6cda3 184 if (var == 0)
726f6388 185 {
b80f6443 186 builtin_error (_("%s: not a function"), name);
726f6388
JA
187 any_failed++;
188 }
189 else
ccc6cda3
JA
190 SETVARATTR (var, attribute, undo);
191
726f6388 192 list = list->next;
726f6388
JA
193 continue;
194 }
195
ccc6cda3 196 /* xxx [-np] name[=value] */
b80f6443 197 assign = assignment (name, 0);
726f6388 198
95732b49 199 aflags = 0;
28ef6c31 200 if (assign)
95732b49
JA
201 {
202 name[assign] = '\0';
203 if (name[assign - 1] == '+')
204 {
205 aflags |= ASS_APPEND;
206 name[assign - 1] = '\0';
207 }
208 }
ccc6cda3 209
726f6388
JA
210 if (legal_identifier (name) == 0)
211 {
7117c2d2 212 sh_invalidid (name);
d166f048
JA
213 if (assign)
214 assign_error++;
215 else
216 any_failed++;
726f6388
JA
217 list = list->next;
218 continue;
219 }
220
ccc6cda3 221 if (assign) /* xxx [-np] name=value */
726f6388
JA
222 {
223 name[assign] = '=';
95732b49
JA
224 if (aflags & ASS_APPEND)
225 name[assign - 1] = '+';
d166f048
JA
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. */
3185942a 229 if (arrays_only || assoc_only)
d166f048
JA
230 {
231 tlist = list->next;
232 list->next = (WORD_LIST *)NULL;
3185942a 233 w = arrays_only ? make_word ("-ra") : make_word ("-rA");
d166f048
JA
234 nlist = make_word_list (w, list);
235 opt = declare_builtin (nlist);
236 if (opt != EXECUTION_SUCCESS)
237 assign_error++;
238 list->next = tlist;
239 dispose_word (w);
240 free (nlist);
241 }
242 else
243#endif
726f6388
JA
244 /* This word has already been expanded once with command
245 and parameter expansion. Call do_assignment_no_expand (),
ccc6cda3
JA
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)
249 assign_error++;
726f6388 250 name[assign] = '\0';
95732b49
JA
251 if (aflags & ASS_APPEND)
252 name[assign - 1] = '\0';
726f6388
JA
253 }
254
ccc6cda3 255 set_var_attribute (name, attribute, undo);
726f6388
JA
256 list = list->next;
257 }
258 }
259 else
260 {
261 SHELL_VAR **variable_list;
262 register int i;
263
264 if ((attribute & att_function) || functions_only)
265 {
266 variable_list = all_shell_functions ();
267 if (attribute != att_function)
268 attribute &= ~att_function; /* so declare -xf works, for example */
269 }
270 else
271 variable_list = all_shell_variables ();
272
ccc6cda3
JA
273#if defined (ARRAY_VARS)
274 if (attribute & att_array)
28ef6c31
JA
275 {
276 arrays_only++;
277 if (attribute != att_array)
ccc6cda3 278 attribute &= ~att_array;
28ef6c31 279 }
3185942a
JA
280 else if (attribute & att_assoc)
281 {
282 assoc_only++;
283 if (attribute != att_assoc)
284 attribute &= ~att_assoc;
285 }
ccc6cda3
JA
286#endif
287
726f6388
JA
288 if (variable_list)
289 {
290 for (i = 0; var = variable_list[i]; i++)
291 {
ccc6cda3
JA
292#if defined (ARRAY_VARS)
293 if (arrays_only && array_p (var) == 0)
28ef6c31 294 continue;
3185942a
JA
295 else if (assoc_only && assoc_p (var) == 0)
296 continue;
ccc6cda3 297#endif
f73dda09 298 if ((var->attributes & attribute))
3185942a
JA
299 {
300 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
301 if (any_failed = sh_chkwrite (any_failed))
302 break;
303 }
ccc6cda3
JA
304 }
305 free (variable_list);
306 }
307 }
308
309 return (assign_error ? EX_BADASSIGN
310 : ((any_failed == 0) ? EXECUTION_SUCCESS
311 : EXECUTION_FAILURE));
312}
313
3185942a
JA
314/* Show all variable variables (v == 1) or functions (v == 0) with
315 attributes. */
316int
317show_all_var_attributes (v, nodefs)
318 int v, nodefs;
319{
320 SHELL_VAR **variable_list, *var;
321 int any_failed;
322 register int i;
323
324 variable_list = v ? all_shell_variables () : all_shell_functions ();
325 if (variable_list == 0)
326 return (EXECUTION_SUCCESS);
327
328 for (i = any_failed = 0; var = variable_list[i]; i++)
329 {
330 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
331 if (any_failed = sh_chkwrite (any_failed))
332 break;
333 }
334 free (variable_list);
335 return (any_failed == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
336}
337
d166f048
JA
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'. */
ccc6cda3 344int
d166f048 345show_var_attributes (var, pattr, nodefs)
ccc6cda3 346 SHELL_VAR *var;
d166f048 347 int pattr, nodefs;
ccc6cda3 348{
3185942a 349 char flags[16], *x;
ccc6cda3 350 int i;
726f6388 351
ccc6cda3 352 i = 0;
726f6388 353
d166f048
JA
354 /* pattr == 0 means we are called from `declare'. */
355 if (pattr == 0 || posixly_correct == 0)
356 {
ccc6cda3 357#if defined (ARRAY_VARS)
d166f048
JA
358 if (array_p (var))
359 flags[i++] = 'a';
3185942a
JA
360
361 if (assoc_p (var))
362 flags[i++] = 'A';
ccc6cda3 363#endif
726f6388 364
d166f048 365 if (function_p (var))
28ef6c31 366 flags[i++] = 'f';
726f6388 367
d166f048 368 if (integer_p (var))
28ef6c31 369 flags[i++] = 'i';
726f6388 370
d166f048 371 if (readonly_p (var))
28ef6c31 372 flags[i++] = 'r';
726f6388 373
7117c2d2
JA
374 if (trace_p (var))
375 flags[i++] = 't';
376
d166f048 377 if (exported_p (var))
28ef6c31 378 flags[i++] = 'x';
3185942a
JA
379
380 if (capcase_p (var))
381 flags[i++] = 'c';
382
383 if (lowercase_p (var))
384 flags[i++] = 'l';
385
386 if (uppercase_p (var))
387 flags[i++] = 'u';
d166f048
JA
388 }
389 else
390 {
391#if defined (ARRAY_VARS)
392 if (array_p (var))
393 flags[i++] = 'a';
3185942a
JA
394
395 if (assoc_p (var))
396 flags[i++] = 'A';
d166f048
JA
397#endif
398
399 if (function_p (var))
28ef6c31 400 flags[i++] = 'f';
d166f048 401 }
726f6388 402
ccc6cda3 403 flags[i] = '\0';
726f6388 404
7117c2d2
JA
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))
409 {
3185942a 410 printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
7117c2d2
JA
411 nodefs++;
412 if (pattr == 0 && i == 1 && flags[0] == 'f')
413 return 0; /* don't print `declare -f name' */
414 }
415
d166f048
JA
416 if (pattr == 0 || posixly_correct == 0)
417 printf ("declare -%s ", i ? flags : "-");
418 else if (i)
419 printf ("%s -%s ", this_command_name, flags);
420 else
421 printf ("%s ", this_command_name);
ccc6cda3
JA
422
423#if defined (ARRAY_VARS)
3185942a 424 if (array_p (var))
ccc6cda3 425 print_array_assignment (var, 1);
3185942a
JA
426 else if (assoc_p (var))
427 print_assoc_assignment (var, 1);
ccc6cda3
JA
428 else
429#endif
7117c2d2 430 /* force `readonly' and `export' to not print out function definitions
d166f048
JA
431 when in POSIX mode. */
432 if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
ccc6cda3
JA
433 printf ("%s\n", var->name);
434 else if (function_p (var))
3185942a 435 printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
495aee44 436 else if (invisible_p (var) || var_isset (var) == 0)
f73dda09 437 printf ("%s\n", var->name);
ccc6cda3
JA
438 else
439 {
495aee44 440 x = sh_double_quote (value_cell (var));
ccc6cda3
JA
441 printf ("%s=%s\n", var->name, x);
442 free (x);
443 }
444 return (0);
445}
446
447int
448show_name_attributes (name, nodefs)
449 char *name;
450 int nodefs;
451{
452 SHELL_VAR *var;
453
7117c2d2 454 var = find_variable_internal (name, 1);
ccc6cda3
JA
455
456 if (var && invisible_p (var) == 0)
457 {
d166f048 458 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
ccc6cda3
JA
459 return (0);
460 }
461 else
462 return (1);
463}
464
465void
466set_var_attribute (name, attribute, undo)
467 char *name;
468 int attribute, undo;
469{
470 SHELL_VAR *var, *tv;
7117c2d2 471 char *tvalue;
ccc6cda3
JA
472
473 if (undo)
474 var = find_variable (name);
475 else
476 {
7117c2d2
JA
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))
ccc6cda3 482 {
7117c2d2
JA
483 tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring ("");
484
95732b49 485 var = bind_variable (tv->name, tvalue, 0);
7117c2d2
JA
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 */
491
95732b49
JA
492 stupidly_hack_special_variables (tv->name);
493
7117c2d2 494 free (tvalue);
ccc6cda3
JA
495 }
496 else
ccc6cda3 497 {
7117c2d2
JA
498 var = find_variable_internal (name, 0);
499 if (var == 0)
500 {
95732b49 501 var = bind_variable (name, (char *)NULL, 0);
7117c2d2
JA
502 VSETATTR (var, att_invisible);
503 }
504 else if (var->context != 0)
505 VSETATTR (var, att_propagate);
726f6388
JA
506 }
507 }
ccc6cda3
JA
508
509 if (var)
510 SETVARATTR (var, attribute, undo);
511
bb70624e 512 if (var && (exported_p (var) || (attribute & att_exported)))
ccc6cda3 513 array_needs_making++; /* XXX */
726f6388 514}