Imported from ../bash-2.05b.tar.gz.
[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-2002 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 sh_builtin_func_t *this_shell_builtin;
44
45 #ifdef ARRAY_VARS
46 extern int declare_builtin __P((WORD_LIST *));
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[=value] ...] 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[=value] ...] 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 #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. */
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);
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 }