Imported from ../bash-2.02.tar.gz.

This commit is contained in:
Jari Aalto
1998-04-17 19:52:44 +00:00
parent e8ce775db8
commit cce855bc5b
323 changed files with 33916 additions and 12321 deletions

View File

@@ -39,15 +39,23 @@
#include "shell.h"
#include "flags.h"
#include "execute_cmd.h"
#include "findcmd.h"
#include "mailcheck.h"
#include "input.h"
#include "builtins/getopt.h"
#include "builtins/common.h"
#include <tilde/tilde.h>
#if defined (READLINE)
# include "bashline.h"
# include <readline/readline.h>
#else
# include <tilde/tilde.h>
#endif
#if defined (HISTORY)
# include "bashhist.h"
# include <readline/history.h>
#endif /* HISTORY */
/* Variables used here and defined in other files. */
@@ -129,20 +137,22 @@ static int qsort_var_comp ();
#define set_auto_export(var) \
do { var->attributes |= att_exported; array_needs_making = 1; } while (0)
/* Initialize the shell variables from the current environment. */
/* Initialize the shell variables from the current environment.
If PRIVMODE is nonzero, don't import functions from ENV or
parse $SHELLOPTS. */
void
initialize_shell_variables (env, no_functions)
initialize_shell_variables (env, privmode)
char **env;
int no_functions; /* If set, don't import functions from ENV. */
int privmode;
{
char *name, *string, *temp_string;
int c, char_index, string_index, string_length;
SHELL_VAR *temp_var;
if (!shell_variables)
if (shell_variables == 0)
shell_variables = make_hash_table (0);
if (!shell_functions)
if (shell_functions == 0)
shell_functions = make_hash_table (0);
for (string_index = 0; string = env[string_index++]; )
@@ -165,7 +175,7 @@ initialize_shell_variables (env, no_functions)
char_index == strlen (name) */
/* If exported function, define it now. */
if (no_functions == 0 && STREQN ("() {", string, 4))
if (privmode == 0 && STREQN ("() {", string, 4))
{
string_length = strlen (string);
temp_string = xmalloc (3 + string_length + char_index);
@@ -233,7 +243,8 @@ initialize_shell_variables (env, no_functions)
temp_string = get_working_directory ("shell-init");
if (temp_string)
{
bind_variable ("PWD", temp_string);
temp_var = bind_variable ("PWD", temp_string);
set_auto_export (temp_var);
free (temp_string);
}
}
@@ -500,7 +511,7 @@ adjust_shell_level (change)
shell_level = 0;
else if (shell_level > 1000)
{
internal_error ("warning: shell level (%d) too high, resetting to 1", shell_level);
internal_warning ("shell level (%d) too high, resetting to 1", shell_level);
shell_level = 1;
}
@@ -626,7 +637,7 @@ set_if_not (name, value)
SHELL_VAR *v;
v = find_variable (name);
if (!v)
if (v == 0)
v = bind_variable (name, value);
return (v);
}
@@ -873,7 +884,7 @@ assign_seconds (self, value)
SHELL_VAR *self;
char *value;
{
seconds_value_assigned = string_to_long (value);
seconds_value_assigned = strtol (value, (char **)NULL, 10);
shell_start_time = NOW;
return (self);
}
@@ -900,18 +911,15 @@ static unsigned long rseed = 1;
static unsigned long last_random_value;
/* A linear congruential random number generator based on the ANSI
C standard. A more complicated one is overkill. */
C standard. This one isn't very good (the values are alternately
odd and even, for example), but a more complicated one is overkill. */
/* Returns a pseudo-random number between 0 and 32767. */
static int
brand ()
{
rseed = rseed * 1103515245 + 12345;
#if 0
return ((unsigned int)(rseed / 65536) % 32768);
#else
return ((unsigned int)(rseed % 32768));
#endif
return ((unsigned int)(rseed & 32767)); /* was % 32768 */
}
/* Set the random number generator seed to SEED. */
@@ -1143,7 +1151,8 @@ find_function (name)
/* Return the string value of a variable. Return NULL if the variable
doesn't exist, or only has a function as a value. Don't cons a new
string. */
string. This is a potential memory leak if the variable is found
in the temporary environment. */
char *
get_string_value (var_name)
char *var_name;
@@ -1451,6 +1460,8 @@ bind_array_variable (name, ind, value)
return (entry);
}
/* Perform a compound assignment statement for array NAME, where VALUE is
the text between the parens: NAME=( VALUE ) */
SHELL_VAR *
assign_array_from_string (name, value)
char *name, *value;
@@ -1467,10 +1478,6 @@ assign_array_from_string (name, value)
}
else if (array_p (var) == 0)
var = convert_var_to_array (var);
#if 0
else
empty_array (array_cell (var));
#endif
return (assign_array_var_from_string (var, value));
}
@@ -1492,6 +1499,8 @@ assign_array_var_from_word_list (var, list)
return var;
}
/* Perform a compound array assignment: VAR->name=( VALUE ). The
VALUE has already had the parentheses stripped. */
SHELL_VAR *
assign_array_var_from_string (var, value)
SHELL_VAR *var;
@@ -1502,28 +1511,45 @@ assign_array_var_from_string (var, value)
char *w, *val, *nval;
int ni, len, ind, last_ind;
a = array_cell (var);
if (value == 0)
return var;
/* Expand the value string into a list of words, performing all the
shell expansions including word splitting. */
if (*value == '(')
/* If this is called from declare_builtin, value[0] == '(' and
strchr(value, ')') != 0. In this case, we need to extract
the value from between the parens before going on. */
if (*value == '(') /*)*/
{
ni = 1;
val = extract_array_assignment_list (value, &ni);
if (val == 0)
return var;
nlist = expand_string (val, 0);
free (val);
return var;
}
else
nlist = expand_string (value, 0);
val = value;
/* Expand the value string into a list of words, performing all the
shell expansions including word splitting. */
#if 1
/* First we split the string on whitespace, using the shell parser
(ksh93 seems to do this). */
list = parse_string_to_word_list (val, "array assign");
/* Now that we've split it, perform the shell expansions on each
word in the list. */
nlist = list ? expand_words_shellexp (list) : (WORD_LIST *)NULL;
dispose_words (list);
#else
nlist = expand_string (val, 0);
#endif
if (val != value)
free (val);
a = array_cell (var);
/* Now that we are ready to assign values to the array, kill the existing
value. */
if (a)
empty_array (a);
#endif
for (last_ind = 0, list = nlist; list; list = list->next)
{
@@ -1656,8 +1682,9 @@ int
unbind_variable (name)
char *name;
{
SHELL_VAR *var = find_variable (name);
SHELL_VAR *var;
var = find_variable (name);
if (!var)
return (-1);
@@ -1947,6 +1974,7 @@ set_var_read_only (name)
entry->attributes |= att_readonly;
}
#ifdef INCLUDE_UNUSED
/* Make the function associated with NAME be readonly.
If NAME does not exist, we just punt, like auto_export code below. */
void
@@ -1983,6 +2011,7 @@ set_func_auto_export (name)
if (entry)
set_auto_export (entry);
}
#endif
#if defined (ARRAY_VARS)
/* This function assumes s[i] == '['; returns with s[ret] == ']' if
@@ -2045,6 +2074,8 @@ assignment (string)
return (0);
}
#ifdef READLINE
static int
visible_var (var)
SHELL_VAR *var;
@@ -2078,6 +2109,8 @@ all_visible_functions ()
return (_visible_names (shell_functions));
}
#endif /* READLINE */
/* Return non-zero if the variable VAR is visible and exported. Array
variables cannot be exported. */
static int
@@ -2161,7 +2194,6 @@ assign_in_env (string)
name = savestring (string);
value = (char *)NULL;
#define freetemp nlen
if (name[offset] == '=')
{
name[offset] = 0;
@@ -2174,9 +2206,7 @@ assign_in_env (string)
return (0);
}
temp = name + offset + 1;
freetemp = strchr (temp, '~') != 0;
if (freetemp)
temp = bash_tilde_expand (temp);
temp = (strchr (temp, '~') != 0) ? bash_tilde_expand (temp) : savestring (temp);
list = expand_string_unsplit (temp, 0);
value = string_list (list);
@@ -2184,10 +2214,8 @@ assign_in_env (string)
if (list)
dispose_words (list);
if (freetemp)
free (temp);
free (temp);
}
#undef freetemp
nlen = strlen (name);
vlen = value ? strlen (value) : 0;
@@ -2248,12 +2276,15 @@ find_name_in_env_array (name, array)
SHELL_VAR *temp;
char *w;
temp = new_shell_variable (name); /* XXX memory leak here */
/* This is a potential memory leak. The code should really save
the created variables in some auxiliary data structure, which
can be disposed of at the appropriate time. */
temp = new_shell_variable (name);
w = array[i] + l + 1;
temp->value = *w ? savestring (w) : (char *)NULL;
temp->attributes = att_exported;
temp->attributes = att_exported|att_tempvar;
temp->context = 0;
temp->prev_context = (SHELL_VAR *)NULL;
@@ -2275,7 +2306,9 @@ SHELL_VAR *
find_tempenv_variable (name)
char *name;
{
SHELL_VAR *var = (SHELL_VAR *)NULL;
SHELL_VAR *var;
var = (SHELL_VAR *)NULL;
if (temporary_env)
var = find_name_in_env_array (name, temporary_env);
@@ -2379,7 +2412,7 @@ do \
export_env[export_env_index] = (char *)NULL; \
} while (0)
#define ISFUNC(s, o) ((s[o + 1] == '(') && (s[o + 2] == ')'))
#define ISFUNCTION(s, o) ((s[o + 1] == '(') && (s[o + 2] == ')'))
/* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
array with the same left-hand side. Return the new EXPORT_ENV. */
@@ -2492,6 +2525,7 @@ put_command_name_into_env (command_name)
export_env = add_or_supercede_exported_var (dummy, 0);
}
#if 0 /* UNUSED -- it caused too many problems */
void
put_gnu_argv_flags_into_env (pid, flags_string)
int pid;
@@ -2516,6 +2550,7 @@ put_gnu_argv_flags_into_env (pid, flags_string)
export_env = add_or_supercede_exported_var (dummy, 0);
}
#endif
/* Return a string denoting what our indirection level is. */
static char indirection_string[100];
@@ -2544,3 +2579,374 @@ indirection_level_string ()
free (ps4);
return (indirection_string);
}
/*************************************************
* *
* Functions to manage special variables *
* *
*************************************************/
/* Extern declarations for variables this code has to manage. */
extern int eof_encountered, eof_encountered_limit, ignoreeof;
#if defined (READLINE)
extern int no_line_editing;
extern int hostname_list_initialized;
#endif
/* An alist of name.function for each special variable. Most of the
functions don't do much, and in fact, this would be faster with a
switch statement, but by the end of this file, I am sick of switch
statements. */
#define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0
struct name_and_function {
char *name;
VFunction *function;
} special_vars[] = {
{ "PATH", sv_path },
{ "MAIL", sv_mail },
{ "MAILPATH", sv_mail },
{ "MAILCHECK", sv_mail },
{ "POSIXLY_CORRECT", sv_strict_posix },
{ "GLOBIGNORE", sv_globignore },
/* Variables which only do something special when READLINE is defined. */
#if defined (READLINE)
{ "TERM", sv_terminal },
{ "TERMCAP", sv_terminal },
{ "TERMINFO", sv_terminal },
{ "HOSTFILE", sv_hostfile },
#endif /* READLINE */
/* Variables which only do something special when HISTORY is defined. */
#if defined (HISTORY)
{ "HISTIGNORE", sv_histignore },
{ "HISTSIZE", sv_histsize },
{ "HISTFILESIZE", sv_histsize },
{ "HISTCONTROL", sv_history_control },
# if defined (BANG_HISTORY)
{ "histchars", sv_histchars },
# endif /* BANG_HISTORY */
#endif /* HISTORY */
{ "IGNOREEOF", sv_ignoreeof },
{ "ignoreeof", sv_ignoreeof },
{ "OPTIND", sv_optind },
{ "OPTERR", sv_opterr },
{ "TEXTDOMAIN", sv_locale },
{ "TEXTDOMAINDIR", sv_locale },
{ "LC_ALL", sv_locale },
{ "LC_COLLATE", sv_locale },
{ "LC_CTYPE", sv_locale },
{ "LC_MESSAGES", sv_locale },
{ "LANG", sv_locale },
#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
{ "TZ", sv_tz },
#endif
{ (char *)0, (VFunction *)0 }
};
/* The variable in NAME has just had its state changed. Check to see if it
is one of the special ones where something special happens. */
void
stupidly_hack_special_variables (name)
char *name;
{
int i;
for (i = 0; special_vars[i].name; i++)
{
if (STREQ (special_vars[i].name, name))
{
(*(special_vars[i].function)) (name);
return;
}
}
}
/* What to do just after the PATH variable has changed. */
void
sv_path (name)
char *name;
{
/* hash -r */
flush_hashed_filenames ();
}
/* What to do just after one of the MAILxxxx variables has changed. NAME
is the name of the variable. This is called with NAME set to one of
MAIL, MAILCHECK, or MAILPATH. */
void
sv_mail (name)
char *name;
{
/* If the time interval for checking the files has changed, then
reset the mail timer. Otherwise, one of the pathname vars
to the users mailbox has changed, so rebuild the array of
filenames. */
if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */
reset_mail_timer ();
else
{
free_mail_files ();
remember_mail_dates ();
}
}
/* What to do when GLOBIGNORE changes. */
void
sv_globignore (name)
char *name;
{
setup_glob_ignore (name);
}
#if defined (READLINE)
/* What to do just after one of the TERMxxx variables has changed.
If we are an interactive shell, then try to reset the terminal
information in readline. */
void
sv_terminal (name)
char *name;
{
if (interactive_shell && no_line_editing == 0)
rl_reset_terminal (get_string_value ("TERM"));
}
void
sv_hostfile (name)
char *name;
{
hostname_list_initialized = 0;
}
#endif /* READLINE */
#if defined (HISTORY)
/* What to do after the HISTSIZE or HISTFILESIZE variables change.
If there is a value for this HISTSIZE (and it is numeric), then stifle
the history. Otherwise, if there is NO value for this variable,
unstifle the history. If name is HISTFILESIZE, and its value is
numeric, truncate the history file to hold no more than that many
lines. */
void
sv_histsize (name)
char *name;
{
char *temp;
long num;
temp = get_string_value (name);
if (temp && *temp)
{
if (legal_number (temp, &num))
{
if (name[4] == 'S')
{
stifle_history (num);
num = where_history ();
if (history_lines_this_session > num)
history_lines_this_session = num;
}
else
{
history_truncate_file (get_string_value ("HISTFILE"), (int)num);
if (num <= history_lines_in_file)
history_lines_in_file = num;
}
}
}
else if (name[4] == 'S')
unstifle_history ();
}
/* What to do after the HISTIGNORE variable changes. */
void
sv_histignore (name)
char *name;
{
setup_history_ignore (name);
}
/* What to do after the HISTCONTROL variable changes. */
void
sv_history_control (name)
char *name;
{
char *temp;
history_control = 0;
temp = get_string_value (name);
if (temp && *temp && STREQN (temp, "ignore", 6))
{
if (temp[6] == 's') /* ignorespace */
history_control = 1;
else if (temp[6] == 'd') /* ignoredups */
history_control = 2;
else if (temp[6] == 'b') /* ignoreboth */
history_control = 3;
}
}
#if defined (BANG_HISTORY)
/* Setting/unsetting of the history expansion character. */
void
sv_histchars (name)
char *name;
{
char *temp;
temp = get_string_value (name);
if (temp)
{
history_expansion_char = *temp;
if (temp[0] && temp[1])
{
history_subst_char = temp[1];
if (temp[2])
history_comment_char = temp[2];
}
}
else
{
history_expansion_char = '!';
history_subst_char = '^';
history_comment_char = '#';
}
}
#endif /* BANG_HISTORY */
#endif /* HISTORY */
#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
void
sv_tz (name)
char *name;
{
tzset ();
}
#endif
/* If the variable exists, then the value of it can be the number
of times we actually ignore the EOF. The default is small,
(smaller than csh, anyway). */
void
sv_ignoreeof (name)
char *name;
{
SHELL_VAR *tmp_var;
char *temp;
eof_encountered = 0;
tmp_var = find_variable (name);
ignoreeof = tmp_var != 0;
temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
if (temp)
eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
set_shellopts (); /* make sure `ignoreeof' is/is not in $SHELLOPTS */
}
void
sv_optind (name)
char *name;
{
char *tt;
int s;
tt = get_string_value ("OPTIND");
if (tt && *tt)
{
s = atoi (tt);
/* According to POSIX, setting OPTIND=1 resets the internal state
of getopt (). */
if (s < 0 || s == 1)
s = 0;
}
else
s = 0;
getopts_reset (s);
}
void
sv_opterr (name)
char *name;
{
char *tt;
tt = get_string_value ("OPTERR");
sh_opterr = (tt && *tt) ? atoi (tt) : 1;
}
void
sv_strict_posix (name)
char *name;
{
SET_INT_VAR (name, posixly_correct);
posix_initialize (posixly_correct);
#if defined (READLINE)
if (interactive_shell)
posix_readline_initialize (posixly_correct);
#endif /* READLINE */
set_shellopts (); /* make sure `posix' is/is not in $SHELLOPTS */
}
void
sv_locale (name)
char *name;
{
char *v;
v = get_string_value (name);
if (name[0] == 'L' && name[1] == 'A') /* LANG */
set_lang (name, v);
else
set_locale_var (name, v); /* LC_*, TEXTDOMAIN* */
}
#if defined (ARRAY_VARS)
void
set_pipestatus_array (ps)
int *ps;
{
SHELL_VAR *v;
ARRAY *a;
register int i;
char *t;
v = find_variable ("PIPESTATUS");
if (v == 0)
v = make_new_array_variable ("PIPESTATUS");
if (array_p (v) == 0)
return; /* Do nothing if not an array variable. */
a = array_cell (v);
if (a)
empty_array (a);
for (i = 0; ps[i] != -1; i++)
{
t = itos (ps[i]);
array_add_element (a, i, t);
free (t);
}
}
#endif
void
set_pipestatus_from_exit (s)
int s;
{
#if defined (ARRAY_VARS)
static int v[2] = { 0, -1 };
v[0] = s;
set_pipestatus_array (v);
#endif
}