mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 07:43:07 +02:00
bash-20120322 remove leftover and stray files
This commit is contained in:
@@ -1 +0,0 @@
|
||||
quit
|
||||
-13668
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 */
|
||||
-4090
File diff suppressed because it is too large
Load Diff
@@ -1,508 +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;
|
||||
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;
|
||||
|
||||
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
|
||||
|
||||
/* 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 (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);
|
||||
}
|
||||
|
||||
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 == 1)
|
||||
{
|
||||
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);
|
||||
}
|
||||
-387
@@ -1,387 +0,0 @@
|
||||
/* command.h -- The structures used internally to represent commands, and
|
||||
the extern declarations of the functions used to create them. */
|
||||
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#if !defined (_COMMAND_H_)
|
||||
#define _COMMAND_H_
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
/* Instructions describing what kind of thing to do for a redirection. */
|
||||
enum r_instruction {
|
||||
r_output_direction, r_input_direction, r_inputa_direction,
|
||||
r_appending_to, r_reading_until, r_reading_string,
|
||||
r_duplicating_input, r_duplicating_output, r_deblank_reading_until,
|
||||
r_close_this, r_err_and_out, r_input_output, r_output_force,
|
||||
r_duplicating_input_word, r_duplicating_output_word,
|
||||
r_move_input, r_move_output, r_move_input_word, r_move_output_word,
|
||||
r_append_err_and_out
|
||||
};
|
||||
|
||||
/* Redirection flags; values for rflags */
|
||||
#define REDIR_VARASSIGN 0x01
|
||||
|
||||
/* Redirection errors. */
|
||||
#define AMBIGUOUS_REDIRECT -1
|
||||
#define NOCLOBBER_REDIRECT -2
|
||||
#define RESTRICTED_REDIRECT -3 /* can only happen in restricted shells. */
|
||||
#define HEREDOC_REDIRECT -4 /* here-doc temp file can't be created */
|
||||
#define BADVAR_REDIRECT -5 /* something wrong with {varname}redir */
|
||||
|
||||
#define CLOBBERING_REDIRECT(ri) \
|
||||
(ri == r_output_direction || ri == r_err_and_out)
|
||||
|
||||
#define OUTPUT_REDIRECT(ri) \
|
||||
(ri == r_output_direction || ri == r_input_output || ri == r_err_and_out || ri == r_append_err_and_out)
|
||||
|
||||
#define INPUT_REDIRECT(ri) \
|
||||
(ri == r_input_direction || ri == r_inputa_direction || ri == r_input_output)
|
||||
|
||||
#define WRITE_REDIRECT(ri) \
|
||||
(ri == r_output_direction || \
|
||||
ri == r_input_output || \
|
||||
ri == r_err_and_out || \
|
||||
ri == r_appending_to || \
|
||||
ri == r_append_err_and_out || \
|
||||
ri == r_output_force)
|
||||
|
||||
/* redirection needs translation */
|
||||
#define TRANSLATE_REDIRECT(ri) \
|
||||
(ri == r_duplicating_input_word || ri == r_duplicating_output_word || \
|
||||
ri == r_move_input_word || ri == r_move_output_word)
|
||||
|
||||
/* Command Types: */
|
||||
enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
|
||||
cm_connection, cm_function_def, cm_until, cm_group,
|
||||
cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc };
|
||||
|
||||
/* Possible values for the `flags' field of a WORD_DESC. */
|
||||
#define W_HASDOLLAR 0x000001 /* Dollar sign present. */
|
||||
#define W_QUOTED 0x000002 /* Some form of quote character is present. */
|
||||
#define W_ASSIGNMENT 0x000004 /* This word is a variable assignment. */
|
||||
#define W_GLOBEXP 0x000008 /* This word is the result of a glob expansion. */
|
||||
#define W_NOSPLIT 0x000010 /* Do not perform word splitting on this word because ifs is empty string. */
|
||||
#define W_NOGLOB 0x000020 /* Do not perform globbing on this word. */
|
||||
#define W_NOSPLIT2 0x000040 /* Don't split word except for $@ expansion (using spaces) because context does not allow it. */
|
||||
#define W_TILDEEXP 0x000080 /* Tilde expand this assignment word */
|
||||
#define W_DOLLARAT 0x000100 /* $@ and its special handling */
|
||||
#define W_DOLLARSTAR 0x000200 /* $* and its special handling */
|
||||
#define W_NOCOMSUB 0x000400 /* Don't perform command substitution on this word */
|
||||
#define W_ASSIGNRHS 0x000800 /* Word is rhs of an assignment statement */
|
||||
#define W_NOTILDE 0x001000 /* Don't perform tilde expansion on this word */
|
||||
#define W_ITILDE 0x002000 /* Internal flag for word expansion */
|
||||
#define W_NOEXPAND 0x004000 /* Don't expand at all -- do quote removal */
|
||||
#define W_COMPASSIGN 0x008000 /* Compound assignment */
|
||||
#define W_ASSNBLTIN 0x010000 /* word is a builtin command that takes assignments */
|
||||
#define W_ASSIGNARG 0x020000 /* word is assignment argument to command */
|
||||
#define W_HASQUOTEDNULL 0x040000 /* word contains a quoted null character */
|
||||
#define W_DQUOTE 0x080000 /* word should be treated as if double-quoted */
|
||||
#define W_NOPROCSUB 0x100000 /* don't perform process substitution */
|
||||
#define W_HASCTLESC 0x200000 /* word contains literal CTLESC characters */
|
||||
#define W_ASSIGNASSOC 0x400000 /* word looks like associative array assignment */
|
||||
#define W_ARRAYIND 0x800000 /* word is an array index being expanded */
|
||||
|
||||
/* Possible values for subshell_environment */
|
||||
#define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */
|
||||
#define SUBSHELL_PAREN 0x02 /* subshell caused by ( ... ) */
|
||||
#define SUBSHELL_COMSUB 0x04 /* subshell caused by `command` or $(command) */
|
||||
#define SUBSHELL_FORK 0x08 /* subshell caused by executing a disk command */
|
||||
#define SUBSHELL_PIPE 0x10 /* subshell from a pipeline element */
|
||||
#define SUBSHELL_PROCSUB 0x20 /* subshell caused by <(command) or >(command) */
|
||||
#define SUBSHELL_COPROC 0x40 /* subshell from a coproc pipeline */
|
||||
#define SUBSHELL_RESETTRAP 0x80 /* subshell needs to reset trap strings on first call to trap */
|
||||
|
||||
/* A structure which represents a word. */
|
||||
typedef struct word_desc {
|
||||
char *word; /* Zero terminated string. */
|
||||
int flags; /* Flags associated with this word. */
|
||||
} WORD_DESC;
|
||||
|
||||
/* A linked list of words. */
|
||||
typedef struct word_list {
|
||||
struct word_list *next;
|
||||
WORD_DESC *word;
|
||||
} WORD_LIST;
|
||||
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Shell Command Structs */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* What a redirection descriptor looks like. If the redirection instruction
|
||||
is ri_duplicating_input or ri_duplicating_output, use DEST, otherwise
|
||||
use the file in FILENAME. Out-of-range descriptors are identified by a
|
||||
negative DEST. */
|
||||
|
||||
typedef union {
|
||||
int dest; /* Place to redirect REDIRECTOR to, or ... */
|
||||
WORD_DESC *filename; /* filename to redirect to. */
|
||||
} REDIRECTEE;
|
||||
|
||||
/* Structure describing a redirection. If REDIRECTOR is negative, the parser
|
||||
(or translator in redir.c) encountered an out-of-range file descriptor. */
|
||||
typedef struct redirect {
|
||||
struct redirect *next; /* Next element, or NULL. */
|
||||
REDIRECTEE redirector; /* Descriptor or varname to be redirected. */
|
||||
int rflags; /* Private flags for this redirection */
|
||||
int flags; /* Flag value for `open'. */
|
||||
enum r_instruction instruction; /* What to do with the information. */
|
||||
REDIRECTEE redirectee; /* File descriptor or filename */
|
||||
char *here_doc_eof; /* The word that appeared in <<foo. */
|
||||
} REDIRECT;
|
||||
|
||||
/* An element used in parsing. A single word or a single redirection.
|
||||
This is an ephemeral construct. */
|
||||
typedef struct element {
|
||||
WORD_DESC *word;
|
||||
REDIRECT *redirect;
|
||||
} ELEMENT;
|
||||
|
||||
/* Possible values for command->flags. */
|
||||
#define CMD_WANT_SUBSHELL 0x01 /* User wants a subshell: ( command ) */
|
||||
#define CMD_FORCE_SUBSHELL 0x02 /* Shell needs to force a subshell. */
|
||||
#define CMD_INVERT_RETURN 0x04 /* Invert the exit value. */
|
||||
#define CMD_IGNORE_RETURN 0x08 /* Ignore the exit value. For set -e. */
|
||||
#define CMD_NO_FUNCTIONS 0x10 /* Ignore functions during command lookup. */
|
||||
#define CMD_INHIBIT_EXPANSION 0x20 /* Do not expand the command words. */
|
||||
#define CMD_NO_FORK 0x40 /* Don't fork; just call execve */
|
||||
#define CMD_TIME_PIPELINE 0x80 /* Time a pipeline */
|
||||
#define CMD_TIME_POSIX 0x100 /* time -p; use POSIX.2 time output spec. */
|
||||
#define CMD_AMPERSAND 0x200 /* command & */
|
||||
#define CMD_STDIN_REDIR 0x400 /* async command needs implicit </dev/null */
|
||||
#define CMD_COMMAND_BUILTIN 0x0800 /* command executed by `command' builtin */
|
||||
#define CMD_COPROC_SUBSHELL 0x1000
|
||||
#define CMD_LASTPIPE 0x2000
|
||||
|
||||
/* What a command looks like. */
|
||||
typedef struct command {
|
||||
enum command_type type; /* FOR CASE WHILE IF CONNECTION or SIMPLE. */
|
||||
int flags; /* Flags controlling execution environment. */
|
||||
int line; /* line number the command starts on */
|
||||
REDIRECT *redirects; /* Special redirects for FOR CASE, etc. */
|
||||
union {
|
||||
struct for_com *For;
|
||||
struct case_com *Case;
|
||||
struct while_com *While;
|
||||
struct if_com *If;
|
||||
struct connection *Connection;
|
||||
struct simple_com *Simple;
|
||||
struct function_def *Function_def;
|
||||
struct group_com *Group;
|
||||
#if defined (SELECT_COMMAND)
|
||||
struct select_com *Select;
|
||||
#endif
|
||||
#if defined (DPAREN_ARITHMETIC)
|
||||
struct arith_com *Arith;
|
||||
#endif
|
||||
#if defined (COND_COMMAND)
|
||||
struct cond_com *Cond;
|
||||
#endif
|
||||
#if defined (ARITH_FOR_COMMAND)
|
||||
struct arith_for_com *ArithFor;
|
||||
#endif
|
||||
struct subshell_com *Subshell;
|
||||
struct coproc_com *Coproc;
|
||||
} value;
|
||||
} COMMAND;
|
||||
|
||||
/* Structure used to represent the CONNECTION type. */
|
||||
typedef struct connection {
|
||||
int ignore; /* Unused; simplifies make_command (). */
|
||||
COMMAND *first; /* Pointer to the first command. */
|
||||
COMMAND *second; /* Pointer to the second command. */
|
||||
int connector; /* What separates this command from others. */
|
||||
} CONNECTION;
|
||||
|
||||
/* Structures used to represent the CASE command. */
|
||||
|
||||
/* Values for FLAGS word in a PATTERN_LIST */
|
||||
#define CASEPAT_FALLTHROUGH 0x01
|
||||
#define CASEPAT_TESTNEXT 0x02
|
||||
|
||||
/* Pattern/action structure for CASE_COM. */
|
||||
typedef struct pattern_list {
|
||||
struct pattern_list *next; /* Clause to try in case this one failed. */
|
||||
WORD_LIST *patterns; /* Linked list of patterns to test. */
|
||||
COMMAND *action; /* Thing to execute if a pattern matches. */
|
||||
int flags;
|
||||
} PATTERN_LIST;
|
||||
|
||||
/* The CASE command. */
|
||||
typedef struct case_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* line number the `case' keyword appears on */
|
||||
WORD_DESC *word; /* The thing to test. */
|
||||
PATTERN_LIST *clauses; /* The clauses to test against, or NULL. */
|
||||
} CASE_COM;
|
||||
|
||||
/* FOR command. */
|
||||
typedef struct for_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* line number the `for' keyword appears on */
|
||||
WORD_DESC *name; /* The variable name to get mapped over. */
|
||||
WORD_LIST *map_list; /* The things to map over. This is never NULL. */
|
||||
COMMAND *action; /* The action to execute.
|
||||
During execution, NAME is bound to successive
|
||||
members of MAP_LIST. */
|
||||
} FOR_COM;
|
||||
|
||||
#if defined (ARITH_FOR_COMMAND)
|
||||
typedef struct arith_for_com {
|
||||
int flags;
|
||||
int line; /* generally used for error messages */
|
||||
WORD_LIST *init;
|
||||
WORD_LIST *test;
|
||||
WORD_LIST *step;
|
||||
COMMAND *action;
|
||||
} ARITH_FOR_COM;
|
||||
#endif
|
||||
|
||||
#if defined (SELECT_COMMAND)
|
||||
/* KSH SELECT command. */
|
||||
typedef struct select_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* line number the `select' keyword appears on */
|
||||
WORD_DESC *name; /* The variable name to get mapped over. */
|
||||
WORD_LIST *map_list; /* The things to map over. This is never NULL. */
|
||||
COMMAND *action; /* The action to execute.
|
||||
During execution, NAME is bound to the member of
|
||||
MAP_LIST chosen by the user. */
|
||||
} SELECT_COM;
|
||||
#endif /* SELECT_COMMAND */
|
||||
|
||||
/* IF command. */
|
||||
typedef struct if_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
COMMAND *test; /* Thing to test. */
|
||||
COMMAND *true_case; /* What to do if the test returned non-zero. */
|
||||
COMMAND *false_case; /* What to do if the test returned zero. */
|
||||
} IF_COM;
|
||||
|
||||
/* WHILE command. */
|
||||
typedef struct while_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
COMMAND *test; /* Thing to test. */
|
||||
COMMAND *action; /* Thing to do while test is non-zero. */
|
||||
} WHILE_COM;
|
||||
|
||||
#if defined (DPAREN_ARITHMETIC)
|
||||
/* The arithmetic evaluation command, ((...)). Just a set of flags and
|
||||
a WORD_LIST, of which the first element is the only one used, for the
|
||||
time being. */
|
||||
typedef struct arith_com {
|
||||
int flags;
|
||||
int line;
|
||||
WORD_LIST *exp;
|
||||
} ARITH_COM;
|
||||
#endif /* DPAREN_ARITHMETIC */
|
||||
|
||||
/* The conditional command, [[...]]. This is a binary tree -- we slippped
|
||||
a recursive-descent parser into the YACC grammar to parse it. */
|
||||
#define COND_AND 1
|
||||
#define COND_OR 2
|
||||
#define COND_UNARY 3
|
||||
#define COND_BINARY 4
|
||||
#define COND_TERM 5
|
||||
#define COND_EXPR 6
|
||||
|
||||
typedef struct cond_com {
|
||||
int flags;
|
||||
int line;
|
||||
int type;
|
||||
WORD_DESC *op;
|
||||
struct cond_com *left, *right;
|
||||
} COND_COM;
|
||||
|
||||
/* The "simple" command. Just a collection of words and redirects. */
|
||||
typedef struct simple_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* line number the command starts on */
|
||||
WORD_LIST *words; /* The program name, the arguments,
|
||||
variable assignments, etc. */
|
||||
REDIRECT *redirects; /* Redirections to perform. */
|
||||
} SIMPLE_COM;
|
||||
|
||||
/* The "function definition" command. */
|
||||
typedef struct function_def {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* Line number the function def starts on. */
|
||||
WORD_DESC *name; /* The name of the function. */
|
||||
COMMAND *command; /* The parsed execution tree. */
|
||||
char *source_file; /* file in which function was defined, if any */
|
||||
} FUNCTION_DEF;
|
||||
|
||||
/* A command that is `grouped' allows pipes and redirections to affect all
|
||||
commands in the group. */
|
||||
typedef struct group_com {
|
||||
int ignore; /* See description of CMD flags. */
|
||||
COMMAND *command;
|
||||
} GROUP_COM;
|
||||
|
||||
typedef struct subshell_com {
|
||||
int flags;
|
||||
COMMAND *command;
|
||||
} SUBSHELL_COM;
|
||||
|
||||
#define COPROC_RUNNING 0x01
|
||||
#define COPROC_DEAD 0x02
|
||||
|
||||
typedef struct coproc {
|
||||
char *c_name;
|
||||
pid_t c_pid;
|
||||
int c_rfd;
|
||||
int c_wfd;
|
||||
int c_rsave;
|
||||
int c_wsave;
|
||||
int c_flags;
|
||||
int c_status;
|
||||
} Coproc;
|
||||
|
||||
typedef struct coproc_com {
|
||||
int flags;
|
||||
char *name;
|
||||
COMMAND *command;
|
||||
} COPROC_COM;
|
||||
|
||||
extern COMMAND *global_command;
|
||||
extern Coproc sh_coproc;
|
||||
|
||||
/* Possible command errors */
|
||||
#define CMDERR_DEFAULT 0
|
||||
#define CMDERR_BADTYPE 1
|
||||
#define CMDERR_BADCONN 2
|
||||
#define CMDERR_BADJUMP 3
|
||||
|
||||
#define CMDERR_LAST 3
|
||||
|
||||
/* Forward declarations of functions declared in copy_cmd.c. */
|
||||
|
||||
extern FUNCTION_DEF *copy_function_def_contents __P((FUNCTION_DEF *, FUNCTION_DEF *));
|
||||
extern FUNCTION_DEF *copy_function_def __P((FUNCTION_DEF *));
|
||||
|
||||
extern WORD_DESC *copy_word __P((WORD_DESC *));
|
||||
extern WORD_LIST *copy_word_list __P((WORD_LIST *));
|
||||
extern REDIRECT *copy_redirect __P((REDIRECT *));
|
||||
extern REDIRECT *copy_redirects __P((REDIRECT *));
|
||||
extern COMMAND *copy_command __P((COMMAND *));
|
||||
|
||||
#endif /* _COMMAND_H_ */
|
||||
-121
@@ -1,121 +0,0 @@
|
||||
/* config-top.h - various user-settable options not under the control of autoconf. */
|
||||
|
||||
/* Copyright (C) 2002-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/>.
|
||||
*/
|
||||
|
||||
/* Define CONTINUE_AFTER_KILL_ERROR if you want the kill command to
|
||||
continue processing arguments after one of them fails. This is
|
||||
what POSIX.2 specifies. */
|
||||
#define CONTINUE_AFTER_KILL_ERROR
|
||||
|
||||
/* Define BREAK_COMPLAINS if you want the non-standard, but useful
|
||||
error messages about `break' and `continue' out of context. */
|
||||
#define BREAK_COMPLAINS
|
||||
|
||||
/* Define BUFFERED_INPUT if you want the shell to do its own input
|
||||
buffering, rather than using stdio. Do not undefine this; it's
|
||||
required to preserve semantics required by POSIX. */
|
||||
#define BUFFERED_INPUT
|
||||
|
||||
/* Define ONESHOT if you want sh -c 'command' to avoid forking to execute
|
||||
`command' whenever possible. This is a big efficiency improvement. */
|
||||
#define ONESHOT
|
||||
|
||||
/* Define V9_ECHO if you want to give the echo builtin backslash-escape
|
||||
interpretation using the -e option, in the style of the Bell Labs 9th
|
||||
Edition version of echo. You cannot emulate the System V echo behavior
|
||||
without this option. */
|
||||
#define V9_ECHO
|
||||
|
||||
/* Define DONT_REPORT_SIGPIPE if you don't want to see `Broken pipe' messages
|
||||
when a job like `cat jobs.c | exit 1' terminates due to a SIGPIPE. */
|
||||
#define DONT_REPORT_SIGPIPE
|
||||
|
||||
/* Define DONT_REPORT_SIGTERM if you don't want to see `Terminates' message
|
||||
when a job exits due to SIGTERM, since that's the default signal sent
|
||||
by the kill builtin. */
|
||||
/* #define DONT_REPORT_SIGTERM */
|
||||
|
||||
/* Define DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS if you don't want builtins
|
||||
like `echo' and `printf' to report errors when output does not succeed
|
||||
due to EPIPE. */
|
||||
/* #define DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS */
|
||||
|
||||
/* The default value of the PATH variable. */
|
||||
#ifndef DEFAULT_PATH_VALUE
|
||||
#define DEFAULT_PATH_VALUE \
|
||||
"/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:."
|
||||
#endif
|
||||
|
||||
/* The value for PATH when invoking `command -p'. This is only used when
|
||||
the Posix.2 confstr () function, or CS_PATH define are not present. */
|
||||
#ifndef STANDARD_UTILS_PATH
|
||||
#define STANDARD_UTILS_PATH \
|
||||
"/bin:/usr/bin:/sbin:/usr/sbin:/etc:/usr/etc"
|
||||
#endif
|
||||
|
||||
/* Default primary and secondary prompt strings. */
|
||||
#define PPROMPT "\\s-\\v\\$ "
|
||||
#define SPROMPT "> "
|
||||
|
||||
/* Undefine this if you don't want the ksh-compatible behavior of reprinting
|
||||
the select menu after a valid choice is made only if REPLY is set to NULL
|
||||
in the body of the select command. The menu is always reprinted if the
|
||||
reply to the select query is an empty line. */
|
||||
#define KSH_COMPATIBLE_SELECT
|
||||
|
||||
/* System-wide .bashrc file for interactive shells. */
|
||||
/* #define SYS_BASHRC "/etc/bash.bashrc" */
|
||||
|
||||
/* System-wide .bash_logout for login shells. */
|
||||
/* #define SYS_BASH_LOGOUT "/etc/bash.bash_logout" */
|
||||
|
||||
/* Define this to make non-interactive shells begun with argv[0][0] == '-'
|
||||
run the startup files when not in posix mode. */
|
||||
/* #define NON_INTERACTIVE_LOGIN_SHELLS */
|
||||
|
||||
/* Define this if you want bash to try to check whether it's being run by
|
||||
sshd and source the .bashrc if so (like the rshd behavior). This checks
|
||||
for the presence of SSH_CLIENT or SSH2_CLIENT in the initial environment,
|
||||
which can be fooled under certain not-uncommon circumstances. */
|
||||
/* #define SSH_SOURCE_BASHRC */
|
||||
|
||||
/* Define if you want the case-capitalizing operators (~[~]) and the
|
||||
`capcase' variable attribute (declare -c). */
|
||||
#define CASEMOD_CAPCASE
|
||||
|
||||
/* This is used as the name of a shell function to call when a command
|
||||
name is not found. If you want to name it something other than the
|
||||
default ("command_not_found_handle"), change it here. */
|
||||
/* #define NOTFOUND_HOOK "command_not_found_handle" */
|
||||
|
||||
/* Define if you want each line saved to the history list in bashhist.c:
|
||||
bash_add_history() to be sent to syslog(). */
|
||||
/* #define SYSLOG_HISTORY */
|
||||
#if defined (SYSLOG_HISTORY)
|
||||
# define SYSLOG_FACILITY LOG_USER
|
||||
# define SYSLOG_LEVEL LOG_INFO
|
||||
#endif
|
||||
|
||||
/* Define if you want to include code in shell.c to support wordexp(3) */
|
||||
/* #define WORDEXP_OPTION */
|
||||
|
||||
/* Define as 1 if you want to enable code that implements multiple coprocs */
|
||||
#ifndef MULTIPLE_COPROCS
|
||||
# define MULTIPLE_COPROCS 0
|
||||
#endif
|
||||
@@ -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
|
||||
Vendored
BIN
Binary file not shown.
-1745
File diff suppressed because it is too large
Load Diff
-8419
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
-5341
File diff suppressed because it is too large
Load Diff
@@ -1,62 +0,0 @@
|
||||
/* posixdir.h -- Posix directory reading includes and defines. */
|
||||
|
||||
/* Copyright (C) 1987,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 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/>.
|
||||
*/
|
||||
|
||||
/* This file should be included instead of <dirent.h> or <sys/dir.h>. */
|
||||
|
||||
#if !defined (_POSIXDIR_H_)
|
||||
#define _POSIXDIR_H_
|
||||
|
||||
#if defined (HAVE_DIRENT_H)
|
||||
# include <dirent.h>
|
||||
# if defined (HAVE_STRUCT_DIRENT_D_NAMLEN)
|
||||
# define D_NAMLEN(d) ((d)->d_namlen)
|
||||
# else
|
||||
# define D_NAMLEN(d) (strlen ((d)->d_name))
|
||||
# endif /* !HAVE_STRUCT_DIRENT_D_NAMLEN */
|
||||
#else
|
||||
# if defined (HAVE_SYS_NDIR_H)
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if defined (HAVE_SYS_DIR_H)
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if defined (HAVE_NDIR_H)
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
# if !defined (dirent)
|
||||
# define dirent direct
|
||||
# endif /* !dirent */
|
||||
# define D_NAMLEN(d) ((d)->d_namlen)
|
||||
#endif /* !HAVE_DIRENT_H */
|
||||
|
||||
#if defined (HAVE_STRUCT_DIRENT_D_INO) && !defined (HAVE_STRUCT_DIRENT_D_FILENO)
|
||||
# define d_fileno d_ino
|
||||
#endif
|
||||
|
||||
#if !defined (HAVE_STRUCT_DIRENT_D_INO) || defined (BROKEN_DIRENT_D_INO)
|
||||
/* Posix does not require that the d_ino field be present, and some
|
||||
systems do not provide it. */
|
||||
# define REAL_DIR_ENTRY(dp) 1
|
||||
#else
|
||||
# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
|
||||
# define D_INO_AVAILABLE 1
|
||||
#endif /* _POSIX_SOURCE */
|
||||
|
||||
#endif /* !_POSIXDIR_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -1,698 +0,0 @@
|
||||
/* signals.c -- signal handling support for readline. */
|
||||
|
||||
/* Copyright (C) 1987-2011 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 <stdio.h> /* Just for NULL. Yuck. */
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
|
||||
/* System-specific feature definitions and include files. */
|
||||
#include "rldefs.h"
|
||||
|
||||
#if defined (GWINSZ_IN_SYS_IOCTL)
|
||||
# include <sys/ioctl.h>
|
||||
#endif /* GWINSZ_IN_SYS_IOCTL */
|
||||
|
||||
/* Some standard library routines. */
|
||||
#include "readline.h"
|
||||
#include "history.h"
|
||||
|
||||
#include "rlprivate.h"
|
||||
|
||||
#if defined (HANDLE_SIGNALS)
|
||||
|
||||
#if !defined (RETSIGTYPE)
|
||||
# if defined (VOID_SIGHANDLER)
|
||||
# define RETSIGTYPE void
|
||||
# else
|
||||
# define RETSIGTYPE int
|
||||
# endif /* !VOID_SIGHANDLER */
|
||||
#endif /* !RETSIGTYPE */
|
||||
|
||||
#if defined (VOID_SIGHANDLER)
|
||||
# define SIGHANDLER_RETURN return
|
||||
#else
|
||||
# define SIGHANDLER_RETURN return (0)
|
||||
#endif
|
||||
|
||||
/* This typedef is equivalent to the one for Function; it allows us
|
||||
to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
|
||||
typedef RETSIGTYPE SigHandler ();
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
typedef struct sigaction sighandler_cxt;
|
||||
# define rl_sigaction(s, nh, oh) sigaction(s, nh, oh)
|
||||
#else
|
||||
typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt;
|
||||
# define sigemptyset(m)
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
#ifndef SA_RESTART
|
||||
# define SA_RESTART 0
|
||||
#endif
|
||||
|
||||
static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
|
||||
static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
|
||||
|
||||
static RETSIGTYPE rl_signal_handler PARAMS((int));
|
||||
static RETSIGTYPE _rl_handle_signal PARAMS((int));
|
||||
|
||||
/* Exported variables for use by applications. */
|
||||
|
||||
/* If non-zero, readline will install its own signal handlers for
|
||||
SIGINT, SIGTERM, SIGHUP, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
|
||||
int rl_catch_signals = 1;
|
||||
|
||||
/* If non-zero, readline will install a signal handler for SIGWINCH. */
|
||||
#ifdef SIGWINCH
|
||||
int rl_catch_sigwinch = 1;
|
||||
#else
|
||||
int rl_catch_sigwinch = 0; /* for the readline state struct in readline.c */
|
||||
#endif
|
||||
|
||||
/* Private variables. */
|
||||
int _rl_interrupt_immediately = 0;
|
||||
int volatile _rl_caught_signal = 0; /* should be sig_atomic_t, but that requires including <signal.h> everywhere */
|
||||
|
||||
/* If non-zero, print characters corresponding to received signals as long as
|
||||
the user has indicated his desire to do so (_rl_echo_control_chars). */
|
||||
int _rl_echoctl = 0;
|
||||
|
||||
int _rl_intr_char = 0;
|
||||
int _rl_quit_char = 0;
|
||||
int _rl_susp_char = 0;
|
||||
|
||||
static int signals_set_flag;
|
||||
static int sigwinch_set_flag;
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Signal Handling */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
static sighandler_cxt old_int, old_term, old_hup, old_alrm, old_quit;
|
||||
#if defined (SIGTSTP)
|
||||
static sighandler_cxt old_tstp, old_ttou, old_ttin;
|
||||
#endif
|
||||
#if defined (SIGWINCH)
|
||||
static sighandler_cxt old_winch;
|
||||
#endif
|
||||
|
||||
_rl_sigcleanup_func_t *_rl_sigcleanup;
|
||||
void *_rl_sigcleanarg;
|
||||
|
||||
/* Readline signal handler functions. */
|
||||
|
||||
/* Called from RL_CHECK_SIGNALS() macro */
|
||||
RETSIGTYPE
|
||||
_rl_signal_handler (sig)
|
||||
int sig;
|
||||
{
|
||||
_rl_caught_signal = 0; /* XXX */
|
||||
|
||||
if (sig == SIGWINCH)
|
||||
rl_resize_terminal ();
|
||||
else
|
||||
_rl_handle_signal (sig);
|
||||
SIGHANDLER_RETURN;
|
||||
}
|
||||
|
||||
static RETSIGTYPE
|
||||
rl_signal_handler (sig)
|
||||
int sig;
|
||||
{
|
||||
if (_rl_interrupt_immediately)
|
||||
{
|
||||
_rl_interrupt_immediately = 0;
|
||||
_rl_handle_signal (sig);
|
||||
}
|
||||
else
|
||||
_rl_caught_signal = sig;
|
||||
|
||||
SIGHANDLER_RETURN;
|
||||
}
|
||||
|
||||
static RETSIGTYPE
|
||||
_rl_handle_signal (sig)
|
||||
int sig;
|
||||
{
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigset_t set;
|
||||
#else /* !HAVE_POSIX_SIGNALS */
|
||||
# if defined (HAVE_BSD_SIGNALS)
|
||||
long omask;
|
||||
# else /* !HAVE_BSD_SIGNALS */
|
||||
sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */
|
||||
# endif /* !HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
RL_SETSTATE(RL_STATE_SIGHANDLER);
|
||||
|
||||
#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
|
||||
/* Since the signal will not be blocked while we are in the signal
|
||||
handler, ignore it until rl_clear_signals resets the catcher. */
|
||||
# if defined (SIGALRM)
|
||||
if (sig == SIGINT || sig == SIGALRM)
|
||||
# else
|
||||
if (sig == SIGINT)
|
||||
# endif
|
||||
rl_set_sighandler (sig, SIG_IGN, &dummy_cxt);
|
||||
#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
|
||||
|
||||
/* If there's a sig cleanup function registered, call it and `deregister'
|
||||
the cleanup function to avoid multiple calls */
|
||||
if (_rl_sigcleanup)
|
||||
{
|
||||
(*_rl_sigcleanup) (sig, _rl_sigcleanarg);
|
||||
_rl_sigcleanup = 0;
|
||||
_rl_sigcleanarg = 0;
|
||||
}
|
||||
|
||||
switch (sig)
|
||||
{
|
||||
case SIGINT:
|
||||
_rl_reset_completion_state ();
|
||||
rl_free_line_state ();
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case SIGTERM:
|
||||
case SIGHUP:
|
||||
#if defined (SIGTSTP)
|
||||
case SIGTSTP:
|
||||
case SIGTTOU:
|
||||
case SIGTTIN:
|
||||
#endif /* SIGTSTP */
|
||||
#if defined (SIGALRM)
|
||||
case SIGALRM:
|
||||
#endif
|
||||
#if defined (SIGQUIT)
|
||||
case SIGQUIT:
|
||||
#endif
|
||||
rl_echo_signal_char (sig);
|
||||
rl_cleanup_after_signal ();
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigemptyset (&set);
|
||||
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
|
||||
sigdelset (&set, sig);
|
||||
#else /* !HAVE_POSIX_SIGNALS */
|
||||
# if defined (HAVE_BSD_SIGNALS)
|
||||
omask = sigblock (0);
|
||||
# endif /* HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
#if defined (__EMX__)
|
||||
signal (sig, SIG_ACK);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_KILL)
|
||||
kill (getpid (), sig);
|
||||
#else
|
||||
raise (sig); /* assume we have raise */
|
||||
#endif
|
||||
|
||||
/* Let the signal that we just sent through. */
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
|
||||
#else /* !HAVE_POSIX_SIGNALS */
|
||||
# if defined (HAVE_BSD_SIGNALS)
|
||||
sigsetmask (omask & ~(sigmask (sig)));
|
||||
# endif /* HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
rl_reset_after_signal ();
|
||||
}
|
||||
|
||||
RL_UNSETSTATE(RL_STATE_SIGHANDLER);
|
||||
SIGHANDLER_RETURN;
|
||||
}
|
||||
|
||||
#if defined (SIGWINCH)
|
||||
static RETSIGTYPE
|
||||
rl_sigwinch_handler (sig)
|
||||
int sig;
|
||||
{
|
||||
SigHandler *oh;
|
||||
|
||||
#if defined (MUST_REINSTALL_SIGHANDLERS)
|
||||
sighandler_cxt dummy_winch;
|
||||
|
||||
/* We don't want to change old_winch -- it holds the state of SIGWINCH
|
||||
disposition set by the calling application. We need this state
|
||||
because we call the application's SIGWINCH handler after updating
|
||||
our own idea of the screen size. */
|
||||
rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch);
|
||||
#endif
|
||||
|
||||
RL_SETSTATE(RL_STATE_SIGHANDLER);
|
||||
_rl_caught_signal = sig;
|
||||
|
||||
/* If another sigwinch handler has been installed, call it. */
|
||||
oh = (SigHandler *)old_winch.sa_handler;
|
||||
if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
|
||||
(*oh) (sig);
|
||||
|
||||
RL_UNSETSTATE(RL_STATE_SIGHANDLER);
|
||||
SIGHANDLER_RETURN;
|
||||
}
|
||||
#endif /* SIGWINCH */
|
||||
|
||||
/* Functions to manage signal handling. */
|
||||
|
||||
#if !defined (HAVE_POSIX_SIGNALS)
|
||||
static int
|
||||
rl_sigaction (sig, nh, oh)
|
||||
int sig;
|
||||
sighandler_cxt *nh, *oh;
|
||||
{
|
||||
oh->sa_handler = signal (sig, nh->sa_handler);
|
||||
return 0;
|
||||
}
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
/* Set up a readline-specific signal handler, saving the old signal
|
||||
information in OHANDLER. Return the old signal handler, like
|
||||
signal(). */
|
||||
static SigHandler *
|
||||
rl_set_sighandler (sig, handler, ohandler)
|
||||
int sig;
|
||||
SigHandler *handler;
|
||||
sighandler_cxt *ohandler;
|
||||
{
|
||||
sighandler_cxt old_handler;
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_handler = handler;
|
||||
# if defined (SIGWINCH)
|
||||
act.sa_flags = (sig == SIGWINCH) ? SA_RESTART : 0;
|
||||
# else
|
||||
act.sa_flags = 0;
|
||||
# endif /* SIGWINCH */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigemptyset (&ohandler->sa_mask);
|
||||
sigaction (sig, &act, &old_handler);
|
||||
#else
|
||||
old_handler.sa_handler = (SigHandler *)signal (sig, handler);
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
/* XXX -- assume we have memcpy */
|
||||
/* If rl_set_signals is called twice in a row, don't set the old handler to
|
||||
rl_signal_handler, because that would cause infinite recursion. */
|
||||
if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler)
|
||||
memcpy (ohandler, &old_handler, sizeof (sighandler_cxt));
|
||||
|
||||
return (ohandler->sa_handler);
|
||||
}
|
||||
|
||||
static void
|
||||
rl_maybe_set_sighandler (sig, handler, ohandler)
|
||||
int sig;
|
||||
SigHandler *handler;
|
||||
sighandler_cxt *ohandler;
|
||||
{
|
||||
sighandler_cxt dummy;
|
||||
SigHandler *oh;
|
||||
|
||||
sigemptyset (&dummy.sa_mask);
|
||||
oh = rl_set_sighandler (sig, handler, ohandler);
|
||||
if (oh == (SigHandler *)SIG_IGN)
|
||||
rl_sigaction (sig, ohandler, &dummy);
|
||||
}
|
||||
|
||||
int
|
||||
rl_set_signals ()
|
||||
{
|
||||
sighandler_cxt dummy;
|
||||
SigHandler *oh;
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
static int sigmask_set = 0;
|
||||
static sigset_t bset, oset;
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
if (rl_catch_signals && sigmask_set == 0)
|
||||
{
|
||||
sigemptyset (&bset);
|
||||
|
||||
sigaddset (&bset, SIGINT);
|
||||
sigaddset (&bset, SIGTERM);
|
||||
sigaddset (&bset, SIGHUP);
|
||||
#if defined (SIGQUIT)
|
||||
sigaddset (&bset, SIGQUIT);
|
||||
#endif
|
||||
#if defined (SIGALRM)
|
||||
sigaddset (&bset, SIGALRM);
|
||||
#endif
|
||||
#if defined (SIGTSTP)
|
||||
sigaddset (&bset, SIGTSTP);
|
||||
#endif
|
||||
#if defined (SIGTTIN)
|
||||
sigaddset (&bset, SIGTTIN);
|
||||
#endif
|
||||
#if defined (SIGTTOU)
|
||||
sigaddset (&bset, SIGTTOU);
|
||||
#endif
|
||||
sigmask_set = 1;
|
||||
}
|
||||
#endif /* HAVE_POSIX_SIGNALS */
|
||||
|
||||
if (rl_catch_signals && signals_set_flag == 0)
|
||||
{
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigemptyset (&oset);
|
||||
sigprocmask (SIG_BLOCK, &bset, &oset);
|
||||
#endif
|
||||
|
||||
rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
|
||||
rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
|
||||
rl_maybe_set_sighandler (SIGHUP, rl_signal_handler, &old_hup);
|
||||
#if defined (SIGQUIT)
|
||||
rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
|
||||
#endif
|
||||
|
||||
#if defined (SIGALRM)
|
||||
oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
|
||||
if (oh == (SigHandler *)SIG_IGN)
|
||||
rl_sigaction (SIGALRM, &old_alrm, &dummy);
|
||||
#if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
|
||||
/* If the application using readline has already installed a signal
|
||||
handler with SA_RESTART, SIGALRM will cause reads to be restarted
|
||||
automatically, so readline should just get out of the way. Since
|
||||
we tested for SIG_IGN above, we can just test for SIG_DFL here. */
|
||||
if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
|
||||
rl_sigaction (SIGALRM, &old_alrm, &dummy);
|
||||
#endif /* HAVE_POSIX_SIGNALS */
|
||||
#endif /* SIGALRM */
|
||||
|
||||
#if defined (SIGTSTP)
|
||||
rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
|
||||
#endif /* SIGTSTP */
|
||||
|
||||
#if defined (SIGTTOU)
|
||||
rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
|
||||
#endif /* SIGTTOU */
|
||||
|
||||
#if defined (SIGTTIN)
|
||||
rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
|
||||
#endif /* SIGTTIN */
|
||||
|
||||
signals_set_flag = 1;
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (SIGWINCH)
|
||||
if (rl_catch_sigwinch && sigwinch_set_flag == 0)
|
||||
{
|
||||
rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch);
|
||||
sigwinch_set_flag = 1;
|
||||
}
|
||||
#endif /* SIGWINCH */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rl_clear_signals ()
|
||||
{
|
||||
sighandler_cxt dummy;
|
||||
|
||||
if (rl_catch_signals && signals_set_flag == 1)
|
||||
{
|
||||
sigemptyset (&dummy.sa_mask);
|
||||
|
||||
rl_sigaction (SIGINT, &old_int, &dummy);
|
||||
rl_sigaction (SIGTERM, &old_term, &dummy);
|
||||
rl_sigaction (SIGHUP, &old_hup, &dummy);
|
||||
#if defined (SIGQUIT)
|
||||
rl_sigaction (SIGQUIT, &old_quit, &dummy);
|
||||
#endif
|
||||
#if defined (SIGALRM)
|
||||
rl_sigaction (SIGALRM, &old_alrm, &dummy);
|
||||
#endif
|
||||
|
||||
#if defined (SIGTSTP)
|
||||
rl_sigaction (SIGTSTP, &old_tstp, &dummy);
|
||||
#endif /* SIGTSTP */
|
||||
|
||||
#if defined (SIGTTOU)
|
||||
rl_sigaction (SIGTTOU, &old_ttou, &dummy);
|
||||
#endif /* SIGTTOU */
|
||||
|
||||
#if defined (SIGTTIN)
|
||||
rl_sigaction (SIGTTIN, &old_ttin, &dummy);
|
||||
#endif /* SIGTTIN */
|
||||
|
||||
signals_set_flag = 0;
|
||||
}
|
||||
|
||||
#if defined (SIGWINCH)
|
||||
if (rl_catch_sigwinch && sigwinch_set_flag == 1)
|
||||
{
|
||||
sigemptyset (&dummy.sa_mask);
|
||||
rl_sigaction (SIGWINCH, &old_winch, &dummy);
|
||||
sigwinch_set_flag = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Clean up the terminal and readline state after catching a signal, before
|
||||
resending it to the calling application. */
|
||||
void
|
||||
rl_cleanup_after_signal ()
|
||||
{
|
||||
_rl_clean_up_for_exit ();
|
||||
if (rl_deprep_term_function)
|
||||
(*rl_deprep_term_function) ();
|
||||
rl_clear_pending_input ();
|
||||
rl_clear_signals ();
|
||||
}
|
||||
|
||||
/* Reset the terminal and readline state after a signal handler returns. */
|
||||
void
|
||||
rl_reset_after_signal ()
|
||||
{
|
||||
if (rl_prep_term_function)
|
||||
(*rl_prep_term_function) (_rl_meta_flag);
|
||||
rl_set_signals ();
|
||||
}
|
||||
|
||||
/* Free up the readline variable line state for the current line (undo list,
|
||||
any partial history entry, any keyboard macros in progress, and any
|
||||
numeric arguments in process) after catching a signal, before calling
|
||||
rl_cleanup_after_signal(). */
|
||||
void
|
||||
rl_free_line_state ()
|
||||
{
|
||||
register HIST_ENTRY *entry;
|
||||
|
||||
rl_free_undo_list ();
|
||||
|
||||
entry = current_history ();
|
||||
if (entry)
|
||||
entry->data = (char *)NULL;
|
||||
|
||||
_rl_kill_kbd_macro ();
|
||||
rl_clear_message ();
|
||||
_rl_reset_argument ();
|
||||
}
|
||||
|
||||
#endif /* HANDLE_SIGNALS */
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* SIGINT Management */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
static sigset_t sigint_set, sigint_oset;
|
||||
static sigset_t sigwinch_set, sigwinch_oset;
|
||||
#else /* !HAVE_POSIX_SIGNALS */
|
||||
# if defined (HAVE_BSD_SIGNALS)
|
||||
static int sigint_oldmask;
|
||||
static int sigwinch_oldmask;
|
||||
# endif /* HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
static int sigint_blocked;
|
||||
static int sigwinch_blocked;
|
||||
|
||||
/* Cause SIGINT to not be delivered until the corresponding call to
|
||||
release_sigint(). */
|
||||
void
|
||||
_rl_block_sigint ()
|
||||
{
|
||||
if (sigint_blocked)
|
||||
return;
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigemptyset (&sigint_set);
|
||||
sigemptyset (&sigint_oset);
|
||||
sigaddset (&sigint_set, SIGINT);
|
||||
sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset);
|
||||
#else /* !HAVE_POSIX_SIGNALS */
|
||||
# if defined (HAVE_BSD_SIGNALS)
|
||||
sigint_oldmask = sigblock (sigmask (SIGINT));
|
||||
# else /* !HAVE_BSD_SIGNALS */
|
||||
# if defined (HAVE_USG_SIGHOLD)
|
||||
sighold (SIGINT);
|
||||
# endif /* HAVE_USG_SIGHOLD */
|
||||
# endif /* !HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
sigint_blocked = 1;
|
||||
}
|
||||
|
||||
/* Allow SIGINT to be delivered. */
|
||||
void
|
||||
_rl_release_sigint ()
|
||||
{
|
||||
if (sigint_blocked == 0)
|
||||
return;
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL);
|
||||
#else
|
||||
# if defined (HAVE_BSD_SIGNALS)
|
||||
sigsetmask (sigint_oldmask);
|
||||
# else /* !HAVE_BSD_SIGNALS */
|
||||
# if defined (HAVE_USG_SIGHOLD)
|
||||
sigrelse (SIGINT);
|
||||
# endif /* HAVE_USG_SIGHOLD */
|
||||
# endif /* !HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
sigint_blocked = 0;
|
||||
}
|
||||
|
||||
/* Cause SIGWINCH to not be delivered until the corresponding call to
|
||||
release_sigwinch(). */
|
||||
void
|
||||
_rl_block_sigwinch ()
|
||||
{
|
||||
if (sigwinch_blocked)
|
||||
return;
|
||||
|
||||
#if defined (SIGWINCH)
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigemptyset (&sigwinch_set);
|
||||
sigemptyset (&sigwinch_oset);
|
||||
sigaddset (&sigwinch_set, SIGWINCH);
|
||||
sigprocmask (SIG_BLOCK, &sigwinch_set, &sigwinch_oset);
|
||||
#else /* !HAVE_POSIX_SIGNALS */
|
||||
# if defined (HAVE_BSD_SIGNALS)
|
||||
sigwinch_oldmask = sigblock (sigmask (SIGWINCH));
|
||||
# else /* !HAVE_BSD_SIGNALS */
|
||||
# if defined (HAVE_USG_SIGHOLD)
|
||||
sighold (SIGWINCH);
|
||||
# endif /* HAVE_USG_SIGHOLD */
|
||||
# endif /* !HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
#endif /* SIGWINCH */
|
||||
|
||||
sigwinch_blocked = 1;
|
||||
}
|
||||
|
||||
/* Allow SIGWINCH to be delivered. */
|
||||
void
|
||||
_rl_release_sigwinch ()
|
||||
{
|
||||
if (sigwinch_blocked == 0)
|
||||
return;
|
||||
|
||||
#if defined (SIGWINCH)
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigprocmask (SIG_SETMASK, &sigwinch_oset, (sigset_t *)NULL);
|
||||
#else
|
||||
# if defined (HAVE_BSD_SIGNALS)
|
||||
sigsetmask (sigwinch_oldmask);
|
||||
# else /* !HAVE_BSD_SIGNALS */
|
||||
# if defined (HAVE_USG_SIGHOLD)
|
||||
sigrelse (SIGWINCH);
|
||||
# endif /* HAVE_USG_SIGHOLD */
|
||||
# endif /* !HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
#endif /* SIGWINCH */
|
||||
|
||||
sigwinch_blocked = 0;
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Echoing special control characters */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
void
|
||||
rl_echo_signal_char (sig)
|
||||
int sig;
|
||||
{
|
||||
char cstr[3];
|
||||
int cslen, c;
|
||||
|
||||
if (_rl_echoctl == 0 || _rl_echo_control_chars == 0)
|
||||
return;
|
||||
|
||||
switch (sig)
|
||||
{
|
||||
case SIGINT: c = _rl_intr_char; break;
|
||||
#if defined (SIGQUIT)
|
||||
case SIGQUIT: c = _rl_quit_char; break;
|
||||
#endif
|
||||
#if defined (SIGTSTP)
|
||||
case SIGTSTP: c = _rl_susp_char; break;
|
||||
#endif
|
||||
default: return;
|
||||
}
|
||||
|
||||
if (CTRL_CHAR (c) || c == RUBOUT)
|
||||
{
|
||||
cstr[0] = '^';
|
||||
cstr[1] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
|
||||
cstr[cslen = 2] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
cstr[0] = c;
|
||||
cstr[cslen = 1] = '\0';
|
||||
}
|
||||
|
||||
_rl_output_some_chars (cstr, cslen);
|
||||
}
|
||||
@@ -1,356 +0,0 @@
|
||||
/* getcwd.c -- get pathname of current directory */
|
||||
|
||||
/* Copyright (C) 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 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_GETCWD)
|
||||
|
||||
#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
|
||||
#pragma alloca
|
||||
#endif /* _AIX && RISC6000 && !__GNUC__ */
|
||||
|
||||
#if defined (__QNX__)
|
||||
# undef HAVE_LSTAT
|
||||
#endif
|
||||
|
||||
#include <bashtypes.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined (HAVE_LIMITS_H)
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <posixdir.h>
|
||||
#include <posixstat.h>
|
||||
#include <maxpath.h>
|
||||
#include <memalloc.h>
|
||||
|
||||
#include <bashansi.h>
|
||||
|
||||
#if defined (BROKEN_DIRENT_D_INO)
|
||||
# include "command.h"
|
||||
# include "general.h"
|
||||
# include "externs.h"
|
||||
#endif
|
||||
|
||||
#include <xmalloc.h>
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
#if !defined (HAVE_LSTAT)
|
||||
# define lstat stat
|
||||
#endif
|
||||
|
||||
#if !defined (NULL)
|
||||
# define NULL 0
|
||||
#endif
|
||||
|
||||
/* If the d_fileno member of a struct dirent doesn't return anything useful,
|
||||
we need to check inode number equivalence the hard way. Return 1 if
|
||||
the inode corresponding to PATH/DIR is identical to THISINO. */
|
||||
#if defined (BROKEN_DIRENT_D_INO)
|
||||
static int
|
||||
_path_checkino (dotp, name, thisino)
|
||||
char *dotp;
|
||||
char *name;
|
||||
ino_t thisino;
|
||||
{
|
||||
char *fullpath;
|
||||
int r, e;
|
||||
struct stat st;
|
||||
|
||||
e = errno;
|
||||
fullpath = sh_makepath (dotp, name, MP_RMDOT);
|
||||
if (stat (fullpath, &st) < 0)
|
||||
{
|
||||
errno = e;
|
||||
return 0;
|
||||
}
|
||||
free (fullpath);
|
||||
errno = e;
|
||||
return (st.st_ino == thisino);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the pathname of the current working directory,
|
||||
and put it in SIZE bytes of BUF. Returns NULL if the
|
||||
directory couldn't be determined or SIZE was too small.
|
||||
If successful, returns BUF. In GNU, if BUF is NULL,
|
||||
an array is allocated with `malloc'; the array is SIZE
|
||||
bytes long, unless SIZE <= 0, in which case it is as
|
||||
big as necessary. */
|
||||
#if defined (__STDC__)
|
||||
char *
|
||||
getcwd (char *buf, size_t size)
|
||||
#else /* !__STDC__ */
|
||||
char *
|
||||
getcwd (buf, size)
|
||||
char *buf;
|
||||
size_t size;
|
||||
#endif /* !__STDC__ */
|
||||
{
|
||||
static const char dots[]
|
||||
= "../../../../../../../../../../../../../../../../../../../../../../../\
|
||||
../../../../../../../../../../../../../../../../../../../../../../../../../../\
|
||||
../../../../../../../../../../../../../../../../../../../../../../../../../..";
|
||||
const char *dotp, *dotlist;
|
||||
size_t dotsize;
|
||||
dev_t rootdev, thisdev;
|
||||
ino_t rootino, thisino;
|
||||
char path[PATH_MAX + 1];
|
||||
register char *pathp;
|
||||
char *pathbuf;
|
||||
size_t pathsize;
|
||||
struct stat st;
|
||||
int saved_errno;
|
||||
|
||||
if (buf != NULL && size == 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
pathsize = sizeof (path);
|
||||
pathp = &path[pathsize];
|
||||
*--pathp = '\0';
|
||||
pathbuf = path;
|
||||
|
||||
if (stat (".", &st) < 0)
|
||||
return ((char *)NULL);
|
||||
thisdev = st.st_dev;
|
||||
thisino = st.st_ino;
|
||||
|
||||
if (stat ("/", &st) < 0)
|
||||
return ((char *)NULL);
|
||||
rootdev = st.st_dev;
|
||||
rootino = st.st_ino;
|
||||
|
||||
saved_errno = 0;
|
||||
|
||||
dotsize = sizeof (dots) - 1;
|
||||
dotp = &dots[sizeof (dots)];
|
||||
dotlist = dots;
|
||||
while (!(thisdev == rootdev && thisino == rootino))
|
||||
{
|
||||
register DIR *dirstream;
|
||||
register struct dirent *d;
|
||||
dev_t dotdev;
|
||||
ino_t dotino;
|
||||
char mount_point;
|
||||
int namlen;
|
||||
|
||||
/* Look at the parent directory. */
|
||||
if (dotp == dotlist)
|
||||
{
|
||||
/* My, what a deep directory tree you have, Grandma. */
|
||||
char *new;
|
||||
if (dotlist == dots)
|
||||
{
|
||||
new = (char *)malloc (dotsize * 2 + 1);
|
||||
if (new == NULL)
|
||||
goto lose;
|
||||
memcpy (new, dots, dotsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
new = (char *)realloc ((PTR_T) dotlist, dotsize * 2 + 1);
|
||||
if (new == NULL)
|
||||
goto lose;
|
||||
}
|
||||
memcpy (&new[dotsize], new, dotsize);
|
||||
dotp = &new[dotsize];
|
||||
dotsize *= 2;
|
||||
new[dotsize] = '\0';
|
||||
dotlist = new;
|
||||
}
|
||||
|
||||
dotp -= 3;
|
||||
|
||||
/* Figure out if this directory is a mount point. */
|
||||
if (stat (dotp, &st) < 0)
|
||||
goto lose;
|
||||
dotdev = st.st_dev;
|
||||
dotino = st.st_ino;
|
||||
mount_point = dotdev != thisdev;
|
||||
|
||||
/* Search for the last directory. */
|
||||
dirstream = opendir (dotp);
|
||||
if (dirstream == NULL)
|
||||
goto lose;
|
||||
while ((d = readdir (dirstream)) != NULL)
|
||||
{
|
||||
if (d->d_name[0] == '.' &&
|
||||
(d->d_name[1] == '\0' ||
|
||||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
|
||||
continue;
|
||||
#if !defined (BROKEN_DIRENT_D_INO)
|
||||
if (mount_point || d->d_fileno == thisino)
|
||||
#else
|
||||
if (mount_point || _path_checkino (dotp, d->d_name, thisino))
|
||||
#endif
|
||||
{
|
||||
char *name;
|
||||
|
||||
namlen = D_NAMLEN(d);
|
||||
name = (char *)
|
||||
alloca (dotlist + dotsize - dotp + 1 + namlen + 1);
|
||||
memcpy (name, dotp, dotlist + dotsize - dotp);
|
||||
name[dotlist + dotsize - dotp] = '/';
|
||||
memcpy (&name[dotlist + dotsize - dotp + 1],
|
||||
d->d_name, namlen + 1);
|
||||
if (lstat (name, &st) < 0)
|
||||
{
|
||||
#if 0
|
||||
int save = errno;
|
||||
(void) closedir (dirstream);
|
||||
errno = save;
|
||||
goto lose;
|
||||
#else
|
||||
saved_errno = errno;
|
||||
#endif
|
||||
}
|
||||
if (st.st_dev == thisdev && st.st_ino == thisino)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (d == NULL)
|
||||
{
|
||||
#if 0
|
||||
int save = errno;
|
||||
#else
|
||||
int save = errno ? errno : saved_errno;
|
||||
#endif
|
||||
(void) closedir (dirstream);
|
||||
errno = save;
|
||||
goto lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t space;
|
||||
|
||||
while ((space = pathp - pathbuf) <= namlen)
|
||||
{
|
||||
char *new;
|
||||
|
||||
if (pathbuf == path)
|
||||
{
|
||||
new = (char *)malloc (pathsize * 2);
|
||||
if (!new)
|
||||
goto lose;
|
||||
}
|
||||
else
|
||||
{
|
||||
new = (char *)realloc ((PTR_T) pathbuf, (pathsize * 2));
|
||||
if (!new)
|
||||
goto lose;
|
||||
pathp = new + space;
|
||||
}
|
||||
(void) memcpy (new + pathsize + space, pathp, pathsize - space);
|
||||
pathp = new + pathsize + space;
|
||||
pathbuf = new;
|
||||
pathsize *= 2;
|
||||
}
|
||||
|
||||
pathp -= namlen;
|
||||
(void) memcpy (pathp, d->d_name, namlen);
|
||||
*--pathp = '/';
|
||||
(void) closedir (dirstream);
|
||||
}
|
||||
|
||||
thisdev = dotdev;
|
||||
thisino = dotino;
|
||||
}
|
||||
|
||||
if (pathp == &path[sizeof(path) - 1])
|
||||
*--pathp = '/';
|
||||
|
||||
if (dotlist != dots)
|
||||
free ((PTR_T) dotlist);
|
||||
|
||||
{
|
||||
size_t len = pathbuf + pathsize - pathp;
|
||||
if (buf == NULL && size <= 0)
|
||||
size = len;
|
||||
|
||||
if ((size_t) size < len)
|
||||
{
|
||||
errno = ERANGE;
|
||||
goto lose2;
|
||||
}
|
||||
if (buf == NULL)
|
||||
{
|
||||
buf = (char *) malloc (size);
|
||||
if (buf == NULL)
|
||||
goto lose2;
|
||||
}
|
||||
|
||||
(void) memcpy((PTR_T) buf, (PTR_T) pathp, len);
|
||||
}
|
||||
|
||||
if (pathbuf != path)
|
||||
free (pathbuf);
|
||||
|
||||
return (buf);
|
||||
|
||||
lose:
|
||||
if ((dotlist != dots) && dotlist)
|
||||
{
|
||||
int e = errno;
|
||||
free ((PTR_T) dotlist);
|
||||
errno = e;
|
||||
}
|
||||
|
||||
lose2:
|
||||
if ((pathbuf != path) && pathbuf)
|
||||
{
|
||||
int e = errno;
|
||||
free ((PTR_T) pathbuf);
|
||||
errno = e;
|
||||
}
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
#if defined (TEST)
|
||||
# include <stdio.h>
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char b[PATH_MAX];
|
||||
|
||||
if (getcwd(b, sizeof(b)))
|
||||
{
|
||||
printf ("%s\n", b);
|
||||
exit (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
perror ("cwd: getcwd");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
#endif /* TEST */
|
||||
#endif /* !HAVE_GETCWD */
|
||||
@@ -1,78 +0,0 @@
|
||||
/* mbschr.c - strchr(3) that handles multibyte characters. */
|
||||
|
||||
/* Copyright (C) 2002 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>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "bashansi.h"
|
||||
#include "shmbutil.h"
|
||||
|
||||
#undef mbschr
|
||||
|
||||
/* In some locales, the non-first byte of some multibyte characters have
|
||||
the same value as some ascii character. Faced with these strings, a
|
||||
legacy strchr() might return the wrong value. */
|
||||
|
||||
char *
|
||||
#if defined (PROTOTYPES)
|
||||
mbschr (const char *s, int c)
|
||||
#else
|
||||
mbschr (s, c)
|
||||
const char *s;
|
||||
int c;
|
||||
#endif
|
||||
{
|
||||
#if HANDLE_MULTIBYTE
|
||||
char *pos;
|
||||
mbstate_t state;
|
||||
size_t strlength, mblength;
|
||||
|
||||
/* The locale encodings with said weird property are BIG5, BIG5-HKSCS,
|
||||
GBK, GB18030, SHIFT_JIS, and JOHAB. They exhibit the problem only
|
||||
when c >= 0x30. We can therefore use the faster bytewise search if
|
||||
c <= 0x30. */
|
||||
if ((unsigned char)c >= '0' && MB_CUR_MAX > 1)
|
||||
{
|
||||
pos = (char *)s;
|
||||
memset (&state, '\0', sizeof(mbstate_t));
|
||||
strlength = strlen (s);
|
||||
|
||||
while (strlength > 0)
|
||||
{
|
||||
mblength = mbrlen (pos, strlength, &state);
|
||||
if (mblength == (size_t)-2 || mblength == (size_t)-1 || mblength == (size_t)0)
|
||||
mblength = 1;
|
||||
|
||||
if (mblength == 1 && c == (unsigned char)*pos)
|
||||
return pos;
|
||||
|
||||
strlength -= mblength;
|
||||
pos += mblength;
|
||||
}
|
||||
|
||||
return ((char *)NULL);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
return (strchr (s, c));
|
||||
}
|
||||
@@ -1,340 +0,0 @@
|
||||
/* unicode.c - functions to convert unicode characters */
|
||||
|
||||
/* Copyright (C) 2010-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 (HANDLE_MULTIBYTE)
|
||||
|
||||
#include <stdc.h>
|
||||
#include <wchar.h>
|
||||
#include <bashansi.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <limits.h>
|
||||
|
||||
#if HAVE_ICONV
|
||||
# include <iconv.h>
|
||||
#endif
|
||||
|
||||
#include <xmalloc.h>
|
||||
|
||||
#ifndef USHORT_MAX
|
||||
# ifdef USHRT_MAX
|
||||
# define USHORT_MAX USHRT_MAX
|
||||
# else
|
||||
# define USHORT_MAX ((unsigned short) ~(unsigned short)0)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined (STREQ)
|
||||
# define STREQ(a, b) ((a)[0] == (b)[0] && strcmp ((a), (b)) == 0)
|
||||
#endif /* !STREQ */
|
||||
|
||||
#if defined (HAVE_LOCALE_CHARSET)
|
||||
extern const char *locale_charset __P((void));
|
||||
#else
|
||||
extern char *get_locale_var __P((char *));
|
||||
#endif
|
||||
|
||||
static int u32init = 0;
|
||||
static int utf8locale = 0;
|
||||
#if defined (HAVE_ICONV)
|
||||
static iconv_t localconv;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LOCALE_CHARSET
|
||||
static char charsetbuf[40];
|
||||
|
||||
static char *
|
||||
stub_charset ()
|
||||
{
|
||||
char *locale, *s, *t;
|
||||
|
||||
locale = get_locale_var ("LC_CTYPE");
|
||||
if (locale == 0 || *locale == 0)
|
||||
{
|
||||
strcpy (charsetbuf, "ASCII");
|
||||
return charsetbuf;
|
||||
}
|
||||
s = strrchr (locale, '.');
|
||||
if (s)
|
||||
{
|
||||
strcpy (charsetbuf, s+1);
|
||||
t = strchr (charsetbuf, '@');
|
||||
if (t)
|
||||
*t = 0;
|
||||
return charsetbuf;
|
||||
}
|
||||
strcpy (charsetbuf, locale);
|
||||
return charsetbuf;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
u32reset ()
|
||||
{
|
||||
#if defined (HAVE_ICONV)
|
||||
if (u32init && localconv != (iconv_t)-1)
|
||||
{
|
||||
iconv_close (localconv);
|
||||
localconv = (iconv_t)-1;
|
||||
}
|
||||
#endif
|
||||
u32init = 0;
|
||||
utf8locale = 0;
|
||||
}
|
||||
|
||||
/* u32toascii ? */
|
||||
int
|
||||
u32tochar (x, s)
|
||||
unsigned long x;
|
||||
char *s;
|
||||
{
|
||||
int l;
|
||||
|
||||
l = (x <= UCHAR_MAX) ? 1 : ((x <= USHORT_MAX) ? 2 : 4);
|
||||
|
||||
if (x <= UCHAR_MAX)
|
||||
s[0] = x & 0xFF;
|
||||
else if (x <= USHORT_MAX) /* assume unsigned short = 16 bits */
|
||||
{
|
||||
s[0] = (x >> 8) & 0xFF;
|
||||
s[1] = x & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
s[0] = (x >> 24) & 0xFF;
|
||||
s[1] = (x >> 16) & 0xFF;
|
||||
s[2] = (x >> 8) & 0xFF;
|
||||
s[3] = x & 0xFF;
|
||||
}
|
||||
s[l] = '\0';
|
||||
return l;
|
||||
}
|
||||
|
||||
int
|
||||
u32tocesc (wc, s)
|
||||
u_bits32_t wc;
|
||||
char *s;
|
||||
{
|
||||
int l;
|
||||
|
||||
if (wc < 0x10000)
|
||||
l = sprintf (s, "\\u%04X", wc);
|
||||
else
|
||||
l = sprintf (s, "\\u%08X", wc);
|
||||
return l;
|
||||
}
|
||||
|
||||
/* Convert unsigned 32-bit int to utf-8 character string */
|
||||
int
|
||||
u32toutf8 (wc, s)
|
||||
u_bits32_t wc;
|
||||
char *s;
|
||||
{
|
||||
int l;
|
||||
|
||||
if (wc < 0x0080)
|
||||
{
|
||||
s[0] = (char)wc;
|
||||
l = 1;
|
||||
}
|
||||
else if (wc < 0x0800)
|
||||
{
|
||||
s[0] = (wc >> 6) | 0xc0;
|
||||
s[1] = (wc & 0x3f) | 0x80;
|
||||
l = 2;
|
||||
}
|
||||
else if (wc < 0x10000)
|
||||
{
|
||||
/* Technically, we could return 0 here if 0xd800 <= wc <= 0x0dfff */
|
||||
s[0] = (wc >> 12) | 0xe0;
|
||||
s[1] = ((wc >> 6) & 0x3f) | 0x80;
|
||||
s[2] = (wc & 0x3f) | 0x80;
|
||||
l = 3;
|
||||
}
|
||||
else if (wc < 0x200000)
|
||||
{
|
||||
s[0] = (wc >> 18) | 0xf0;
|
||||
s[1] = ((wc >> 12) & 0x3f) | 0x80;
|
||||
s[2] = ((wc >> 6) & 0x3f) | 0x80;
|
||||
s[3] = (wc & 0x3f) | 0x80;
|
||||
l = 4;
|
||||
}
|
||||
/* Strictly speaking, UTF-8 doesn't have characters longer than 4 bytes */
|
||||
else if (wc < 0x04000000)
|
||||
{
|
||||
s[0] = (wc >> 24) | 0xf8;
|
||||
s[1] = ((wc >> 18) & 0x3f) | 0x80;
|
||||
s[2] = ((wc >> 12) & 0x3f) | 0x80;
|
||||
s[3] = ((wc >> 6) & 0x3f) | 0x80;
|
||||
s[4] = (wc & 0x3f) | 0x80;
|
||||
l = 5;
|
||||
}
|
||||
else if (wc < 0x080000000)
|
||||
{
|
||||
s[0] = (wc >> 30) | 0xf8;
|
||||
s[1] = ((wc >> 24) & 0x3f) | 0x80;
|
||||
s[2] = ((wc >> 18) & 0x3f) | 0x80;
|
||||
s[3] = ((wc >> 12) & 0x3f) | 0x80;
|
||||
s[4] = ((wc >> 6) & 0x3f) | 0x80;
|
||||
s[5] = (wc & 0x3f) | 0x80;
|
||||
l = 6;
|
||||
}
|
||||
else
|
||||
l = 0;
|
||||
|
||||
s[l] = '\0';
|
||||
return l;
|
||||
}
|
||||
|
||||
/* Convert a 32-bit unsigned int (unicode) to a UTF-16 string. Rarely used,
|
||||
only if sizeof(wchar_t) == 2. */
|
||||
int
|
||||
u32toutf16 (c, s)
|
||||
u_bits32_t c;
|
||||
unsigned short *s;
|
||||
{
|
||||
int l;
|
||||
|
||||
l = 0;
|
||||
if (c < 0x0d800)
|
||||
{
|
||||
s[0] = (unsigned short) (c & 0xFFFF);
|
||||
l = 1;
|
||||
}
|
||||
else if (c >= 0x0e000 && c <= 0x010ffff)
|
||||
{
|
||||
c -= 0x010000;
|
||||
s[0] = (unsigned short)((c >> 10) + 0xd800);
|
||||
s[1] = (unsigned short)((c & 0x3ff) + 0xdc00);
|
||||
l = 2;
|
||||
}
|
||||
s[l] = 0;
|
||||
return l;
|
||||
}
|
||||
|
||||
/* convert a single unicode-32 character into a multibyte string and put the
|
||||
result in S, which must be large enough (at least MB_LEN_MAX bytes) */
|
||||
int
|
||||
u32cconv (c, s)
|
||||
unsigned long c;
|
||||
char *s;
|
||||
{
|
||||
wchar_t wc;
|
||||
wchar_t ws[3];
|
||||
int n;
|
||||
#if HAVE_ICONV
|
||||
const char *charset;
|
||||
char obuf[25], *optr;
|
||||
size_t obytesleft;
|
||||
const char *iptr;
|
||||
size_t sn;
|
||||
#endif
|
||||
|
||||
#if __STDC_ISO_10646__
|
||||
wc = c;
|
||||
if (sizeof (wchar_t) == 4 && c <= 0x7fffffff)
|
||||
n = wctomb (s, wc);
|
||||
else if (sizeof (wchar_t) == 2 && c <= 0x10ffff && u32toutf16 (c, ws))
|
||||
n = wcstombs (s, ws, MB_LEN_MAX);
|
||||
else
|
||||
n = -1;
|
||||
if (n != -1)
|
||||
return n;
|
||||
#endif
|
||||
|
||||
#if HAVE_NL_LANGINFO
|
||||
codeset = nl_langinfo (CODESET);
|
||||
if (STREQ (codeset, "UTF-8"))
|
||||
{
|
||||
n = u32toutf8 (c, s);
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_ICONV
|
||||
/* this is mostly from coreutils-8.5/lib/unicodeio.c */
|
||||
if (u32init == 0)
|
||||
{
|
||||
# if HAVE_LOCALE_CHARSET
|
||||
charset = locale_charset (); /* XXX - fix later */
|
||||
# else
|
||||
charset = stub_charset ();
|
||||
# endif
|
||||
if (STREQ (charset, "UTF-8"))
|
||||
utf8locale = 1;
|
||||
else
|
||||
{
|
||||
localconv = iconv_open (charset, "UTF-8");
|
||||
if (localconv == (iconv_t)-1)
|
||||
/* We assume ASCII when presented with an unknown encoding. */
|
||||
localconv = iconv_open ("ASCII", "UTF-8");
|
||||
}
|
||||
u32init = 1;
|
||||
}
|
||||
|
||||
/* If we have a UTF-8 locale, convert to UTF-8 and return converted value. */
|
||||
n = u32toutf8 (c, s);
|
||||
if (utf8locale)
|
||||
return n;
|
||||
|
||||
/* If the conversion is not supported, even the ASCII requested above, we
|
||||
bail now. Currently we return the UTF-8 conversion. We could return
|
||||
u32cesc(). */
|
||||
if (localconv == (iconv_t)-1)
|
||||
return n;
|
||||
|
||||
optr = obuf;
|
||||
obytesleft = sizeof (obuf);
|
||||
iptr = s;
|
||||
sn = n;
|
||||
|
||||
iconv (localconv, NULL, NULL, NULL, NULL);
|
||||
|
||||
if (iconv (localconv, (ICONV_CONST char **)&iptr, &sn, &optr, &obytesleft) == (size_t)-1)
|
||||
{
|
||||
#if 1
|
||||
/* You get ISO C99 escape sequences if iconv fails */
|
||||
n = u32tocesc (c, s);
|
||||
#else
|
||||
/* You get UTF-8 if iconv fails */
|
||||
#endif
|
||||
return n;
|
||||
}
|
||||
|
||||
*optr = '\0';
|
||||
|
||||
/* number of chars to be copied is optr - obuf if we want to do bounds
|
||||
checking */
|
||||
strcpy (s, obuf);
|
||||
return (optr - obuf);
|
||||
#endif /* HAVE_ICONV */
|
||||
|
||||
n = u32tocesc (c, s); /* fallback is ISO C99 escape sequences */
|
||||
return n;
|
||||
}
|
||||
#else
|
||||
void
|
||||
u32reset ()
|
||||
{
|
||||
}
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
-174
@@ -1,174 +0,0 @@
|
||||
/* zread - read data from file descriptor into buffer with retries */
|
||||
|
||||
/* Copyright (C) 1999-2002 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>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_CUR
|
||||
# define SEEK_CUR 1
|
||||
#endif
|
||||
|
||||
/* Read LEN bytes from FD into BUF. Retry the read on EINTR. Any other
|
||||
error causes the loop to break. */
|
||||
ssize_t
|
||||
zread (fd, buf, len)
|
||||
int fd;
|
||||
char *buf;
|
||||
size_t len;
|
||||
{
|
||||
ssize_t r;
|
||||
|
||||
while ((r = read (fd, buf, len)) < 0 && errno == EINTR)
|
||||
;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Read LEN bytes from FD into BUF. Retry the read on EINTR, up to three
|
||||
interrupts. Any other error causes the loop to break. */
|
||||
|
||||
#ifdef NUM_INTR
|
||||
# undef NUM_INTR
|
||||
#endif
|
||||
#define NUM_INTR 3
|
||||
|
||||
ssize_t
|
||||
zreadretry (fd, buf, len)
|
||||
int fd;
|
||||
char *buf;
|
||||
size_t len;
|
||||
{
|
||||
ssize_t r;
|
||||
int nintr;
|
||||
|
||||
for (nintr = 0; ; )
|
||||
{
|
||||
r = read (fd, buf, len);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
if (r == -1 && errno == EINTR)
|
||||
{
|
||||
if (++nintr >= NUM_INTR)
|
||||
return -1;
|
||||
continue;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call read(2) and allow it to be interrupted. Just a stub for now. */
|
||||
ssize_t
|
||||
zreadintr (fd, buf, len)
|
||||
int fd;
|
||||
char *buf;
|
||||
size_t len;
|
||||
{
|
||||
return (read (fd, buf, len));
|
||||
}
|
||||
|
||||
/* Read one character from FD and return it in CP. Return values are as
|
||||
in read(2). This does some local buffering to avoid many one-character
|
||||
calls to read(2), like those the `read' builtin performs. */
|
||||
|
||||
static char lbuf[128];
|
||||
static size_t lind, lused;
|
||||
|
||||
ssize_t
|
||||
zreadc (fd, cp)
|
||||
int fd;
|
||||
char *cp;
|
||||
{
|
||||
ssize_t nr;
|
||||
|
||||
if (lind == lused || lused == 0)
|
||||
{
|
||||
nr = zread (fd, lbuf, sizeof (lbuf));
|
||||
lind = 0;
|
||||
if (nr <= 0)
|
||||
{
|
||||
lused = 0;
|
||||
return nr;
|
||||
}
|
||||
lused = nr;
|
||||
}
|
||||
if (cp)
|
||||
*cp = lbuf[lind++];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Don't mix calls to zreadc and zreadcintr in the same function, since they
|
||||
use the same local buffer. */
|
||||
ssize_t
|
||||
zreadcintr (fd, cp)
|
||||
int fd;
|
||||
char *cp;
|
||||
{
|
||||
ssize_t nr;
|
||||
|
||||
if (lind == lused || lused == 0)
|
||||
{
|
||||
nr = zreadintr (fd, lbuf, sizeof (lbuf));
|
||||
lind = 0;
|
||||
if (nr <= 0)
|
||||
{
|
||||
lused = 0;
|
||||
return nr;
|
||||
}
|
||||
lused = nr;
|
||||
}
|
||||
if (cp)
|
||||
*cp = lbuf[lind++];
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
zreset ()
|
||||
{
|
||||
lind = lused = 0;
|
||||
}
|
||||
|
||||
/* Sync the seek pointer for FD so that the kernel's idea of the last char
|
||||
read is the last char returned by zreadc. */
|
||||
void
|
||||
zsyncfd (fd)
|
||||
int fd;
|
||||
{
|
||||
off_t off, r;
|
||||
|
||||
off = lused - lind;
|
||||
r = 0;
|
||||
if (off > 0)
|
||||
r = lseek (fd, -off, SEEK_CUR);
|
||||
if (r < 0)
|
||||
itrace("zsyncfd: lseek (-%d) returns < 0: %s", off, strerror (errno));
|
||||
|
||||
if (r != -1)
|
||||
lused = lind = 0;
|
||||
}
|
||||
@@ -1,954 +0,0 @@
|
||||
/* nojobs.c - functions that make children, remember them, and handle their termination. */
|
||||
|
||||
/* This file works under BSD, System V, minix, and Posix systems. It does
|
||||
not implement job control. */
|
||||
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "bashtypes.h"
|
||||
#include "filecntl.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined (BUFFERED_INPUT)
|
||||
# include "input.h"
|
||||
#endif
|
||||
|
||||
/* Need to include this up here for *_TTY_DRIVER definitions. */
|
||||
#include "shtty.h"
|
||||
|
||||
#include "bashintl.h"
|
||||
|
||||
#include "shell.h"
|
||||
#include "jobs.h"
|
||||
#include "execute_cmd.h"
|
||||
|
||||
#include "builtins/builtext.h" /* for wait_builtin */
|
||||
|
||||
#define DEFAULT_CHILD_MAX 32
|
||||
|
||||
#if defined (_POSIX_VERSION) || !defined (HAVE_KILLPG)
|
||||
# define killpg(pg, sig) kill(-(pg),(sig))
|
||||
#endif /* USG || _POSIX_VERSION */
|
||||
|
||||
#if !defined (HAVE_SIGINTERRUPT) && !defined (HAVE_POSIX_SIGNALS)
|
||||
# define siginterrupt(sig, code)
|
||||
#endif /* !HAVE_SIGINTERRUPT && !HAVE_POSIX_SIGNALS */
|
||||
|
||||
#if defined (HAVE_WAITPID)
|
||||
# define WAITPID(pid, statusp, options) waitpid (pid, statusp, options)
|
||||
#else
|
||||
# define WAITPID(pid, statusp, options) wait (statusp)
|
||||
#endif /* !HAVE_WAITPID */
|
||||
|
||||
/* Return the fd from which we are actually getting input. */
|
||||
#define input_tty() (shell_tty != -1) ? shell_tty : fileno (stderr)
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
extern int interactive, interactive_shell, login_shell;
|
||||
extern int subshell_environment;
|
||||
extern int last_command_exit_value, last_command_exit_signal;
|
||||
extern int interrupt_immediately;
|
||||
extern sh_builtin_func_t *this_shell_builtin;
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
extern sigset_t top_level_mask;
|
||||
#endif
|
||||
extern procenv_t wait_intr_buf;
|
||||
extern int wait_signal_received;
|
||||
|
||||
pid_t last_made_pid = NO_PID;
|
||||
pid_t last_asynchronous_pid = NO_PID;
|
||||
|
||||
/* Call this when you start making children. */
|
||||
int already_making_children = 0;
|
||||
|
||||
/* The controlling tty for this shell. */
|
||||
int shell_tty = -1;
|
||||
|
||||
/* If this is non-zero, $LINES and $COLUMNS are reset after every process
|
||||
exits from get_tty_state(). */
|
||||
int check_window_size;
|
||||
|
||||
/* STATUS and FLAGS are only valid if pid != NO_PID
|
||||
STATUS is only valid if (flags & PROC_RUNNING) == 0 */
|
||||
struct proc_status {
|
||||
pid_t pid;
|
||||
int status; /* Exit status of PID or 128 + fatal signal number */
|
||||
int flags;
|
||||
};
|
||||
|
||||
/* Values for proc_status.flags */
|
||||
#define PROC_RUNNING 0x01
|
||||
#define PROC_NOTIFIED 0x02
|
||||
#define PROC_ASYNC 0x04
|
||||
#define PROC_SIGNALED 0x10
|
||||
|
||||
/* Return values from find_status_by_pid */
|
||||
#define PROC_BAD -1
|
||||
#define PROC_STILL_ALIVE -2
|
||||
|
||||
static struct proc_status *pid_list = (struct proc_status *)NULL;
|
||||
static int pid_list_size;
|
||||
static int wait_sigint_received;
|
||||
|
||||
static long child_max = -1L;
|
||||
|
||||
static void alloc_pid_list __P((void));
|
||||
static int find_proc_slot __P((void));
|
||||
static int find_index_by_pid __P((pid_t));
|
||||
static int find_status_by_pid __P((pid_t));
|
||||
static int process_exit_status __P((WAIT));
|
||||
static int find_termsig_by_pid __P((pid_t));
|
||||
static int get_termsig __P((WAIT));
|
||||
static void set_pid_status __P((pid_t, WAIT));
|
||||
static void set_pid_flags __P((pid_t, int));
|
||||
static void unset_pid_flags __P((pid_t, int));
|
||||
static int get_pid_flags __P((pid_t));
|
||||
static void add_pid __P((pid_t, int));
|
||||
static void mark_dead_jobs_as_notified __P((int));
|
||||
|
||||
static sighandler wait_sigint_handler __P((int));
|
||||
static char *j_strsignal __P((int));
|
||||
|
||||
#if defined (HAVE_WAITPID)
|
||||
static void reap_zombie_children __P((void));
|
||||
#endif
|
||||
|
||||
#if !defined (HAVE_SIGINTERRUPT) && defined (HAVE_POSIX_SIGNALS)
|
||||
static int siginterrupt __P((int, int));
|
||||
#endif
|
||||
|
||||
static void restore_sigint_handler __P((void));
|
||||
|
||||
/* Allocate new, or grow existing PID_LIST. */
|
||||
static void
|
||||
alloc_pid_list ()
|
||||
{
|
||||
register int i;
|
||||
int old = pid_list_size;
|
||||
|
||||
pid_list_size += 10;
|
||||
pid_list = (struct proc_status *)xrealloc (pid_list, pid_list_size * sizeof (struct proc_status));
|
||||
|
||||
/* None of the newly allocated slots have process id's yet. */
|
||||
for (i = old; i < pid_list_size; i++)
|
||||
pid_list[i].pid = NO_PID;
|
||||
}
|
||||
|
||||
/* Return the offset within the PID_LIST array of an empty slot. This can
|
||||
create new slots if all of the existing slots are taken. */
|
||||
static int
|
||||
find_proc_slot ()
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < pid_list_size; i++)
|
||||
if (pid_list[i].pid == NO_PID)
|
||||
return (i);
|
||||
|
||||
if (i == pid_list_size)
|
||||
alloc_pid_list ();
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
/* Return the offset within the PID_LIST array of a slot containing PID,
|
||||
or the value NO_PID if the pid wasn't found. */
|
||||
static int
|
||||
find_index_by_pid (pid)
|
||||
pid_t pid;
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < pid_list_size; i++)
|
||||
if (pid_list[i].pid == pid)
|
||||
return (i);
|
||||
|
||||
return (NO_PID);
|
||||
}
|
||||
|
||||
/* Return the status of PID as looked up in the PID_LIST array. A
|
||||
return value of PROC_BAD indicates that PID wasn't found. */
|
||||
static int
|
||||
find_status_by_pid (pid)
|
||||
pid_t pid;
|
||||
{
|
||||
int i;
|
||||
|
||||
i = find_index_by_pid (pid);
|
||||
if (i == NO_PID)
|
||||
return (PROC_BAD);
|
||||
if (pid_list[i].flags & PROC_RUNNING)
|
||||
return (PROC_STILL_ALIVE);
|
||||
return (pid_list[i].status);
|
||||
}
|
||||
|
||||
static int
|
||||
process_exit_status (status)
|
||||
WAIT status;
|
||||
{
|
||||
if (WIFSIGNALED (status))
|
||||
return (128 + WTERMSIG (status));
|
||||
else
|
||||
return (WEXITSTATUS (status));
|
||||
}
|
||||
|
||||
/* Return the status of PID as looked up in the PID_LIST array. A
|
||||
return value of PROC_BAD indicates that PID wasn't found. */
|
||||
static int
|
||||
find_termsig_by_pid (pid)
|
||||
pid_t pid;
|
||||
{
|
||||
int i;
|
||||
|
||||
i = find_index_by_pid (pid);
|
||||
if (i == NO_PID)
|
||||
return (0);
|
||||
if (pid_list[i].flags & PROC_RUNNING)
|
||||
return (0);
|
||||
return (get_termsig ((WAIT)pid_list[i].status));
|
||||
}
|
||||
|
||||
/* Set LAST_COMMAND_EXIT_SIGNAL depending on STATUS. If STATUS is -1, look
|
||||
up PID in the pid array and set LAST_COMMAND_EXIT_SIGNAL appropriately
|
||||
depending on its flags and exit status. */
|
||||
static int
|
||||
get_termsig (status)
|
||||
WAIT status;
|
||||
{
|
||||
if (WIFSTOPPED (status) == 0 && WIFSIGNALED (status))
|
||||
return (WTERMSIG (status));
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Give PID the status value STATUS in the PID_LIST array. */
|
||||
static void
|
||||
set_pid_status (pid, status)
|
||||
pid_t pid;
|
||||
WAIT status;
|
||||
{
|
||||
int slot;
|
||||
|
||||
#if defined (COPROCESS_SUPPORT)
|
||||
coproc_pidchk (pid, status);
|
||||
#endif
|
||||
|
||||
slot = find_index_by_pid (pid);
|
||||
if (slot == NO_PID)
|
||||
return;
|
||||
|
||||
pid_list[slot].status = process_exit_status (status);
|
||||
pid_list[slot].flags &= ~PROC_RUNNING;
|
||||
if (WIFSIGNALED (status))
|
||||
pid_list[slot].flags |= PROC_SIGNALED;
|
||||
/* If it's not a background process, mark it as notified so it gets
|
||||
cleaned up. */
|
||||
if ((pid_list[slot].flags & PROC_ASYNC) == 0)
|
||||
pid_list[slot].flags |= PROC_NOTIFIED;
|
||||
}
|
||||
|
||||
/* Give PID the flags FLAGS in the PID_LIST array. */
|
||||
static void
|
||||
set_pid_flags (pid, flags)
|
||||
pid_t pid;
|
||||
int flags;
|
||||
{
|
||||
int slot;
|
||||
|
||||
slot = find_index_by_pid (pid);
|
||||
if (slot == NO_PID)
|
||||
return;
|
||||
|
||||
pid_list[slot].flags |= flags;
|
||||
}
|
||||
|
||||
/* Unset FLAGS for PID in the pid list */
|
||||
static void
|
||||
unset_pid_flags (pid, flags)
|
||||
pid_t pid;
|
||||
int flags;
|
||||
{
|
||||
int slot;
|
||||
|
||||
slot = find_index_by_pid (pid);
|
||||
if (slot == NO_PID)
|
||||
return;
|
||||
|
||||
pid_list[slot].flags &= ~flags;
|
||||
}
|
||||
|
||||
/* Return the flags corresponding to PID in the PID_LIST array. */
|
||||
static int
|
||||
get_pid_flags (pid)
|
||||
pid_t pid;
|
||||
{
|
||||
int slot;
|
||||
|
||||
slot = find_index_by_pid (pid);
|
||||
if (slot == NO_PID)
|
||||
return 0;
|
||||
|
||||
return (pid_list[slot].flags);
|
||||
}
|
||||
|
||||
static void
|
||||
add_pid (pid, async)
|
||||
pid_t pid;
|
||||
int async;
|
||||
{
|
||||
int slot;
|
||||
|
||||
slot = find_proc_slot ();
|
||||
|
||||
pid_list[slot].pid = pid;
|
||||
pid_list[slot].status = -1;
|
||||
pid_list[slot].flags = PROC_RUNNING;
|
||||
if (async)
|
||||
pid_list[slot].flags |= PROC_ASYNC;
|
||||
}
|
||||
|
||||
static void
|
||||
mark_dead_jobs_as_notified (force)
|
||||
int force;
|
||||
{
|
||||
register int i, ndead;
|
||||
|
||||
/* first, count the number of non-running async jobs if FORCE == 0 */
|
||||
for (i = ndead = 0; force == 0 && i < pid_list_size; i++)
|
||||
{
|
||||
if (pid_list[i].pid == NO_PID)
|
||||
continue;
|
||||
if (((pid_list[i].flags & PROC_RUNNING) == 0) &&
|
||||
(pid_list[i].flags & PROC_ASYNC))
|
||||
ndead++;
|
||||
}
|
||||
|
||||
if (child_max < 0)
|
||||
child_max = getmaxchild ();
|
||||
if (child_max < 0)
|
||||
child_max = DEFAULT_CHILD_MAX;
|
||||
|
||||
if (force == 0 && ndead <= child_max)
|
||||
return;
|
||||
|
||||
/* If FORCE == 0, we just mark as many non-running async jobs as notified
|
||||
to bring us under the CHILD_MAX limit. */
|
||||
for (i = 0; i < pid_list_size; i++)
|
||||
{
|
||||
if (pid_list[i].pid == NO_PID)
|
||||
continue;
|
||||
if (((pid_list[i].flags & PROC_RUNNING) == 0) &&
|
||||
pid_list[i].pid != last_asynchronous_pid)
|
||||
{
|
||||
pid_list[i].flags |= PROC_NOTIFIED;
|
||||
if (force == 0 && (pid_list[i].flags & PROC_ASYNC) && --ndead <= child_max)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove all dead, notified jobs from the pid_list. */
|
||||
int
|
||||
cleanup_dead_jobs ()
|
||||
{
|
||||
register int i;
|
||||
|
||||
#if defined (HAVE_WAITPID)
|
||||
reap_zombie_children ();
|
||||
#endif
|
||||
|
||||
for (i = 0; i < pid_list_size; i++)
|
||||
{
|
||||
if ((pid_list[i].flags & PROC_RUNNING) == 0 &&
|
||||
(pid_list[i].flags & PROC_NOTIFIED))
|
||||
pid_list[i].pid = NO_PID;
|
||||
}
|
||||
|
||||
#if defined (COPROCESS_SUPPORT)
|
||||
coproc_reap ();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
reap_dead_jobs ()
|
||||
{
|
||||
mark_dead_jobs_as_notified (0);
|
||||
cleanup_dead_jobs ();
|
||||
}
|
||||
|
||||
/* Initialize the job control mechanism, and set up the tty stuff. */
|
||||
initialize_job_control (force)
|
||||
int force;
|
||||
{
|
||||
shell_tty = fileno (stderr);
|
||||
|
||||
if (interactive)
|
||||
get_tty_state ();
|
||||
}
|
||||
|
||||
/* Setup this shell to handle C-C, etc. */
|
||||
void
|
||||
initialize_job_signals ()
|
||||
{
|
||||
set_signal_handler (SIGINT, sigint_sighandler);
|
||||
|
||||
/* If this is a login shell we don't wish to be disturbed by
|
||||
stop signals. */
|
||||
if (login_shell)
|
||||
ignore_tty_job_signals ();
|
||||
}
|
||||
|
||||
#if defined (HAVE_WAITPID)
|
||||
/* Collect the status of all zombie children so that their system
|
||||
resources can be deallocated. */
|
||||
static void
|
||||
reap_zombie_children ()
|
||||
{
|
||||
# if defined (WNOHANG)
|
||||
pid_t pid;
|
||||
WAIT status;
|
||||
|
||||
CHECK_TERMSIG;
|
||||
while ((pid = waitpid (-1, (int *)&status, WNOHANG)) > 0)
|
||||
set_pid_status (pid, status);
|
||||
# endif /* WNOHANG */
|
||||
CHECK_TERMSIG;
|
||||
}
|
||||
#endif /* WAITPID */
|
||||
|
||||
#if !defined (HAVE_SIGINTERRUPT) && defined (HAVE_POSIX_SIGNALS)
|
||||
|
||||
#if !defined (SA_RESTART)
|
||||
# define SA_RESTART 0
|
||||
#endif
|
||||
|
||||
static int
|
||||
siginterrupt (sig, flag)
|
||||
int sig, flag;
|
||||
{
|
||||
struct sigaction act;
|
||||
|
||||
sigaction (sig, (struct sigaction *)NULL, &act);
|
||||
|
||||
if (flag)
|
||||
act.sa_flags &= ~SA_RESTART;
|
||||
else
|
||||
act.sa_flags |= SA_RESTART;
|
||||
|
||||
return (sigaction (sig, &act, (struct sigaction *)NULL));
|
||||
}
|
||||
#endif /* !HAVE_SIGINTERRUPT && HAVE_POSIX_SIGNALS */
|
||||
|
||||
/* Fork, handling errors. Returns the pid of the newly made child, or 0.
|
||||
COMMAND is just for remembering the name of the command; we don't do
|
||||
anything else with it. ASYNC_P says what to do with the tty. If
|
||||
non-zero, then don't give it away. */
|
||||
pid_t
|
||||
make_child (command, async_p)
|
||||
char *command;
|
||||
int async_p;
|
||||
{
|
||||
pid_t pid;
|
||||
int forksleep;
|
||||
|
||||
/* Discard saved memory. */
|
||||
if (command)
|
||||
free (command);
|
||||
|
||||
start_pipeline ();
|
||||
|
||||
#if defined (BUFFERED_INPUT)
|
||||
/* If default_buffered_input is active, we are reading a script. If
|
||||
the command is asynchronous, we have already duplicated /dev/null
|
||||
as fd 0, but have not changed the buffered stream corresponding to
|
||||
the old fd 0. We don't want to sync the stream in this case. */
|
||||
if (default_buffered_input != -1 && (!async_p || default_buffered_input > 0))
|
||||
sync_buffered_stream (default_buffered_input);
|
||||
#endif /* BUFFERED_INPUT */
|
||||
|
||||
/* Create the child, handle severe errors. Retry on EAGAIN. */
|
||||
forksleep = 1;
|
||||
while ((pid = fork ()) < 0 && errno == EAGAIN && forksleep < FORKSLEEP_MAX)
|
||||
{
|
||||
sys_error ("fork: retry");
|
||||
#if defined (HAVE_WAITPID)
|
||||
/* Posix systems with a non-blocking waitpid () system call available
|
||||
get another chance after zombies are reaped. */
|
||||
reap_zombie_children ();
|
||||
if (forksleep > 1 && sleep (forksleep) != 0)
|
||||
break;
|
||||
#else
|
||||
if (sleep (forksleep) != 0)
|
||||
break;
|
||||
#endif /* HAVE_WAITPID */
|
||||
forksleep <<= 1;
|
||||
}
|
||||
|
||||
if (pid < 0)
|
||||
{
|
||||
sys_error ("fork");
|
||||
throw_to_top_level ();
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
#if defined (BUFFERED_INPUT)
|
||||
unset_bash_input (0);
|
||||
#endif /* BUFFERED_INPUT */
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
/* Restore top-level signal mask. */
|
||||
sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Ignore INT and QUIT in asynchronous children. */
|
||||
if (async_p)
|
||||
last_asynchronous_pid = getpid ();
|
||||
#endif
|
||||
|
||||
default_tty_job_signals ();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In the parent. */
|
||||
|
||||
last_made_pid = pid;
|
||||
|
||||
if (async_p)
|
||||
last_asynchronous_pid = pid;
|
||||
|
||||
add_pid (pid, async_p);
|
||||
}
|
||||
return (pid);
|
||||
}
|
||||
|
||||
void
|
||||
ignore_tty_job_signals ()
|
||||
{
|
||||
#if defined (SIGTSTP)
|
||||
set_signal_handler (SIGTSTP, SIG_IGN);
|
||||
set_signal_handler (SIGTTIN, SIG_IGN);
|
||||
set_signal_handler (SIGTTOU, SIG_IGN);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
default_tty_job_signals ()
|
||||
{
|
||||
#if defined (SIGTSTP)
|
||||
set_signal_handler (SIGTSTP, SIG_DFL);
|
||||
set_signal_handler (SIGTTIN, SIG_DFL);
|
||||
set_signal_handler (SIGTTOU, SIG_DFL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Wait for a single pid (PID) and return its exit status. Called by
|
||||
the wait builtin. */
|
||||
int
|
||||
wait_for_single_pid (pid)
|
||||
pid_t pid;
|
||||
{
|
||||
pid_t got_pid;
|
||||
WAIT status;
|
||||
int pstatus, flags;
|
||||
|
||||
pstatus = find_status_by_pid (pid);
|
||||
|
||||
if (pstatus == PROC_BAD)
|
||||
{
|
||||
internal_error (_("wait: pid %ld is not a child of this shell"), (long)pid);
|
||||
return (127);
|
||||
}
|
||||
|
||||
if (pstatus != PROC_STILL_ALIVE)
|
||||
{
|
||||
if (pstatus > 128)
|
||||
last_command_exit_signal = find_termsig_by_pid (pid);
|
||||
return (pstatus);
|
||||
}
|
||||
|
||||
siginterrupt (SIGINT, 1);
|
||||
while ((got_pid = WAITPID (pid, &status, 0)) != pid)
|
||||
{
|
||||
CHECK_TERMSIG;
|
||||
if (got_pid < 0)
|
||||
{
|
||||
if (errno != EINTR && errno != ECHILD)
|
||||
{
|
||||
siginterrupt (SIGINT, 0);
|
||||
sys_error ("wait");
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (got_pid > 0)
|
||||
set_pid_status (got_pid, status);
|
||||
}
|
||||
|
||||
if (got_pid > 0)
|
||||
{
|
||||
set_pid_status (got_pid, status);
|
||||
set_pid_flags (got_pid, PROC_NOTIFIED);
|
||||
}
|
||||
|
||||
siginterrupt (SIGINT, 0);
|
||||
QUIT;
|
||||
|
||||
return (got_pid > 0 ? process_exit_status (status) : -1);
|
||||
}
|
||||
|
||||
/* Wait for all of the shell's children to exit. Called by the `wait'
|
||||
builtin. */
|
||||
void
|
||||
wait_for_background_pids ()
|
||||
{
|
||||
pid_t got_pid;
|
||||
WAIT status;
|
||||
|
||||
/* If we aren't using job control, we let the kernel take care of the
|
||||
bookkeeping for us. wait () will return -1 and set errno to ECHILD
|
||||
when there are no more unwaited-for child processes on both
|
||||
4.2 BSD-based and System V-based systems. */
|
||||
|
||||
siginterrupt (SIGINT, 1);
|
||||
|
||||
/* Wait for ECHILD */
|
||||
while ((got_pid = WAITPID (-1, &status, 0)) != -1)
|
||||
set_pid_status (got_pid, status);
|
||||
|
||||
if (errno != EINTR && errno != ECHILD)
|
||||
{
|
||||
siginterrupt (SIGINT, 0);
|
||||
sys_error("wait");
|
||||
}
|
||||
|
||||
siginterrupt (SIGINT, 0);
|
||||
QUIT;
|
||||
|
||||
mark_dead_jobs_as_notified (1);
|
||||
cleanup_dead_jobs ();
|
||||
}
|
||||
|
||||
/* Make OLD_SIGINT_HANDLER the SIGINT signal handler. */
|
||||
#define INVALID_SIGNAL_HANDLER (SigHandler *)wait_for_background_pids
|
||||
static SigHandler *old_sigint_handler = INVALID_SIGNAL_HANDLER;
|
||||
|
||||
static void
|
||||
restore_sigint_handler ()
|
||||
{
|
||||
if (old_sigint_handler != INVALID_SIGNAL_HANDLER)
|
||||
{
|
||||
set_signal_handler (SIGINT, old_sigint_handler);
|
||||
old_sigint_handler = INVALID_SIGNAL_HANDLER;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle SIGINT while we are waiting for children in a script to exit.
|
||||
All interrupts are effectively ignored by the shell, but allowed to
|
||||
kill a running job. */
|
||||
static sighandler
|
||||
wait_sigint_handler (sig)
|
||||
int sig;
|
||||
{
|
||||
SigHandler *sigint_handler;
|
||||
|
||||
/* If we got a SIGINT while in `wait', and SIGINT is trapped, do
|
||||
what POSIX.2 says (see builtins/wait.def for more info). */
|
||||
if (this_shell_builtin && this_shell_builtin == wait_builtin &&
|
||||
signal_is_trapped (SIGINT) &&
|
||||
((sigint_handler = trap_to_sighandler (SIGINT)) == trap_handler))
|
||||
{
|
||||
last_command_exit_value = EXECUTION_FAILURE;
|
||||
restore_sigint_handler ();
|
||||
interrupt_immediately = 0;
|
||||
trap_handler (SIGINT); /* set pending_traps[SIGINT] */
|
||||
wait_signal_received = SIGINT;
|
||||
longjmp (wait_intr_buf, 1);
|
||||
}
|
||||
|
||||
if (interrupt_immediately)
|
||||
{
|
||||
last_command_exit_value = EXECUTION_FAILURE;
|
||||
restore_sigint_handler ();
|
||||
ADDINTERRUPT;
|
||||
QUIT;
|
||||
}
|
||||
|
||||
wait_sigint_received = 1;
|
||||
|
||||
SIGRETURN (0);
|
||||
}
|
||||
|
||||
static char *
|
||||
j_strsignal (s)
|
||||
int s;
|
||||
{
|
||||
static char retcode_name_buffer[64] = { '\0' };
|
||||
char *x;
|
||||
|
||||
x = strsignal (s);
|
||||
if (x == 0)
|
||||
{
|
||||
x = retcode_name_buffer;
|
||||
sprintf (x, "Signal %d", s);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/* Wait for pid (one of our children) to terminate. This is called only
|
||||
by the execution code in execute_cmd.c. */
|
||||
int
|
||||
wait_for (pid)
|
||||
pid_t pid;
|
||||
{
|
||||
int return_val, pstatus;
|
||||
pid_t got_pid;
|
||||
WAIT status;
|
||||
|
||||
pstatus = find_status_by_pid (pid);
|
||||
|
||||
if (pstatus == PROC_BAD)
|
||||
return (0);
|
||||
|
||||
if (pstatus != PROC_STILL_ALIVE)
|
||||
{
|
||||
if (pstatus > 128)
|
||||
last_command_exit_signal = find_termsig_by_pid (pid);
|
||||
return (pstatus);
|
||||
}
|
||||
|
||||
/* If we are running a script, ignore SIGINT while we're waiting for
|
||||
a child to exit. The loop below does some of this, but not all. */
|
||||
wait_sigint_received = 0;
|
||||
if (interactive_shell == 0)
|
||||
old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
|
||||
|
||||
while ((got_pid = WAITPID (-1, &status, 0)) != pid) /* XXX was pid now -1 */
|
||||
{
|
||||
CHECK_TERMSIG;
|
||||
if (got_pid < 0 && errno == ECHILD)
|
||||
{
|
||||
#if !defined (_POSIX_VERSION)
|
||||
status.w_termsig = status.w_retcode = 0;
|
||||
#else
|
||||
status = 0;
|
||||
#endif /* _POSIX_VERSION */
|
||||
break;
|
||||
}
|
||||
else if (got_pid < 0 && errno != EINTR)
|
||||
programming_error ("wait_for(%ld): %s", (long)pid, strerror(errno));
|
||||
else if (got_pid > 0)
|
||||
set_pid_status (got_pid, status);
|
||||
}
|
||||
|
||||
if (got_pid > 0)
|
||||
set_pid_status (got_pid, status);
|
||||
|
||||
#if defined (HAVE_WAITPID)
|
||||
if (got_pid >= 0)
|
||||
reap_zombie_children ();
|
||||
#endif /* HAVE_WAITPID */
|
||||
|
||||
if (interactive_shell == 0)
|
||||
{
|
||||
SigHandler *temp_handler;
|
||||
|
||||
temp_handler = old_sigint_handler;
|
||||
restore_sigint_handler ();
|
||||
|
||||
/* If the job exited because of SIGINT, make sure the shell acts as if
|
||||
it had received one also. */
|
||||
if (WIFSIGNALED (status) && (WTERMSIG (status) == SIGINT))
|
||||
{
|
||||
|
||||
if (maybe_call_trap_handler (SIGINT) == 0)
|
||||
{
|
||||
if (temp_handler == SIG_DFL)
|
||||
termsig_handler (SIGINT);
|
||||
else if (temp_handler != INVALID_SIGNAL_HANDLER && temp_handler != SIG_IGN)
|
||||
(*temp_handler) (SIGINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Default return value. */
|
||||
/* ``a full 8 bits of status is returned'' */
|
||||
return_val = process_exit_status (status);
|
||||
last_command_exit_signal = get_termsig (status);
|
||||
|
||||
#if defined (DONT_REPORT_SIGPIPE) && defined (DONT_REPORT_SIGTERM)
|
||||
# define REPORTSIG(x) ((x) != SIGINT && (x) != SIGPIPE && (x) != SIGTERM)
|
||||
#elif !defined (DONT_REPORT_SIGPIPE) && !defined (DONT_REPORT_SIGTERM)
|
||||
# define REPORTSIG(x) ((x) != SIGINT)
|
||||
#elif defined (DONT_REPORT_SIGPIPE)
|
||||
# define REPORTSIG(x) ((x) != SIGINT && (x) != SIGPIPE)
|
||||
#else
|
||||
# define REPORTSIG(x) ((x) != SIGINT && (x) != SIGTERM)
|
||||
#endif
|
||||
|
||||
if ((WIFSTOPPED (status) == 0) && WIFSIGNALED (status) && REPORTSIG(WTERMSIG (status)))
|
||||
{
|
||||
fprintf (stderr, "%s", j_strsignal (WTERMSIG (status)));
|
||||
if (WIFCORED (status))
|
||||
fprintf (stderr, _(" (core dumped)"));
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
if (interactive_shell && subshell_environment == 0)
|
||||
{
|
||||
if (WIFSIGNALED (status) || WIFSTOPPED (status))
|
||||
set_tty_state ();
|
||||
else
|
||||
get_tty_state ();
|
||||
}
|
||||
else if (interactive_shell == 0 && subshell_environment == 0 && check_window_size)
|
||||
get_new_window_size (0, (int *)0, (int *)0);
|
||||
|
||||
return (return_val);
|
||||
}
|
||||
|
||||
/* Send PID SIGNAL. Returns -1 on failure, 0 on success. If GROUP is non-zero,
|
||||
or PID is less than -1, then kill the process group associated with PID. */
|
||||
int
|
||||
kill_pid (pid, signal, group)
|
||||
pid_t pid;
|
||||
int signal, group;
|
||||
{
|
||||
int result;
|
||||
|
||||
if (pid < -1)
|
||||
{
|
||||
pid = -pid;
|
||||
group = 1;
|
||||
}
|
||||
result = group ? killpg (pid, signal) : kill (pid, signal);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static TTYSTRUCT shell_tty_info;
|
||||
static int got_tty_state;
|
||||
|
||||
/* Fill the contents of shell_tty_info with the current tty info. */
|
||||
get_tty_state ()
|
||||
{
|
||||
int tty;
|
||||
|
||||
tty = input_tty ();
|
||||
if (tty != -1)
|
||||
{
|
||||
ttgetattr (tty, &shell_tty_info);
|
||||
got_tty_state = 1;
|
||||
if (check_window_size)
|
||||
get_new_window_size (0, (int *)0, (int *)0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make the current tty use the state in shell_tty_info. */
|
||||
int
|
||||
set_tty_state ()
|
||||
{
|
||||
int tty;
|
||||
|
||||
tty = input_tty ();
|
||||
if (tty != -1)
|
||||
{
|
||||
if (got_tty_state == 0)
|
||||
return 0;
|
||||
ttsetattr (tty, &shell_tty_info);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Give the terminal to PGRP. */
|
||||
give_terminal_to (pgrp, force)
|
||||
pid_t pgrp;
|
||||
int force;
|
||||
{
|
||||
}
|
||||
|
||||
/* Stop a pipeline. */
|
||||
int
|
||||
stop_pipeline (async, ignore)
|
||||
int async;
|
||||
COMMAND *ignore;
|
||||
{
|
||||
already_making_children = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
start_pipeline ()
|
||||
{
|
||||
already_making_children = 1;
|
||||
}
|
||||
|
||||
void
|
||||
stop_making_children ()
|
||||
{
|
||||
already_making_children = 0;
|
||||
}
|
||||
|
||||
int
|
||||
get_job_by_pid (pid, block)
|
||||
pid_t pid;
|
||||
int block;
|
||||
{
|
||||
int i;
|
||||
|
||||
i = find_index_by_pid (pid);
|
||||
return ((i == NO_PID) ? PROC_BAD : i);
|
||||
}
|
||||
|
||||
/* Print descriptive information about the job with leader pid PID. */
|
||||
void
|
||||
describe_pid (pid)
|
||||
pid_t pid;
|
||||
{
|
||||
fprintf (stderr, "%ld\n", (long) pid);
|
||||
}
|
||||
|
||||
void
|
||||
freeze_jobs_list ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
unfreeze_jobs_list ()
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
count_all_jobs ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
-1634
File diff suppressed because it is too large
Load Diff
-1591
File diff suppressed because it is too large
Load Diff
@@ -1,685 +0,0 @@
|
||||
/* sig.c - interface for shell signal handlers and signal initialization. */
|
||||
|
||||
/* Copyright (C) 1994-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"
|
||||
|
||||
#include "bashtypes.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "bashintl.h"
|
||||
|
||||
#include "shell.h"
|
||||
#if defined (JOB_CONTROL)
|
||||
#include "jobs.h"
|
||||
#endif /* JOB_CONTROL */
|
||||
#include "siglist.h"
|
||||
#include "sig.h"
|
||||
#include "trap.h"
|
||||
|
||||
#include "builtins/common.h"
|
||||
|
||||
#if defined (READLINE)
|
||||
# include "bashline.h"
|
||||
# include <readline/readline.h>
|
||||
#endif
|
||||
|
||||
#if defined (HISTORY)
|
||||
# include "bashhist.h"
|
||||
#endif
|
||||
|
||||
extern int last_command_exit_value;
|
||||
extern int last_command_exit_signal;
|
||||
extern int return_catch_flag;
|
||||
extern int loop_level, continuing, breaking, funcnest;
|
||||
extern int executing_list;
|
||||
extern int comsub_ignore_return;
|
||||
extern int parse_and_execute_level, shell_initialized;
|
||||
#if defined (HISTORY)
|
||||
extern int history_lines_this_session;
|
||||
#endif
|
||||
extern int no_line_editing;
|
||||
|
||||
extern void initialize_siglist ();
|
||||
|
||||
/* Non-zero after SIGINT. */
|
||||
volatile int interrupt_state = 0;
|
||||
|
||||
/* Non-zero after SIGWINCH */
|
||||
volatile int sigwinch_received = 0;
|
||||
|
||||
/* Set to the value of any terminating signal received. */
|
||||
volatile int terminating_signal = 0;
|
||||
|
||||
/* The environment at the top-level R-E loop. We use this in
|
||||
the case of error return. */
|
||||
procenv_t top_level;
|
||||
|
||||
#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
|
||||
/* The signal masks that this shell runs with. */
|
||||
sigset_t top_level_mask;
|
||||
#endif /* JOB_CONTROL */
|
||||
|
||||
/* When non-zero, we throw_to_top_level (). */
|
||||
int interrupt_immediately = 0;
|
||||
|
||||
/* When non-zero, we call the terminating signal handler immediately. */
|
||||
int terminate_immediately = 0;
|
||||
|
||||
#if defined (SIGWINCH)
|
||||
static SigHandler *old_winch = (SigHandler *)SIG_DFL;
|
||||
#endif
|
||||
|
||||
static void initialize_shell_signals __P((void));
|
||||
|
||||
void
|
||||
initialize_signals (reinit)
|
||||
int reinit;
|
||||
{
|
||||
initialize_shell_signals ();
|
||||
initialize_job_signals ();
|
||||
#if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
|
||||
if (reinit == 0)
|
||||
initialize_siglist ();
|
||||
#endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
|
||||
}
|
||||
|
||||
/* A structure describing a signal that terminates the shell if not
|
||||
caught. The orig_handler member is present so children can reset
|
||||
these signals back to their original handlers. */
|
||||
struct termsig {
|
||||
int signum;
|
||||
SigHandler *orig_handler;
|
||||
int orig_flags;
|
||||
};
|
||||
|
||||
#define NULL_HANDLER (SigHandler *)SIG_DFL
|
||||
|
||||
/* The list of signals that would terminate the shell if not caught.
|
||||
We catch them, but just so that we can write the history file,
|
||||
and so forth. */
|
||||
static struct termsig terminating_signals[] = {
|
||||
#ifdef SIGHUP
|
||||
{ SIGHUP, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGINT
|
||||
{ SIGINT, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGILL
|
||||
{ SIGILL, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGTRAP
|
||||
{ SIGTRAP, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGIOT
|
||||
{ SIGIOT, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGDANGER
|
||||
{ SIGDANGER, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGEMT
|
||||
{ SIGEMT, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGFPE
|
||||
{ SIGFPE, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGBUS
|
||||
{ SIGBUS, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGSEGV
|
||||
{ SIGSEGV, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGSYS
|
||||
{ SIGSYS, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGPIPE
|
||||
{ SIGPIPE, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGALRM
|
||||
{ SIGALRM, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGTERM
|
||||
{ SIGTERM, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGXCPU
|
||||
{ SIGXCPU, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGXFSZ
|
||||
{ SIGXFSZ, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGVTALRM
|
||||
{ SIGVTALRM, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#ifdef SIGPROF
|
||||
{ SIGPROF, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SIGLOST
|
||||
{ SIGLOST, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGUSR1
|
||||
{ SIGUSR1, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
|
||||
#ifdef SIGUSR2
|
||||
{ SIGUSR2, NULL_HANDLER, 0 },
|
||||
#endif
|
||||
};
|
||||
|
||||
#define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
|
||||
|
||||
#define XSIG(x) (terminating_signals[x].signum)
|
||||
#define XHANDLER(x) (terminating_signals[x].orig_handler)
|
||||
#define XSAFLAGS(x) (terminating_signals[x].orig_flags)
|
||||
|
||||
static int termsigs_initialized = 0;
|
||||
|
||||
/* Initialize signals that will terminate the shell to do some
|
||||
unwind protection. For non-interactive shells, we only call
|
||||
this when a trap is defined for EXIT (0) or when trap is run
|
||||
to display signal dispositions. */
|
||||
void
|
||||
initialize_terminating_signals ()
|
||||
{
|
||||
register int i;
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
struct sigaction act, oact;
|
||||
#endif
|
||||
|
||||
if (termsigs_initialized)
|
||||
return;
|
||||
|
||||
/* The following code is to avoid an expensive call to
|
||||
set_signal_handler () for each terminating_signals. Fortunately,
|
||||
this is possible in Posix. Unfortunately, we have to call signal ()
|
||||
on non-Posix systems for each signal in terminating_signals. */
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
act.sa_handler = termsig_sighandler;
|
||||
act.sa_flags = 0;
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigemptyset (&oact.sa_mask);
|
||||
for (i = 0; i < TERMSIGS_LENGTH; i++)
|
||||
sigaddset (&act.sa_mask, XSIG (i));
|
||||
for (i = 0; i < TERMSIGS_LENGTH; i++)
|
||||
{
|
||||
/* If we've already trapped it, don't do anything. */
|
||||
if (signal_is_trapped (XSIG (i)))
|
||||
continue;
|
||||
|
||||
sigaction (XSIG (i), &act, &oact);
|
||||
XHANDLER(i) = oact.sa_handler;
|
||||
XSAFLAGS(i) = oact.sa_flags;
|
||||
/* Don't do anything with signals that are ignored at shell entry
|
||||
if the shell is not interactive. */
|
||||
/* XXX - should we do this for interactive shells, too? */
|
||||
if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
|
||||
{
|
||||
sigaction (XSIG (i), &oact, &act);
|
||||
set_signal_ignored (XSIG (i));
|
||||
}
|
||||
#if defined (SIGPROF) && !defined (_MINIX)
|
||||
if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
|
||||
sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
|
||||
#endif /* SIGPROF && !_MINIX */
|
||||
}
|
||||
|
||||
#else /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
for (i = 0; i < TERMSIGS_LENGTH; i++)
|
||||
{
|
||||
/* If we've already trapped it, don't do anything. */
|
||||
if (signal_is_trapped (XSIG (i)))
|
||||
continue;
|
||||
|
||||
XHANDLER(i) = signal (XSIG (i), termsig_sighandler);
|
||||
XSAFLAGS(i) = 0;
|
||||
/* Don't do anything with signals that are ignored at shell entry
|
||||
if the shell is not interactive. */
|
||||
/* XXX - should we do this for interactive shells, too? */
|
||||
if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
|
||||
{
|
||||
signal (XSIG (i), SIG_IGN);
|
||||
set_signal_ignored (XSIG (i));
|
||||
}
|
||||
#ifdef SIGPROF
|
||||
if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
|
||||
signal (XSIG (i), XHANDLER (i));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
termsigs_initialized = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
initialize_shell_signals ()
|
||||
{
|
||||
if (interactive)
|
||||
initialize_terminating_signals ();
|
||||
|
||||
#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
|
||||
/* All shells use the signal mask they inherit, and pass it along
|
||||
to child processes. Children will never block SIGCHLD, though. */
|
||||
sigemptyset (&top_level_mask);
|
||||
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
|
||||
# if defined (SIGCHLD)
|
||||
sigdelset (&top_level_mask, SIGCHLD);
|
||||
# endif
|
||||
#endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
|
||||
|
||||
/* And, some signals that are specifically ignored by the shell. */
|
||||
set_signal_handler (SIGQUIT, SIG_IGN);
|
||||
|
||||
if (interactive)
|
||||
{
|
||||
set_signal_handler (SIGINT, sigint_sighandler);
|
||||
set_signal_handler (SIGTERM, SIG_IGN);
|
||||
set_sigwinch_handler ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
reset_terminating_signals ()
|
||||
{
|
||||
register int i;
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
struct sigaction act;
|
||||
#endif
|
||||
|
||||
if (termsigs_initialized == 0)
|
||||
return;
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
act.sa_flags = 0;
|
||||
sigemptyset (&act.sa_mask);
|
||||
for (i = 0; i < TERMSIGS_LENGTH; i++)
|
||||
{
|
||||
/* Skip a signal if it's trapped or handled specially, because the
|
||||
trap code will restore the correct value. */
|
||||
if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
|
||||
continue;
|
||||
|
||||
act.sa_handler = XHANDLER (i);
|
||||
act.sa_flags = XSAFLAGS (i);
|
||||
sigaction (XSIG (i), &act, (struct sigaction *) NULL);
|
||||
}
|
||||
#else /* !HAVE_POSIX_SIGNALS */
|
||||
for (i = 0; i < TERMSIGS_LENGTH; i++)
|
||||
{
|
||||
if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
|
||||
continue;
|
||||
|
||||
signal (XSIG (i), XHANDLER (i));
|
||||
}
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
}
|
||||
#undef XSIG
|
||||
#undef XHANDLER
|
||||
|
||||
/* Run some of the cleanups that should be performed when we run
|
||||
jump_to_top_level from a builtin command context. XXX - might want to
|
||||
also call reset_parser here. */
|
||||
void
|
||||
top_level_cleanup ()
|
||||
{
|
||||
/* Clean up string parser environment. */
|
||||
while (parse_and_execute_level)
|
||||
parse_and_execute_cleanup ();
|
||||
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
unlink_fifo_list ();
|
||||
#endif /* PROCESS_SUBSTITUTION */
|
||||
|
||||
run_unwind_protects ();
|
||||
loop_level = continuing = breaking = funcnest = 0;
|
||||
executing_list = comsub_ignore_return = return_catch_flag = 0;
|
||||
}
|
||||
|
||||
/* What to do when we've been interrupted, and it is safe to handle it. */
|
||||
void
|
||||
throw_to_top_level ()
|
||||
{
|
||||
int print_newline = 0;
|
||||
|
||||
if (interrupt_state)
|
||||
{
|
||||
print_newline = 1;
|
||||
DELINTERRUPT;
|
||||
}
|
||||
|
||||
if (interrupt_state)
|
||||
return;
|
||||
|
||||
last_command_exit_signal = (last_command_exit_value > 128) ?
|
||||
(last_command_exit_value - 128) : 0;
|
||||
last_command_exit_value |= 128;
|
||||
|
||||
/* Run any traps set on SIGINT. */
|
||||
run_interrupt_trap ();
|
||||
|
||||
/* Clean up string parser environment. */
|
||||
while (parse_and_execute_level)
|
||||
parse_and_execute_cleanup ();
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
give_terminal_to (shell_pgrp, 0);
|
||||
#endif /* JOB_CONTROL */
|
||||
|
||||
#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
|
||||
/* This should not be necessary on systems using sigsetjmp/siglongjmp. */
|
||||
sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
|
||||
#endif
|
||||
|
||||
reset_parser ();
|
||||
|
||||
#if defined (READLINE)
|
||||
if (interactive)
|
||||
bashline_reset ();
|
||||
#endif /* READLINE */
|
||||
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
unlink_fifo_list ();
|
||||
#endif /* PROCESS_SUBSTITUTION */
|
||||
|
||||
run_unwind_protects ();
|
||||
loop_level = continuing = breaking = funcnest = 0;
|
||||
executing_list = comsub_ignore_return = return_catch_flag = 0;
|
||||
|
||||
if (interactive && print_newline)
|
||||
{
|
||||
fflush (stdout);
|
||||
fprintf (stderr, "\n");
|
||||
fflush (stderr);
|
||||
}
|
||||
|
||||
/* An interrupted `wait' command in a script does not exit the script. */
|
||||
if (interactive || (interactive_shell && !shell_initialized) ||
|
||||
(print_newline && signal_is_trapped (SIGINT)))
|
||||
jump_to_top_level (DISCARD);
|
||||
else
|
||||
jump_to_top_level (EXITPROG);
|
||||
}
|
||||
|
||||
/* This is just here to isolate the longjmp calls. */
|
||||
void
|
||||
jump_to_top_level (value)
|
||||
int value;
|
||||
{
|
||||
longjmp (top_level, value);
|
||||
}
|
||||
|
||||
sighandler
|
||||
termsig_sighandler (sig)
|
||||
int sig;
|
||||
{
|
||||
/* If we get called twice with the same signal before handling it,
|
||||
terminate right away. */
|
||||
if (
|
||||
#ifdef SIGHUP
|
||||
sig != SIGHUP &&
|
||||
#endif
|
||||
#ifdef SIGINT
|
||||
sig != SIGINT &&
|
||||
#endif
|
||||
#ifdef SIGDANGER
|
||||
sig != SIGDANGER &&
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
sig != SIGPIPE &&
|
||||
#endif
|
||||
#ifdef SIGALRM
|
||||
sig != SIGALRM &&
|
||||
#endif
|
||||
#ifdef SIGTERM
|
||||
sig != SIGTERM &&
|
||||
#endif
|
||||
#ifdef SIGXCPU
|
||||
sig != SIGXCPU &&
|
||||
#endif
|
||||
#ifdef SIGXFSZ
|
||||
sig != SIGXFSZ &&
|
||||
#endif
|
||||
#ifdef SIGVTALRM
|
||||
sig != SIGVTALRM &&
|
||||
#endif
|
||||
#ifdef SIGLOST
|
||||
sig != SIGLOST &&
|
||||
#endif
|
||||
#ifdef SIGUSR1
|
||||
sig != SIGUSR1 &&
|
||||
#endif
|
||||
#ifdef SIGUSR2
|
||||
sig != SIGUSR2 &&
|
||||
#endif
|
||||
sig == terminating_signal)
|
||||
terminate_immediately = 1;
|
||||
|
||||
terminating_signal = sig;
|
||||
|
||||
/* XXX - should this also trigger when interrupt_immediately is set? */
|
||||
if (terminate_immediately)
|
||||
{
|
||||
#if defined (HISTORY)
|
||||
/* XXX - will inhibit history file being written */
|
||||
# if defined (READLINE)
|
||||
if (interactive_shell == 0 || interactive == 0 || (sig != SIGHUP && sig != SIGTERM) || no_line_editing || (RL_ISSTATE (RL_STATE_READCMD) == 0))
|
||||
# endif
|
||||
history_lines_this_session = 0;
|
||||
#endif
|
||||
terminate_immediately = 0;
|
||||
termsig_handler (sig);
|
||||
}
|
||||
|
||||
#if defined (READLINE)
|
||||
if (interactive_shell && interactive && no_line_editing == 0)
|
||||
bashline_set_event_hook ();
|
||||
#endif
|
||||
|
||||
SIGRETURN (0);
|
||||
}
|
||||
|
||||
void
|
||||
termsig_handler (sig)
|
||||
int sig;
|
||||
{
|
||||
static int handling_termsig = 0;
|
||||
|
||||
/* Simple semaphore to keep this function from being executed multiple
|
||||
times. Since we no longer are running as a signal handler, we don't
|
||||
block multiple occurrences of the terminating signals while running. */
|
||||
if (handling_termsig)
|
||||
return;
|
||||
handling_termsig = 1;
|
||||
terminating_signal = 0; /* keep macro from re-testing true. */
|
||||
|
||||
/* I don't believe this condition ever tests true. */
|
||||
if (sig == SIGINT && signal_is_trapped (SIGINT))
|
||||
run_interrupt_trap ();
|
||||
|
||||
#if defined (HISTORY)
|
||||
if (interactive_shell && sig != SIGABRT)
|
||||
maybe_save_shell_history ();
|
||||
#endif /* HISTORY */
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
if (sig == SIGHUP && (interactive || (subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PROCSUB))))
|
||||
hangup_all_jobs ();
|
||||
end_job_control ();
|
||||
#endif /* JOB_CONTROL */
|
||||
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
unlink_fifo_list ();
|
||||
#endif /* PROCESS_SUBSTITUTION */
|
||||
|
||||
/* Reset execution context */
|
||||
loop_level = continuing = breaking = funcnest = 0;
|
||||
executing_list = comsub_ignore_return = return_catch_flag = 0;
|
||||
|
||||
run_exit_trap ();
|
||||
set_signal_handler (sig, SIG_DFL);
|
||||
kill (getpid (), sig);
|
||||
}
|
||||
|
||||
/* What we really do when SIGINT occurs. */
|
||||
sighandler
|
||||
sigint_sighandler (sig)
|
||||
int sig;
|
||||
{
|
||||
#if defined (MUST_REINSTALL_SIGHANDLERS)
|
||||
signal (sig, sigint_sighandler);
|
||||
#endif
|
||||
|
||||
/* interrupt_state needs to be set for the stack of interrupts to work
|
||||
right. Should it be set unconditionally? */
|
||||
if (interrupt_state == 0)
|
||||
ADDINTERRUPT;
|
||||
|
||||
if (interrupt_immediately)
|
||||
{
|
||||
interrupt_immediately = 0;
|
||||
last_command_exit_value = 128 + sig;
|
||||
throw_to_top_level ();
|
||||
}
|
||||
|
||||
SIGRETURN (0);
|
||||
}
|
||||
|
||||
#if defined (SIGWINCH)
|
||||
sighandler
|
||||
sigwinch_sighandler (sig)
|
||||
int sig;
|
||||
{
|
||||
#if defined (MUST_REINSTALL_SIGHANDLERS)
|
||||
set_signal_handler (SIGWINCH, sigwinch_sighandler);
|
||||
#endif /* MUST_REINSTALL_SIGHANDLERS */
|
||||
sigwinch_received = 1;
|
||||
SIGRETURN (0);
|
||||
}
|
||||
#endif /* SIGWINCH */
|
||||
|
||||
void
|
||||
set_sigwinch_handler ()
|
||||
{
|
||||
#if defined (SIGWINCH)
|
||||
old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
unset_sigwinch_handler ()
|
||||
{
|
||||
#if defined (SIGWINCH)
|
||||
set_signal_handler (SIGWINCH, old_winch);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Signal functions used by the rest of the code. */
|
||||
#if !defined (HAVE_POSIX_SIGNALS)
|
||||
|
||||
/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
|
||||
sigprocmask (operation, newset, oldset)
|
||||
int operation, *newset, *oldset;
|
||||
{
|
||||
int old, new;
|
||||
|
||||
if (newset)
|
||||
new = *newset;
|
||||
else
|
||||
new = 0;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case SIG_BLOCK:
|
||||
old = sigblock (new);
|
||||
break;
|
||||
|
||||
case SIG_SETMASK:
|
||||
old = sigsetmask (new);
|
||||
break;
|
||||
|
||||
default:
|
||||
internal_error (_("sigprocmask: %d: invalid operation"), operation);
|
||||
}
|
||||
|
||||
if (oldset)
|
||||
*oldset = old;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if !defined (SA_INTERRUPT)
|
||||
# define SA_INTERRUPT 0
|
||||
#endif
|
||||
|
||||
#if !defined (SA_RESTART)
|
||||
# define SA_RESTART 0
|
||||
#endif
|
||||
|
||||
SigHandler *
|
||||
set_signal_handler (sig, handler)
|
||||
int sig;
|
||||
SigHandler *handler;
|
||||
{
|
||||
struct sigaction act, oact;
|
||||
|
||||
act.sa_handler = handler;
|
||||
act.sa_flags = 0;
|
||||
|
||||
/* XXX - bash-4.2 */
|
||||
/* We don't want a child death to interrupt interruptible system calls, even
|
||||
if we take the time to reap children */
|
||||
if (sig == SIGCHLD)
|
||||
act.sa_flags |= SA_RESTART; /* XXX */
|
||||
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigemptyset (&oact.sa_mask);
|
||||
sigaction (sig, &act, &oact);
|
||||
return (oact.sa_handler);
|
||||
}
|
||||
#endif /* HAVE_POSIX_SIGNALS */
|
||||
@@ -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 "$@"
|
||||
@@ -1,112 +0,0 @@
|
||||
# test cases for array quoting and escaping fixed post bash-3.2-release
|
||||
|
||||
oIFS="$IFS"
|
||||
|
||||
a=(a b c)
|
||||
echo ${a[@]}
|
||||
|
||||
a2=("${a[@]/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
echo "${dbg-"'hey'"}"
|
||||
echo "${dbg-"hey"}"
|
||||
echo "${dbg-'"'hey}"
|
||||
echo "${dbg-'"hey'}"
|
||||
|
||||
unset a a2
|
||||
|
||||
IFS=
|
||||
a2=(${a[@]/#/"-iname '"})
|
||||
recho "${a2[@]}"
|
||||
|
||||
IFS="$oIFS"
|
||||
unset a a2
|
||||
|
||||
a=('a b' 'c d' 'e f')
|
||||
|
||||
recho ${a[@]:1:2}
|
||||
recho "${a[@]:1:2}"
|
||||
|
||||
IFS=
|
||||
recho ${a[@]:1:2}
|
||||
recho "${a[@]:1:2}"
|
||||
|
||||
IFS="$oIFS"
|
||||
unset a a2
|
||||
|
||||
a=(abc def)
|
||||
|
||||
# Prevent word splitting
|
||||
#IFS=
|
||||
|
||||
a2=("${a[@]/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
eval a2=("${a[@]/#/\"-iname \'\"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
eval a2=("${a[@]/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
a2=("${a[@]/#/-iname \'}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
eval a2=("${a[@]/#/-iname \'}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
set -- abc def
|
||||
|
||||
a2=("${@/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
eval a2=("${@/#/"-iname '"}")
|
||||
recho "${a2[@]}"
|
||||
|
||||
unset a a2
|
||||
|
||||
IFS=
|
||||
pat=('*.*')
|
||||
case $(ls ${pat[@]} 2>/dev/null) in
|
||||
'') echo '*.* BAD' ;;
|
||||
*) echo '*.* OK' ;;
|
||||
esac
|
||||
|
||||
IFS="$oIFS"
|
||||
unset a a2 pat
|
||||
|
||||
IFS=
|
||||
|
||||
s='abc'
|
||||
|
||||
set - ${s/b/1 2 3}
|
||||
echo $#
|
||||
echo "$1"
|
||||
|
||||
IFS="$oIFS"
|
||||
unset s
|
||||
|
||||
set -- ab cd ef
|
||||
foo="var with spaces"
|
||||
|
||||
IFS=
|
||||
recho $foo
|
||||
recho "$foo"
|
||||
|
||||
recho ${foo}"$@"
|
||||
recho ${foo}$@
|
||||
|
||||
array=(ab cd ef)
|
||||
recho ${foo}"${array[@]}"
|
||||
recho ${foo}${array[@]}
|
||||
|
||||
recho $(echo $foo)"$@"
|
||||
recho $(echo $foo)$@
|
||||
|
||||
a=('word1 with spaces' 'word2 with spaces')
|
||||
set - ${a[@]/word/element}
|
||||
echo $#
|
||||
recho "$@"
|
||||
recho $@
|
||||
|
||||
IFS="$oIFS"
|
||||
unset a a2 array foo
|
||||
@@ -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...
|
||||
:;
|
||||
@@ -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
|
||||
@@ -1,36 +0,0 @@
|
||||
export LC_ALL=C
|
||||
export LANG=C
|
||||
|
||||
# test out the new $(< filename) code
|
||||
# it should be exactly equivalent to $(cat filename)
|
||||
|
||||
FILENAME=/tmp/bashtmp.x$$
|
||||
|
||||
trap 'rm -f $FILENAME' 0
|
||||
|
||||
cat >$FILENAME << EOF
|
||||
line 1
|
||||
line 2
|
||||
line 3
|
||||
EOF
|
||||
|
||||
LINES1=$(cat $FILENAME)
|
||||
LINES2=$(< $FILENAME)
|
||||
|
||||
if [[ $LINES1 != $LINES2 ]]; then
|
||||
echo 'whoops: $(< filename) failed'
|
||||
fi
|
||||
|
||||
LINES2=$(< /tmp/bashtmp.x*)
|
||||
if [[ $LINES1 != $LINES2 ]]; then
|
||||
echo 'whoops: $(< filename) with glob expansion failed'
|
||||
fi
|
||||
|
||||
# but the glob expansion in the redirection should fail in posix mode
|
||||
set -o posix
|
||||
LINES2=$(< /tmp/bashtmp.x*)
|
||||
set +o posix
|
||||
|
||||
# now see what happens when we try it with a non-existant file
|
||||
LINES3=$(< /tmp/redir-notthere)
|
||||
echo $?
|
||||
@@ -1,105 +0,0 @@
|
||||
/* trap.h -- data structures used in the trap mechanism. */
|
||||
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
#if !defined (_TRAP_H_)
|
||||
#define _TRAP_H_
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
#if !defined (SIG_DFL)
|
||||
#include "bashtypes.h"
|
||||
#include <signal.h>
|
||||
#endif /* SIG_DFL */
|
||||
|
||||
#if !defined (NSIG)
|
||||
#define NSIG 64
|
||||
#endif /* !NSIG */
|
||||
|
||||
#define NO_SIG -1
|
||||
#define DEFAULT_SIG SIG_DFL
|
||||
#define IGNORE_SIG SIG_IGN
|
||||
|
||||
/* Special shell trap names. */
|
||||
#define DEBUG_TRAP NSIG
|
||||
#define ERROR_TRAP NSIG+1
|
||||
#define RETURN_TRAP NSIG+2
|
||||
#define EXIT_TRAP 0
|
||||
|
||||
/* system signals plus special bash traps */
|
||||
#define BASH_NSIG NSIG+3
|
||||
|
||||
/* Flags values for decode_signal() */
|
||||
#define DSIG_SIGPREFIX 0x01 /* don't alllow `SIG' PREFIX */
|
||||
#define DSIG_NOCASE 0x02 /* case-insensitive comparison */
|
||||
|
||||
/* A value which can never be the target of a trap handler. */
|
||||
#define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
|
||||
|
||||
#define signal_object_p(x,f) (decode_signal (x,f) != NO_SIG)
|
||||
|
||||
#define TRAP_STRING(s) \
|
||||
(signal_is_trapped (s) && signal_is_ignored (s) == 0) ? trap_list[s] \
|
||||
: (char *)NULL
|
||||
|
||||
extern char *trap_list[];
|
||||
|
||||
/* Externally-visible functions declared in trap.c. */
|
||||
extern void initialize_traps __P((void));
|
||||
|
||||
extern void run_pending_traps __P((void));
|
||||
|
||||
extern void maybe_set_sigchld_trap __P((char *));
|
||||
extern void set_impossible_sigchld_trap __P((void));
|
||||
extern void set_sigchld_trap __P((char *));
|
||||
|
||||
extern void set_debug_trap __P((char *));
|
||||
extern void set_error_trap __P((char *));
|
||||
extern void set_return_trap __P((char *));
|
||||
|
||||
extern void set_sigint_trap __P((char *));
|
||||
extern void set_signal __P((int, char *));
|
||||
|
||||
extern void restore_default_signal __P((int));
|
||||
extern void ignore_signal __P((int));
|
||||
extern int run_exit_trap __P((void));
|
||||
extern void run_trap_cleanup __P((int));
|
||||
extern int run_debug_trap __P((void));
|
||||
extern void run_error_trap __P((void));
|
||||
extern void run_return_trap __P((void));
|
||||
|
||||
extern void free_trap_strings __P((void));
|
||||
extern void reset_signal_handlers __P((void));
|
||||
extern void restore_original_signals __P((void));
|
||||
|
||||
extern void get_all_original_signals __P((void));
|
||||
|
||||
extern char *signal_name __P((int));
|
||||
|
||||
extern int decode_signal __P((char *, int));
|
||||
extern void run_interrupt_trap __P((void));
|
||||
extern int maybe_call_trap_handler __P((int));
|
||||
extern int signal_is_special __P((int));
|
||||
extern int signal_is_trapped __P((int));
|
||||
extern int signal_is_ignored __P((int));
|
||||
extern int signal_is_hard_ignored __P((int));
|
||||
extern void set_signal_ignored __P((int));
|
||||
extern int signal_in_progress __P((int));
|
||||
|
||||
#endif /* _TRAP_H_ */
|
||||
-94
@@ -1,94 +0,0 @@
|
||||
/* version.c -- distribution and version numbers. */
|
||||
|
||||
/* Copyright (C) 1989-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>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
#include "version.h"
|
||||
#include "patchlevel.h"
|
||||
#include "conftypes.h"
|
||||
|
||||
#include "bashintl.h"
|
||||
|
||||
extern char *shell_name;
|
||||
|
||||
/* Defines from version.h */
|
||||
const char * const dist_version = DISTVERSION;
|
||||
const int patch_level = PATCHLEVEL;
|
||||
const int build_version = BUILDVERSION;
|
||||
#ifdef RELSTATUS
|
||||
const char * const release_status = RELSTATUS;
|
||||
#else
|
||||
const char * const release_status = (char *)0;
|
||||
#endif
|
||||
const char * const sccs_version = SCCSVERSION;
|
||||
|
||||
const char * const bash_copyright = N_("Copyright (C) 2011 Free Software Foundation, Inc.");
|
||||
const char * const bash_license = N_("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n");
|
||||
|
||||
/* If == 31, shell compatible with bash-3.1, == 32 with bash-3.2, and so on */
|
||||
int shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
|
||||
|
||||
/* Functions for getting, setting, and displaying the shell version. */
|
||||
|
||||
/* Forward declarations so we don't have to include externs.h */
|
||||
extern char *shell_version_string __P((void));
|
||||
extern void show_shell_version __P((int));
|
||||
|
||||
/* Give version information about this shell. */
|
||||
char *
|
||||
shell_version_string ()
|
||||
{
|
||||
static char tt[32] = { '\0' };
|
||||
|
||||
if (tt[0] == '\0')
|
||||
{
|
||||
if (release_status)
|
||||
#if defined (HAVE_SNPRINTF)
|
||||
snprintf (tt, sizeof (tt), "%s.%d(%d)-%s", dist_version, patch_level, build_version, release_status);
|
||||
#else
|
||||
sprintf (tt, "%s.%d(%d)-%s", dist_version, patch_level, build_version, release_status);
|
||||
#endif
|
||||
else
|
||||
#if defined (HAVE_SNPRINTF)
|
||||
snprintf (tt, sizeof (tt), "%s.%d(%d)", dist_version, patch_level, build_version);
|
||||
#else
|
||||
sprintf (tt, "%s.%d(%d)", dist_version, patch_level, build_version);
|
||||
#endif
|
||||
}
|
||||
return tt;
|
||||
}
|
||||
|
||||
void
|
||||
show_shell_version (extended)
|
||||
int extended;
|
||||
{
|
||||
printf (_("GNU bash, version %s (%s)\n"), shell_version_string (), MACHTYPE);
|
||||
if (extended)
|
||||
{
|
||||
printf ("%s\n", _(bash_copyright));
|
||||
printf ("%s\n", _(bash_license));
|
||||
printf (_("This is free software; you are free to change and redistribute it.\n"));
|
||||
printf (_("There is NO WARRANTY, to the extent permitted by law.\n"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user