mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-03 10:20:49 +02:00
commit bash-20140117 snapshot
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
This document details the changes between this version, bash-4.3-rc1, and the
|
||||
previous version, bash-4.3-beta2.
|
||||
This document details the changes between this version, bash-4.3-rc2, and the
|
||||
previous version, bash-4.3-rc1.
|
||||
|
||||
1. Changes to Bash
|
||||
|
||||
@@ -33,6 +33,16 @@ j. Converting an existing variable to a nameref variable now turns off the
|
||||
k. Displaying a nameref variable with `declare -p' now displays the nameref
|
||||
variable and its value rather than following the nameref chain.
|
||||
|
||||
l. Fixed a problem with interrupt handling that caused a second and subsequent
|
||||
SIGINT to be ignored by interactive shells.
|
||||
|
||||
m. Fixed a bug that caused certain positional parameter and array expansions
|
||||
to mishandle (discard) null positional parameters and array elements.
|
||||
|
||||
n. The shell no longer blocks receipt of signals while running trap handlers
|
||||
for those signals, and allows trap handlers to be run recursively
|
||||
(running trap handlers while a trap handler is executing).
|
||||
|
||||
2. Changes to Readline
|
||||
|
||||
a. Fixed a bug that could cause readline to crash and seg fault attempting to
|
||||
|
||||
+64
@@ -1,3 +1,67 @@
|
||||
This document details the changes between this version, bash-4.3-rc2, and the
|
||||
previous version, bash-4.3-rc1.
|
||||
|
||||
1. Changes to Bash
|
||||
|
||||
a. Fixed a bug that left variables set by printf -v marked as invisible.
|
||||
|
||||
b. Fixed an off-by-one error in a job control warning message.
|
||||
|
||||
c. Fixed a bug that caused the shell to crash after declaring a nameref variable
|
||||
without a value.
|
||||
|
||||
d. Fixed a bug that caused asynchronous commands to not set $? correctly.
|
||||
|
||||
e. Fixed a bug that caused out-of-order execution when executing aliases with
|
||||
embedded newlines containing `.' commands.
|
||||
|
||||
f. Fixed a bug that caused error messages generated by expansion errors in
|
||||
`for' commands to have the wrong line number.
|
||||
|
||||
g. Fixed a bug that caused the `wait' builtin to not be interruptible in an
|
||||
interactive shell with job control enabled.
|
||||
|
||||
h. Fixed a bug that caused SIGINT and SIGQUIT to not be trappable in
|
||||
asynchronous subshell commands.
|
||||
|
||||
i. Bash now requires that the value assigned to a nameref variable be a valid
|
||||
shell identifier (variable name or array reference).
|
||||
|
||||
j. Converting an existing variable to a nameref variable now turns off the
|
||||
-i/-l/-u/-c attributes.
|
||||
|
||||
k. Displaying a nameref variable with `declare -p' now displays the nameref
|
||||
variable and its value rather than following the nameref chain.
|
||||
|
||||
l. Fixed a problem with interrupt handling that caused a second and subsequent
|
||||
SIGINT to be ignored by interactive shells.
|
||||
|
||||
m. Fixed a bug that caused certain positional parameter and array expansions
|
||||
to mishandle (discard) null positional parameters and array elements.
|
||||
|
||||
n. The shell no longer blocks receipt of signals while running trap handlers
|
||||
for those signals, and allows trap handlers to be run recursively
|
||||
(running trap handlers while a trap handler is executing).
|
||||
|
||||
2. Changes to Readline
|
||||
|
||||
a. Fixed a bug that could cause readline to crash and seg fault attempting to
|
||||
expand an empty history entry.
|
||||
|
||||
b. Fixed a bug that caused a bad entry in the $LS_COLORS variable to abort all
|
||||
color processing but leave color enabled.
|
||||
|
||||
c. Fixed a bug that caused display problems with multi-line prompts containing
|
||||
invisible characters on multiple lines.
|
||||
|
||||
d. Fixed a bug that caused effects made by undoing changes to a history line to
|
||||
be discarded.
|
||||
|
||||
3. New Features in Bash
|
||||
|
||||
4. New Features in Readline
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
This document details the changes between this version, bash-4.3-rc1, and the
|
||||
previous version, bash-4.3-beta2.
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
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.
|
||||
@@ -0,0 +1,544 @@
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/* 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 */
|
||||
@@ -856,6 +856,7 @@ tests/cond.tests f
|
||||
tests/cond.right f
|
||||
tests/cond-regexp1.sub f
|
||||
tests/cond-regexp2.sub f
|
||||
tests/cond-regexp3.sub f
|
||||
tests/coproc.tests f
|
||||
tests/coproc.right f
|
||||
tests/cprint.tests f
|
||||
@@ -873,6 +874,7 @@ tests/dollar-at2.sub f
|
||||
tests/dollar-at3.sub f
|
||||
tests/dollar-at4.sub f
|
||||
tests/dollar-at5.sub f
|
||||
tests/dollar-at6.sub f
|
||||
tests/dollar-star1.sub f
|
||||
tests/dollar-star2.sub f
|
||||
tests/dollar-star3.sub f
|
||||
@@ -992,6 +994,7 @@ tests/nameref4.sub f
|
||||
tests/nameref5.sub f
|
||||
tests/nameref6.sub f
|
||||
tests/nameref7.sub f
|
||||
tests/nameref8.sub f
|
||||
tests/nameref.right f
|
||||
tests/new-exp.tests f
|
||||
tests/new-exp1.sub f
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# This file is a shell script that caches the results of configure
|
||||
# tests for CYGWIN32 so they don't need to be done when cross-compiling.
|
||||
|
||||
# AC_FUNC_GETPGRP should also define GETPGRP_VOID
|
||||
ac_cv_func_getpgrp_void=${ac_cv_func_getpgrp_void='yes'}
|
||||
# AC_FUNC_SETVBUF_REVERSED should not define anything else
|
||||
ac_cv_func_setvbuf_reversed=${ac_cv_func_setvbuf_reversed='no'}
|
||||
# on CYGWIN32, system calls do not restart
|
||||
ac_cv_sys_restartable_syscalls=${ac_cv_sys_restartable_syscalls='no'}
|
||||
bash_cv_sys_restartable_syscalls=${bash_cv_sys_restartable_syscalls='no'}
|
||||
|
||||
# these may be necessary, but they are currently commented out
|
||||
#ac_cv_c_bigendian=${ac_cv_c_bigendian='no'}
|
||||
ac_cv_sizeof_char_p=${ac_cv_sizeof_char_p='4'}
|
||||
ac_cv_sizeof_int=${ac_cv_sizeof_int='4'}
|
||||
ac_cv_sizeof_long=${ac_cv_sizeof_long='4'}
|
||||
ac_cv_sizeof_double=${ac_cv_sizeof_double='8'}
|
||||
|
||||
bash_cv_dup2_broken=${bash_cv_dup2_broken='no'}
|
||||
bash_cv_pgrp_pipe=${bash_cv_pgrp_pipe='no'}
|
||||
bash_cv_type_rlimit=${bash_cv_type_rlimit='long'}
|
||||
bash_cv_decl_under_sys_siglist=${bash_cv_decl_under_sys_siglist='no'}
|
||||
bash_cv_under_sys_siglist=${bash_cv_under_sys_siglist='no'}
|
||||
bash_cv_sys_siglist=${bash_cv_sys_siglist='no'}
|
||||
bash_cv_opendir_not_robust=${bash_cv_opendir_not_robust='no'}
|
||||
bash_cv_getenv_redef=${bash_cv_getenv_redef='yes'}
|
||||
bash_cv_printf_declared=${bash_cv_printf_declared='yes'}
|
||||
bash_cv_ulimit_maxfds=${bash_cv_ulimit_maxfds='no'}
|
||||
bash_cv_getcwd_calls_popen=${bash_cv_getcwd_calls_popen='no'}
|
||||
bash_cv_must_reinstall_sighandlers=${bash_cv_must_reinstall_sighandlers='no'}
|
||||
bash_cv_job_control_missing=${bash_cv_job_control_missing='present'}
|
||||
bash_cv_sys_named_pipes=${bash_cv_sys_named_pipes='missing'}
|
||||
bash_cv_func_sigsetjmp=${bash_cv_func_sigsetjmp='missing'}
|
||||
bash_cv_mail_dir=${bash_cv_mail_dir='unknown'}
|
||||
bash_cv_func_strcoll_broken=${bash_cv_func_strcoll_broken='no'}
|
||||
|
||||
bash_cv_type_int32_t=${bash_cv_type_int32_t='int'}
|
||||
bash_cv_type_u_int32_t=${bash_cv_type_u_int32_t='int'}
|
||||
|
||||
ac_cv_type_bits64_t=${ac_cv_type_bits64_t='no'}
|
||||
|
||||
# end of cross-build/cygwin32.cache
|
||||
+1745
File diff suppressed because it is too large
Load Diff
@@ -6087,6 +6087,7 @@ and store the definition.
|
||||
.B call\-last\-kbd\-macro (C\-x e)
|
||||
Re-execute the last keyboard macro defined, by making the characters
|
||||
in the macro appear as if typed at the keyboard.
|
||||
.TP
|
||||
.B print\-last\-kbd\-macro ()
|
||||
Print the last keyboard macro defined in a format suitable for the
|
||||
\fIinputrc\fP file.
|
||||
|
||||
@@ -340,6 +340,36 @@ parser_error (lineno, format, va_alist)
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* This assumes ASCII and is suitable only for debugging */
|
||||
char *
|
||||
strescape (str)
|
||||
const char *str;
|
||||
{
|
||||
char *r, *result;
|
||||
unsigned char *s;
|
||||
|
||||
r = result = (char *)xmalloc (strlen (str) * 2 + 1);
|
||||
|
||||
for (s = (unsigned char *)str; s && *s; s++)
|
||||
{
|
||||
if (*s < ' ')
|
||||
{
|
||||
*r++ = '^';
|
||||
*r++ = *s+64;
|
||||
}
|
||||
else if (*s == 127)
|
||||
{
|
||||
*r++ = '^';
|
||||
*r++ = '?';
|
||||
}
|
||||
else
|
||||
*r++ = *s;
|
||||
}
|
||||
|
||||
*r = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
#if defined (PREFER_STDARG)
|
||||
itrace (const char *format, ...)
|
||||
|
||||
@@ -51,6 +51,7 @@ extern void internal_error __P((const char *, ...)) __attribute__((__format__ (
|
||||
extern void internal_warning __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
|
||||
|
||||
/* Debugging functions, not enabled in released version. */
|
||||
extern char *strescape __P((const char *));
|
||||
extern void itrace __P((const char *, ...)) __attribute__ ((__format__ (printf, 1, 2)));
|
||||
extern void trace __P((const char *, ...)) __attribute__ ((__format__ (printf, 1, 2)));
|
||||
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
#
|
||||
# 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
|
||||
+8
-1
@@ -3504,6 +3504,7 @@ execute_cond_node (cond)
|
||||
{
|
||||
int result, invert, patmatch, rmatch, mflags, ignore;
|
||||
char *arg1, *arg2;
|
||||
char *t1, *t2;
|
||||
|
||||
invert = (cond->flags & CMD_INVERT_RETURN);
|
||||
ignore = (cond->flags & CMD_IGNORE_RETURN);
|
||||
@@ -3581,7 +3582,13 @@ execute_cond_node (cond)
|
||||
#if defined (ARRAY_VARS)
|
||||
mflags |= SHMAT_SUBEXP;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
t1 = strescape(arg1);
|
||||
t2 = strescape(arg2);
|
||||
itrace("execute_cond_node: sh_regmatch on `%s' and `%s'", t1, t2);
|
||||
free(t1);
|
||||
free(t2);
|
||||
#endif
|
||||
result = sh_regmatch (arg1, arg2, mflags);
|
||||
}
|
||||
else
|
||||
|
||||
+5427
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,76 @@
|
||||
# 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,6 +1,6 @@
|
||||
/* pathexp.c -- The shell interface to the globbing library. */
|
||||
|
||||
/* Copyright (C) 1995-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1995-2014 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -196,7 +196,13 @@ quote_string_for_globbing (pathname, qflags)
|
||||
brack = cclass = collsym = equiv = 0;
|
||||
for (i = j = 0; pathname[i]; i++)
|
||||
{
|
||||
if (pathname[i] == CTLESC)
|
||||
/* Fix for CTLESC at the end of the string? */
|
||||
if (pathname[i] == CTLESC && pathname[i+1] == '\0')
|
||||
{
|
||||
temp[j++] = pathname[i++];
|
||||
break;
|
||||
}
|
||||
else if (pathname[i] == CTLESC)
|
||||
{
|
||||
if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
|
||||
continue;
|
||||
@@ -274,10 +280,18 @@ quote_string_for_globbing (pathname, qflags)
|
||||
}
|
||||
else if (pathname[i] == '\\')
|
||||
{
|
||||
/* If we want to pass through backslash unaltered, comment out these
|
||||
lines. */
|
||||
temp[j++] = '\\';
|
||||
i++;
|
||||
if (pathname[i] == '\0')
|
||||
break;
|
||||
/* XXX - if not quoting regexp, use backslash as quote char. Should
|
||||
we just pass it through without treating it as special? That is
|
||||
what ksh93 seems to do. */
|
||||
if ((qflags & QGLOB_REGEXP) == 0)
|
||||
{
|
||||
i++;
|
||||
if (pathname[i] == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
temp[j++] = pathname[i];
|
||||
}
|
||||
|
||||
+597
@@ -0,0 +1,597 @@
|
||||
/* pathexp.c -- The shell interface to the globbing library. */
|
||||
|
||||
/* Copyright (C) 1995-2014 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 <stdio.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "bashansi.h"
|
||||
|
||||
#include "shell.h"
|
||||
#include "pathexp.h"
|
||||
#include "flags.h"
|
||||
|
||||
#include "shmbutil.h"
|
||||
#include "bashintl.h"
|
||||
|
||||
#include <glob/strmatch.h>
|
||||
|
||||
static int glob_name_is_acceptable __P((const char *));
|
||||
static void ignore_globbed_names __P((char **, sh_ignore_func_t *));
|
||||
static char *split_ignorespec __P((char *, int *));
|
||||
|
||||
#if defined (USE_POSIX_GLOB_LIBRARY)
|
||||
# include <glob.h>
|
||||
typedef int posix_glob_errfunc_t __P((const char *, int));
|
||||
#else
|
||||
# include <glob/glob.h>
|
||||
#endif
|
||||
|
||||
/* Control whether * matches .files in globbing. */
|
||||
int glob_dot_filenames;
|
||||
|
||||
/* Control whether the extended globbing features are enabled. */
|
||||
int extended_glob = EXTGLOB_DEFAULT;
|
||||
|
||||
/* Control enabling special handling of `**' */
|
||||
int glob_star = 0;
|
||||
|
||||
/* Return nonzero if STRING has any unquoted special globbing chars in it. */
|
||||
int
|
||||
unquoted_glob_pattern_p (string)
|
||||
register char *string;
|
||||
{
|
||||
register int c;
|
||||
char *send;
|
||||
int open;
|
||||
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
open = 0;
|
||||
send = string + strlen (string);
|
||||
|
||||
while (c = *string++)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '?':
|
||||
case '*':
|
||||
return (1);
|
||||
|
||||
case '[':
|
||||
open++;
|
||||
continue;
|
||||
|
||||
case ']':
|
||||
if (open)
|
||||
return (1);
|
||||
continue;
|
||||
|
||||
case '+':
|
||||
case '@':
|
||||
case '!':
|
||||
if (*string == '(') /*)*/
|
||||
return (1);
|
||||
continue;
|
||||
|
||||
case CTLESC:
|
||||
case '\\':
|
||||
if (*string++ == '\0')
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Advance one fewer byte than an entire multibyte character to
|
||||
account for the auto-increment in the loop above. */
|
||||
#ifdef HANDLE_MULTIBYTE
|
||||
string--;
|
||||
ADVANCE_CHAR_P (string, send - string);
|
||||
string++;
|
||||
#else
|
||||
ADVANCE_CHAR_P (string, send - string);
|
||||
#endif
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Return 1 if C is a character that is `special' in a POSIX ERE and needs to
|
||||
be quoted to match itself. */
|
||||
static inline int
|
||||
ere_char (c)
|
||||
int c;
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '.':
|
||||
case '[':
|
||||
case '\\':
|
||||
case '(':
|
||||
case ')':
|
||||
case '*':
|
||||
case '+':
|
||||
case '?':
|
||||
case '{':
|
||||
case '|':
|
||||
case '^':
|
||||
case '$':
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
glob_char_p (s)
|
||||
const char *s;
|
||||
{
|
||||
switch (*s)
|
||||
{
|
||||
case '*':
|
||||
case '[':
|
||||
case ']':
|
||||
case '?':
|
||||
case '\\':
|
||||
return 1;
|
||||
case '+':
|
||||
case '@':
|
||||
case '!':
|
||||
if (s[1] == '(') /*(*/
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* PATHNAME can contain characters prefixed by CTLESC; this indicates
|
||||
that the character is to be quoted. We quote it here in the style
|
||||
that the glob library recognizes. If flags includes QGLOB_CVTNULL,
|
||||
we change quoted null strings (pathname[0] == CTLNUL) into empty
|
||||
strings (pathname[0] == 0). If this is called after quote removal
|
||||
is performed, (flags & QGLOB_CVTNULL) should be 0; if called when quote
|
||||
removal has not been done (for example, before attempting to match a
|
||||
pattern while executing a case statement), flags should include
|
||||
QGLOB_CVTNULL. If flags includes QGLOB_FILENAME, appropriate quoting
|
||||
to match a filename should be performed. QGLOB_REGEXP means we're
|
||||
quoting for a Posix ERE (for [[ string =~ pat ]]) and that requires
|
||||
some special handling. */
|
||||
char *
|
||||
quote_string_for_globbing (pathname, qflags)
|
||||
const char *pathname;
|
||||
int qflags;
|
||||
{
|
||||
char *temp;
|
||||
register int i, j;
|
||||
int brack, cclass, collsym, equiv, c;
|
||||
|
||||
temp = (char *)xmalloc (strlen (pathname) + 1);
|
||||
|
||||
if ((qflags & QGLOB_CVTNULL) && QUOTED_NULL (pathname))
|
||||
{
|
||||
temp[0] = '\0';
|
||||
return temp;
|
||||
}
|
||||
|
||||
brack = cclass = collsym = equiv = 0;
|
||||
for (i = j = 0; pathname[i]; i++)
|
||||
{
|
||||
/* Fix for CTLESC at the end of the string? */
|
||||
if (pathname[i] == CTLESC && pathname[i+1] == '\0')
|
||||
{
|
||||
temp[j++] = pathname[i++];
|
||||
break;
|
||||
}
|
||||
else if (pathname[i] == CTLESC)
|
||||
{
|
||||
if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
|
||||
continue;
|
||||
if (pathname[i+1] != CTLESC && (qflags & QGLOB_REGEXP) && ere_char (pathname[i+1]) == 0)
|
||||
continue;
|
||||
temp[j++] = '\\';
|
||||
i++;
|
||||
if (pathname[i] == '\0')
|
||||
break;
|
||||
}
|
||||
else if ((qflags & QGLOB_REGEXP) && (i == 0 || pathname[i-1] != CTLESC) && pathname[i] == '[') /*]*/
|
||||
{
|
||||
brack = 1;
|
||||
temp[j++] = pathname[i++]; /* open bracket */
|
||||
c = pathname[i++]; /* c == char after open bracket */
|
||||
do
|
||||
{
|
||||
if (c == 0)
|
||||
goto endpat;
|
||||
else if (c == CTLESC)
|
||||
{
|
||||
/* skip c, check for EOS, let assignment at end of loop */
|
||||
/* pathname[i] == backslash-escaped character */
|
||||
if (pathname[i] == 0)
|
||||
goto endpat;
|
||||
temp[j++] = pathname[i++];
|
||||
}
|
||||
else if (c == '[' && pathname[i] == ':')
|
||||
{
|
||||
temp[j++] = c;
|
||||
temp[j++] = pathname[i++];
|
||||
cclass = 1;
|
||||
}
|
||||
else if (cclass && c == ':' && pathname[i] == ']')
|
||||
{
|
||||
temp[j++] = c;
|
||||
temp[j++] = pathname[i++];
|
||||
cclass = 0;
|
||||
}
|
||||
else if (c == '[' && pathname[i] == '=')
|
||||
{
|
||||
temp[j++] = c;
|
||||
temp[j++] = pathname[i++];
|
||||
if (pathname[i] == ']')
|
||||
temp[j++] = pathname[i++]; /* right brack can be in equiv */
|
||||
equiv = 1;
|
||||
}
|
||||
else if (equiv && c == '=' && pathname[i] == ']')
|
||||
{
|
||||
temp[j++] = c;
|
||||
temp[j++] = pathname[i++];
|
||||
equiv = 0;
|
||||
}
|
||||
else if (c == '[' && pathname[i] == '.')
|
||||
{
|
||||
temp[j++] = c;
|
||||
temp[j++] = pathname[i++];
|
||||
if (pathname[i] == ']')
|
||||
temp[j++] = pathname[i++]; /* right brack can be in collsym */
|
||||
collsym = 1;
|
||||
}
|
||||
else if (collsym && c == '.' && pathname[i] == ']')
|
||||
{
|
||||
temp[j++] = c;
|
||||
temp[j++] = pathname[i++];
|
||||
collsym = 0;
|
||||
}
|
||||
else
|
||||
temp[j++] = c;
|
||||
}
|
||||
while ((c = pathname[i++]) != ']');
|
||||
temp[j++] = c; /* closing right bracket */
|
||||
i--; /* increment will happen above in loop */
|
||||
continue; /* skip double assignment below */
|
||||
}
|
||||
else if (pathname[i] == '\\')
|
||||
{
|
||||
temp[j++] = '\\';
|
||||
/* XXX - if not quoting regexp, use backslash as quote char. Should
|
||||
we just pass it through without treating it as special? That is
|
||||
what ksh93 seems to do. */
|
||||
if ((qflags & QGLOB_REGEXP) == 0)
|
||||
{
|
||||
i++;
|
||||
if (pathname[i] == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
temp[j++] = pathname[i];
|
||||
}
|
||||
endpat:
|
||||
temp[j] = '\0';
|
||||
|
||||
return (temp);
|
||||
}
|
||||
|
||||
char *
|
||||
quote_globbing_chars (string)
|
||||
char *string;
|
||||
{
|
||||
size_t slen;
|
||||
char *temp, *s, *t, *send;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string);
|
||||
send = string + slen;
|
||||
|
||||
temp = (char *)xmalloc (slen * 2 + 1);
|
||||
for (t = temp, s = string; *s; )
|
||||
{
|
||||
if (glob_char_p (s))
|
||||
*t++ = '\\';
|
||||
|
||||
/* Copy a single (possibly multibyte) character from s to t,
|
||||
incrementing both. */
|
||||
COPY_CHAR_P (t, s, send);
|
||||
}
|
||||
*t = '\0';
|
||||
return temp;
|
||||
}
|
||||
|
||||
/* Call the glob library to do globbing on PATHNAME. */
|
||||
char **
|
||||
shell_glob_filename (pathname)
|
||||
const char *pathname;
|
||||
{
|
||||
#if defined (USE_POSIX_GLOB_LIBRARY)
|
||||
register int i;
|
||||
char *temp, **results;
|
||||
glob_t filenames;
|
||||
int glob_flags;
|
||||
|
||||
temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
|
||||
|
||||
filenames.gl_offs = 0;
|
||||
|
||||
# if defined (GLOB_PERIOD)
|
||||
glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
|
||||
# else
|
||||
glob_flags = 0;
|
||||
# endif /* !GLOB_PERIOD */
|
||||
|
||||
glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
|
||||
|
||||
i = glob (temp, glob_flags, (posix_glob_errfunc_t *)NULL, &filenames);
|
||||
|
||||
free (temp);
|
||||
|
||||
if (i == GLOB_NOSPACE || i == GLOB_ABORTED)
|
||||
return ((char **)NULL);
|
||||
else if (i == GLOB_NOMATCH)
|
||||
filenames.gl_pathv = (char **)NULL;
|
||||
else if (i != 0) /* other error codes not in POSIX.2 */
|
||||
filenames.gl_pathv = (char **)NULL;
|
||||
|
||||
results = filenames.gl_pathv;
|
||||
|
||||
if (results && ((GLOB_FAILED (results)) == 0))
|
||||
{
|
||||
if (should_ignore_glob_matches ())
|
||||
ignore_glob_matches (results);
|
||||
if (results && results[0])
|
||||
strvec_sort (results);
|
||||
else
|
||||
{
|
||||
FREE (results);
|
||||
results = (char **)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (results);
|
||||
|
||||
#else /* !USE_POSIX_GLOB_LIBRARY */
|
||||
|
||||
char *temp, **results;
|
||||
|
||||
noglob_dot_filenames = glob_dot_filenames == 0;
|
||||
|
||||
temp = quote_string_for_globbing (pathname, QGLOB_FILENAME);
|
||||
results = glob_filename (temp, glob_star ? GX_GLOBSTAR : 0);
|
||||
free (temp);
|
||||
|
||||
if (results && ((GLOB_FAILED (results)) == 0))
|
||||
{
|
||||
if (should_ignore_glob_matches ())
|
||||
ignore_glob_matches (results);
|
||||
if (results && results[0])
|
||||
strvec_sort (results);
|
||||
else
|
||||
{
|
||||
FREE (results);
|
||||
results = (char **)&glob_error_return;
|
||||
}
|
||||
}
|
||||
|
||||
return (results);
|
||||
#endif /* !USE_POSIX_GLOB_LIBRARY */
|
||||
}
|
||||
|
||||
/* Stuff for GLOBIGNORE. */
|
||||
|
||||
static struct ignorevar globignore =
|
||||
{
|
||||
"GLOBIGNORE",
|
||||
(struct ign *)0,
|
||||
0,
|
||||
(char *)0,
|
||||
(sh_iv_item_func_t *)0,
|
||||
};
|
||||
|
||||
/* Set up to ignore some glob matches because the value of GLOBIGNORE
|
||||
has changed. If GLOBIGNORE is being unset, we also need to disable
|
||||
the globbing of filenames beginning with a `.'. */
|
||||
void
|
||||
setup_glob_ignore (name)
|
||||
char *name;
|
||||
{
|
||||
char *v;
|
||||
|
||||
v = get_string_value (name);
|
||||
setup_ignore_patterns (&globignore);
|
||||
|
||||
if (globignore.num_ignores)
|
||||
glob_dot_filenames = 1;
|
||||
else if (v == 0)
|
||||
glob_dot_filenames = 0;
|
||||
}
|
||||
|
||||
int
|
||||
should_ignore_glob_matches ()
|
||||
{
|
||||
return globignore.num_ignores;
|
||||
}
|
||||
|
||||
/* Return 0 if NAME matches a pattern in the globignore.ignores list. */
|
||||
static int
|
||||
glob_name_is_acceptable (name)
|
||||
const char *name;
|
||||
{
|
||||
struct ign *p;
|
||||
int flags;
|
||||
|
||||
/* . and .. are never matched */
|
||||
if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
|
||||
return (0);
|
||||
|
||||
flags = FNM_PATHNAME | FNMATCH_EXTFLAG;
|
||||
for (p = globignore.ignores; p->val; p++)
|
||||
{
|
||||
if (strmatch (p->val, (char *)name, flags) != FNM_NOMATCH)
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Internal function to test whether filenames in NAMES should be
|
||||
ignored. NAME_FUNC is a pointer to a function to call with each
|
||||
name. It returns non-zero if the name is acceptable to the particular
|
||||
ignore function which called _ignore_names; zero if the name should
|
||||
be removed from NAMES. */
|
||||
|
||||
static void
|
||||
ignore_globbed_names (names, name_func)
|
||||
char **names;
|
||||
sh_ignore_func_t *name_func;
|
||||
{
|
||||
char **newnames;
|
||||
int n, i;
|
||||
|
||||
for (i = 0; names[i]; i++)
|
||||
;
|
||||
newnames = strvec_create (i + 1);
|
||||
|
||||
for (n = i = 0; names[i]; i++)
|
||||
{
|
||||
if ((*name_func) (names[i]))
|
||||
newnames[n++] = names[i];
|
||||
else
|
||||
free (names[i]);
|
||||
}
|
||||
|
||||
newnames[n] = (char *)NULL;
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
names[0] = (char *)NULL;
|
||||
free (newnames);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy the acceptable names from NEWNAMES back to NAMES and set the
|
||||
new array end. */
|
||||
for (n = 0; newnames[n]; n++)
|
||||
names[n] = newnames[n];
|
||||
names[n] = (char *)NULL;
|
||||
free (newnames);
|
||||
}
|
||||
|
||||
void
|
||||
ignore_glob_matches (names)
|
||||
char **names;
|
||||
{
|
||||
if (globignore.num_ignores == 0)
|
||||
return;
|
||||
|
||||
ignore_globbed_names (names, glob_name_is_acceptable);
|
||||
}
|
||||
|
||||
static char *
|
||||
split_ignorespec (s, ip)
|
||||
char *s;
|
||||
int *ip;
|
||||
{
|
||||
char *t;
|
||||
int n, i;
|
||||
|
||||
if (s == 0)
|
||||
return 0;
|
||||
|
||||
i = *ip;
|
||||
if (s[i] == 0)
|
||||
return 0;
|
||||
|
||||
n = skip_to_delim (s, i, ":", SD_NOJMP|SD_EXTGLOB);
|
||||
t = substring (s, i, n);
|
||||
|
||||
if (s[n] == ':')
|
||||
n++;
|
||||
*ip = n;
|
||||
return t;
|
||||
}
|
||||
|
||||
void
|
||||
setup_ignore_patterns (ivp)
|
||||
struct ignorevar *ivp;
|
||||
{
|
||||
int numitems, maxitems, ptr;
|
||||
char *colon_bit, *this_ignoreval;
|
||||
struct ign *p;
|
||||
|
||||
this_ignoreval = get_string_value (ivp->varname);
|
||||
|
||||
/* If nothing has changed then just exit now. */
|
||||
if ((this_ignoreval && ivp->last_ignoreval && STREQ (this_ignoreval, ivp->last_ignoreval)) ||
|
||||
(!this_ignoreval && !ivp->last_ignoreval))
|
||||
return;
|
||||
|
||||
/* Oops. The ignore variable has changed. Re-parse it. */
|
||||
ivp->num_ignores = 0;
|
||||
|
||||
if (ivp->ignores)
|
||||
{
|
||||
for (p = ivp->ignores; p->val; p++)
|
||||
free(p->val);
|
||||
free (ivp->ignores);
|
||||
ivp->ignores = (struct ign *)NULL;
|
||||
}
|
||||
|
||||
if (ivp->last_ignoreval)
|
||||
{
|
||||
free (ivp->last_ignoreval);
|
||||
ivp->last_ignoreval = (char *)NULL;
|
||||
}
|
||||
|
||||
if (this_ignoreval == 0 || *this_ignoreval == '\0')
|
||||
return;
|
||||
|
||||
ivp->last_ignoreval = savestring (this_ignoreval);
|
||||
|
||||
numitems = maxitems = ptr = 0;
|
||||
|
||||
#if 0
|
||||
while (colon_bit = extract_colon_unit (this_ignoreval, &ptr))
|
||||
#else
|
||||
while (colon_bit = split_ignorespec (this_ignoreval, &ptr))
|
||||
#endif
|
||||
{
|
||||
if (numitems + 1 >= maxitems)
|
||||
{
|
||||
maxitems += 10;
|
||||
ivp->ignores = (struct ign *)xrealloc (ivp->ignores, maxitems * sizeof (struct ign));
|
||||
}
|
||||
ivp->ignores[numitems].val = colon_bit;
|
||||
ivp->ignores[numitems].len = strlen (colon_bit);
|
||||
ivp->ignores[numitems].flags = 0;
|
||||
if (ivp->item_func)
|
||||
(*ivp->item_func) (&ivp->ignores[numitems]);
|
||||
numitems++;
|
||||
}
|
||||
ivp->ignores[numitems].val = (char *)NULL;
|
||||
ivp->num_ignores = numitems;
|
||||
}
|
||||
@@ -1607,7 +1607,7 @@ set_shell_name (argv0)
|
||||
{
|
||||
if (*shell_name == '-')
|
||||
shell_name++;
|
||||
login_shell++;
|
||||
login_shell = 1;
|
||||
}
|
||||
|
||||
if (shell_name[0] == 's' && shell_name[1] == 'h' && shell_name[2] == '\0')
|
||||
|
||||
@@ -220,6 +220,8 @@ static WORD_LIST *expand_string_leave_quoted __P((char *, int));
|
||||
static WORD_LIST *expand_string_for_rhs __P((char *, int, int *, int *));
|
||||
|
||||
static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
|
||||
static WORD_LIST *list_dequote_escapes __P((WORD_LIST *));
|
||||
|
||||
static char *make_quoted_char __P((int));
|
||||
static WORD_LIST *quote_list __P((WORD_LIST *));
|
||||
|
||||
@@ -3250,13 +3252,16 @@ cond_expand_word (w, special)
|
||||
l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
|
||||
if (l)
|
||||
{
|
||||
if (special == 0)
|
||||
if (special == 0) /* LHS */
|
||||
{
|
||||
dequote_list (l);
|
||||
r = string_list (l);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Need to figure out whether or not we should call dequote_escapes
|
||||
or a new dequote_ctlnul function here, and under what
|
||||
circumstances. */
|
||||
qflags = QGLOB_CVTNULL;
|
||||
if (special == 2)
|
||||
qflags |= QGLOB_REGEXP;
|
||||
@@ -3544,6 +3549,7 @@ quote_escapes (string)
|
||||
COPY_CHAR_P (t, s, send);
|
||||
}
|
||||
*t = '\0';
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
@@ -3609,9 +3615,26 @@ dequote_escapes (string)
|
||||
COPY_CHAR_P (t, s, send);
|
||||
}
|
||||
*t = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static WORD_LIST *
|
||||
list_dequote_escapes (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
register WORD_LIST *w;
|
||||
char *t;
|
||||
|
||||
for (w = list; w; w = w->next)
|
||||
{
|
||||
t = w->word->word;
|
||||
w->word->word = dequote_escapes (t);
|
||||
free (t);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/* Return a new string with the quoted representation of character C.
|
||||
This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
|
||||
set in any resultant WORD_DESC where this value is the word. */
|
||||
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
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 "$@"
|
||||
@@ -0,0 +1,66 @@
|
||||
# simple expansion -- no problem, it's quote_string_for_globbing that was flawed
|
||||
c=$'\177'
|
||||
r="\\$c"
|
||||
|
||||
recho $r
|
||||
|
||||
# first, match some regular expressions containing ^A, ^G, ^?
|
||||
[[ $'\001' =~ $'\001' ]] ; echo $?
|
||||
[[ $'\001' =~ $'\\\001' ]] ; echo $?
|
||||
[[ $'\001' =~ $'\\[\001]' ]] ; echo $?
|
||||
|
||||
[[ $'\a' =~ $'\a' ]] ; echo $?
|
||||
[[ $'\a' =~ $'\\\a' ]] ; echo $?
|
||||
[[ $'\a' =~ $'\\[\a]' ]] ; echo $?
|
||||
|
||||
[[ $'\177' =~ $'\177' ]] ; echo $?
|
||||
[[ $'\177' =~ $'\\\177' ]] ; echo $?
|
||||
[[ $'\177' =~ $'\\[\177]' ]] ; echo $?
|
||||
|
||||
# Now let's try it with variables expanding to those values
|
||||
for c in $'\001' $'\a' $'\177' ; do
|
||||
for r in "$c" "\\$c" "\\[$c]"; do
|
||||
[[ $c =~ $r ]];
|
||||
printf '[[ %q =~ %q ]] -> %d\n' "$c" "$r" "$?";
|
||||
done;
|
||||
printf %s\\n ---
|
||||
done
|
||||
|
||||
# try again with literals
|
||||
|
||||
[[ '' =~ $'' ]] ; echo $?
|
||||
[[ '' =~ '\' ]] ; echo $?
|
||||
[[ '' =~ '\[]' ]] ; echo $?
|
||||
|
||||
[[ '' =~ '' ]] ; echo $?
|
||||
[[ '' =~ '\' ]] ; echo $?
|
||||
[[ '' =~ '\[]' ]] ; echo $?
|
||||
|
||||
[[ '' =~ $'' ]] ; echo $?
|
||||
[[ '' =~ '\' ]] ; echo $?
|
||||
[[ '' =~ '\[]' ]] ; echo $?
|
||||
|
||||
# more expansions, but with literal non-special characters
|
||||
[[ x =~ \x ]] ; echo $?
|
||||
[[ x =~ \\x ]] ; echo $?
|
||||
|
||||
bs='\'
|
||||
[[ x =~ ${bs}x ]] ; echo $?
|
||||
|
||||
[[ x =~ $'\\'x ]] ; echo $?
|
||||
[[ x =~ '\'x ]] ; echo $?
|
||||
|
||||
c=$'\001'
|
||||
|
||||
recho $c "$c"
|
||||
|
||||
[[ $c == $c ]] && echo ok 1
|
||||
[[ $c =~ $c ]] && echo ok 2
|
||||
[[ $c =~ \\$c ]] || echo ok 3
|
||||
[[ $c =~ \\"$c" ]] || echo ok 4
|
||||
|
||||
[[ $c =~ "\\"$c ]] || echo ok 5
|
||||
[[ $c =~ '\'$c ]] || echo ok 6
|
||||
|
||||
[[ $c =~ "\\""$c" ]] || echo ok 7
|
||||
[[ $c =~ '\'"$c" ]] || echo ok 8
|
||||
@@ -78,3 +78,49 @@ ok 9
|
||||
ok 10
|
||||
ok 11
|
||||
ok 12
|
||||
argv[1] = <\^?>
|
||||
0
|
||||
1
|
||||
1
|
||||
0
|
||||
1
|
||||
1
|
||||
0
|
||||
1
|
||||
1
|
||||
[[ $'\001' =~ $'\001' ]] -> 0
|
||||
[[ $'\001' =~ $'\\\001' ]] -> 1
|
||||
[[ $'\001' =~ $'\\[\001]' ]] -> 1
|
||||
---
|
||||
[[ $'\a' =~ $'\a' ]] -> 0
|
||||
[[ $'\a' =~ $'\\\a' ]] -> 1
|
||||
[[ $'\a' =~ $'\\[\a]' ]] -> 1
|
||||
---
|
||||
[[ $'\177' =~ $'\177' ]] -> 0
|
||||
[[ $'\177' =~ $'\\\177' ]] -> 1
|
||||
[[ $'\177' =~ $'\\[\177]' ]] -> 1
|
||||
---
|
||||
0
|
||||
1
|
||||
1
|
||||
0
|
||||
1
|
||||
1
|
||||
0
|
||||
1
|
||||
1
|
||||
0
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
argv[1] = <^A>
|
||||
argv[2] = <^A>
|
||||
ok 1
|
||||
ok 2
|
||||
ok 3
|
||||
ok 4
|
||||
ok 5
|
||||
ok 6
|
||||
ok 7
|
||||
ok 8
|
||||
|
||||
@@ -183,3 +183,5 @@ if [[ "123abc" == *?(a)bc ]]; then echo ok 43; else echo bad 43; fi
|
||||
${THIS_SH} ./cond-regexp1.sub
|
||||
|
||||
${THIS_SH} ./cond-regexp2.sub
|
||||
|
||||
${THIS_SH} ./cond-regexp3.sub
|
||||
|
||||
Executable
+185
@@ -0,0 +1,185 @@
|
||||
#
|
||||
# the test/[ code is tested elsewhere, and the [[...]] just uses the same
|
||||
# code. this tests the special features of [[...]]
|
||||
#
|
||||
TDIR=/usr/homes/chet
|
||||
|
||||
# this one is straight out of the ksh88 book
|
||||
[[ foo > bar && $PWD -ef . ]]
|
||||
echo returns: $?
|
||||
|
||||
# [[ x ]] is equivalent to [[ -n x ]]
|
||||
[[ x ]]
|
||||
echo returns: $?
|
||||
|
||||
# [[ ! x ]] is equivalent to [[ ! -n x ]]
|
||||
[[ ! x ]]
|
||||
echo returns: $?
|
||||
|
||||
# ! binds tighter than test/[ -- it binds to a term, not an expression
|
||||
[[ ! x || x ]]
|
||||
echo returns: $?
|
||||
|
||||
# parenthesized terms didn't work right until post-2.04
|
||||
[[ a ]]
|
||||
echo returns: $?
|
||||
|
||||
[[ (a) ]]
|
||||
echo returns: $?
|
||||
|
||||
[[ -n a ]]
|
||||
echo returns: $?
|
||||
|
||||
[[ (-n a) ]]
|
||||
echo returns: $?
|
||||
|
||||
# unset variables don't need to be quoted
|
||||
[[ -n $UNSET ]]
|
||||
echo returns: $?
|
||||
|
||||
[[ -z $UNSET ]]
|
||||
echo returns: $?
|
||||
|
||||
# the ==/= and != operators do pattern matching
|
||||
[[ $TDIR == /usr/homes/* ]]
|
||||
echo returns: $?
|
||||
|
||||
# ...but you can quote any part of the pattern to have it matched as a string
|
||||
[[ $TDIR == /usr/homes/\* ]]
|
||||
echo returns: $?
|
||||
|
||||
[[ $TDIR == '/usr/homes/*' ]]
|
||||
echo returns: $?
|
||||
|
||||
# if the first part of && fails, the second is not executed
|
||||
[[ -n $UNSET && $UNSET == foo ]]
|
||||
echo returns: $?
|
||||
|
||||
[[ -z $UNSET && $UNSET == foo ]]
|
||||
echo returns: $?
|
||||
|
||||
# if the first part of || succeeds, the second is not executed
|
||||
[[ -z $UNSET || -d $PWD ]]
|
||||
echo returns: $?
|
||||
|
||||
# if the rhs were executed, it would be an error
|
||||
[[ -n $TDIR || $HOME -ef ${H*} ]]
|
||||
echo returns: $?
|
||||
|
||||
[[ -n $TDIR && -z $UNSET || $HOME -ef ${H*} ]]
|
||||
echo returns: $?
|
||||
|
||||
# && has a higher parsing precedence than ||
|
||||
[[ -n $TDIR && -n $UNSET || $TDIR -ef . ]]
|
||||
echo returns: $?
|
||||
|
||||
# ...but expressions in parentheses may be used to override precedence rules
|
||||
[[ -n $TDIR || -n $UNSET && $PWD -ef xyz ]]
|
||||
echo returns: $?
|
||||
|
||||
[[ ( -n $TDIR || -n $UNSET ) && $PWD -ef xyz ]]
|
||||
echo returns: $?
|
||||
|
||||
# some arithmetic tests for completeness -- see what happens with missing
|
||||
# operands, bad expressions, makes sure arguments are evaluated as
|
||||
# arithmetic expressions, etc.
|
||||
|
||||
unset IVAR A
|
||||
[[ 7 -gt $IVAR ]]
|
||||
echo returns: $?
|
||||
|
||||
[[ $IVAR -gt 7 ]]
|
||||
echo returns: $?
|
||||
|
||||
IVAR=4
|
||||
[[ $IVAR -gt 7 ]]
|
||||
echo returns: $?
|
||||
|
||||
[[ 7 -eq 4+3 ]]
|
||||
echo returns: $?
|
||||
|
||||
[[ 7 -eq 4+ ]]
|
||||
echo returns: $?
|
||||
|
||||
IVAR=4+3
|
||||
[[ $IVAR -eq 7 ]]
|
||||
echo returns: $?
|
||||
|
||||
A=7
|
||||
[[ $IVAR -eq A ]]
|
||||
echo returns: $?
|
||||
|
||||
unset IVAR A
|
||||
|
||||
# more pattern matching tests
|
||||
|
||||
[[ $filename == *.c ]]
|
||||
echo returns: $?
|
||||
|
||||
filename=patmatch.c
|
||||
|
||||
[[ $filename == *.c ]]
|
||||
echo returns: $?
|
||||
|
||||
# the extended globbing features may be used when matching patterns
|
||||
shopt -s extglob
|
||||
|
||||
arg=-7
|
||||
|
||||
[[ $arg == -+([0-9]) ]]
|
||||
echo returns: $?
|
||||
|
||||
arg=-H
|
||||
|
||||
[[ $arg == -+([0-9]) ]]
|
||||
echo returns: $?
|
||||
|
||||
arg=+4
|
||||
[[ $arg == ++([0-9]) ]]
|
||||
echo returns: $?
|
||||
|
||||
# make sure the null string is never matched if the string is not null
|
||||
STR=file.c
|
||||
PAT=
|
||||
|
||||
if [[ $STR = $PAT ]]; then
|
||||
echo oops
|
||||
fi
|
||||
|
||||
# but that if the string is null, a null pattern is matched correctly
|
||||
STR=
|
||||
PAT=
|
||||
|
||||
if [[ $STR = $PAT ]]; then
|
||||
echo ok
|
||||
fi
|
||||
|
||||
# test the regular expression conditional operator
|
||||
[[ jbig2dec-0.9-i586-001.tgz =~ ([^-]+)-([^-]+)-([^-]+)-0*([1-9][0-9]*)\.tgz ]]
|
||||
echo ${BASH_REMATCH[1]}
|
||||
|
||||
# this shouldn't echo anything
|
||||
[[ jbig2dec-0.9-i586-001.tgz =~ \([^-]+\)-\([^-]+\)-\([^-]+\)-0*\([1-9][0-9]*\)\.tgz ]]
|
||||
echo ${BASH_REMATCH[1]}
|
||||
|
||||
LDD_BASH=" linux-gate.so.1 => (0xffffe000)
|
||||
libreadline.so.5 => /lib/libreadline.so.5 (0xb7f91000)
|
||||
libhistory.so.5 => /lib/libhistory.so.5 (0xb7f8a000)
|
||||
libncurses.so.5 => /lib/libncurses.so.5 (0xb7f55000)
|
||||
libdl.so.2 => /lib/libdl.so.2 (0xb7f51000)
|
||||
libc.so.6 => /lib/libc.so.6 (0xb7e34000)
|
||||
/lib/ld-linux.so.2 (0xb7fd0000)"
|
||||
|
||||
[[ "$LDD_BASH" =~ "libc" ]] && echo "found 1"
|
||||
echo ${BASH_REMATCH[@]}
|
||||
|
||||
[[ "$LDD_BASH" =~ libc ]] && echo "found 2"
|
||||
echo ${BASH_REMATCH[@]}
|
||||
|
||||
# bug in all versions up to and including bash-2.05b
|
||||
if [[ "123abc" == *?(a)bc ]]; then echo ok 42; else echo bad 42; fi
|
||||
if [[ "123abc" == *?(a)bc ]]; then echo ok 43; else echo bad 43; fi
|
||||
|
||||
${THIS_SH} ./cond-regexp1.sub
|
||||
|
||||
${THIS_SH} ./cond-regexp2.sub
|
||||
@@ -246,6 +246,10 @@ ${THIS_SH} ./dollar-at4.sub
|
||||
# through bash-4.2
|
||||
${THIS_SH} ./dollar-at5.sub
|
||||
|
||||
# tests for problems with "${@:1}" and other expansions with null entries
|
||||
# in positional parameters
|
||||
${THIS_SH} ./dollar-at6.sub
|
||||
|
||||
# tests for expansions of $* when $1 == ""; problem through bash-4.2
|
||||
${THIS_SH} ./dollar-star6.sub
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
set -- '';
|
||||
|
||||
recho "${@}" x
|
||||
recho "${@:1}" x
|
||||
|
||||
set -- "${@:1}"
|
||||
echo "$#"
|
||||
|
||||
set -- '' ''
|
||||
|
||||
recho "${@:1}" x
|
||||
recho "${@:1:1}" x
|
||||
|
||||
typeset -a A # ksh93 needs this
|
||||
A=('' '')
|
||||
recho "${A[@]:0}" x
|
||||
|
||||
recho "${A[@]:0:1}" x
|
||||
|
||||
recho "${A[@]:1}" x
|
||||
|
||||
set -- ''
|
||||
|
||||
recho "${@/foo/bar}"
|
||||
recho "${@^^[abcde]}"
|
||||
|
||||
A=( '' )
|
||||
|
||||
recho "${A[@]/foo/bar}"
|
||||
recho "${A[@],,[abcde]}"
|
||||
@@ -233,6 +233,27 @@ ${@:2}c$1 c2 c3 #works as long as quoting omitted
|
||||
set y zcx c2 c3
|
||||
0
|
||||
declare -a c='([0]="y" [1]="zcx" [2]="c2" [3]="c3")'
|
||||
argv[1] = <>
|
||||
argv[2] = <x>
|
||||
argv[1] = <>
|
||||
argv[2] = <x>
|
||||
1
|
||||
argv[1] = <>
|
||||
argv[2] = <>
|
||||
argv[3] = <x>
|
||||
argv[1] = <>
|
||||
argv[2] = <x>
|
||||
argv[1] = <>
|
||||
argv[2] = <>
|
||||
argv[3] = <x>
|
||||
argv[1] = <>
|
||||
argv[2] = <x>
|
||||
argv[1] = <>
|
||||
argv[2] = <x>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <>
|
||||
argv[1] = <AwR>
|
||||
argv[1] = <AwR>
|
||||
argv[1] = <AR>
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
:; ./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...
|
||||
:;
|
||||
@@ -0,0 +1,10 @@
|
||||
#! /bin/sh
|
||||
for cmd in sh bash ash ksh zsh
|
||||
do
|
||||
echo
|
||||
echo $cmd:
|
||||
for demo in shx?
|
||||
do
|
||||
$cmd $demo
|
||||
done
|
||||
done
|
||||
@@ -118,3 +118,12 @@ y -- 0
|
||||
y -- 0
|
||||
bar
|
||||
unset
|
||||
inside
|
||||
inside: one
|
||||
outside: two
|
||||
foo
|
||||
local
|
||||
./nameref8.sub: line 47: typeset: v: nameref variable self references not allowed
|
||||
./nameref8.sub: line 54: warning: x: circular name reference
|
||||
./nameref8.sub: line 55: warning: x: circular name reference
|
||||
x =
|
||||
|
||||
@@ -115,3 +115,4 @@ ${THIS_SH} ./nameref4.sub
|
||||
${THIS_SH} ./nameref5.sub
|
||||
${THIS_SH} ./nameref6.sub
|
||||
${THIS_SH} ./nameref7.sub
|
||||
${THIS_SH} ./nameref8.sub
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
# basic nameref tests
|
||||
bar=one
|
||||
flow=two
|
||||
flip=three
|
||||
|
||||
foo=bar
|
||||
typeset -n foo
|
||||
|
||||
typeset -n fee=flow
|
||||
|
||||
echo ${foo}
|
||||
echo ${fee}
|
||||
|
||||
typeset -n fee=flip
|
||||
echo ${fee}
|
||||
|
||||
typeset -n
|
||||
|
||||
echo turning off nameref attribute on foo
|
||||
typeset +n foo=other
|
||||
echo ${foo}
|
||||
echo after +n foo bar = $bar
|
||||
|
||||
unset foo bar fee
|
||||
|
||||
bar=one
|
||||
|
||||
foo=bar
|
||||
typeset -n foo
|
||||
|
||||
foo=two printf "%s\n" $foo
|
||||
foo=two eval 'printf "%s\n" $foo'
|
||||
|
||||
foo=two echo $foo
|
||||
|
||||
unset foo bar
|
||||
# other basic assignment tests
|
||||
bar=one
|
||||
|
||||
echo "expect <one>"
|
||||
recho ${bar}
|
||||
typeset -n foo=bar
|
||||
foo=two
|
||||
|
||||
echo "expect <two>"
|
||||
recho ${bar}
|
||||
|
||||
# this appears to be a ksh93 bug; it doesn't unset foo here and messes up
|
||||
# later
|
||||
unset foo bar
|
||||
|
||||
# initial tests of working inside shell functions
|
||||
echoval()
|
||||
{
|
||||
typeset -n ref=$1
|
||||
printf "%s\n" $ref
|
||||
}
|
||||
|
||||
foo=bar
|
||||
bar=one
|
||||
echo "expect <$foo>"
|
||||
echoval foo
|
||||
echo "expect <$bar>"
|
||||
echoval bar
|
||||
|
||||
unset foo bar
|
||||
changevar()
|
||||
{
|
||||
typeset -n v=$1
|
||||
|
||||
shift
|
||||
v="$@"
|
||||
echo "changevar: expect <$@>"
|
||||
recho "$v"
|
||||
}
|
||||
|
||||
bar=one
|
||||
|
||||
echo "expect <one>"
|
||||
recho ${bar}
|
||||
changevar bar two
|
||||
echo "expect <two>"
|
||||
recho $bar
|
||||
|
||||
changevar bar three four five
|
||||
echo "expect <three four five>"
|
||||
recho "$bar"
|
||||
|
||||
unset foo bar
|
||||
unset -n foo bar
|
||||
readonly foo=one
|
||||
typeset -n bar=foo
|
||||
bar=4
|
||||
foo=4
|
||||
|
||||
echo $foo
|
||||
echo $bar
|
||||
|
||||
assignvar()
|
||||
{
|
||||
typeset -n ref=$1
|
||||
shift
|
||||
ref="$@"
|
||||
}
|
||||
|
||||
readonly foo=one
|
||||
|
||||
assignvar foo two three four
|
||||
echo $foo
|
||||
|
||||
${THIS_SH} ./nameref1.sub
|
||||
${THIS_SH} ./nameref2.sub
|
||||
${THIS_SH} ./nameref3.sub
|
||||
${THIS_SH} ./nameref4.sub
|
||||
${THIS_SH} ./nameref5.sub
|
||||
${THIS_SH} ./nameref6.sub
|
||||
${THIS_SH} ./nameref7.sub
|
||||
@@ -0,0 +1,57 @@
|
||||
function f1
|
||||
{
|
||||
typeset -n v=$1
|
||||
|
||||
v=inside
|
||||
}
|
||||
|
||||
v=global
|
||||
f1 v
|
||||
echo $v
|
||||
|
||||
unset v
|
||||
unset -f f1
|
||||
|
||||
function foo
|
||||
{
|
||||
typeset x=one
|
||||
|
||||
typeset -n y=$1
|
||||
y=two
|
||||
echo inside: $x
|
||||
}
|
||||
|
||||
foo x
|
||||
echo outside: $x
|
||||
|
||||
function foo2
|
||||
{
|
||||
typeset -n x=$1
|
||||
|
||||
x=foo
|
||||
}
|
||||
|
||||
foo2 x
|
||||
echo $x
|
||||
|
||||
unset -f foo
|
||||
function foo { typeset -n v=$1; v=local; }
|
||||
|
||||
v=global
|
||||
foo v
|
||||
echo $v
|
||||
|
||||
unset v
|
||||
|
||||
# invalid self reference at global scope
|
||||
typeset -n v=v
|
||||
|
||||
# can we catch a circular self-reference?
|
||||
typeset -n v=w
|
||||
typeset -n w=x
|
||||
typeset -n x=v
|
||||
|
||||
x=4
|
||||
echo x = $x
|
||||
|
||||
unset -n v w x
|
||||
Reference in New Issue
Block a user