dad11fdfe1c97fa821bad73857011a87febe9aad
[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 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 ();
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 0
252               if ((var->attributes & attribute) && invisible_p (var) == 0)
253 #else
254               if ((var->attributes & attribute))
255 #endif
256                 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
257             }
258           free (variable_list);
259         }
260     }
261
262   return (assign_error ? EX_BADASSIGN
263                        : ((any_failed == 0) ? EXECUTION_SUCCESS
264                                             : EXECUTION_FAILURE));
265 }
266
267 /* Show the attributes for shell variable VAR.  If NODEFS is non-zero,
268    don't show function definitions along with the name.  If PATTR is
269    non-zero, it indicates we're being called from `export' or `readonly'.
270    In POSIX mode, this prints the name of the calling builtin (`export'
271    or `readonly') instead of `declare', and doesn't print function defs
272    when called by `export' or `readonly'. */
273 int
274 show_var_attributes (var, pattr, nodefs)
275      SHELL_VAR *var;
276      int pattr, nodefs;
277 {
278   char flags[6], *x;
279   int i;
280
281   i = 0;
282
283   /* pattr == 0 means we are called from `declare'. */
284   if (pattr == 0 || posixly_correct == 0)
285     {
286 #if defined (ARRAY_VARS)
287       if (array_p (var))
288         flags[i++] = 'a';
289 #endif
290
291       if (function_p (var))
292         flags[i++] = 'f';
293
294       if (integer_p (var))
295         flags[i++] = 'i';
296
297       if (readonly_p (var))
298         flags[i++] = 'r';
299
300       if (exported_p (var))
301         flags[i++] = 'x';
302     }
303   else
304     {
305 #if defined (ARRAY_VARS)
306       if (array_p (var))
307         flags[i++] = 'a';
308 #endif
309
310       if (function_p (var))
311         flags[i++] = 'f';
312     }
313
314   flags[i] = '\0';
315
316   if (pattr == 0 || posixly_correct == 0)
317     printf ("declare -%s ", i ? flags : "-");
318   else if (i)
319     printf ("%s -%s ", this_command_name, flags);
320   else
321     printf ("%s ", this_command_name);
322
323 #if defined (ARRAY_VARS)
324  if (array_p (var))
325     print_array_assignment (var, 1);
326   else
327 #endif
328   /* force `readline' and `export' to not print out function definitions
329      when in POSIX mode. */
330   if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
331     printf ("%s\n", var->name);
332   else if (function_p (var))
333     printf ("%s\n", named_function_string (var->name, function_cell (var), 1));
334   else if (invisible_p (var))
335     printf ("%s\n", var->name);
336   else
337     {
338       x = sh_double_quote (value_cell (var) ? value_cell (var) : "");
339       printf ("%s=%s\n", var->name, x);
340       free (x);
341     }
342   return (0);
343 }
344
345 int
346 show_name_attributes (name, nodefs)
347      char *name;
348      int nodefs;
349 {
350   SHELL_VAR *var;
351
352   var = find_tempenv_variable (name);
353   if (var == 0)
354     var = find_variable (name);
355
356   if (var && invisible_p (var) == 0)
357     {
358       show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
359       if (tempvar_p (var))
360         dispose_variable (var);
361       return (0);
362     }
363   else
364     return (1);
365 }
366
367 void
368 set_var_attribute (name, attribute, undo)
369      char *name;
370      int attribute, undo;
371 {
372   SHELL_VAR *var, *tv;
373
374   if (undo)
375     var = find_variable (name);
376   else
377     {
378       if (tv = find_tempenv_variable (name))
379         {
380           var = bind_variable (tv->name, tv->value ? tv->value : "");
381           dispose_variable (tv);
382         }
383       else
384         var = find_variable (name);
385
386       if (var == 0)
387         {
388           var = bind_variable (name, (char *)NULL);
389           VSETATTR (var, att_invisible);
390         }
391     }
392
393   if (var)
394     SETVARATTR (var, attribute, undo);
395
396   if (var && (exported_p (var) || (attribute & att_exported)))
397     array_needs_making++;       /* XXX */
398 }