Imported from ../bash-2.0.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, 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 array_needs_making;
38 extern char *this_command_name;
39
40 $BUILTIN export
41 $FUNCTION export_builtin
42 $SHORT_DOC export [-nf] [name ...] or export -p
43 NAMEs are marked for automatic export to the environment of
44 subsequently executed commands.  If the -f option is given,
45 the NAMEs refer to functions.  If no NAMEs are given, or if `-p'
46 is given, a list of all names that are exported in this shell is
47 printed.  An argument of `-n' says to remove the export property
48 from subsequent NAMEs.  An argument of `--' disables further option
49 processing.
50 $END
51
52 /* For each variable name in LIST, make that variable appear in the
53    environment passed to simple commands.  If there is no LIST, then
54    print all such variables.  An argument of `-n' says to remove the
55    exported attribute from variables named in LIST.  An argument of
56   -f indicates that the names present in LIST refer to functions. */
57 int
58 export_builtin (list)
59      register WORD_LIST *list;
60 {
61   return (set_or_show_attributes (list, att_exported, 0));
62 }
63
64 $BUILTIN readonly
65 $FUNCTION readonly_builtin
66 $SHORT_DOC readonly [-anf] [name ...] or readonly -p
67 The given NAMEs are marked readonly and the values of these NAMEs may
68 not be changed by subsequent assignment.  If the -f option is given,
69 then functions corresponding to the NAMEs are so marked.  If no
70 arguments are given, or if `-p' is given, a list of all readonly names
71 is printed.  An argument of `-n' says to remove the readonly property
72 from subsequent NAMEs.  The `-a' option means to treat each NAME as
73 an array variable.  An argument of `--' disables further option
74 processing.
75 $END
76
77 /* For each variable name in LIST, make that variable readonly.  Given an
78    empty LIST, print out all existing readonly variables. */
79 int
80 readonly_builtin (list)
81      register WORD_LIST *list;
82 {
83   return (set_or_show_attributes (list, att_readonly, 0));
84 }
85
86 /* For each variable name in LIST, make that variable have the specified
87    ATTRIBUTE.  An arg of `-n' says to remove the attribute from the the
88    remaining names in LIST. */
89 int
90 set_or_show_attributes (list, attribute, nodefs)
91      register WORD_LIST *list;
92      int attribute, nodefs;
93 {
94   register SHELL_VAR *var;
95   int assign, undo, functions_only, arrays_only, any_failed, assign_error, opt;
96   char *name;
97
98   undo = functions_only = arrays_only = any_failed = assign_error = 0;
99   /* Read arguments from the front of the list. */
100   reset_internal_getopt ();
101   while ((opt = internal_getopt (list, "anfp")) != -1)
102     {
103       switch (opt)
104         {
105           case 'n':
106             undo = 1;
107             break;
108           case 'f':
109             functions_only = 1;
110             break;
111 #if defined (ARRAY_VARS)
112           case 'a':
113              arrays_only = 1;
114              break;
115 #endif
116           case 'p':
117             break;
118           default:
119             builtin_usage ();
120             return (EX_USAGE);
121         }
122     }
123   list = loptend;
124
125   if (list)
126     {
127       if (attribute & att_exported)
128         array_needs_making = 1;
129
130       /* Cannot undo readonly status, silently disallowed. */
131       if (undo && (attribute & att_readonly))
132         attribute &= ~att_readonly;
133
134       while (list)
135         {
136           name = list->word->word;
137
138           if (functions_only)           /* xxx -f name */
139             {
140               var = find_function (name);
141               if (var == 0)
142                 {
143                   builtin_error ("%s: not a function", name);
144                   any_failed++;
145                 }
146               else
147                 SETVARATTR (var, attribute, undo);
148
149               list = list->next;
150               continue;
151             }
152
153           /* xxx [-np] name[=value] */
154           assign = assignment (name);
155
156           if (assign)
157             name[assign] = '\0';
158
159           if (legal_identifier (name) == 0)
160             {
161               builtin_error ("`%s': not a valid identifier", name);
162               assign_error++;
163               list = list->next;
164               continue;
165             }
166
167           if (assign)   /* xxx [-np] name=value */
168             {
169               name[assign] = '=';
170               /* This word has already been expanded once with command
171                  and parameter expansion.  Call do_assignment_no_expand (),
172                  which does not do command or parameter substitution.  If
173                  the assignment is not performed correctly, flag an error. */
174               if (do_assignment_no_expand (name) == 0)
175                 assign_error++;
176               name[assign] = '\0';
177             }
178
179           set_var_attribute (name, attribute, undo);
180           list = list->next;
181         }
182     }
183   else
184     {
185       SHELL_VAR **variable_list;
186       register int i;
187
188       if ((attribute & att_function) || functions_only)
189         {
190           variable_list = all_shell_functions ();
191           if (attribute != att_function)
192             attribute &= ~att_function; /* so declare -xf works, for example */
193         }
194       else
195         variable_list = all_shell_variables ();
196
197 #if defined (ARRAY_VARS)
198       if (attribute & att_array)
199         {
200           arrays_only++;
201           if (attribute != att_array)
202             attribute &= ~att_array;
203         }
204 #endif
205
206       if (variable_list)
207         {
208           for (i = 0; var = variable_list[i]; i++)
209             {
210 #if defined (ARRAY_VARS)
211               if (arrays_only && array_p (var) == 0)
212                 continue;
213 #endif
214               if ((var->attributes & attribute) && invisible_p (var) == 0)
215                 show_var_attributes (var, nodefs);
216             }
217           free (variable_list);
218         }
219     }
220
221   return (assign_error ? EX_BADASSIGN
222                        : ((any_failed == 0) ? EXECUTION_SUCCESS
223                                             : EXECUTION_FAILURE));
224 }
225
226 int
227 show_var_attributes (var, nodefs)
228      SHELL_VAR *var;
229      int nodefs;
230 {
231   char flags[6], *x;
232   int i;
233
234   i = 0;
235
236 #if defined (ARRAY_VARS)
237   if (array_p (var))
238     flags[i++] = 'a';
239 #endif
240
241   if (function_p (var))
242     flags[i++] = 'f';
243
244   if (integer_p (var))
245     flags[i++] = 'i';
246
247   if (readonly_p (var))
248     flags[i++] = 'r';
249
250   if (exported_p (var))
251     flags[i++] = 'x';
252
253   flags[i] = '\0';
254
255   printf ("declare -%s ", i ? flags : "-");
256
257 #if defined (ARRAY_VARS)
258  if (array_p (var))
259     print_array_assignment (var, 1);
260   else
261 #endif
262   if (nodefs)
263     printf ("%s\n", var->name);
264   else if (function_p (var))
265     printf ("%s\n", named_function_string (var->name, function_cell (var), 1));
266   else
267     {
268       x = double_quote (value_cell (var));
269       printf ("%s=%s\n", var->name, x);
270       free (x);
271     }
272   return (0);
273 }
274
275 int
276 show_name_attributes (name, nodefs)
277      char *name;
278      int nodefs;
279 {
280   SHELL_VAR *var;
281
282   var = find_tempenv_variable (name);
283   if (var == 0)
284     var = find_variable (name);
285
286   if (var && invisible_p (var) == 0)
287     {
288       show_var_attributes (var, nodefs);
289       return (0);
290     }
291   else
292     return (1);
293 }
294
295 void
296 set_var_attribute (name, attribute, undo)
297      char *name;
298      int attribute, undo;
299 {
300   SHELL_VAR *var, *tv;
301
302   if (undo)
303     var = find_variable (name);
304   else
305     {
306       if (tv = find_tempenv_variable (name))
307         {
308           var = bind_variable (tv->name, tv->value);
309           dispose_variable (tv);
310         }
311       else
312         var = find_variable (name);
313
314       if (var == 0)
315         {
316           var = bind_variable (name, (char *)NULL);
317           var->attributes |= att_invisible;
318         }
319     }
320
321   if (var)
322     SETVARATTR (var, attribute, undo);
323
324   if (var && ((var->attributes & att_exported) || (attribute & att_exported)))
325     array_needs_making++;       /* XXX */
326 }