source: trunk/essentials/app-shells/bash/builtins/setattr.def

Last change on this file was 3228, checked in by bird, 18 years ago

bash 3.1

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