]> git.ipfire.org Git - thirdparty/bash.git/blob - variables.c
615aacd14f12eb482857879fc347e461e39dcef7
[thirdparty/bash.git] / variables.c
1 /* variables.c -- Functions for hacking shell variables. */
2
3 /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
7 Bash is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 Bash is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Bash; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
20
21 #include "config.h"
22
23 #include "bashtypes.h"
24 #include "posixstat.h"
25
26 #if defined (qnx)
27 # include <sys/vc.h>
28 #endif
29
30 #if defined (HAVE_UNISTD_H)
31 # include <unistd.h>
32 #endif
33
34 #include <stdio.h>
35 #include <ctype.h>
36 #include <pwd.h>
37 #include "bashansi.h"
38
39 #include "shell.h"
40 #include "flags.h"
41 #include "execute_cmd.h"
42 #include "findcmd.h"
43 #include "mailcheck.h"
44 #include "input.h"
45
46 #include "builtins/getopt.h"
47 #include "builtins/common.h"
48
49 #if defined (READLINE)
50 # include "bashline.h"
51 # include <readline/readline.h>
52 #else
53 # include <tilde/tilde.h>
54 #endif
55
56 #if defined (HISTORY)
57 # include "bashhist.h"
58 # include <readline/history.h>
59 #endif /* HISTORY */
60
61 #if defined (PROGRAMMABLE_COMPLETION)
62 # include "pcomplete.h"
63 #endif
64
65 /* Variables used here and defined in other files. */
66 extern int posixly_correct;
67 extern int variable_context, line_number;
68 extern int interactive, interactive_shell, login_shell;
69 extern int subshell_environment, indirection_level;
70 extern int build_version, patch_level;
71 extern char *dist_version, *release_status;
72 extern char *shell_name;
73 extern char *primary_prompt, *secondary_prompt;
74 extern char *current_host_name;
75 extern Function *this_shell_builtin;
76 extern SHELL_VAR *this_shell_function;
77 extern char *this_command_name;
78 extern time_t shell_start_time;
79
80 /* The list of shell variables that the user has created, or that came from
81 the environment. */
82 HASH_TABLE *shell_variables = (HASH_TABLE *)NULL;
83
84 /* The list of shell functions that the user has created, or that came from
85 the environment. */
86 HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
87
88 /* The current variable context. This is really a count of how deep into
89 executing functions we are. */
90 int variable_context = 0;
91
92 /* The array of shell assignments which are made only in the environment
93 for a single command. */
94 char **temporary_env = (char **)NULL;
95
96 /* The array of shell assignments which are in the environment for the
97 execution of a shell function. */
98 char **function_env = (char **)NULL;
99
100 /* The array of shell assignments which are made only in the environment
101 for the execution of a shell builtin command which may cause more than
102 one command to be executed (e.g., "source"). */
103 char **builtin_env = (char **)NULL;
104
105 /* Some funky variables which are known about specially. Here is where
106 "$*", "$1", and all the cruft is kept. */
107 char *dollar_vars[10];
108 WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
109
110 /* The value of $$. */
111 int dollar_dollar_pid;
112
113 /* An array which is passed to commands as their environment. It is
114 manufactured from the union of the initial environment and the
115 shell variables that are marked for export. */
116 char **export_env = (char **)NULL;
117 static int export_env_index;
118 static int export_env_size;
119
120 /* Non-zero means that we have to remake EXPORT_ENV. */
121 int array_needs_making = 1;
122
123 /* The number of times BASH has been executed. This is set
124 by initialize_variables (). */
125 int shell_level = 0;
126
127 static char *have_local_variables;
128 static int local_variable_stack_size;
129
130 /* Some forward declarations. */
131 static void set_home_var ();
132 static void set_shell_var ();
133 static char *get_bash_name ();
134 static void initialize_shell_level ();
135 static void uidset ();
136 static void initialize_dynamic_variables ();
137 static void make_vers_array ();
138 static void sbrand (); /* set bash random number generator. */
139 static int qsort_var_comp ();
140
141 /* Make VAR be auto-exported. VAR is a pointer to a SHELL_VAR. */
142 #define set_auto_export(var) \
143 do { var->attributes |= att_exported; array_needs_making = 1; } while (0)
144
145 /* Initialize the shell variables from the current environment.
146 If PRIVMODE is nonzero, don't import functions from ENV or
147 parse $SHELLOPTS. */
148 void
149 initialize_shell_variables (env, privmode)
150 char **env;
151 int privmode;
152 {
153 char *name, *string, *temp_string;
154 int c, char_index, string_index, string_length;
155 SHELL_VAR *temp_var;
156
157 if (shell_variables == 0)
158 shell_variables = make_hash_table (0);
159
160 if (shell_functions == 0)
161 shell_functions = make_hash_table (0);
162
163 for (string_index = 0; string = env[string_index++]; )
164 {
165 char_index = 0;
166 name = string;
167 while ((c = *string++) && c != '=')
168 ;
169 if (string[-1] == '=')
170 char_index = string - name - 1;
171
172 /* If there are weird things in the environment, like `=xxx' or a
173 string without an `=', just skip them. */
174 if (char_index == 0)
175 continue;
176
177 /* ASSERT(name[char_index] == '=') */
178 name[char_index] = '\0';
179 /* Now, name = env variable name, string = env variable value, and
180 char_index == strlen (name) */
181
182 /* If exported function, define it now. */
183 if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
184 {
185 string_length = strlen (string);
186 temp_string = xmalloc (3 + string_length + char_index);
187
188 strcpy (temp_string, name);
189 temp_string[char_index] = ' ';
190 strcpy (temp_string + char_index + 1, string);
191
192 parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
193
194 /* Ancient backwards compatibility. Old versions of bash exported
195 functions like name()=() {...} */
196 if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
197 name[char_index - 2] = '\0';
198
199 if (temp_var = find_function (name))
200 {
201 VSETATTR (temp_var, (att_exported|att_imported));
202 array_needs_making = 1;
203 }
204 else
205 report_error ("error importing function definition for `%s'", name);
206
207 /* ( */
208 if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
209 name[char_index - 2] = '('; /* ) */
210 }
211 #if defined (ARRAY_VARS)
212 # if 0
213 /* Array variables may not yet be exported. */
214 else if (*string == '(' && string[1] == '[' && strchr (string, ')'))
215 {
216 string_length = 1;
217 temp_string = extract_array_assignment_list (string, &string_length);
218 temp_var = assign_array_from_string (name, temp_string);
219 FREE (temp_string);
220 VSETATTR (temp_var, (att_exported | att_imported));
221 array_needs_making = 1;
222 }
223 # endif
224 #endif
225 else
226 {
227 temp_var = bind_variable (name, string);
228 VSETATTR (temp_var, (att_exported | att_imported));
229 array_needs_making = 1;
230 }
231
232 name[char_index] = '=';
233 /* temp_var can be NULL if it was an exported function with a syntax
234 error (a different bug, but it still shouldn't dump core). */
235 if (temp_var && function_p (temp_var) == 0) /* XXX not yet */
236 {
237 CACHE_IMPORTSTR (temp_var, name);
238 }
239 }
240
241 /* If we got PWD from the environment, update our idea of the current
242 working directory. In any case, make sure that PWD exists before
243 checking it. It is possible for getcwd () to fail on shell startup,
244 and in that case, PWD would be undefined. */
245 temp_var = find_variable ("PWD");
246 if (temp_var && imported_p (temp_var) &&
247 (temp_string = value_cell (temp_var)) &&
248 same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL))
249 set_working_directory (temp_string);
250 else
251 {
252 temp_string = get_working_directory ("shell-init");
253 if (temp_string)
254 {
255 temp_var = bind_variable ("PWD", temp_string);
256 set_auto_export (temp_var);
257 free (temp_string);
258 }
259 }
260
261 /* According to the Single Unix Specification, v2, $OLDPWD is an
262 `environment variable' and therefore should be auto-exported.
263 Make a dummy invisible variable for OLDPWD, and mark it as exported. */
264 temp_var = bind_variable ("OLDPWD", (char *)NULL);
265 VSETATTR (temp_var, (att_exported | att_invisible));
266
267 /* Set up initial value of $_ */
268 temp_var = bind_variable ("_", dollar_vars[0]);
269
270 /* Remember this pid. */
271 dollar_dollar_pid = (int)getpid ();
272
273 /* Now make our own defaults in case the vars that we think are
274 important are missing. */
275 temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
276 set_auto_export (temp_var);
277
278 temp_var = set_if_not ("TERM", "dumb");
279 set_auto_export (temp_var);
280
281 #if defined (qnx)
282 /* set node id -- don't import it from the environment */
283 {
284 char node_name[22];
285 qnx_nidtostr (getnid (), node_name, sizeof (node_name));
286 temp_var = bind_variable ("NODE", node_name);
287 set_auto_export (temp_var);
288 }
289 #endif
290
291 /* set up the prompts. */
292 if (interactive_shell)
293 {
294 #if defined (PROMPT_STRING_DECODE)
295 set_if_not ("PS1", primary_prompt);
296 #else
297 if (current_user.uid == -1)
298 get_current_user_info ();
299 set_if_not ("PS1", current_user.euid == 0 ? "# " : primary_prompt);
300 #endif
301 set_if_not ("PS2", secondary_prompt);
302 }
303 set_if_not ("PS4", "+ ");
304
305 /* Don't allow IFS to be imported from the environment. */
306 temp_var = bind_variable ("IFS", " \t\n");
307
308 /* Magic machine types. Pretty convenient. */
309 temp_var = bind_variable ("HOSTTYPE", HOSTTYPE);
310 set_auto_export (temp_var);
311 temp_var = bind_variable ("OSTYPE", OSTYPE);
312 set_auto_export (temp_var);
313 temp_var = bind_variable ("MACHTYPE", MACHTYPE);
314 set_auto_export (temp_var);
315 temp_var = bind_variable ("HOSTNAME", current_host_name);
316 set_auto_export (temp_var);
317
318 /* Default MAILCHECK for interactive shells. Defer the creation of a
319 default MAILPATH until the startup files are read, because MAIL
320 names a mail file if MAILCHECK is not set, and we should provide a
321 default only if neither is set. */
322 if (interactive_shell)
323 set_if_not ("MAILCHECK", "60");
324
325 /* Do some things with shell level. */
326 initialize_shell_level ();
327
328 set_ppid ();
329
330 /* Initialize the `getopts' stuff. */
331 bind_variable ("OPTIND", "1");
332 getopts_reset (0);
333 bind_variable ("OPTERR", "1");
334 sh_opterr = 1;
335
336 if (login_shell == 1)
337 set_home_var ();
338
339 /* Get the full pathname to THIS shell, and set the BASH variable
340 to it. */
341 name = get_bash_name ();
342 temp_var = bind_variable ("BASH", name);
343 free (name);
344
345 /* Make the exported environment variable SHELL be the user's login
346 shell. Note that the `tset' command looks at this variable
347 to determine what style of commands to output; if it ends in "csh",
348 then C-shell commands are output, else Bourne shell commands. */
349 set_shell_var ();
350
351 /* Make a variable called BASH_VERSION which contains the version info. */
352 bind_variable ("BASH_VERSION", shell_version_string ());
353 #if defined (ARRAY_VARS)
354 make_vers_array ();
355 #endif
356
357 /* Find out if we're supposed to be in Posix.2 mode via an
358 environment variable. */
359 temp_var = find_variable ("POSIXLY_CORRECT");
360 if (!temp_var)
361 temp_var = find_variable ("POSIX_PEDANTIC");
362 if (temp_var && imported_p (temp_var))
363 sv_strict_posix (temp_var->name);
364
365 #if defined (HISTORY)
366 /* Set history variables to defaults, and then do whatever we would
367 do if the variable had just been set. Do this only in the case
368 that we are remembering commands on the history list. */
369 if (remember_on_history)
370 {
371 name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history");
372
373 set_if_not ("HISTFILE", name);
374 free (name);
375
376 set_if_not ("HISTSIZE", "500");
377 sv_histsize ("HISTSIZE");
378 }
379 #endif /* HISTORY */
380
381 /* Seed the random number generator. */
382 sbrand (dollar_dollar_pid + (long)shell_start_time);
383
384 /* Handle some "special" variables that we may have inherited from a
385 parent shell. */
386 if (interactive_shell)
387 {
388 temp_var = find_variable ("IGNOREEOF");
389 if (!temp_var)
390 temp_var = find_variable ("ignoreeof");
391 if (temp_var && imported_p (temp_var))
392 sv_ignoreeof (temp_var->name);
393 }
394
395 #if defined (HISTORY)
396 if (interactive_shell && remember_on_history)
397 {
398 sv_history_control ("HISTCONTROL");
399 sv_histignore ("HISTIGNORE");
400 }
401 #endif /* HISTORY */
402
403 temp_var = find_variable ("SSH_CLIENT");
404 if (temp_var && imported_p (temp_var))
405 {
406 VUNSETATTR (temp_var, att_exported);
407 array_needs_making = 1;
408 }
409
410 /* Get the user's real and effective user ids. */
411 uidset ();
412
413 /* Initialize the dynamic variables, and seed their values. */
414 initialize_dynamic_variables ();
415 }
416
417 /* Set $HOME to the information in the password file if we didn't get
418 it from the environment. */
419
420 /* This function is not static so the tilde and readline libraries can
421 use it. */
422 char *
423 get_home_dir ()
424 {
425 if (current_user.home_dir == 0)
426 get_current_user_info ();
427 return current_user.home_dir;
428 }
429
430 static void
431 set_home_var ()
432 {
433 SHELL_VAR *temp_var;
434
435 temp_var = find_variable ("HOME");
436 if (temp_var == 0)
437 temp_var = bind_variable ("HOME", get_home_dir ());
438 VSETATTR (temp_var, att_exported);
439 }
440
441 /* Set $SHELL to the user's login shell if it is not already set. Call
442 get_current_user_info if we haven't already fetched the shell. */
443 static void
444 set_shell_var ()
445 {
446 SHELL_VAR *temp_var;
447
448 temp_var = find_variable ("SHELL");
449 if (temp_var == 0)
450 {
451 if (current_user.shell == 0)
452 get_current_user_info ();
453 temp_var = bind_variable ("SHELL", current_user.shell);
454 }
455 VSETATTR (temp_var, att_exported);
456 }
457
458 static char *
459 get_bash_name ()
460 {
461 char *name;
462
463 if ((login_shell == 1) && (*shell_name != '/'))
464 {
465 if (current_user.shell == 0)
466 get_current_user_info ();
467 name = savestring (current_user.shell);
468 }
469 else if (*shell_name == '/')
470 name = savestring (shell_name);
471 else if (shell_name[0] == '.' && shell_name[1] == '/')
472 {
473 /* Fast path for common case. */
474 char *cdir;
475 int len;
476
477 cdir = get_string_value ("PWD");
478 len = strlen (cdir);
479 name = xmalloc (len + strlen (shell_name) + 1);
480 strcpy (name, cdir);
481 strcpy (name + len, shell_name + 1);
482 }
483 else
484 {
485 char *tname;
486 int s;
487
488 tname = find_user_command (shell_name);
489
490 if (tname == 0)
491 {
492 /* Try the current directory. If there is not an executable
493 there, just punt and use the login shell. */
494 s = file_status (shell_name);
495 if (s & FS_EXECABLE)
496 {
497 tname = make_absolute (shell_name, get_string_value ("PWD"));
498 if (*shell_name == '.')
499 {
500 name = canonicalize_pathname (tname);
501 if (name == 0)
502 name = tname;
503 else
504 free (tname);
505 }
506 else
507 name = tname;
508 }
509 else
510 {
511 if (current_user.shell == 0)
512 get_current_user_info ();
513 name = savestring (current_user.shell);
514 }
515 }
516 else
517 {
518 name = full_pathname (tname);
519 free (tname);
520 }
521 }
522
523 return (name);
524 }
525
526 void
527 adjust_shell_level (change)
528 int change;
529 {
530 char new_level[5], *old_SHLVL;
531 int old_level;
532 SHELL_VAR *temp_var;
533
534 old_SHLVL = get_string_value ("SHLVL");
535 old_level = old_SHLVL ? atoi (old_SHLVL) : 0;
536
537 shell_level = old_level + change;
538 if (shell_level < 0)
539 shell_level = 0;
540 else if (shell_level > 1000)
541 {
542 internal_warning ("shell level (%d) too high, resetting to 1", shell_level);
543 shell_level = 1;
544 }
545
546 /* We don't need the full generality of itos here. */
547 if (shell_level < 10)
548 {
549 new_level[0] = shell_level + '0';
550 new_level[1] = '\0';
551 }
552 else if (shell_level < 100)
553 {
554 new_level[0] = (shell_level / 10) + '0';
555 new_level[1] = (shell_level % 10) + '0';
556 new_level[2] = '\0';
557 }
558 else if (shell_level < 1000)
559 {
560 new_level[0] = (shell_level / 100) + '0';
561 old_level = shell_level % 100;
562 new_level[1] = (old_level / 10) + '0';
563 new_level[2] = (old_level % 10) + '0';
564 new_level[3] = '\0';
565 }
566
567 temp_var = bind_variable ("SHLVL", new_level);
568 set_auto_export (temp_var);
569 }
570
571 static void
572 initialize_shell_level ()
573 {
574 adjust_shell_level (1);
575 }
576
577 /* Make a variable $PPID, which holds the pid of the shell's parent. */
578 void
579 set_ppid ()
580 {
581 char namebuf[32], *name;
582 SHELL_VAR *temp_var;
583
584 name = inttostr ((int) getppid (), namebuf, sizeof(namebuf));
585 temp_var = find_variable ("PPID");
586 if (temp_var)
587 VUNSETATTR (temp_var, (att_readonly | att_exported));
588 temp_var = bind_variable ("PPID", name);
589 VSETATTR (temp_var, (att_readonly | att_integer));
590 }
591
592 static void
593 uidset ()
594 {
595 char buff[32], *b;
596 register SHELL_VAR *v;
597
598 b = inttostr (current_user.uid, buff, sizeof (buff));
599 v = find_variable ("UID");
600 if (v)
601 VUNSETATTR (v, att_readonly);
602
603 v = bind_variable ("UID", b);
604 VSETATTR (v, (att_readonly | att_integer));
605
606 if (current_user.euid != current_user.uid)
607 b = inttostr (current_user.euid, buff, sizeof (buff));
608
609 v = find_variable ("EUID");
610 if (v)
611 VUNSETATTR (v, att_readonly);
612
613 v = bind_variable ("EUID", b);
614 VSETATTR (v, (att_readonly | att_integer));
615 }
616
617 #if defined (ARRAY_VARS)
618 static void
619 make_vers_array ()
620 {
621 SHELL_VAR *vv;
622 ARRAY *av;
623 char *s, d[32];
624
625 makunbound ("BASH_VERSINFO", shell_variables);
626
627 vv = make_new_array_variable ("BASH_VERSINFO");
628 av = array_cell (vv);
629 strcpy (d, dist_version);
630 s = strchr (d, '.');
631 if (s)
632 *s++ = '\0';
633 array_add_element (av, 0, d);
634 array_add_element (av, 1, s);
635 s = inttostr (patch_level, d, sizeof (d));
636 array_add_element (av, 2, s);
637 s = inttostr (build_version, d, sizeof (d));
638 array_add_element (av, 3, s);
639 array_add_element (av, 4, release_status);
640 array_add_element (av, 5, MACHTYPE);
641
642 VSETATTR (vv, att_readonly);
643 }
644 #endif /* ARRAY_VARS */
645
646 /* Set the environment variables $LINES and $COLUMNS in response to
647 a window size change. */
648 void
649 set_lines_and_columns (lines, cols)
650 int lines, cols;
651 {
652 char val[32], *v;
653
654 v = inttostr (lines, val, sizeof (val));
655 bind_variable ("LINES", v);
656
657 v = inttostr (cols, val, sizeof (val));
658 bind_variable ("COLUMNS", v);
659 }
660
661 /* Set NAME to VALUE if NAME has no value. */
662 SHELL_VAR *
663 set_if_not (name, value)
664 char *name, *value;
665 {
666 SHELL_VAR *v;
667
668 v = find_variable (name);
669 if (v == 0)
670 v = bind_variable (name, value);
671 return (v);
672 }
673
674 /* Map FUNCTION over the variables in VARIABLES. Return an array of the
675 variables for which FUNCTION returns a non-zero value. A NULL value
676 for FUNCTION means to use all variables. */
677 SHELL_VAR **
678 map_over (function, var_hash_table)
679 Function *function;
680 HASH_TABLE* var_hash_table;
681 {
682 register int i;
683 register BUCKET_CONTENTS *tlist;
684 SHELL_VAR *var, **list;
685 int list_index, list_size;
686
687 list = (SHELL_VAR **)NULL;
688 for (i = list_index = list_size = 0; i < var_hash_table->nbuckets; i++)
689 {
690 tlist = get_hash_bucket (i, var_hash_table);
691
692 while (tlist)
693 {
694 var = (SHELL_VAR *)tlist->data;
695
696 if (!function || (*function) (var))
697 {
698 if (list_index + 1 >= list_size)
699 list = (SHELL_VAR **)
700 xrealloc (list, (list_size += 20) * sizeof (SHELL_VAR *));
701
702 list[list_index++] = var;
703 list[list_index] = (SHELL_VAR *)NULL;
704 }
705 tlist = tlist->next;
706 }
707 }
708 return (list);
709 }
710
711 void
712 sort_variables (array)
713 SHELL_VAR **array;
714 {
715 qsort (array, array_len ((char **)array), sizeof (SHELL_VAR *), qsort_var_comp);
716 }
717
718 static int
719 qsort_var_comp (var1, var2)
720 SHELL_VAR **var1, **var2;
721 {
722 int result;
723
724 if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0)
725 result = strcmp ((*var1)->name, (*var2)->name);
726
727 return (result);
728 }
729
730 /* Create a NULL terminated array of all the shell variables in TABLE. */
731 static SHELL_VAR **
732 all_vars (table)
733 HASH_TABLE *table;
734 {
735 SHELL_VAR **list;
736
737 list = map_over ((Function *)NULL, table);
738 if (list /* && posixly_correct */)
739 sort_variables (list);
740 return (list);
741 }
742
743 /* Create a NULL terminated array of all the shell variables. */
744 SHELL_VAR **
745 all_shell_variables ()
746 {
747 return (all_vars (shell_variables));
748 }
749
750 /* Create a NULL terminated array of all the shell functions. */
751 SHELL_VAR **
752 all_shell_functions ()
753 {
754 return (all_vars (shell_functions));
755 }
756
757 /* Print VARS to stdout in such a way that they can be read back in. */
758 void
759 print_var_list (list)
760 register SHELL_VAR **list;
761 {
762 register int i;
763 register SHELL_VAR *var;
764
765 for (i = 0; list && (var = list[i]); i++)
766 if (!invisible_p (var))
767 print_assignment (var);
768 }
769
770 #if defined (NOTDEF)
771 /* Print LIST (a linked list of shell variables) to stdout
772 by printing the names, without the values. Used to support the
773 `set +' command. */
774 void
775 print_vars_no_values (list)
776 register SHELL_VAR **list;
777 {
778 register int i;
779 register SHELL_VAR *var;
780
781 for (i = 0; list && (var = list[i]); i++)
782 if (!invisible_p (var))
783 printf ("%s\n", var->name);
784 }
785 #endif
786
787 /* Print the value of a single SHELL_VAR. No newline is
788 output, but the variable is printed in such a way that
789 it can be read back in. */
790 void
791 print_assignment (var)
792 SHELL_VAR *var;
793 {
794 if (function_p (var) && var->value)
795 {
796 printf ("%s=", var->name);
797 print_var_function (var);
798 printf ("\n");
799 }
800 #if defined (ARRAY_VARS)
801 else if (array_p (var) && var->value)
802 print_array_assignment (var, 0);
803 #endif /* ARRAY_VARS */
804 else if (var->value)
805 {
806 printf ("%s=", var->name);
807 print_var_value (var, 1);
808 printf ("\n");
809 }
810 }
811
812 /* Print the value cell of VAR, a shell variable. Do not print
813 the name, nor leading/trailing newline. If QUOTE is non-zero,
814 and the value contains shell metacharacters, quote the value
815 in such a way that it can be read back in. */
816 void
817 print_var_value (var, quote)
818 SHELL_VAR *var;
819 int quote;
820 {
821 char *t;
822
823 if (var->value)
824 {
825 if (quote && contains_shell_metas (var->value))
826 {
827 t = single_quote (var->value);
828 printf ("%s", t);
829 free (t);
830 }
831 else
832 printf ("%s", var->value);
833 }
834 }
835
836 /* Print the function cell of VAR, a shell variable. Do not
837 print the name, nor leading/trailing newline. */
838 void
839 print_var_function (var)
840 SHELL_VAR *var;
841 {
842 if (function_p (var) && var->value)
843 printf ("%s", named_function_string ((char *)NULL, function_cell(var), 1));
844 }
845
846 #if defined (ARRAY_VARS)
847 void
848 print_array_assignment (var, quoted)
849 SHELL_VAR *var;
850 int quoted;
851 {
852 char *vstr;
853
854 if (quoted)
855 vstr = quoted_array_assignment_string (array_cell (var));
856 else
857 vstr = array_to_assignment_string (array_cell (var));
858
859 if (vstr == 0)
860 printf ("%s=%s\n", var->name, quoted ? "'()'" : "()");
861 else
862 {
863 printf ("%s=%s\n", var->name, vstr);
864 free (vstr);
865 }
866 }
867 #endif /* ARRAY_VARS */
868
869 /* **************************************************************** */
870 /* */
871 /* Dynamic Variable Extension */
872 /* */
873 /* **************************************************************** */
874
875 /* DYNAMIC VARIABLES
876
877 These are variables whose values are generated anew each time they are
878 referenced. These are implemented using a pair of function pointers
879 in the struct variable: assign_func, which is called from bind_variable,
880 and dynamic_value, which is called from find_variable.
881
882 assign_func is called from bind_variable, if bind_variable discovers
883 that the variable being assigned to has such a function. The function
884 is called as
885 SHELL_VAR *temp = (*(entry->assign_func)) (entry, value)
886 and the (SHELL_VAR *)temp is returned as the value of bind_variable. It
887 is usually ENTRY (self).
888
889 dynamic_value is called from find_variable to return a `new' value for
890 the specified dynamic varible. If this function is NULL, the variable
891 is treated as a `normal' shell variable. If it is not, however, then
892 this function is called like this:
893 tempvar = (*(var->dynamic_value)) (var);
894
895 Sometimes `tempvar' will replace the value of `var'. Other times, the
896 shell will simply use the string value. Pretty object-oriented, huh?
897
898 Be warned, though: if you `unset' a special variable, it loses its
899 special meaning, even if you subsequently set it.
900
901 The special assignment code would probably have been better put in
902 subst.c: do_assignment, in the same style as
903 stupidly_hack_special_variables, but I wanted the changes as
904 localized as possible. */
905
906 static SHELL_VAR *
907 null_assign (self, value)
908 SHELL_VAR *self;
909 char *value;
910 {
911 return (self);
912 }
913
914 #if defined (ARRAY_VARS)
915 static SHELL_VAR *
916 null_array_assign (self, ind, value)
917 SHELL_VAR *self;
918 int ind;
919 char *value;
920 {
921 return (self);
922 }
923 #endif
924
925 /* The value of $SECONDS. This is the number of seconds since shell
926 invocation, or, the number of seconds since the last assignment + the
927 value of the last assignment. */
928 static long seconds_value_assigned;
929
930 static SHELL_VAR *
931 assign_seconds (self, value)
932 SHELL_VAR *self;
933 char *value;
934 {
935 seconds_value_assigned = strtol (value, (char **)NULL, 10);
936 shell_start_time = NOW;
937 return (self);
938 }
939
940 static SHELL_VAR *
941 get_seconds (var)
942 SHELL_VAR *var;
943 {
944 time_t time_since_start;
945 char *p;
946
947 time_since_start = NOW - shell_start_time;
948 p = itos((int) seconds_value_assigned + time_since_start);
949
950 FREE (var->value);
951
952 VSETATTR (var, att_integer);
953 var->value = p;
954 return (var);
955 }
956
957 /* The random number seed. You can change this by setting RANDOM. */
958 static unsigned long rseed = 1;
959 static unsigned long last_random_value;
960
961 /* A linear congruential random number generator based on the ANSI
962 C standard. This one isn't very good (the values are alternately
963 odd and even, for example), but a more complicated one is overkill. */
964
965 /* Returns a pseudo-random number between 0 and 32767. */
966 static int
967 brand ()
968 {
969 rseed = rseed * 1103515245 + 12345;
970 return ((unsigned int)(rseed & 32767)); /* was % 32768 */
971 }
972
973 /* Set the random number generator seed to SEED. */
974 static void
975 sbrand (seed)
976 int seed;
977 {
978 rseed = seed;
979 last_random_value = 0;
980 }
981
982 static SHELL_VAR *
983 assign_random (self, value)
984 SHELL_VAR *self;
985 char *value;
986 {
987 sbrand (atoi (value));
988 return (self);
989 }
990
991 static SHELL_VAR *
992 get_random (var)
993 SHELL_VAR *var;
994 {
995 int rv;
996 char *p;
997
998 /* Reset for command and process substitution. */
999 if (subshell_environment)
1000 sbrand (rseed + (int)(getpid() + NOW));
1001
1002 do
1003 rv = brand ();
1004 while (rv == (int)last_random_value);
1005
1006 last_random_value = rv;
1007 p = itos ((int)rv);
1008
1009 FREE (var->value);
1010
1011 VSETATTR (var, att_integer);
1012 var->value = p;
1013 return (var);
1014 }
1015
1016 /* Function which returns the current line number. */
1017 static SHELL_VAR *
1018 get_lineno (var)
1019 SHELL_VAR *var;
1020 {
1021 char *p;
1022 int ln;
1023
1024 ln = executing_line_number ();
1025 p = itos (ln);
1026 FREE (var->value);
1027 var->value = p;
1028 return (var);
1029 }
1030
1031 static SHELL_VAR *
1032 assign_lineno (var, value)
1033 SHELL_VAR *var;
1034 char *value;
1035 {
1036 line_number = atoi (value);
1037 return var;
1038 }
1039
1040 #if defined (HISTORY)
1041 static SHELL_VAR *
1042 get_histcmd (var)
1043 SHELL_VAR *var;
1044 {
1045 char *p;
1046
1047 p = itos (history_number ());
1048 FREE (var->value);
1049 var->value = p;
1050 return (var);
1051 }
1052 #endif
1053
1054 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1055 static SHELL_VAR *
1056 get_dirstack (self)
1057 SHELL_VAR *self;
1058 {
1059 ARRAY *a;
1060 WORD_LIST *l;
1061
1062 l = get_directory_stack ();
1063 a = word_list_to_array (l);
1064 dispose_array (array_cell (self));
1065 dispose_words (l);
1066 self->value = (char *)a;
1067 return self;
1068 }
1069
1070 static SHELL_VAR *
1071 assign_dirstack (self, ind, value)
1072 SHELL_VAR *self;
1073 int ind;
1074 char *value;
1075 {
1076 set_dirstack_element (ind, 1, value);
1077 return self;
1078 }
1079 #endif /* PUSHD AND POPD && ARRAY_VARS */
1080
1081 #if defined (ARRAY_VARS)
1082 /* We don't want to initialize the group set with a call to getgroups()
1083 unless we're asked to, but we only want to do it once. */
1084 static SHELL_VAR *
1085 get_groupset (self)
1086 SHELL_VAR *self;
1087 {
1088 register int i;
1089 int ng;
1090 ARRAY *a;
1091 static char **group_set = (char **)NULL;
1092
1093 if (group_set == 0)
1094 {
1095 group_set = get_group_list (&ng);
1096 a = array_cell (self);
1097 for (i = 0; i < ng; i++)
1098 array_add_element (a, i, group_set[i]);
1099 }
1100 return (self);
1101 }
1102 #endif /* ARRAY_VARS */
1103
1104 static SHELL_VAR *
1105 get_funcname (self)
1106 SHELL_VAR *self;
1107 {
1108 if (variable_context && this_shell_function)
1109 {
1110 FREE (self->value);
1111 self->value = savestring (this_shell_function->name);
1112 }
1113 return (self);
1114 }
1115
1116 void
1117 make_funcname_visible (on_or_off)
1118 int on_or_off;
1119 {
1120 SHELL_VAR *v;
1121
1122 v = find_variable ("FUNCNAME");
1123 if (v == 0 || v->dynamic_value == 0)
1124 return;
1125
1126 if (on_or_off)
1127 VUNSETATTR (v, att_invisible);
1128 else
1129 VSETATTR (v, att_invisible);
1130 }
1131
1132 #define INIT_DYNAMIC_VAR(var, val, gfunc, afunc) \
1133 do \
1134 { \
1135 v = bind_variable (var, val); \
1136 v->dynamic_value = gfunc; \
1137 v->assign_func = afunc; \
1138 } while (0)
1139
1140 #define INIT_DYNAMIC_ARRAY_VAR(var, gfunc, afunc) \
1141 do \
1142 { \
1143 v = make_new_array_variable (var); \
1144 v->dynamic_value = gfunc; \
1145 v->assign_func = afunc; \
1146 } while (0)
1147
1148 static void
1149 initialize_dynamic_variables ()
1150 {
1151 SHELL_VAR *v;
1152
1153 INIT_DYNAMIC_VAR ("SECONDS", (char *)NULL, get_seconds, assign_seconds);
1154 INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random);
1155 INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
1156
1157 #if defined (HISTORY)
1158 INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (DYNAMIC_FUNC *)NULL);
1159 #endif
1160
1161 #if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
1162 INIT_DYNAMIC_ARRAY_VAR ("DIRSTACK", get_dirstack, assign_dirstack);
1163 #endif /* PUSHD_AND_POPD && ARRAY_VARS */
1164
1165 #if defined (ARRAY_VARS)
1166 INIT_DYNAMIC_ARRAY_VAR ("GROUPS", get_groupset, null_array_assign);
1167 #endif
1168
1169 INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
1170 VSETATTR (v, att_invisible);
1171 }
1172
1173 /* How to get a pointer to the shell variable or function named NAME.
1174 HASHED_VARS is a pointer to the hash table containing the list
1175 of interest (either variables or functions). */
1176 SHELL_VAR *
1177 var_lookup (name, hashed_vars)
1178 char *name;
1179 HASH_TABLE *hashed_vars;
1180 {
1181 BUCKET_CONTENTS *bucket;
1182
1183 bucket = find_hash_item (name, hashed_vars);
1184 return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
1185 }
1186
1187 /* Look up the variable entry named NAME. If SEARCH_TEMPENV is non-zero,
1188 then also search the temporarily built list of exported variables. */
1189 SHELL_VAR *
1190 find_variable_internal (name, search_tempenv)
1191 char *name;
1192 int search_tempenv;
1193 {
1194 SHELL_VAR *var = (SHELL_VAR *)NULL;
1195
1196 /* If explicitly requested, first look in the temporary environment for
1197 the variable. This allows constructs such as "foo=x eval 'echo $foo'"
1198 to get the `exported' value of $foo. This happens if we are executing
1199 a function or builtin, or if we are looking up a variable in a
1200 "subshell environment". */
1201 if ((search_tempenv || subshell_environment) &&
1202 (temporary_env || builtin_env || function_env))
1203 var = find_tempenv_variable (name);
1204
1205 if (!var)
1206 var = var_lookup (name, shell_variables);
1207
1208 if (!var)
1209 return ((SHELL_VAR *)NULL);
1210
1211 return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
1212 }
1213
1214 /* Look up the variable entry named NAME. Returns the entry or NULL. */
1215 SHELL_VAR *
1216 find_variable (name)
1217 char *name;
1218 {
1219 return (find_variable_internal
1220 (name, (variable_context || this_shell_builtin || builtin_env)));
1221 }
1222
1223 /* Look up the function entry whose name matches STRING.
1224 Returns the entry or NULL. */
1225 SHELL_VAR *
1226 find_function (name)
1227 char *name;
1228 {
1229 return (var_lookup (name, shell_functions));
1230 }
1231
1232 /* Return the string value of a variable. Return NULL if the variable
1233 doesn't exist, or only has a function as a value. Don't cons a new
1234 string. This is a potential memory leak if the variable is found
1235 in the temporary environment. */
1236 char *
1237 get_string_value (var_name)
1238 char *var_name;
1239 {
1240 SHELL_VAR *var;
1241
1242 var = find_variable (var_name);
1243
1244 if (!var)
1245 return (char *)NULL;
1246 #if defined (ARRAY_VARS)
1247 else if (array_p (var))
1248 return (array_reference (array_cell (var), 0));
1249 #endif
1250 else
1251 return (var->value);
1252 }
1253
1254 /* This is present for use by the tilde and readline libraries. */
1255 char *
1256 get_env_value (v)
1257 char *v;
1258 {
1259 return get_string_value (v);
1260 }
1261
1262 /* Create a local variable referenced by NAME. */
1263 SHELL_VAR *
1264 make_local_variable (name)
1265 char *name;
1266 {
1267 SHELL_VAR *new_var, *old_var;
1268 BUCKET_CONTENTS *elt;
1269
1270 /* local foo; local foo; is a no-op. */
1271 old_var = find_variable (name);
1272 if (old_var && old_var->context == variable_context)
1273 return (old_var);
1274
1275 /* Since this is called only from the local/declare/typeset code, we can
1276 call builtin_error here without worry (of course, it will also work
1277 for anything that sets this_command_name). */
1278 if (old_var && readonly_p (old_var))
1279 {
1280 builtin_error ("%s: readonly variable");
1281 return ((SHELL_VAR *)NULL);
1282 }
1283
1284 elt = remove_hash_item (name, shell_variables);
1285 if (elt)
1286 {
1287 old_var = (SHELL_VAR *)elt->data;
1288 free (elt->key);
1289 free (elt);
1290 }
1291 else
1292 old_var = (SHELL_VAR *)NULL;
1293
1294 /* If a variable does not already exist with this name, then
1295 just make a new one. */
1296 if (old_var == 0)
1297 new_var = bind_variable (name, "");
1298 else
1299 {
1300 new_var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1301
1302 new_var->name = savestring (name);
1303 new_var->value = xmalloc (1);
1304 new_var->value[0] = '\0';
1305
1306 CLEAR_EXPORTSTR (new_var);
1307
1308 new_var->dynamic_value = (DYNAMIC_FUNC *)NULL;
1309 new_var->assign_func = (DYNAMIC_FUNC *)NULL;
1310
1311 new_var->attributes = exported_p (old_var) ? att_exported : 0;
1312
1313 new_var->prev_context = old_var;
1314 elt = add_hash_item (savestring (name), shell_variables);
1315 elt->data = (char *)new_var;
1316 }
1317
1318 new_var->context = variable_context;
1319 VSETATTR (new_var, att_local);
1320
1321 /* XXX */
1322 if (variable_context >= local_variable_stack_size)
1323 {
1324 int old_size = local_variable_stack_size;
1325 RESIZE_MALLOCED_BUFFER (have_local_variables, variable_context, 1,
1326 local_variable_stack_size, 8);
1327 bzero ((char *)have_local_variables + old_size,
1328 local_variable_stack_size - old_size);
1329 }
1330 have_local_variables[variable_context] = 1; /* XXX */
1331
1332 return (new_var);
1333 }
1334
1335 #if defined (ARRAY_VARS)
1336 SHELL_VAR *
1337 make_local_array_variable (name)
1338 char *name;
1339 {
1340 SHELL_VAR *var;
1341 ARRAY *array;
1342
1343 var = make_local_variable (name);
1344 if (var == 0)
1345 return var;
1346 array = new_array ();
1347
1348 FREE (value_cell(var));
1349 var->value = (char *)array;
1350 VSETATTR (var, att_array);
1351 return var;
1352 }
1353 #endif /* ARRAY_VARS */
1354
1355 /* Create a new shell variable with name NAME and add it to the hash table
1356 of shell variables. */
1357 static
1358 SHELL_VAR *
1359 make_new_variable (name)
1360 char *name;
1361 {
1362 SHELL_VAR *entry;
1363 BUCKET_CONTENTS *elt;
1364
1365 entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
1366
1367 entry->attributes = 0;
1368 entry->name = savestring (name);
1369 entry->value = (char *)NULL;
1370 CLEAR_EXPORTSTR (entry);
1371
1372 entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
1373 entry->assign_func = (DYNAMIC_FUNC *)NULL;
1374
1375 /* Always assume variables are to be made at toplevel!
1376 make_local_variable has the responsibilty of changing the
1377 variable context. */
1378 entry->context = 0;
1379 entry->prev_context = (SHELL_VAR *)NULL;
1380
1381 elt = add_hash_item (savestring (name), shell_variables);
1382 elt->data = (char *)entry;
1383
1384 return entry;
1385 }
1386
1387 #if defined (ARRAY_VARS)
1388 SHELL_VAR *
1389 make_new_array_variable (name)
1390 char *name;
1391 {
1392 SHELL_VAR *entry;
1393 ARRAY *array;
1394
1395 entry = make_new_variable (name);
1396 array = new_array ();
1397 entry->value = (char *)array;
1398 VSETATTR (entry, att_array);
1399 return entry;
1400 }
1401 #endif
1402
1403 char *
1404 make_variable_value (var, value)
1405 SHELL_VAR *var;
1406 char *value;
1407 {
1408 char *retval;
1409 long lval;
1410 int expok;
1411
1412 /* If this variable has had its type set to integer (via `declare -i'),
1413 then do expression evaluation on it and store the result. The
1414 functions in expr.c (evalexp and bind_int_variable) are responsible
1415 for turning off the integer flag if they don't want further
1416 evaluation done. */
1417 if (integer_p (var))
1418 {
1419 lval = evalexp (value, &expok);
1420 if (expok == 0)
1421 jump_to_top_level (DISCARD);
1422 retval = itos (lval);
1423 }
1424 else if (value)
1425 {
1426 if (*value)
1427 retval = savestring (value);
1428 else
1429 {
1430 retval = xmalloc (1);
1431 retval[0] = '\0';
1432 }
1433 }
1434 else
1435 retval = (char *)NULL;
1436
1437 return retval;
1438 }
1439
1440 /* Bind a variable NAME to VALUE. This conses up the name
1441 and value strings. */
1442 SHELL_VAR *
1443 bind_variable (name, value)
1444 char *name, *value;
1445 {
1446 char *newval;
1447 SHELL_VAR *entry;
1448
1449 entry = var_lookup (name, shell_variables);
1450
1451 if (entry == 0)
1452 {
1453 entry = make_new_variable (name);
1454 entry->value = make_variable_value (entry, value);
1455 }
1456 #if defined (ARRAY_VARS)
1457 else if (entry->assign_func && array_p (entry) == 0)
1458 #else
1459 else if (entry->assign_func)
1460 #endif
1461 {
1462 INVALIDATE_EXPORTSTR (entry);
1463 return ((*(entry->assign_func)) (entry, value));
1464 }
1465 else
1466 {
1467 if (readonly_p (entry))
1468 {
1469 report_error ("%s: readonly variable", name);
1470 return (entry);
1471 }
1472
1473 /* Variables which are bound are visible. */
1474 VUNSETATTR (entry, att_invisible);
1475
1476 newval = make_variable_value (entry, value);
1477
1478 /* Invalidate any cached export string */
1479 INVALIDATE_EXPORTSTR (entry);
1480
1481 #if defined (ARRAY_VARS)
1482 /* XXX -- this bears looking at again -- XXX */
1483 /* If an existing array variable x is being assigned to with x=b or
1484 `read x' or something of that nature, silently convert it to
1485 x[0]=b or `read x[0]'. */
1486 if (array_p (entry))
1487 {
1488 array_add_element (array_cell (entry), 0, newval);
1489 free (newval);
1490 }
1491 else
1492 {
1493 FREE (entry->value);
1494 entry->value = newval;
1495 }
1496 #else
1497 FREE (entry->value);
1498 entry->value = newval;
1499 #endif
1500 }
1501
1502 if (mark_modified_vars)
1503 VSETATTR (entry, att_exported);
1504
1505 if (exported_p (entry))
1506 array_needs_making = 1;
1507
1508 return (entry);
1509 }
1510
1511 /* Make VAR, a simple shell variable, have value VALUE. Once assigned a
1512 value, variables are no longer invisible. This is a duplicate of part
1513 of the internals of bind_variable. If the variable is exported, or
1514 all modified variables should be exported, mark the variable for export
1515 and note that the export environment needs to be recreated. */
1516 SHELL_VAR *
1517 bind_variable_value (var, value)
1518 SHELL_VAR *var;
1519 char *value;
1520 {
1521 char *t;
1522
1523 VUNSETATTR (var, att_invisible);
1524
1525 t = make_variable_value (var, value);
1526 FREE (var->value);
1527 var->value = t;
1528
1529 INVALIDATE_EXPORTSTR (var);
1530
1531 if (mark_modified_vars)
1532 VSETATTR (var, att_exported);
1533
1534 if (exported_p (var))
1535 array_needs_making = 1;
1536
1537 return (var);
1538 }
1539
1540 /* Bind/create a shell variable with the name LHS to the RHS.
1541 This creates or modifies a variable such that it is an integer.
1542
1543 This used to be in expr.c, but it is here so that all of the
1544 variable binding stuff is localized. Since we don't want any
1545 recursive evaluation from bind_variable() (possible without this code,
1546 since bind_variable() calls the evaluator for variables with the integer
1547 attribute set), we temporarily turn off the integer attribute for each
1548 variable we set here, then turn it back on after binding as necessary. */
1549
1550 SHELL_VAR *
1551 bind_int_variable (lhs, rhs)
1552 char *lhs, *rhs;
1553 {
1554 register SHELL_VAR *v;
1555 int isint;
1556
1557 isint = 0;
1558 v = find_variable (lhs);
1559 if (v)
1560 {
1561 isint = integer_p (v);
1562 VUNSETATTR (v, att_integer);
1563 }
1564
1565 v = bind_variable (lhs, rhs);
1566 if (isint)
1567 VSETATTR (v, att_integer);
1568
1569 return (v);
1570 }
1571
1572 #if defined (ARRAY_VARS)
1573 /* Convert a shell variable to an array variable. The original value is
1574 saved as array[0]. */
1575 SHELL_VAR *
1576 convert_var_to_array (var)
1577 SHELL_VAR *var;
1578 {
1579 char *oldval;
1580 ARRAY *array;
1581
1582 oldval = value_cell (var);
1583 array = new_array ();
1584 array_add_element (array, 0, oldval);
1585
1586 FREE (value_cell (var));
1587 var->value = (char *)array;
1588
1589 INVALIDATE_EXPORTSTR (var);
1590
1591 VSETATTR (var, att_array);
1592 VUNSETATTR (var, att_invisible);
1593
1594 return var;
1595 }
1596
1597 /* Perform an array assignment name[ind]=value. If NAME already exists and
1598 is not an array, and IND is 0, perform name=value instead. If NAME exists
1599 and is not an array, and IND is not 0, convert it into an array with the
1600 existing value as name[0].
1601
1602 If NAME does not exist, just create an array variable, no matter what
1603 IND's value may be. */
1604 SHELL_VAR *
1605 bind_array_variable (name, ind, value)
1606 char *name;
1607 int ind;
1608 char *value;
1609 {
1610 SHELL_VAR *entry;
1611 char *newval;
1612
1613 entry = var_lookup (name, shell_variables);
1614
1615 if (entry == (SHELL_VAR *) 0)
1616 entry = make_new_array_variable (name);
1617 else if (readonly_p (entry))
1618 {
1619 report_error ("%s: readonly variable", name);
1620 return (entry);
1621 }
1622 else if (array_p (entry) == 0)
1623 entry = convert_var_to_array (entry);
1624
1625 /* ENTRY is an array variable, and ARRAY points to the value. */
1626 newval = make_variable_value (entry, value);
1627 if (entry->assign_func)
1628 (*entry->assign_func) (entry, ind, newval);
1629 else
1630 array_add_element (array_cell (entry), ind, newval);
1631 FREE (newval);
1632
1633 return (entry);
1634 }
1635
1636 /* Perform a compound assignment statement for array NAME, where VALUE is
1637 the text between the parens: NAME=( VALUE ) */
1638 SHELL_VAR *
1639 assign_array_from_string (name, value)
1640 char *name, *value;
1641 {
1642 SHELL_VAR *var;
1643
1644 var = find_variable (name);
1645 if (var == 0)
1646 var = make_new_array_variable (name);
1647 else if (readonly_p (var))
1648 {
1649 report_error ("%s: readonly variable", name);
1650 return ((SHELL_VAR *)NULL);
1651 }
1652 else if (array_p (var) == 0)
1653 var = convert_var_to_array (var);
1654
1655 return (assign_array_var_from_string (var, value));
1656 }
1657
1658 SHELL_VAR *
1659 assign_array_var_from_word_list (var, list)
1660 SHELL_VAR *var;
1661 WORD_LIST *list;
1662 {
1663 register int i;
1664 register WORD_LIST *l;
1665 ARRAY *a;
1666
1667 for (a = array_cell (var), l = list, i = 0; l; l = l->next, i++)
1668 if (var->assign_func)
1669 (*var->assign_func) (var, i, l->word->word);
1670 else
1671 array_add_element (a, i, l->word->word);
1672 return var;
1673 }
1674
1675 /* For each word in a compound array assignment, if the word looks like
1676 [ind]=value, quote the `[' and `]' before the `=' to protect them from
1677 unwanted filename expansion. */
1678 static void
1679 quote_array_assignment_chars (list)
1680 WORD_LIST *list;
1681 {
1682 char *s, *t, *nword;
1683 int saw_eq;
1684 WORD_LIST *l;
1685
1686 for (l = list; l; l = l->next)
1687 {
1688 if (l->word == 0 || l->word->word == 0 || l->word->word[0] == '\0')
1689 continue; /* should not happen, but just in case... */
1690 /* Don't bother if it doesn't look like [ind]=value */
1691 if (l->word->word[0] != '[' || strchr (l->word->word, '=') == 0) /* ] */
1692 continue;
1693 s = nword = xmalloc (strlen (l->word->word) * 2 + 1);
1694 saw_eq = 0;
1695 for (t = l->word->word; *t; )
1696 {
1697 if (*t == '=')
1698 saw_eq = 1;
1699 if (saw_eq == 0 && (*t == '[' || *t == ']'))
1700 *s++ = '\\';
1701 *s++ = *t++;
1702 }
1703 *s = '\0';
1704 free (l->word->word);
1705 l->word->word = nword;
1706 }
1707 }
1708
1709 /* Perform a compound array assignment: VAR->name=( VALUE ). The
1710 VALUE has already had the parentheses stripped. */
1711 SHELL_VAR *
1712 assign_array_var_from_string (var, value)
1713 SHELL_VAR *var;
1714 char *value;
1715 {
1716 ARRAY *a;
1717 WORD_LIST *list, *nlist;
1718 char *w, *val, *nval;
1719 int ni, len, ind, last_ind;
1720
1721 if (value == 0)
1722 return var;
1723
1724 /* If this is called from declare_builtin, value[0] == '(' and
1725 strchr(value, ')') != 0. In this case, we need to extract
1726 the value from between the parens before going on. */
1727 if (*value == '(') /*)*/
1728 {
1729 ni = 1;
1730 val = extract_array_assignment_list (value, &ni);
1731 if (val == 0)
1732 return var;
1733 }
1734 else
1735 val = value;
1736
1737 /* Expand the value string into a list of words, performing all the
1738 shell expansions including pathname generation and word splitting. */
1739 /* First we split the string on whitespace, using the shell parser
1740 (ksh93 seems to do this). */
1741 list = parse_string_to_word_list (val, "array assign");
1742
1743 /* If we're using [subscript]=value, we need to quote each [ and ] to
1744 prevent unwanted filename expansion. */
1745 if (list)
1746 quote_array_assignment_chars (list);
1747
1748 /* Now that we've split it, perform the shell expansions on each
1749 word in the list. */
1750 nlist = list ? expand_words_no_vars (list) : (WORD_LIST *)NULL;
1751
1752 dispose_words (list);
1753
1754 if (val != value)
1755 free (val);
1756
1757 a = array_cell (var);
1758
1759 /* Now that we are ready to assign values to the array, kill the existing
1760 value. */
1761 if (a)
1762 empty_array (a);
1763
1764 for (last_ind = 0, list = nlist; list; list = list->next)
1765 {
1766 w = list->word->word;
1767
1768 /* We have a word of the form [ind]=value */
1769 if (w[0] == '[')
1770 {
1771 len = skipsubscript (w, 0);
1772
1773 if (w[len] != ']' || w[len+1] != '=')
1774 {
1775 nval = make_variable_value (var, w);
1776 if (var->assign_func)
1777 (*var->assign_func) (var, last_ind, nval);
1778 else
1779 array_add_element (a, last_ind, nval);
1780 FREE (nval);
1781 last_ind++;
1782 continue;
1783 }
1784
1785 if (len == 1)
1786 {
1787 report_error ("%s: bad array subscript", w);
1788 continue;
1789 }
1790
1791 if (ALL_ELEMENT_SUB (w[1]) && len == 2)
1792 {
1793 report_error ("%s: cannot assign to non-numeric index", w);
1794 continue;
1795 }
1796
1797 ind = array_expand_index (w + 1, len);
1798 if (ind < 0)
1799 {
1800 report_error ("%s: bad array subscript", w);
1801 continue;
1802 }
1803 last_ind = ind;
1804 val = w + len + 2;
1805 }
1806 else /* No [ind]=value, just a stray `=' */
1807 {
1808 ind = last_ind;
1809 val = w;
1810 }
1811
1812 if (integer_p (var))
1813 this_command_name = (char *)NULL; /* no command name for errors */
1814 nval = make_variable_value (var, val);
1815 if (var->assign_func)
1816 (*var->assign_func) (var, ind, nval);
1817 else
1818 array_add_element (a, ind, nval);
1819 FREE (nval);
1820 last_ind++;
1821 }
1822
1823 dispose_words (nlist);
1824 return (var);
1825 }
1826 #endif /* ARRAY_VARS */
1827
1828 /* Dispose of the information attached to VAR. */
1829 void
1830 dispose_variable (var)
1831 SHELL_VAR *var;
1832 {
1833 if (!var)
1834 return;
1835
1836 if (function_p (var))
1837 dispose_command (function_cell (var));
1838 #if defined (ARRAY_VARS)
1839 else if (array_p (var))
1840 dispose_array (array_cell (var));
1841 #endif
1842 else
1843 FREE (value_cell (var));
1844
1845 FREE_EXPORTSTR (var);
1846
1847 free (var->name);
1848
1849 if (exported_p (var))
1850 array_needs_making = 1;
1851
1852 free (var);
1853 }
1854
1855 #if defined (ARRAY_VARS)
1856 /* This function is called with SUB pointing to just after the beginning
1857 `[' of an array subscript. */
1858 int
1859 unbind_array_element (var, sub)
1860 SHELL_VAR *var;
1861 char *sub;
1862 {
1863 int len, ind;
1864 ARRAY_ELEMENT *ae;
1865
1866 len = skipsubscript (sub, 0);
1867 if (sub[len] != ']' || len == 0)
1868 {
1869 builtin_error ("%s[%s: bad array subscript", var->name, sub);
1870 return -1;
1871 }
1872 sub[len] = '\0';
1873
1874 if (ALL_ELEMENT_SUB (sub[0]) && sub[1] == 0)
1875 {
1876 makunbound (var->name, shell_variables);
1877 return (0);
1878 }
1879 ind = array_expand_index (sub, len+1);
1880 if (ind < 0)
1881 {
1882 builtin_error ("[%s]: bad array subscript", sub);
1883 return -1;
1884 }
1885 ae = array_delete_element (array_cell (var), ind);
1886 if (ae)
1887 destroy_array_element (ae);
1888 return 0;
1889 }
1890 #endif
1891
1892 /* Unset the variable referenced by NAME. */
1893 int
1894 unbind_variable (name)
1895 char *name;
1896 {
1897 SHELL_VAR *var;
1898
1899 var = find_variable (name);
1900 if (!var)
1901 return (-1);
1902
1903 /* This function should never be called with an array variable name. */
1904 #if defined (ARRAY_VARS)
1905 if (array_p (var) == 0 && var->value)
1906 #else
1907 if (var->value)
1908 #endif
1909 {
1910 free (var->value);
1911 var->value = (char *)NULL;
1912 }
1913
1914 makunbound (name, shell_variables);
1915
1916 return (0);
1917 }
1918
1919 /* Make the variable associated with NAME go away. HASH_LIST is the
1920 hash table from which this variable should be deleted (either
1921 shell_variables or shell_functions).
1922 Returns non-zero if the variable couldn't be found. */
1923 int
1924 makunbound (name, hash_list)
1925 char *name;
1926 HASH_TABLE *hash_list;
1927 {
1928 BUCKET_CONTENTS *elt, *new_elt;
1929 SHELL_VAR *old_var, *new_var;
1930 char *t;
1931
1932 elt = remove_hash_item (name, hash_list);
1933
1934 if (elt == 0)
1935 return (-1);
1936
1937 old_var = (SHELL_VAR *)elt->data;
1938 new_var = old_var->prev_context;
1939
1940 if (old_var && exported_p (old_var))
1941 array_needs_making++;
1942
1943 #if defined (PROGRAMMABLE_COMPLETION)
1944 if (hash_list == shell_functions)
1945 set_itemlist_dirty (&it_functions);
1946 #endif
1947
1948 /* If we're unsetting a local variable and we're still executing inside
1949 the function, just mark the variable as invisible.
1950 kill_all_local_variables will clean it up later. This must be done
1951 so that if the variable is subsequently assigned a new value inside
1952 the function, the `local' attribute is still present. We also need
1953 to add it back into the correct hash table. */
1954 if (old_var && local_p (old_var) && variable_context == old_var->context)
1955 {
1956 VSETATTR (old_var, att_invisible);
1957 INVALIDATE_EXPORTSTR (old_var);
1958 new_elt = add_hash_item (savestring (old_var->name), hash_list);
1959 new_elt->data = (char *)old_var;
1960 stupidly_hack_special_variables (old_var->name);
1961 free (elt->key);
1962 free (elt);
1963 return (0);
1964 }
1965
1966 if (new_var)
1967 {
1968 /* Has to be a variable, functions don't have previous contexts. */
1969 new_elt = add_hash_item (savestring (new_var->name), hash_list);
1970 new_elt->data = (char *)new_var;
1971
1972 if (exported_p (new_var))
1973 set_auto_export (new_var);
1974 }
1975
1976 /* Have to save a copy of name here, because it might refer to
1977 old_var->name. If so, stupidly_hack_special_variables will
1978 reference freed memory. */
1979 t = savestring (name);
1980
1981 free (elt->key);
1982 free (elt);
1983
1984 dispose_variable (old_var);
1985 stupidly_hack_special_variables (t);
1986 free (t);
1987 return (0);
1988 }
1989
1990 #ifdef INCLUDE_UNUSED
1991 /* Remove the variable with NAME if it is a local variable in the
1992 current context. */
1993 int
1994 kill_local_variable (name)
1995 char *name;
1996 {
1997 SHELL_VAR *temp;
1998
1999 temp = find_variable (name);
2000 if (temp && temp->context == variable_context)
2001 {
2002 makunbound (name, shell_variables);
2003 return (0);
2004 }
2005 return (-1);
2006 }
2007 #endif
2008
2009 /* Get rid of all of the variables in the current context. */
2010 int
2011 variable_in_context (var)
2012 SHELL_VAR *var;
2013 {
2014 return (var && var->context == variable_context);
2015 }
2016
2017 void
2018 kill_all_local_variables ()
2019 {
2020 register int i, pass;
2021 register SHELL_VAR *var, **list;
2022 HASH_TABLE *varlist;
2023
2024 /* If HAVE_LOCAL_VARIABLES == 0, it means that we don't have any local
2025 variables at all. If VARIABLE_CONTEXT >= LOCAL_VARIABLE_STACK_SIZE,
2026 it means that we have some local variables, but not in this variable
2027 context (level of function nesting). Also, if
2028 HAVE_LOCAL_VARIABLES[VARIABLE_CONTEXT] == 0, we have no local variables
2029 at this context. */
2030 if (have_local_variables == 0 ||
2031 variable_context >= local_variable_stack_size ||
2032 have_local_variables[variable_context] == 0)
2033 return;
2034
2035 for (pass = 0; pass < 2; pass++)
2036 {
2037 varlist = pass ? shell_functions : shell_variables;
2038
2039 list = map_over (variable_in_context, varlist);
2040
2041 if (list)
2042 {
2043 for (i = 0; var = list[i]; i++)
2044 {
2045 VUNSETATTR (var, att_local);
2046 makunbound (var->name, varlist);
2047 }
2048 free (list);
2049 }
2050 }
2051
2052 have_local_variables[variable_context] = 0; /* XXX */
2053 }
2054
2055 static void
2056 free_variable_hash_data (data)
2057 char *data;
2058 {
2059 SHELL_VAR *var, *prev;
2060
2061 var = (SHELL_VAR *)data;
2062 while (var)
2063 {
2064 prev = var->prev_context;
2065 dispose_variable (var);
2066 var = prev;
2067 }
2068 }
2069
2070 /* Delete the entire contents of the hash table. */
2071 void
2072 delete_all_variables (hashed_vars)
2073 HASH_TABLE *hashed_vars;
2074 {
2075 flush_hash_table (hashed_vars, free_variable_hash_data);
2076 }
2077
2078 static SHELL_VAR *
2079 new_shell_variable (name)
2080 char *name;
2081 {
2082 SHELL_VAR *var;
2083
2084 var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
2085
2086 bzero ((char *)var, sizeof (SHELL_VAR));
2087 var->name = savestring (name);
2088 return (var);
2089 }
2090
2091 /* Do a function binding to a variable. You pass the name and
2092 the command to bind to. This conses the name and command. */
2093 SHELL_VAR *
2094 bind_function (name, value)
2095 char *name;
2096 COMMAND *value;
2097 {
2098 SHELL_VAR *entry;
2099
2100 entry = find_function (name);
2101 if (!entry)
2102 {
2103 BUCKET_CONTENTS *elt;
2104
2105 elt = add_hash_item (savestring (name), shell_functions);
2106
2107 entry = new_shell_variable (name);
2108 entry->dynamic_value = entry->assign_func = (DYNAMIC_FUNC *)NULL;
2109 CLEAR_EXPORTSTR (entry);
2110
2111 /* Functions are always made at the top level. This allows a
2112 function to define another function (like autoload). */
2113 entry->context = 0;
2114
2115 elt->data = (char *)entry;
2116 }
2117
2118 INVALIDATE_EXPORTSTR (entry);
2119
2120 if (entry->value)
2121 dispose_command ((COMMAND *)entry->value);
2122
2123 entry->value = value ? (char *)copy_command (value) : (char *)NULL;
2124 VSETATTR (entry, att_function);
2125
2126 if (mark_modified_vars)
2127 VSETATTR (entry, att_exported);
2128
2129 VUNSETATTR (entry, att_invisible); /* Just to be sure */
2130
2131 if (exported_p (entry))
2132 array_needs_making = 1;
2133
2134 #if defined (PROGRAMMABLE_COMPLETION)
2135 set_itemlist_dirty (&it_functions);
2136 #endif
2137
2138 return (entry);
2139 }
2140
2141 #ifdef INCLUDE_UNUSED
2142 /* Copy VAR to a new data structure and return that structure. */
2143 SHELL_VAR *
2144 copy_variable (var)
2145 SHELL_VAR *var;
2146 {
2147 SHELL_VAR *copy = (SHELL_VAR *)NULL;
2148
2149 if (var)
2150 {
2151 copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
2152
2153 copy->attributes = var->attributes;
2154 copy->name = savestring (var->name);
2155
2156 if (function_p (var))
2157 copy->value = (char *)copy_command (function_cell (var));
2158 #if defined (ARRAY_VARS)
2159 else if (array_p (var))
2160 copy->value = (char *)dup_array (array_cell (var));
2161 #endif
2162 else if (value_cell (var))
2163 copy->value = savestring (value_cell (var));
2164 else
2165 copy->value = (char *)NULL;
2166
2167 copy->dynamic_value = var->dynamic_value;
2168 copy->assign_func = var->assign_func;
2169
2170 copy->exportstr = COPY_EXPORTSTR (var);
2171
2172 copy->context = var->context;
2173
2174 /* Don't bother copying previous contexts along with this variable. */
2175 copy->prev_context = (SHELL_VAR *)NULL;
2176 }
2177 return (copy);
2178 }
2179 #endif
2180
2181 #define FIND_OR_MAKE_VARIABLE(name, entry) \
2182 do \
2183 { \
2184 entry = find_variable (name); \
2185 if (!entry) \
2186 { \
2187 entry = bind_variable (name, ""); \
2188 if (!no_invisible_vars) entry->attributes |= att_invisible; \
2189 } \
2190 } \
2191 while (0)
2192
2193 /* Make the variable associated with NAME be readonly.
2194 If NAME does not exist yet, create it. */
2195 void
2196 set_var_read_only (name)
2197 char *name;
2198 {
2199 SHELL_VAR *entry;
2200
2201 FIND_OR_MAKE_VARIABLE (name, entry);
2202 VSETATTR (entry, att_readonly);
2203 }
2204
2205 #ifdef INCLUDE_UNUSED
2206 /* Make the function associated with NAME be readonly.
2207 If NAME does not exist, we just punt, like auto_export code below. */
2208 void
2209 set_func_read_only (name)
2210 char *name;
2211 {
2212 SHELL_VAR *entry;
2213
2214 entry = find_function (name);
2215 if (entry)
2216 VSETATTR (entry, att_readonly);
2217 }
2218
2219 /* Make the variable associated with NAME be auto-exported.
2220 If NAME does not exist yet, create it. */
2221 void
2222 set_var_auto_export (name)
2223 char *name;
2224 {
2225 SHELL_VAR *entry;
2226
2227 FIND_OR_MAKE_VARIABLE (name, entry);
2228 set_auto_export (entry);
2229 }
2230
2231 /* Make the function associated with NAME be auto-exported. */
2232 void
2233 set_func_auto_export (name)
2234 char *name;
2235 {
2236 SHELL_VAR *entry;
2237
2238 entry = find_function (name);
2239 if (entry)
2240 set_auto_export (entry);
2241 }
2242 #endif
2243
2244 #if defined (ARRAY_VARS)
2245 /* This function assumes s[i] == '['; returns with s[ret] == ']' if
2246 an array subscript is correctly parsed. */
2247 int
2248 skipsubscript (s, i)
2249 char *s;
2250 int i;
2251 {
2252 int count, c;
2253
2254 for (count = 1; count && (c = s[++i]); )
2255 {
2256 if (c == '[')
2257 count++;
2258 else if (c == ']')
2259 count--;
2260 }
2261 return i;
2262 }
2263 #endif /* ARRAY_VARS */
2264
2265 /* Returns non-zero if STRING is an assignment statement. The returned value
2266 is the index of the `=' sign. */
2267 int
2268 assignment (string)
2269 char *string;
2270 {
2271 register int c, newi, indx;
2272
2273 c = string[indx = 0];
2274
2275 if (legal_variable_starter (c) == 0)
2276 return (0);
2277
2278 while (c = string[indx])
2279 {
2280 /* The following is safe. Note that '=' at the start of a word
2281 is not an assignment statement. */
2282 if (c == '=')
2283 return (indx);
2284
2285 #if defined (ARRAY_VARS)
2286 if (c == '[')
2287 {
2288 newi = skipsubscript (string, indx);
2289 if (string[newi++] != ']')
2290 return (0);
2291 return ((string[newi] == '=') ? newi : 0);
2292 }
2293 #endif /* ARRAY_VARS */
2294
2295 /* Variable names in assignment statements may contain only letters,
2296 digits, and `_'. */
2297 if (legal_variable_char (c) == 0)
2298 return (0);
2299
2300 indx++;
2301 }
2302 return (0);
2303 }
2304
2305 static int
2306 visible_var (var)
2307 SHELL_VAR *var;
2308 {
2309 return (invisible_p (var) == 0);
2310 }
2311
2312 static SHELL_VAR **
2313 _visible_names (table)
2314 HASH_TABLE *table;
2315 {
2316 SHELL_VAR **list;
2317
2318 list = map_over (visible_var, table);
2319
2320 if (list /* && posixly_correct */)
2321 sort_variables (list);
2322
2323 return (list);
2324 }
2325
2326 SHELL_VAR **
2327 all_visible_functions ()
2328 {
2329 return (_visible_names (shell_functions));
2330 }
2331
2332 SHELL_VAR **
2333 all_visible_variables ()
2334 {
2335 return (_visible_names (shell_variables));
2336 }
2337
2338 /* Return non-zero if the variable VAR is visible and exported. Array
2339 variables cannot be exported. */
2340 static int
2341 visible_and_exported (var)
2342 SHELL_VAR *var;
2343 {
2344 return (invisible_p (var) == 0 && exported_p (var));
2345 }
2346
2347 SHELL_VAR **
2348 all_exported_variables ()
2349 {
2350 SHELL_VAR **list;
2351
2352 list = map_over (visible_and_exported, shell_variables);
2353 if (list)
2354 sort_variables (list);
2355 return (list);
2356 }
2357
2358 #if defined (ARRAY_VARS)
2359 /* Return non-zero if the variable VAR is visible and an array. */
2360 static int
2361 visible_array_vars (var)
2362 SHELL_VAR *var;
2363 {
2364 return (invisible_p (var) == 0 && array_p (var));
2365 }
2366
2367 SHELL_VAR **
2368 all_array_variables ()
2369 {
2370 SHELL_VAR **list;
2371
2372 list = map_over (visible_array_vars, shell_variables);
2373 if (list)
2374 sort_variables (list);
2375 return (list);
2376 }
2377 #endif /* ARRAY_VARS */
2378
2379 char **
2380 all_variables_matching_prefix (prefix)
2381 char *prefix;
2382 {
2383 SHELL_VAR **varlist;
2384 char **rlist;
2385 int vind, rind, plen;
2386
2387 plen = STRLEN (prefix);
2388 varlist = all_visible_variables ();
2389 for (vind = 0; varlist && varlist[vind]; vind++)
2390 ;
2391 if (varlist == 0 || vind == 0)
2392 return ((char **)NULL);
2393 rlist = alloc_array (vind + 1);
2394 for (vind = rind = 0; varlist[vind]; vind++)
2395 {
2396 if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
2397 rlist[rind++] = savestring (varlist[vind]->name);
2398 }
2399 rlist[rind] = (char *)0;
2400 free (varlist);
2401
2402 return rlist;
2403 }
2404
2405 static inline char *
2406 mk_env_string (name, value)
2407 char *name, *value;
2408 {
2409 int name_len, value_len;
2410 char *p;
2411
2412 name_len = strlen (name);
2413 value_len = STRLEN (value);
2414 p = xmalloc (2 + name_len + value_len);
2415 strcpy (p, name);
2416 p[name_len] = '=';
2417 if (value && *value)
2418 strcpy (p + name_len + 1, value);
2419 else
2420 p[name_len + 1] = '\0';
2421 return (p);
2422 }
2423
2424 /* Debugging */
2425 static int
2426 valid_exportstr (v)
2427 SHELL_VAR *v;
2428 {
2429 char *s;
2430
2431 s = v->exportstr;
2432 if (legal_variable_starter (*s) == 0)
2433 {
2434 internal_error ("invalid character %d in exportstr for %s", *s, v->name);
2435 return (0);
2436 }
2437 for (s = v->exportstr + 1; s && *s; s++)
2438 {
2439 if (*s == '=')
2440 break;
2441 if (legal_variable_char (*s) == 0)
2442 {
2443 internal_error ("invalid character %d in exportstr for %s", *s, v->name);
2444 return (0);
2445 }
2446 }
2447 if (*s != '=')
2448 {
2449 internal_error ("no `=' in exportstr for %s", v->name);
2450 return (0);
2451 }
2452 return (1);
2453 }
2454
2455 /* Make an array of assignment statements from the hash table
2456 HASHED_VARS which contains SHELL_VARs. Only visible, exported
2457 variables are eligible. */
2458 char **
2459 make_var_array (hashed_vars)
2460 HASH_TABLE *hashed_vars;
2461 {
2462 register int i, list_index;
2463 register SHELL_VAR *var;
2464 char **list, *value;
2465 SHELL_VAR **vars;
2466
2467 vars = map_over (visible_and_exported, hashed_vars);
2468
2469 if (vars == 0)
2470 return (char **)NULL;
2471
2472 list = alloc_array ((1 + array_len ((char **)vars)));
2473
2474 #define USE_EXPORTSTR (value == var->exportstr)
2475
2476 for (i = 0, list_index = 0; var = vars[i]; i++)
2477 {
2478 if (var->exportstr)
2479 {
2480 #if defined(__CYGWIN__) || defined (__CYGWIN32__)
2481 INVALIDATE_EXPORTSTR (var);
2482 value = value_cell (var);
2483 #else
2484 /* XXX -- this test can go away in the next release, to be replaced
2485 by a simple `value = var->exportstr;', when the exportstr code
2486 is better-tested. Until then, don't do it for cygwin at all,
2487 since that system has some weird environment variables. */
2488 if (valid_exportstr (var))
2489 value = var->exportstr;
2490 else
2491 {
2492 INVALIDATE_EXPORTSTR (var);
2493 value = value_cell (var);
2494 }
2495 #endif
2496 }
2497 else if (function_p (var))
2498 value = named_function_string ((char *)NULL, function_cell (var), 0);
2499 #if defined (ARRAY_VARS)
2500 else if (array_p (var))
2501 # if 0
2502 value = array_to_assignment_string (array_cell (var));
2503 # else
2504 continue; /* XXX array vars cannot yet be exported */
2505 # endif
2506 #endif
2507 else
2508 value = value_cell (var);
2509
2510 if (value)
2511 {
2512 /* Gee, I'd like to get away with not using savestring() if we're
2513 using the cached exportstr... */
2514 list[list_index] = USE_EXPORTSTR ? savestring (value)
2515 : mk_env_string (var->name, value);
2516
2517 if (USE_EXPORTSTR == 0 && function_p (var))
2518 {
2519 SAVE_EXPORTSTR (var, list[list_index]);
2520 }
2521 list_index++;
2522 #undef USE_EXPORTSTR
2523
2524 #if 0 /* not yet */
2525 #if defined (ARRAY_VARS)
2526 if (array_p (var))
2527 free (value);
2528 #endif
2529 #endif
2530 }
2531 }
2532
2533 free (vars);
2534 list[list_index] = (char *)NULL;
2535 return (list);
2536 }
2537
2538 /* Add STRING to the array of foo=bar strings that we already
2539 have to add to the environment. */
2540 int
2541 assign_in_env (string)
2542 char *string;
2543 {
2544 int size, offset;
2545 char *name, *temp, *value;
2546 int nlen, vlen;
2547 WORD_LIST *list;
2548 SHELL_VAR *var;
2549
2550 offset = assignment (string);
2551 name = savestring (string);
2552 value = (char *)NULL;
2553
2554 if (name[offset] == '=')
2555 {
2556 name[offset] = 0;
2557
2558 var = find_variable (name);
2559 if (var && readonly_p (var))
2560 {
2561 report_error ("%s: readonly variable", name);
2562 free (name);
2563 return (0);
2564 }
2565 temp = name + offset + 1;
2566 temp = (strchr (temp, '~') != 0) ? bash_tilde_expand (temp) : savestring (temp);
2567
2568 list = expand_string_unsplit (temp, 0);
2569 value = string_list (list);
2570
2571 if (list)
2572 dispose_words (list);
2573
2574 free (temp);
2575 }
2576
2577 temp = mk_env_string (name, value);
2578 FREE (value);
2579 free (name);
2580
2581 if (temporary_env == 0)
2582 {
2583 temporary_env = (char **)xmalloc (sizeof (char *));
2584 temporary_env [0] = (char *)NULL;
2585 }
2586
2587 size = array_len (temporary_env);
2588 temporary_env = (char **)
2589 xrealloc (temporary_env, (size + 2) * (sizeof (char *)));
2590
2591 temporary_env[size] = temp;
2592 temporary_env[size + 1] = (char *)NULL;
2593 array_needs_making = 1;
2594
2595 if (echo_command_at_execute)
2596 {
2597 /* The Korn shell prints the `+ ' in front of assignment statements,
2598 so we do too. */
2599 fprintf (stderr, "%s%s\n", indirection_level_string (), temp);
2600 fflush (stderr);
2601 }
2602
2603 return 1;
2604 }
2605
2606 /* Search for NAME in ARRAY, an array of strings in the same format as the
2607 environment array (i.e, name=value). If NAME is present, make a new
2608 variable and return it. Otherwise, return NULL. */
2609 static SHELL_VAR *
2610 find_name_in_env_array (name, array)
2611 char *name;
2612 char **array;
2613 {
2614 register int i, l;
2615
2616 if (array == 0)
2617 return ((SHELL_VAR *)NULL);
2618
2619 for (i = 0, l = strlen (name); array[i]; i++)
2620 {
2621 if (STREQN (array[i], name, l) && array[i][l] == '=')
2622 {
2623 SHELL_VAR *temp;
2624 char *w;
2625
2626 /* This is a potential memory leak. The code should really save
2627 the created variables in some auxiliary data structure, which
2628 can be disposed of at the appropriate time. */
2629 temp = new_shell_variable (name);
2630 w = array[i] + l + 1;
2631
2632 temp->value = *w ? savestring (w) : (char *)NULL;
2633
2634 temp->attributes = att_exported|att_tempvar;
2635 temp->context = 0;
2636 temp->prev_context = (SHELL_VAR *)NULL;
2637
2638 temp->dynamic_value = temp->assign_func = (DYNAMIC_FUNC *)NULL;
2639 CLEAR_EXPORTSTR (temp);
2640
2641 return (temp);
2642 }
2643 }
2644 return ((SHELL_VAR *)NULL);
2645 }
2646
2647 /* Find a variable in the temporary environment that is named NAME.
2648 The temporary environment can be either the environment provided
2649 to a simple command, or the environment provided to a shell function.
2650 We only search the function environment if we are currently executing
2651 a shell function body (variable_context > 0). Return a consed variable,
2652 or NULL if not found. */
2653 SHELL_VAR *
2654 find_tempenv_variable (name)
2655 char *name;
2656 {
2657 SHELL_VAR *var;
2658
2659 var = (SHELL_VAR *)NULL;
2660
2661 if (temporary_env)
2662 var = find_name_in_env_array (name, temporary_env);
2663
2664 /* We don't check this_shell_builtin because the command that needs the
2665 value from builtin_env may be a disk command run inside a script run
2666 with `.' and a temporary env. */
2667 if (!var && builtin_env)
2668 var = find_name_in_env_array (name, builtin_env);
2669
2670 if (!var && variable_context && function_env)
2671 var = find_name_in_env_array (name, function_env);
2672
2673 return (var);
2674 }
2675
2676 /* Free the storage allocated to the string array pointed to by ARRAYP, and
2677 make that variable have a null pointer as a value. */
2678 static void
2679 dispose_temporary_vars (arrayp)
2680 char ***arrayp;
2681 {
2682 if (!*arrayp)
2683 return;
2684
2685 free_array (*arrayp);
2686 *arrayp = (char **)NULL;
2687 array_needs_making = 1;
2688 }
2689
2690 /* Free the storage used in the variable array for temporary
2691 environment variables. */
2692 void
2693 dispose_used_env_vars ()
2694 {
2695 dispose_temporary_vars (&temporary_env);
2696 }
2697
2698 /* Free the storage used for temporary environment variables given to
2699 commands when executing inside of a function body. */
2700 void
2701 dispose_function_env ()
2702 {
2703 dispose_temporary_vars (&function_env);
2704 }
2705
2706 /* Free the storage used for temporary environment variables given to
2707 commands when executing a builtin command such as "source". */
2708 void
2709 dispose_builtin_env ()
2710 {
2711 dispose_temporary_vars (&builtin_env);
2712 }
2713
2714 /* Take all of the shell variables in ENV_ARRAY and make shell variables
2715 from them at the current variable context. */
2716 static void
2717 merge_env_array (env_array)
2718 char **env_array;
2719 {
2720 register int i, l;
2721 SHELL_VAR *temp;
2722 char *val, *name;
2723
2724 if (env_array == 0)
2725 return;
2726
2727 for (i = 0; env_array[i]; i++)
2728 {
2729 l = assignment (env_array[i]);
2730 name = env_array[i];
2731 val = env_array[i] + l + 1;
2732 name[l] = '\0';
2733 temp = bind_variable (name, val);
2734 name[l] = '=';
2735 }
2736 }
2737
2738 void
2739 merge_temporary_env ()
2740 {
2741 merge_env_array (temporary_env);
2742 }
2743
2744 void
2745 merge_builtin_env ()
2746 {
2747 merge_env_array (builtin_env);
2748 }
2749
2750 int
2751 any_temporary_variables ()
2752 {
2753 return (temporary_env || function_env);
2754 }
2755
2756 /* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
2757 #define add_to_export_env(envstr,do_alloc) \
2758 do \
2759 { \
2760 if (export_env_index >= (export_env_size - 1)) \
2761 { \
2762 export_env_size += 16; \
2763 export_env = (char **)xrealloc (export_env, export_env_size * sizeof (char *)); \
2764 } \
2765 export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
2766 export_env[export_env_index] = (char *)NULL; \
2767 } while (0)
2768
2769 #define ISFUNCTION(s, o) ((s[o + 1] == '(') && (s[o + 2] == ')'))
2770
2771 /* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
2772 array with the same left-hand side. Return the new EXPORT_ENV. */
2773 char **
2774 add_or_supercede_exported_var (assign, do_alloc)
2775 char *assign;
2776 int do_alloc;
2777 {
2778 register int i;
2779 int equal_offset;
2780
2781 equal_offset = assignment (assign);
2782 if (equal_offset == 0)
2783 return (export_env);
2784
2785 /* If this is a function, then only supercede the function definition.
2786 We do this by including the `=(' in the comparison. */
2787 if (assign[equal_offset + 1] == '(')
2788 equal_offset++;
2789
2790 for (i = 0; i < export_env_index; i++)
2791 {
2792 if (STREQN (assign, export_env[i], equal_offset + 1))
2793 {
2794 free (export_env[i]);
2795 export_env[i] = do_alloc ? savestring (assign) : assign;
2796 return (export_env);
2797 }
2798 }
2799 add_to_export_env (assign, do_alloc);
2800 return (export_env);
2801 }
2802
2803 /* Make the environment array for the command about to be executed, if the
2804 array needs making. Otherwise, do nothing. If a shell action could
2805 change the array that commands receive for their environment, then the
2806 code should `array_needs_making++'. */
2807 void
2808 maybe_make_export_env ()
2809 {
2810 register int i;
2811 register char **temp_array;
2812 int new_size;
2813
2814 if (array_needs_making)
2815 {
2816 if (export_env)
2817 free_array_members (export_env);
2818
2819 /* Make a guess based on how many shell variables and functions we
2820 have. Since there will always be array variables, and array
2821 variables are not (yet) exported, this will always be big enough
2822 for the exported variables and functions, without any temporary
2823 or function environments. */
2824 new_size = HASH_ENTRIES (shell_variables) + HASH_ENTRIES (shell_functions) + 1;
2825 if (new_size > export_env_size)
2826 {
2827 export_env_size = new_size;
2828 export_env = (char **)xrealloc (export_env, export_env_size * sizeof (char *));
2829 }
2830 export_env[export_env_index = 0] = (char *)NULL;
2831
2832 temp_array = make_var_array (shell_variables);
2833 if (temp_array)
2834 {
2835 for (i = 0; temp_array[i]; i++)
2836 add_to_export_env (temp_array[i], 0);
2837 free (temp_array);
2838 }
2839
2840 temp_array = make_var_array (shell_functions);
2841 if (temp_array)
2842 {
2843 for (i = 0; temp_array[i]; i++)
2844 add_to_export_env (temp_array[i], 0);
2845 free (temp_array);
2846 }
2847
2848 if (function_env)
2849 for (i = 0; function_env[i]; i++)
2850 export_env = add_or_supercede_exported_var (function_env[i], 1);
2851
2852 if (temporary_env)
2853 for (i = 0; temporary_env[i]; i++)
2854 export_env = add_or_supercede_exported_var (temporary_env[i], 1);
2855
2856 #if 0
2857 /* If we changed the array, then sort it alphabetically. */
2858 if (posixly_correct == 0 && (temporary_env || function_env))
2859 sort_char_array (export_env);
2860 #endif
2861
2862 array_needs_making = 0;
2863 }
2864 }
2865
2866 /* This is an efficiency hack. PWD and OLDPWD are auto-exported, so
2867 we will need to remake the exported environment every time we
2868 change directories. `_' is always put into the environment for
2869 every external command, so without special treatment it will always
2870 cause the environment to be remade.
2871
2872 If there is no other reason to make the exported environment, we can
2873 just update the variables in place and mark the exported environment
2874 as no longer needing a remake. */
2875 void
2876 update_export_env_inplace (env_prefix, preflen, value)
2877 char *env_prefix;
2878 int preflen;
2879 char *value;
2880 {
2881 char *evar;
2882
2883 evar = xmalloc (STRLEN (value) + preflen + 1);
2884 strcpy (evar, env_prefix);
2885 if (value)
2886 strcpy (evar + preflen, value);
2887 export_env = add_or_supercede_exported_var (evar, 0);
2888 }
2889
2890 /* We always put _ in the environment as the name of this command. */
2891 void
2892 put_command_name_into_env (command_name)
2893 char *command_name;
2894 {
2895 update_export_env_inplace ("_=", 2, command_name);
2896 }
2897
2898 #if 0 /* UNUSED -- it caused too many problems */
2899 void
2900 put_gnu_argv_flags_into_env (pid, flags_string)
2901 int pid;
2902 char *flags_string;
2903 {
2904 char *dummy, *pbuf;
2905 int l, fl;
2906
2907 pbuf = itos (pid);
2908 l = strlen (pbuf);
2909
2910 fl = strlen (flags_string);
2911
2912 dummy = xmalloc (l + fl + 30);
2913 dummy[0] = '_';
2914 strcpy (dummy + 1, pbuf);
2915 strcpy (dummy + 1 + l, "_GNU_nonoption_argv_flags_");
2916 dummy[l + 27] = '=';
2917 strcpy (dummy + l + 28, flags_string);
2918
2919 free (pbuf);
2920
2921 export_env = add_or_supercede_exported_var (dummy, 0);
2922 }
2923 #endif
2924
2925 /* Return a string denoting what our indirection level is. */
2926 static char indirection_string[100];
2927
2928 char *
2929 indirection_level_string ()
2930 {
2931 register int i, j;
2932 char *ps4;
2933
2934 indirection_string[0] = '\0';
2935 ps4 = get_string_value ("PS4");
2936
2937 if (ps4 == 0 || *ps4 == '\0')
2938 return (indirection_string);
2939
2940 ps4 = decode_prompt_string (ps4);
2941
2942 for (i = 0; *ps4 && i < indirection_level && i < 99; i++)
2943 indirection_string[i] = *ps4;
2944
2945 for (j = 1; *ps4 && ps4[j] && i < 99; i++, j++)
2946 indirection_string[i] = ps4[j];
2947
2948 indirection_string[i] = '\0';
2949 free (ps4);
2950 return (indirection_string);
2951 }
2952
2953 /*************************************************
2954 * *
2955 * Functions to manage special variables *
2956 * *
2957 *************************************************/
2958
2959 /* Extern declarations for variables this code has to manage. */
2960 extern int eof_encountered, eof_encountered_limit, ignoreeof;
2961
2962 #if defined (READLINE)
2963 extern int no_line_editing;
2964 extern int hostname_list_initialized;
2965 #endif
2966
2967 /* An alist of name.function for each special variable. Most of the
2968 functions don't do much, and in fact, this would be faster with a
2969 switch statement, but by the end of this file, I am sick of switch
2970 statements. */
2971
2972 #define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0
2973
2974 struct name_and_function {
2975 char *name;
2976 VFunction *function;
2977 } special_vars[] = {
2978 { "PATH", sv_path },
2979 { "MAIL", sv_mail },
2980 { "MAILPATH", sv_mail },
2981 { "MAILCHECK", sv_mail },
2982
2983 { "POSIXLY_CORRECT", sv_strict_posix },
2984 { "GLOBIGNORE", sv_globignore },
2985
2986 /* Variables which only do something special when READLINE is defined. */
2987 #if defined (READLINE)
2988 { "TERM", sv_terminal },
2989 { "TERMCAP", sv_terminal },
2990 { "TERMINFO", sv_terminal },
2991 { "HOSTFILE", sv_hostfile },
2992 #endif /* READLINE */
2993
2994 /* Variables which only do something special when HISTORY is defined. */
2995 #if defined (HISTORY)
2996 { "HISTIGNORE", sv_histignore },
2997 { "HISTSIZE", sv_histsize },
2998 { "HISTFILESIZE", sv_histsize },
2999 { "HISTCONTROL", sv_history_control },
3000 # if defined (BANG_HISTORY)
3001 { "histchars", sv_histchars },
3002 # endif /* BANG_HISTORY */
3003 #endif /* HISTORY */
3004
3005 { "IGNOREEOF", sv_ignoreeof },
3006 { "ignoreeof", sv_ignoreeof },
3007
3008 { "OPTIND", sv_optind },
3009 { "OPTERR", sv_opterr },
3010
3011 { "TEXTDOMAIN", sv_locale },
3012 { "TEXTDOMAINDIR", sv_locale },
3013 { "LC_ALL", sv_locale },
3014 { "LC_COLLATE", sv_locale },
3015 { "LC_CTYPE", sv_locale },
3016 { "LC_MESSAGES", sv_locale },
3017 { "LC_NUMERIC", sv_locale },
3018 { "LANG", sv_locale },
3019
3020 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
3021 { "TZ", sv_tz },
3022 #endif
3023
3024 { (char *)0, (VFunction *)0 }
3025 };
3026
3027 /* The variable in NAME has just had its state changed. Check to see if it
3028 is one of the special ones where something special happens. */
3029 void
3030 stupidly_hack_special_variables (name)
3031 char *name;
3032 {
3033 int i;
3034
3035 for (i = 0; special_vars[i].name; i++)
3036 {
3037 if (STREQ (special_vars[i].name, name))
3038 {
3039 (*(special_vars[i].function)) (name);
3040 return;
3041 }
3042 }
3043 }
3044
3045 /* What to do just after the PATH variable has changed. */
3046 void
3047 sv_path (name)
3048 char *name;
3049 {
3050 /* hash -r */
3051 flush_hashed_filenames ();
3052 }
3053
3054 /* What to do just after one of the MAILxxxx variables has changed. NAME
3055 is the name of the variable. This is called with NAME set to one of
3056 MAIL, MAILCHECK, or MAILPATH. */
3057 void
3058 sv_mail (name)
3059 char *name;
3060 {
3061 /* If the time interval for checking the files has changed, then
3062 reset the mail timer. Otherwise, one of the pathname vars
3063 to the users mailbox has changed, so rebuild the array of
3064 filenames. */
3065 if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */
3066 reset_mail_timer ();
3067 else
3068 {
3069 free_mail_files ();
3070 remember_mail_dates ();
3071 }
3072 }
3073
3074 /* What to do when GLOBIGNORE changes. */
3075 void
3076 sv_globignore (name)
3077 char *name;
3078 {
3079 setup_glob_ignore (name);
3080 }
3081
3082 #if defined (READLINE)
3083 /* What to do just after one of the TERMxxx variables has changed.
3084 If we are an interactive shell, then try to reset the terminal
3085 information in readline. */
3086 void
3087 sv_terminal (name)
3088 char *name;
3089 {
3090 if (interactive_shell && no_line_editing == 0)
3091 rl_reset_terminal (get_string_value ("TERM"));
3092 }
3093
3094 void
3095 sv_hostfile (name)
3096 char *name;
3097 {
3098 SHELL_VAR *v;
3099
3100 v = find_variable (name);
3101 if (v == 0)
3102 clear_hostname_list ();
3103 else
3104 hostname_list_initialized = 0;
3105 }
3106 #endif /* READLINE */
3107
3108 #if defined (HISTORY)
3109 /* What to do after the HISTSIZE or HISTFILESIZE variables change.
3110 If there is a value for this HISTSIZE (and it is numeric), then stifle
3111 the history. Otherwise, if there is NO value for this variable,
3112 unstifle the history. If name is HISTFILESIZE, and its value is
3113 numeric, truncate the history file to hold no more than that many
3114 lines. */
3115 void
3116 sv_histsize (name)
3117 char *name;
3118 {
3119 char *temp;
3120 long num;
3121
3122 temp = get_string_value (name);
3123
3124 if (temp && *temp)
3125 {
3126 if (legal_number (temp, &num))
3127 {
3128 if (name[4] == 'S')
3129 {
3130 stifle_history (num);
3131 num = where_history ();
3132 if (history_lines_this_session > num)
3133 history_lines_this_session = num;
3134 }
3135 else
3136 {
3137 history_truncate_file (get_string_value ("HISTFILE"), (int)num);
3138 if (num <= history_lines_in_file)
3139 history_lines_in_file = num;
3140 }
3141 }
3142 }
3143 else if (name[4] == 'S')
3144 unstifle_history ();
3145 }
3146
3147 /* What to do after the HISTIGNORE variable changes. */
3148 void
3149 sv_histignore (name)
3150 char *name;
3151 {
3152 setup_history_ignore (name);
3153 }
3154
3155 /* What to do after the HISTCONTROL variable changes. */
3156 void
3157 sv_history_control (name)
3158 char *name;
3159 {
3160 char *temp;
3161
3162 history_control = 0;
3163 temp = get_string_value (name);
3164
3165 if (temp && *temp && STREQN (temp, "ignore", 6))
3166 {
3167 if (temp[6] == 's') /* ignorespace */
3168 history_control = 1;
3169 else if (temp[6] == 'd') /* ignoredups */
3170 history_control = 2;
3171 else if (temp[6] == 'b') /* ignoreboth */
3172 history_control = 3;
3173 }
3174 }
3175
3176 #if defined (BANG_HISTORY)
3177 /* Setting/unsetting of the history expansion character. */
3178 void
3179 sv_histchars (name)
3180 char *name;
3181 {
3182 char *temp;
3183
3184 temp = get_string_value (name);
3185 if (temp)
3186 {
3187 history_expansion_char = *temp;
3188 if (temp[0] && temp[1])
3189 {
3190 history_subst_char = temp[1];
3191 if (temp[2])
3192 history_comment_char = temp[2];
3193 }
3194 }
3195 else
3196 {
3197 history_expansion_char = '!';
3198 history_subst_char = '^';
3199 history_comment_char = '#';
3200 }
3201 }
3202 #endif /* BANG_HISTORY */
3203 #endif /* HISTORY */
3204
3205 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
3206 void
3207 sv_tz (name)
3208 char *name;
3209 {
3210 tzset ();
3211 }
3212 #endif
3213
3214 /* If the variable exists, then the value of it can be the number
3215 of times we actually ignore the EOF. The default is small,
3216 (smaller than csh, anyway). */
3217 void
3218 sv_ignoreeof (name)
3219 char *name;
3220 {
3221 SHELL_VAR *tmp_var;
3222 char *temp;
3223
3224 eof_encountered = 0;
3225
3226 tmp_var = find_variable (name);
3227 ignoreeof = tmp_var != 0;
3228 temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
3229 if (temp)
3230 eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
3231 set_shellopts (); /* make sure `ignoreeof' is/is not in $SHELLOPTS */
3232 }
3233
3234 void
3235 sv_optind (name)
3236 char *name;
3237 {
3238 char *tt;
3239 int s;
3240
3241 tt = get_string_value ("OPTIND");
3242 if (tt && *tt)
3243 {
3244 s = atoi (tt);
3245
3246 /* According to POSIX, setting OPTIND=1 resets the internal state
3247 of getopt (). */
3248 if (s < 0 || s == 1)
3249 s = 0;
3250 }
3251 else
3252 s = 0;
3253 getopts_reset (s);
3254 }
3255
3256 void
3257 sv_opterr (name)
3258 char *name;
3259 {
3260 char *tt;
3261
3262 tt = get_string_value ("OPTERR");
3263 sh_opterr = (tt && *tt) ? atoi (tt) : 1;
3264 }
3265
3266 void
3267 sv_strict_posix (name)
3268 char *name;
3269 {
3270 SET_INT_VAR (name, posixly_correct);
3271 posix_initialize (posixly_correct);
3272 #if defined (READLINE)
3273 if (interactive_shell)
3274 posix_readline_initialize (posixly_correct);
3275 #endif /* READLINE */
3276 set_shellopts (); /* make sure `posix' is/is not in $SHELLOPTS */
3277 }
3278
3279 void
3280 sv_locale (name)
3281 char *name;
3282 {
3283 char *v;
3284
3285 v = get_string_value (name);
3286 if (name[0] == 'L' && name[1] == 'A') /* LANG */
3287 set_lang (name, v);
3288 else
3289 set_locale_var (name, v); /* LC_*, TEXTDOMAIN* */
3290 }
3291
3292 #if defined (ARRAY_VARS)
3293 void
3294 set_pipestatus_array (ps)
3295 int *ps;
3296 {
3297 SHELL_VAR *v;
3298 ARRAY *a;
3299 register int i;
3300 char *t, tbuf[16];
3301
3302 v = find_variable ("PIPESTATUS");
3303 if (v == 0)
3304 v = make_new_array_variable ("PIPESTATUS");
3305 if (array_p (v) == 0)
3306 return; /* Do nothing if not an array variable. */
3307 a = array_cell (v);
3308 if (a)
3309 empty_array (a);
3310 for (i = 0; ps[i] != -1; i++)
3311 {
3312 t = inttostr (ps[i], tbuf, sizeof (tbuf));
3313 array_add_element (a, i, t);
3314 }
3315 }
3316 #endif
3317
3318 void
3319 set_pipestatus_from_exit (s)
3320 int s;
3321 {
3322 #if defined (ARRAY_VARS)
3323 static int v[2] = { 0, -1 };
3324
3325 v[0] = s;
3326 set_pipestatus_array (v);
3327 #endif
3328 }