]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/setattr.def
Imported from ../bash-2.05.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, 1989, 1991 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
36 #include "../shell.h"
37 #include "common.h"
38 #include "bashgetopt.h"
39
40 extern int posixly_correct;
41 extern int array_needs_making;
42 extern char *this_command_name;
43 extern Function *this_shell_builtin;
44
45 #ifdef ARRAY_VARS
46 extern int declare_builtin ();
47 #endif
48
49 #define READONLY_OR_EXPORT \
50 (this_shell_builtin == readonly_builtin || this_shell_builtin == export_builtin)
51
52 $BUILTIN export
53 $FUNCTION export_builtin
54 $SHORT_DOC export [-nf] [name ...] or export -p
55 NAMEs are marked for automatic export to the environment of
56 subsequently executed commands. If the -f option is given,
57 the NAMEs refer to functions. If no NAMEs are given, or if `-p'
58 is given, a list of all names that are exported in this shell is
59 printed. An argument of `-n' says to remove the export property
60 from subsequent NAMEs. An argument of `--' disables further option
61 processing.
62 $END
63
64 /* For each variable name in LIST, make that variable appear in the
65 environment passed to simple commands. If there is no LIST, then
66 print all such variables. An argument of `-n' says to remove the
67 exported attribute from variables named in LIST. An argument of
68 -f indicates that the names present in LIST refer to functions. */
69 int
70 export_builtin (list)
71 register WORD_LIST *list;
72 {
73 return (set_or_show_attributes (list, att_exported, 0));
74 }
75
76 $BUILTIN readonly
77 $FUNCTION readonly_builtin
78 $SHORT_DOC readonly [-anf] [name ...] or readonly -p
79 The given NAMEs are marked readonly and the values of these NAMEs may
80 not be changed by subsequent assignment. If the -f option is given,
81 then functions corresponding to the NAMEs are so marked. If no
82 arguments are given, or if `-p' is given, a list of all readonly names
83 is printed. An argument of `-n' says to remove the readonly property
84 from subsequent NAMEs. 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 /* For each variable name in LIST, make that variable have the specified
99 ATTRIBUTE. An arg of `-n' says to remove the attribute from the the
100 remaining names in LIST. */
101 int
102 set_or_show_attributes (list, attribute, nodefs)
103 register WORD_LIST *list;
104 int attribute, nodefs;
105 {
106 register SHELL_VAR *var;
107 int assign, undo, functions_only, arrays_only, any_failed, assign_error, opt;
108 char *name;
109 #if defined (ARRAY_VARS)
110 WORD_LIST *nlist, *tlist;
111 WORD_DESC *w;
112 #endif
113
114 undo = functions_only = arrays_only = any_failed = assign_error = 0;
115 /* Read arguments from the front of the list. */
116 reset_internal_getopt ();
117 while ((opt = internal_getopt (list, "anfp")) != -1)
118 {
119 switch (opt)
120 {
121 case 'n':
122 undo = 1;
123 break;
124 case 'f':
125 functions_only = 1;
126 break;
127 #if defined (ARRAY_VARS)
128 case 'a':
129 arrays_only = 1;
130 break;
131 #endif
132 case 'p':
133 break;
134 default:
135 builtin_usage ();
136 return (EX_USAGE);
137 }
138 }
139 list = loptend;
140
141 if (list)
142 {
143 if (attribute & att_exported)
144 array_needs_making = 1;
145
146 /* Cannot undo readonly status, silently disallowed. */
147 if (undo && (attribute & att_readonly))
148 attribute &= ~att_readonly;
149
150 while (list)
151 {
152 name = list->word->word;
153
154 if (functions_only) /* xxx -f name */
155 {
156 var = find_function (name);
157 if (var == 0)
158 {
159 builtin_error ("%s: not a function", name);
160 any_failed++;
161 }
162 else
163 SETVARATTR (var, attribute, undo);
164
165 list = list->next;
166 continue;
167 }
168
169 /* xxx [-np] name[=value] */
170 assign = assignment (name);
171
172 if (assign)
173 name[assign] = '\0';
174
175 if (legal_identifier (name) == 0)
176 {
177 builtin_error ("`%s': not a valid identifier", name);
178 if (assign)
179 assign_error++;
180 else
181 any_failed++;
182 list = list->next;
183 continue;
184 }
185
186 if (assign) /* xxx [-np] name=value */
187 {
188 name[assign] = '=';
189 #if defined (ARRAY_VARS)
190 /* Let's try something here. Turn readonly -a xxx=yyy into
191 declare -ra xxx=yyy and see what that gets us. */
192 if (arrays_only)
193 {
194 tlist = list->next;
195 list->next = (WORD_LIST *)NULL;
196 w = make_word ("-ra");
197 nlist = make_word_list (w, list);
198 opt = declare_builtin (nlist);
199 if (opt != EXECUTION_SUCCESS)
200 assign_error++;
201 list->next = tlist;
202 dispose_word (w);
203 free (nlist);
204 }
205 else
206 #endif
207 /* This word has already been expanded once with command
208 and parameter expansion. Call do_assignment_no_expand (),
209 which does not do command or parameter substitution. If
210 the assignment is not performed correctly, flag an error. */
211 if (do_assignment_no_expand (name) == 0)
212 assign_error++;
213 name[assign] = '\0';
214 }
215
216 set_var_attribute (name, attribute, undo);
217 list = list->next;
218 }
219 }
220 else
221 {
222 SHELL_VAR **variable_list;
223 register int i;
224
225 if ((attribute & att_function) || functions_only)
226 {
227 variable_list = all_shell_functions ();
228 if (attribute != att_function)
229 attribute &= ~att_function; /* so declare -xf works, for example */
230 }
231 else
232 variable_list = all_shell_variables ();
233
234 #if defined (ARRAY_VARS)
235 if (attribute & att_array)
236 {
237 arrays_only++;
238 if (attribute != att_array)
239 attribute &= ~att_array;
240 }
241 #endif
242
243 if (variable_list)
244 {
245 for (i = 0; var = variable_list[i]; i++)
246 {
247 #if defined (ARRAY_VARS)
248 if (arrays_only && array_p (var) == 0)
249 continue;
250 #endif
251 if ((var->attributes & attribute) && invisible_p (var) == 0)
252 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
253 }
254 free (variable_list);
255 }
256 }
257
258 return (assign_error ? EX_BADASSIGN
259 : ((any_failed == 0) ? EXECUTION_SUCCESS
260 : EXECUTION_FAILURE));
261 }
262
263 /* Show the attributes for shell variable VAR. If NODEFS is non-zero,
264 don't show function definitions along with the name. If PATTR is
265 non-zero, it indicates we're being called from `export' or `readonly'.
266 In POSIX mode, this prints the name of the calling builtin (`export'
267 or `readonly') instead of `declare', and doesn't print function defs
268 when called by `export' or `readonly'. */
269 int
270 show_var_attributes (var, pattr, nodefs)
271 SHELL_VAR *var;
272 int pattr, nodefs;
273 {
274 char flags[6], *x;
275 int i;
276
277 i = 0;
278
279 /* pattr == 0 means we are called from `declare'. */
280 if (pattr == 0 || posixly_correct == 0)
281 {
282 #if defined (ARRAY_VARS)
283 if (array_p (var))
284 flags[i++] = 'a';
285 #endif
286
287 if (function_p (var))
288 flags[i++] = 'f';
289
290 if (integer_p (var))
291 flags[i++] = 'i';
292
293 if (readonly_p (var))
294 flags[i++] = 'r';
295
296 if (exported_p (var))
297 flags[i++] = 'x';
298 }
299 else
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
310 flags[i] = '\0';
311
312 if (pattr == 0 || posixly_correct == 0)
313 printf ("declare -%s ", i ? flags : "-");
314 else if (i)
315 printf ("%s -%s ", this_command_name, flags);
316 else
317 printf ("%s ", this_command_name);
318
319 #if defined (ARRAY_VARS)
320 if (array_p (var))
321 print_array_assignment (var, 1);
322 else
323 #endif
324 /* force `readline' and `export' to not print out function definitions
325 when in POSIX mode. */
326 if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
327 printf ("%s\n", var->name);
328 else if (function_p (var))
329 printf ("%s\n", named_function_string (var->name, function_cell (var), 1));
330 else
331 {
332 x = sh_double_quote (value_cell (var) ? value_cell (var) : "");
333 printf ("%s=%s\n", var->name, x);
334 free (x);
335 }
336 return (0);
337 }
338
339 int
340 show_name_attributes (name, nodefs)
341 char *name;
342 int nodefs;
343 {
344 SHELL_VAR *var;
345 int ret;
346
347 var = find_tempenv_variable (name);
348 if (var == 0)
349 var = find_variable (name);
350
351 if (var && invisible_p (var) == 0)
352 {
353 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
354 if (tempvar_p (var))
355 dispose_variable (var);
356 return (0);
357 }
358 else
359 return (1);
360 }
361
362 void
363 set_var_attribute (name, attribute, undo)
364 char *name;
365 int attribute, undo;
366 {
367 SHELL_VAR *var, *tv;
368
369 if (undo)
370 var = find_variable (name);
371 else
372 {
373 if (tv = find_tempenv_variable (name))
374 {
375 var = bind_variable (tv->name, tv->value ? tv->value : "");
376 dispose_variable (tv);
377 }
378 else
379 var = find_variable (name);
380
381 if (var == 0)
382 {
383 var = bind_variable (name, (char *)NULL);
384 VSETATTR (var, att_invisible);
385 }
386 }
387
388 if (var)
389 SETVARATTR (var, attribute, undo);
390
391 if (var && (exported_p (var) || (attribute & att_exported)))
392 array_needs_making++; /* XXX */
393 }