]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
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 | |
bb70624e | 10 | Software Foundation; either version 2, or (at your option) any later |
726f6388 JA |
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 | |
bb70624e | 20 | Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. |
726f6388 JA |
21 | |
22 | $PRODUCES setattr.c | |
23 | ||
ccc6cda3 JA |
24 | #include <config.h> |
25 | ||
26 | #if defined (HAVE_UNISTD_H) | |
cce855bc JA |
27 | # ifdef _MINIX |
28 | # include <sys/types.h> | |
29 | # endif | |
ccc6cda3 JA |
30 | # include <unistd.h> |
31 | #endif | |
32 | ||
33 | #include <stdio.h> | |
34 | #include "../bashansi.h" | |
35 | ||
726f6388 JA |
36 | #include "../shell.h" |
37 | #include "common.h" | |
38 | #include "bashgetopt.h" | |
39 | ||
d166f048 | 40 | extern int posixly_correct; |
726f6388 JA |
41 | extern int array_needs_making; |
42 | extern char *this_command_name; | |
d166f048 JA |
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) | |
726f6388 JA |
51 | |
52 | $BUILTIN export | |
53 | $FUNCTION export_builtin | |
ccc6cda3 | 54 | $SHORT_DOC export [-nf] [name ...] or export -p |
726f6388 JA |
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. */ | |
ccc6cda3 | 69 | int |
726f6388 JA |
70 | export_builtin (list) |
71 | register WORD_LIST *list; | |
72 | { | |
ccc6cda3 | 73 | return (set_or_show_attributes (list, att_exported, 0)); |
726f6388 JA |
74 | } |
75 | ||
76 | $BUILTIN readonly | |
77 | $FUNCTION readonly_builtin | |
ccc6cda3 | 78 | $SHORT_DOC readonly [-anf] [name ...] or readonly -p |
726f6388 JA |
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 | |
ccc6cda3 JA |
84 | from subsequent NAMEs. The `-a' option means to treat each NAME as |
85 | an array variable. An argument of `--' disables further option | |
726f6388 JA |
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. */ | |
ccc6cda3 | 91 | int |
726f6388 JA |
92 | readonly_builtin (list) |
93 | register WORD_LIST *list; | |
94 | { | |
ccc6cda3 | 95 | return (set_or_show_attributes (list, att_readonly, 0)); |
726f6388 JA |
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 | |
ccc6cda3 | 102 | set_or_show_attributes (list, attribute, nodefs) |
726f6388 | 103 | register WORD_LIST *list; |
ccc6cda3 | 104 | int attribute, nodefs; |
726f6388 JA |
105 | { |
106 | register SHELL_VAR *var; | |
ccc6cda3 JA |
107 | int assign, undo, functions_only, arrays_only, any_failed, assign_error, opt; |
108 | char *name; | |
d166f048 JA |
109 | #if defined (ARRAY_VARS) |
110 | WORD_LIST *nlist, *tlist; | |
111 | WORD_DESC *w; | |
112 | #endif | |
726f6388 | 113 | |
ccc6cda3 | 114 | undo = functions_only = arrays_only = any_failed = assign_error = 0; |
726f6388 JA |
115 | /* Read arguments from the front of the list. */ |
116 | reset_internal_getopt (); | |
ccc6cda3 | 117 | while ((opt = internal_getopt (list, "anfp")) != -1) |
726f6388 JA |
118 | { |
119 | switch (opt) | |
120 | { | |
121 | case 'n': | |
122 | undo = 1; | |
123 | break; | |
124 | case 'f': | |
125 | functions_only = 1; | |
126 | break; | |
ccc6cda3 JA |
127 | #if defined (ARRAY_VARS) |
128 | case 'a': | |
129 | arrays_only = 1; | |
130 | break; | |
131 | #endif | |
726f6388 JA |
132 | case 'p': |
133 | break; | |
134 | default: | |
ccc6cda3 | 135 | builtin_usage (); |
726f6388 JA |
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 | ||
ccc6cda3 | 146 | /* Cannot undo readonly status, silently disallowed. */ |
726f6388 JA |
147 | if (undo && (attribute & att_readonly)) |
148 | attribute &= ~att_readonly; | |
149 | ||
150 | while (list) | |
151 | { | |
ccc6cda3 | 152 | name = list->word->word; |
726f6388 | 153 | |
ccc6cda3 | 154 | if (functions_only) /* xxx -f name */ |
726f6388 JA |
155 | { |
156 | var = find_function (name); | |
ccc6cda3 | 157 | if (var == 0) |
726f6388 JA |
158 | { |
159 | builtin_error ("%s: not a function", name); | |
160 | any_failed++; | |
161 | } | |
162 | else | |
ccc6cda3 JA |
163 | SETVARATTR (var, attribute, undo); |
164 | ||
726f6388 | 165 | list = list->next; |
726f6388 JA |
166 | continue; |
167 | } | |
168 | ||
ccc6cda3 | 169 | /* xxx [-np] name[=value] */ |
726f6388 JA |
170 | assign = assignment (name); |
171 | ||
28ef6c31 | 172 | if (assign) |
726f6388 | 173 | name[assign] = '\0'; |
ccc6cda3 | 174 | |
726f6388 JA |
175 | if (legal_identifier (name) == 0) |
176 | { | |
ccc6cda3 | 177 | builtin_error ("`%s': not a valid identifier", name); |
d166f048 JA |
178 | if (assign) |
179 | assign_error++; | |
180 | else | |
181 | any_failed++; | |
726f6388 JA |
182 | list = list->next; |
183 | continue; | |
184 | } | |
185 | ||
ccc6cda3 | 186 | if (assign) /* xxx [-np] name=value */ |
726f6388 JA |
187 | { |
188 | name[assign] = '='; | |
d166f048 JA |
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 | |
726f6388 JA |
207 | /* This word has already been expanded once with command |
208 | and parameter expansion. Call do_assignment_no_expand (), | |
ccc6cda3 JA |
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++; | |
726f6388 JA |
213 | name[assign] = '\0'; |
214 | } | |
215 | ||
ccc6cda3 | 216 | set_var_attribute (name, attribute, undo); |
726f6388 JA |
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 | ||
ccc6cda3 JA |
234 | #if defined (ARRAY_VARS) |
235 | if (attribute & att_array) | |
28ef6c31 JA |
236 | { |
237 | arrays_only++; | |
238 | if (attribute != att_array) | |
ccc6cda3 | 239 | attribute &= ~att_array; |
28ef6c31 | 240 | } |
ccc6cda3 JA |
241 | #endif |
242 | ||
726f6388 JA |
243 | if (variable_list) |
244 | { | |
245 | for (i = 0; var = variable_list[i]; i++) | |
246 | { | |
ccc6cda3 JA |
247 | #if defined (ARRAY_VARS) |
248 | if (arrays_only && array_p (var) == 0) | |
28ef6c31 | 249 | continue; |
ccc6cda3 JA |
250 | #endif |
251 | if ((var->attributes & attribute) && invisible_p (var) == 0) | |
d166f048 | 252 | show_var_attributes (var, READONLY_OR_EXPORT, nodefs); |
ccc6cda3 JA |
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 | ||
d166f048 JA |
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'. */ | |
ccc6cda3 | 269 | int |
d166f048 | 270 | show_var_attributes (var, pattr, nodefs) |
ccc6cda3 | 271 | SHELL_VAR *var; |
d166f048 | 272 | int pattr, nodefs; |
ccc6cda3 JA |
273 | { |
274 | char flags[6], *x; | |
275 | int i; | |
726f6388 | 276 | |
ccc6cda3 | 277 | i = 0; |
726f6388 | 278 | |
d166f048 JA |
279 | /* pattr == 0 means we are called from `declare'. */ |
280 | if (pattr == 0 || posixly_correct == 0) | |
281 | { | |
ccc6cda3 | 282 | #if defined (ARRAY_VARS) |
d166f048 JA |
283 | if (array_p (var)) |
284 | flags[i++] = 'a'; | |
ccc6cda3 | 285 | #endif |
726f6388 | 286 | |
d166f048 | 287 | if (function_p (var)) |
28ef6c31 | 288 | flags[i++] = 'f'; |
726f6388 | 289 | |
d166f048 | 290 | if (integer_p (var)) |
28ef6c31 | 291 | flags[i++] = 'i'; |
726f6388 | 292 | |
d166f048 | 293 | if (readonly_p (var)) |
28ef6c31 | 294 | flags[i++] = 'r'; |
726f6388 | 295 | |
d166f048 | 296 | if (exported_p (var)) |
28ef6c31 | 297 | flags[i++] = 'x'; |
d166f048 JA |
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)) | |
28ef6c31 | 307 | flags[i++] = 'f'; |
d166f048 | 308 | } |
726f6388 | 309 | |
ccc6cda3 | 310 | flags[i] = '\0'; |
726f6388 | 311 | |
d166f048 JA |
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); | |
ccc6cda3 JA |
318 | |
319 | #if defined (ARRAY_VARS) | |
320 | if (array_p (var)) | |
321 | print_array_assignment (var, 1); | |
322 | else | |
323 | #endif | |
d166f048 JA |
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)) | |
ccc6cda3 JA |
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 | { | |
28ef6c31 | 332 | x = sh_double_quote (value_cell (var) ? value_cell (var) : ""); |
ccc6cda3 JA |
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; | |
cce855bc | 345 | int ret; |
ccc6cda3 JA |
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 | { | |
d166f048 | 353 | show_var_attributes (var, READONLY_OR_EXPORT, nodefs); |
cce855bc JA |
354 | if (tempvar_p (var)) |
355 | dispose_variable (var); | |
ccc6cda3 JA |
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 | { | |
e8ce775d | 375 | var = bind_variable (tv->name, tv->value ? tv->value : ""); |
ccc6cda3 JA |
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); | |
bb70624e | 384 | VSETATTR (var, att_invisible); |
726f6388 JA |
385 | } |
386 | } | |
ccc6cda3 JA |
387 | |
388 | if (var) | |
389 | SETVARATTR (var, attribute, undo); | |
390 | ||
bb70624e | 391 | if (var && (exported_p (var) || (attribute & att_exported))) |
ccc6cda3 | 392 | array_needs_making++; /* XXX */ |
726f6388 | 393 | } |