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