]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/setattr.def
Imported from ../bash-3.0.16.tar.gz.
[thirdparty/bash.git] / builtins / setattr.def
1 This file is setattr.def, from which is created setattr.c.
2 It implements the builtins "export" and "readonly", in Bash.
3
4 Copyright (C) 1987-2003 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
21
22 $PRODUCES setattr.c
23
24 #include <config.h>
25
26 #if defined (HAVE_UNISTD_H)
27 # ifdef _MINIX
28 # include <sys/types.h>
29 # endif
30 # include <unistd.h>
31 #endif
32
33 #include <stdio.h>
34 #include "../bashansi.h"
35 #include "../bashintl.h"
36
37 #include "../shell.h"
38 #include "common.h"
39 #include "bashgetopt.h"
40
41 extern int posixly_correct;
42 extern int array_needs_making;
43 extern char *this_command_name;
44 extern sh_builtin_func_t *this_shell_builtin;
45
46 #ifdef ARRAY_VARS
47 extern int declare_builtin __P((WORD_LIST *));
48 #endif
49
50 #define READONLY_OR_EXPORT \
51 (this_shell_builtin == readonly_builtin || this_shell_builtin == export_builtin)
52
53 $BUILTIN export
54 $FUNCTION export_builtin
55 $SHORT_DOC export [-nf] [name[=value] ...] or export -p
56 NAMEs are marked for automatic export to the environment of
57 subsequently executed commands. If the -f option is given,
58 the NAMEs refer to functions. If no NAMEs are given, or if `-p'
59 is given, a list of all names that are exported in this shell is
60 printed. An argument of `-n' says to remove the export property
61 from subsequent NAMEs. An argument of `--' disables further option
62 processing.
63 $END
64
65 /* For each variable name in LIST, make that variable appear in the
66 environment passed to simple commands. If there is no LIST, then
67 print all such variables. An argument of `-n' says to remove the
68 exported attribute from variables named in LIST. An argument of
69 -f indicates that the names present in LIST refer to functions. */
70 int
71 export_builtin (list)
72 register WORD_LIST *list;
73 {
74 return (set_or_show_attributes (list, att_exported, 0));
75 }
76
77 $BUILTIN readonly
78 $FUNCTION readonly_builtin
79 $SHORT_DOC readonly [-af] [name[=value] ...] or readonly -p
80 The given NAMEs are marked readonly and the values of these NAMEs may
81 not be changed by subsequent assignment. If the -f option is given,
82 then functions corresponding to the NAMEs are so marked. If no
83 arguments are given, or if `-p' is given, a list of all readonly names
84 is printed. The `-a' option means to treat each NAME as
85 an array variable. An argument of `--' disables further option
86 processing.
87 $END
88
89 /* For each variable name in LIST, make that variable readonly. Given an
90 empty LIST, print out all existing readonly variables. */
91 int
92 readonly_builtin (list)
93 register WORD_LIST *list;
94 {
95 return (set_or_show_attributes (list, att_readonly, 0));
96 }
97
98 #if defined (ARRAY_VARS)
99 # define ATTROPTS "afnp"
100 #else
101 # define ATTROPTS "fnp"
102 #endif
103
104 /* For each variable name in LIST, make that variable have the specified
105 ATTRIBUTE. An arg of `-n' says to remove the attribute from the the
106 remaining names in LIST (doesn't work for readonly). */
107 int
108 set_or_show_attributes (list, attribute, nodefs)
109 register WORD_LIST *list;
110 int attribute, nodefs;
111 {
112 register SHELL_VAR *var;
113 int assign, undo, functions_only, arrays_only, any_failed, assign_error, opt;
114 char *name;
115 #if defined (ARRAY_VARS)
116 WORD_LIST *nlist, *tlist;
117 WORD_DESC *w;
118 #endif
119
120 undo = functions_only = arrays_only = any_failed = assign_error = 0;
121 /* Read arguments from the front of the list. */
122 reset_internal_getopt ();
123 while ((opt = internal_getopt (list, ATTROPTS)) != -1)
124 {
125 switch (opt)
126 {
127 case 'n':
128 undo = 1;
129 break;
130 case 'f':
131 functions_only = 1;
132 break;
133 #if defined (ARRAY_VARS)
134 case 'a':
135 arrays_only = 1;
136 break;
137 #endif
138 case 'p':
139 break;
140 default:
141 builtin_usage ();
142 return (EX_USAGE);
143 }
144 }
145 list = loptend;
146
147 if (list)
148 {
149 if (attribute & att_exported)
150 array_needs_making = 1;
151
152 /* Cannot undo readonly status, silently disallowed. */
153 if (undo && (attribute & att_readonly))
154 attribute &= ~att_readonly;
155
156 while (list)
157 {
158 name = list->word->word;
159
160 if (functions_only) /* xxx -f name */
161 {
162 var = find_function (name);
163 if (var == 0)
164 {
165 builtin_error (_("%s: not a function"), name);
166 any_failed++;
167 }
168 else
169 SETVARATTR (var, attribute, undo);
170
171 list = list->next;
172 continue;
173 }
174
175 /* xxx [-np] name[=value] */
176 assign = assignment (name, 0);
177
178 if (assign)
179 name[assign] = '\0';
180
181 if (legal_identifier (name) == 0)
182 {
183 sh_invalidid (name);
184 if (assign)
185 assign_error++;
186 else
187 any_failed++;
188 list = list->next;
189 continue;
190 }
191
192 if (assign) /* xxx [-np] name=value */
193 {
194 name[assign] = '=';
195 #if defined (ARRAY_VARS)
196 /* Let's try something here. Turn readonly -a xxx=yyy into
197 declare -ra xxx=yyy and see what that gets us. */
198 if (arrays_only)
199 {
200 tlist = list->next;
201 list->next = (WORD_LIST *)NULL;
202 w = make_word ("-ra");
203 nlist = make_word_list (w, list);
204 opt = declare_builtin (nlist);
205 if (opt != EXECUTION_SUCCESS)
206 assign_error++;
207 list->next = tlist;
208 dispose_word (w);
209 free (nlist);
210 }
211 else
212 #endif
213 /* This word has already been expanded once with command
214 and parameter expansion. Call do_assignment_no_expand (),
215 which does not do command or parameter substitution. If
216 the assignment is not performed correctly, flag an error. */
217 if (do_assignment_no_expand (name) == 0)
218 assign_error++;
219 name[assign] = '\0';
220 }
221
222 set_var_attribute (name, attribute, undo);
223 list = list->next;
224 }
225 }
226 else
227 {
228 SHELL_VAR **variable_list;
229 register int i;
230
231 if ((attribute & att_function) || functions_only)
232 {
233 variable_list = all_shell_functions ();
234 if (attribute != att_function)
235 attribute &= ~att_function; /* so declare -xf works, for example */
236 }
237 else
238 variable_list = all_shell_variables ();
239
240 #if defined (ARRAY_VARS)
241 if (attribute & att_array)
242 {
243 arrays_only++;
244 if (attribute != att_array)
245 attribute &= ~att_array;
246 }
247 #endif
248
249 if (variable_list)
250 {
251 for (i = 0; var = variable_list[i]; i++)
252 {
253 #if defined (ARRAY_VARS)
254 if (arrays_only && array_p (var) == 0)
255 continue;
256 #endif
257 if ((var->attributes & attribute))
258 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
259 }
260 free (variable_list);
261 }
262 }
263
264 return (assign_error ? EX_BADASSIGN
265 : ((any_failed == 0) ? EXECUTION_SUCCESS
266 : EXECUTION_FAILURE));
267 }
268
269 /* Show the attributes for shell variable VAR. If NODEFS is non-zero,
270 don't show function definitions along with the name. If PATTR is
271 non-zero, it indicates we're being called from `export' or `readonly'.
272 In POSIX mode, this prints the name of the calling builtin (`export'
273 or `readonly') instead of `declare', and doesn't print function defs
274 when called by `export' or `readonly'. */
275 int
276 show_var_attributes (var, pattr, nodefs)
277 SHELL_VAR *var;
278 int pattr, nodefs;
279 {
280 char flags[8], *x;
281 int i;
282
283 i = 0;
284
285 /* pattr == 0 means we are called from `declare'. */
286 if (pattr == 0 || posixly_correct == 0)
287 {
288 #if defined (ARRAY_VARS)
289 if (array_p (var))
290 flags[i++] = 'a';
291 #endif
292
293 if (function_p (var))
294 flags[i++] = 'f';
295
296 if (integer_p (var))
297 flags[i++] = 'i';
298
299 if (readonly_p (var))
300 flags[i++] = 'r';
301
302 if (trace_p (var))
303 flags[i++] = 't';
304
305 if (exported_p (var))
306 flags[i++] = 'x';
307 }
308 else
309 {
310 #if defined (ARRAY_VARS)
311 if (array_p (var))
312 flags[i++] = 'a';
313 #endif
314
315 if (function_p (var))
316 flags[i++] = 'f';
317 }
318
319 flags[i] = '\0';
320
321 /* If we're printing functions with definitions, print the function def
322 first, then the attributes, instead of printing output that can't be
323 reused as input to recreate the current state. */
324 if (function_p (var) && nodefs == 0 && (pattr == 0 || posixly_correct == 0))
325 {
326 printf ("%s\n", named_function_string (var->name, function_cell (var), 1));
327 nodefs++;
328 if (pattr == 0 && i == 1 && flags[0] == 'f')
329 return 0; /* don't print `declare -f name' */
330 }
331
332 if (pattr == 0 || posixly_correct == 0)
333 printf ("declare -%s ", i ? flags : "-");
334 else if (i)
335 printf ("%s -%s ", this_command_name, flags);
336 else
337 printf ("%s ", this_command_name);
338
339 #if defined (ARRAY_VARS)
340 if (array_p (var))
341 print_array_assignment (var, 1);
342 else
343 #endif
344 /* force `readonly' and `export' to not print out function definitions
345 when in POSIX mode. */
346 if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
347 printf ("%s\n", var->name);
348 else if (function_p (var))
349 printf ("%s\n", named_function_string (var->name, function_cell (var), 1));
350 else if (invisible_p (var))
351 printf ("%s\n", var->name);
352 else
353 {
354 x = sh_double_quote (var_isset (var) ? value_cell (var) : "");
355 printf ("%s=%s\n", var->name, x);
356 free (x);
357 }
358 return (0);
359 }
360
361 int
362 show_name_attributes (name, nodefs)
363 char *name;
364 int nodefs;
365 {
366 SHELL_VAR *var;
367
368 var = find_variable_internal (name, 1);
369
370 if (var && invisible_p (var) == 0)
371 {
372 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
373 return (0);
374 }
375 else
376 return (1);
377 }
378
379 void
380 set_var_attribute (name, attribute, undo)
381 char *name;
382 int attribute, undo;
383 {
384 SHELL_VAR *var, *tv;
385 char *tvalue;
386
387 if (undo)
388 var = find_variable (name);
389 else
390 {
391 tv = find_tempenv_variable (name);
392 /* XXX -- need to handle case where tv is a temp variable in a
393 function-scope context, since function_env has been merged into
394 the local variables table. */
395 if (tv && tempvar_p (tv))
396 {
397 tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring ("");
398
399 var = bind_variable (tv->name, tvalue);
400 var->attributes |= tv->attributes & ~att_tempvar;
401 VSETATTR (tv, att_propagate);
402 if (var->context != 0)
403 VSETATTR (var, att_propagate);
404 SETVARATTR (tv, attribute, undo); /* XXX */
405
406 free (tvalue);
407 }
408 else
409 {
410 var = find_variable_internal (name, 0);
411 if (var == 0)
412 {
413 var = bind_variable (name, (char *)NULL);
414 VSETATTR (var, att_invisible);
415 }
416 else if (var->context != 0)
417 VSETATTR (var, att_propagate);
418 }
419 }
420
421 if (var)
422 SETVARATTR (var, attribute, undo);
423
424 if (var && (exported_p (var) || (attribute & att_exported)))
425 array_needs_making++; /* XXX */
426 }