home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / bash / bash_110 / mint / bash110s.zoo / bash-1.10 / variables.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-28  |  37.9 KB  |  1,600 lines

  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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <pwd.h>
  24. #include <sys/types.h>
  25.  
  26. #include "shell.h"
  27. #include "hash.h"
  28. #include "flags.h"
  29.  
  30. #if defined (USG) && !defined (isc386) && !defined (sgi)
  31. struct passwd *getpwuid (), *getpwent ();
  32. #endif
  33.  
  34. /* The list of shell variables that the user has created, or that came from
  35.    the environment. */
  36. HASH_TABLE *shell_variables = (HASH_TABLE *)NULL;
  37.  
  38. /* The list of shell functions that the user has created, or that came from
  39.    the environment. */
  40. HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
  41.  
  42. /* The current variable context.  This is really a count of how deep into
  43.    executing functions we are. */
  44. int variable_context = 0;
  45.  
  46. /* The array of shell assignments which are made only in the environment
  47.    for a single command. */
  48. char **temporary_env = (char **)NULL;
  49.  
  50. /* Some funky variables which are known about specially.  Here is where
  51.    "$*", "$1", and all the cruft is kept. */
  52. char *dollar_vars[10];
  53. WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
  54.  
  55. /* The value of $$. */
  56. int dollar_dollar_pid;
  57.  
  58. /* An array which is passed to commands as their environment.  It is
  59.    manufactured from the overlap of the initial environment and the
  60.    shell variables that are marked for export. */
  61. char **export_env = (char **)NULL;
  62.  
  63. /* Non-zero means that we have to remake EXPORT_ENV. */
  64. int array_needs_making = 1;
  65.  
  66. /* The list of variables that may not be unset in this shell. */
  67. char **non_unsettable_vars = (char **)NULL;
  68.  
  69. #if defined (USG)
  70. #define DEFAULT_MAIL_PATH "/usr/mail/"
  71. #else
  72. #define DEFAULT_MAIL_PATH "/usr/spool/mail/"
  73. #endif
  74.  
  75. /* Some forward declarations. */
  76. SHELL_VAR *set_if_not ();    /* returns new or existing entry */
  77. static void sbrand ();        /* set bash random number generator */
  78.  
  79. /* Make VAR be auto-exported.  VAR is a pointer to a SHELL_VAR. */
  80. #define set_auto_export(var) \
  81. { var->attributes |= att_exported; array_needs_making = 1; }
  82.  
  83. /* Initialize the shell variables from the current environment. */
  84. initialize_shell_variables (env)
  85.      char *env[];
  86. {
  87.   extern char *primary_prompt, *secondary_prompt;
  88.   char *name, *string;
  89.   int c, char_index;
  90.   int string_index = 0;
  91.   SHELL_VAR *temp_var;
  92.  
  93.   if (!shell_variables)
  94.     shell_variables = make_hash_table (0);
  95.  
  96.   if (!shell_functions)
  97.     shell_functions = make_hash_table (0);
  98.  
  99.   while (string = env[string_index++])
  100.     {
  101.       char_index = 0;
  102.  
  103.       name = (char *)alloca (1 + strlen (string));
  104.  
  105.       while ((c = *string++) && c != '=')
  106.     name[char_index++] = c;
  107.  
  108.       name[char_index] = '\0';
  109.  
  110.       /* If exported function, define it now. */
  111.       /* Posix.2 style exported function: name()=value */
  112.       if (strncmp ("() {", string, 4) == 0 ||
  113.       ((name[char_index - 1] == ')' &&
  114.         name[char_index - 2] == '(' &&
  115.         string[0] == '{')))
  116.     {
  117.       char *eval_string;
  118.  
  119.       eval_string = (char *)xmalloc (3 + strlen (string) + strlen (name));
  120.       sprintf (eval_string, "%s %s", name, string);
  121.       parse_and_execute (eval_string, name);
  122.  
  123.       if (name[char_index - 1] == ')')
  124.         name[char_index - 2] = '\0';
  125.       set_func_auto_export (name);
  126.     }
  127.       else
  128.     {
  129.       SHELL_VAR *v;
  130.  
  131.       v = bind_variable (name, string);
  132.       set_auto_export (v);
  133.     }
  134.     }
  135.  
  136.   /* Remember this pid. */
  137.   dollar_dollar_pid = (int)getpid ();
  138.  
  139.   /* Now make our own defaults in case the vars that we think are
  140.      important are missing. */
  141.   temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
  142.   set_auto_export (temp_var);
  143.  
  144.   temp_var = set_if_not ("TERM", "dumb");
  145.   set_auto_export (temp_var);
  146.  
  147.   set_if_not ("PS1", primary_prompt);
  148.   set_if_not ("PS2", secondary_prompt);
  149.   set_if_not ("IFS", " \t\n");
  150.  
  151.   /* Magic machine types.  Pretty convenient. */
  152.   temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
  153.   set_auto_export (temp_var);
  154.  
  155.   /* Default MAILPATH, and MAILCHECK. */
  156.   set_if_not ("MAILCHECK", "60");
  157.   if ((get_string_value ("MAIL") == (char *)NULL) &&
  158.       (get_string_value ("MAILPATH") == (char *)NULL))
  159.     {
  160.       extern char *current_user_name;
  161.       char *tem;
  162.  
  163.       tem = (char *)xmalloc (1 + sizeof (DEFAULT_MAIL_PATH)
  164.                + strlen (current_user_name));
  165.       strcpy (tem, DEFAULT_MAIL_PATH);
  166.       strcat (tem, current_user_name);
  167.  
  168.       bind_variable ("MAILPATH", tem);
  169.       free (tem);
  170.     }
  171.  
  172.   /* Set up $PWD. */
  173.   {
  174.     char *get_working_directory (), *cd;
  175.  
  176.     cd = get_working_directory ("shell-init");
  177.     if (cd)
  178.       {
  179.     bind_variable ("PWD", cd);
  180.     free (cd);
  181.       }
  182.   }
  183.  
  184.   /* Do some things with shell level. */
  185.   temp_var = set_if_not ("SHLVL", "0");
  186.   set_auto_export (temp_var);
  187.   adjust_shell_level (1);
  188.  
  189.   /* Make a variable $PPID, which holds the pid of the shell's parent.  */
  190.   {
  191.     char *ppid;
  192.     SHELL_VAR *v;
  193.     extern char *itos ();
  194.  
  195.     ppid = itos ((int) getppid ());
  196.     v = find_variable ("PPID");
  197.  
  198.     if (v)
  199.       v->attributes &= ~att_readonly;
  200.  
  201.     v = bind_variable ("PPID", ppid);
  202.     v->attributes |= (att_readonly | att_integer);
  203.  
  204.     non_unsettable ("PPID");
  205.     free (ppid);
  206.   }
  207.  
  208.   /* Initialize the `getopts' stuff. */
  209.   bind_variable ("OPTIND", "1");
  210.   bind_variable ("OPTERR", "1");
  211.  
  212.   /* Get the full pathname to THIS shell, and set the BASH variable
  213.      to it. */
  214.   {
  215.     extern char *shell_name, *find_user_command (), *full_pathname ();
  216.     extern int login_shell;
  217.     char *tname = find_user_command (shell_name);
  218.  
  219.     if ((login_shell == 1) && (*shell_name != '/'))
  220.       {
  221.     struct passwd *entry = getpwuid (getuid ());
  222.  
  223.     if (entry)
  224.       {
  225.         /* If HOME doesn't exist, set it. */
  226.         temp_var = (SHELL_VAR *)find_variable ("HOME");
  227.         if (!temp_var)
  228.           {
  229.         temp_var = bind_variable ("HOME", entry->pw_dir);
  230.         temp_var->attributes |= att_exported;
  231.           }
  232.         name = savestring (entry->pw_shell);
  233.       }
  234.     else
  235.       name = savestring ("a.out");
  236.     endpwent ();
  237.       }
  238.     else
  239.       {
  240.     if (!tname)
  241.       {
  242.         char *make_absolute ();
  243.         name = make_absolute (shell_name, get_string_value ("PWD"));
  244.       }
  245.     else
  246.       {
  247.         name = full_pathname (tname);
  248.         free (tname);
  249.       }
  250.       }
  251.  
  252.     /* Make the exported environment variable SHELL be whatever the name of
  253.        this shell is.  Note that the `tset' command looks at this variable
  254.        to determine what style of commands to output; if it ends in "csh",
  255.        then C-shell commands are output, else Bourne shell commands. */
  256.     temp_var = set_if_not ("SHELL", name);
  257.     set_auto_export (temp_var);
  258.  
  259.     /* Make a variable called BASH, which is the name of THIS shell. */
  260.     temp_var = bind_variable ("BASH", name);
  261.     temp_var->attributes |= att_exported;
  262.  
  263.     free (name);
  264.   }
  265.  
  266.   /* Make a variable called BASH_VERSION which contains the version info. */
  267.   {
  268.     char tt[12];
  269.     extern char *dist_version;
  270.     extern int build_version;
  271.  
  272.     sprintf (tt, "%s.%d", dist_version, build_version);
  273.     bind_variable ("BASH_VERSION", tt);
  274.   }
  275.  
  276.   /* Set history variables to defaults, and then do whatever we would
  277.      do if the variable had just been set. */
  278.   {
  279.     char *tilde_expand ();
  280.     char *tem = tilde_expand ("~/.bash_history");
  281.  
  282.     set_if_not ("HISTFILE", tem);
  283.     free (tem);
  284.  
  285.     set_if_not ("HISTSIZE", "500");
  286.     sv_histsize ("HISTSIZE");
  287.   }
  288.  
  289.   /* seed the random number generator */
  290.  
  291.   sbrand (dollar_dollar_pid);
  292.  
  293.   /* If we have inherited `noclobber' from a previous shell, then set
  294.      noclobbering on. */
  295.   {
  296.     extern int noclobber;
  297.  
  298.     noclobber = find_variable ("noclobber") != NULL;
  299.   }
  300.  
  301.   /* Initialize the dynamic variables, and seed their values */
  302.   initialize_dynamic_variables ();
  303.  
  304.   non_unsettable ("PATH");
  305.   non_unsettable ("PS1");
  306.   non_unsettable ("PS2");
  307.   non_unsettable ("IFS");
  308.  
  309.   /* Get the users real user id, and save that in an readonly variable.
  310.      To make the variable *really* readonly, we have added it to a special
  311.      list of vars. */
  312.  
  313.   sv_uids ();
  314.   set_var_read_only ("UID");
  315.   set_var_read_only ("EUID");
  316.  
  317.   non_unsettable ("EUID");
  318.   non_unsettable ("UID");
  319. }
  320.  
  321. adjust_shell_level (change)
  322.      int change;
  323. {
  324.   extern int shell_level;
  325.   extern char *itos ();
  326.   char *new_level;
  327.   int old_level;
  328.  
  329.  
  330.   old_level = atoi (get_string_value ("SHLVL"));
  331.   shell_level = old_level + change;
  332.   new_level = itos (shell_level);
  333.   bind_variable ("SHLVL", new_level);
  334.   free (new_level);
  335. }
  336.  
  337. /* Add NAME to the list of variables that cannot be unset
  338.    if it isn't already there. */
  339. non_unsettable (name)
  340.      char *name;
  341. {
  342.   register int i;
  343.  
  344.   if (!non_unsettable_vars)
  345.     {
  346.       non_unsettable_vars = (char **)xmalloc (1 * sizeof (char *));
  347.       non_unsettable_vars[0] = (char *)NULL;
  348.     }
  349.  
  350.   for (i = 0; non_unsettable_vars[i]; i++)
  351.     if (strcmp (non_unsettable_vars[i], name) == 0)
  352.       return;
  353.  
  354.   non_unsettable_vars = (char **)
  355.     xrealloc (non_unsettable_vars, (2 + i) * sizeof (char *));
  356.   non_unsettable_vars[i] = savestring (name);
  357.   non_unsettable_vars[i + 1] = (char *)NULL;
  358. }
  359.  
  360. /* Set NAME to VALUE if NAME has no value. */
  361. SHELL_VAR *
  362. set_if_not (name, value)
  363.      char *name, *value;
  364. {
  365.   SHELL_VAR *v = find_variable (name);
  366.  
  367.   if (!v)
  368.     v = bind_variable (name, value);
  369.   return (v);
  370. }
  371.  
  372. /* Map FUNCTION over the variables in VARIABLES.  Return an array of the
  373.    variables that satisfy FUNCTION.  Satisfy means that FUNCTION returns
  374.    a non-zero value for.  A NULL value for FUNCTION means to use all
  375.    variables. */
  376. SHELL_VAR **
  377. map_over (function, var_hash_table)
  378.      Function *function;
  379.      HASH_TABLE* var_hash_table;
  380. {
  381.   register int i;
  382.   register BUCKET_CONTENTS *tlist;
  383.   SHELL_VAR *var, **list = (SHELL_VAR **)NULL;
  384.   int list_index = 0, list_size = 0;
  385.  
  386.   for (i = 0; i < var_hash_table->nbuckets; i++)
  387.     {
  388.       tlist = get_hash_bucket (i, var_hash_table);
  389.  
  390.       while (tlist)
  391.     {
  392.       var = (SHELL_VAR *)tlist->data;
  393.  
  394.       if (!function || (*function) (var))
  395.         {
  396.           if (list_index + 1 >= list_size)
  397.         list = (SHELL_VAR **)
  398.           xrealloc (list, (list_size += 20) * sizeof (SHELL_VAR *));
  399.  
  400.           list[list_index++] = var;
  401.           list[list_index] = (SHELL_VAR *)NULL;
  402.         }
  403.       tlist = tlist->next;
  404.     }
  405.     }
  406.   return (list);
  407. }
  408.  
  409. int
  410. qsort_var_comp (var1, var2)
  411.      SHELL_VAR **var1, **var2;
  412. {
  413.   return (strcmp ((*var1)->name, (*var2)->name));
  414. }
  415.  
  416. sort_variables (array)
  417.      SHELL_VAR **array;
  418. {
  419.   qsort (array, array_len (array), sizeof (SHELL_VAR *), qsort_var_comp);
  420. }
  421.  
  422. /* Create a NULL terminated array of all the shell variables in TABLE. */
  423. static SHELL_VAR **
  424. all_vars (table)
  425.      HASH_TABLE *table;
  426. {
  427.   SHELL_VAR **list;
  428.  
  429.   list = map_over ((Function *)NULL, table);
  430.   if (list)
  431.     sort_variables (list);
  432.   return (list);
  433. }
  434.  
  435. /* Create a NULL terminated array of all the shell variables. */
  436. SHELL_VAR **
  437. all_shell_variables ()
  438. {
  439.   return (all_vars (shell_variables));
  440. }
  441.  
  442. /* Create a NULL terminated array of all the shell functions. */
  443. SHELL_VAR **
  444. all_shell_functions ()
  445. {
  446.   return (all_vars (shell_functions));
  447. }
  448.  
  449. /* Print VARS to stdout in such a way that they can be read back in. */
  450. print_var_list (list)
  451.      register SHELL_VAR **list;
  452. {
  453.   register int i;
  454.   register SHELL_VAR *var;
  455.  
  456.   for (i = 0; list && (var = list[i]); i++)
  457.     if (!invisible_p (var))
  458.       print_assignment (var);
  459. }
  460.  
  461. #if defined (NOTDEF)
  462. /* Print LIST (a linked list of shell variables) to stdout
  463.    by printing the names, without the values.  Used to support the
  464.    `set +' command. */
  465. print_vars_no_values (list)
  466.      register SHELL_VAR **list;
  467. {
  468.   register int i;
  469.   register SHELL_VAR *var;
  470.  
  471.   for (i = 0; list && (var = list[i]); i++)
  472.     if (!invisible_p (var))
  473.       printf ("%s\n", var->name);
  474. }
  475. #endif
  476.  
  477. /* Print the value of a single SHELL_VAR.  No newline is
  478.    output, but the variable is printed in such a way that
  479.    it can be read back in. */
  480. print_assignment (var)
  481.      SHELL_VAR *var;
  482. {
  483.   if (function_p (var) && var->value)
  484.     {
  485.       printf ("%s=", var->name);
  486.       print_var_function (var);
  487.       printf ("\n");
  488.     }
  489.   else if (var->value)
  490.     {
  491.       printf ("%s=", var->name);
  492.       print_var_value (var);
  493.       printf ("\n");
  494.     }
  495. }
  496.  
  497. /* Print the value cell of VAR, a shell variable.  Do not print
  498.    the name, nor leading/trailing newline. */
  499. print_var_value (var)
  500.      SHELL_VAR *var;
  501. {
  502.   if (var->value)
  503.     printf ("%s", var->value);
  504. }
  505.  
  506. /* Print the function cell of VAR, a shell variable.  Do not
  507.    print the name, nor leading/trailing newline. */
  508. print_var_function (var)
  509.      SHELL_VAR *var;
  510. {
  511.   char *named_function_string ();
  512.  
  513.   if (function_p (var) && var->value)
  514.     printf ("%s", named_function_string ((char *)NULL, var->value, 1));
  515. }
  516.  
  517.  
  518. /* **************************************************************** */
  519. /*                                                                  */
  520. /*                 Dynamic Variable Extension                       */
  521. /*                                                                  */
  522. /* **************************************************************** */
  523.  
  524. /* DYNAMIC VARIABLES
  525.    
  526.    These are variables whose values are generated anew each time they are
  527.    referenced.  These are implemented using a pair of function pointers
  528.    in the struct variable: assign_func, which is called from bind_variable,
  529.    and dynamic_value, which is called from find_variable.
  530.    
  531.    assign_func is called from bind_variable, if bind_variable discovers
  532.    that the variable being assigned to has such a function.  The function
  533.    is called as
  534.       SHELL_VAR *temp = (*(entry->assign_func)) (entry, value)
  535.    and the (SHELL_VAR *)temp is returned as the value of bind_variable.  It
  536.    is usually ENTRY (self).
  537.    
  538.    dynamic_value is called from find_variable to return a `new' value for
  539.    the specified dynamic varible.  If this function is NULL, the variable
  540.    is treated as a `normal' shell variable.  If it is not, however, then
  541.    this function is called like this:
  542.       tempvar = (*(var->dynamic_value)) (var);
  543.    
  544.    Sometimes `tempvar' will replace the value of `var'.  Other times, the
  545.    shell will simply use the string value.  Pretty object-oriented, huh?
  546.    
  547.    Be warned, though: if you `unset' a special variable, it loses its
  548.    special meaning, even if you subsequently set it.
  549.    
  550.    The special assignment code would probably have been better put in
  551.    subst.c: do_assignment, in the same style as
  552.    stupidly_hack_special_variables, but I wanted the changes as
  553.    localized as possible.  */
  554.  
  555. /* The value of $SECONDS.  This is the number of seconds since shell
  556.    invocation, or, the number of seconds since the last assignment + the
  557.    value of the last assignment. */
  558. static long seconds_value_assigned = (long)0;
  559.  
  560. /* Originally defined in shell.c */
  561. extern time_t shell_start_time;
  562.  
  563. SHELL_VAR *
  564. assign_seconds (self, value)
  565.      SHELL_VAR *self;
  566.      char *value;
  567. {
  568.   seconds_value_assigned = atol (value);
  569.   shell_start_time = NOW;
  570.   return (self);
  571. }
  572.  
  573. SHELL_VAR *
  574. get_seconds (var)
  575.      SHELL_VAR *var;
  576. {
  577.   extern char *itos ();
  578.   time_t time_since_start;
  579.   char *p;
  580.  
  581.   time_since_start = NOW - shell_start_time;
  582.   p = itos((int) seconds_value_assigned + time_since_start);
  583.  
  584.   if (var->value)
  585.     free (var->value);
  586.  
  587.   var->attributes |= att_integer;
  588.   var->value = p;
  589.   return (var);
  590. }
  591.  
  592. /* The random number seed.  You can change this by setting RANDOM. */
  593. static unsigned long rseed = 1;
  594.  
  595. /* A linear congruential random number generator based on the ANSI
  596.    C standard.  A more complicated one is overkill.  */
  597.  
  598. /* Returns a pseudo-random number between 0 and 32767. */
  599. static int
  600. brand ()
  601. {
  602.   rseed = rseed * 1103515245 + 12345;
  603.   return ((unsigned int)(rseed / 65536) % 32768);
  604. }
  605.  
  606. /* Set the random number generator seed to SEED. */
  607. static void
  608. sbrand (seed)
  609.      int seed;
  610. {
  611.   rseed = seed;
  612. }
  613.  
  614. static SHELL_VAR *
  615. assign_random (self, value)
  616.      SHELL_VAR *self;
  617.      char *value;
  618. {
  619.   int s = atoi (value);
  620.  
  621.   sbrand (s);
  622.   return (self);
  623. }
  624.  
  625. static SHELL_VAR *
  626. get_random (var)
  627.      SHELL_VAR *var;
  628. {
  629.   int brand (), rv;
  630.   char *p;
  631.   extern char *itos ();
  632.  
  633.   rv = brand ();
  634.   p = itos ((int)rv);
  635.   if (var->value)
  636.     free (var->value);
  637.  
  638.   var->attributes |= att_integer;
  639.   var->value = p;
  640.   return (var);
  641. }
  642.  
  643. /* Function which returns the current line number. */
  644. static SHELL_VAR *
  645. get_lineno (var)
  646.      SHELL_VAR *var;
  647. {
  648.   extern int line_number;
  649.   char *p;
  650.   extern char *itos ();
  651.  
  652.   p = itos (line_number);
  653.   if (var->value)
  654.     free (var->value);
  655.   var->value = p;
  656.   return (var);
  657. }
  658.  
  659. initialize_dynamic_variables ()
  660. {
  661.   SHELL_VAR *v;
  662.  
  663.   v = bind_variable ("SECONDS", (char *)NULL);
  664.   v->dynamic_value = get_seconds;
  665.   v->assign_func = assign_seconds;
  666.  
  667.   v = bind_variable ("RANDOM", (char *)NULL);
  668.   v->dynamic_value = get_random;
  669.   v->assign_func = assign_random;
  670.  
  671.   v = bind_variable ("LINENO", (char *)NULL);
  672.   v->dynamic_value = get_lineno;
  673.   v->assign_func = (DYNAMIC_FUNC *)NULL;
  674. }
  675.  
  676. /* How to get a pointer to the shell variable or function named NAME.
  677.    HASHED_VARS is a pointer to the hash table containing the list
  678.    of interest (either variables or functions). */
  679. SHELL_VAR *
  680. var_lookup (name, hashed_vars)
  681.      char *name;
  682.      HASH_TABLE *hashed_vars;
  683. {
  684.   BUCKET_CONTENTS *bucket;
  685.  
  686.   bucket = find_hash_item (name, hashed_vars);
  687.  
  688.   if (bucket)
  689.     return ((SHELL_VAR *)bucket->data);
  690.   else
  691.     return ((SHELL_VAR *)NULL);
  692. }
  693.  
  694. /* Look up the variable entry whose name matches STRING.
  695.    Returns the entry or NULL. */
  696. SHELL_VAR *
  697. find_variable (name)
  698.      char *name;
  699. {
  700.   extern int variable_context;
  701.   extern Function *this_shell_builtin;
  702.   SHELL_VAR *find_tempenv_variable ();
  703.   SHELL_VAR *var = (SHELL_VAR *)NULL;
  704.  
  705.   /* If we are executing a function or builtin, first look in the
  706.      temporary environment for the variable.  This allows constructs
  707.      such as "foo=x eval 'echo $foo'" to get the `exported' value
  708.      of $foo. */
  709.   if (variable_context || this_shell_builtin)
  710.     var = find_tempenv_variable (name);
  711.  
  712.   if (!var)
  713.     var = var_lookup (name, shell_variables);
  714.  
  715.   if (!var)
  716.     return ((SHELL_VAR *)NULL);
  717.  
  718.   if (var->dynamic_value)
  719.     return ((*(var->dynamic_value)) (var));
  720.   else
  721.     return (var);
  722. }
  723.  
  724. /* Look up the function entry whose name matches STRING.
  725.    Returns the entry or NULL. */
  726. SHELL_VAR *
  727. find_function (name)
  728.      char *name;
  729. {
  730.   return (var_lookup (name, shell_functions));
  731. }
  732.  
  733. /* Return the string value of a variable.  Return NULL if the variable
  734.    doesn't exist, or only has a function as a value.  Don't cons a new
  735.    string. */
  736. char *
  737. get_string_value (var_name)
  738.      char *var_name;
  739. {
  740.   SHELL_VAR *var = find_variable (var_name);
  741.  
  742.   if (!var)
  743.     return (char *)NULL;
  744.   else
  745.     return (var->value);
  746. }
  747.  
  748. /* Create a local variable referenced by NAME. */
  749. SHELL_VAR *
  750. make_local_variable (name)
  751.      char *name;
  752. {
  753.   SHELL_VAR *new_var, *old_var, *bind_variable ();
  754.   BUCKET_CONTENTS *elt;
  755.  
  756.   /* local foo; local foo;  is a no-op. */
  757.   old_var = find_variable (name);
  758.   if (old_var && old_var->context == variable_context)
  759.     return (old_var);
  760.  
  761.   elt = remove_hash_item (name, shell_variables);
  762.   if (elt)
  763.     {
  764.       old_var = (SHELL_VAR *)elt->data;
  765.       free (elt->key);
  766.       free (elt);
  767.     }
  768.   else
  769.     old_var = (SHELL_VAR *)NULL;
  770.  
  771.   /* If a variable does not already exist with this name, then
  772.      just make a new one. */
  773.   if (!old_var)
  774.     {
  775.       new_var = bind_variable (name, "");
  776.     }
  777.   else
  778.     {
  779.       new_var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  780.  
  781.       new_var->name = savestring (name);
  782.       new_var->value = savestring ("");
  783.  
  784.       new_var->dynamic_value = (DYNAMIC_FUNC *)NULL;
  785.       new_var->assign_func = (DYNAMIC_FUNC *)NULL;
  786.  
  787.       new_var->attributes = 0;
  788.  
  789.       if (exported_p (old_var))
  790.     new_var->attributes |= att_exported;
  791.  
  792.       new_var->prev_context = old_var;
  793.       elt = add_hash_item (savestring (name), shell_variables);
  794.       elt->data = (char *)new_var;
  795.     }
  796.  
  797.   new_var->context = variable_context;
  798.   return (new_var);
  799. }
  800.  
  801. /* Bind a variable NAME to VALUE.  This conses up the name
  802.    and value strings. */
  803. SHELL_VAR *
  804. bind_variable (name, value)
  805.      char *name, *value;
  806. {
  807.   SHELL_VAR *entry = find_variable (name);
  808.  
  809.   if (!entry)
  810.     {
  811.       /* Make a new entry for this variable.  Then do the binding. */
  812.       entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  813.  
  814.       entry->attributes = 0;
  815.       entry->name = savestring (name);
  816.  
  817.       if (value)
  818.     entry->value = savestring (value);
  819.       else
  820.     entry->value = (char *)NULL;
  821.  
  822.       entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
  823.       entry->assign_func = (DYNAMIC_FUNC *)NULL;
  824.  
  825.       /* Always assume variables are to be made at toplevel!
  826.      make_local_variable has the responsibilty of changing the
  827.      variable context. */
  828.       entry->context = 0;
  829.       entry->prev_context = (SHELL_VAR *)NULL;
  830.  
  831.       {
  832.     BUCKET_CONTENTS *elt;
  833.  
  834.     elt = add_hash_item (savestring (name), shell_variables);
  835.     elt->data = (char *)entry;
  836.       }
  837.     }
  838.   else if (entry->assign_func)
  839.     return ((*(entry->assign_func)) (entry, value));
  840.   else
  841.     {
  842.       if (readonly_p (entry))
  843.     {
  844.       report_error ("%s: read-only variable", name);
  845.       return (entry);
  846.     }
  847.  
  848.       /* If this variable has had its type set to integer (via `declare -i'),
  849.      then do expression evaluation on it and store the result.  The
  850.      functions in expr.c (evalexp and bind_int_variable) are responsible
  851.      for turning off the integer flag if they don't want further
  852.      evaluation done. */
  853.       if (integer_p (entry))
  854.     {
  855.       long val, evalexp();
  856.       extern char *itos();
  857.  
  858.       val = evalexp (value);
  859.       /* We cannot free () entry->value before this; what if the string
  860.          we are working is `even=even+2'?  We need the original value
  861.          around while we are doing the evaluation to handle any possible
  862.          recursion. */
  863.       if (entry->value)
  864.         free (entry->value);
  865.  
  866.       entry->value = itos (val);
  867.     }
  868.       else
  869.     {
  870.       if (entry->value)
  871.         free (entry->value);
  872.  
  873.       if (value)
  874.         entry->value = savestring (value);
  875.       else
  876.         entry->value = (char *)NULL;
  877.     }
  878.     }
  879.  
  880.   if (mark_modified_vars)
  881.     entry->attributes |= att_exported;
  882.  
  883.   if (exported_p (entry))
  884.     array_needs_making = 1;
  885.  
  886.   return (entry);
  887. }
  888.  
  889. /* Dispose of the information attached to VAR. */
  890. dispose_variable (var)
  891.      SHELL_VAR *var;
  892. {
  893.   if (!var)
  894.     return;
  895.  
  896.   if (function_p (var))
  897.     dispose_command (var->value);
  898.   else if (var->value)
  899.     free (var->value);
  900.  
  901.   free (var->name);
  902.  
  903.   if (exported_p (var))
  904.     array_needs_making = 1;
  905.  
  906.   free (var);
  907. }
  908.  
  909. /* Unset the variable referenced by NAME. */
  910. unbind_variable (name)
  911.      char *name;
  912. {
  913.   SHELL_VAR *var = find_variable (name);
  914.  
  915.   if (!var)
  916.     return (-1);
  917.  
  918.   if (var->value)
  919.     {
  920.       free (var->value);
  921.       var->value = (char *)NULL;
  922.     }
  923.  
  924.   makunbound (name, shell_variables);
  925.  
  926.   return (0);
  927. }
  928.  
  929. /* Make the variable associated with NAME go away.  HASH_LIST is the
  930.    hash table from which this variable should be deleted (either
  931.    shell_variables or shell_functions).
  932.    Returns non-zero if the variable couldn't be found. */
  933. makunbound (name, hash_list)
  934.      char *name;
  935.      HASH_TABLE *hash_list;
  936. {
  937.   BUCKET_CONTENTS *elt;
  938.   SHELL_VAR *old_var, *new_var;
  939.  
  940.   elt = remove_hash_item (name, hash_list);
  941.  
  942.   if (!elt)
  943.     return (-1);
  944.  
  945.   old_var = (SHELL_VAR *)elt->data;
  946.   new_var = old_var->prev_context;
  947.  
  948.   if (old_var && exported_p (old_var))
  949.     array_needs_making++;
  950.  
  951.   if (new_var)
  952.     {
  953.       /* Has to be a variable, functions don't have previous contexts. */
  954.       BUCKET_CONTENTS *new_elt;
  955.  
  956.       new_elt = add_hash_item (savestring (new_var->name), hash_list);
  957.       new_elt->data = (char *)new_var;
  958.  
  959.       if (exported_p (new_var))
  960.     set_var_auto_export (new_var->name);
  961.     }
  962.  
  963.   free (elt->key);
  964.   free (elt);
  965.  
  966.   dispose_variable (old_var);
  967.   stupidly_hack_special_variables (name);
  968.   return (0);
  969. }
  970.  
  971. /* Remove the variable with NAME if it is a local variable in the
  972.    current context. */
  973. kill_local_variable (name)
  974.      char *name;
  975. {
  976.   SHELL_VAR *temp = find_variable (name);
  977.  
  978.   if (temp && (temp->context == variable_context))
  979.     {
  980.       makunbound (name, shell_variables);
  981.       return (0);
  982.     }
  983.   return (-1);
  984. }
  985.  
  986. /* Get rid of all of the variables in the current context. */
  987. int
  988. variable_in_context (var)
  989.      SHELL_VAR *var;
  990. {
  991.   return (var && var->context == variable_context);
  992. }
  993.  
  994. kill_all_local_variables ()
  995. {
  996.   register int i, pass;
  997.   register SHELL_VAR *var, **list;
  998.   HASH_TABLE *varlist;
  999.  
  1000.   for (pass = 0; pass < 2; pass++)
  1001.     {
  1002.       varlist = pass ? shell_functions : shell_variables;
  1003.  
  1004.       list = map_over (variable_in_context, varlist);
  1005.  
  1006.       if (list)
  1007.     {
  1008.       for (i = 0; var = list[i]; i++)
  1009.         makunbound (var->name, varlist);
  1010.  
  1011.       free (list);
  1012.     }
  1013.     }
  1014. }
  1015.  
  1016. /* Delete the entire contents of the hash table. */
  1017. delete_all_variables (hashed_vars)
  1018.      HASH_TABLE *hashed_vars;
  1019. {
  1020.   register int i;
  1021.   register BUCKET_CONTENTS *bucket;
  1022.  
  1023.   for (i = 0; i < hashed_vars->nbuckets; i++)
  1024.     {
  1025.       bucket = hashed_vars->bucket_array[i];
  1026.  
  1027.       while (bucket)
  1028.     {
  1029.       BUCKET_CONTENTS *temp = bucket;
  1030.       SHELL_VAR *var, *prev;
  1031.  
  1032.       bucket = bucket->next;
  1033.  
  1034.       var = (SHELL_VAR *)temp->data;
  1035.  
  1036.       while (var)
  1037.         {
  1038.           prev = var->prev_context;
  1039.           dispose_variable (var);
  1040.  
  1041.           var = prev;
  1042.         }
  1043.  
  1044.       free (temp->key);
  1045.       free (temp);
  1046.     }
  1047.       hashed_vars->bucket_array[i] = (BUCKET_CONTENTS *)NULL;
  1048.     }
  1049. }
  1050.  
  1051. SHELL_VAR *
  1052. new_shell_variable (name)
  1053.      char *name;
  1054. {
  1055.   SHELL_VAR *var;
  1056.  
  1057.   var = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  1058.  
  1059.   bzero (var, sizeof (SHELL_VAR));
  1060.   var->name = savestring (name);
  1061.   return (var);
  1062. }
  1063.  
  1064. /* Do a function binding to a variable.  You pass the name and
  1065.    the command to bind to.  This conses the name and command. */
  1066. SHELL_VAR *
  1067. bind_function (name, value)
  1068.      char *name;
  1069.      COMMAND *value;
  1070. {
  1071.   SHELL_VAR *entry = find_function (name);
  1072.  
  1073.   if (!entry)
  1074.     {
  1075.       BUCKET_CONTENTS *elt;
  1076.  
  1077.       elt = add_hash_item (savestring (name), shell_functions);
  1078.  
  1079.       elt->data = (char *)new_shell_variable (name);
  1080.       entry = (SHELL_VAR *)elt->data;
  1081.       entry->dynamic_value = (DYNAMIC_FUNC *)NULL;
  1082.       entry->assign_func = (DYNAMIC_FUNC *)NULL;
  1083.  
  1084.       /* Functions are always made at the top level.  This allows a
  1085.      function to define another function (like autoload). */
  1086.       entry->context = 0;
  1087.     }
  1088.  
  1089.   if (entry->value)
  1090.     dispose_command (entry->value);
  1091.  
  1092.   if (value)    /* I don't think this can happen anymore */
  1093.     entry->value = (char *)copy_command (value);
  1094.   else
  1095.     entry->value = (char *)NULL;
  1096.  
  1097.   entry->attributes |= att_function;
  1098.  
  1099.   if (mark_modified_vars)
  1100.     entry->attributes |= att_exported;
  1101.  
  1102.   entry->attributes &= ~att_invisible;    /* Just to be sure */
  1103.  
  1104.   array_needs_making = 1;
  1105.  
  1106.   return (entry);
  1107. }
  1108.  
  1109. /* Copy VAR to a new data structure and return that structure. */
  1110. SHELL_VAR *
  1111. copy_variable (var)
  1112.      SHELL_VAR *var;
  1113. {
  1114.   SHELL_VAR *copy = (SHELL_VAR *)NULL;
  1115.  
  1116.   if (var)
  1117.     {
  1118.       copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
  1119.  
  1120.       copy->attributes = var->attributes;
  1121.       copy->name = savestring (var->name);
  1122.  
  1123.       if (function_p (var))
  1124.     copy->value = (char *)copy_command (var->value);
  1125.       else if (var->value)
  1126.     copy->value = savestring (var->value);
  1127.       else
  1128.     copy->value = (char *)NULL;
  1129.  
  1130.       copy->dynamic_value = var->dynamic_value;
  1131.       copy->assign_func = var->assign_func;
  1132.  
  1133.       copy->context = var->context;
  1134.  
  1135.       /* Don't bother copying previous contexts along with this variable. */
  1136.       copy->prev_context = (SHELL_VAR *)NULL;
  1137.     }
  1138.   return (copy);
  1139. }
  1140.  
  1141. /* Make the variable associated with NAME be read-only.
  1142.    If NAME does not exist yet, create it. */
  1143. set_var_read_only (name)
  1144.      char *name;
  1145. {
  1146.   SHELL_VAR *entry = find_variable (name);
  1147.  
  1148.   if (!entry)
  1149.     {
  1150.       entry = bind_variable (name, "");
  1151.       if (!no_invisible_vars)
  1152.     entry->attributes |= att_invisible;
  1153.     }
  1154.   entry->attributes |= att_readonly;
  1155. }
  1156.  
  1157. /* Make the function associated with NAME be read-only.
  1158.    If NAME does not exist, we just punt, like auto_export code below. */
  1159. set_func_read_only (name)
  1160.      char *name;
  1161. {
  1162.   SHELL_VAR *entry = find_function (name);
  1163.  
  1164.   if (entry)
  1165.     entry->attributes |= att_readonly;
  1166. }
  1167.  
  1168. /* Make the variable associated with NAME be auto-exported.
  1169.    If NAME does not exist yet, create it. */
  1170. set_var_auto_export (name)
  1171.      char *name;
  1172. {
  1173.   SHELL_VAR *entry = find_variable (name);
  1174.  
  1175.   if (!entry)
  1176.     {
  1177.       entry = bind_variable (name, "");
  1178.       if (!no_invisible_vars)
  1179.     entry->attributes |= att_invisible;
  1180.     }
  1181.  
  1182.   set_auto_export (entry);
  1183. }
  1184.  
  1185. /* Make the function associated with NAME be auto-exported. */
  1186. set_func_auto_export (name)
  1187.      char *name;
  1188. {
  1189.   SHELL_VAR *entry = find_function (name);
  1190.  
  1191.   if (entry)
  1192.     {
  1193.       entry->attributes |= att_exported;
  1194.       array_needs_making = 1;
  1195.     }
  1196. }
  1197.  
  1198. /* Returns non-zero if STRING is an assignment statement.  The returned value
  1199.    is the index of the `=' sign. */
  1200. assignment (string)
  1201.      char *string;
  1202. {
  1203.   register int c, index = 0;
  1204.  
  1205.   c = string[index];
  1206.  
  1207.   if (!isletter (c) && c != '_')
  1208.     return (0);
  1209.  
  1210.   while (c = string[index])
  1211.     {
  1212.       /* The following is safe.  Note that '=' at the start of a word
  1213.      is not an assignment statement. */
  1214.       if (c == '=')
  1215.     return (index);
  1216.  
  1217.       if (!isletter (c) && !digit (c) && c != '_')
  1218.     return (0);
  1219.  
  1220.       index++;
  1221.     }
  1222.   return (0);
  1223. }
  1224.  
  1225. int
  1226. visible_var (var)
  1227.      SHELL_VAR *var;
  1228. {
  1229.   return (!invisible_p (var));
  1230. }
  1231.  
  1232. SHELL_VAR **
  1233. all_visible_variables ()
  1234. {
  1235.   SHELL_VAR **list;
  1236.  
  1237.   list = map_over (visible_var, shell_variables);
  1238.  
  1239.   if (list)
  1240.     sort_variables (list);
  1241.  
  1242.   return (list);
  1243. }
  1244.  
  1245. SHELL_VAR **
  1246. all_visible_functions ()
  1247. {
  1248.   SHELL_VAR **list;
  1249.  
  1250.   list = map_over (visible_var, shell_functions);
  1251.  
  1252.   if (list)
  1253.     sort_variables (list);
  1254.  
  1255.   return (list);
  1256. }
  1257.  
  1258. /* Return non-zero if the variable VAR is visible and exported. */
  1259. int
  1260. visible_and_exported (var)
  1261.      SHELL_VAR *var;
  1262. {
  1263.   return (!invisible_p (var) && exported_p (var));
  1264. }
  1265.  
  1266. /* Make an array of assignment statements from the hash table
  1267.    HASHED_VARS which contains SHELL_VARs.  Only visible, exported
  1268.    variables are eligible. */
  1269. char **
  1270. make_var_array (hashed_vars)
  1271.      HASH_TABLE *hashed_vars;
  1272. {
  1273.   register int i, list_index;
  1274.   register SHELL_VAR *var;
  1275.   char **list = (char **)NULL;
  1276.   SHELL_VAR **vars;
  1277.  
  1278.   vars = map_over (visible_and_exported, hashed_vars);
  1279.  
  1280.   if (!vars)
  1281.     return (char **)NULL;
  1282.  
  1283.   list = (char **)xmalloc ((1 + array_len ((char **)vars)) * sizeof (char *));
  1284.  
  1285.   for (i = 0, list_index = 0; var = vars[i]; i++)
  1286.     {
  1287.       char *value, *named_function_string ();
  1288.  
  1289.       if (function_p (var))
  1290.     {
  1291.       value =
  1292.         named_function_string ((char *)NULL,
  1293.                    (COMMAND *)function_cell (var), 0);
  1294.     }
  1295.       else
  1296.     value = value_cell (var);
  1297.  
  1298.       if (value)
  1299.     {
  1300. #if 0
  1301.       list[list_index] =
  1302.         (char *)xmalloc (2 + strlen (var->name) + strlen (value));
  1303.  
  1304.       sprintf (list[list_index], "%s=%s", var->name, value);
  1305. #else
  1306.       /* Let's see if this makes any kind of performance difference. */
  1307.       int name_len = strlen (var->name);
  1308.       int value_len = strlen (value);
  1309.       char    *p;
  1310.  
  1311.       p = list[list_index] =  (char *)xmalloc (2 + name_len + value_len);
  1312.       strcpy (p, var->name);
  1313.       p[name_len] = '=';
  1314.       strcpy (&p[name_len + 1], value);
  1315. #endif
  1316.       list_index++;
  1317.     }
  1318.     }
  1319.  
  1320.   free (vars);
  1321.   list[list_index] = (char *)NULL;
  1322.   return (list);
  1323. }
  1324.  
  1325. /* Add STRING to the array of foo=bar strings that we already
  1326.    have to add to the environment.  */
  1327. assign_in_env (string)
  1328.      char *string;
  1329. {
  1330.   int size;
  1331.  
  1332.   int offset = assignment (string);
  1333.   char *name = savestring (string);
  1334.   char *temp, *value = (char *)NULL;
  1335.  
  1336.   if (name[offset] == '=')
  1337.     {
  1338.       char *tilde_expand (), *string_list ();
  1339.       WORD_LIST *list, *expand_string_unsplit ();
  1340.  
  1341.       name[offset] = 0;
  1342.       temp = name + offset + 1;
  1343.       temp = tilde_expand (temp);
  1344.  
  1345.       list = expand_string_unsplit (temp, 0);
  1346.       value = string_list (list);
  1347.  
  1348.       if (list)
  1349.     dispose_words (list);
  1350.  
  1351.       free (temp);
  1352.     }
  1353.  
  1354.   if (!value) value = savestring ("");
  1355.  
  1356.   temp = (char *)xmalloc (2 + strlen (name) + strlen (value));
  1357.   sprintf (temp, "%s=%s", name, value);
  1358.   free (name);
  1359.  
  1360.   if (!temporary_env)
  1361.     {
  1362.       temporary_env = (char **)xmalloc (sizeof (char *));
  1363.       temporary_env [0] = (char *)NULL;
  1364.     }
  1365.  
  1366.   size = array_len (temporary_env);
  1367.   temporary_env = (char **)
  1368.     xrealloc (temporary_env, (size + 2) * (sizeof (char *)));
  1369.  
  1370.   temporary_env[size] = (temp);
  1371.   temporary_env[size + 1] = (char *)NULL;
  1372.   array_needs_making = 1;
  1373.  
  1374.   if (echo_command_at_execute)
  1375.     {
  1376.       /* The K*rn shell prints the `+ ' in front of assignment statements,
  1377.      so we do too. */
  1378.       extern char *indirection_level_string ();
  1379.       fprintf (stderr, "%s%s\n", indirection_level_string (), temp);
  1380.       fflush (stderr);
  1381.     }
  1382. }
  1383.  
  1384. /* Find a variable in the temporary environment that is named NAME.
  1385.    Return a consed variable, or NULL if not found. */
  1386. SHELL_VAR *
  1387. find_tempenv_variable (name)
  1388.      char *name;
  1389. {
  1390.   register int i, l = strlen (name);
  1391.  
  1392.   if (!temporary_env)
  1393.     return ((SHELL_VAR *)NULL);
  1394.  
  1395.   for (i = 0; temporary_env[i]; i++)
  1396.     {
  1397.       if (strncmp (temporary_env[i], name, l) == 0 &&
  1398.       temporary_env[i][l] == '=')
  1399.     {
  1400.       SHELL_VAR *temp;
  1401.  
  1402.       temp = new_shell_variable (name);
  1403.  
  1404.       if (temporary_env[i][l + 1])
  1405.         temp->value = savestring (&temporary_env[i][l + 1]);
  1406.       else
  1407.         temp->value = savestring ("");
  1408.       temp->attributes = att_exported;
  1409.       temp->context = 0;
  1410.       temp->prev_context = (SHELL_VAR *)NULL;
  1411.  
  1412.       temp->dynamic_value = (DYNAMIC_FUNC *)NULL;
  1413.       temp->assign_func = (DYNAMIC_FUNC *)NULL;
  1414.  
  1415.       return (temp);
  1416.     }
  1417.     }
  1418.   return ((SHELL_VAR *)NULL);
  1419. }
  1420.  
  1421. /* Free the storage used in the variable array for temporary
  1422.    environment variables. */
  1423. dispose_used_env_vars ()
  1424. {
  1425.   if (!temporary_env)
  1426.     return;
  1427.  
  1428.   free_array (temporary_env);
  1429.   temporary_env = (char **)NULL;
  1430.   array_needs_making = 1;
  1431. }
  1432.  
  1433. /* Stupid comparison routine for qsort () ing strings. */
  1434. qsort_string_compare (s1, s2)
  1435.      register char **s1, **s2;
  1436. {
  1437.   return (strcmp (*s1, *s2));
  1438. }
  1439.  
  1440. /* Sort ARRAY, a null terminated array of pointers to strings. */
  1441. sort_char_array (array)
  1442.      char **array;
  1443. {
  1444.   qsort (array, array_len (array), sizeof (char *), qsort_string_compare);
  1445. }
  1446.  
  1447. #define ISFUNC(s, o) ((s[o + 1] == '(')  && (s[o + 2] == ')'))
  1448.  
  1449. /* Add ASSIGN to ARRAY, or supercede a previous assignment in the
  1450.    array with the same left-hand side.  Return the new array. */
  1451. char **
  1452. add_or_supercede (assign, array)
  1453.      char *assign;
  1454.      register char **array;
  1455. {
  1456.   register int i;
  1457.   int equal_offset = assignment (assign);
  1458.  
  1459.   if (!equal_offset)
  1460.     return (array);
  1461.  
  1462.   /* If this is a function, then only supercede the function definition.
  1463.      We do this by including the `=(' in the comparison.  */
  1464.   if (assign[equal_offset + 1] == '(')
  1465.     equal_offset++;
  1466.  
  1467.   for (i = 0; array[i]; i++)
  1468.     {
  1469.       if (STREQN (assign, array[i], equal_offset + 1))
  1470.     {
  1471.       free (array[i]);
  1472.       array[i] = savestring (assign);
  1473.       return (array);
  1474.     }
  1475.     }
  1476.   array = (char **)xrealloc (array, ((2 + i) * sizeof (char *)));
  1477.   array[i++] = savestring (assign);
  1478.   array[i] = (char *)NULL;
  1479.   return (array);
  1480. }
  1481.  
  1482. /* Make the environment array for the command about to be executed.  If the
  1483.    array needs making.  Otherwise, do nothing.  If a shell action could
  1484.    change the array that commands receive for their environment, then the
  1485.    code should `array_needs_making++'. */
  1486. maybe_make_export_env ()
  1487. {
  1488.   register int i;
  1489.   register char **temp_array;
  1490.  
  1491.   if (array_needs_making)
  1492.     {
  1493.       if (export_env)
  1494.     free_array (export_env);
  1495.  
  1496. #ifdef SHADOWED_ENV
  1497.       export_env =
  1498.     (char **)xmalloc ((1 + array_len (shell_environment)) * sizeof (char *));
  1499.  
  1500.       for (i = 0; shell_environment[i]; i++)
  1501.     export_env[i] = savestring (shell_environment[i]);
  1502.       export_env[i] = (char *)NULL;
  1503.  
  1504. #else /* !SHADOWED_ENV */
  1505.  
  1506.       export_env = (char **)xmalloc (sizeof (char *));
  1507.       export_env[0] = (char *)NULL;
  1508.  
  1509. #endif /* SHADOWED_ENV */
  1510.  
  1511.       temp_array = make_var_array (shell_variables);
  1512.       for (i = 0; temp_array && temp_array[i]; i++)
  1513.     export_env = add_or_supercede (temp_array[i], export_env);
  1514.       free_array (temp_array);
  1515.  
  1516.       temp_array = make_var_array (shell_functions);
  1517.       for (i = 0; temp_array && temp_array[i]; i++)
  1518.     export_env = add_or_supercede (temp_array[i], export_env);
  1519.       free_array (temp_array);
  1520.  
  1521.       if (temporary_env)
  1522.     {
  1523.       for (i = 0; temporary_env[i]; i++)
  1524.         export_env = add_or_supercede (temporary_env[i], export_env);
  1525.  
  1526.       /* Sort the array alphabetically. */
  1527.       sort_char_array (export_env);
  1528.     }
  1529.       array_needs_making = 0;
  1530.     }
  1531. }
  1532.  
  1533. /* We always put _ in the environment as the name of this command. */
  1534. put_command_name_into_env (command_name)
  1535.      char *command_name;
  1536. {
  1537.   char *dummy;
  1538.  
  1539.   dummy = (char *)xmalloc (4 + strlen (command_name));
  1540.  
  1541.   /* These three statements replace a call to sprintf */
  1542.   dummy[0] = '_';
  1543.   dummy[1] = '=';
  1544.   strcpy (&dummy[2], command_name);
  1545.   export_env = add_or_supercede (dummy, export_env);
  1546.   free (dummy);
  1547. }
  1548.  
  1549. /* We supply our own version of getenv () because we want library
  1550.    routines to get the changed values of exported variables. */
  1551. char *last_tempenv_value = (char *)NULL;
  1552.  
  1553. /* The NeXT C library has getenv () defined and used in the same file.
  1554.    This screws our scheme.  However, Bash will run on the NeXT using
  1555.    the C library getenv (), since right now the only environment variable
  1556.    that we care about is HOME, and that is already defined.  */
  1557. #if !defined (NeXT)
  1558. char *
  1559. getenv (name)
  1560.      char *name;
  1561. {
  1562.   SHELL_VAR *var = find_tempenv_variable (name);
  1563.  
  1564.   if (var)
  1565.     {
  1566.       if (last_tempenv_value)
  1567.     free (last_tempenv_value);
  1568.  
  1569.       last_tempenv_value = savestring (value_cell (var));
  1570.       dispose_variable (var);
  1571.       return (last_tempenv_value);
  1572.     }
  1573.   else if (shell_variables)
  1574.     {
  1575.       var = find_variable (name);
  1576.       if (var && exported_p (var))
  1577.     return (value_cell (var));
  1578.     }
  1579.   else
  1580.     {
  1581.       register int i, len = strlen (name);
  1582.       extern char **environ;
  1583.  
  1584.       /* In some cases, s5r3 invokes getenv() before main(); BSD systems
  1585.          using gprof also exhibit this behavior.  This means that
  1586.          shell_variables will be 0 when this is invoked.  We look up the
  1587.      variable in the real environment in that case. */
  1588.  
  1589.       for (i = 0; environ[i]; i++)
  1590.     {
  1591.       if ((strncmp (environ[i], name, len) == 0) &&
  1592.           (environ[i][len] == '='))
  1593.         return (environ[i] + len + 1);
  1594.     }
  1595.     }
  1596.  
  1597.   return ((char *)NULL);
  1598. }
  1599. #endif /* NeXT */
  1600.