bash-20120629 remove leftover and stray files

This commit is contained in:
Chet Ramey
2012-07-07 12:26:34 -04:00
parent d42cb8c15b
commit 23477ba0d3
41 changed files with 0 additions and 75699 deletions
-14137
View File
File diff suppressed because it is too large Load Diff
-82
View File
@@ -1,82 +0,0 @@
Starting bash with the `--posix' command-line option or executing
`set -o posix' while bash is running will cause bash to conform more
closely to the Posix.2 standard by changing the behavior to match that
specified by Posix.2 in areas where the bash default differs.
The following list is what's changed when `posix mode' is in effect:
1. When a command in the hash table no longer exists, bash will re-search
$PATH to find the new location. This is also available with
`shopt -s checkhash'.
2. The >& redirection does not redirect stdout and stderr.
3. The message printed by the job control code and builtins when a job
exits with a non-zero status is `Done(status)'.
4. Reserved words may not be aliased.
5. The Posix.2 PS1 and PS2 expansions of `!' -> history number and
`!!' -> `!' are enabled, and parameter expansion is performed on
the value regardless of the setting of the `promptvars' option.
6. Interactive comments are enabled by default. (Note that bash has
them on by default anyway.)
7. The Posix.2 startup files are executed ($ENV) rather than the normal
bash files.
8. Tilde expansion is only performed on assignments preceding a command
name, rather than on all assignment statements on the line.
9. The default history file is ~/.sh_history (default value of $HISTFILE).
10. The output of `kill -l' prints all the signal names on a single line,
separated by spaces.
11. Non-interactive shells exit if `file' in `. file' is not found.
12. Redirection operators do not perform pathname expansion on the word
in the redirection unless the shell is interactive
13. Function names must be valid shell identifiers. That is, they may not
contain characters other than letters, digits, and underscores, and
may not start with a digit. Declaring a function with an illegal name
causes a fatal syntax error in non-interactive shells.
14. Posix.2 `special' builtins are found before shell functions during command
lookup.
15. If a Posix.2 special builtin returns an error status, a non-interactive
shell exits. The fatal errors are those listed in the POSIX.2 standard,
and include things like passing incorrect options, redirection errors,
variable assignment errors for assignments preceding the command name,
and so on.
16. The environment passed to executed commands is not sorted. Neither is
the output of `set'. This is not strictly Posix.2 behavior, but sh
does it this way. Ksh does not. It's not necessary to sort the
environment; no program should rely on it being sorted.
17. If the `cd' builtin finds a directory to change to using $CDPATH, the
value it assigns to $PWD does not contain any symbolic links, as if
`cd -P' had been executed.
18. A non-interactive shell exits with an error status if a variable
assignment error occurs when no command name follows the assignment
statements. A variable assignment error occurs, for example, when
trying to assign a value to a read-only variable.
19. A non-interactive shell exits with an error status if the iteration
variable in a for statement or the selection variable in a select
statement is a read-only variable.
20. Process substitution is not available.
21. Assignment statements preceding POSIX.2 `special' builtins persist in
the shell environment after the builtin completes.
There is other Posix.2 behavior that bash does not implement. Specifically:
1. Assignment statements affect the execution environment of all builtins,
not just special ones.
-544
View File
@@ -1,544 +0,0 @@
This file is set.def, from which is created set.c.
It implements the "set" and "unset" builtins in Bash.
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
$PRODUCES set.c
#include <stdio.h>
#include "../shell.h"
#include "../flags.h"
#include "bashgetopt.h"
extern int interactive;
extern int noclobber, posixly_correct;
#if defined (READLINE)
extern int rl_editing_mode, no_line_editing;
#endif /* READLINE */
$BUILTIN set
$FUNCTION set_builtin
$SHORT_DOC set [--abefhkmnptuvxldBCHP] [-o option] [arg ...]
-a Mark variables which are modified or created for export.
-b Notify of job termination immediately.
-e Exit immediately if a command exits with a non-zero status.
-f Disable file name generation (globbing).
-h Locate and remember function commands as functions are
defined. Function commands are normally looked up when
the function is executed.
-i Force the shell to be an "interactive" one. Interactive shells
always read `~/.bashrc' on startup.
-k All keyword arguments are placed in the environment for a
command, not just those that precede the command name.
-m Job control is enabled.
-n Read commands but do not execute them.
-o option-name
Set the variable corresponding to option-name:
allexport same as -a
braceexpand same as -B
#if defined (READLINE)
emacs use an emacs-style line editing interface
#endif /* READLINE */
errexit same as -e
histexpand same as -H
ignoreeof the shell will not exit upon reading EOF
interactive-comments
allow comments to appear in interactive commands
monitor same as -m
noclobber disallow redirection to existing files
noexec same as -n
noglob same as -f
nohash same as -d
notify save as -b
nounset same as -u
physical same as -P
posix change the behavior of bash where the default
operation differs from the 1003.2 standard to
match the standard
privileged same as -p
verbose same as -v
#if defined (READLINE)
vi use a vi-style line editing interface
#endif /* READLINE */
xtrace same as -x
-p Turned on whenever the real and effective user ids do not match.
Disables processing of the $ENV file and importing of shell
functions. Turning this option off causes the effective uid and
gid to be set to the real uid and gid.
-t Exit after reading and executing one command.
-u Treat unset variables as an error when substituting.
-v Print shell input lines as they are read.
-x Print commands and their arguments as they are executed.
-l Save and restore the binding of the NAME in a FOR command.
-d Disable the hashing of commands that are looked up for execution.
Normally, commands are remembered in a hash table, and once
found, do not have to be looked up again.
#if defined (BRACE_EXPANSION)
-B the shell will perform brace expansion
#endif /* BRACE_EXPANSION */
#if defined (BANG_HISTORY)
-H Enable ! style history substitution. This flag is on
by default.
#endif /* BANG_HISTORY */
-C If set, disallow existing regular files to be overwritten
by redirection of output.
-P If set, do not follow symbolic links when executing commands
such as cd which change the current directory.
Using + rather than - causes these flags to be turned off. The
flags can also be used upon invocation of the shell. The current
set of flags may be found in $-. The remaining n ARGs are positional
parameters and are assigned, in order, to $1, $2, .. $n. If no
ARGs are given, all shell variables are printed.
$END
/* An a-list used to match long options for set -o to the corresponding
option letter. */
struct {
char *name;
int letter;
} o_options[] = {
{ "allexport", 'a' },
#if defined (BRACE_EXPANSION)
{ "braceexpand",'B' },
#endif
{ "errexit", 'e' },
{ "histexpand", 'H' },
{ "monitor", 'm' },
{ "noexec", 'n' },
{ "noglob", 'f' },
{ "nohash", 'd' },
#if defined (JOB_CONTROL)
{ "notify", 'b' },
#endif /* JOB_CONTROL */
{"nounset", 'u' },
{"physical", 'P' },
{"privileged", 'p' },
{"verbose", 'v' },
{"xtrace", 'x' },
{(char *)NULL, 0},
};
#define MINUS_O_FORMAT "%-15s\t%s\n"
void
list_minus_o_opts ()
{
register int i;
char *on = "on", *off = "off";
printf (MINUS_O_FORMAT, "noclobber", (noclobber == 1) ? on : off);
if (find_variable ("ignoreeof") || find_variable ("IGNOREEOF"))
printf (MINUS_O_FORMAT, "ignoreeof", on);
else
printf (MINUS_O_FORMAT, "ignoreeof", off);
printf (MINUS_O_FORMAT, "interactive-comments",
interactive_comments ? on : off);
printf (MINUS_O_FORMAT, "posix", posixly_correct ? on : off);
#if defined (READLINE)
if (no_line_editing)
{
printf (MINUS_O_FORMAT, "emacs", off);
printf (MINUS_O_FORMAT, "vi", off);
}
else
{
/* Magic. This code `knows' how readline handles rl_editing_mode. */
printf (MINUS_O_FORMAT, "emacs", (rl_editing_mode == 1) ? on : off);
printf (MINUS_O_FORMAT, "vi", (rl_editing_mode == 0) ? on : off);
}
#endif /* READLINE */
for (i = 0; o_options[i].name; i++)
{
int *on_or_off, zero = 0;
on_or_off = find_flag (o_options[i].letter);
if (on_or_off == FLAG_UNKNOWN)
on_or_off = &zero;
printf (MINUS_O_FORMAT, o_options[i].name, (*on_or_off == 1) ? on : off);
}
}
set_minus_o_option (on_or_off, option_name)
int on_or_off;
char *option_name;
{
int option_char = -1;
if (STREQ (option_name, "noclobber"))
{
if (on_or_off == FLAG_ON)
bind_variable ("noclobber", "");
else
unbind_variable ("noclobber");
stupidly_hack_special_variables ("noclobber");
}
else if (STREQ (option_name, "ignoreeof"))
{
unbind_variable ("ignoreeof");
unbind_variable ("IGNOREEOF");
if (on_or_off == FLAG_ON)
bind_variable ("IGNOREEOF", "10");
stupidly_hack_special_variables ("IGNOREEOF");
}
#if defined (READLINE)
else if ((STREQ (option_name, "emacs")) || (STREQ (option_name, "vi")))
{
if (on_or_off == FLAG_ON)
{
rl_variable_bind ("editing-mode", option_name);
if (interactive)
with_input_from_stdin ();
no_line_editing = 0;
}
else
{
int isemacs = (rl_editing_mode == 1);
if ((isemacs && STREQ (option_name, "emacs")) ||
(!isemacs && STREQ (option_name, "vi")))
{
if (interactive)
with_input_from_stream (stdin, "stdin");
no_line_editing = 1;
}
else
builtin_error ("not in %s editing mode", option_name);
}
}
#endif /* READLINE */
else if (STREQ (option_name, "interactive-comments"))
interactive_comments = (on_or_off == FLAG_ON);
else if (STREQ (option_name, "posix"))
{
posixly_correct = (on_or_off == FLAG_ON);
unbind_variable ("POSIXLY_CORRECT");
unbind_variable ("POSIX_PEDANTIC");
if (on_or_off == FLAG_ON)
{
bind_variable ("POSIXLY_CORRECT", "");
stupidly_hack_special_variables ("POSIXLY_CORRECT");
}
}
else
{
register int i;
for (i = 0; o_options[i].name; i++)
{
if (STREQ (option_name, o_options[i].name))
{
option_char = o_options[i].letter;
break;
}
}
if (option_char == -1)
{
builtin_error ("%s: unknown option name", option_name);
return (EXECUTION_FAILURE);
}
if (change_flag (option_char, on_or_off) == FLAG_ERROR)
{
bad_option (option_name);
return (EXECUTION_FAILURE);
}
}
return (EXECUTION_SUCCESS);
}
/* Set some flags from the word values in the input list. If LIST is empty,
then print out the values of the variables instead. If LIST contains
non-flags, then set $1 - $9 to the successive words of LIST. */
set_builtin (list)
WORD_LIST *list;
{
int on_or_off, flag_name, force_assignment = 0;
if (!list)
{
SHELL_VAR **vars;
vars = all_shell_variables ();
if (vars)
{
print_var_list (vars);
free (vars);
}
vars = all_shell_functions ();
if (vars)
{
print_var_list (vars);
free (vars);
}
return (EXECUTION_SUCCESS);
}
/* Check validity of flag arguments. */
if (*list->word->word == '-' || *list->word->word == '+')
{
register char *arg;
WORD_LIST *save_list = list;
while (list && (arg = list->word->word))
{
char c;
if (arg[0] != '-' && arg[0] != '+')
break;
/* `-' or `--' signifies end of flag arguments. */
if (arg[0] == '-' &&
(!arg[1] || (arg[1] == '-' && !arg[2])))
break;
while (c = *++arg)
{
if (find_flag (c) == FLAG_UNKNOWN && c != 'o')
{
char s[2];
s[0] = c; s[1] = '\0';
bad_option (s);
if (c == '?')
builtin_usage ();
return (c == '?' ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
}
list = list->next;
}
list = save_list;
}
/* Do the set command. While the list consists of words starting with
'-' or '+' treat them as flags, otherwise, start assigning them to
$1 ... $n. */
while (list)
{
char *string = list->word->word;
/* If the argument is `--' or `-' then signal the end of the list
and remember the remaining arguments. */
if (string[0] == '-' && (!string[1] || (string[1] == '-' && !string[2])))
{
list = list->next;
/* `set --' unsets the positional parameters. */
if (string[1] == '-')
force_assignment = 1;
/* Until told differently, the old shell behaviour of
`set - [arg ...]' being equivalent to `set +xv [arg ...]'
stands. Posix.2 says the behaviour is marked as obsolescent. */
else
{
change_flag ('x', '+');
change_flag ('v', '+');
}
break;
}
if ((on_or_off = *string) &&
(on_or_off == '-' || on_or_off == '+'))
{
int i = 1;
while (flag_name = string[i++])
{
if (flag_name == '?')
{
builtin_usage ();
return (EXECUTION_SUCCESS);
}
else if (flag_name == 'o') /* -+o option-name */
{
char *option_name;
WORD_LIST *opt;
opt = list->next;
if (!opt)
{
list_minus_o_opts ();
continue;
}
option_name = opt->word->word;
if (!option_name || !*option_name || (*option_name == '-'))
{
list_minus_o_opts ();
continue;
}
list = list->next; /* Skip over option name. */
if (set_minus_o_option (on_or_off, option_name) != EXECUTION_SUCCESS)
return (EXECUTION_FAILURE);
}
else
{
if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
{
char opt[3];
opt[0] = on_or_off;
opt[1] = flag_name;
opt[2] = '\0';
bad_option (opt);
builtin_usage ();
return (EXECUTION_FAILURE);
}
}
}
}
else
{
break;
}
list = list->next;
}
/* Assigning $1 ... $n */
if (list || force_assignment)
remember_args (list, 1);
return (EXECUTION_SUCCESS);
}
$BUILTIN unset
$FUNCTION unset_builtin
$SHORT_DOC unset [-f] [-v] [name ...]
For each NAME, remove the corresponding variable or function. Given
the `-v', unset will only act on variables. Given the `-f' flag,
unset will only act on functions. With neither flag, unset first
tries to unset a variable, and if that fails, then tries to unset a
function. Some variables (such as PATH and IFS) cannot be unset; also
see readonly.
$END
#define NEXT_VARIABLE() any_failed++; list = list->next; continue;
unset_builtin (list)
WORD_LIST *list;
{
int unset_function, unset_variable, unset_array, opt, any_failed;
char *name;
unset_function = unset_variable = unset_array = any_failed = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "fv")) != -1)
{
switch (opt)
{
case 'f':
unset_function = 1;
break;
case 'v':
unset_variable = 1;
break;
default:
builtin_usage ();
return (EXECUTION_FAILURE);
}
}
list = loptend;
if (unset_function && unset_variable)
{
builtin_error ("cannot simultaneously unset a function and a variable");
return (EXECUTION_FAILURE);
}
while (list)
{
SHELL_VAR *var;
int tem;
#if defined (ARRAY_VARS)
char *t;
#endif
name = list->word->word;
#if defined (ARRAY_VARS)
if (!unset_function && valid_array_reference (name))
{
t = strchr (name, '[');
*t++ = '\0';
unset_array++;
}
#endif
var = unset_function ? find_function (name) : find_variable (name);
if (var && !unset_function && non_unsettable_p (var))
{
builtin_error ("%s: cannot unset", name);
NEXT_VARIABLE ();
}
/* Posix.2 says that unsetting readonly variables is an error. */
if (var && readonly_p (var))
{
builtin_error ("%s: cannot unset: readonly %s",
name, unset_function ? "function" : "variable");
NEXT_VARIABLE ();
}
/* Unless the -f option is supplied, the name refers to a variable. */
#if defined (ARRAY_VARS)
if (var && unset_array)
{
if (array_p (var) == 0)
{
builtin_error ("%s: not an array variable", name);
NEXT_VARIABLE ();
}
else
tem = unbind_array_element (var, t);
}
else
#endif /* ARRAY_VARS */
tem = makunbound (name, unset_function ? shell_functions : shell_variables);
/* This is what Posix.2 draft 11+ says. ``If neither -f nor -v
is specified, the name refers to a variable; if a variable by
that name does not exist, a function by that name, if any,
shall be unset.'' */
if ((tem == -1) && !unset_function && !unset_variable)
tem = makunbound (name, shell_functions);
if (tem == -1)
any_failed++;
else if (!unset_function)
stupidly_hack_special_variables (name);
list = list->next;
}
if (any_failed)
return (EXECUTION_FAILURE);
else
return (EXECUTION_SUCCESS);
}
-50
View File
@@ -1,50 +0,0 @@
/* unwind_prot.h - Macros and functions for hacking unwind protection. */
/* Copyright (C) 1993 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (_UNWIND_PROT_H)
#define _UNWIND_PROT_H
/* Run a function without interrupts. */
extern void begin_unwind_frame ();
extern void discard_unwind_frame ();
extern void run_unwind_frame ();
extern void add_unwind_protect ();
extern void remove_unwind_protect ();
extern void run_unwind_protects ();
extern void unwind_protect_var ();
/* Define for people who like their code to look a certain way. */
#define end_unwind_frame()
/* How to protect an integer. */
#define unwind_protect_int(X) unwind_protect_var (&(X), (char *)(X), sizeof (int))
/* How to protect a pointer to a string. */
#define unwind_protect_string(X) \
unwind_protect_var ((int *)&(X), (X), sizeof (char *))
/* How to protect any old pointer. */
#define unwind_protect_pointer(X) unwind_protect_string (X)
/* How to protect the contents of a jmp_buf. */
#define unwind_protect_jmp_buf(X) \
unwind_protect_var ((int *)(X), (char *)(X), sizeof (procenv_t))
#endif /* _UNWIND_PROT_H */
-1222
View File
File diff suppressed because it is too large Load Diff
-1121
View File
File diff suppressed because it is too large Load Diff
-923
View File
@@ -1,923 +0,0 @@
/* bashhist.c -- bash interface to the GNU history library. */
/* Copyright (C) 1993-2011 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#if defined (HISTORY)
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include "bashtypes.h"
#include <stdio.h>
#include <errno.h>
#include "bashansi.h"
#include "posixstat.h"
#include "filecntl.h"
#include "bashintl.h"
#if defined (SYSLOG_HISTORY)
# include <syslog.h>
#endif
#include "shell.h"
#include "flags.h"
#include "input.h"
#include "parser.h" /* for the struct dstack stuff. */
#include "pathexp.h" /* for the struct ignorevar stuff */
#include "bashhist.h" /* matching prototypes and declarations */
#include "builtins/common.h"
#include <readline/history.h>
#include <glob/glob.h>
#include <glob/strmatch.h>
#if defined (READLINE)
# include "bashline.h"
extern int rl_done, rl_dispatching; /* should really include readline.h */
#endif
#if !defined (errno)
extern int errno;
#endif
static int histignore_item_func __P((struct ign *));
static int check_history_control __P((char *));
static void hc_erasedups __P((char *));
static void really_add_history __P((char *));
static struct ignorevar histignore =
{
"HISTIGNORE",
(struct ign *)0,
0,
(char *)0,
(sh_iv_item_func_t *)histignore_item_func,
};
#define HIGN_EXPAND 0x01
/* Declarations of bash history variables. */
/* Non-zero means to remember lines typed to the shell on the history
list. This is different than the user-controlled behaviour; this
becomes zero when we read lines from a file, for example. */
int remember_on_history = 1;
int enable_history_list = 1; /* value for `set -o history' */
/* The number of lines that Bash has added to this history session. The
difference between the number of the top element in the history list
(offset from history_base) and the number of lines in the history file.
Appending this session's history to the history file resets this to 0. */
int history_lines_this_session;
/* The number of lines that Bash has read from the history file. */
int history_lines_in_file;
#if defined (BANG_HISTORY)
/* Non-zero means do no history expansion on this line, regardless
of what history_expansion says. */
int history_expansion_inhibited;
#endif
/* With the old default, every line was saved in the history individually.
I.e., if the user enters:
bash$ for i in a b c
> do
> echo $i
> done
Each line will be individually saved in the history.
bash$ history
10 for i in a b c
11 do
12 echo $i
13 done
14 history
If the variable command_oriented_history is set, multiple lines
which form one command will be saved as one history entry.
bash$ for i in a b c
> do
> echo $i
> done
bash$ history
10 for i in a b c
do
echo $i
done
11 history
The user can then recall the whole command all at once instead
of just being able to recall one line at a time.
This is now enabled by default.
*/
int command_oriented_history = 1;
/* Set to 1 if the first line of a possibly-multi-line command was saved
in the history list. Managed by maybe_add_history(), but global so
the history-manipluating builtins can see it. */
int current_command_first_line_saved = 0;
/* Non-zero means to store newlines in the history list when using
command_oriented_history rather than trying to use semicolons. */
int literal_history;
/* Non-zero means to append the history to the history file at shell
exit, even if the history has been stifled. */
int force_append_history;
/* A nit for picking at history saving. Flags have the following values:
Value == 0 means save all lines parsed by the shell on the history.
Value & HC_IGNSPACE means save all lines that do not start with a space.
Value & HC_IGNDUPS means save all lines that do not match the last
line saved.
Value & HC_ERASEDUPS means to remove all other matching lines from the
history list before saving the latest line. */
int history_control;
/* Set to 1 if the last command was added to the history list successfully
as a separate history entry; set to 0 if the line was ignored or added
to a previous entry as part of command-oriented-history processing. */
int hist_last_line_added;
/* Set to 1 if builtins/history.def:push_history added the last history
entry. */
int hist_last_line_pushed;
#if defined (READLINE)
/* If non-zero, and readline is being used, the user is offered the
chance to re-edit a failed history expansion. */
int history_reediting;
/* If non-zero, and readline is being used, don't directly execute a
line with history substitution. Reload it into the editing buffer
instead and let the user further edit and confirm with a newline. */
int hist_verify;
#endif /* READLINE */
/* Non-zero means to not save function definitions in the history list. */
int dont_save_function_defs;
/* Variables declared in other files used here. */
extern int current_command_line_count;
extern struct dstack dstack;
extern int parser_state;
static int bash_history_inhibit_expansion __P((char *, int));
#if defined (READLINE)
static void re_edit __P((char *));
#endif
static int history_expansion_p __P((char *));
static int shell_comment __P((char *));
static int should_expand __P((char *));
static HIST_ENTRY *last_history_entry __P((void));
static char *expand_histignore_pattern __P((char *));
static int history_should_ignore __P((char *));
/* Is the history expansion starting at string[i] one that should not
be expanded? */
static int
bash_history_inhibit_expansion (string, i)
char *string;
int i;
{
/* The shell uses ! as a pattern negation character in globbing [...]
expressions, so let those pass without expansion. */
if (i > 0 && (string[i - 1] == '[') && member (']', string + i + 1))
return (1);
/* The shell uses ! as the indirect expansion character, so let those
expansions pass as well. */
else if (i > 1 && string[i - 1] == '{' && string[i - 2] == '$' &&
member ('}', string + i + 1))
return (1);
/* The shell uses $! as a defined parameter expansion. */
else if (i > 1 && string[i - 1] == '$' && string[i] == '!')
return (1);
#if defined (EXTENDED_GLOB)
else if (extended_glob && i > 1 && string[i+1] == '(' && member (')', string + i + 2))
return (1);
#endif
else
return (0);
}
void
bash_initialize_history ()
{
history_quotes_inhibit_expansion = 1;
history_search_delimiter_chars = ";&()|<>";
history_inhibit_expansion_function = bash_history_inhibit_expansion;
#if defined (BANG_HISTORY)
sv_histchars ("histchars");
#endif
}
void
bash_history_reinit (interact)
int interact;
{
#if defined (BANG_HISTORY)
history_expansion = interact != 0;
history_expansion_inhibited = 1;
#endif
remember_on_history = enable_history_list = interact != 0;
history_inhibit_expansion_function = bash_history_inhibit_expansion;
}
void
bash_history_disable ()
{
remember_on_history = 0;
#if defined (BANG_HISTORY)
history_expansion_inhibited = 1;
#endif
}
void
bash_history_enable ()
{
remember_on_history = 1;
#if defined (BANG_HISTORY)
history_expansion_inhibited = 0;
#endif
history_inhibit_expansion_function = bash_history_inhibit_expansion;
sv_history_control ("HISTCONTROL");
sv_histignore ("HISTIGNORE");
}
/* Load the history list from the history file. */
void
load_history ()
{
char *hf;
/* Truncate history file for interactive shells which desire it.
Note that the history file is automatically truncated to the
size of HISTSIZE if the user does not explicitly set the size
differently. */
set_if_not ("HISTSIZE", "500");
sv_histsize ("HISTSIZE");
set_if_not ("HISTFILESIZE", get_string_value ("HISTSIZE"));
sv_histsize ("HISTFILESIZE");
/* Read the history in HISTFILE into the history list. */
hf = get_string_value ("HISTFILE");
if (hf && *hf && file_exists (hf))
{
read_history (hf);
using_history ();
history_lines_in_file = where_history ();
}
}
void
bash_clear_history ()
{
clear_history ();
history_lines_this_session = 0;
}
/* Delete and free the history list entry at offset I. */
int
bash_delete_histent (i)
int i;
{
HIST_ENTRY *discard;
discard = remove_history (i);
if (discard)
free_history_entry (discard);
history_lines_this_session--;
return 1;
}
int
bash_delete_last_history ()
{
register int i;
HIST_ENTRY **hlist, *histent;
int r;
hlist = history_list ();
if (hlist == NULL)
return 0;
for (i = 0; hlist[i]; i++)
;
i--;
/* History_get () takes a parameter that must be offset by history_base. */
histent = history_get (history_base + i); /* Don't free this */
if (histent == NULL)
return 0;
r = bash_delete_histent (i);
if (where_history () > history_length)
history_set_pos (history_length);
return r;
}
#ifdef INCLUDE_UNUSED
/* Write the existing history out to the history file. */
void
save_history ()
{
char *hf;
int r;
hf = get_string_value ("HISTFILE");
if (hf && *hf && file_exists (hf))
{
/* Append only the lines that occurred this session to
the history file. */
using_history ();
if (history_lines_this_session <= where_history () || force_append_history)
r = append_history (history_lines_this_session, hf);
else
r = write_history (hf);
sv_histsize ("HISTFILESIZE");
}
}
#endif
int
maybe_append_history (filename)
char *filename;
{
int fd, result;
struct stat buf;
result = EXECUTION_SUCCESS;
if (history_lines_this_session && (history_lines_this_session <= where_history ()))
{
/* If the filename was supplied, then create it if necessary. */
if (stat (filename, &buf) == -1 && errno == ENOENT)
{
fd = open (filename, O_WRONLY|O_CREAT, 0600);
if (fd < 0)
{
builtin_error (_("%s: cannot create: %s"), filename, strerror (errno));
return (EXECUTION_FAILURE);
}
close (fd);
}
result = append_history (history_lines_this_session, filename);
history_lines_in_file += history_lines_this_session;
history_lines_this_session = 0;
}
return (result);
}
/* If this is an interactive shell, then append the lines executed
this session to the history file. */
int
maybe_save_shell_history ()
{
int result;
char *hf;
result = 0;
if (history_lines_this_session)
{
hf = get_string_value ("HISTFILE");
if (hf && *hf)
{
/* If the file doesn't exist, then create it. */
if (file_exists (hf) == 0)
{
int file;
file = open (hf, O_CREAT | O_TRUNC | O_WRONLY, 0600);
if (file != -1)
close (file);
}
/* Now actually append the lines if the history hasn't been
stifled. If the history has been stifled, rewrite the
history file. */
using_history ();
if (history_lines_this_session <= where_history () || force_append_history)
{
result = append_history (history_lines_this_session, hf);
history_lines_in_file += history_lines_this_session;
}
else
{
result = write_history (hf);
history_lines_in_file = history_lines_this_session;
}
history_lines_this_session = 0;
sv_histsize ("HISTFILESIZE");
}
}
return (result);
}
#if defined (READLINE)
/* Tell readline () that we have some text for it to edit. */
static void
re_edit (text)
char *text;
{
if (bash_input.type == st_stdin)
bash_re_edit (text);
}
#endif /* READLINE */
/* Return 1 if this line needs history expansion. */
static int
history_expansion_p (line)
char *line;
{
register char *s;
for (s = line; *s; s++)
if (*s == history_expansion_char || *s == history_subst_char)
return 1;
return 0;
}
/* Do pre-processing on LINE. If PRINT_CHANGES is non-zero, then
print the results of expanding the line if there were any changes.
If there is an error, return NULL, otherwise the expanded line is
returned. If ADDIT is non-zero the line is added to the history
list after history expansion. ADDIT is just a suggestion;
REMEMBER_ON_HISTORY can veto, and does.
Right now this does history expansion. */
char *
pre_process_line (line, print_changes, addit)
char *line;
int print_changes, addit;
{
char *history_value;
char *return_value;
int expanded;
return_value = line;
expanded = 0;
# if defined (BANG_HISTORY)
/* History expand the line. If this results in no errors, then
add that line to the history if ADDIT is non-zero. */
if (!history_expansion_inhibited && history_expansion && history_expansion_p (line))
{
expanded = history_expand (line, &history_value);
if (expanded)
{
if (print_changes)
{
if (expanded < 0)
internal_error ("%s", history_value);
#if defined (READLINE)
else if (hist_verify == 0 || expanded == 2)
#else
else
#endif
fprintf (stderr, "%s\n", history_value);
}
/* If there was an error, return NULL. */
if (expanded < 0 || expanded == 2) /* 2 == print only */
{
# if defined (READLINE)
if (expanded == 2 && rl_dispatching == 0 && *history_value)
# else
if (expanded == 2 && *history_value)
# endif /* !READLINE */
maybe_add_history (history_value);
free (history_value);
# if defined (READLINE)
/* New hack. We can allow the user to edit the
failed history expansion. */
if (history_reediting && expanded < 0 && rl_done)
re_edit (line);
# endif /* READLINE */
return ((char *)NULL);
}
# if defined (READLINE)
if (hist_verify && expanded == 1)
{
re_edit (history_value);
return ((char *)NULL);
}
# endif
}
/* Let other expansions know that return_value can be free'ed,
and that a line has been added to the history list. Note
that we only add lines that have something in them. */
expanded = 1;
return_value = history_value;
}
# endif /* BANG_HISTORY */
if (addit && remember_on_history && *return_value)
maybe_add_history (return_value);
#if 0
if (expanded == 0)
return_value = savestring (line);
#endif
return (return_value);
}
/* Return 1 if the first non-whitespace character in LINE is a `#', indicating
* that the line is a shell comment. */
static int
shell_comment (line)
char *line;
{
char *p;
for (p = line; p && *p && whitespace (*p); p++)
;
return (p && *p == '#');
}
#ifdef INCLUDE_UNUSED
/* Remove shell comments from LINE. A `#' and anything after it is a comment.
This isn't really useful yet, since it doesn't handle quoting. */
static char *
filter_comments (line)
char *line;
{
char *p;
for (p = line; p && *p && *p != '#'; p++)
;
if (p && *p == '#')
*p = '\0';
return (line);
}
#endif
/* Check LINE against what HISTCONTROL says to do. Returns 1 if the line
should be saved; 0 if it should be discarded. */
static int
check_history_control (line)
char *line;
{
HIST_ENTRY *temp;
int r;
if (history_control == 0)
return 1;
/* ignorespace or ignoreboth */
if ((history_control & HC_IGNSPACE) && *line == ' ')
return 0;
/* ignoredups or ignoreboth */
if (history_control & HC_IGNDUPS)
{
using_history ();
temp = previous_history ();
r = (temp == 0 || STREQ (temp->line, line) == 0);
using_history ();
if (r == 0)
return r;
}
return 1;
}
/* Remove all entries matching LINE from the history list. Triggered when
HISTCONTROL includes `erasedups'. */
static void
hc_erasedups (line)
char *line;
{
HIST_ENTRY *temp;
int r;
using_history ();
while (temp = previous_history ())
{
if (STREQ (temp->line, line))
{
r = where_history ();
remove_history (r);
}
}
using_history ();
}
/* Add LINE to the history list, handling possibly multi-line compound
commands. We note whether or not we save the first line of each command
(which is usually the entire command and history entry), and don't add
the second and subsequent lines of a multi-line compound command if we
didn't save the first line. We don't usually save shell comment lines in
compound commands in the history, because they could have the effect of
commenting out the rest of the command when the entire command is saved as
a single history entry (when COMMAND_ORIENTED_HISTORY is enabled). If
LITERAL_HISTORY is set, we're saving lines in the history with embedded
newlines, so it's OK to save comment lines. If we're collecting the body
of a here-document, we should act as if literal_history is enabled, because
we want to save the entire contents of the here-document as it was
entered. We also make sure to save multiple-line quoted strings or other
constructs. */
void
maybe_add_history (line)
char *line;
{
hist_last_line_added = 0;
/* Don't use the value of history_control to affect the second
and subsequent lines of a multi-line command (old code did
this only when command_oriented_history is enabled). */
if (current_command_line_count > 1)
{
if (current_command_first_line_saved &&
((parser_state & PST_HEREDOC) || literal_history || dstack.delimiter_depth != 0 || shell_comment (line) == 0))
bash_add_history (line);
return;
}
/* This is the first line of a (possible multi-line) command. Note whether
or not we should save the first line and remember it. */
current_command_first_line_saved = check_add_history (line, 0);
}
/* Just check LINE against HISTCONTROL and HISTIGNORE and add it to the
history if it's OK. Used by `history -s' as well as maybe_add_history().
Returns 1 if the line was saved in the history, 0 otherwise. */
int
check_add_history (line, force)
char *line;
int force;
{
if (check_history_control (line) && history_should_ignore (line) == 0)
{
/* We're committed to saving the line. If the user has requested it,
remove other matching lines from the history. */
if (history_control & HC_ERASEDUPS)
hc_erasedups (line);
if (force)
{
really_add_history (line);
using_history ();
}
else
bash_add_history (line);
return 1;
}
return 0;
}
#if defined (SYSLOG_HISTORY)
#define SYSLOG_MAXLEN 600
void
bash_syslog_history (line)
const char *line;
{
char trunc[SYSLOG_MAXLEN];
if (strlen(line) < SYSLOG_MAXLEN)
syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d UID=%d %s", getpid(), current_user.uid, line);
else
{
strncpy (trunc, line, SYSLOG_MAXLEN);
trunc[SYSLOG_MAXLEN - 1] = '\0';
syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d UID=%d %s", getpid(), current_user.uid, trunc);
}
}
#endif
/* Add a line to the history list.
The variable COMMAND_ORIENTED_HISTORY controls the style of history
remembering; when non-zero, and LINE is not the first line of a
complete parser construct, append LINE to the last history line instead
of adding it as a new line. */
void
bash_add_history (line)
char *line;
{
int add_it, offset, curlen;
HIST_ENTRY *current, *old;
char *chars_to_add, *new_line;
add_it = 1;
if (command_oriented_history && current_command_line_count > 1)
{
/* The second and subsequent lines of a here document have the trailing
newline preserved. We don't want to add extra newlines here, but we
do want to add one after the first line (which is the command that
contains the here-doc specifier). parse.y:history_delimiting_chars()
does the right thing to take care of this for us. We don't want to
add extra newlines if the user chooses to enable literal_history,
so we have to duplicate some of what that function does here. */
if ((parser_state & PST_HEREDOC) && literal_history && current_command_line_count > 2 && line[strlen (line) - 1] == '\n')
chars_to_add = "";
else
chars_to_add = literal_history ? "\n" : history_delimiting_chars (line);
using_history ();
current = previous_history ();
if (current)
{
/* If the previous line ended with an escaped newline (escaped
with backslash, but otherwise unquoted), then remove the quoted
newline, since that is what happens when the line is parsed. */
curlen = strlen (current->line);
if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\\' &&
current->line[curlen - 2] != '\\')
{
current->line[curlen - 1] = '\0';
curlen--;
chars_to_add = "";
}
/* If we're not in some kind of quoted construct, the current history
entry ends with a newline, and we're going to add a semicolon,
don't. In some cases, it results in a syntax error (e.g., before
a close brace), and it should not be needed. */
if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\n' && *chars_to_add == ';')
chars_to_add++;
new_line = (char *)xmalloc (1
+ curlen
+ strlen (line)
+ strlen (chars_to_add));
sprintf (new_line, "%s%s%s", current->line, chars_to_add, line);
offset = where_history ();
old = replace_history_entry (offset, new_line, current->data);
free (new_line);
if (old)
free_history_entry (old);
add_it = 0;
}
}
if (add_it)
really_add_history (line);
#if defined (SYSLOG_HISTORY)
bash_syslog_history (line);
#endif
using_history ();
}
static void
really_add_history (line)
char *line;
{
hist_last_line_added = 1;
hist_last_line_pushed = 0;
add_history (line);
history_lines_this_session++;
}
int
history_number ()
{
using_history ();
return (remember_on_history ? history_base + where_history () : 1);
}
static int
should_expand (s)
char *s;
{
char *p;
for (p = s; p && *p; p++)
{
if (*p == '\\')
p++;
else if (*p == '&')
return 1;
}
return 0;
}
static int
histignore_item_func (ign)
struct ign *ign;
{
if (should_expand (ign->val))
ign->flags |= HIGN_EXPAND;
return (0);
}
void
setup_history_ignore (varname)
char *varname;
{
setup_ignore_patterns (&histignore);
}
static HIST_ENTRY *
last_history_entry ()
{
HIST_ENTRY *he;
using_history ();
he = previous_history ();
using_history ();
return he;
}
char *
last_history_line ()
{
HIST_ENTRY *he;
he = last_history_entry ();
if (he == 0)
return ((char *)NULL);
return he->line;
}
static char *
expand_histignore_pattern (pat)
char *pat;
{
HIST_ENTRY *phe;
char *ret;
phe = last_history_entry ();
if (phe == (HIST_ENTRY *)0)
return (savestring (pat));
ret = strcreplace (pat, '&', phe->line, 1);
return ret;
}
/* Return 1 if we should not put LINE into the history according to the
patterns in HISTIGNORE. */
static int
history_should_ignore (line)
char *line;
{
register int i, match;
char *npat;
if (histignore.num_ignores == 0)
return 0;
for (i = match = 0; i < histignore.num_ignores; i++)
{
if (histignore.ignores[i].flags & HIGN_EXPAND)
npat = expand_histignore_pattern (histignore.ignores[i].val);
else
npat = histignore.ignores[i].val;
match = strmatch (npat, line, FNMATCH_EXTFLAG) != FNM_NOMATCH;
if (histignore.ignores[i].flags & HIGN_EXPAND)
free (npat);
if (match)
break;
}
return match;
}
#endif /* HISTORY */
-4122
View File
File diff suppressed because it is too large Load Diff
-221
View File
@@ -1,221 +0,0 @@
/* bracecomp.c -- Complete a filename with the possible completions enclosed
in csh-style braces such that the list of completions is available to the
shell. */
/* Original version by tromey@cns.caltech.edu, Fri Feb 7 1992. */
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#if defined (BRACE_EXPANSION) && defined (READLINE)
#include <stdio.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include "bashansi.h"
#include "shmbutil.h"
#include "shell.h"
#include <readline/readline.h>
static int _strcompare __P((char **, char **));
/* Find greatest common prefix of two strings. */
static int
string_gcd (s1, s2)
char *s1, *s2;
{
register int i;
if (s1 == NULL || s2 == NULL)
return (0);
for (i = 0; *s1 && *s2; ++s1, ++s2, ++i)
{
if (*s1 != *s2)
break;
}
return (i);
}
static char *
really_munge_braces (array, real_start, real_end, gcd_zero)
char **array;
int real_start, real_end, gcd_zero;
{
int start, end, gcd;
char *result, *subterm, *x;
int result_size, flag, tlen;
flag = 0;
if (real_start == real_end)
{
x = array[real_start] ? sh_backslash_quote (array[real_start] + gcd_zero, 0)
: sh_backslash_quote (array[0], 0);
return x;
}
result = (char *)xmalloc (result_size = 16);
*result = '\0';
for (start = real_start; start < real_end; start = end + 1)
{
gcd = strlen (array[start]);
for (end = start + 1; end < real_end; end++)
{
int temp;
temp = string_gcd (array[start], array[end]);
if (temp <= gcd_zero)
break;
gcd = temp;
}
end--;
if (gcd_zero == 0 && start == real_start && end != (real_end - 1))
{
/* In this case, add in a leading '{', because we are at
top level, and there isn't a consistent prefix. */
result_size += 1;
result = (char *)xrealloc (result, result_size);
result[0] = '{'; result[1] = '\0';
flag++;
}
/* Make sure we backslash quote every substring we insert into the
resultant brace expression. This is so the default filename
quoting function won't inappropriately quote the braces. */
if (start == end)
{
x = savestring (array[start] + gcd_zero);
subterm = sh_backslash_quote (x, 0);
free (x);
}
else
{
/* If there is more than one element in the subarray,
insert the (quoted) prefix and an opening brace. */
tlen = gcd - gcd_zero;
x = (char *)xmalloc (tlen + 1);
strncpy (x, array[start] + gcd_zero, tlen);
x[tlen] = '\0';
subterm = sh_backslash_quote (x, 0);
free (x);
result_size += strlen (subterm) + 1;
result = (char *)xrealloc (result, result_size);
strcat (result, subterm);
free (subterm);
strcat (result, "{");
subterm = really_munge_braces (array, start, end + 1, gcd);
subterm[strlen (subterm) - 1] = '}';
}
result_size += strlen (subterm) + 1;
result = (char *)xrealloc (result, result_size);
strcat (result, subterm);
strcat (result, ",");
free (subterm);
}
if (gcd_zero == 0)
result[strlen (result) - 1] = flag ? '}' : '\0';
return (result);
}
static int
_strcompare (s1, s2)
char **s1, **s2;
{
int result;
result = **s1 - **s2;
if (result == 0)
result = strcmp (*s1, *s2);
return result;
}
static int
hack_braces_completion (names)
char **names;
{
register int i;
char *temp;
i = strvec_len (names);
if (MB_CUR_MAX > 1 && i > 2)
qsort (names+1, i-1, sizeof (char *), (QSFUNC *)_strcompare);
temp = really_munge_braces (names, 1, i, 0);
for (i = 0; names[i]; ++i)
{
free (names[i]);
names[i] = NULL;
}
names[0] = temp;
return 0;
}
/* We handle quoting ourselves within hack_braces_completion, so we turn off
rl_filename_quoting_desired and rl_filename_quoting_function. */
int
bash_brace_completion (count, ignore)
int count, ignore;
{
rl_compignore_func_t *orig_ignore_func;
rl_compentry_func_t *orig_entry_func;
rl_quote_func_t *orig_quoting_func;
rl_completion_func_t *orig_attempt_func;
int orig_quoting_desired, r;
orig_ignore_func = rl_ignore_some_completions_function;
orig_attempt_func = rl_attempted_completion_function;
orig_entry_func = rl_completion_entry_function;
orig_quoting_func = rl_filename_quoting_function;
orig_quoting_desired = rl_filename_quoting_desired;
rl_completion_entry_function = rl_filename_completion_function;
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
rl_ignore_some_completions_function = hack_braces_completion;
rl_filename_quoting_function = (rl_quote_func_t *)NULL;
rl_filename_quoting_desired = 0;
r = rl_complete_internal (TAB);
rl_ignore_some_completions_function = orig_ignore_func;
rl_attempted_completion_function = orig_attempt_func;
rl_completion_entry_function = orig_entry_func;
rl_filename_quoting_function = orig_quoting_func;
rl_filename_quoting_desired = orig_quoting_desired;
return r;
}
#endif /* BRACE_EXPANSION && READLINE */
-786
View File
@@ -1,786 +0,0 @@
/* braces.c -- code for doing word expansion in curly braces. */
/* Copyright (C) 1987-2012 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
/* Stuff in curly braces gets expanded before all other shell expansions. */
#include "config.h"
#if defined (BRACE_EXPANSION)
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <errno.h>
#include "bashansi.h"
#if defined (SHELL)
# include "shell.h"
#endif /* SHELL */
#include "general.h"
#include "shmbutil.h"
#include "chartypes.h"
#ifndef errno
extern int errno;
#endif
#define brace_whitespace(c) (!(c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
#define BRACE_SEQ_SPECIFIER ".."
extern int asprintf __P((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
extern int last_command_exit_value;
/* Basic idea:
Segregate the text into 3 sections: preamble (stuff before an open brace),
postamble (stuff after the matching close brace) and amble (stuff after
preamble, and before postamble). Expand amble, and then tack on the
expansions to preamble. Expand postamble, and tack on the expansions to
the result so far.
*/
/* The character which is used to separate arguments. */
static const int brace_arg_separator = ',';
#if defined (__P)
static int brace_gobbler __P((char *, size_t, int *, int));
static char **expand_amble __P((char *, size_t, int));
static char **expand_seqterm __P((char *, size_t));
static char **mkseq __P((intmax_t, intmax_t, intmax_t, int, int));
static char **array_concat __P((char **, char **));
#else
static int brace_gobbler ();
static char **expand_amble ();
static char **expand_seqterm ();
static char **mkseq();
static char **array_concat ();
#endif
#if 0
static void
dump_result (a)
char **a;
{
int i;
for (i = 0; a[i]; i++)
printf ("dump_result: a[%d] = -%s-\n", i, a[i]);
}
#endif
/* Return an array of strings; the brace expansion of TEXT. */
char **
brace_expand (text)
char *text;
{
register int start;
size_t tlen;
char *preamble, *postamble, *amble;
size_t alen;
char **tack, **result;
int i, j, c, c1;
DECLARE_MBSTATE;
/* Find the text of the preamble. */
tlen = strlen (text);
i = 0;
#if defined (CSH_BRACE_COMPAT)
c = brace_gobbler (text, tlen, &i, '{'); /* } */
#else
/* Make sure that when we exit this loop, c == 0 or text[i] begins a
valid brace expansion sequence. */
do
{
c = brace_gobbler (text, tlen, &i, '{'); /* } */
c1 = c;
/* Verify that c begins a valid brace expansion word. If it doesn't, we
go on. Loop stops when there are no more open braces in the word. */
if (c)
{
start = j = i + 1; /* { */
c = brace_gobbler (text, tlen, &j, '}');
if (c == 0) /* it's not */
{
i++;
c = c1;
continue;
}
else /* it is */
{
c = c1;
break;
}
}
else
break;
}
while (c);
#endif /* !CSH_BRACE_COMPAT */
preamble = (char *)xmalloc (i + 1);
if (i > 0)
strncpy (preamble, text, i);
preamble[i] = '\0';
result = (char **)xmalloc (2 * sizeof (char *));
result[0] = preamble;
result[1] = (char *)NULL;
/* Special case. If we never found an exciting character, then
the preamble is all of the text, so just return that. */
if (c != '{')
return (result);
/* Find the amble. This is the stuff inside this set of braces. */
start = ++i;
c = brace_gobbler (text, tlen, &i, '}');
/* What if there isn't a matching close brace? */
if (c == 0)
{
#if defined (NOTDEF)
/* Well, if we found an unquoted BRACE_ARG_SEPARATOR between START
and I, then this should be an error. Otherwise, it isn't. */
j = start;
while (j < i)
{
if (text[j] == '\\')
{
j++;
ADVANCE_CHAR (text, tlen, j);
continue;
}
if (text[j] == brace_arg_separator)
{ /* { */
strvec_dispose (result);
last_command_exit_value = 1;
report_error ("no closing `%c' in %s", '}', text);
throw_to_top_level ();
}
ADVANCE_CHAR (text, tlen, j);
}
#endif
free (preamble); /* Same as result[0]; see initialization. */
result[0] = savestring (text);
return (result);
}
#if defined (SHELL)
amble = substring (text, start, i);
alen = i - start;
#else
amble = (char *)xmalloc (1 + (i - start));
strncpy (amble, &text[start], (i - start));
alen = i - start;
amble[alen] = '\0';
#endif
#if defined (SHELL)
INITIALIZE_MBSTATE;
/* If the amble does not contain an unquoted BRACE_ARG_SEPARATOR, then
just return without doing any expansion. */
j = 0;
while (amble[j])
{
if (amble[j] == '\\')
{
j++;
ADVANCE_CHAR (amble, alen, j);
continue;
}
if (amble[j] == brace_arg_separator)
break;
ADVANCE_CHAR (amble, alen, j);
}
if (amble[j] == 0)
{
tack = expand_seqterm (amble, alen);
if (tack)
goto add_tack;
else
{
free (amble);
free (preamble);
result[0] = savestring (text);
return (result);
}
}
#endif /* SHELL */
tack = expand_amble (amble, alen, 0);
add_tack:
result = array_concat (result, tack);
free (amble);
if (tack != result)
strvec_dispose (tack);
postamble = text + i + 1;
if (postamble && *postamble)
{
tack = brace_expand (postamble);
result = array_concat (result, tack);
if (tack != result)
strvec_dispose (tack);
}
return (result);
}
/* Expand the text found inside of braces. We simply try to split the
text at BRACE_ARG_SEPARATORs into separate strings. We then brace
expand each slot which needs it, until there are no more slots which
need it. */
static char **
expand_amble (text, tlen, flags)
char *text;
size_t tlen;
int flags;
{
char **result, **partial;
char *tem;
int start, i, c;
DECLARE_MBSTATE;
result = (char **)NULL;
start = i = 0;
c = 1;
while (c)
{
c = brace_gobbler (text, tlen, &i, brace_arg_separator);
#if defined (SHELL)
tem = substring (text, start, i);
#else
tem = (char *)xmalloc (1 + (i - start));
strncpy (tem, &text[start], (i - start));
tem[i- start] = '\0';
#endif
partial = brace_expand (tem);
if (!result)
result = partial;
else
{
register int lr, lp, j;
lr = strvec_len (result);
lp = strvec_len (partial);
result = strvec_resize (result, lp + lr + 1);
for (j = 0; j < lp; j++)
result[lr + j] = partial[j];
result[lr + j] = (char *)NULL;
free (partial);
}
free (tem);
ADVANCE_CHAR (text, tlen, i);
start = i;
}
return (result);
}
#define ST_BAD 0
#define ST_INT 1
#define ST_CHAR 2
#define ST_ZINT 3
#ifndef sh_imaxabs
# define sh_imaxabs(x) (((x) >= 0) ? (x) : -(x))
#endif
/* Handle signed arithmetic overflow and underflow. Have to do it this way
to avoid compilers optimizing out simpler overflow checks. */
/* Make sure that a+b does not exceed MAXV or is smaller than MINV (if b < 0).
Assumes that b > 0 if a > 0 and b < 0 if a < 0 */
#define ADDOVERFLOW(a,b,minv,maxv) \
((((a) > 0) && ((b) > ((maxv) - (a)))) || \
(((a) < 0) && ((b) < ((minv) - (a)))))
/* Make sure that a-b is not smaller than MINV or exceeds MAXV (if b < 0).
Assumes that b > 0 if a > 0 and b < 0 if a < 0 */
#define SUBOVERFLOW(a,b,minv,maxv) \
((((b) > 0) && ((a) < ((minv) + (b)))) || \
(((b) < 0) && ((a) > ((maxv) + (b)))))
static char **
mkseq (start, end, incr, type, width)
intmax_t start, end, incr;
int type, width;
{
intmax_t n, prevn;
int i, nelem;
char **result, *t;
if (incr == 0)
incr = 1;
if (start > end && incr > 0)
incr = -incr;
else if (start < end && incr < 0)
{
if (incr == INTMAX_MIN) /* Don't use -INTMAX_MIN */
return ((char **)NULL);
incr = -incr;
}
/* Check that end-start will not overflow INTMAX_MIN, INTMAX_MAX. The +3
and -2, not strictly necessary, are there because of the way the number
of elements and value passed to strvec_create() are calculated below. */
if (SUBOVERFLOW (end, start, INTMAX_MIN+3, INTMAX_MAX-2))
return ((char **)NULL);
prevn = sh_imaxabs (end - start);
/* Need to check this way in case INT_MAX == INTMAX_MAX */
if (INT_MAX == INTMAX_MAX && (ADDOVERFLOW (prevn, 2, INT_MIN, INT_MAX)))
return ((char **)NULL);
else if (ADDOVERFLOW ((prevn/sh_imaxabs(incr)), 1, INTMAX_MIN, INTMAX_MAX))
return ((char **)NULL);
/* XXX - TOFIX: potentially allocating a lot of extra memory if
imaxabs(incr) != 1 */
/* Instead of a simple nelem = prevn + 1, something like:
nelem = (prevn / imaxabs(incr)) + 1;
would work */
nelem = (prevn / sh_imaxabs(incr)) + 1;
if (nelem > INT_MAX - 2) /* Don't overflow int */
return ((char **)NULL);
result = strvec_create (nelem + 1);
/* Make sure we go through the loop at least once, so {3..3} prints `3' */
i = 0;
n = start;
do
{
#if defined (SHELL)
QUIT; /* XXX - memory leak here */
#endif
if (type == ST_INT)
result[i++] = itos (n);
else if (type == ST_ZINT)
{
int len, arg;
arg = n;
len = asprintf (&t, "%0*d", width, arg);
result[i++] = t;
}
else
{
t = (char *)xmalloc (2);
t[0] = n;
t[1] = '\0';
result[i++] = t;
}
/* Handle overflow and underflow of n+incr */
if (ADDOVERFLOW (n, incr, INTMAX_MIN, INTMAX_MAX))
break;
n += incr;
if ((incr < 0 && n < end) || (incr > 0 && n > end))
break;
}
while (1);
result[i] = (char *)0;
return (result);
}
static char **
expand_seqterm (text, tlen)
char *text;
size_t tlen;
{
char *t, *lhs, *rhs;
int i, lhs_t, rhs_t, lhs_l, rhs_l, width;
intmax_t lhs_v, rhs_v, incr;
intmax_t tl, tr;
char **result, *ep, *oep;
t = strstr (text, BRACE_SEQ_SPECIFIER);
if (t == 0)
return ((char **)NULL);
lhs_l = t - text; /* index of start of BRACE_SEQ_SPECIFIER */
lhs = substring (text, 0, lhs_l);
rhs = substring (text, lhs_l + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen);
if (lhs[0] == 0 || rhs[0] == 0)
{
free (lhs);
free (rhs);
return ((char **)NULL);
}
/* Now figure out whether LHS and RHS are integers or letters. Both
sides have to match. */
lhs_t = (legal_number (lhs, &tl)) ? ST_INT :
((ISALPHA (lhs[0]) && lhs[1] == 0) ? ST_CHAR : ST_BAD);
/* Decide on rhs and whether or not it looks like the user specified
an increment */
ep = 0;
if (ISDIGIT (rhs[0]) || ((rhs[0] == '+' || rhs[0] == '-') && ISDIGIT (rhs[1])))
{
rhs_t = ST_INT;
errno == 0;
tr = strtoimax (rhs, &ep, 10);
if (errno == ERANGE || (ep && *ep != 0 && *ep != '.'))
rhs_t = ST_BAD; /* invalid */
}
else if (ISALPHA (rhs[0]) && (rhs[1] == 0 || rhs[1] == '.'))
{
rhs_t = ST_CHAR;
ep = rhs + 1;
}
else
{
rhs_t = ST_BAD;
ep = 0;
}
incr = 1;
if (rhs_t != ST_BAD)
{
oep = ep;
errno = 0;
if (ep && *ep == '.' && ep[1] == '.' && ep[2])
incr = strtoimax (ep + 2, &ep, 10);
if (*ep != 0 || errno == ERANGE)
rhs_t = ST_BAD; /* invalid incr or overflow */
tlen -= ep - oep;
}
if (lhs_t != rhs_t || lhs_t == ST_BAD || rhs_t == ST_BAD)
{
free (lhs);
free (rhs);
return ((char **)NULL);
}
/* OK, we have something. It's either a sequence of integers, ascending
or descending, or a sequence or letters, ditto. Generate the sequence,
put it into a string vector, and return it. */
if (lhs_t == ST_CHAR)
{
lhs_v = (unsigned char)lhs[0];
rhs_v = (unsigned char)rhs[0];
width = 1;
}
else
{
lhs_v = tl; /* integer truncation */
rhs_v = tr;
/* Decide whether or not the terms need zero-padding */
rhs_l = tlen - lhs_l - sizeof (BRACE_SEQ_SPECIFIER) + 1;
width = 0;
if (lhs_l > 1 && lhs[0] == '0')
width = lhs_l, lhs_t = ST_ZINT;
if (lhs_l > 2 && lhs[0] == '-' && lhs[1] == '0')
width = lhs_l, lhs_t = ST_ZINT;
if (rhs_l > 1 && rhs[0] == '0' && width < rhs_l)
width = rhs_l, lhs_t = ST_ZINT;
if (rhs_l > 2 && rhs[0] == '-' && rhs[1] == '0' && width < rhs_l)
width = rhs_l, lhs_t = ST_ZINT;
if (width < lhs_l && lhs_t == ST_ZINT)
width = lhs_l;
if (width < rhs_l && lhs_t == ST_ZINT)
width = rhs_l;
}
result = mkseq (lhs_v, rhs_v, incr, lhs_t, width);
free (lhs);
free (rhs);
return (result);
}
/* Start at INDEX, and skip characters in TEXT. Set INDEX to the
index of the character matching SATISFY. This understands about
quoting. Return the character that caused us to stop searching;
this is either the same as SATISFY, or 0. */
/* If SATISFY is `}', we are looking for a brace expression, so we
should enforce the rules that govern valid brace expansions:
1) to count as an arg separator, a comma or `..' has to be outside
an inner set of braces.
*/
static int
brace_gobbler (text, tlen, indx, satisfy)
char *text;
size_t tlen;
int *indx;
int satisfy;
{
register int i, c, quoted, level, commas, pass_next;
#if defined (SHELL)
int si;
char *t;
#endif
DECLARE_MBSTATE;
level = quoted = pass_next = 0;
#if defined (CSH_BRACE_COMPAT)
commas = 1;
#else
commas = (satisfy == '}') ? 0 : 1;
#endif
i = *indx;
while (c = text[i])
{
if (pass_next)
{
pass_next = 0;
ADVANCE_CHAR (text, tlen, i);
continue;
}
/* A backslash escapes the next character. This allows backslash to
escape the quote character in a double-quoted string. */
if (c == '\\' && (quoted == 0 || quoted == '"' || quoted == '`'))
{
pass_next = 1;
i++;
continue;
}
#if defined (SHELL)
/* If compiling for the shell, treat ${...} like \{...} */
if (c == '$' && text[i+1] == '{' && quoted != '\'') /* } */
{
pass_next = 1;
i++;
if (quoted == 0)
level++;
continue;
}
#endif
if (quoted)
{
if (c == quoted)
quoted = 0;
#if defined (SHELL)
/* The shell allows quoted command substitutions */
if (quoted == '"' && c == '$' && text[i+1] == '(') /*)*/
goto comsub;
#endif
ADVANCE_CHAR (text, tlen, i);
continue;
}
if (c == '"' || c == '\'' || c == '`')
{
quoted = c;
i++;
continue;
}
#if defined (SHELL)
/* Pass new-style command and process substitutions through unchanged. */
if ((c == '$' || c == '<' || c == '>') && text[i+1] == '(') /* ) */
{
comsub:
si = i + 2;
t = extract_command_subst (text, &si, 0);
i = si;
free (t);
i++;
continue;
}
#endif
if (c == satisfy && level == 0 && quoted == 0 && commas > 0)
{
/* We ignore an open brace surrounded by whitespace, and also
an open brace followed immediately by a close brace preceded
by whitespace. */
if (c == '{' &&
((!i || brace_whitespace (text[i - 1])) &&
(brace_whitespace (text[i + 1]) || text[i + 1] == '}')))
{
i++;
continue;
}
break;
}
if (c == '{')
level++;
else if (c == '}' && level)
level--;
#if !defined (CSH_BRACE_COMPAT)
else if (satisfy == '}' && c == brace_arg_separator && level == 0)
commas++;
else if (satisfy == '}' && STREQN (text+i, BRACE_SEQ_SPECIFIER, 2) &&
text[i+2] != satisfy && level == 0)
commas++;
#endif
ADVANCE_CHAR (text, tlen, i);
}
*indx = i;
return (c);
}
/* Return 1 if ARR has any non-empty-string members. Used to short-circuit
in array_concat() below. */
static int
degenerate_array (arr)
char **arr;
{
register int i;
for (i = 0; arr[i]; i++)
if (arr[i][0] != '\0')
return 0;
return 1;
}
/* Return a new array of strings which is the result of appending each
string in ARR2 to each string in ARR1. The resultant array is
len (arr1) * len (arr2) long. For convenience, ARR1 (and its contents)
are free ()'ed. ARR1 can be NULL, in that case, a new version of ARR2
is returned. */
static char **
array_concat (arr1, arr2)
char **arr1, **arr2;
{
register int i, j, len, len1, len2;
register char **result;
if (arr1 == 0)
return (arr2); /* XXX - see if we can get away without copying? */
if (arr2 == 0)
return (arr1); /* XXX - caller expects us to free arr1 */
if (degenerate_array (arr1))
{
strvec_dispose (arr1);
return (arr2); /* XXX - use flags to see if we can avoid copying here */
}
if (degenerate_array (arr2))
return (arr1); /* XXX - rather than copying and freeing it */
len1 = strvec_len (arr1);
len2 = strvec_len (arr2);
result = (char **)xmalloc ((1 + (len1 * len2)) * sizeof (char *));
len = 0;
for (i = 0; i < len1; i++)
{
int strlen_1 = strlen (arr1[i]);
for (j = 0; j < len2; j++)
{
result[len] = (char *)xmalloc (1 + strlen_1 + strlen (arr2[j]));
strcpy (result[len], arr1[i]);
strcpy (result[len] + strlen_1, arr2[j]);
len++;
}
free (arr1[i]);
}
free (arr1);
result[len] = (char *)NULL;
return (result);
}
#if defined (TEST)
#include <stdio.h>
fatal_error (format, arg1, arg2)
char *format, *arg1, *arg2;
{
report_error (format, arg1, arg2);
exit (1);
}
report_error (format, arg1, arg2)
char *format, *arg1, *arg2;
{
fprintf (stderr, format, arg1, arg2);
fprintf (stderr, "\n");
}
main ()
{
char example[256];
for (;;)
{
char **result;
int i;
fprintf (stderr, "brace_expand> ");
if ((!fgets (example, 256, stdin)) ||
(strncmp (example, "quit", 4) == 0))
break;
if (strlen (example))
example[strlen (example) - 1] = '\0';
result = brace_expand (example);
for (i = 0; result[i]; i++)
printf ("%s\n", result[i]);
free_array (result);
}
}
/*
* Local variables:
* compile-command: "gcc -g -Bstatic -DTEST -o brace_expand braces.c general.o"
* end:
*/
#endif /* TEST */
#endif /* BRACE_EXPANSION */
-659
View File
@@ -1,659 +0,0 @@
This file is declare.def, from which is created declare.c.
It implements the builtins "declare" and "local" in Bash.
Copyright (C) 1987-2012 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
$PRODUCES declare.c
$BUILTIN declare
$FUNCTION declare_builtin
$SHORT_DOC declare [-aAfFgilnrtux] [-p] [name[=value] ...]
Set variable values and attributes.
Declare variables and give them attributes. If no NAMEs are given,
display the attributes and values of all variables.
Options:
-f restrict action or display to function names and definitions
-F restrict display to function names only (plus line number and
source file when debugging)
-g create global variables when used in a shell function; otherwise
ignored
-p display the attributes and value of each NAME
Options which set attributes:
-a to make NAMEs indexed arrays (if supported)
-A to make NAMEs associative arrays (if supported)
-i to make NAMEs have the `integer' attribute
-l to convert NAMEs to lower case on assignment
-n make NAME a reference to the variable named by its value
-r to make NAMEs readonly
-t to make NAMEs have the `trace' attribute
-u to convert NAMEs to upper case on assignment
-x to make NAMEs export
Using `+' instead of `-' turns off the given attribute.
Variables with the integer attribute have arithmetic evaluation (see
the `let' command) performed when the variable is assigned a value.
When used in a function, `declare' makes NAMEs local, as with the `local'
command. The `-g' option suppresses this behavior.
Exit Status:
Returns success unless an invalid option is supplied or an error occurs.
$END
$BUILTIN typeset
$FUNCTION declare_builtin
$SHORT_DOC typeset [-aAfFgilrtux] [-p] name[=value] ...
Set variable values and attributes.
Obsolete. See `help declare'.
$END
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <stdio.h>
#include "../bashansi.h"
#include "../bashintl.h"
#include "../shell.h"
#include "common.h"
#include "builtext.h"
#include "bashgetopt.h"
extern int array_needs_making;
extern int posixly_correct;
static int declare_internal __P((register WORD_LIST *, int));
/* Declare or change variable attributes. */
int
declare_builtin (list)
register WORD_LIST *list;
{
return (declare_internal (list, 0));
}
$BUILTIN local
$FUNCTION local_builtin
$SHORT_DOC local [option] name[=value] ...
Define local variables.
Create a local variable called NAME, and give it VALUE. OPTION can
be any option accepted by `declare'.
Local variables can only be used within a function; they are visible
only to the function where they are defined and its children.
Exit Status:
Returns success unless an invalid option is supplied, an error occurs,
or the shell is not executing a function.
$END
int
local_builtin (list)
register WORD_LIST *list;
{
if (variable_context)
return (declare_internal (list, 1));
else
{
builtin_error (_("can only be used in a function"));
return (EXECUTION_FAILURE);
}
}
#if defined (ARRAY_VARS)
# define DECLARE_OPTS "+acfgilnprtuxAF"
#else
# define DECLARE_OPTS "+cfgilnprtuxF"
#endif
/* The workhorse function. */
static int
declare_internal (list, local_var)
register WORD_LIST *list;
int local_var;
{
int flags_on, flags_off, *flags;
int any_failed, assign_error, pflag, nodefs, opt, mkglobal, onref, offref;
char *t, *subscript_start;
SHELL_VAR *var, *refvar;
FUNCTION_DEF *shell_fn;
flags_on = flags_off = any_failed = assign_error = pflag = nodefs = mkglobal = 0;
refvar = (SHELL_VAR *)NULL;
reset_internal_getopt ();
while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF)
{
flags = list_opttype == '+' ? &flags_off : &flags_on;
switch (opt)
{
case 'a':
#if defined (ARRAY_VARS)
*flags |= att_array;
break;
#else
builtin_usage ();
return (EX_USAGE);
#endif
case 'A':
#if defined (ARRAY_VARS)
*flags |= att_assoc;
break;
#else
builtin_usage ();
return (EX_USAGE);
#endif
case 'p':
if (local_var == 0)
pflag++;
break;
case 'F':
nodefs++;
*flags |= att_function;
break;
case 'f':
*flags |= att_function;
break;
case 'g':
if (flags == &flags_on)
mkglobal = 1;
break;
case 'i':
*flags |= att_integer;
break;
case 'n':
*flags |= att_nameref;
break;
case 'r':
*flags |= att_readonly;
break;
case 't':
*flags |= att_trace;
break;
case 'x':
*flags |= att_exported;
array_needs_making = 1;
break;
#if defined (CASEMOD_ATTRS)
# if defined (CASEMOD_CAPCASE)
case 'c':
*flags |= att_capcase;
if (flags == &flags_on)
flags_off |= att_uppercase|att_lowercase;
break;
# endif
case 'l':
*flags |= att_lowercase;
if (flags == &flags_on)
flags_off |= att_capcase|att_uppercase;
break;
case 'u':
*flags |= att_uppercase;
if (flags == &flags_on)
flags_off |= att_capcase|att_lowercase;
break;
#endif /* CASEMOD_ATTRS */
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
/* If there are no more arguments left, then we just want to show
some variables. */
if (list == 0) /* declare -[aAfFirtx] */
{
/* Show local variables defined at this context level if this is
the `local' builtin. */
if (local_var)
{
register SHELL_VAR **vlist;
register int i;
vlist = all_local_variables ();
if (vlist)
{
for (i = 0; vlist[i]; i++)
print_assignment (vlist[i]);
free (vlist);
}
}
else if (pflag && (flags_on == 0 || flags_on == att_function))
show_all_var_attributes (flags_on == 0, nodefs);
else if (flags_on == 0)
return (set_builtin ((WORD_LIST *)NULL));
else
set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
return (sh_chkwrite (EXECUTION_SUCCESS));
}
if (pflag) /* declare -p [-aAfFirtx] name [name...] */
{
for (any_failed = 0; list; list = list->next)
{
pflag = show_name_attributes (list->word->word, nodefs);
if (pflag)
{
sh_notfound (list->word->word);
any_failed++;
}
}
return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
}
#define NEXT_VARIABLE() free (name); list = list->next; continue
/* There are arguments left, so we are making variables. */
while (list) /* declare [-aAfFirx] name [name ...] */
{
char *value, *name;
int offset, aflags;
#if defined (ARRAY_VARS)
int making_array_special, compound_array_assign, simple_array_assign;
#endif
name = savestring (list->word->word);
offset = assignment (name, 0);
aflags = 0;
if (offset) /* declare [-aAfFirx] name=value */
{
name[offset] = '\0';
value = name + offset + 1;
if (name[offset - 1] == '+')
{
aflags |= ASS_APPEND;
name[offset - 1] = '\0';
}
}
else
value = "";
#if defined (ARRAY_VARS)
compound_array_assign = simple_array_assign = 0;
subscript_start = (char *)NULL;
if (t = strchr (name, '[')) /* ] */
{
/* If offset != 0 we have already validated any array reference */
if (offset == 0 && valid_array_reference (name) == 0)
{
sh_invalidid (name);
assign_error++;
NEXT_VARIABLE ();
}
subscript_start = t;
*t = '\0';
making_array_special = 1;
}
else
making_array_special = 0;
#endif
/* If we're in posix mode or not looking for a shell function (since
shell function names don't have to be valid identifiers when the
shell's not in posix mode), check whether or not the argument is a
valid, well-formed shell identifier. */
if ((posixly_correct || (flags_on & att_function) == 0) && legal_identifier (name) == 0)
{
sh_invalidid (name);
assign_error++;
NEXT_VARIABLE ();
}
/* If VARIABLE_CONTEXT has a non-zero value, then we are executing
inside of a function. This means we should make local variables,
not global ones. */
/* XXX - this has consequences when we're making a local copy of a
variable that was in the temporary environment. Watch out
for this. */
refvar = (SHELL_VAR *)NULL;
if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0))
{
#if defined (ARRAY_VARS)
if (flags_on & att_assoc)
var = make_local_assoc_variable (name);
else if ((flags_on & att_array) || making_array_special)
var = make_local_array_variable (name, making_array_special);
else
#endif
#if 0
/* XXX - this doesn't work right yet. */
/* See below for rationale for doing this. */
if (flags_on & att_nameref)
{
/* See if we are trying to modify an existing nameref variable */
var = find_variable_last_nameref (name);
if (var && nameref_p (var) == 0)
var = make_local_variable (name);
}
else if (flags_off & att_nameref)
{
var = (SHELL_VAR *)NULL;
/* See if we are trying to modify an existing nameref variable */
refvar = find_variable_last_nameref (name);
if (refvar && nameref_p (refvar) == 0)
refvar = 0;
if (refvar)
var = make_local_variable (nameref_cell (refvar));
if (var == 0)
var = make_local_variable (name);
}
else
#endif
var = make_local_variable (name);
if (var == 0)
{
any_failed++;
NEXT_VARIABLE ();
}
}
else
var = (SHELL_VAR *)NULL;
/* If we are declaring a function, then complain about it in some way.
We don't let people make functions by saying `typeset -f foo=bar'. */
/* There should be a way, however, to let people look at a particular
function definition by saying `typeset -f foo'. */
if (flags_on & att_function)
{
if (offset) /* declare -f [-rix] foo=bar */
{
builtin_error (_("cannot use `-f' to make functions"));
free (name);
return (EXECUTION_FAILURE);
}
else /* declare -f [-rx] name [name...] */
{
var = find_function (name);
if (var)
{
if (readonly_p (var) && (flags_off & att_readonly))
{
builtin_error (_("%s: readonly function"), name);
any_failed++;
NEXT_VARIABLE ();
}
/* declare -[Ff] name [name...] */
if (flags_on == att_function && flags_off == 0)
{
#if defined (DEBUGGER)
if (nodefs && debugging_mode)
{
shell_fn = find_function_def (var->name);
if (shell_fn)
printf ("%s %d %s\n", var->name, shell_fn->line, shell_fn->source_file);
else
printf ("%s\n", var->name);
}
else
#endif /* DEBUGGER */
{
t = nodefs ? var->name
: named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
printf ("%s\n", t);
any_failed = sh_chkwrite (any_failed);
}
}
else /* declare -[fF] -[rx] name [name...] */
{
VSETATTR (var, flags_on);
VUNSETATTR (var, flags_off);
}
}
else
any_failed++;
NEXT_VARIABLE ();
}
}
else /* declare -[aAirx] name [name...] */
{
/* Non-null if we just created or fetched a local variable. */
/* Here's what ksh93 seems to do. If we are modifying an existing
nameref variable, we don't follow the nameref chain past the last
nameref, and we set the nameref variable's value so future
references to that variable will return the value of the variable
we're assigning right now. */
if (var == 0 && (flags_on & att_nameref))
{
/* See if we are trying to modify an existing nameref variable */
var = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
if (var && nameref_p (var) == 0)
var = 0;
}
/* However, if we're turning off the nameref attribute on an existing
nameref variable, we first follow the nameref chain to the end,
modify the value of the variable this nameref variable references,
*CHANGING ITS VALUE AS A SIDE EFFECT* then turn off the nameref
flag *LEAVING THE NAMEREF VARIABLE'S VALUE UNCHANGED* */
else if (var == 0 && (flags_off & att_nameref))
{
/* See if we are trying to modify an existing nameref variable */
refvar = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
if (refvar && nameref_p (refvar) == 0)
refvar = 0;
if (refvar)
var = mkglobal ? find_global_variable (nameref_cell (refvar)) : find_variable (nameref_cell (refvar));
}
if (var == 0)
var = mkglobal ? find_global_variable (name) : find_variable (name);
if (var == 0)
{
#if defined (ARRAY_VARS)
if (flags_on & att_assoc)
var = make_new_assoc_variable (name);
else if ((flags_on & att_array) || making_array_special)
var = make_new_array_variable (name);
else
#endif
if (offset)
var = bind_variable (name, "", 0);
else
{
var = bind_variable (name, (char *)NULL, 0);
VSETATTR (var, att_invisible);
}
}
/* Cannot use declare +r to turn off readonly attribute. */
if (readonly_p (var) && (flags_off & att_readonly))
{
sh_readonly (name);
any_failed++;
NEXT_VARIABLE ();
}
/* Cannot use declare to assign value to readonly or noassign
variable. */
if ((readonly_p (var) || noassign_p (var)) && offset)
{
if (readonly_p (var))
sh_readonly (name);
assign_error++;
NEXT_VARIABLE ();
}
#if defined (ARRAY_VARS)
if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset)
{
int vlen;
vlen = STRLEN (value);
if (value[0] == '(' && value[vlen-1] == ')')
compound_array_assign = 1;
else
simple_array_assign = 1;
}
/* Cannot use declare +a name or declare +A name to remove an
array variable. */
if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var)))
{
builtin_error (_("%s: cannot destroy array variables in this way"), name);
any_failed++;
NEXT_VARIABLE ();
}
if ((flags_on & att_array) && assoc_p (var))
{
builtin_error (_("%s: cannot convert associative to indexed array"), name);
any_failed++;
NEXT_VARIABLE ();
}
if ((flags_on & att_assoc) && array_p (var))
{
builtin_error (_("%s: cannot convert indexed to associative array"), name);
any_failed++;
NEXT_VARIABLE ();
}
/* declare -A name[[n]] makes name an associative array variable. */
if (flags_on & att_assoc)
{
if (assoc_p (var) == 0)
var = convert_var_to_assoc (var);
}
/* declare -a name[[n]] or declare name[n] makes name an indexed
array variable. */
else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
var = convert_var_to_array (var);
#endif /* ARRAY_VARS */
/* XXX - we note that we are turning on nameref attribute and defer
setting it until the assignment has been made so we don't do an
inadvertent nameref lookup. Might have to do the same thing for
flags_off&att_nameref. */
/* XXX - ksh93 makes it an error to have a readonly nameref variable */
onref = (flags_on & att_nameref);
flags_on &= ~att_nameref;
if (array_p (var) || assoc_p (var)
|| (offset && compound_array_assign)
|| simple_array_assign)
onref = 0; /* array variables may not be namerefs */
/* ksh93 seems to do this */
offref = (flags_off & att_nameref);
flags_off &= ~att_nameref;
VSETATTR (var, flags_on);
VUNSETATTR (var, flags_off);
#if defined (ARRAY_VARS)
if (offset && compound_array_assign)
assign_array_var_from_string (var, value, aflags);
else if (simple_array_assign && subscript_start)
{
/* declare [-aA] name[N]=value */
*subscript_start = '['; /* ] */
var = assign_array_element (name, value, 0); /* XXX - not aflags */
*subscript_start = '\0';
if (var == 0) /* some kind of assignment error */
{
assign_error++;
flags_on |= onref;
flags_off |= offref;
NEXT_VARIABLE ();
}
}
else if (simple_array_assign)
{
/* let bind_{array,assoc}_variable take care of this. */
if (assoc_p (var))
bind_assoc_variable (var, name, savestring ("0"), value, aflags);
else
bind_array_variable (name, 0, value, aflags);
}
else
#endif
/* bind_variable_value duplicates the essential internals of
bind_variable() */
if (offset)
bind_variable_value (var, value, aflags);
/* If we found this variable in the temporary environment, as with
`var=value declare -x var', make sure it is treated identically
to `var=value export var'. Do the same for `declare -r' and
`readonly'. Preserve the attributes, except for att_tempvar. */
/* XXX -- should this create a variable in the global scope, or
modify the local variable flags? ksh93 has it modify the
global scope.
Need to handle case like in set_var_attribute where a temporary
variable is in the same table as the function local vars. */
if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
{
SHELL_VAR *tv;
char *tvalue;
tv = find_tempenv_variable (var->name);
if (tv)
{
tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
tv = bind_variable (var->name, tvalue, 0);
tv->attributes |= var->attributes & ~att_tempvar;
if (tv->context > 0)
VSETATTR (tv, att_propagate);
free (tvalue);
}
VSETATTR (var, att_propagate);
}
}
/* Turn on nameref attribute we deferred above. */
/* XXX - should we turn on the noassign attribute for consistency with
ksh93 when we turn on the nameref attribute? */
VSETATTR (var, onref);
flags_on |= onref;
VUNSETATTR (var, offref);
flags_off |= offref;
/* Yuck. ksh93 compatibility */
if (refvar)
VUNSETATTR (refvar, flags_off);
stupidly_hack_special_variables (name);
NEXT_VARIABLE ();
}
return (assign_error ? EX_BADASSIGN
: ((any_failed == 0) ? EXECUTION_SUCCESS
: EXECUTION_FAILURE));
}
-349
View File
@@ -1,349 +0,0 @@
/* evalfile.c - read and evaluate commands from a file or file descriptor */
/* Copyright (C) 1996-2009 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashtypes.h"
#include "posixstat.h"
#include "filecntl.h"
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include "../bashansi.h"
#include "../bashintl.h"
#include "../shell.h"
#include "../jobs.h"
#include "../builtins.h"
#include "../flags.h"
#include "../input.h"
#include "../execute_cmd.h"
#include "../trap.h"
#if defined (HISTORY)
# include "../bashhist.h"
#endif
#include <typemax.h>
#include "common.h"
#if !defined (errno)
extern int errno;
#endif
/* Flags for _evalfile() */
#define FEVAL_ENOENTOK 0x001
#define FEVAL_BUILTIN 0x002
#define FEVAL_UNWINDPROT 0x004
#define FEVAL_NONINT 0x008
#define FEVAL_LONGJMP 0x010
#define FEVAL_HISTORY 0x020
#define FEVAL_CHECKBINARY 0x040
#define FEVAL_REGFILE 0x080
#define FEVAL_NOPUSHARGS 0x100
extern int posixly_correct;
extern int indirection_level, subshell_environment;
extern int return_catch_flag, return_catch_value;
extern int last_command_exit_value;
extern int executing_command_builtin;
/* How many `levels' of sourced files we have. */
int sourcelevel = 0;
static int
_evalfile (filename, flags)
const char *filename;
int flags;
{
volatile int old_interactive;
procenv_t old_return_catch;
int return_val, fd, result, pflags, i, nnull;
ssize_t nr; /* return value from read(2) */
char *string;
struct stat finfo;
size_t file_size;
sh_vmsg_func_t *errfunc;
#if defined (ARRAY_VARS)
SHELL_VAR *funcname_v, *nfv, *bash_source_v, *bash_lineno_v;
ARRAY *funcname_a, *bash_source_a, *bash_lineno_a;
# if defined (DEBUGGER)
SHELL_VAR *bash_argv_v, *bash_argc_v;
ARRAY *bash_argv_a, *bash_argc_a;
# endif
char *t, tt[2];
#endif
char *lastcom;
USE_VAR(pflags);
#if defined (ARRAY_VARS)
GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a);
# if defined (DEBUGGER)
GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
# endif
#endif
fd = open (filename, O_RDONLY);
if (fd < 0 || (fstat (fd, &finfo) == -1))
{
file_error_and_exit:
if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT)
file_error (filename);
if (flags & FEVAL_LONGJMP)
{
last_command_exit_value = 1;
jump_to_top_level (EXITPROG);
}
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE
: ((errno == ENOENT) ? 0 : -1));
}
errfunc = ((flags & FEVAL_BUILTIN) ? builtin_error : internal_error);
if (S_ISDIR (finfo.st_mode))
{
(*errfunc) (_("%s: is a directory"), filename);
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
}
else if ((flags & FEVAL_REGFILE) && S_ISREG (finfo.st_mode) == 0)
{
(*errfunc) (_("%s: not a regular file"), filename);
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
}
file_size = (size_t)finfo.st_size;
/* Check for overflow with large files. */
if (file_size != finfo.st_size || file_size + 1 < file_size)
{
(*errfunc) (_("%s: file is too large"), filename);
return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
}
if (S_ISREG (finfo.st_mode) && file_size <= SSIZE_MAX)
{
string = (char *)xmalloc (1 + file_size);
nr = read (fd, string, file_size);
if (nr >= 0)
string[nr] = '\0';
}
else
nr = zmapfd (fd, &string, 0);
return_val = errno;
close (fd);
errno = return_val;
if (nr < 0) /* XXX was != file_size, not < 0 */
{
free (string);
goto file_error_and_exit;
}
if (nr == 0)
{
free (string);
return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1);
}
if ((flags & FEVAL_CHECKBINARY) &&
check_binary_file (string, (nr > 80) ? 80 : nr))
{
free (string);
(*errfunc) (_("%s: cannot execute binary file"), filename);
return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1);
}
i = strlen (string);
if (i < nr)
{
for (nnull = i = 0; i < nr; i++)
if (string[i] == '\0')
{
memmove (string+i, string+i+1, nr - i);
nr--;
/* Even if the `check binary' flag is not set, we want to avoid
sourcing files with more than 256 null characters -- that
probably indicates a binary file. */
if ((flags & FEVAL_BUILTIN) && ++nnull > 256)
{
free (string);
(*errfunc) (_("%s: cannot execute binary file"), filename);
return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1);
}
}
}
if (flags & FEVAL_UNWINDPROT)
{
begin_unwind_frame ("_evalfile");
unwind_protect_int (return_catch_flag);
unwind_protect_jmp_buf (return_catch);
if (flags & FEVAL_NONINT)
unwind_protect_int (interactive);
unwind_protect_int (sourcelevel);
}
else
{
COPY_PROCENV (return_catch, old_return_catch);
if (flags & FEVAL_NONINT)
old_interactive = interactive;
}
if (flags & FEVAL_NONINT)
interactive = 0;
return_catch_flag++;
sourcelevel++;
#if defined (ARRAY_VARS)
array_push (bash_source_a, (char *)filename);
t = itos (executing_line_number ());
array_push (bash_lineno_a, t);
free (t);
array_push (funcname_a, "source"); /* not exactly right */
# if defined (DEBUGGER)
/* Have to figure out a better way to do this when `source' is supplied
arguments */
if ((flags & FEVAL_NOPUSHARGS) == 0)
{
array_push (bash_argv_a, (char *)filename);
tt[0] = '1'; tt[1] = '\0';
array_push (bash_argc_a, tt);
}
# endif
#endif
/* set the flags to be passed to parse_and_execute */
pflags = SEVAL_RESETLINE;
pflags |= (flags & FEVAL_HISTORY) ? 0 : SEVAL_NOHIST;
if (flags & FEVAL_BUILTIN)
result = EXECUTION_SUCCESS;
return_val = setjmp (return_catch);
/* If `return' was seen outside of a function, but in the script, then
force parse_and_execute () to clean up. */
if (return_val)
{
parse_and_execute_cleanup ();
result = return_catch_value;
}
else
result = parse_and_execute (string, filename, pflags);
if (flags & FEVAL_UNWINDPROT)
run_unwind_frame ("_evalfile");
else
{
if (flags & FEVAL_NONINT)
interactive = old_interactive;
return_catch_flag--;
sourcelevel--;
COPY_PROCENV (old_return_catch, return_catch);
}
#if defined (ARRAY_VARS)
/* These two variables cannot be unset, and cannot be affected by the
sourced file. */
array_pop (bash_source_a);
array_pop (bash_lineno_a);
/* FUNCNAME can be unset, and so can potentially be changed by the
sourced file. */
GET_ARRAY_FROM_VAR ("FUNCNAME", nfv, funcname_a);
if (nfv == funcname_v)
array_pop (funcname_a);
# if defined (DEBUGGER)
if ((flags & FEVAL_NOPUSHARGS) == 0)
{
array_pop (bash_argc_a);
array_pop (bash_argv_a);
}
# endif
#endif
return ((flags & FEVAL_BUILTIN) ? result : 1);
}
int
maybe_execute_file (fname, force_noninteractive)
const char *fname;
int force_noninteractive;
{
char *filename;
int result, flags;
filename = bash_tilde_expand (fname, 0);
flags = FEVAL_ENOENTOK;
if (force_noninteractive)
flags |= FEVAL_NONINT;
result = _evalfile (filename, flags);
free (filename);
return result;
}
#if defined (HISTORY)
int
fc_execute_file (filename)
const char *filename;
{
int flags;
/* We want these commands to show up in the history list if
remember_on_history is set. */
flags = FEVAL_ENOENTOK|FEVAL_HISTORY|FEVAL_REGFILE;
return (_evalfile (filename, flags));
}
#endif /* HISTORY */
int
source_file (filename, sflags)
const char *filename;
int sflags;
{
int flags, rval;
flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
if (sflags)
flags |= FEVAL_NOPUSHARGS;
/* POSIX shells exit if non-interactive and file error. */
if (posixly_correct && interactive_shell == 0 && executing_command_builtin == 0)
flags |= FEVAL_LONGJMP;
rval = _evalfile (filename, flags);
run_return_trap ();
return rval;
}
-524
View File
@@ -1,524 +0,0 @@
/* evalstring.c - evaluate a string as one or more shell commands. */
/* Copyright (C) 1996-2012 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include "filecntl.h"
#include "../bashansi.h"
#include "../shell.h"
#include "../jobs.h"
#include "../builtins.h"
#include "../flags.h"
#include "../input.h"
#include "../execute_cmd.h"
#include "../redir.h"
#include "../trap.h"
#include "../bashintl.h"
#include <y.tab.h>
#if defined (HISTORY)
# include "../bashhist.h"
#endif
#include "common.h"
#include "builtext.h"
#if !defined (errno)
extern int errno;
#endif
#define IS_BUILTIN(s) (builtin_address_internal(s, 0) != (struct builtin *)NULL)
extern int indirection_level, subshell_environment;
extern int line_number, line_number_for_err_trap;
extern int current_token, shell_eof_token;
extern int last_command_exit_value;
extern int running_trap;
extern int loop_level;
extern int executing_list;
extern int comsub_ignore_return;
extern int posixly_correct;
extern sh_builtin_func_t *this_shell_builtin;
extern char *the_printed_command_except_trap;
int parse_and_execute_level = 0;
static int cat_file __P((REDIRECT *));
#define PE_TAG "parse_and_execute top"
#define PS_TAG "parse_string top"
#if defined (HISTORY)
static void
set_history_remembering ()
{
remember_on_history = enable_history_list;
}
#endif
static void
restore_lastcom (x)
char *x;
{
FREE (the_printed_command_except_trap);
the_printed_command_except_trap = x;
}
/* How to force parse_and_execute () to clean up after itself. */
void
parse_and_execute_cleanup ()
{
if (running_trap)
{
run_trap_cleanup (running_trap - 1);
unfreeze_jobs_list ();
}
if (have_unwind_protects ())
run_unwind_frame (PE_TAG);
else
parse_and_execute_level = 0; /* XXX */
}
static void
parse_prologue (string, flags, tag)
char *string;
int flags;
char *tag;
{
char *orig_string;
int x;
orig_string = string;
/* Unwind protect this invocation of parse_and_execute (). */
begin_unwind_frame (tag);
unwind_protect_int (parse_and_execute_level);
unwind_protect_jmp_buf (top_level);
unwind_protect_int (indirection_level);
unwind_protect_int (line_number);
unwind_protect_int (line_number_for_err_trap);
unwind_protect_int (loop_level);
unwind_protect_int (executing_list);
unwind_protect_int (comsub_ignore_return);
if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
unwind_protect_int (interactive);
#if defined (HISTORY)
if (parse_and_execute_level == 0)
add_unwind_protect (set_history_remembering, (char *)NULL);
else
unwind_protect_int (remember_on_history); /* can be used in scripts */
# if defined (BANG_HISTORY)
if (interactive_shell)
unwind_protect_int (history_expansion_inhibited);
# endif /* BANG_HISTORY */
#endif /* HISTORY */
if (interactive_shell)
{
x = get_current_prompt_level ();
add_unwind_protect (set_current_prompt_level, x);
}
if (the_printed_command_except_trap)
{
lastcom = savestring (the_printed_command_except_trap);
add_unwind_protect (restore_lastcom (lastcom));
}
add_unwind_protect (pop_stream, (char *)NULL);
if (orig_string && ((flags & SEVAL_NOFREE) == 0))
add_unwind_protect (xfree, orig_string);
end_unwind_frame ();
if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
interactive = (flags & SEVAL_NONINT) ? 0 : 1;
#if defined (HISTORY)
if (flags & SEVAL_NOHIST)
bash_history_disable ();
#endif /* HISTORY */
}
/* Parse and execute the commands in STRING. Returns whatever
execute_command () returns. This frees STRING. FLAGS is a
flags word; look in common.h for the possible values. Actions
are:
(flags & SEVAL_NONINT) -> interactive = 0;
(flags & SEVAL_INTERACT) -> interactive = 1;
(flags & SEVAL_NOHIST) -> call bash_history_disable ()
(flags & SEVAL_NOFREE) -> don't free STRING when finished
(flags & SEVAL_RESETLINE) -> reset line_number to 1
*/
int
parse_and_execute (string, from_file, flags)
char *string;
const char *from_file;
int flags;
{
int code, lreset;
volatile int should_jump_to_top_level, last_result;
COMMAND *volatile command;
parse_prologue (string, flags, PE_TAG);
parse_and_execute_level++;
lreset = flags & SEVAL_RESETLINE;
/* Reset the line number if the caller wants us to. If we don't reset the
line number, we have to subtract one, because we will add one just
before executing the next command (resetting the line number sets it to
0; the first line number is 1). */
push_stream (lreset);
if (lreset == 0)
line_number--;
indirection_level++;
code = should_jump_to_top_level = 0;
last_result = EXECUTION_SUCCESS;
with_input_from_string (string, from_file);
while (*(bash_input.location.string))
{
command = (COMMAND *)NULL;
if (interrupt_state)
{
last_result = EXECUTION_FAILURE;
break;
}
/* Provide a location for functions which `longjmp (top_level)' to
jump to. This prevents errors in substitution from restarting
the reader loop directly, for example. */
code = setjmp (top_level);
if (code)
{
should_jump_to_top_level = 0;
switch (code)
{
case FORCE_EOF:
case ERREXIT:
case EXITPROG:
if (command)
run_unwind_frame ("pe_dispose");
/* Remember to call longjmp (top_level) after the old
value for it is restored. */
should_jump_to_top_level = 1;
goto out;
case DISCARD:
if (command)
run_unwind_frame ("pe_dispose");
last_result = last_command_exit_value = EXECUTION_FAILURE; /* XXX */
if (subshell_environment)
{
should_jump_to_top_level = 1;
goto out;
}
else
{
#if 0
dispose_command (command); /* pe_dispose does this */
#endif
continue;
}
default:
command_error ("parse_and_execute", CMDERR_BADJUMP, code, 0);
break;
}
}
if (parse_command () == 0)
{
if ((flags & SEVAL_PARSEONLY) || (interactive_shell == 0 && read_but_dont_execute))
{
last_result = EXECUTION_SUCCESS;
dispose_command (global_command);
global_command = (COMMAND *)NULL;
}
else if (command = global_command)
{
struct fd_bitmap *bitmap;
bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
begin_unwind_frame ("pe_dispose");
add_unwind_protect (dispose_fd_bitmap, bitmap);
add_unwind_protect (dispose_command, command); /* XXX */
global_command = (COMMAND *)NULL;
if ((subshell_environment & SUBSHELL_COMSUB) && comsub_ignore_return)
command->flags |= CMD_IGNORE_RETURN;
#if defined (ONESHOT)
/*
* IF
* we were invoked as `bash -c' (startup_state == 2) AND
* parse_and_execute has not been called recursively AND
* we're not running a trap AND
* we have parsed the full command (string == '\0') AND
* we're not going to run the exit trap AND
* we have a simple command without redirections AND
* the command is not being timed AND
* the command's return status is not being inverted
* THEN
* tell the execution code that we don't need to fork
*/
if (startup_state == 2 && parse_and_execute_level == 1 &&
running_trap == 0 &&
*bash_input.location.string == '\0' &&
command->type == cm_simple &&
signal_is_trapped (EXIT_TRAP) == 0 &&
command->redirects == 0 && command->value.Simple->redirects == 0 &&
((command->flags & CMD_TIME_PIPELINE) == 0) &&
((command->flags & CMD_INVERT_RETURN) == 0))
{
command->flags |= CMD_NO_FORK;
command->value.Simple->flags |= CMD_NO_FORK;
}
#endif /* ONESHOT */
/* See if this is a candidate for $( <file ). */
if (startup_state == 2 &&
(subshell_environment & SUBSHELL_COMSUB) &&
*bash_input.location.string == '\0' &&
command->type == cm_simple && !command->redirects &&
(command->flags & CMD_TIME_PIPELINE) == 0 &&
command->value.Simple->words == 0 &&
command->value.Simple->redirects &&
command->value.Simple->redirects->next == 0 &&
command->value.Simple->redirects->instruction == r_input_direction &&
command->value.Simple->redirects->redirector.dest == 0)
{
int r;
r = cat_file (command->value.Simple->redirects);
last_result = (r < 0) ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
}
else
last_result = execute_command_internal
(command, 0, NO_PIPE, NO_PIPE, bitmap);
dispose_command (command);
dispose_fd_bitmap (bitmap);
discard_unwind_frame ("pe_dispose");
}
}
else
{
last_result = EXECUTION_FAILURE;
if (interactive_shell == 0 && this_shell_builtin &&
(this_shell_builtin == source_builtin || this_shell_builtin == eval_builtin) &&
last_command_exit_value == EX_BADSYNTAX && posixly_correct)
{
should_jump_to_top_level = 1;
code = ERREXIT;
last_command_exit_value = EX_BADUSAGE;
}
/* Since we are shell compatible, syntax errors in a script
abort the execution of the script. Right? */
break;
}
}
out:
run_unwind_frame (PE_TAG);
if (interrupt_state && parse_and_execute_level == 0)
{
/* An interrupt during non-interactive execution in an
interactive shell (e.g. via $PROMPT_COMMAND) should
not cause the shell to exit. */
interactive = interactive_shell;
throw_to_top_level ();
}
if (should_jump_to_top_level)
jump_to_top_level (code);
return (last_result);
}
/* Parse a command contained in STRING according to FLAGS and return the
number of characters consumed from the string. If non-NULL, set *ENDP
to the position in the string where the parse ended. Used to validate
command substitutions during parsing to obey Posix rules about finding
the end of the command and balancing parens. */
int
parse_string (string, from_file, flags, endp)
char *string;
const char *from_file;
int flags;
char **endp;
{
int code, nc;
volatile int should_jump_to_top_level;
COMMAND *volatile command, *oglobal;
char *ostring;
parse_prologue (string, flags, PS_TAG);
/* Reset the line number if the caller wants us to. If we don't reset the
line number, we have to subtract one, because we will add one just
before executing the next command (resetting the line number sets it to
0; the first line number is 1). */
push_stream (0);
code = should_jump_to_top_level = 0;
oglobal = global_command;
ostring = string;
with_input_from_string (string, from_file);
while (*(bash_input.location.string))
{
command = (COMMAND *)NULL;
#if 0
if (interrupt_state)
break;
#endif
/* Provide a location for functions which `longjmp (top_level)' to
jump to. */
code = setjmp (top_level);
if (code)
{
#if defined (DEBUG)
itrace("parse_string: longjmp executed: code = %d", code);
#endif
should_jump_to_top_level = 0;
switch (code)
{
case FORCE_EOF:
case ERREXIT:
case EXITPROG:
case DISCARD: /* XXX */
if (command)
dispose_command (command);
/* Remember to call longjmp (top_level) after the old
value for it is restored. */
should_jump_to_top_level = 1;
goto out;
default:
command_error ("parse_string", CMDERR_BADJUMP, code, 0);
break;
}
}
if (parse_command () == 0)
{
dispose_command (global_command);
global_command = (COMMAND *)NULL;
}
else
{
if ((flags & SEVAL_NOLONGJMP) == 0)
{
should_jump_to_top_level = 1;
code = DISCARD;
}
else
reset_parser (); /* XXX - sets token_to_read */
break;
}
if (current_token == yacc_EOF || current_token == shell_eof_token)
break;
}
out:
global_command = oglobal;
nc = bash_input.location.string - ostring;
if (endp)
*endp = bash_input.location.string;
run_unwind_frame (PS_TAG);
if (should_jump_to_top_level)
jump_to_top_level (code);
return (nc);
}
/* Handle a $( < file ) command substitution. This expands the filename,
returning errors as appropriate, then just cats the file to the standard
output. */
static int
cat_file (r)
REDIRECT *r;
{
char *fn;
int fd, rval;
if (r->instruction != r_input_direction)
return -1;
/* Get the filename. */
if (posixly_correct && !interactive_shell)
disallow_filename_globbing++;
fn = redirection_expand (r->redirectee.filename);
if (posixly_correct && !interactive_shell)
disallow_filename_globbing--;
if (fn == 0)
{
redirection_error (r, AMBIGUOUS_REDIRECT);
return -1;
}
fd = open(fn, O_RDONLY);
if (fd < 0)
{
file_error (fn);
free (fn);
return -1;
}
rval = zcatfd (fd, 1, fn);
free (fn);
close (fd);
return (rval);
}
-1252
View File
File diff suppressed because it is too large Load Diff
-878
View File
@@ -1,878 +0,0 @@
This file is set.def, from which is created set.c.
It implements the "set" and "unset" builtins in Bash.
Copyright (C) 1987-2011 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
$PRODUCES set.c
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <stdio.h>
#include "../bashansi.h"
#include "../bashintl.h"
#include "../shell.h"
#include "../flags.h"
#include "common.h"
#include "bashgetopt.h"
#if defined (READLINE)
# include "../input.h"
# include "../bashline.h"
# include <readline/readline.h>
#endif
#if defined (HISTORY)
# include "../bashhist.h"
#endif
extern int posixly_correct, ignoreeof, eof_encountered_limit;
#if defined (HISTORY)
extern int dont_save_function_defs;
#endif
#if defined (READLINE)
extern int no_line_editing;
#endif /* READLINE */
$BUILTIN set
$FUNCTION set_builtin
$SHORT_DOC set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
Set or unset values of shell options and positional parameters.
Change the value of shell attributes and positional parameters, or
display the names and values of shell variables.
Options:
-a Mark variables which are modified or created for export.
-b Notify of job termination immediately.
-e Exit immediately if a command exits with a non-zero status.
-f Disable file name generation (globbing).
-h Remember the location of commands as they are looked up.
-k All assignment arguments are placed in the environment for a
command, not just those that precede the command name.
-m Job control is enabled.
-n Read commands but do not execute them.
-o option-name
Set the variable corresponding to option-name:
allexport same as -a
braceexpand same as -B
#if defined (READLINE)
emacs use an emacs-style line editing interface
#endif /* READLINE */
errexit same as -e
errtrace same as -E
functrace same as -T
hashall same as -h
#if defined (BANG_HISTORY)
histexpand same as -H
#endif /* BANG_HISTORY */
#if defined (HISTORY)
history enable command history
#endif
ignoreeof the shell will not exit upon reading EOF
interactive-comments
allow comments to appear in interactive commands
keyword same as -k
#if defined (JOB_CONTROL)
monitor same as -m
#endif
noclobber same as -C
noexec same as -n
noglob same as -f
nolog currently accepted but ignored
#if defined (JOB_CONTROL)
notify same as -b
#endif
nounset same as -u
onecmd same as -t
physical same as -P
pipefail the return value of a pipeline is the status of
the last command to exit with a non-zero status,
or zero if no command exited with a non-zero status
posix change the behavior of bash where the default
operation differs from the Posix standard to
match the standard
privileged same as -p
verbose same as -v
#if defined (READLINE)
vi use a vi-style line editing interface
#endif /* READLINE */
xtrace same as -x
-p Turned on whenever the real and effective user ids do not match.
Disables processing of the $ENV file and importing of shell
functions. Turning this option off causes the effective uid and
gid to be set to the real uid and gid.
-t Exit after reading and executing one command.
-u Treat unset variables as an error when substituting.
-v Print shell input lines as they are read.
-x Print commands and their arguments as they are executed.
#if defined (BRACE_EXPANSION)
-B the shell will perform brace expansion
#endif /* BRACE_EXPANSION */
-C If set, disallow existing regular files to be overwritten
by redirection of output.
-E If set, the ERR trap is inherited by shell functions.
#if defined (BANG_HISTORY)
-H Enable ! style history substitution. This flag is on
by default when the shell is interactive.
#endif /* BANG_HISTORY */
-P If set, do not resolve symbolic links when executing commands
such as cd which change the current directory.
-T If set, the DEBUG trap is inherited by shell functions.
-- Assign any remaining arguments to the positional parameters.
If there are no remaining arguments, the positional parameters
are unset.
- Assign any remaining arguments to the positional parameters.
The -x and -v options are turned off.
Using + rather than - causes these flags to be turned off. The
flags can also be used upon invocation of the shell. The current
set of flags may be found in $-. The remaining n ARGs are positional
parameters and are assigned, in order, to $1, $2, .. $n. If no
ARGs are given, all shell variables are printed.
Exit Status:
Returns success unless an invalid option is given.
$END
typedef int setopt_set_func_t __P((int, char *));
typedef int setopt_get_func_t __P((char *));
static void print_minus_o_option __P((char *, int, int));
static void print_all_shell_variables __P((void));
static int set_ignoreeof __P((int, char *));
static int set_posix_mode __P((int, char *));
#if defined (READLINE)
static int set_edit_mode __P((int, char *));
static int get_edit_mode __P((char *));
#endif
#if defined (HISTORY)
static int bash_set_history __P((int, char *));
#endif
static const char * const on = "on";
static const char * const off = "off";
/* A struct used to match long options for set -o to the corresponding
option letter or internal variable. The functions can be called to
dynamically generate values. */
const struct {
char *name;
int letter;
int *variable;
setopt_set_func_t *set_func;
setopt_get_func_t *get_func;
} o_options[] = {
{ "allexport", 'a', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#if defined (BRACE_EXPANSION)
{ "braceexpand",'B', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#endif
#if defined (READLINE)
{ "emacs", '\0', (int *)NULL, set_edit_mode, get_edit_mode },
#endif
{ "errexit", 'e', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
{ "errtrace", 'E', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
{ "functrace", 'T', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
{ "hashall", 'h', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#if defined (BANG_HISTORY)
{ "histexpand", 'H', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#endif /* BANG_HISTORY */
#if defined (HISTORY)
{ "history", '\0', &enable_history_list, bash_set_history, (setopt_get_func_t *)NULL },
#endif
{ "ignoreeof", '\0', &ignoreeof, set_ignoreeof, (setopt_get_func_t *)NULL },
{ "interactive-comments", '\0', &interactive_comments, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
{ "keyword", 'k', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#if defined (JOB_CONTROL)
{ "monitor", 'm', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#endif
{ "noclobber", 'C', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
{ "noexec", 'n', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
{ "noglob", 'f', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#if defined (HISTORY)
{ "nolog", '\0', &dont_save_function_defs, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#endif
#if defined (JOB_CONTROL)
{ "notify", 'b', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#endif /* JOB_CONTROL */
{ "nounset", 'u', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
{ "onecmd", 't', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
{ "physical", 'P', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
{ "pipefail", '\0', &pipefail_opt, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
{ "posix", '\0', &posixly_correct, set_posix_mode, (setopt_get_func_t *)NULL },
{ "privileged", 'p', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
{ "verbose", 'v', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#if defined (READLINE)
{ "vi", '\0', (int *)NULL, set_edit_mode, get_edit_mode },
#endif
{ "xtrace", 'x', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
{(char *)NULL, 0 , (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
};
#define N_O_OPTIONS (sizeof (o_options) / sizeof (o_options[0]))
#define GET_BINARY_O_OPTION_VALUE(i, name) \
((o_options[i].get_func) ? (*o_options[i].get_func) (name) \
: (*o_options[i].variable))
#define SET_BINARY_O_OPTION_VALUE(i, onoff, name) \
((o_options[i].set_func) ? (*o_options[i].set_func) (onoff, name) \
: (*o_options[i].variable = (onoff == FLAG_ON)))
int
minus_o_option_value (name)
char *name;
{
register int i;
int *on_or_off;
for (i = 0; o_options[i].name; i++)
{
if (STREQ (name, o_options[i].name))
{
if (o_options[i].letter)
{
on_or_off = find_flag (o_options[i].letter);
return ((on_or_off == FLAG_UNKNOWN) ? -1 : *on_or_off);
}
else
return (GET_BINARY_O_OPTION_VALUE (i, name));
}
}
return (-1);
}
#define MINUS_O_FORMAT "%-15s\t%s\n"
static void
print_minus_o_option (name, value, pflag)
char *name;
int value, pflag;
{
if (pflag == 0)
printf (MINUS_O_FORMAT, name, value ? on : off);
else
printf ("set %co %s\n", value ? '-' : '+', name);
}
void
list_minus_o_opts (mode, reusable)
int mode, reusable;
{
register int i;
int *on_or_off, value;
for (i = 0; o_options[i].name; i++)
{
if (o_options[i].letter)
{
value = 0;
on_or_off = find_flag (o_options[i].letter);
if (on_or_off == FLAG_UNKNOWN)
on_or_off = &value;
if (mode == -1 || mode == *on_or_off)
print_minus_o_option (o_options[i].name, *on_or_off, reusable);
}
else
{
value = GET_BINARY_O_OPTION_VALUE (i, o_options[i].name);
if (mode == -1 || mode == value)
print_minus_o_option (o_options[i].name, value, reusable);
}
}
}
char **
get_minus_o_opts ()
{
char **ret;
int i;
ret = strvec_create (N_O_OPTIONS + 1);
for (i = 0; o_options[i].name; i++)
ret[i] = o_options[i].name;
ret[i] = (char *)NULL;
return ret;
}
static int
set_ignoreeof (on_or_off, option_name)
int on_or_off;
char *option_name;
{
ignoreeof = on_or_off == FLAG_ON;
unbind_variable ("ignoreeof");
if (ignoreeof)
bind_variable ("IGNOREEOF", "10", 0);
else
unbind_variable ("IGNOREEOF");
sv_ignoreeof ("IGNOREEOF");
return 0;
}
static int
set_posix_mode (on_or_off, option_name)
int on_or_off;
char *option_name;
{
posixly_correct = on_or_off == FLAG_ON;
if (posixly_correct == 0)
unbind_variable ("POSIXLY_CORRECT");
else
bind_variable ("POSIXLY_CORRECT", "y", 0);
sv_strict_posix ("POSIXLY_CORRECT");
return (0);
}
#if defined (READLINE)
/* Magic. This code `knows' how readline handles rl_editing_mode. */
static int
set_edit_mode (on_or_off, option_name)
int on_or_off;
char *option_name;
{
int isemacs;
if (on_or_off == FLAG_ON)
{
rl_variable_bind ("editing-mode", option_name);
if (interactive)
with_input_from_stdin ();
no_line_editing = 0;
}
else
{
isemacs = rl_editing_mode == 1;
if ((isemacs && *option_name == 'e') || (!isemacs && *option_name == 'v'))
{
if (interactive)
with_input_from_stream (stdin, "stdin");
no_line_editing = 1;
}
}
return 1-no_line_editing;
}
static int
get_edit_mode (name)
char *name;
{
return (*name == 'e' ? no_line_editing == 0 && rl_editing_mode == 1
: no_line_editing == 0 && rl_editing_mode == 0);
}
#endif /* READLINE */
#if defined (HISTORY)
static int
bash_set_history (on_or_off, option_name)
int on_or_off;
char *option_name;
{
if (on_or_off == FLAG_ON)
{
enable_history_list = 1;
bash_history_enable ();
if (history_lines_this_session == 0)
load_history ();
}
else
{
enable_history_list = 0;
bash_history_disable ();
}
return (1 - enable_history_list);
}
#endif
int
set_minus_o_option (on_or_off, option_name)
int on_or_off;
char *option_name;
{
register int i;
for (i = 0; o_options[i].name; i++)
{
if (STREQ (option_name, o_options[i].name))
{
if (o_options[i].letter == 0)
{
SET_BINARY_O_OPTION_VALUE (i, on_or_off, option_name);
return (EXECUTION_SUCCESS);
}
else
{
if (change_flag (o_options[i].letter, on_or_off) == FLAG_ERROR)
{
sh_invalidoptname (option_name);
return (EXECUTION_FAILURE);
}
else
return (EXECUTION_SUCCESS);
}
}
}
sh_invalidoptname (option_name);
return (EX_USAGE);
}
static void
print_all_shell_variables ()
{
SHELL_VAR **vars;
vars = all_shell_variables ();
if (vars)
{
print_var_list (vars);
free (vars);
}
/* POSIX.2 does not allow function names and definitions to be output when
`set' is invoked without options (PASC Interp #202). */
if (posixly_correct == 0)
{
vars = all_shell_functions ();
if (vars)
{
print_func_list (vars);
free (vars);
}
}
}
void
set_shellopts ()
{
char *value;
char tflag[N_O_OPTIONS];
int vsize, i, vptr, *ip, exported;
SHELL_VAR *v;
for (vsize = i = 0; o_options[i].name; i++)
{
tflag[i] = 0;
if (o_options[i].letter)
{
ip = find_flag (o_options[i].letter);
if (ip && *ip)
{
vsize += strlen (o_options[i].name) + 1;
tflag[i] = 1;
}
}
else if (GET_BINARY_O_OPTION_VALUE (i, o_options[i].name))
{
vsize += strlen (o_options[i].name) + 1;
tflag[i] = 1;
}
}
value = (char *)xmalloc (vsize + 1);
for (i = vptr = 0; o_options[i].name; i++)
{
if (tflag[i])
{
strcpy (value + vptr, o_options[i].name);
vptr += strlen (o_options[i].name);
value[vptr++] = ':';
}
}
if (vptr)
vptr--; /* cut off trailing colon */
value[vptr] = '\0';
v = find_variable ("SHELLOPTS");
/* Turn off the read-only attribute so we can bind the new value, and
note whether or not the variable was exported. */
if (v)
{
VUNSETATTR (v, att_readonly);
exported = exported_p (v);
}
else
exported = 0;
v = bind_variable ("SHELLOPTS", value, 0);
/* Turn the read-only attribute back on, and turn off the export attribute
if it was set implicitly by mark_modified_vars and SHELLOPTS was not
exported before we bound the new value. */
VSETATTR (v, att_readonly);
if (mark_modified_vars && exported == 0 && exported_p (v))
VUNSETATTR (v, att_exported);
free (value);
}
void
parse_shellopts (value)
char *value;
{
char *vname;
int vptr;
vptr = 0;
while (vname = extract_colon_unit (value, &vptr))
{
set_minus_o_option (FLAG_ON, vname);
free (vname);
}
}
void
initialize_shell_options (no_shellopts)
int no_shellopts;
{
char *temp;
SHELL_VAR *var;
if (no_shellopts == 0)
{
var = find_variable ("SHELLOPTS");
/* set up any shell options we may have inherited. */
if (var && imported_p (var))
{
temp = (array_p (var) || assoc_p (var)) ? (char *)NULL : savestring (value_cell (var));
if (temp)
{
parse_shellopts (temp);
free (temp);
}
}
}
/* Set up the $SHELLOPTS variable. */
set_shellopts ();
}
/* Reset the values of the -o options that are not also shell flags. This is
called from execute_cmd.c:initialize_subshell() when setting up a subshell
to run an executable shell script without a leading `#!'. */
void
reset_shell_options ()
{
#if defined (HISTORY)
remember_on_history = enable_history_list = 1;
#endif
ignoreeof = 0;
}
/* Set some flags from the word values in the input list. If LIST is empty,
then print out the values of the variables instead. If LIST contains
non-flags, then set $1 - $9 to the successive words of LIST. */
int
set_builtin (list)
WORD_LIST *list;
{
int on_or_off, flag_name, force_assignment, opts_changed, rv, r;
register char *arg;
char s[3];
if (list == 0)
{
print_all_shell_variables ();
return (sh_chkwrite (EXECUTION_SUCCESS));
}
/* Check validity of flag arguments. */
rv = EXECUTION_SUCCESS;
reset_internal_getopt ();
while ((flag_name = internal_getopt (list, optflags)) != -1)
{
switch (flag_name)
{
case '?':
builtin_usage ();
return (list_optopt == '?' ? EXECUTION_SUCCESS : EX_USAGE);
default:
break;
}
}
/* Do the set command. While the list consists of words starting with
'-' or '+' treat them as flags, otherwise, start assigning them to
$1 ... $n. */
for (force_assignment = opts_changed = 0; list; )
{
arg = list->word->word;
/* If the argument is `--' or `-' then signal the end of the list
and remember the remaining arguments. */
if (arg[0] == '-' && (!arg[1] || (arg[1] == '-' && !arg[2])))
{
list = list->next;
/* `set --' unsets the positional parameters. */
if (arg[1] == '-')
force_assignment = 1;
/* Until told differently, the old shell behaviour of
`set - [arg ...]' being equivalent to `set +xv [arg ...]'
stands. Posix.2 says the behaviour is marked as obsolescent. */
else
{
change_flag ('x', '+');
change_flag ('v', '+');
opts_changed = 1;
}
break;
}
if ((on_or_off = *arg) && (on_or_off == '-' || on_or_off == '+'))
{
while (flag_name = *++arg)
{
if (flag_name == '?')
{
builtin_usage ();
return (EXECUTION_SUCCESS);
}
else if (flag_name == 'o') /* -+o option-name */
{
char *option_name;
WORD_LIST *opt;
opt = list->next;
if (opt == 0)
{
list_minus_o_opts (-1, (on_or_off == '+'));
rv = sh_chkwrite (rv);
continue;
}
option_name = opt->word->word;
if (option_name == 0 || *option_name == '\0' ||
*option_name == '-' || *option_name == '+')
{
list_minus_o_opts (-1, (on_or_off == '+'));
continue;
}
list = list->next; /* Skip over option name. */
opts_changed = 1;
if ((r = set_minus_o_option (on_or_off, option_name)) != EXECUTION_SUCCESS)
{
set_shellopts ();
return (r);
}
}
else if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
{
s[0] = on_or_off;
s[1] = flag_name;
s[2] = '\0';
sh_invalidopt (s);
builtin_usage ();
set_shellopts ();
return (EXECUTION_FAILURE);
}
opts_changed = 1;
}
}
else
{
break;
}
list = list->next;
}
/* Assigning $1 ... $n */
if (list || force_assignment)
remember_args (list, 1);
/* Set up new value of $SHELLOPTS */
if (opts_changed)
set_shellopts ();
return (rv);
}
$BUILTIN unset
$FUNCTION unset_builtin
$SHORT_DOC unset [-f] [-v] [name ...]
Unset values and attributes of shell variables and functions.
For each NAME, remove the corresponding variable or function.
Options:
-f treat each NAME as a shell function
-v treat each NAME as a shell variable
Without options, unset first tries to unset a variable, and if that fails,
tries to unset a function.
Some variables cannot be unset; also see `readonly'.
Exit Status:
Returns success unless an invalid option is given or a NAME is read-only.
$END
#define NEXT_VARIABLE() any_failed++; list = list->next; continue;
int
unset_builtin (list)
WORD_LIST *list;
{
int unset_function, unset_variable, unset_array, opt, any_failed;
char *name;
unset_function = unset_variable = unset_array = any_failed = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "fv")) != -1)
{
switch (opt)
{
case 'f':
unset_function = 1;
break;
case 'v':
unset_variable = 1;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (unset_function && unset_variable)
{
builtin_error (_("cannot simultaneously unset a function and a variable"));
return (EXECUTION_FAILURE);
}
while (list)
{
SHELL_VAR *var;
int tem;
#if defined (ARRAY_VARS)
char *t;
#endif
name = list->word->word;
#if defined (ARRAY_VARS)
unset_array = 0;
if (!unset_function && valid_array_reference (name))
{
t = strchr (name, '[');
*t++ = '\0';
unset_array++;
}
#endif
/* Get error checking out of the way first. The low-level functions
just perform the unset, relying on the caller to verify. */
/* Bash allows functions with names which are not valid identifiers
to be created when not in posix mode, so check only when in posix
mode when unsetting a function. */
if (((unset_function && posixly_correct) || !unset_function) && legal_identifier (name) == 0)
{
sh_invalidid (name);
NEXT_VARIABLE ();
}
/* Only search for functions here if -f supplied. */
var = unset_function ? find_function (name) : find_variable (name);
/* Some variables (but not functions yet) cannot be unset, period. */
if (var && unset_function == 0 && non_unsettable_p (var))
{
builtin_error (_("%s: cannot unset"), name);
NEXT_VARIABLE ();
}
/* Posix.2 says try variables first, then functions. If we would
find a function after unsuccessfully searching for a variable,
note that we're acting on a function now as if -f were
supplied. The readonly check below takes care of it. */
if (var == 0 && unset_variable == 0 && unset_function == 0)
{
if (var = find_function (name))
unset_function = 1;
}
/* Posix.2 says that unsetting readonly variables is an error. */
if (var && readonly_p (var))
{
builtin_error (_("%s: cannot unset: readonly %s"),
name, unset_function ? "function" : "variable");
NEXT_VARIABLE ();
}
/* Unless the -f option is supplied, the name refers to a variable. */
#if defined (ARRAY_VARS)
if (var && unset_array)
{
if (array_p (var) == 0 && assoc_p (var) == 0)
{
builtin_error (_("%s: not an array variable"), name);
NEXT_VARIABLE ();
}
else
{
tem = unbind_array_element (var, t);
if (tem == -1)
any_failed++;
}
}
else
#endif /* ARRAY_VARS */
tem = unset_function ? unbind_func (name) : unbind_variable (name);
/* This is what Posix.2 says: ``If neither -f nor -v
is specified, the name refers to a variable; if a variable by
that name does not exist, a function by that name, if any,
shall be unset.'' */
if (tem == -1 && unset_function == 0 && unset_variable == 0)
tem = unbind_func (name);
/* SUSv3, POSIX.1-2001 say: ``Unsetting a variable or function that
was not previously set shall not be considered an error.'' */
if (unset_function == 0)
stupidly_hack_special_variables (name);
list = list->next;
}
return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
}
-517
View File
@@ -1,517 +0,0 @@
This file is setattr.def, from which is created setattr.c.
It implements the builtins "export" and "readonly", in Bash.
Copyright (C) 1987-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
$PRODUCES setattr.c
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <stdio.h>
#include "../bashansi.h"
#include "../bashintl.h"
#include "../shell.h"
#include "common.h"
#include "bashgetopt.h"
extern int posixly_correct;
extern int array_needs_making;
extern char *this_command_name;
extern sh_builtin_func_t *this_shell_builtin;
#ifdef ARRAY_VARS
extern int declare_builtin __P((WORD_LIST *));
#endif
#define READONLY_OR_EXPORT \
(this_shell_builtin == readonly_builtin || this_shell_builtin == export_builtin)
$BUILTIN export
$FUNCTION export_builtin
$SHORT_DOC export [-fn] [name[=value] ...] or export -p
Set export attribute for shell variables.
Marks each NAME for automatic export to the environment of subsequently
executed commands. If VALUE is supplied, assign VALUE before exporting.
Options:
-f refer to shell functions
-n remove the export property from each NAME
-p display a list of all exported variables and functions
An argument of `--' disables further option processing.
Exit Status:
Returns success unless an invalid option is given or NAME is invalid.
$END
/* For each variable name in LIST, make that variable appear in the
environment passed to simple commands. If there is no LIST, then
print all such variables. An argument of `-n' says to remove the
exported attribute from variables named in LIST. An argument of
-f indicates that the names present in LIST refer to functions. */
int
export_builtin (list)
register WORD_LIST *list;
{
return (set_or_show_attributes (list, att_exported, 0));
}
$BUILTIN readonly
$FUNCTION readonly_builtin
$SHORT_DOC readonly [-aAf] [name[=value] ...] or readonly -p
Mark shell variables as unchangeable.
Mark each NAME as read-only; the values of these NAMEs may not be
changed by subsequent assignment. If VALUE is supplied, assign VALUE
before marking as read-only.
Options:
-a refer to indexed array variables
-A refer to associative array variables
-f refer to shell functions
-p display a list of all readonly variables and functions
An argument of `--' disables further option processing.
Exit Status:
Returns success unless an invalid option is given or NAME is invalid.
$END
/* For each variable name in LIST, make that variable readonly. Given an
empty LIST, print out all existing readonly variables. */
int
readonly_builtin (list)
register WORD_LIST *list;
{
return (set_or_show_attributes (list, att_readonly, 0));
}
#if defined (ARRAY_VARS)
# define ATTROPTS "aAfnp"
#else
# define ATTROPTS "fnp"
#endif
/* For each variable name in LIST, make that variable have the specified
ATTRIBUTE. An arg of `-n' says to remove the attribute from the the
remaining names in LIST (doesn't work for readonly). */
int
set_or_show_attributes (list, attribute, nodefs)
register WORD_LIST *list;
int attribute, nodefs;
{
register SHELL_VAR *var;
int assign, undo, any_failed, assign_error, opt;
int functions_only, arrays_only, assoc_only;
int aflags;
char *name;
#if defined (ARRAY_VARS)
WORD_LIST *nlist, *tlist;
WORD_DESC *w;
#endif
functions_only = arrays_only = assoc_only = 0;
undo = any_failed = assign_error = 0;
/* Read arguments from the front of the list. */
reset_internal_getopt ();
while ((opt = internal_getopt (list, ATTROPTS)) != -1)
{
switch (opt)
{
case 'n':
undo = 1;
break;
case 'f':
functions_only = 1;
break;
#if defined (ARRAY_VARS)
case 'a':
arrays_only = 1;
break;
case 'A':
assoc_only = 1;
break;
#endif
case 'p':
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
if (list)
{
if (attribute & att_exported)
array_needs_making = 1;
/* Cannot undo readonly status, silently disallowed. */
if (undo && (attribute & att_readonly))
attribute &= ~att_readonly;
while (list)
{
name = list->word->word;
if (functions_only) /* xxx -f name */
{
var = find_function (name);
if (var == 0)
{
builtin_error (_("%s: not a function"), name);
any_failed++;
}
else
SETVARATTR (var, attribute, undo);
list = list->next;
continue;
}
/* xxx [-np] name[=value] */
assign = assignment (name, 0);
aflags = 0;
if (assign)
{
name[assign] = '\0';
if (name[assign - 1] == '+')
{
aflags |= ASS_APPEND;
name[assign - 1] = '\0';
}
}
if (legal_identifier (name) == 0)
{
sh_invalidid (name);
if (assign)
assign_error++;
else
any_failed++;
list = list->next;
continue;
}
if (assign) /* xxx [-np] name=value */
{
name[assign] = '=';
if (aflags & ASS_APPEND)
name[assign - 1] = '+';
#if defined (ARRAY_VARS)
/* Let's try something here. Turn readonly -a xxx=yyy into
declare -ra xxx=yyy and see what that gets us. */
if (arrays_only || assoc_only)
{
tlist = list->next;
list->next = (WORD_LIST *)NULL;
w = arrays_only ? make_word ("-ra") : make_word ("-rA");
nlist = make_word_list (w, list);
opt = declare_builtin (nlist);
if (opt != EXECUTION_SUCCESS)
assign_error++;
list->next = tlist;
dispose_word (w);
free (nlist);
}
else
#endif
/* This word has already been expanded once with command
and parameter expansion. Call do_assignment_no_expand (),
which does not do command or parameter substitution. If
the assignment is not performed correctly, flag an error. */
if (do_assignment_no_expand (name) == 0)
assign_error++;
name[assign] = '\0';
if (aflags & ASS_APPEND)
name[assign - 1] = '\0';
}
set_var_attribute (name, attribute, undo);
list = list->next;
}
}
else
{
SHELL_VAR **variable_list;
register int i;
if ((attribute & att_function) || functions_only)
{
variable_list = all_shell_functions ();
if (attribute != att_function)
attribute &= ~att_function; /* so declare -xf works, for example */
}
else
variable_list = all_shell_variables ();
#if defined (ARRAY_VARS)
if (attribute & att_array)
{
arrays_only++;
if (attribute != att_array)
attribute &= ~att_array;
}
else if (attribute & att_assoc)
{
assoc_only++;
if (attribute != att_assoc)
attribute &= ~att_assoc;
}
#endif
if (variable_list)
{
for (i = 0; var = variable_list[i]; i++)
{
#if defined (ARRAY_VARS)
if (arrays_only && array_p (var) == 0)
continue;
else if (assoc_only && assoc_p (var) == 0)
continue;
#endif
if ((var->attributes & attribute))
{
show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
if (any_failed = sh_chkwrite (any_failed))
break;
}
}
free (variable_list);
}
}
return (assign_error ? EX_BADASSIGN
: ((any_failed == 0) ? EXECUTION_SUCCESS
: EXECUTION_FAILURE));
}
/* Show all variable variables (v == 1) or functions (v == 0) with
attributes. */
int
show_all_var_attributes (v, nodefs)
int v, nodefs;
{
SHELL_VAR **variable_list, *var;
int any_failed;
register int i;
variable_list = v ? all_shell_variables () : all_shell_functions ();
if (variable_list == 0)
return (EXECUTION_SUCCESS);
for (i = any_failed = 0; var = variable_list[i]; i++)
{
show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
if (any_failed = sh_chkwrite (any_failed))
break;
}
free (variable_list);
return (any_failed == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
/* Show the attributes for shell variable VAR. If NODEFS is non-zero,
don't show function definitions along with the name. If PATTR is
non-zero, it indicates we're being called from `export' or `readonly'.
In POSIX mode, this prints the name of the calling builtin (`export'
or `readonly') instead of `declare', and doesn't print function defs
when called by `export' or `readonly'. */
int
show_var_attributes (var, pattr, nodefs)
SHELL_VAR *var;
int pattr, nodefs;
{
char flags[16], *x;
int i;
i = 0;
/* pattr == 0 means we are called from `declare'. */
if (pattr == 0 || posixly_correct == 0)
{
#if defined (ARRAY_VARS)
if (array_p (var))
flags[i++] = 'a';
if (assoc_p (var))
flags[i++] = 'A';
#endif
if (function_p (var))
flags[i++] = 'f';
if (integer_p (var))
flags[i++] = 'i';
if (nameref_p (var))
flags[i++] = 'n';
if (readonly_p (var))
flags[i++] = 'r';
if (trace_p (var))
flags[i++] = 't';
if (exported_p (var))
flags[i++] = 'x';
if (capcase_p (var))
flags[i++] = 'c';
if (lowercase_p (var))
flags[i++] = 'l';
if (uppercase_p (var))
flags[i++] = 'u';
}
else
{
#if defined (ARRAY_VARS)
if (array_p (var))
flags[i++] = 'a';
if (assoc_p (var))
flags[i++] = 'A';
#endif
if (function_p (var))
flags[i++] = 'f';
}
flags[i] = '\0';
/* If we're printing functions with definitions, print the function def
first, then the attributes, instead of printing output that can't be
reused as input to recreate the current state. */
if (function_p (var) && nodefs == 0 && (pattr == 0 || posixly_correct == 0))
{
printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
nodefs++;
if (pattr == 0 && i == 1 && flags[0] == 'f')
return 0; /* don't print `declare -f name' */
}
if (pattr == 0 || posixly_correct == 0)
printf ("declare -%s ", i ? flags : "-");
else if (i)
printf ("%s -%s ", this_command_name, flags);
else
printf ("%s ", this_command_name);
#if defined (ARRAY_VARS)
if (array_p (var))
print_array_assignment (var, 1);
else if (assoc_p (var))
print_assoc_assignment (var, 1);
else
#endif
/* force `readonly' and `export' to not print out function definitions
when in POSIX mode. */
if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
printf ("%s\n", var->name);
else if (function_p (var))
printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
else if (invisible_p (var) || var_isset (var) == 0)
printf ("%s\n", var->name);
else
{
x = sh_double_quote (value_cell (var));
printf ("%s=%s\n", var->name, x);
free (x);
}
return (0);
}
int
show_name_attributes (name, nodefs)
char *name;
int nodefs;
{
SHELL_VAR *var;
var = find_variable_tempenv (name);
if (var && invisible_p (var) == 0)
{
show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
return (0);
}
else
return (1);
}
void
set_var_attribute (name, attribute, undo)
char *name;
int attribute, undo;
{
SHELL_VAR *var, *tv;
char *tvalue;
if (undo)
var = find_variable (name);
else
{
tv = find_tempenv_variable (name);
/* XXX -- need to handle case where tv is a temp variable in a
function-scope context, since function_env has been merged into
the local variables table. */
if (tv && tempvar_p (tv))
{
tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring ("");
var = bind_variable (tv->name, tvalue, 0);
var->attributes |= tv->attributes & ~att_tempvar;
VSETATTR (tv, att_propagate);
if (var->context != 0)
VSETATTR (var, att_propagate);
SETVARATTR (tv, attribute, undo); /* XXX */
stupidly_hack_special_variables (tv->name);
free (tvalue);
}
else
{
var = find_variable_notempenv (name);
if (var == 0)
{
var = bind_variable (name, (char *)NULL, 0);
VSETATTR (var, att_invisible);
}
else if (var->context != 0)
VSETATTR (var, att_propagate);
}
}
if (var)
SETVARATTR (var, attribute, undo);
if (var && (exported_p (var) || (attribute & att_exported)))
array_needs_making++; /* XXX */
}
-199
View File
@@ -1,199 +0,0 @@
This file is source.def, from which is created source.c.
It implements the builtins "." and "source" in Bash.
Copyright (C) 1987-2009 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
$PRODUCES source.c
$BUILTIN source
$FUNCTION source_builtin
$SHORT_DOC source filename [arguments]
Execute commands from a file in the current shell.
Read and execute commands from FILENAME in the current shell. The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.
Exit Status:
Returns the status of the last command executed in FILENAME; fails if
FILENAME cannot be read.
$END
$BUILTIN .
$DOCNAME dot
$FUNCTION source_builtin
$SHORT_DOC . filename [arguments]
Execute commands from a file in the current shell.
Read and execute commands from FILENAME in the current shell. The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.
Exit Status:
Returns the status of the last command executed in FILENAME; fails if
FILENAME cannot be read.
$END
#include <config.h>
#include "../bashtypes.h"
#include "posixstat.h"
#include "filecntl.h"
#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
# include <sys/file.h>
#endif
#include <errno.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "../bashansi.h"
#include "../bashintl.h"
#include "../shell.h"
#include "../flags.h"
#include "../findcmd.h"
#include "common.h"
#include "bashgetopt.h"
#include "../trap.h"
#if !defined (errno)
extern int errno;
#endif /* !errno */
extern int posixly_correct;
extern int last_command_exit_value;
extern int executing_command_builtin;
extern char *the_printed_command_except_trap;
static void maybe_pop_dollar_vars __P((void));
/* If non-zero, `.' uses $PATH to look up the script to be sourced. */
int source_uses_path = 1;
/* If non-zero, `.' looks in the current directory if the filename argument
is not found in the $PATH. */
int source_searches_cwd = 1;
/* If this . script is supplied arguments, we save the dollar vars and
replace them with the script arguments for the duration of the script's
execution. If the script does not change the dollar vars, we restore
what we saved. If the dollar vars are changed in the script, and we are
not executing a shell function, we leave the new values alone and free
the saved values. */
static void
maybe_pop_dollar_vars ()
{
if (variable_context == 0 && (dollar_vars_changed () & ARGS_SETBLTIN))
dispose_saved_dollar_vars ();
else
pop_dollar_vars ();
if (debugging_mode)
pop_args (); /* restore BASH_ARGC and BASH_ARGV */
set_dollar_vars_unchanged ();
}
/* Read and execute commands from the file passed as argument. Guess what.
This cannot be done in a subshell, since things like variable assignments
take place in there. So, I open the file, place it into a large string,
close the file, and then execute the string. */
int
source_builtin (list)
WORD_LIST *list;
{
int result;
char *filename, *debug_trap;
if (no_options (list))
return (EX_USAGE);
list = loptend;
if (list == 0)
{
builtin_error (_("filename argument required"));
builtin_usage ();
return (EX_USAGE);
}
#if defined (RESTRICTED_SHELL)
if (restricted && strchr (list->word->word, '/'))
{
sh_restricted (list->word->word);
return (EXECUTION_FAILURE);
}
#endif
filename = (char *)NULL;
/* XXX -- should this be absolute_pathname? */
if (posixly_correct && strchr (list->word->word, '/'))
filename = savestring (list->word->word);
else if (absolute_pathname (list->word->word))
filename = savestring (list->word->word);
else if (source_uses_path)
filename = find_path_file (list->word->word);
if (filename == 0)
{
if (source_searches_cwd == 0)
{
builtin_error (_("%s: file not found"), list->word->word);
if (posixly_correct && interactive_shell == 0 && executing_command_builtin == 0)
{
last_command_exit_value = 1;
jump_to_top_level (EXITPROG);
}
return (EXECUTION_FAILURE);
}
else
filename = savestring (list->word->word);
}
begin_unwind_frame ("source");
add_unwind_protect ((Function *)xfree, filename);
if (list->next)
{
push_dollar_vars ();
add_unwind_protect ((Function *)maybe_pop_dollar_vars, (char *)NULL);
remember_args (list->next, 1);
if (debugging_mode)
push_args (list->next); /* Update BASH_ARGV and BASH_ARGC */
}
set_dollar_vars_unchanged ();
/* Don't inherit the DEBUG trap unless function_trace_mode (overloaded)
is set. XXX - should sourced files inherit the RETURN trap? Functions
don't. */
debug_trap = TRAP_STRING (DEBUG_TRAP);
if (debug_trap && function_trace_mode == 0)
{
debug_trap = savestring (debug_trap);
add_unwind_protect (xfree, debug_trap);
add_unwind_protect (set_debug_trap, debug_trap);
restore_default_signal (DEBUG_TRAP);
}
itrace("source_builtin: the printed command = %s", the_printed_command_except_trap);
result = source_file (filename, (list && list->next));
run_unwind_frame ("source");
return (result);
}
-42
View File
@@ -1,42 +0,0 @@
# This file is a shell script that caches the results of configure
# tests for CYGWIN32 so they don't need to be done when cross-compiling.
# AC_FUNC_GETPGRP should also define GETPGRP_VOID
ac_cv_func_getpgrp_void=${ac_cv_func_getpgrp_void='yes'}
# AC_FUNC_SETVBUF_REVERSED should not define anything else
ac_cv_func_setvbuf_reversed=${ac_cv_func_setvbuf_reversed='no'}
# on CYGWIN32, system calls do not restart
ac_cv_sys_restartable_syscalls=${ac_cv_sys_restartable_syscalls='no'}
bash_cv_sys_restartable_syscalls=${bash_cv_sys_restartable_syscalls='no'}
# these may be necessary, but they are currently commented out
#ac_cv_c_bigendian=${ac_cv_c_bigendian='no'}
ac_cv_sizeof_char_p=${ac_cv_sizeof_char_p='4'}
ac_cv_sizeof_int=${ac_cv_sizeof_int='4'}
ac_cv_sizeof_long=${ac_cv_sizeof_long='4'}
ac_cv_sizeof_double=${ac_cv_sizeof_double='8'}
bash_cv_dup2_broken=${bash_cv_dup2_broken='no'}
bash_cv_pgrp_pipe=${bash_cv_pgrp_pipe='no'}
bash_cv_type_rlimit=${bash_cv_type_rlimit='long'}
bash_cv_decl_under_sys_siglist=${bash_cv_decl_under_sys_siglist='no'}
bash_cv_under_sys_siglist=${bash_cv_under_sys_siglist='no'}
bash_cv_sys_siglist=${bash_cv_sys_siglist='no'}
bash_cv_opendir_not_robust=${bash_cv_opendir_not_robust='no'}
bash_cv_getenv_redef=${bash_cv_getenv_redef='yes'}
bash_cv_printf_declared=${bash_cv_printf_declared='yes'}
bash_cv_ulimit_maxfds=${bash_cv_ulimit_maxfds='no'}
bash_cv_getcwd_calls_popen=${bash_cv_getcwd_calls_popen='no'}
bash_cv_must_reinstall_sighandlers=${bash_cv_must_reinstall_sighandlers='no'}
bash_cv_job_control_missing=${bash_cv_job_control_missing='present'}
bash_cv_sys_named_pipes=${bash_cv_sys_named_pipes='missing'}
bash_cv_func_sigsetjmp=${bash_cv_func_sigsetjmp='missing'}
bash_cv_mail_dir=${bash_cv_mail_dir='unknown'}
bash_cv_func_strcoll_broken=${bash_cv_func_strcoll_broken='no'}
bash_cv_type_int32_t=${bash_cv_type_int32_t='int'}
bash_cv_type_u_int32_t=${bash_cv_type_u_int32_t='int'}
ac_cv_type_bits64_t=${ac_cv_type_bits64_t='no'}
# end of cross-build/cygwin32.cache
-1745
View File
File diff suppressed because it is too large Load Diff
-10139
View File
File diff suppressed because it is too large Load Diff
-238
View File
@@ -1,238 +0,0 @@
#
# Simple makefile for the sample loadable builtins
#
# Copyright (C) 1996 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
# Include some boilerplate Gnu makefile definitions.
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
libdir = @libdir@
infodir = @infodir@
includedir = @includedir@
topdir = @top_srcdir@
BUILD_DIR = @BUILD_DIR@
srcdir = @srcdir@
VPATH = .:@srcdir@
@SET_MAKE@
CC = @CC@
RM = rm -f
SHELL = @MAKE_SHELL@
host_os = @host_os@
host_cpu = @host_cpu@
host_vendor = @host_vendor@
CFLAGS = @CFLAGS@
LOCAL_CFLAGS = @LOCAL_CFLAGS@
DEFS = @DEFS@
LOCAL_DEFS = @LOCAL_DEFS@
CPPFLAGS = @CPPFLAGS@
BASHINCDIR = ${topdir}/include
LIBBUILD = ${BUILD_DIR}/lib
INTL_LIBSRC = ${topdir}/lib/intl
INTL_BUILDDIR = ${LIBBUILD}/intl
INTL_INC = @INTL_INC@
LIBINTL_H = @LIBINTL_H@
CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CFLAGS)
#
# These values are generated for configure by ${topdir}/support/shobj-conf.
# If your system is not supported by that script, but includes facilities for
# dynamic loading of shared objects, please update the script and send the
# changes to bash-maintainers@gnu.org.
#
SHOBJ_CC = @SHOBJ_CC@
SHOBJ_CFLAGS = @SHOBJ_CFLAGS@
SHOBJ_LD = @SHOBJ_LD@
SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@
SHOBJ_XLDFLAGS = @SHOBJ_XLDFLAGS@
SHOBJ_LIBS = @SHOBJ_LIBS@
SHOBJ_STATUS = @SHOBJ_STATUS@
INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins \
-I$(BASHINCDIR) -I$(BUILD_DIR) -I$(LIBBUILD) \
-I$(BUILD_DIR)/builtins $(INTL_INC)
.c.o:
$(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CCFLAGS) $(INC) -c -o $@ $<
ALLPROG = print truefalse sleep pushd finfo logname basename dirname \
tty pathchk tee head mkdir rmdir printenv id whoami \
uname sync push ln unlink cut realpath getconf strftime
OTHERPROG = necho hello cat
all: $(SHOBJ_STATUS)
supported: $(ALLPROG)
others: $(OTHERPROG)
unsupported:
@echo "Your system (${host_os}) is not supported by the"
@echo "${topdir}/support/shobj-conf script."
@echo "If your operating system provides facilities for dynamic"
@echo "loading of shared objects using the dlopen(3) interface,"
@echo "please update the script and re-run configure.
@echo "Please send the changes you made to bash-maintainers@gnu.org"
@echo "for inclusion in future bash releases."
everything: supported others
print: print.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ print.o $(SHOBJ_LIBS)
necho: necho.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ necho.o $(SHOBJ_LIBS)
getconf: getconf.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ getconf.o $(SHOBJ_LIBS)
hello: hello.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ hello.o $(SHOBJ_LIBS)
truefalse: truefalse.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ truefalse.o $(SHOBJ_LIBS)
sleep: sleep.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sleep.o $(SHOBJ_LIBS)
finfo: finfo.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ finfo.o $(SHOBJ_LIBS)
cat: cat.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cat.o $(SHOBJ_LIBS)
logname: logname.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ logname.o $(SHOBJ_LIBS)
basename: basename.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ basename.o $(SHOBJ_LIBS)
dirname: dirname.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ dirname.o $(SHOBJ_LIBS)
tty: tty.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tty.o $(SHOBJ_LIBS)
pathchk: pathchk.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pathchk.o $(SHOBJ_LIBS)
tee: tee.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tee.o $(SHOBJ_LIBS)
mkdir: mkdir.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ mkdir.o $(SHOBJ_LIBS)
rmdir: rmdir.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ rmdir.o $(SHOBJ_LIBS)
head: head.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ head.o $(SHOBJ_LIBS)
printenv: printenv.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ printenv.o $(SHOBJ_LIBS)
id: id.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ id.o $(SHOBJ_LIBS)
whoami: whoami.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ whoami.o $(SHOBJ_LIBS)
uname: uname.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ uname.o $(SHOBJ_LIBS)
sync: sync.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sync.o $(SHOBJ_LIBS)
push: push.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ push.o $(SHOBJ_LIBS)
ln: ln.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ ln.o $(SHOBJ_LIBS)
unlink: unlink.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ unlink.o $(SHOBJ_LIBS)
cut: cut.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cut.o $(SHOBJ_LIBS)
realpath: realpath.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ realpath.o $(SHOBJ_LIBS)
strftime: strftime.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ strftime.o $(SHOBJ_LIBS)
# pushd is a special case. We use the same source that the builtin version
# uses, with special compilation options.
#
pushd.c: ${topdir}/builtins/pushd.def
$(RM) $@
${BUILD_DIR}/builtins/mkbuiltins -D ${topdir}/builtins ${topdir}/builtins/pushd.def
pushd.o: pushd.c
$(RM) $@
$(SHOBJ_CC) -DHAVE_CONFIG_H -DPUSHD_AND_POPD -DLOADABLE_BUILTIN $(SHOBJ_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(INC) -c -o $@ $<
pushd: pushd.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pushd.o $(SHOBJ_LIBS)
clean:
$(RM) $(ALLPROG) $(OTHERPROG) *.o
-( cd perl && ${MAKE} ${MFLAGS} $@ )
mostlyclean: clean
-( cd perl && ${MAKE} ${MFLAGS} $@ )
distclean maintainer-clean: clean
$(RM) Makefile pushd.c
-( cd perl && ${MAKE} ${MFLAGS} $@ )
print.o: print.c
truefalse.o: truefalse.c
sleep.o: sleep.c
finfo.o: finfo.c
logname.o: logname.c
basename.o: basename.c
dirname.o: dirname.c
tty.o: tty.c
pathchk.o: pathchk.c
tee.o: tee.c
head.o: head.c
rmdir.o: rmdir.c
necho.o: necho.c
getconf.o: getconf.c
hello.o: hello.c
cat.o: cat.c
printenv.o: printenv.c
id.o: id.c
whoami.o: whoami.c
uname.o: uname.c
sync.o: sync.c
push.o: push.c
mkdir.o: mkdir.c
realpath.o: realpath.c
strftime.o: strftime.c
-549
View File
@@ -1,549 +0,0 @@
#!/bin/bash
# ash -- "Adventure shell"
# last edit: 86/04/21 D A Gwyn
# SCCS ID: @(#)ash.sh 1.4
OPATH=$PATH
ask()
{
echo -n "$@" '[y/n] '
read ans
case "$ans" in
y*|Y*)
return 0
;;
*)
return 1
;;
esac
}
CAT=${PAGER:-more}
ash_inst()
{
cat <<- EOF
Instructions for the Adventure shell
Welcome to the Adventure shell! In this exploration of the UNIX file
system, I will act as your eyes and hands. As you move around, I will
describe whatever is visible and will carry out your commands. The
general form of a command is
Verb Object Extra_stuff.
Most commands pay no attention to the "Extra_stuff", and many do not
need an "Object". A typical command is
get all
which picks up all files in the current "room" (directory). You can
find out what you are carrying by typing the command
inventory
The command "help" results in a full description of all commands that I
understand. To quit the Adventure shell, type
quit
There are UNIX monsters lurking in the background. These are also
known as "commands with arguments".
Good luck!
EOF
}
ash_help()
{
echo "I understand the following commands (synonyms in parentheses):"
echo ""
echo "change OBJECT to NEW_NAME changes the name of the object"
echo "clone OBJECT as NEW_NAME duplicates the object"
echo "drop OBJECTS leaves the objects in the room"
echo "enter (go) PASSAGE takes the labeled passage"
echo "examine OBJECTS describes the objects in detail"
echo "feed OBJECT to MONSTER stuffs the object into a UNIX monster"
echo "get (take) OBJECTS picks up the specified objects"
echo "gripe (bug) report a problem with the Adventure shell"
echo "help prints this summary"
echo "inventory (i) tells what you are carrying"
echo "kill (destroy) OBJECTS destroys the objects"
echo "look (l) describes the room, including hidden objects"
echo "open (read) OBJECT shows the contents of an object"
echo "quit (exit) leaves the Adventure shell"
echo "resurrect OBJECTS attempts to restore dead objects"
echo "steal OBJECT from MONSTER obtains the object from a UNIX monster"
echo "throw OBJECT at daemon feeds the object to the printer daemon"
echo "up takes the overhead passage"
echo "wake MONSTER awakens a UNIX monster"
echo "where (w) tells you where you are"
echo "xyzzy moves you to your home"
}
MAINT=chet@ins.cwru.edu
PATH=/usr/ucb:/bin:/usr/bin:/usr/local/bin:.
export PATH
trap 'echo Ouch!' 2 3
#trap '' 18 # disable Berkeley job control
ash_lk(){ echo " $1 " | fgrep " $2 " >&- 2>&-; }
ash_pr(){ echo $* | tr ' ' '\012' | pr -5 -t -w75 -l$[ ( $# + 4 ) / 5 ]; }
ash_rm(){ echo " $1 " | sed -e "s/ $2 / /" -e 's/^ //' -e 's/ $//'; }
# enable history, bang history expansion, and emacs editing
set -o history
set -o histexpand
set -o emacs
cd
LIM=.limbo # $HOME/$LIM contains "destroyed" objects
mkdir $LIM >&- 2>&-
KNAP=.knapsack # $HOME/$KNAP contains objects being "carried"
if [ ! -d $KNAP ]
then mkdir $KNAP >&- 2>&-
if [ $? = 0 ]
then echo 'You found a discarded empty knapsack.'
else echo 'You have no knapsack to carry things in.'
exit 1
fi
else echo 'One moment while I peek in your old knapsack...'
fi
kn=`echo \`ls -a $KNAP | sed -e '/^\.$/d' -e '/^\.\.$/d'\``
if ask 'Welcome to the Adventure shell! Do you need instructions?'
then
ash_inst
echo -n 'Type a newline to continue: '
read
fi
wiz=false
cha=false
prev=$LIM
while :
do room=`pwd`
if [ $room != $prev ]
then if [ $room = $HOME ]
then echo 'You are in your own home.'
else echo "You have entered $room."
fi
exs=
obs=
hexs=
hobs=
f=false
for i in `ls -a`
do case $i in
.|..) ;;
.*) if [ -f $i ]
then hobs="$hobs $i"
elif [ -d $i ]
then hexs="$hexs $i"
else f=true
fi
;;
*) if [ -f $i ]
then obs="$obs $i"
elif [ -d $i ]
then exs="$exs $i"
else f=true
fi
;;
esac
done
if [ "$obs" ]
then echo 'This room contains:'
ash_pr $obs
else echo 'The room looks empty.'
fi
if [ "$exs" ]
then echo 'There are exits labeled:'
ash_pr $exs
echo 'as well as a passage overhead.'
else echo 'There is a passage overhead.'
fi
if sh -c $f
then echo 'There are shadowy figures in the corner.'
fi
prev=$room
fi
read -e -p '-advsh> ' verb obj x # prompt is '-advsh> '
if [ $? != 0 ]
then verb=quit # EOF
fi
case $verb in
change) if [ "$obj" ]
then if ash_lk "$obs $hobs" "$obj"
then set -- $x
case "$1" in
to) if [ "$2" ]
then if [ -f $2 ]
then echo "You must destroy $2 first."
set --
fi
if [ "$2" ]
then if mv $obj $2 >&- 2>&-
then echo "The $obj shimmers and turns into $2."
obs=`ash_rm "$2 $obs" "$obj"`
else echo "There is a cloud of smoke but the $obj is unchanged."
fi
fi
else echo 'To what?'
fi
;;
*) echo "Change $obj to what?"
;;
esac
else if ash_lk "$kn" "$obj"
then echo 'You must drop it first.'
else echo "I see no $obj here."
fi
fi
else echo 'Change what?'
fi
;;
clone) if [ "$obj" ]
then if ash_lk "$obs $hobs" "$obj"
then if [ ! -r $obj ]
then echo "The $obj does not wish to be cloned."
else set -- $x
case "$1" in
as) if [ "$2" ]
then if [ -f $2 ]
then echo "You must destroy $2 first."
else if cp $obj $2 >&- 2>&-
then echo "Poof! When the smoke clears, you see the new $2."
obs="$obs $2"
else echo 'You hear a dull thud but no clone appears.'
fi
fi
else echo 'As what?'
fi
;;
*) echo "Clone $obj as what?"
;;
esac
fi
else if ash_lk "$kn" "$obj"
then echo 'You must drop it first.'
else echo "I see no $obj here."
fi
fi
else echo 'Clone what?'
fi
;;
drop) if [ "$obj" ]
then for it in $obj $x
do if ash_lk "$kn" "$it"
then if [ -w $it ]
then echo "You must destroy $it first."
else if mv $HOME/$KNAP/$it $it >&- 2>&-
then echo "$it: dropped."
kn=`ash_rm "$kn" "$it"`
obs=`echo $it $obs`
else echo "The $it is caught in your knapsack."
fi
fi
else echo "You're not carrying the $it!"
fi
done
else echo 'Drop what?'
fi
;;
enter|go) if [ "$obj" ]
then if [ $obj != up ]
then if ash_lk "$exs $hexs" "$obj"
then if [ -x $obj ]
then if cd $obj
then echo 'You squeeze through the passage.'
else echo "You can't go that direction."
fi
else echo 'An invisible force blocks your way.'
fi
else echo 'I see no such passage.'
fi
else if cd ..
then echo 'You struggle upwards.'
else echo "You can't reach that high."
fi
fi
else echo 'Which passage?'
fi
;;
examine) if [ "$obj" ]
then if [ $obj = all ]
then $obj=`echo $obs $exs`
x=
fi
for it in $obj $x
do if ash_lk "$obs $hobs $exs $hexs" "$it"
then echo "Upon close inspection of the $it, you see:"
ls -ld $it 2>&-
if [ $? != 0 ]
then echo "-- when you look directly at the $it, it vanishes."
fi
else if ash_lk "$kn" "$it"
then echo 'You must drop it first.'
else echo "I see no $it here."
fi
fi
done
else echo 'Examine what?'
fi
;;
feed) if [ "$obj" ]
then if ash_lk "$obs $hobs" "$obj"
then set -- $x
case "$1" in
to) if [ "$2" ]
then shift
if PATH=$OPATH $* <$obj 2>&-
then echo "The $1 monster devours your $obj."
if rm -f $obj >&- 2>&-
then obs=`ash_rm "$obs" "$obj"`
else echo 'But he spits it back up.'
fi
else echo "The $1 monster holds his nose in disdain."
fi
else echo 'To what?'
fi
;;
*) echo "Feed $obj to what?"
;;
esac
else if ash_lk "$kn" "$obj"
then echo 'You must drop it first.'
else echo "I see no $obj here."
fi
fi
else echo 'Feed what?'
fi
;;
get|take) if [ "$obj" ]
then if [ $obj = all ]
then obj="$obs"
x=
fi
for it in $obj $x
do if ash_lk "$obs $hobs" "$it"
then if ash_lk "$kn" "$it"
then echo 'You already have one.'
else if mv $it $HOME/$KNAP/$it >&- 2>&-
then echo "$it: taken."
kn="$it $kn"
obs=`ash_rm "$obs" "$it"`
else echo "The $it is too heavy."
fi
fi
else echo "I see no $it here."
fi
done
else echo 'Get what?'
fi
;;
gripe|bug) echo 'Please describe the problem and your situation at the time it failed.\nEnd the bug report with a line containing just a Ctrl-D.'
cat | mail $MAINT -s 'ash bug'
echo 'Thank you!'
;;
help) ash_help
;;
inventory|i) if [ "$kn" ]
then echo 'Your knapsack contains:'
ash_pr $kn
else echo 'You are poverty-stricken.'
fi
;;
kill|destroy) if [ "$obj" ]
then if [ $obj = all ]
then x=
if ask "Do you really want to attempt to $verb them all?"
then obj=`echo $obs`
else echo 'Chicken!'
obj=
fi
fi
for it in $obj $x
do if ash_lk "$obs $hobs" "$it"
then if mv $it $HOME/$LIM <&- >&- 2>&-
then if [ $verb = kill ]
then echo "The $it cannot defend himself; he dies."
else echo "You have destroyed the $it; it vanishes."
fi
obs=`ash_rm "$obs" "$it"`
else if [ $verb = kill ]
then echo "Your feeble blows are no match for the $it."
else echo "The $it is indestructible."
fi
fi
else if ash_lk "$kn" "$it"
then echo "You must drop the $it first."
found=false
else echo "I see no $it here."
fi
fi
done
else echo 'Kill what?'
fi
;;
look|l) obs=`echo $obs $hobs`
hobs=
if [ "$obs" ]
then echo 'The room contains:'
ash_pr $obs
else echo 'The room is empty.'
fi
exs=`echo $exs $hexs`
hexs=
if [ "$exs" ]
then echo 'There are exits plainly labeled:'
ash_pr $exs
echo 'and a passage directly overhead.'
else echo 'The only exit is directly overhead.'
fi
;;
magic) if [ "$obj" = mode ]
then if sh -c $cha
then echo 'You had your chance and you blew it.'
else if ask 'Are you a wizard?'
then echo -n 'Prove it! Say the magic word: '
read obj
if [ "$obj" = armadillo ]
then echo 'Yes, master!!'
wiz=true
else echo "Homie says: I don't think so"
cha=true
fi
else echo "I didn't think so."
fi
fi
else echo 'Nice try.'
fi
;;
open|read) if [ "$obj" ]
then if ash_lk "$obs $hobs" "$obj"
then if [ -r $obj ]
then if [ -s $obj ]
then echo "Opening the $obj reveals:"
$CAT < $obj
if [ $? != 0 ]
then echo '-- oops, you lost the contents!'
fi
else echo "There is nothing inside the $obj."
fi
else echo "You do not have the proper tools to open the $obj."
fi
else if ash_lk "$kn" "$obj"
then echo 'You must drop it first.'
found=false
else echo "I see no $obj here."
fi
fi
else echo 'Open what?'
fi
;;
quit|exit) if ask 'Do you really want to quit now?'
then if [ "$kn" ]
then echo 'The contents of your knapsack will still be there next time.'
fi
rm -rf $HOME/$LIM
echo 'See you later!'
exit 0
fi
;;
resurrect) if [ "$obj" ]
then for it in $obj $x
do if ash_lk "$obs $hobs" "$it"
then echo "The $it is already alive and well."
else if mv $HOME/$LIM/$it $it <&- >&- 2>&-
then echo "The $it staggers to his feet."
obs=`echo $it $obs`
else echo "There are sparks but no $it appears."
fi
fi
done
else echo 'Resurrect what?'
fi
;;
steal) if [ "$obj" ]
then if ash_lk "$obs $hobs" "$obj"
then echo 'There is already one here.'
else set -- $x
case "$1" in
from) if [ "$2" ]
then shift
if PATH=$OPATH $* >$obj 2>&-
then echo "The $1 monster drops the $obj."
obs=`echo $obj $obs`
else echo "The $1 monster runs away as you approach."
rm -f $obj >&- 2>&-
fi
else echo 'From what?'
fi
;;
*) echo "Steal $obj from what?"
;;
esac
fi
else echo 'Steal what?'
fi
;;
throw) if [ "$obj" ]
then if ash_lk "$obs $hobs" "$obj"
then set -- $x
case "$1" in
at) case "$2" in
daemon) if sh -c "lpr -r $obj"
then echo "The daemon catches the $obj, turns it into paper,\nand leaves it in the basket."
obs=`ash_rm "$obs" "$obj"`
else echo "The daemon is nowhere to be found."
fi
;;
*) echo 'At what?'
;;
esac
;;
*) echo "Throw $obj at what?"
;;
esac
else if ash_lk "$kn" "$obj"
then echo 'It is in your knapsack.'
found=false
else echo "I see no $obj here."
fi
fi
else echo 'Throw what?'
fi
;;
u|up) if cd ..
then echo 'You pull yourself up a level.'
else echo "You can't reach that high."
fi
;;
wake) if [ "$obj" ]
then echo "You awaken the $obj monster:"
PATH=$OPATH $obj $x
echo 'The monster slithers back into the darkness.'
else echo 'Wake what?'
fi
;;
w|where) echo "You are in $room."
;;
xyzzy) if cd
then echo 'A strange feeling comes over you.'
else echo 'Your spell fizzles out.'
fi
;;
*) if [ "$verb" ]
then if sh -c $wiz
then PATH=$OPATH $verb $obj $x
else echo "I don't know how to \"$verb\"."
echo 'Type "help" for assistance.'
fi
else echo 'Say something!'
fi
;;
esac
done
-5338
View File
File diff suppressed because it is too large Load Diff
-502
View File
@@ -1,502 +0,0 @@
/* externs.h -- extern function declarations which do not appear in their
own header file. */
/* Copyright (C) 1993-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
/* Make sure that this is included *after* config.h! */
#if !defined (_EXTERNS_H_)
# define _EXTERNS_H_
#include "stdc.h"
/* Functions from expr.c. */
extern intmax_t evalexp __P((char *, int *));
/* Functions from print_cmd.c. */
#define FUNC_MULTILINE 0x01
#define FUNC_EXTERNAL 0x02
extern char *make_command_string __P((COMMAND *));
extern char *named_function_string __P((char *, COMMAND *, int));
extern void print_command __P((COMMAND *));
extern void print_simple_command __P((SIMPLE_COM *));
extern void print_word_list __P((WORD_LIST *, char *));
/* debugger support */
extern void print_for_command_head __P((FOR_COM *));
#if defined (SELECT_COMMAND)
extern void print_select_command_head __P((SELECT_COM *));
#endif
extern void print_case_command_head __P((CASE_COM *));
#if defined (DPAREN_ARITHMETIC)
extern void print_arith_command __P((WORD_LIST *));
#endif
#if defined (COND_COMMAND)
extern void print_cond_command __P((COND_COM *));
#endif
/* set -x support */
extern void xtrace_init __P((void));
#ifdef NEED_XTRACE_SET_DECL
extern void xtrace_set __P((int, FILE *));
#endif
extern void xtrace_fdchk __P((int));
extern void xtrace_reset __P((void));
extern char *indirection_level_string __P((void));
extern void xtrace_print_assignment __P((char *, char *, int, int));
extern void xtrace_print_word_list __P((WORD_LIST *, int));
extern void xtrace_print_for_command_head __P((FOR_COM *));
#if defined (SELECT_COMMAND)
extern void xtrace_print_select_command_head __P((SELECT_COM *));
#endif
extern void xtrace_print_case_command_head __P((CASE_COM *));
#if defined (DPAREN_ARITHMETIC)
extern void xtrace_print_arith_cmd __P((WORD_LIST *));
#endif
#if defined (COND_COMMAND)
extern void xtrace_print_cond_term __P((int, int, WORD_DESC *, char *, char *));
#endif
/* Functions from shell.c. */
extern void exit_shell __P((int)) __attribute__((__noreturn__));
extern void sh_exit __P((int)) __attribute__((__noreturn__));
extern void disable_priv_mode __P((void));
extern void unbind_args __P((void));
#if defined (RESTRICTED_SHELL)
extern int shell_is_restricted __P((char *));
extern int maybe_make_restricted __P((char *));
#endif
extern void unset_bash_input __P((int));
extern void get_current_user_info __P((void));
/* Functions from eval.c. */
extern int reader_loop __P((void));
extern int parse_command __P((void));
extern int read_command __P((void));
/* Functions from braces.c. */
#if defined (BRACE_EXPANSION)
extern char **brace_expand __P((char *));
#endif
/* Miscellaneous functions from parse.y */
extern int yyparse __P((void));
extern int return_EOF __P((void));
extern char *xparse_dolparen __P((char *, char *, int *, int));
extern void reset_parser __P((void));
extern WORD_LIST *parse_string_to_word_list __P((char *, int, const char *));
extern int parser_in_command_position __P((void));
extern void free_pushed_string_input __P((void));
extern char *decode_prompt_string __P((char *));
extern int get_current_prompt_level __P((void));
extern void set_current_prompt_level __P((int));
#if defined (HISTORY)
extern char *history_delimiting_chars __P((const char *));
#endif
/* Declarations for functions defined in locale.c */
extern void set_default_locale __P((void));
extern void set_default_locale_vars __P((void));
extern int set_locale_var __P((char *, char *));
extern int set_lang __P((char *, char *));
extern void set_default_lang __P((void));
extern char *get_locale_var __P((char *));
extern char *localetrans __P((char *, int, int *));
extern char *mk_msgstr __P((char *, int *));
extern char *localeexpand __P((char *, int, int, int, int *));
/* Declarations for functions defined in list.c. */
extern void list_walk __P((GENERIC_LIST *, sh_glist_func_t *));
extern void wlist_walk __P((WORD_LIST *, sh_icpfunc_t *));
extern GENERIC_LIST *list_reverse ();
extern int list_length ();
extern GENERIC_LIST *list_append ();
extern GENERIC_LIST *list_remove ();
/* Declarations for functions defined in stringlib.c */
extern int find_string_in_alist __P((char *, STRING_INT_ALIST *, int));
extern char *find_token_in_alist __P((int, STRING_INT_ALIST *, int));
extern int find_index_in_alist __P((char *, STRING_INT_ALIST *, int));
extern char *substring __P((const char *, int, int));
extern char *strsub __P((char *, char *, char *, int));
extern char *strcreplace __P((char *, int, char *, int));
extern void strip_leading __P((char *));
extern void strip_trailing __P((char *, int, int));
extern void xbcopy __P((char *, char *, int));
/* Functions from version.c. */
extern char *shell_version_string __P((void));
extern void show_shell_version __P((int));
/* Functions from the bash library, lib/sh/libsh.a. These should really
go into a separate include file. */
/* declarations for functions defined in lib/sh/casemod.c */
extern char *sh_modcase __P((const char *, char *, int));
/* Defines for flags argument to sh_modcase. These need to agree with what's
in lib/sh/casemode.c */
#define CASE_LOWER 0x0001
#define CASE_UPPER 0x0002
#define CASE_CAPITALIZE 0x0004
#define CASE_UNCAP 0x0008
#define CASE_TOGGLE 0x0010
#define CASE_TOGGLEALL 0x0020
#define CASE_UPFIRST 0x0040
#define CASE_LOWFIRST 0x0080
#define CASE_USEWORDS 0x1000
/* declarations for functions defined in lib/sh/clktck.c */
extern long get_clk_tck __P((void));
/* declarations for functions defined in lib/sh/clock.c */
extern void clock_t_to_secs ();
extern void print_clock_t ();
/* Declarations for functions defined in lib/sh/dprintf.c */
#if !defined (HAVE_DPRINTF)
extern void dprintf __P((int, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
#endif
/* Declarations for functions defined in lib/sh/fmtulong.c */
#define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */
#define FL_ADDBASE 0x02 /* add base# prefix to converted value */
#define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */
#define FL_UNSIGNED 0x08 /* don't add any sign */
extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
/* Declarations for functions defined in lib/sh/fmtulong.c */
#if defined (HAVE_LONG_LONG)
extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
#endif
/* Declarations for functions defined in lib/sh/fmtumax.c */
extern char *fmtumax __P((uintmax_t, int, char *, size_t, int));
/* Declarations for functions defined in lib/sh/fnxform.c */
extern char *fnx_fromfs __P((char *, size_t));
extern char *fnx_tofs __P((char *, size_t));
/* Declarations for functions defined in lib/sh/fpurge.c */
#if defined NEED_FPURGE_DECL
#if !HAVE_DECL_FPURGE
#if HAVE_FPURGE
# define fpurge _bash_fpurge
#endif
extern int fpurge __P((FILE *stream));
#endif /* HAVE_DECL_FPURGE */
#endif /* NEED_FPURGE_DECL */
/* Declarations for functions defined in lib/sh/getcwd.c */
#if !defined (HAVE_GETCWD)
extern char *getcwd __P((char *, size_t));
#endif
/* Declarations for functions defined in lib/sh/input_avail.c */
extern int input_avail __P((int));
/* Declarations for functions defined in lib/sh/itos.c */
extern char *inttostr __P((intmax_t, char *, size_t));
extern char *itos __P((intmax_t));
extern char *uinttostr __P((uintmax_t, char *, size_t));
extern char *uitos __P((uintmax_t));
/* declarations for functions defined in lib/sh/makepath.c */
#define MP_DOTILDE 0x01
#define MP_DOCWD 0x02
#define MP_RMDOT 0x04
#define MP_IGNDOT 0x08
extern char *sh_makepath __P((const char *, const char *, int));
/* declarations for functions defined in lib/sh/mbscasecmp.c */
#if !defined (HAVE_MBSCASECMP)
extern char *mbscasecmp __P((const char *, const char *));
#endif
/* declarations for functions defined in lib/sh/mbschr.c */
#if !defined (HAVE_MBSCHR)
extern char *mbschr __P((const char *, int));
#endif
/* declarations for functions defined in lib/sh/mbscmp.c */
#if !defined (HAVE_MBSCMP)
extern char *mbscmp __P((const char *, const char *));
#endif
/* declarations for functions defined in lib/sh/netconn.c */
extern int isnetconn __P((int));
/* declarations for functions defined in lib/sh/netopen.c */
extern int netopen __P((char *));
/* Declarations for functions defined in lib/sh/oslib.c */
#if !defined (HAVE_DUP2) || defined (DUP2_BROKEN)
extern int dup2 __P((int, int));
#endif
#if !defined (HAVE_GETDTABLESIZE)
extern int getdtablesize __P((void));
#endif /* !HAVE_GETDTABLESIZE */
#if !defined (HAVE_GETHOSTNAME)
extern int gethostname __P((char *, int));
#endif /* !HAVE_GETHOSTNAME */
extern int getmaxgroups __P((void));
extern long getmaxchild __P((void));
/* declarations for functions defined in lib/sh/pathcanon.c */
#define PATH_CHECKDOTDOT 0x0001
#define PATH_CHECKEXISTS 0x0002
#define PATH_HARDPATH 0x0004
#define PATH_NOALLOC 0x0008
extern char *sh_canonpath __P((char *, int));
/* declarations for functions defined in lib/sh/pathphys.c */
extern char *sh_physpath __P((char *, int));
extern char *sh_realpath __P((const char *, char *));
/* declarations for functions defined in lib/sh/setlinebuf.c */
#ifdef NEED_SH_SETLINEBUF_DECL
extern int sh_setlinebuf __P((FILE *));
#endif
/* declarations for functions defined in lib/sh/shaccess.c */
extern int sh_eaccess __P((char *, int));
/* declarations for functions defined in lib/sh/shmatch.c */
extern int sh_regmatch __P((const char *, const char *, int));
/* defines for flags argument to sh_regmatch. */
#define SHMAT_SUBEXP 0x001 /* save subexpressions in SH_REMATCH */
#define SHMAT_PWARN 0x002 /* print a warning message on invalid regexp */
/* declarations for functions defined in lib/sh/shmbchar.c */
extern size_t mbstrlen __P((const char *));
extern char *mbsmbchar __P((const char *));
extern int sh_mbsnlen __P((const char *, size_t, int));
/* declarations for functions defined in lib/sh/shquote.c */
extern char *sh_single_quote __P((const char *));
extern char *sh_double_quote __P((const char *));
extern char *sh_mkdoublequoted __P((const char *, int, int));
extern char *sh_un_double_quote __P((char *));
extern char *sh_backslash_quote __P((char *, const char *));
extern char *sh_backslash_quote_for_double_quotes __P((char *));
extern int sh_contains_shell_metas __P((char *));
/* declarations for functions defined in lib/sh/spell.c */
extern int spname __P((char *, char *));
extern char *dirspell __P((char *));
/* declarations for functions defined in lib/sh/strcasecmp.c */
#if !defined (HAVE_STRCASECMP)
extern int strncasecmp __P((const char *, const char *, int));
extern int strcasecmp __P((const char *, const char *));
#endif /* HAVE_STRCASECMP */
/* declarations for functions defined in lib/sh/strcasestr.c */
#if ! HAVE_STRCASESTR
extern char *strcasestr __P((const char *, const char *));
#endif
/* declarations for functions defined in lib/sh/strchrnul.c */
#if ! HAVE_STRCHRNUL
extern char *strchrnul __P((const char *, int));
#endif
/* declarations for functions defined in lib/sh/strerror.c */
#if !defined (HAVE_STRERROR) && !defined (strerror)
extern char *strerror __P((int));
#endif
/* declarations for functions defined in lib/sh/strftime.c */
#if !defined (HAVE_STRFTIME) && defined (NEED_STRFTIME_DECL)
extern size_t strftime __P((char *, size_t, const char *, const struct tm *));
#endif
/* declarations for functions and structures defined in lib/sh/stringlist.c */
/* This is a general-purpose argv-style array struct. */
typedef struct _list_of_strings {
char **list;
int list_size;
int list_len;
} STRINGLIST;
typedef int sh_strlist_map_func_t __P((char *));
extern STRINGLIST *strlist_create __P((int));
extern STRINGLIST *strlist_resize __P((STRINGLIST *, int));
extern void strlist_flush __P((STRINGLIST *));
extern void strlist_dispose __P((STRINGLIST *));
extern int strlist_remove __P((STRINGLIST *, char *));
extern STRINGLIST *strlist_copy __P((STRINGLIST *));
extern STRINGLIST *strlist_merge __P((STRINGLIST *, STRINGLIST *));
extern STRINGLIST *strlist_append __P((STRINGLIST *, STRINGLIST *));
extern STRINGLIST *strlist_prefix_suffix __P((STRINGLIST *, char *, char *));
extern void strlist_print __P((STRINGLIST *, char *));
extern void strlist_walk __P((STRINGLIST *, sh_strlist_map_func_t *));
extern void strlist_sort __P((STRINGLIST *));
/* declarations for functions defined in lib/sh/stringvec.c */
extern char **strvec_create __P((int));
extern char **strvec_resize __P((char **, int));
extern void strvec_flush __P((char **));
extern void strvec_dispose __P((char **));
extern int strvec_remove __P((char **, char *));
extern int strvec_len __P((char **));
extern int strvec_search __P((char **, char *));
extern char **strvec_copy __P((char **));
extern int strvec_strcmp __P((char **, char **));
extern void strvec_sort __P((char **));
extern char **strvec_from_word_list __P((WORD_LIST *, int, int, int *));
extern WORD_LIST *strvec_to_word_list __P((char **, int, int));
/* declarations for functions defined in lib/sh/strnlen.c */
#if !defined (HAVE_STRNLEN)
extern size_t strnlen __P((const char *, size_t));
#endif
/* declarations for functions defined in lib/sh/strpbrk.c */
#if !defined (HAVE_STRPBRK)
extern char *strpbrk __P((const char *, const char *));
#endif
/* declarations for functions defined in lib/sh/strtod.c */
#if !defined (HAVE_STRTOD)
extern double strtod __P((const char *, char **));
#endif
/* declarations for functions defined in lib/sh/strtol.c */
#if !HAVE_DECL_STRTOL
extern long strtol __P((const char *, char **, int));
#endif
/* declarations for functions defined in lib/sh/strtoll.c */
#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOLL
extern long long strtoll __P((const char *, char **, int));
#endif
/* declarations for functions defined in lib/sh/strtoul.c */
#if !HAVE_DECL_STRTOUL
extern unsigned long strtoul __P((const char *, char **, int));
#endif
/* declarations for functions defined in lib/sh/strtoull.c */
#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOULL
extern unsigned long long strtoull __P((const char *, char **, int));
#endif
/* declarations for functions defined in lib/sh/strimax.c */
#if !HAVE_DECL_STRTOIMAX
extern intmax_t strtoimax __P((const char *, char **, int));
#endif
/* declarations for functions defined in lib/sh/strumax.c */
#if !HAVE_DECL_STRTOUMAX
extern uintmax_t strtoumax __P((const char *, char **, int));
#endif
/* declarations for functions defined in lib/sh/strtrans.c */
extern char *ansicstr __P((char *, int, int, int *, int *));
extern char *ansic_quote __P((char *, int, int *));
extern int ansic_shouldquote __P((const char *));
extern char *ansiexpand __P((char *, int, int, int *));
/* declarations for functions defined in lib/sh/timeval.c. No prototypes
so we don't have to count on having a definition of struct timeval in
scope when this file is included. */
extern void timeval_to_secs ();
extern void print_timeval ();
/* declarations for functions defined in lib/sh/tmpfile.c */
#define MT_USETMPDIR 0x0001
#define MT_READWRITE 0x0002
#define MT_USERANDOM 0x0004
extern char *sh_mktmpname __P((char *, int));
extern int sh_mktmpfd __P((char *, int, char **));
/* extern FILE *sh_mktmpfp __P((char *, int, char **)); */
/* declarations for functions defined in lib/sh/uconvert.c */
extern int uconvert __P((char *, long *, long *));
/* declarations for functions defined in lib/sh/ufuncs.c */
extern unsigned int falarm __P((unsigned int, unsigned int));
extern unsigned int fsleep __P((unsigned int, unsigned int));
/* declarations for functions defined in lib/sh/unicode.c */
extern int u32cconv __P((unsigned long, char *));
extern void u32reset __P((void));
/* declarations for functions defined in lib/sh/winsize.c */
extern void get_new_window_size __P((int, int *, int *));
/* declarations for functions defined in lib/sh/zcatfd.c */
extern int zcatfd __P((int, int, char *));
/* declarations for functions defined in lib/sh/zgetline.c */
extern ssize_t zgetline __P((int, char **, size_t *, int));
/* declarations for functions defined in lib/sh/zmapfd.c */
extern int zmapfd __P((int, char **, char *));
/* declarations for functions defined in lib/sh/zread.c */
extern ssize_t zread __P((int, char *, size_t));
extern ssize_t zreadretry __P((int, char *, size_t));
extern ssize_t zreadintr __P((int, char *, size_t));
extern ssize_t zreadc __P((int, char *));
extern ssize_t zreadcintr __P((int, char *));
extern void zreset __P((void));
extern void zsyncfd __P((int));
/* declarations for functions defined in lib/sh/zwrite.c */
extern int zwrite __P((int, char *, size_t));
/* declarations for functions defined in lib/glob/gmisc.c */
extern int match_pattern_char __P((char *, char *));
extern int umatchlen __P((char *, size_t));
#if defined (HANDLE_MULTIBYTE)
extern int match_pattern_wchar __P((wchar_t *, wchar_t *));
extern int wmatchlen __P((wchar_t *, size_t));
#endif
#endif /* _EXTERNS_H_ */
-1244
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-76
View File
@@ -1,76 +0,0 @@
# This makefile for Readline library documentation is in -*- text -*- mode.
# Emacs likes it that way.
RM = rm -f
MAKEINFO = makeinfo
TEXI2DVI = texi2dvi
TEXI2HTML = texi2html
QUIETPS = #set this to -q to shut up dvips
DVIPS = dvips -D 300 $(QUIETPS) -o $@ # tricky
INSTALL_DATA = cp
infodir = /usr/local/info
RLSRC = rlman.texinfo rluser.texinfo rltech.texinfo
HISTSRC = hist.texinfo hsuser.texinfo hstech.texinfo
DVIOBJ = readline.dvi history.dvi
INFOOBJ = readline.info history.info
PSOBJ = readline.ps history.ps
HTMLOBJ = readline.html history.html
all: info dvi html ps
nodvi: info html
readline.dvi: $(RLSRC)
$(TEXI2DVI) rlman.texinfo
mv rlman.dvi readline.dvi
readline.info: $(RLSRC)
$(MAKEINFO) --no-split -o $@ rlman.texinfo
history.dvi: ${HISTSRC}
$(TEXI2DVI) hist.texinfo
mv hist.dvi history.dvi
history.info: ${HISTSRC}
$(MAKEINFO) --no-split -o $@ hist.texinfo
readline.ps: readline.dvi
$(RM) $@
$(DVIPS) readline.dvi
history.ps: history.dvi
$(RM) $@
$(DVIPS) history.dvi
readline.html: ${RLSRC}
$(TEXI2HTML) rlman.texinfo
sed -e 's:rlman.html:readline.html:' -e 's:rlman_toc.html:readline_toc.html:' rlman.html > readline.html
sed -e 's:rlman.html:readline.html:' -e 's:rlman_toc.html:readline_toc.html:' rlman_toc.html > readline_toc.html
$(RM) rlman.html rlman_toc.html
history.html: ${HISTSRC}
$(TEXI2HTML) hist.texinfo
sed -e 's:hist.html:history.html:' -e 's:hist_toc.html:history_toc.html:' hist.html > history.html
sed -e 's:hist.html:history.html:' -e 's:hist_toc.html:history_toc.html:' hist_toc.html > history_toc.html
$(RM) hist.html hist_toc.html
info: $(INFOOBJ)
dvi: $(DVIOBJ)
ps: $(PSOBJ)
html: $(HTMLOBJ)
clean:
$(RM) *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.cps *.pgs \
*.fns *.kys *.tps *.vrs *.o core
distclean: clean
mostlyclean: clean
maintainer-clean: clean
$(RM) *.dvi *.info *.info-* *.ps *.html
install: info
${INSTALL_DATA} readline.info $(infodir)/readline.info
${INSTALL_DATA} history.info $(infodir)/history.info
-378
View File
@@ -1,378 +0,0 @@
/* mbutil.c -- readline multibyte character utility functions */
/* Copyright (C) 2001-2009 Free Software Foundation, Inc.
This file is part of the GNU Readline Library (Readline), a library
for reading lines of text with interactive input and history editing.
Readline is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Readline is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Readline. If not, see <http://www.gnu.org/licenses/>.
*/
#define READLINE_LIBRARY
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#include <sys/types.h>
#include <fcntl.h>
#include "posixjmp.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h> /* for _POSIX_VERSION */
#endif /* HAVE_UNISTD_H */
#if defined (HAVE_STDLIB_H)
# include <stdlib.h>
#else
# include "ansi_stdlib.h"
#endif /* HAVE_STDLIB_H */
#include <stdio.h>
#include <ctype.h>
/* System-specific feature definitions and include files. */
#include "rldefs.h"
#include "rlmbutil.h"
#if defined (TIOCSTAT_IN_SYS_IOCTL)
# include <sys/ioctl.h>
#endif /* TIOCSTAT_IN_SYS_IOCTL */
/* Some standard library routines. */
#include "readline.h"
#include "rlprivate.h"
#include "xmalloc.h"
/* Declared here so it can be shared between the readline and history
libraries. */
#if defined (HANDLE_MULTIBYTE)
int rl_byte_oriented = 0;
#else
int rl_byte_oriented = 1;
#endif
/* Ditto */
int _rl_utf8locale = 0;
/* **************************************************************** */
/* */
/* Multibyte Character Utility Functions */
/* */
/* **************************************************************** */
#if defined(HANDLE_MULTIBYTE)
static int
_rl_find_next_mbchar_internal (string, seed, count, find_non_zero)
char *string;
int seed, count, find_non_zero;
{
size_t tmp, len;
mbstate_t ps;
int point;
wchar_t wc;
tmp = 0;
memset(&ps, 0, sizeof (mbstate_t));
if (seed < 0)
seed = 0;
if (count <= 0)
return seed;
point = seed + _rl_adjust_point (string, seed, &ps);
/* if this is true, means that seed was not pointing to a byte indicating
the beginning of a multibyte character. Correct the point and consume
one char. */
if (seed < point)
count--;
while (count > 0)
{
len = strlen (string + point);
if (len == 0)
break;
tmp = mbrtowc (&wc, string+point, len, &ps);
if (MB_INVALIDCH ((size_t)tmp))
{
/* invalid bytes. assume a byte represents a character */
point++;
count--;
/* reset states. */
memset(&ps, 0, sizeof(mbstate_t));
}
else if (MB_NULLWCH (tmp))
break; /* found wide '\0' */
else
{
/* valid bytes */
point += tmp;
if (find_non_zero)
{
if (WCWIDTH (wc) == 0)
continue;
else
count--;
}
else
count--;
}
}
if (find_non_zero)
{
tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
while (MB_NULLWCH (tmp) == 0 && MB_INVALIDCH (tmp) == 0 && WCWIDTH (wc) == 0)
{
point += tmp;
tmp = mbrtowc (&wc, string + point, strlen (string + point), &ps);
}
}
return point;
}
static int
_rl_find_prev_mbchar_internal (string, seed, find_non_zero)
char *string;
int seed, find_non_zero;
{
mbstate_t ps;
int prev, non_zero_prev, point, length;
size_t tmp;
wchar_t wc;
memset(&ps, 0, sizeof(mbstate_t));
length = strlen(string);
if (seed < 0)
return 0;
else if (length < seed)
return length;
prev = non_zero_prev = point = 0;
while (point < seed)
{
tmp = mbrtowc (&wc, string + point, length - point, &ps);
if (MB_INVALIDCH ((size_t)tmp))
{
/* in this case, bytes are invalid or shorted to compose
multibyte char, so assume that the first byte represents
a single character anyway. */
tmp = 1;
/* clear the state of the byte sequence, because
in this case effect of mbstate is undefined */
memset(&ps, 0, sizeof (mbstate_t));
/* Since we're assuming that this byte represents a single
non-zero-width character, don't forget about it. */
prev = point;
}
else if (MB_NULLWCH (tmp))
break; /* Found '\0' char. Can this happen? */
else
{
if (find_non_zero)
{
if (WCWIDTH (wc) != 0)
prev = point;
}
else
prev = point;
}
point += tmp;
}
return prev;
}
/* return the number of bytes parsed from the multibyte sequence starting
at src, if a non-L'\0' wide character was recognized. It returns 0,
if a L'\0' wide character was recognized. It returns (size_t)(-1),
if an invalid multibyte sequence was encountered. It returns (size_t)(-2)
if it couldn't parse a complete multibyte character. */
int
_rl_get_char_len (src, ps)
char *src;
mbstate_t *ps;
{
size_t tmp;
tmp = mbrlen((const char *)src, (size_t)strlen (src), ps);
if (tmp == (size_t)(-2))
{
/* shorted to compose multibyte char */
if (ps)
memset (ps, 0, sizeof(mbstate_t));
return -2;
}
else if (tmp == (size_t)(-1))
{
/* invalid to compose multibyte char */
/* initialize the conversion state */
if (ps)
memset (ps, 0, sizeof(mbstate_t));
return -1;
}
else if (tmp == (size_t)0)
return 0;
else
return (int)tmp;
}
/* compare the specified two characters. If the characters matched,
return 1. Otherwise return 0. */
int
_rl_compare_chars (buf1, pos1, ps1, buf2, pos2, ps2)
char *buf1;
int pos1;
mbstate_t *ps1;
char *buf2;
int pos2;
mbstate_t *ps2;
{
int i, w1, w2;
if ((w1 = _rl_get_char_len (&buf1[pos1], ps1)) <= 0 ||
(w2 = _rl_get_char_len (&buf2[pos2], ps2)) <= 0 ||
(w1 != w2) ||
(buf1[pos1] != buf2[pos2]))
return 0;
for (i = 1; i < w1; i++)
if (buf1[pos1+i] != buf2[pos2+i])
return 0;
return 1;
}
/* adjust pointed byte and find mbstate of the point of string.
adjusted point will be point <= adjusted_point, and returns
differences of the byte(adjusted_point - point).
if point is invalied (point < 0 || more than string length),
it returns -1 */
int
_rl_adjust_point(string, point, ps)
char *string;
int point;
mbstate_t *ps;
{
size_t tmp = 0;
int length;
int pos = 0;
length = strlen(string);
if (point < 0)
return -1;
if (length < point)
return -1;
while (pos < point)
{
tmp = mbrlen (string + pos, length - pos, ps);
if (MB_INVALIDCH ((size_t)tmp))
{
/* in this case, bytes are invalid or shorted to compose
multibyte char, so assume that the first byte represents
a single character anyway. */
pos++;
/* clear the state of the byte sequence, because
in this case effect of mbstate is undefined */
if (ps)
memset (ps, 0, sizeof (mbstate_t));
}
else if (MB_NULLWCH (tmp))
pos++;
else
pos += tmp;
}
return (pos - point);
}
int
_rl_is_mbchar_matched (string, seed, end, mbchar, length)
char *string;
int seed, end;
char *mbchar;
int length;
{
int i;
if ((end - seed) < length)
return 0;
for (i = 0; i < length; i++)
if (string[seed + i] != mbchar[i])
return 0;
return 1;
}
wchar_t
_rl_char_value (buf, ind)
char *buf;
int ind;
{
size_t tmp;
wchar_t wc;
mbstate_t ps;
int l;
if (MB_LEN_MAX == 1 || rl_byte_oriented)
return ((wchar_t) buf[ind]);
l = strlen (buf);
if (ind >= l - 1)
return ((wchar_t) buf[ind]);
memset (&ps, 0, sizeof (mbstate_t));
tmp = mbrtowc (&wc, buf + ind, l - ind, &ps);
if (MB_INVALIDCH (tmp) || MB_NULLWCH (tmp))
return ((wchar_t) buf[ind]);
return wc;
}
#endif /* HANDLE_MULTIBYTE */
/* Find next `count' characters started byte point of the specified seed.
If flags is MB_FIND_NONZERO, we look for non-zero-width multibyte
characters. */
#undef _rl_find_next_mbchar
int
_rl_find_next_mbchar (string, seed, count, flags)
char *string;
int seed, count, flags;
{
#if defined (HANDLE_MULTIBYTE)
return _rl_find_next_mbchar_internal (string, seed, count, flags);
#else
return (seed + count);
#endif
}
/* Find previous character started byte point of the specified seed.
Returned point will be point <= seed. If flags is MB_FIND_NONZERO,
we look for non-zero-width multibyte characters. */
#undef _rl_find_prev_mbchar
int
_rl_find_prev_mbchar (string, seed, flags)
char *string;
int seed, flags;
{
#if defined (HANDLE_MULTIBYTE)
return _rl_find_prev_mbchar_internal (string, seed, flags);
#else
return ((seed == 0) ? seed : seed - 1);
#endif
}
File diff suppressed because it is too large Load Diff
-301
View File
@@ -1,301 +0,0 @@
/* shquote - functions to quote and dequote strings */
/* Copyright (C) 1999 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <stdio.h>
#include "syntax.h"
#include <xmalloc.h>
/* Default set of characters that should be backslash-quoted in strings */
static const char bstab[256] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 0, 0, 0, 0, /* TAB, NL */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 0, 1, 0, 1, 1, /* SPACE, !, DQUOTE, DOL, AMP, SQUOTE */
1, 1, 1, 0, 1, 0, 0, 0, /* LPAR, RPAR, STAR, COMMA */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 0, 1, 1, /* SEMI, LESSTHAN, GREATERTHAN, QUEST */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 0, /* LBRACK, BS, RBRACK, CARAT */
1, 0, 0, 0, 0, 0, 0, 0, /* BACKQ */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0, /* LBRACE, BAR, RBRACE */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
/* **************************************************************** */
/* */
/* Functions for quoting strings to be re-read as input */
/* */
/* **************************************************************** */
/* Return a new string which is the single-quoted version of STRING.
Used by alias and trap, among others. */
char *
sh_single_quote (string)
const char *string;
{
register int c;
char *result, *r;
const char *s;
result = (char *)xmalloc (3 + (4 * strlen (string)));
r = result;
*r++ = '\'';
for (s = string; s && (c = *s); s++)
{
*r++ = c;
if (c == '\'')
{
*r++ = '\\'; /* insert escaped single quote */
*r++ = '\'';
*r++ = '\''; /* start new quoted string */
}
}
*r++ = '\'';
*r = '\0';
return (result);
}
/* Quote STRING using double quotes. Return a new string. */
char *
sh_double_quote (string)
const char *string;
{
register unsigned char c;
char *result, *r;
const char *s;
result = (char *)xmalloc (3 + (2 * strlen (string)));
r = result;
*r++ = '"';
for (s = string; s && (c = *s); s++)
{
/* Backslash-newline disappears within double quotes, so don't add one. */
if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n')
*r++ = '\\';
else if (c == CTLESC || c == CTLNUL)
*r++ = CTLESC; /* could be '\\'? */
*r++ = c;
}
*r++ = '"';
*r = '\0';
return (result);
}
/* Turn S into a simple double-quoted string. If FLAGS is non-zero, quote
double quote characters in S with backslashes. */
char *
sh_mkdoublequoted (s, slen, flags)
const char *s;
int slen, flags;
{
char *r, *ret;
int rlen;
rlen = (flags == 0) ? slen + 3 : (2 * slen) + 1;
ret = r = (char *)xmalloc (rlen);
*r++ = '"';
while (*s)
{
if (flags && *s == '"')
*r++ = '\\';
*r++ = *s++;
}
*r++ = '"';
*r = '\0';
return ret;
}
/* Remove backslashes that are quoting characters that are special between
double quotes. Return a new string. XXX - should this handle CTLESC
and CTLNUL? */
char *
sh_un_double_quote (string)
char *string;
{
register int c, pass_next;
char *result, *r, *s;
r = result = (char *)xmalloc (strlen (string) + 1);
for (pass_next = 0, s = string; s && (c = *s); s++)
{
if (pass_next)
{
*r++ = c;
pass_next = 0;
continue;
}
if (c == '\\' && (sh_syntaxtab[(unsigned char) s[1]] & CBSDQUOTE))
{
pass_next = 1;
continue;
}
*r++ = c;
}
*r = '\0';
return result;
}
/* Quote special characters in STRING using backslashes. Return a new
string. NOTE: if the string is to be further expanded, we need a
way to protect the CTLESC and CTLNUL characters. As I write this,
the current callers will never cause the string to be expanded without
going through the shell parser, which will protect the internal
quoting characters. */
char *
sh_backslash_quote (string, table)
char *string;
char *table;
{
int c;
char *result, *r, *s, *backslash_table;
result = (char *)xmalloc (2 * strlen (string) + 1);
backslash_table = table ? table : bstab;
for (r = result, s = string; s && (c = *s); s++)
{
if (backslash_table[c] == 1)
*r++ = '\\';
else if (c == '#' && s == string) /* comment char */
*r++ = '\\';
else if (c == '~' && (s == string || s[-1] == ':' || s[-1] == '='))
/* Tildes are special at the start of a word or after a `:' or `='
(technically unquoted, but it doesn't make a difference in practice) */
*r++ = '\\';
*r++ = c;
}
*r = '\0';
return (result);
}
#if defined (PROMPT_STRING_DECODE)
/* Quote characters that get special treatment when in double quotes in STRING
using backslashes. Return a new string. */
char *
sh_backslash_quote_for_double_quotes (string)
char *string;
{
unsigned char c;
char *result, *r, *s;
result = (char *)xmalloc (2 * strlen (string) + 1);
for (r = result, s = string; s && (c = *s); s++)
{
if (sh_syntaxtab[c] & CBSDQUOTE)
*r++ = '\\';
/* I should probably add flags for these to sh_syntaxtab[] */
else if (c == CTLESC || c == CTLNUL)
*r++ = CTLESC; /* could be '\\'? */
*r++ = c;
}
*r = '\0';
return (result);
}
#endif /* PROMPT_STRING_DECODE */
int
sh_contains_shell_metas (string)
char *string;
{
char *s;
for (s = string; s && *s; s++)
{
switch (*s)
{
case ' ': case '\t': case '\n': /* IFS white space */
case '\'': case '"': case '\\': /* quoting chars */
case '|': case '&': case ';': /* shell metacharacters */
case '(': case ')': case '<': case '>':
case '!': case '{': case '}': /* reserved words */
case '*': case '[': case '?': case ']': /* globbing chars */
case '^':
case '$': case '`': /* expansion chars */
return (1);
case '~': /* tilde expansion */
if (s == string || s[-1] == '=' || s[-1] == ':')
return (1);
break;
case '#':
if (s == string) /* comment char */
return (1);
/* FALLTHROUGH */
default:
break;
}
}
return (0);
}
-6082
View File
File diff suppressed because it is too large Load Diff
-9488
View File
File diff suppressed because it is too large Load Diff
-9
View File
@@ -1,9 +0,0 @@
BUILD_DIR=/usr/local/build/chet/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
export THIS_SH PATH
rm -f /tmp/xx
/bin/sh "$@"
-50
View File
@@ -1,50 +0,0 @@
:; ./shx
sh:
<&$fd ok
nlbq Mon Aug 3 02:45:00 EDT 1992
bang geoff
quote 712824302
setbq defmsgid=<1992Aug3.024502.6176@host>
bgwait sleep done... wait 6187
bash:
<&$fd ok
nlbq Mon Aug 3 02:45:09 EDT 1992
bang geoff
quote 712824311
setbq defmsgid=<1992Aug3.024512.6212@host>
bgwait sleep done... wait 6223
ash:
<&$fd shx1: 4: Syntax error: Bad fd number
nlbq Mon Aug 3 02:45:19 EDT 1992
bang geoff
quote getdate: `"now"' not a valid date
setbq defmsgid=<1992Aug3.` echo 024521
bgwait sleep done... wait 6241
ksh:
<&$fd ok
nlbq ./shx: 6248 Memory fault - core dumped
bang geoff
quote getdate: `"now"' not a valid date
setbq defmsgid=<1992Aug3.024530.6257@host>
bgwait no such job: 6265
wait 6265
sleep done...
zsh:
<&$fd ok
nlbq Mon Aug 3 02:45:36 EDT 1992
bang shx3: event not found: /s/ [4]
quote 712824337
setbq defmsgid=<..6290@host>
bgwait shx7: unmatched " [9]
sleep done...
:;
-10
View File
@@ -1,10 +0,0 @@
#! /bin/sh
for cmd in sh bash ash ksh zsh
do
echo
echo $cmd:
for demo in shx?
do
$cmd $demo
done
done
-108
View File
@@ -1,108 +0,0 @@
# basic nameref tests
bar=one
flow=two
flip=three
foo=bar
typeset -n foo
typeset -n fee=flow
echo ${foo}
echo ${fee}
typeset -n fee=flip
echo ${fee}
typeset -n
echo turning off nameref attribute on foo
typeset +n foo=other
echo ${foo}
echo after +n foo bar = $bar
unset foo bar fee
bar=one
foo=bar
typeset -n foo
foo=two printf "%s\n" $foo
foo=two eval 'printf "%s\n" $foo'
foo=two echo $foo
unset foo bar
# other basic assignment tests
bar=one
echo "expect <one>"
recho ${bar}
typeset -n foo=bar
foo=two
echo "expect <two>"
recho ${bar}
# this appears to be a ksh93 bug; it doesn't unset foo here and messes up
# later
unset foo bar
# initial tests of working inside shell functions
echoval()
{
typeset -n ref=$1
printf "%s\n" $ref
}
foo=bar
bar=one
echo "expect <$foo>"
echoval foo
echo "expect <$bar>"
echoval bar
unset foo bar
changevar()
{
typeset -n v=$1
shift
v="$@"
echo "changevar: expect <$@>"
recho "$v"
}
bar=one
echo "expect <one>"
recho ${bar}
changevar bar two
echo "expect <two>"
recho $bar
changevar bar three four five
echo "expect <three four five>"
recho "$bar"
unset foo bar
readonly foo=one
typeset -n bar=foo
bar=4
foo=4
echo $foo
echo $bar
assignvar()
{
typeset -n ref=$1
shift
ref="$@"
}
readonly foo=one
assignvar foo two three four
echo $foo
-4
View File
@@ -1,4 +0,0 @@
echo "warning: all of these tests will fail if arrays have not" >&2
echo "warning: been compiled into the shell" >&2
${THIS_SH} ./assoc.tests > /tmp/xx 2>&1
diff /tmp/xx assoc.right && rm -f /tmp/xx
-69
View File
@@ -1,69 +0,0 @@
# this is needed because posix mode restricts tilde expansion to assignment
# statements preceding a command, instead of the default of expanding all
# assignment statements on the line (e.g., after `export'). Without this,
# the next-to-last test fails
set +o posix
HOME=/usr/xyz
SHELL=~/bash
echo ~ch\et
echo ~/"foo"
echo "~chet"/"foo"
echo \~chet/"foo"
echo \~chet/bar
echo ~\chet/bar
echo ~chet""/bar
echo ":~chet/"
echo abcd~chet
echo "SHELL=~/bash"
echo $SHELL
echo abcd:~chet
path=/usr/ucb:/bin:~/bin:~/tmp/bin:/usr/bin
echo $path
cd /usr
cd /tmp
echo ~-
echo ~+
XPATH=/bin:/usr/bin:.
# yes tilde expansion
PPATH=$XPATH:~/bin
echo "$PPATH"
# no tilde expansion
PPATH="$XPATH:~/bin"
echo "$PPATH"
# yes tilde expansion
export PPATH=$XPATH:~/bin
echo "$PPATH"
declare -x PPATH=$XPATH:~/bin
echo "$PPATH"
# no tilde expansion
export PPATH="$XPATH:~/bin"
echo "$PPATH"
declare -x PPATH="$XPATH:~/bin"
echo "$PPATH"
# more tests of tilde expansion when executing case commands
case ~ in
$HOME) echo ok 1;;
*) echo bad 1 ;;
esac
case ~ in
~) echo ok 2 ;;
\~) echo bad 2a ;;
*) echo bad 2b ;;
esac
case $unset in
"") echo ok 3 ;;
*) echo bad 3 ;;
esac
USER=root # should exist just about everywhere
echo ~$USER
-1142
View File
File diff suppressed because it is too large Load Diff
-5138
View File
File diff suppressed because it is too large Load Diff
-404
View File
@@ -1,404 +0,0 @@
/* variables.h -- data structures for shell variables. */
/* Copyright (C) 1987-2012 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (_VARIABLES_H_)
#define _VARIABLES_H_
#include "stdc.h"
#include "array.h"
#include "assoc.h"
/* Shell variables and functions are stored in hash tables. */
#include "hashlib.h"
#include "conftypes.h"
/* A variable context. */
typedef struct var_context {
char *name; /* empty or NULL means global context */
int scope; /* 0 means global context */
int flags;
struct var_context *up; /* previous function calls */
struct var_context *down; /* down towards global context */
HASH_TABLE *table; /* variables at this scope */
} VAR_CONTEXT;
/* Flags for var_context->flags */
#define VC_HASLOCAL 0x01
#define VC_HASTMPVAR 0x02
#define VC_FUNCENV 0x04 /* also function if name != NULL */
#define VC_BLTNENV 0x08 /* builtin_env */
#define VC_TEMPENV 0x10 /* temporary_env */
#define VC_TEMPFLAGS (VC_FUNCENV|VC_BLTNENV|VC_TEMPENV)
/* Accessing macros */
#define vc_isfuncenv(vc) (((vc)->flags & VC_FUNCENV) != 0)
#define vc_isbltnenv(vc) (((vc)->flags & VC_BLTNENV) != 0)
#define vc_istempenv(vc) (((vc)->flags & (VC_TEMPFLAGS)) == VC_TEMPENV)
#define vc_istempscope(vc) (((vc)->flags & (VC_TEMPENV|VC_BLTNENV)) != 0)
#define vc_haslocals(vc) (((vc)->flags & VC_HASLOCAL) != 0)
#define vc_hastmpvars(vc) (((vc)->flags & VC_HASTMPVAR) != 0)
/* What a shell variable looks like. */
typedef struct variable *sh_var_value_func_t __P((struct variable *));
typedef struct variable *sh_var_assign_func_t __P((struct variable *, char *, arrayind_t, char *));
/* For the future */
union _value {
char *s; /* string value */
intmax_t i; /* int value */
COMMAND *f; /* function */
ARRAY *a; /* array */
HASH_TABLE *h; /* associative array */
double d; /* floating point number */
#if defined (HAVE_LONG_DOUBLE)
long double ld; /* long double */
#endif
struct variable *v; /* possible indirect variable use */
void *opaque; /* opaque data for future use */
};
typedef struct variable {
char *name; /* Symbol that the user types. */
char *value; /* Value that is returned. */
char *exportstr; /* String for the environment. */
sh_var_value_func_t *dynamic_value; /* Function called to return a `dynamic'
value for a variable, like $SECONDS
or $RANDOM. */
sh_var_assign_func_t *assign_func; /* Function called when this `special
variable' is assigned a value in
bind_variable. */
int attributes; /* export, readonly, array, invisible... */
int context; /* Which context this variable belongs to. */
} SHELL_VAR;
typedef struct _vlist {
SHELL_VAR **list;
int list_size; /* allocated size */
int list_len; /* current number of entries */
} VARLIST;
/* The various attributes that a given variable can have. */
/* First, the user-visible attributes */
#define att_exported 0x0000001 /* export to environment */
#define att_readonly 0x0000002 /* cannot change */
#define att_array 0x0000004 /* value is an array */
#define att_function 0x0000008 /* value is a function */
#define att_integer 0x0000010 /* internal representation is int */
#define att_local 0x0000020 /* variable is local to a function */
#define att_assoc 0x0000040 /* variable is an associative array */
#define att_trace 0x0000080 /* function is traced with DEBUG trap */
#define att_uppercase 0x0000100 /* word converted to uppercase on assignment */
#define att_lowercase 0x0000200 /* word converted to lowercase on assignment */
#define att_capcase 0x0000400 /* word capitalized on assignment */
#define att_nameref 0x0000800 /* word is a name reference */
#define user_attrs (att_exported|att_readonly|att_integer|att_local|att_trace|att_uppercase|att_lowercase|att_capcase|att_nameref)
#define attmask_user 0x0000fff
/* Internal attributes used for bookkeeping */
#define att_invisible 0x0001000 /* cannot see */
#define att_nounset 0x0002000 /* cannot unset */
#define att_noassign 0x0004000 /* assignment not allowed */
#define att_imported 0x0008000 /* came from environment */
#define att_special 0x0010000 /* requires special handling */
#define att_nofree 0x0020000 /* do not free value on unset */
#define attmask_int 0x00ff000
/* Internal attributes used for variable scoping. */
#define att_tempvar 0x0100000 /* variable came from the temp environment */
#define att_propagate 0x0200000 /* propagate to previous scope */
#define attmask_scope 0x0f00000
#define exported_p(var) ((((var)->attributes) & (att_exported)))
#define readonly_p(var) ((((var)->attributes) & (att_readonly)))
#define array_p(var) ((((var)->attributes) & (att_array)))
#define function_p(var) ((((var)->attributes) & (att_function)))
#define integer_p(var) ((((var)->attributes) & (att_integer)))
#define local_p(var) ((((var)->attributes) & (att_local)))
#define assoc_p(var) ((((var)->attributes) & (att_assoc)))
#define trace_p(var) ((((var)->attributes) & (att_trace)))
#define uppercase_p(var) ((((var)->attributes) & (att_uppercase)))
#define lowercase_p(var) ((((var)->attributes) & (att_lowercase)))
#define capcase_p(var) ((((var)->attributes) & (att_capcase)))
#define nameref_p(var) ((((var)->attributes) & (att_nameref)))
#define invisible_p(var) ((((var)->attributes) & (att_invisible)))
#define non_unsettable_p(var) ((((var)->attributes) & (att_nounset)))
#define noassign_p(var) ((((var)->attributes) & (att_noassign)))
#define imported_p(var) ((((var)->attributes) & (att_imported)))
#define specialvar_p(var) ((((var)->attributes) & (att_special)))
#define nofree_p(var) ((((var)->attributes) & (att_nofree)))
#define tempvar_p(var) ((((var)->attributes) & (att_tempvar)))
/* Acessing variable values: rvalues */
#define value_cell(var) ((var)->value)
#define function_cell(var) (COMMAND *)((var)->value)
#define array_cell(var) (ARRAY *)((var)->value)
#define assoc_cell(var) (HASH_TABLE *)((var)->value)
#define nameref_cell(var) ((var)->value) /* so it can change later */
#define NAMEREF_MAX 8 /* only 8 levels of nameref indirection */
#define var_isnull(var) ((var)->value == 0)
#define var_isset(var) ((var)->value != 0)
/* Assigning variable values: lvalues */
#define var_setvalue(var, str) ((var)->value = (str))
#define var_setfunc(var, func) ((var)->value = (char *)(func))
#define var_setarray(var, arr) ((var)->value = (char *)(arr))
#define var_setassoc(var, arr) ((var)->value = (char *)(arr))
#define var_setref(var, str) ((var)->value = (str))
/* Make VAR be auto-exported. */
#define set_auto_export(var) \
do { (var)->attributes |= att_exported; array_needs_making = 1; } while (0)
#define SETVARATTR(var, attr, undo) \
((undo == 0) ? ((var)->attributes |= (attr)) \
: ((var)->attributes &= ~(attr)))
#define VSETATTR(var, attr) ((var)->attributes |= (attr))
#define VUNSETATTR(var, attr) ((var)->attributes &= ~(attr))
#define VGETFLAGS(var) ((var)->attributes)
#define VSETFLAGS(var, flags) ((var)->attributes = (flags))
#define VCLRFLAGS(var) ((var)->attributes = 0)
/* Macros to perform various operations on `exportstr' member of a SHELL_VAR. */
#define CLEAR_EXPORTSTR(var) (var)->exportstr = (char *)NULL
#define COPY_EXPORTSTR(var) ((var)->exportstr) ? savestring ((var)->exportstr) : (char *)NULL
#define SET_EXPORTSTR(var, value) (var)->exportstr = (value)
#define SAVE_EXPORTSTR(var, value) (var)->exportstr = (value) ? savestring (value) : (char *)NULL
#define FREE_EXPORTSTR(var) \
do { if ((var)->exportstr) free ((var)->exportstr); } while (0)
#define CACHE_IMPORTSTR(var, value) \
(var)->exportstr = savestring (value)
#define INVALIDATE_EXPORTSTR(var) \
do { \
if ((var)->exportstr) \
{ \
free ((var)->exportstr); \
(var)->exportstr = (char *)NULL; \
} \
} while (0)
/* Stuff for hacking variables. */
typedef int sh_var_map_func_t __P((SHELL_VAR *));
/* Where we keep the variables and functions */
extern VAR_CONTEXT *global_variables;
extern VAR_CONTEXT *shell_variables;
extern HASH_TABLE *shell_functions;
extern HASH_TABLE *temporary_env;
extern int variable_context;
extern char *dollar_vars[];
extern char **export_env;
extern void initialize_shell_variables __P((char **, int));
extern SHELL_VAR *set_if_not __P((char *, char *));
extern void sh_set_lines_and_columns __P((int, int));
extern void set_pwd __P((void));
extern void set_ppid __P((void));
extern void make_funcname_visible __P((int));
extern SHELL_VAR *var_lookup __P((const char *, VAR_CONTEXT *));
extern SHELL_VAR *find_function __P((const char *));
extern FUNCTION_DEF *find_function_def __P((const char *));
extern SHELL_VAR *find_variable __P((const char *));
extern SHELL_VAR *find_variable_noref __P((const char *));
extern SHELL_VAR *find_variable_last_nameref __P((const char *));
extern SHELL_VAR *find_variable_nameref __P((SHELL_VAR *));
extern SHELL_VAR *find_variable_internal __P((const char *, int));
extern SHELL_VAR *find_variable_tempenv __P((const char *));
extern SHELL_VAR *find_variable_notempenv __P((const char *));
extern SHELL_VAR *find_global_variable __P((const char *));
extern SHELL_VAR *find_global_variable_noref __P((const char *));
extern SHELL_VAR *find_shell_variable __P((const char *));
extern SHELL_VAR *find_tempenv_variable __P((const char *));
extern SHELL_VAR *copy_variable __P((SHELL_VAR *));
extern SHELL_VAR *make_local_variable __P((const char *));
extern SHELL_VAR *bind_variable __P((const char *, char *, int));
extern SHELL_VAR *bind_function __P((const char *, COMMAND *));
extern void bind_function_def __P((const char *, FUNCTION_DEF *));
extern SHELL_VAR **map_over __P((sh_var_map_func_t *, VAR_CONTEXT *));
SHELL_VAR **map_over_funcs __P((sh_var_map_func_t *));
extern SHELL_VAR **all_shell_variables __P((void));
extern SHELL_VAR **all_shell_functions __P((void));
extern SHELL_VAR **all_visible_variables __P((void));
extern SHELL_VAR **all_visible_functions __P((void));
extern SHELL_VAR **all_exported_variables __P((void));
extern SHELL_VAR **local_exported_variables __P((void));
extern SHELL_VAR **all_local_variables __P((void));
#if defined (ARRAY_VARS)
extern SHELL_VAR **all_array_variables __P((void));
#endif
extern char **all_variables_matching_prefix __P((const char *));
extern char **make_var_array __P((HASH_TABLE *));
extern char **add_or_supercede_exported_var __P((char *, int));
extern char *get_variable_value __P((SHELL_VAR *));
extern char *get_string_value __P((const char *));
extern char *sh_get_env_value __P((const char *));
extern char *make_variable_value __P((SHELL_VAR *, char *, int));
extern SHELL_VAR *bind_variable_value __P((SHELL_VAR *, char *, int));
extern SHELL_VAR *bind_int_variable __P((char *, char *));
extern SHELL_VAR *bind_var_to_int __P((char *, intmax_t));
extern int assign_in_env __P((WORD_DESC *, int));
extern int unbind_variable __P((const char *));
extern int unbind_func __P((const char *));
extern int unbind_function_def __P((const char *));
extern int makunbound __P((const char *, VAR_CONTEXT *));
extern int kill_local_variable __P((const char *));
extern void delete_all_variables __P((HASH_TABLE *));
extern void delete_all_contexts __P((VAR_CONTEXT *));
extern VAR_CONTEXT *new_var_context __P((char *, int));
extern void dispose_var_context __P((VAR_CONTEXT *));
extern VAR_CONTEXT *push_var_context __P((char *, int, HASH_TABLE *));
extern void pop_var_context __P((void));
extern VAR_CONTEXT *push_scope __P((int, HASH_TABLE *));
extern void pop_scope __P((int));
extern void push_context __P((char *, int, HASH_TABLE *));
extern void pop_context __P((void));
extern void push_dollar_vars __P((void));
extern void pop_dollar_vars __P((void));
extern void dispose_saved_dollar_vars __P((void));
extern void push_args __P((WORD_LIST *));
extern void pop_args __P((void));
extern void adjust_shell_level __P((int));
extern void non_unsettable __P((char *));
extern void dispose_variable __P((SHELL_VAR *));
extern void dispose_used_env_vars __P((void));
extern void dispose_function_env __P((void));
extern void dispose_builtin_env __P((void));
extern void merge_temporary_env __P((void));
extern void merge_builtin_env __P((void));
extern void kill_all_local_variables __P((void));
extern void set_var_read_only __P((char *));
extern void set_func_read_only __P((const char *));
extern void set_var_auto_export __P((char *));
extern void set_func_auto_export __P((const char *));
extern void sort_variables __P((SHELL_VAR **));
extern int chkexport __P((char *));
extern void maybe_make_export_env __P((void));
extern void update_export_env_inplace __P((char *, int, char *));
extern void put_command_name_into_env __P((char *));
extern void put_gnu_argv_flags_into_env __P((intmax_t, char *));
extern void print_var_list __P((SHELL_VAR **));
extern void print_func_list __P((SHELL_VAR **));
extern void print_assignment __P((SHELL_VAR *));
extern void print_var_value __P((SHELL_VAR *, int));
extern void print_var_function __P((SHELL_VAR *));
#if defined (ARRAY_VARS)
extern SHELL_VAR *make_new_array_variable __P((char *));
extern SHELL_VAR *make_local_array_variable __P((char *, int));
extern SHELL_VAR *make_new_assoc_variable __P((char *));
extern SHELL_VAR *make_local_assoc_variable __P((char *));
extern void set_pipestatus_array __P((int *, int));
extern ARRAY *save_pipestatus_array __P((void));
extern void restore_pipestatus_array __P((ARRAY *));
#endif
extern void set_pipestatus_from_exit __P((int));
/* 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. */
extern void stupidly_hack_special_variables __P((char *));
/* Reinitialize some special variables that have external effects upon unset
when the shell reinitializes itself. */
extern void reinit_special_variables __P((void));
extern int get_random_number __P((void));
/* The `special variable' functions that get called when a particular
variable is set. */
extern void sv_ifs __P((char *));
extern void sv_path __P((char *));
extern void sv_mail __P((char *));
extern void sv_funcnest __P((char *));
extern void sv_globignore __P((char *));
extern void sv_ignoreeof __P((char *));
extern void sv_strict_posix __P((char *));
extern void sv_optind __P((char *));
extern void sv_opterr __P((char *));
extern void sv_locale __P((char *));
extern void sv_xtracefd __P((char *));
#if defined (READLINE)
extern void sv_comp_wordbreaks __P((char *));
extern void sv_terminal __P((char *));
extern void sv_hostfile __P((char *));
extern void sv_winsize __P((char *));
#endif
#if defined (__CYGWIN__)
extern void sv_home __P((char *));
#endif
#if defined (HISTORY)
extern void sv_histsize __P((char *));
extern void sv_histignore __P((char *));
extern void sv_history_control __P((char *));
# if defined (BANG_HISTORY)
extern void sv_histchars __P((char *));
# endif
extern void sv_histtimefmt __P((char *));
#endif /* HISTORY */
#if defined (HAVE_TZSET)
extern void sv_tz __P((char *));
#endif
#endif /* !_VARIABLES_H_ */