Imported from ../bash-2.02.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 #  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 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)
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 ((var->attributes & attribute) && invisible_p (var) == 0)
252                 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
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
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'. */
269 int
270 show_var_attributes (var, pattr, nodefs)
271      SHELL_VAR *var;
272      int pattr, nodefs;
273 {
274   char flags[6], *x;
275   int i;
276
277   i = 0;
278
279   /* pattr == 0 means we are called from `declare'. */
280   if (pattr == 0 || posixly_correct == 0)
281     {
282 #if defined (ARRAY_VARS)
283       if (array_p (var))
284         flags[i++] = 'a';
285 #endif
286
287       if (function_p (var))
288         flags[i++] = 'f';
289
290       if (integer_p (var))
291         flags[i++] = 'i';
292
293       if (readonly_p (var))
294         flags[i++] = 'r';
295
296       if (exported_p (var))
297         flags[i++] = 'x';
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))
307         flags[i++] = 'f';
308     }
309
310   flags[i] = '\0';
311
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);
318
319 #if defined (ARRAY_VARS)
320  if (array_p (var))
321     print_array_assignment (var, 1);
322   else
323 #endif
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))
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     {
332       x = double_quote (value_cell (var) ? value_cell (var) : "");
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;
345   int ret;
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     {
353       show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
354       if (tempvar_p (var))
355         dispose_variable (var);
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         {
375           var = bind_variable (tv->name, tv->value ? tv->value : "");
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);
384           var->attributes |= att_invisible;
385         }
386     }
387
388   if (var)
389     SETVARATTR (var, attribute, undo);
390
391   if (var && ((var->attributes & att_exported) || (attribute & att_exported)))
392     array_needs_making++;       /* XXX */
393 }