mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-03 18:30:49 +02:00
commit bash-20121207 snapshot
This commit is contained in:
@@ -3965,3 +3965,27 @@ subst.c
|
||||
temp environment, since we don't have to worry about order of
|
||||
evaluation in a subshell. Fixes bug reported by Andrey Borzenkov
|
||||
<arvidjaar@gmail.com>
|
||||
|
||||
12/4
|
||||
----
|
||||
lib/glob/glob.c
|
||||
- glob_filename: changes to avoid null filenames and multiple entries
|
||||
returned for patterns like **/** (globstar enabled). Fixes bug
|
||||
reported by Ulf Magnusson <ulfalizer@gmail.com>
|
||||
|
||||
12/10
|
||||
-----
|
||||
lib/glob/glob.c
|
||||
- glob_filename: finish up a series of changes to make globstar-style
|
||||
globbing more efficient, avoid more duplicate filenames, and be more
|
||||
compatible with other shells that implement it
|
||||
o collapse a sequence of **/**/** to one **
|
||||
o note when the directory name is all ** or ends in ** so we
|
||||
can treat it specially when the filename is **
|
||||
All inspired by report from Andrey Borzenkov <arvidjaar@gmail.com>
|
||||
|
||||
lib/sh/zread.c
|
||||
- zreadn: new function, like zread, but takes an additional argument
|
||||
saying how many bytes to read into the local buffer. Can be used to
|
||||
implement `read -N' without so many one-byte calls to zreadc. Code
|
||||
from Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
+3985
File diff suppressed because it is too large
Load Diff
@@ -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 */
|
||||
@@ -815,6 +815,7 @@ tests/builtins.right f
|
||||
tests/builtins1.sub f
|
||||
tests/builtins2.sub f
|
||||
tests/builtins3.sub f
|
||||
tests/builtins4.sub f
|
||||
tests/source1.sub f
|
||||
tests/source2.sub f
|
||||
tests/source3.sub f
|
||||
@@ -924,6 +925,7 @@ tests/glob.right f
|
||||
tests/globstar.tests f
|
||||
tests/globstar.right f
|
||||
tests/globstar1.sub f
|
||||
tests/globstar2.sub f
|
||||
tests/heredoc.tests f
|
||||
tests/heredoc.right f
|
||||
tests/heredoc1.sub f
|
||||
@@ -1023,6 +1025,7 @@ tests/printf3.sub f
|
||||
tests/printf4.sub f
|
||||
tests/quote.tests f
|
||||
tests/quote.right f
|
||||
tests/quote1.sub f
|
||||
tests/read.tests f
|
||||
tests/read.right f
|
||||
tests/read1.sub f
|
||||
|
||||
@@ -43,6 +43,11 @@ printf interprets:
|
||||
%(fmt)T output the date-time string resulting from using FMT as a format
|
||||
string for strftime(3)
|
||||
|
||||
The format is re-used as necessary to consume all of the arguments. If
|
||||
there are fewer arguments than the format requires, extra format
|
||||
specifications behave as if a zero value or null string, as appropriate,
|
||||
had been supplied.
|
||||
|
||||
Exit Status:
|
||||
Returns success unless an invalid option is given or a write or assignment
|
||||
error occurs.
|
||||
|
||||
@@ -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
@@ -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
|
||||
Executable
+549
@@ -0,0 +1,549 @@
|
||||
#!/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
|
||||
@@ -490,6 +490,7 @@ extern ssize_t zreadretry __P((int, char *, size_t));
|
||||
extern ssize_t zreadintr __P((int, char *, size_t));
|
||||
extern ssize_t zreadc __P((int, char *));
|
||||
extern ssize_t zreadcintr __P((int, char *));
|
||||
extern ssize_t zreadn __P((int, char *, size_t));
|
||||
extern void zreset __P((void));
|
||||
extern void zsyncfd __P((int));
|
||||
|
||||
|
||||
+508
@@ -0,0 +1,508 @@
|
||||
/* externs.h -- extern function declarations which do not appear in their
|
||||
own header file. */
|
||||
|
||||
/* Copyright (C) 1993-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Make sure that this is included *after* config.h! */
|
||||
|
||||
#if !defined (_EXTERNS_H_)
|
||||
# define _EXTERNS_H_
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
/* Functions from expr.c. */
|
||||
extern intmax_t evalexp __P((char *, int *));
|
||||
|
||||
/* Functions from print_cmd.c. */
|
||||
#define FUNC_MULTILINE 0x01
|
||||
#define FUNC_EXTERNAL 0x02
|
||||
|
||||
extern char *make_command_string __P((COMMAND *));
|
||||
extern char *named_function_string __P((char *, COMMAND *, int));
|
||||
|
||||
extern void print_command __P((COMMAND *));
|
||||
extern void print_simple_command __P((SIMPLE_COM *));
|
||||
extern void print_word_list __P((WORD_LIST *, char *));
|
||||
|
||||
/* debugger support */
|
||||
extern void print_for_command_head __P((FOR_COM *));
|
||||
#if defined (SELECT_COMMAND)
|
||||
extern void print_select_command_head __P((SELECT_COM *));
|
||||
#endif
|
||||
extern void print_case_command_head __P((CASE_COM *));
|
||||
#if defined (DPAREN_ARITHMETIC)
|
||||
extern void print_arith_command __P((WORD_LIST *));
|
||||
#endif
|
||||
#if defined (COND_COMMAND)
|
||||
extern void print_cond_command __P((COND_COM *));
|
||||
#endif
|
||||
|
||||
/* set -x support */
|
||||
extern void xtrace_init __P((void));
|
||||
#ifdef NEED_XTRACE_SET_DECL
|
||||
extern void xtrace_set __P((int, FILE *));
|
||||
#endif
|
||||
extern void xtrace_fdchk __P((int));
|
||||
extern void xtrace_reset __P((void));
|
||||
extern char *indirection_level_string __P((void));
|
||||
extern void xtrace_print_assignment __P((char *, char *, int, int));
|
||||
extern void xtrace_print_word_list __P((WORD_LIST *, int));
|
||||
extern void xtrace_print_for_command_head __P((FOR_COM *));
|
||||
#if defined (SELECT_COMMAND)
|
||||
extern void xtrace_print_select_command_head __P((SELECT_COM *));
|
||||
#endif
|
||||
extern void xtrace_print_case_command_head __P((CASE_COM *));
|
||||
#if defined (DPAREN_ARITHMETIC)
|
||||
extern void xtrace_print_arith_cmd __P((WORD_LIST *));
|
||||
#endif
|
||||
#if defined (COND_COMMAND)
|
||||
extern void xtrace_print_cond_term __P((int, int, WORD_DESC *, char *, char *));
|
||||
#endif
|
||||
|
||||
/* Functions from shell.c. */
|
||||
extern void exit_shell __P((int)) __attribute__((__noreturn__));
|
||||
extern void sh_exit __P((int)) __attribute__((__noreturn__));
|
||||
extern void subshell_exit __P((int)) __attribute__((__noreturn__));
|
||||
extern void disable_priv_mode __P((void));
|
||||
extern void unbind_args __P((void));
|
||||
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
extern int shell_is_restricted __P((char *));
|
||||
extern int maybe_make_restricted __P((char *));
|
||||
#endif
|
||||
|
||||
extern void unset_bash_input __P((int));
|
||||
extern void get_current_user_info __P((void));
|
||||
|
||||
/* Functions from eval.c. */
|
||||
extern int reader_loop __P((void));
|
||||
extern int parse_command __P((void));
|
||||
extern int read_command __P((void));
|
||||
|
||||
/* Functions from braces.c. */
|
||||
#if defined (BRACE_EXPANSION)
|
||||
extern char **brace_expand __P((char *));
|
||||
#endif
|
||||
|
||||
/* Miscellaneous functions from parse.y */
|
||||
extern int yyparse __P((void));
|
||||
extern int return_EOF __P((void));
|
||||
extern char *xparse_dolparen __P((char *, char *, int *, int));
|
||||
extern void reset_parser __P((void));
|
||||
extern WORD_LIST *parse_string_to_word_list __P((char *, int, const char *));
|
||||
|
||||
extern int parser_in_command_position __P((void));
|
||||
|
||||
extern void free_pushed_string_input __P((void));
|
||||
|
||||
extern char *decode_prompt_string __P((char *));
|
||||
|
||||
extern int get_current_prompt_level __P((void));
|
||||
extern void set_current_prompt_level __P((int));
|
||||
|
||||
#if defined (HISTORY)
|
||||
extern char *history_delimiting_chars __P((const char *));
|
||||
#endif
|
||||
|
||||
/* Declarations for functions defined in locale.c */
|
||||
extern void set_default_locale __P((void));
|
||||
extern void set_default_locale_vars __P((void));
|
||||
extern int set_locale_var __P((char *, char *));
|
||||
extern int set_lang __P((char *, char *));
|
||||
extern void set_default_lang __P((void));
|
||||
extern char *get_locale_var __P((char *));
|
||||
extern char *localetrans __P((char *, int, int *));
|
||||
extern char *mk_msgstr __P((char *, int *));
|
||||
extern char *localeexpand __P((char *, int, int, int, int *));
|
||||
|
||||
/* Declarations for functions defined in list.c. */
|
||||
extern void list_walk __P((GENERIC_LIST *, sh_glist_func_t *));
|
||||
extern void wlist_walk __P((WORD_LIST *, sh_icpfunc_t *));
|
||||
extern GENERIC_LIST *list_reverse ();
|
||||
extern int list_length ();
|
||||
extern GENERIC_LIST *list_append ();
|
||||
extern GENERIC_LIST *list_remove ();
|
||||
|
||||
/* Declarations for functions defined in stringlib.c */
|
||||
extern int find_string_in_alist __P((char *, STRING_INT_ALIST *, int));
|
||||
extern char *find_token_in_alist __P((int, STRING_INT_ALIST *, int));
|
||||
extern int find_index_in_alist __P((char *, STRING_INT_ALIST *, int));
|
||||
|
||||
extern char *substring __P((const char *, int, int));
|
||||
extern char *strsub __P((char *, char *, char *, int));
|
||||
extern char *strcreplace __P((char *, int, char *, int));
|
||||
extern void strip_leading __P((char *));
|
||||
extern void strip_trailing __P((char *, int, int));
|
||||
extern void xbcopy __P((char *, char *, int));
|
||||
|
||||
/* Functions from version.c. */
|
||||
extern char *shell_version_string __P((void));
|
||||
extern void show_shell_version __P((int));
|
||||
|
||||
/* Functions from the bash library, lib/sh/libsh.a. These should really
|
||||
go into a separate include file. */
|
||||
|
||||
/* declarations for functions defined in lib/sh/casemod.c */
|
||||
extern char *sh_modcase __P((const char *, char *, int));
|
||||
|
||||
/* Defines for flags argument to sh_modcase. These need to agree with what's
|
||||
in lib/sh/casemode.c */
|
||||
#define CASE_LOWER 0x0001
|
||||
#define CASE_UPPER 0x0002
|
||||
#define CASE_CAPITALIZE 0x0004
|
||||
#define CASE_UNCAP 0x0008
|
||||
#define CASE_TOGGLE 0x0010
|
||||
#define CASE_TOGGLEALL 0x0020
|
||||
#define CASE_UPFIRST 0x0040
|
||||
#define CASE_LOWFIRST 0x0080
|
||||
|
||||
#define CASE_USEWORDS 0x1000
|
||||
|
||||
/* declarations for functions defined in lib/sh/clktck.c */
|
||||
extern long get_clk_tck __P((void));
|
||||
|
||||
/* declarations for functions defined in lib/sh/clock.c */
|
||||
extern void clock_t_to_secs ();
|
||||
extern void print_clock_t ();
|
||||
|
||||
/* Declarations for functions defined in lib/sh/dprintf.c */
|
||||
#if !defined (HAVE_DPRINTF)
|
||||
extern void dprintf __P((int, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
|
||||
#endif
|
||||
|
||||
/* Declarations for functions defined in lib/sh/fmtulong.c */
|
||||
#define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */
|
||||
#define FL_ADDBASE 0x02 /* add base# prefix to converted value */
|
||||
#define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */
|
||||
#define FL_UNSIGNED 0x08 /* don't add any sign */
|
||||
|
||||
extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
|
||||
|
||||
/* Declarations for functions defined in lib/sh/fmtulong.c */
|
||||
#if defined (HAVE_LONG_LONG)
|
||||
extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
|
||||
#endif
|
||||
|
||||
/* Declarations for functions defined in lib/sh/fmtumax.c */
|
||||
extern char *fmtumax __P((uintmax_t, int, char *, size_t, int));
|
||||
|
||||
/* Declarations for functions defined in lib/sh/fnxform.c */
|
||||
extern char *fnx_fromfs __P((char *, size_t));
|
||||
extern char *fnx_tofs __P((char *, size_t));
|
||||
|
||||
/* Declarations for functions defined in lib/sh/fpurge.c */
|
||||
|
||||
#if defined NEED_FPURGE_DECL
|
||||
#if !HAVE_DECL_FPURGE
|
||||
|
||||
#if HAVE_FPURGE
|
||||
# define fpurge _bash_fpurge
|
||||
#endif
|
||||
extern int fpurge __P((FILE *stream));
|
||||
|
||||
#endif /* HAVE_DECL_FPURGE */
|
||||
#endif /* NEED_FPURGE_DECL */
|
||||
|
||||
/* Declarations for functions defined in lib/sh/getcwd.c */
|
||||
#if !defined (HAVE_GETCWD)
|
||||
extern char *getcwd __P((char *, size_t));
|
||||
#endif
|
||||
|
||||
/* Declarations for functions defined in lib/sh/input_avail.c */
|
||||
extern int input_avail __P((int));
|
||||
|
||||
/* Declarations for functions defined in lib/sh/itos.c */
|
||||
extern char *inttostr __P((intmax_t, char *, size_t));
|
||||
extern char *itos __P((intmax_t));
|
||||
extern char *uinttostr __P((uintmax_t, char *, size_t));
|
||||
extern char *uitos __P((uintmax_t));
|
||||
|
||||
/* declarations for functions defined in lib/sh/makepath.c */
|
||||
#define MP_DOTILDE 0x01
|
||||
#define MP_DOCWD 0x02
|
||||
#define MP_RMDOT 0x04
|
||||
#define MP_IGNDOT 0x08
|
||||
|
||||
extern char *sh_makepath __P((const char *, const char *, int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/mbscasecmp.c */
|
||||
#if !defined (HAVE_MBSCASECMP)
|
||||
extern char *mbscasecmp __P((const char *, const char *));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/mbschr.c */
|
||||
#if !defined (HAVE_MBSCHR)
|
||||
extern char *mbschr __P((const char *, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/mbscmp.c */
|
||||
#if !defined (HAVE_MBSCMP)
|
||||
extern char *mbscmp __P((const char *, const char *));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/netconn.c */
|
||||
extern int isnetconn __P((int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/netopen.c */
|
||||
extern int netopen __P((char *));
|
||||
|
||||
/* Declarations for functions defined in lib/sh/oslib.c */
|
||||
|
||||
#if !defined (HAVE_DUP2) || defined (DUP2_BROKEN)
|
||||
extern int dup2 __P((int, int));
|
||||
#endif
|
||||
|
||||
#if !defined (HAVE_GETDTABLESIZE)
|
||||
extern int getdtablesize __P((void));
|
||||
#endif /* !HAVE_GETDTABLESIZE */
|
||||
|
||||
#if !defined (HAVE_GETHOSTNAME)
|
||||
extern int gethostname __P((char *, int));
|
||||
#endif /* !HAVE_GETHOSTNAME */
|
||||
|
||||
extern int getmaxgroups __P((void));
|
||||
extern long getmaxchild __P((void));
|
||||
|
||||
/* declarations for functions defined in lib/sh/pathcanon.c */
|
||||
#define PATH_CHECKDOTDOT 0x0001
|
||||
#define PATH_CHECKEXISTS 0x0002
|
||||
#define PATH_HARDPATH 0x0004
|
||||
#define PATH_NOALLOC 0x0008
|
||||
|
||||
extern char *sh_canonpath __P((char *, int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/pathphys.c */
|
||||
extern char *sh_physpath __P((char *, int));
|
||||
extern char *sh_realpath __P((const char *, char *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/setlinebuf.c */
|
||||
#ifdef NEED_SH_SETLINEBUF_DECL
|
||||
extern int sh_setlinebuf __P((FILE *));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/shaccess.c */
|
||||
extern int sh_eaccess __P((char *, int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/shmatch.c */
|
||||
extern int sh_regmatch __P((const char *, const char *, int));
|
||||
|
||||
/* defines for flags argument to sh_regmatch. */
|
||||
#define SHMAT_SUBEXP 0x001 /* save subexpressions in SH_REMATCH */
|
||||
#define SHMAT_PWARN 0x002 /* print a warning message on invalid regexp */
|
||||
|
||||
/* declarations for functions defined in lib/sh/shmbchar.c */
|
||||
extern size_t mbstrlen __P((const char *));
|
||||
extern char *mbsmbchar __P((const char *));
|
||||
extern int sh_mbsnlen __P((const char *, size_t, int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/shquote.c */
|
||||
extern char *sh_single_quote __P((const char *));
|
||||
extern char *sh_double_quote __P((const char *));
|
||||
extern char *sh_mkdoublequoted __P((const char *, int, int));
|
||||
extern char *sh_un_double_quote __P((char *));
|
||||
extern char *sh_backslash_quote __P((char *, const char *, int));
|
||||
extern char *sh_backslash_quote_for_double_quotes __P((char *));
|
||||
extern int sh_contains_shell_metas __P((char *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/spell.c */
|
||||
extern int spname __P((char *, char *));
|
||||
extern char *dirspell __P((char *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/strcasecmp.c */
|
||||
#if !defined (HAVE_STRCASECMP)
|
||||
extern int strncasecmp __P((const char *, const char *, int));
|
||||
extern int strcasecmp __P((const char *, const char *));
|
||||
#endif /* HAVE_STRCASECMP */
|
||||
|
||||
/* declarations for functions defined in lib/sh/strcasestr.c */
|
||||
#if ! HAVE_STRCASESTR
|
||||
extern char *strcasestr __P((const char *, const char *));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strchrnul.c */
|
||||
#if ! HAVE_STRCHRNUL
|
||||
extern char *strchrnul __P((const char *, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strerror.c */
|
||||
#if !defined (HAVE_STRERROR) && !defined (strerror)
|
||||
extern char *strerror __P((int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strftime.c */
|
||||
#if !defined (HAVE_STRFTIME) && defined (NEED_STRFTIME_DECL)
|
||||
extern size_t strftime __P((char *, size_t, const char *, const struct tm *));
|
||||
#endif
|
||||
|
||||
/* declarations for functions and structures defined in lib/sh/stringlist.c */
|
||||
|
||||
/* This is a general-purpose argv-style array struct. */
|
||||
typedef struct _list_of_strings {
|
||||
char **list;
|
||||
int list_size;
|
||||
int list_len;
|
||||
} STRINGLIST;
|
||||
|
||||
typedef int sh_strlist_map_func_t __P((char *));
|
||||
|
||||
extern STRINGLIST *strlist_create __P((int));
|
||||
extern STRINGLIST *strlist_resize __P((STRINGLIST *, int));
|
||||
extern void strlist_flush __P((STRINGLIST *));
|
||||
extern void strlist_dispose __P((STRINGLIST *));
|
||||
extern int strlist_remove __P((STRINGLIST *, char *));
|
||||
extern STRINGLIST *strlist_copy __P((STRINGLIST *));
|
||||
extern STRINGLIST *strlist_merge __P((STRINGLIST *, STRINGLIST *));
|
||||
extern STRINGLIST *strlist_append __P((STRINGLIST *, STRINGLIST *));
|
||||
extern STRINGLIST *strlist_prefix_suffix __P((STRINGLIST *, char *, char *));
|
||||
extern void strlist_print __P((STRINGLIST *, char *));
|
||||
extern void strlist_walk __P((STRINGLIST *, sh_strlist_map_func_t *));
|
||||
extern void strlist_sort __P((STRINGLIST *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/stringvec.c */
|
||||
|
||||
extern char **strvec_create __P((int));
|
||||
extern char **strvec_resize __P((char **, int));
|
||||
extern void strvec_flush __P((char **));
|
||||
extern void strvec_dispose __P((char **));
|
||||
extern int strvec_remove __P((char **, char *));
|
||||
extern int strvec_len __P((char **));
|
||||
extern int strvec_search __P((char **, char *));
|
||||
extern char **strvec_copy __P((char **));
|
||||
extern int strvec_strcmp __P((char **, char **));
|
||||
extern void strvec_sort __P((char **));
|
||||
|
||||
extern char **strvec_from_word_list __P((WORD_LIST *, int, int, int *));
|
||||
extern WORD_LIST *strvec_to_word_list __P((char **, int, int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/strnlen.c */
|
||||
#if !defined (HAVE_STRNLEN)
|
||||
extern size_t strnlen __P((const char *, size_t));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strpbrk.c */
|
||||
#if !defined (HAVE_STRPBRK)
|
||||
extern char *strpbrk __P((const char *, const char *));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strtod.c */
|
||||
#if !defined (HAVE_STRTOD)
|
||||
extern double strtod __P((const char *, char **));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strtol.c */
|
||||
#if !HAVE_DECL_STRTOL
|
||||
extern long strtol __P((const char *, char **, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strtoll.c */
|
||||
#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOLL
|
||||
extern long long strtoll __P((const char *, char **, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strtoul.c */
|
||||
#if !HAVE_DECL_STRTOUL
|
||||
extern unsigned long strtoul __P((const char *, char **, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strtoull.c */
|
||||
#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOULL
|
||||
extern unsigned long long strtoull __P((const char *, char **, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strimax.c */
|
||||
#if !HAVE_DECL_STRTOIMAX
|
||||
extern intmax_t strtoimax __P((const char *, char **, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strumax.c */
|
||||
#if !HAVE_DECL_STRTOUMAX
|
||||
extern uintmax_t strtoumax __P((const char *, char **, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/strtrans.c */
|
||||
extern char *ansicstr __P((char *, int, int, int *, int *));
|
||||
extern char *ansic_quote __P((char *, int, int *));
|
||||
extern int ansic_shouldquote __P((const char *));
|
||||
extern char *ansiexpand __P((char *, int, int, int *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/timeval.c. No prototypes
|
||||
so we don't have to count on having a definition of struct timeval in
|
||||
scope when this file is included. */
|
||||
extern void timeval_to_secs ();
|
||||
extern void print_timeval ();
|
||||
|
||||
/* declarations for functions defined in lib/sh/tmpfile.c */
|
||||
#define MT_USETMPDIR 0x0001
|
||||
#define MT_READWRITE 0x0002
|
||||
#define MT_USERANDOM 0x0004
|
||||
|
||||
extern char *sh_mktmpname __P((char *, int));
|
||||
extern int sh_mktmpfd __P((char *, int, char **));
|
||||
/* extern FILE *sh_mktmpfp __P((char *, int, char **)); */
|
||||
|
||||
/* declarations for functions defined in lib/sh/uconvert.c */
|
||||
extern int uconvert __P((char *, long *, long *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/ufuncs.c */
|
||||
extern unsigned int falarm __P((unsigned int, unsigned int));
|
||||
extern unsigned int fsleep __P((unsigned int, unsigned int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/unicode.c */
|
||||
extern int u32cconv __P((unsigned long, char *));
|
||||
extern void u32reset __P((void));
|
||||
|
||||
/* declarations for functions defined in lib/sh/wcsnwidth.c */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
extern int wcsnwidth __P((const wchar_t *, size_t, int));
|
||||
#endif
|
||||
|
||||
/* declarations for functions defined in lib/sh/winsize.c */
|
||||
extern void get_new_window_size __P((int, int *, int *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/zcatfd.c */
|
||||
extern int zcatfd __P((int, int, char *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/zgetline.c */
|
||||
extern ssize_t zgetline __P((int, char **, size_t *, int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/zmapfd.c */
|
||||
extern int zmapfd __P((int, char **, char *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/zread.c */
|
||||
extern ssize_t zread __P((int, char *, size_t));
|
||||
extern ssize_t zreadretry __P((int, char *, size_t));
|
||||
extern ssize_t zreadintr __P((int, char *, size_t));
|
||||
extern ssize_t zreadc __P((int, char *));
|
||||
extern ssize_t zreadcintr __P((int, char *));
|
||||
extern void zreset __P((void));
|
||||
extern void zsyncfd __P((int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/zwrite.c */
|
||||
extern int zwrite __P((int, char *, size_t));
|
||||
|
||||
/* declarations for functions defined in lib/glob/gmisc.c */
|
||||
extern int match_pattern_char __P((char *, char *));
|
||||
extern int umatchlen __P((char *, size_t));
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
extern int match_pattern_wchar __P((wchar_t *, wchar_t *));
|
||||
extern int wmatchlen __P((wchar_t *, size_t));
|
||||
#endif
|
||||
|
||||
#endif /* _EXTERNS_H_ */
|
||||
@@ -0,0 +1,35 @@
|
||||
/* If we're expanding **, we don't need to glue the directory
|
||||
name to the results; we've already done it in glob_vector */
|
||||
if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && (filename[2] == '\0' || filename[2] == '/'))
|
||||
{
|
||||
/* When do we remove null elements from temp_results? And
|
||||
how to avoid duplicate elements in the final result? */
|
||||
/* If (dflags & GX_NULLDIR) glob_filename potentially left a
|
||||
NULL placeholder in the temp results just in case
|
||||
glob_vector/glob_dir_to_array did something with it, but
|
||||
if it didn't, and we're not supposed to be passing them
|
||||
through for some reason ((flags & GX_NULLDIR) == 0) we
|
||||
need to remove all the NULL elements from the beginning
|
||||
of TEMP_RESULTS. */
|
||||
/* If we have a null directory name and ** as the filename,
|
||||
we have just searched for everything from the current
|
||||
directory on down. Break now (shouldbreak = 1) to avoid
|
||||
duplicate entries in the final result. */
|
||||
#define NULL_PLACEHOLDER(x) ((x) && *(x) && **(x) == 0)
|
||||
if ((dflags & GX_NULLDIR) && /* (flags & GX_NULLDIR) == 0 && */
|
||||
NULL_PLACEHOLDER (temp_results))
|
||||
#undef NULL_PLACEHOLDER
|
||||
{
|
||||
register int i, n;
|
||||
for (n = 0; temp_results[n] && *temp_results[n] == 0; n++)
|
||||
;
|
||||
i = n;
|
||||
do
|
||||
temp_results[i - n] = temp_results[i];
|
||||
while (temp_results[i++] != 0);
|
||||
array = temp_results;
|
||||
shouldbreak = 1;
|
||||
}
|
||||
else
|
||||
array = temp_results;
|
||||
}
|
||||
+1291
File diff suppressed because it is too large
Load Diff
+112
-12
@@ -609,11 +609,11 @@ glob_vector (pat, dir, flags)
|
||||
nextname = (char *)malloc (dirlen + patlen + 2);
|
||||
npat = (char *)malloc (patlen + 1);
|
||||
if (nextname == 0 || npat == 0)
|
||||
{
|
||||
FREE (nextname);
|
||||
FREE (npat);
|
||||
{
|
||||
FREE (nextname);
|
||||
FREE (npat);
|
||||
lose = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (npat, pat);
|
||||
@@ -1036,17 +1036,68 @@ glob_filename (pathname, flags)
|
||||
have to expand the previous levels. Just recurse. */
|
||||
if (directory_len > 0 && glob_pattern_p (directory_name))
|
||||
{
|
||||
char **directories;
|
||||
char **directories, *d, *p;
|
||||
register unsigned int i;
|
||||
int all_starstar, last_starstar;
|
||||
|
||||
all_starstar = last_starstar = 0;
|
||||
d = directory_name;
|
||||
dflags = flags & ~GX_MARKDIRS;
|
||||
if ((flags & GX_GLOBSTAR) && directory_name[0] == '*' && directory_name[1] == '*' && (directory_name[2] == '/' || directory_name[2] == '\0'))
|
||||
dflags |= GX_ALLDIRS|GX_ADDCURDIR;
|
||||
/* Collapse a sequence of ** patterns separated by one or more slashes
|
||||
to a single ** terminated by a slash or NUL */
|
||||
if ((flags & GX_GLOBSTAR) && d[0] == '*' && d[1] == '*' && (d[2] == '/' || d[2] == '\0'))
|
||||
{
|
||||
p = d;
|
||||
while (d[0] == '*' && d[1] == '*' && (d[2] == '/' || d[2] == '\0'))
|
||||
{
|
||||
p = d;
|
||||
if (d[2])
|
||||
{
|
||||
d += 3;
|
||||
while (*d == '/')
|
||||
d++;
|
||||
if (*d == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*d == 0)
|
||||
all_starstar = 1;
|
||||
d = p;
|
||||
dflags |= GX_ALLDIRS|GX_ADDCURDIR;
|
||||
directory_len = strlen (d);
|
||||
}
|
||||
|
||||
if (directory_name[directory_len - 1] == '/')
|
||||
directory_name[directory_len - 1] = '\0';
|
||||
/* If there is a non [star][star]/ component in directory_name, we
|
||||
still need to collapse trailing sequences of [star][star]/ into
|
||||
a single one and note that the directory name ends with [star][star],
|
||||
so we can compensate if filename is [star][star] */
|
||||
if ((flags & GX_GLOBSTAR) && all_starstar == 0)
|
||||
{
|
||||
int dl, prev;
|
||||
prev = dl = directory_len;
|
||||
while (dl >= 4 && d[dl - 1] == '/' &&
|
||||
d[dl - 2] == '*' &&
|
||||
d[dl - 3] == '*' &&
|
||||
d[dl - 4] == '/')
|
||||
prev = dl, dl -= 3;
|
||||
if (dl != directory_len)
|
||||
last_starstar = 1;
|
||||
directory_len = prev;
|
||||
}
|
||||
|
||||
directories = glob_filename (directory_name, dflags);
|
||||
/* If the directory name ends in [star][star]/ but the filename is
|
||||
[star][star], just remove the final [star][star] from the directory
|
||||
so we don't have to scan everything twice. */
|
||||
if (last_starstar && directory_len > 4 &&
|
||||
filename[0] == '*' && filename[1] == '*' && filename[2] == 0)
|
||||
{
|
||||
directory_len -= 3;
|
||||
}
|
||||
|
||||
if (d[directory_len - 1] == '/')
|
||||
d[directory_len - 1] = '\0';
|
||||
|
||||
directories = glob_filename (d, dflags);
|
||||
|
||||
if (free_dirname)
|
||||
{
|
||||
@@ -1068,13 +1119,26 @@ glob_filename (pathname, flags)
|
||||
return ((char **) &glob_error_return);
|
||||
}
|
||||
|
||||
/* If we have something like [star][star]/[star][star], it's no use to
|
||||
glob **, then do it again, and throw half the results away. */
|
||||
if (all_starstar && filename[0] == '*' && filename[1] == '*' && filename[2] == 0)
|
||||
{
|
||||
free ((char *) directories);
|
||||
free (directory_name);
|
||||
directory_name = NULL;
|
||||
directory_len = 0;
|
||||
goto only_filename;
|
||||
}
|
||||
|
||||
/* We have successfully globbed the preceding directory name.
|
||||
For each name in DIRECTORIES, call glob_vector on it and
|
||||
FILENAME. Concatenate the results together. */
|
||||
for (i = 0; directories[i] != NULL; ++i)
|
||||
{
|
||||
char **temp_results;
|
||||
int shouldbreak;
|
||||
|
||||
shouldbreak = 0;
|
||||
/* XXX -- we've recursively scanned any directories resulting from
|
||||
a `**', so turn off the flag. We turn it on again below if
|
||||
filename is `**' */
|
||||
@@ -1105,8 +1169,39 @@ glob_filename (pathname, flags)
|
||||
|
||||
/* If we're expanding **, we don't need to glue the directory
|
||||
name to the results; we've already done it in glob_vector */
|
||||
if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
|
||||
array = temp_results;
|
||||
if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && (filename[2] == '\0' || filename[2] == '/'))
|
||||
{
|
||||
/* When do we remove null elements from temp_results? And
|
||||
how to avoid duplicate elements in the final result? */
|
||||
/* If (dflags & GX_NULLDIR) glob_filename potentially left a
|
||||
NULL placeholder in the temp results just in case
|
||||
glob_vector/glob_dir_to_array did something with it, but
|
||||
if it didn't, and we're not supposed to be passing them
|
||||
through for some reason ((flags & GX_NULLDIR) == 0) we
|
||||
need to remove all the NULL elements from the beginning
|
||||
of TEMP_RESULTS. */
|
||||
/* If we have a null directory name and ** as the filename,
|
||||
we have just searched for everything from the current
|
||||
directory on down. Break now (shouldbreak = 1) to avoid
|
||||
duplicate entries in the final result. */
|
||||
#define NULL_PLACEHOLDER(x) ((x) && *(x) && **(x) == 0)
|
||||
if ((dflags & GX_NULLDIR) && (flags & GX_NULLDIR) == 0 &&
|
||||
NULL_PLACEHOLDER (temp_results))
|
||||
#undef NULL_PLACEHOLDER
|
||||
{
|
||||
register int i, n;
|
||||
for (n = 0; temp_results[n] && *temp_results[n] == 0; n++)
|
||||
;
|
||||
i = n;
|
||||
do
|
||||
temp_results[i - n] = temp_results[i];
|
||||
while (temp_results[i++] != 0);
|
||||
array = temp_results;
|
||||
shouldbreak = 1;
|
||||
}
|
||||
else
|
||||
array = temp_results;
|
||||
}
|
||||
else
|
||||
array = glob_dir_to_array (directories[i], temp_results, flags);
|
||||
l = 0;
|
||||
@@ -1129,6 +1224,9 @@ glob_filename (pathname, flags)
|
||||
free ((char *) array);
|
||||
else if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
|
||||
free (temp_results); /* expanding ** case above */
|
||||
|
||||
if (shouldbreak)
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Free the directories. */
|
||||
@@ -1140,6 +1238,7 @@ glob_filename (pathname, flags)
|
||||
return (result);
|
||||
}
|
||||
|
||||
only_filename:
|
||||
/* If there is only a directory name, return it. */
|
||||
if (*filename == '\0')
|
||||
{
|
||||
@@ -1204,6 +1303,7 @@ glob_filename (pathname, flags)
|
||||
}
|
||||
|
||||
result = glob_dir_to_array ((dflags & GX_ALLDIRS) ? "" : directory_name, temp_results, flags);
|
||||
|
||||
if (free_dirname)
|
||||
free (directory_name);
|
||||
return (result);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1359
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
|
||||
@@ -150,6 +150,32 @@ zreadcintr (fd, cp)
|
||||
return 1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
zreadn (fd, cp, len)
|
||||
int fd;
|
||||
char *cp;
|
||||
size_t len;
|
||||
{
|
||||
ssize_t nr;
|
||||
|
||||
if (lind == lused || lused == 0)
|
||||
{
|
||||
if (len > sizeof (lbuf))
|
||||
len = sizeof (lbuf);
|
||||
nr = zread (fd, lbuf, len);
|
||||
lind = 0;
|
||||
if (nr <= 0)
|
||||
{
|
||||
lused = 0;
|
||||
return nr;
|
||||
}
|
||||
lused = nr;
|
||||
}
|
||||
if (cp)
|
||||
*cp = lbuf[lind++];
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
zreset ()
|
||||
{
|
||||
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
/* 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
|
||||
|
||||
extern void check_signals_and_traps (void);
|
||||
|
||||
/* 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)
|
||||
check_signals_and_traps (); /* XXX */
|
||||
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 != -1)
|
||||
lused = lind = 0;
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
BUILD_DIR=/usr/local/build/chet/bash/bash-current
|
||||
BUILD_DIR=/usr/local/build/bash/bash-current
|
||||
THIS_SH=$BUILD_DIR/bash
|
||||
PATH=$PATH:$BUILD_DIR
|
||||
|
||||
|
||||
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 "$@"
|
||||
+11
-1
@@ -141,4 +141,14 @@ b
|
||||
before: f = 4
|
||||
inside
|
||||
after: f = 8 bar = 4
|
||||
./builtins.tests: line 254: exit: status: numeric argument required
|
||||
./builtins4.sub: line 2: declare: c: not found
|
||||
./builtins4.sub: line 5: declare: d: not found
|
||||
declare -a c='([0]="4")'
|
||||
declare -A c='([0]="4" )'
|
||||
declare -a c='([0]="1" [1]="2" [2]="3")'
|
||||
declare -A c='([one]="1" [two]="2" [three]="3" )'
|
||||
declare -a c='([0]="1" [1]="2" [2]="3")'
|
||||
declare -a c='([0]="1" [1]="2" [2]="3")'
|
||||
unset
|
||||
unset
|
||||
./builtins.tests: line 257: exit: status: numeric argument required
|
||||
|
||||
@@ -250,6 +250,9 @@ ${THIS_SH} ./builtins2.sub
|
||||
# test behavior of declare -g
|
||||
${THIS_SH} ./builtins3.sub
|
||||
|
||||
# test behavior of using declare to create variables without assigning values
|
||||
${THIS_SH} ./builtins4.sub
|
||||
|
||||
# this must be last -- it is a fatal error
|
||||
exit status
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
declare -a c
|
||||
declare -p c
|
||||
|
||||
declare -A d
|
||||
declare -p d
|
||||
unset c d
|
||||
|
||||
declare -a c
|
||||
c=4
|
||||
declare -p c
|
||||
unset c
|
||||
|
||||
declare -A c
|
||||
c=4
|
||||
declare -p c
|
||||
unset c
|
||||
|
||||
declare -a c
|
||||
c=(1 2 3)
|
||||
declare -p c
|
||||
unset c
|
||||
|
||||
declare -A c
|
||||
c=([one]=1 [two]=2 [three]=3)
|
||||
declare -p c
|
||||
unset c
|
||||
|
||||
declare -a c
|
||||
read -a c < <(echo 1 2 3)
|
||||
declare -p c
|
||||
unset c
|
||||
|
||||
declare -a c
|
||||
mapfile -t c < <(echo 1$'\n'2$'\n'3)
|
||||
declare -p c
|
||||
unset c
|
||||
|
||||
unset foo
|
||||
declare -A foo
|
||||
echo ${foo-unset}
|
||||
|
||||
unset foo
|
||||
declare -a foo
|
||||
echo ${foo-unset}
|
||||
@@ -226,5 +226,8 @@ set y zcx c2 c3
|
||||
0
|
||||
declare -a c='([0]="y" [1]="zcx" [2]="c2" [3]="c3")'
|
||||
argv[1] = <AwR>
|
||||
argv[1] = <AwR>
|
||||
argv[1] = <AR>
|
||||
argv[1] = <AwR>
|
||||
argv[1] = <AR>
|
||||
argv[1] = <AR>
|
||||
|
||||
@@ -153,3 +153,433 @@ alias.o builtins builtins/history.o builtins/jobs.o builtins/kill.o builtins/let
|
||||
bar/foo foo
|
||||
bar/foo/ foo/
|
||||
bar/foo/e bar/foo/f foo/a foo/b
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
== <**/a> ==
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/b/a>
|
||||
<a/b/a>
|
||||
<a/b/a/a>
|
||||
<a/b/b/a>
|
||||
<b/a>
|
||||
<b/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/b/a>
|
||||
<b/b/a>
|
||||
<b/b/a/a>
|
||||
<b/b/b/a>
|
||||
== <a/**> ==
|
||||
<a/>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b/a>
|
||||
<a/a/b/b>
|
||||
<a/b>
|
||||
<a/b/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/b>
|
||||
<a/b/b>
|
||||
<a/b/b/a>
|
||||
<a/b/b/b>
|
||||
== <**> ==
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b/a>
|
||||
<a/a/b/b>
|
||||
<a/b>
|
||||
<a/b/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/b>
|
||||
<a/b/b>
|
||||
<a/b/b/a>
|
||||
<a/b/b/b>
|
||||
<b>
|
||||
<b/a>
|
||||
<b/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/b>
|
||||
<b/a/b>
|
||||
<b/a/b/a>
|
||||
<b/a/b/b>
|
||||
<b/b>
|
||||
<b/b/a>
|
||||
<b/b/a/a>
|
||||
<b/b/a/b>
|
||||
<b/b/b>
|
||||
<b/b/b/a>
|
||||
<b/b/b/b>
|
||||
== <**/**> ==
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b/a>
|
||||
<a/a/b/b>
|
||||
<a/b>
|
||||
<a/b/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/b>
|
||||
<a/b/b>
|
||||
<a/b/b/a>
|
||||
<a/b/b/b>
|
||||
<b>
|
||||
<b/a>
|
||||
<b/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/b>
|
||||
<b/a/b>
|
||||
<b/a/b/a>
|
||||
<b/a/b/b>
|
||||
<b/b>
|
||||
<b/b/a>
|
||||
<b/b/a/a>
|
||||
<b/b/a/b>
|
||||
<b/b/b>
|
||||
<b/b/b/a>
|
||||
<b/b/b/b>
|
||||
== <**/**/**> ==
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b/a>
|
||||
<a/a/b/b>
|
||||
<a/b>
|
||||
<a/b/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/b>
|
||||
<a/b/b>
|
||||
<a/b/b/a>
|
||||
<a/b/b/b>
|
||||
<b>
|
||||
<b/a>
|
||||
<b/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/b>
|
||||
<b/a/b>
|
||||
<b/a/b/a>
|
||||
<b/a/b/b>
|
||||
<b/b>
|
||||
<b/b/a>
|
||||
<b/b/a/a>
|
||||
<b/b/a/b>
|
||||
<b/b/b>
|
||||
<b/b/b/a>
|
||||
<b/b/b/b>
|
||||
== <**/**/**/**/**> ==
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b/a>
|
||||
<a/a/b/b>
|
||||
<a/b>
|
||||
<a/b/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/b>
|
||||
<a/b/b>
|
||||
<a/b/b/a>
|
||||
<a/b/b/b>
|
||||
<b>
|
||||
<b/a>
|
||||
<b/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/b>
|
||||
<b/a/b>
|
||||
<b/a/b/a>
|
||||
<b/a/b/b>
|
||||
<b/b>
|
||||
<b/b/a>
|
||||
<b/b/a/a>
|
||||
<b/b/a/b>
|
||||
<b/b/b>
|
||||
<b/b/b/a>
|
||||
<b/b/b/b>
|
||||
== <**/**/a> ==
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/b/a>
|
||||
<a/b/a>
|
||||
<a/b/a/a>
|
||||
<a/b/b/a>
|
||||
<b/a>
|
||||
<b/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/b/a>
|
||||
<b/b/a>
|
||||
<b/b/a/a>
|
||||
<b/b/b/a>
|
||||
== <a/**/**> ==
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b/a>
|
||||
<a/a/b/b>
|
||||
<a/b>
|
||||
<a/b/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/b>
|
||||
<a/b/b>
|
||||
<a/b/b/a>
|
||||
<a/b/b/b>
|
||||
== <a/**/**/**> ==
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b/a>
|
||||
<a/a/b/b>
|
||||
<a/b>
|
||||
<a/b/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/b>
|
||||
<a/b/b>
|
||||
<a/b/b/a>
|
||||
<a/b/b/b>
|
||||
== <a/**/**/**/**> ==
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b/a>
|
||||
<a/a/b/b>
|
||||
<a/b>
|
||||
<a/b/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/b>
|
||||
<a/b/b>
|
||||
<a/b/b/a>
|
||||
<a/b/b/b>
|
||||
== <**/a/**> ==
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a/a/a>
|
||||
<a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/b>
|
||||
<a/a/a/b>
|
||||
<a/a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b/a>
|
||||
<a/a/b/a>
|
||||
<a/a/b/a>
|
||||
<a/a/b/b>
|
||||
<a/a/b/b>
|
||||
<a/b>
|
||||
<a/b/a>
|
||||
<a/b/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/b>
|
||||
<a/b/a/b>
|
||||
<a/b/b>
|
||||
<a/b/b/a>
|
||||
<a/b/b/a>
|
||||
<a/b/b/b>
|
||||
<b/a>
|
||||
<b/a/a>
|
||||
<b/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/b>
|
||||
<b/a/a/b>
|
||||
<b/a/b>
|
||||
<b/a/b/a>
|
||||
<b/a/b/a>
|
||||
<b/a/b/b>
|
||||
<b/b/a>
|
||||
<b/b/a/a>
|
||||
<b/b/a/a>
|
||||
<b/b/a/b>
|
||||
<b/b/b/a>
|
||||
== <**/a/**/**> ==
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a/a/a>
|
||||
<a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/b>
|
||||
<a/a/a/b>
|
||||
<a/a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b/a>
|
||||
<a/a/b/a>
|
||||
<a/a/b/a>
|
||||
<a/a/b/b>
|
||||
<a/a/b/b>
|
||||
<a/b>
|
||||
<a/b/a>
|
||||
<a/b/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/b>
|
||||
<a/b/a/b>
|
||||
<a/b/b>
|
||||
<a/b/b/a>
|
||||
<a/b/b/a>
|
||||
<a/b/b/b>
|
||||
<b/a>
|
||||
<b/a/a>
|
||||
<b/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/b>
|
||||
<b/a/a/b>
|
||||
<b/a/b>
|
||||
<b/a/b/a>
|
||||
<b/a/b/a>
|
||||
<b/a/b/b>
|
||||
<b/b/a>
|
||||
<b/b/a/a>
|
||||
<b/b/a/a>
|
||||
<b/b/a/b>
|
||||
<b/b/b/a>
|
||||
== <**/a/**/**/**> ==
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a/a/a>
|
||||
<a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/b>
|
||||
<a/a/a/b>
|
||||
<a/a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b/a>
|
||||
<a/a/b/a>
|
||||
<a/a/b/a>
|
||||
<a/a/b/b>
|
||||
<a/a/b/b>
|
||||
<a/b>
|
||||
<a/b/a>
|
||||
<a/b/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/b>
|
||||
<a/b/a/b>
|
||||
<a/b/b>
|
||||
<a/b/b/a>
|
||||
<a/b/b/a>
|
||||
<a/b/b/b>
|
||||
<b/a>
|
||||
<b/a/a>
|
||||
<b/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/b>
|
||||
<b/a/a/b>
|
||||
<b/a/b>
|
||||
<b/a/b/a>
|
||||
<b/a/b/a>
|
||||
<b/a/b/b>
|
||||
<b/b/a>
|
||||
<b/b/a/a>
|
||||
<b/b/a/a>
|
||||
<b/b/a/b>
|
||||
<b/b/b/a>
|
||||
== <**/**/a/**> ==
|
||||
<a>
|
||||
<a/a>
|
||||
<a/a>
|
||||
<a/a/a>
|
||||
<a/a/a>
|
||||
<a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/a>
|
||||
<a/a/a/b>
|
||||
<a/a/a/b>
|
||||
<a/a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b>
|
||||
<a/a/b/a>
|
||||
<a/a/b/a>
|
||||
<a/a/b/a>
|
||||
<a/a/b/b>
|
||||
<a/a/b/b>
|
||||
<a/b>
|
||||
<a/b/a>
|
||||
<a/b/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/a>
|
||||
<a/b/a/b>
|
||||
<a/b/a/b>
|
||||
<a/b/b>
|
||||
<a/b/b/a>
|
||||
<a/b/b/a>
|
||||
<a/b/b/b>
|
||||
<b/a>
|
||||
<b/a/a>
|
||||
<b/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/a>
|
||||
<b/a/a/b>
|
||||
<b/a/a/b>
|
||||
<b/a/b>
|
||||
<b/a/b/a>
|
||||
<b/a/b/a>
|
||||
<b/a/b/b>
|
||||
<b/b/a>
|
||||
<b/b/a/a>
|
||||
<b/b/a/a>
|
||||
<b/b/a/b>
|
||||
<b/b/b/a>
|
||||
/tmp/empty
|
||||
|
||||
@@ -39,3 +39,4 @@ cd $dir
|
||||
rm -rf $GDIR
|
||||
|
||||
${THIS_SH} ./globstar1.sub
|
||||
${THIS_SH} ./globstar2.sub
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
: ${TMPDIR:=/var/tmp}
|
||||
dir=$PWD
|
||||
|
||||
shopt -s globstar
|
||||
|
||||
export LANG=C LC_ALL=C LC_COLLATE=C
|
||||
|
||||
GDIR=$TMPDIR/globstar-$$
|
||||
|
||||
mkdir $GDIR || exit 1
|
||||
cd $GDIR || exit 1
|
||||
|
||||
mkdir lib builtins
|
||||
mkdir lib/glob lib/readline lib/sh
|
||||
|
||||
touch builtins/history.o builtins/jobs.o builtins/kill.o builtins/let.o builtins/mapfile.o
|
||||
touch lib/glob/glob.o lib/glob/smatch.o lib/glob/strmatch.o
|
||||
touch lib/readline/bind.o lib/readline/callback.o lib/readline/compat.o lib/readline/complete.o lib/readline/display.o
|
||||
|
||||
touch lib/sh/casemod.o lib/sh/clktck.o lib/sh/clock.o lib/sh/eaccess.o
|
||||
touch lib/sh/fdprintf.o lib/sh/fmtullong.o lib/sh/fmtulong.o lib/sh/fmtumax.o
|
||||
touch lib/sh/fpurge.o lib/sh/getenv.o lib/sh/input_avail.o lib/sh/itos.o
|
||||
|
||||
touch alias.o
|
||||
touch pcomplib.o print_cmd.o redir.o shell.o sig.o stringlib.o subst.o syntax.o
|
||||
touch test.o trap.o unwind_prot.o variables.o version.o xmalloc.o y.tab.o
|
||||
|
||||
ls lib/**
|
||||
|
||||
ls lib/**/*.o
|
||||
|
||||
echo **/*.o
|
||||
|
||||
ls **
|
||||
|
||||
echo **
|
||||
|
||||
cd $dir
|
||||
rm -rf $GDIR
|
||||
|
||||
${THIS_SH} ./globstar1.sub
|
||||
@@ -0,0 +1,80 @@
|
||||
shopt -s globstar
|
||||
s()
|
||||
{
|
||||
printf '== <%s> ==\n' "$@"
|
||||
}
|
||||
p()
|
||||
{
|
||||
printf '<%q>\n' "$@"
|
||||
}
|
||||
|
||||
mkdir -p /tmp/empty/a/a/a
|
||||
cd /tmp/empty
|
||||
|
||||
# good
|
||||
p **
|
||||
p **/**
|
||||
p **/**/**
|
||||
|
||||
rm -rf a
|
||||
mkdir -p /tmp/empty/{a,b}/{a,b}/{a,b}/{a,b}
|
||||
cd /tmp/empty
|
||||
|
||||
# good
|
||||
s '**/a'
|
||||
p **/a
|
||||
|
||||
# good
|
||||
s 'a/**'
|
||||
p a/**
|
||||
|
||||
# good
|
||||
s '**'
|
||||
p **
|
||||
|
||||
# good
|
||||
s '**/**'
|
||||
p **/**
|
||||
|
||||
# good
|
||||
s '**/**/**'
|
||||
p **/**/**
|
||||
|
||||
# good
|
||||
s '**/**/**/**/**'
|
||||
p **/**/**/**/**
|
||||
|
||||
# good
|
||||
s '**/**/a'
|
||||
p **/**/a
|
||||
|
||||
# good
|
||||
s 'a/**/**'
|
||||
p a/**/**
|
||||
|
||||
# good
|
||||
s 'a/**/**/**'
|
||||
p a/**/**/**
|
||||
|
||||
# good
|
||||
s 'a/**/**/**/**'
|
||||
p a/**/**/**/**
|
||||
|
||||
# same as ksh93
|
||||
s '**/a/**'
|
||||
p **/a/**
|
||||
|
||||
# same as ksh93
|
||||
s '**/a/**/**'
|
||||
p **/a/**/**
|
||||
|
||||
# same as ksh93
|
||||
s '**/a/**/**/**'
|
||||
p **/a/**/**/**
|
||||
|
||||
# good
|
||||
s '**/**/a/**'
|
||||
p **/**/a/**
|
||||
|
||||
cd -
|
||||
rm -rf /tmp/empty
|
||||
+18
-15
@@ -24,20 +24,23 @@ job 7 returns 0
|
||||
4
|
||||
0
|
||||
i killed it
|
||||
12
|
||||
[1]- Running sleep 20 &
|
||||
[3]+ Running sleep 20 &
|
||||
0
|
||||
./jobs.tests: line 19: wait: %1: no such job
|
||||
./jobs.tests: line 24: fg: no job control
|
||||
./jobs.tests: line 22: wait: %1: no such job
|
||||
./jobs.tests: line 27: fg: no job control
|
||||
wait-for-pid
|
||||
wait-errors
|
||||
./jobs.tests: line 37: wait: `1-1': not a pid or valid job spec
|
||||
./jobs.tests: line 38: wait: `-4': not a pid or valid job spec
|
||||
./jobs.tests: line 40: wait: `1-1': not a pid or valid job spec
|
||||
./jobs.tests: line 41: wait: `-4': not a pid or valid job spec
|
||||
wait-for-background-pids
|
||||
async list wait-for-background-pids
|
||||
async list wait for child
|
||||
forked
|
||||
wait-when-no-children
|
||||
wait-for-job
|
||||
./jobs.tests: line 60: wait: %2: no such job
|
||||
./jobs.tests: line 63: wait: %2: no such job
|
||||
127
|
||||
async list wait-for-job
|
||||
forked
|
||||
@@ -50,19 +53,19 @@ sleep 5
|
||||
fg-bg 4
|
||||
sleep 5
|
||||
fg-bg 5
|
||||
./jobs.tests: line 87: fg: %2: no such job
|
||||
./jobs.tests: line 88: bg: job 1 already in background
|
||||
./jobs.tests: line 90: fg: %2: no such job
|
||||
./jobs.tests: line 91: bg: job 1 already in background
|
||||
fg-bg 6
|
||||
./jobs.tests: line 95: fg: -s: invalid option
|
||||
./jobs.tests: line 98: fg: -s: invalid option
|
||||
fg: usage: fg [job_spec]
|
||||
./jobs.tests: line 96: bg: -s: invalid option
|
||||
./jobs.tests: line 99: bg: -s: invalid option
|
||||
bg: usage: bg [job_spec ...]
|
||||
./jobs.tests: line 101: disown: -s: invalid option
|
||||
./jobs.tests: line 104: disown: -s: invalid option
|
||||
disown: usage: disown [-h] [-ar] [jobspec ...]
|
||||
./jobs.tests: line 105: disown: %1: no such job
|
||||
./jobs.tests: line 108: disown: %2: no such job
|
||||
./jobs.tests: line 108: disown: %1: no such job
|
||||
./jobs.tests: line 111: disown: %2: no such job
|
||||
wait-for-non-child
|
||||
./jobs.tests: line 111: wait: pid 1 is not a child of this shell
|
||||
./jobs.tests: line 114: wait: pid 1 is not a child of this shell
|
||||
127
|
||||
3 -- 1 2 3 -- 1 - 2 - 3
|
||||
[1] Running sleep 300 &
|
||||
@@ -72,8 +75,8 @@ running jobs:
|
||||
[1] Running sleep 300 &
|
||||
[2]- Running sleep 350 &
|
||||
[3]+ Running sleep 400 &
|
||||
./jobs.tests: line 128: kill: %4: no such job
|
||||
./jobs.tests: line 130: jobs: %4: no such job
|
||||
./jobs.tests: line 131: kill: %4: no such job
|
||||
./jobs.tests: line 133: jobs: %4: no such job
|
||||
current job:
|
||||
[3]+ Running sleep 400 &
|
||||
previous job:
|
||||
|
||||
@@ -12,6 +12,9 @@ ${THIS_SH} ./jobs3.sub
|
||||
# active
|
||||
${THIS_SH} ./jobs4.sub
|
||||
|
||||
# test out wait -n framework
|
||||
${THIS_SH} ./jobs5.sub
|
||||
|
||||
jobs
|
||||
echo $?
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# framework to test new `wait -n' option that waits for any job to finish
|
||||
|
||||
set -m
|
||||
|
||||
sleep 20 &
|
||||
{ sleep 5; exit 12; } &
|
||||
sleep 20 &
|
||||
|
||||
wait -n
|
||||
echo $?
|
||||
|
||||
jobs
|
||||
@@ -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
|
||||
@@ -66,3 +66,14 @@ argv[2] = <ab>
|
||||
${
|
||||
argv[1] = <(")>
|
||||
argv[1] = <(")>
|
||||
'weferfds'\''dsfsdf'
|
||||
'weferfdsdsfsdf'
|
||||
'weferfds'\''dsfsdf'
|
||||
'weferfds'\\dsfsdf'
|
||||
testdd ddtest
|
||||
testdd '\''ddtest
|
||||
testdddding
|
||||
testdddding
|
||||
test'ing
|
||||
test'ing
|
||||
test'string
|
||||
|
||||
@@ -109,3 +109,4 @@ recho `echo "(\\")"`
|
||||
# ultimate workaround
|
||||
recho `echo "(\")"`
|
||||
|
||||
${THIS_SH} ./quote1.sub
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
echo "Single Quote"
|
||||
echo 'foo
|
||||
bar'
|
||||
echo 'foo
|
||||
bar'
|
||||
echo 'foo\
|
||||
bar'
|
||||
|
||||
echo "Double Quote"
|
||||
echo "foo
|
||||
bar"
|
||||
echo "foo
|
||||
bar"
|
||||
echo "foo\
|
||||
bar"
|
||||
|
||||
echo "Backslash Single Quote"
|
||||
echo `echo 'foo
|
||||
bar'`
|
||||
echo `echo 'foo
|
||||
bar'`
|
||||
echo `echo 'foo\
|
||||
bar'`
|
||||
|
||||
echo "Backslash Double Quote"
|
||||
echo `echo "foo
|
||||
bar"`
|
||||
echo `echo "foo
|
||||
bar"`
|
||||
echo `echo "foo\
|
||||
bar"`
|
||||
|
||||
echo "Double Quote Backslash Single Quote"
|
||||
echo "`echo 'foo
|
||||
bar'`"
|
||||
echo "`echo 'foo
|
||||
bar'`"
|
||||
echo "`echo 'foo\
|
||||
bar'`"
|
||||
|
||||
echo "Dollar Paren Single Quote"
|
||||
echo $(echo 'foo
|
||||
bar')
|
||||
echo $(echo 'foo
|
||||
bar')
|
||||
echo $(echo 'foo\
|
||||
bar')
|
||||
|
||||
echo "Dollar Paren Double Quote"
|
||||
echo $(echo "foo
|
||||
bar")
|
||||
echo $(echo "foo
|
||||
bar")
|
||||
echo $(echo "foo\
|
||||
bar")
|
||||
|
||||
echo "Double Quote Dollar Paren Single Quote"
|
||||
echo "$(echo 'foo
|
||||
bar')"
|
||||
echo "$(echo 'foo
|
||||
bar')"
|
||||
echo "$(echo 'foo\
|
||||
bar')"
|
||||
|
||||
# old-style command substitution parsing compatibility tests -- post bash-3.1
|
||||
recho 'foo \\
|
||||
bar'
|
||||
|
||||
recho 'foo \
|
||||
bar'
|
||||
|
||||
echo `recho sed -e 's/[ :]/\\
|
||||
/g'`
|
||||
|
||||
echo `recho sed -e 's/[ :]/\
|
||||
/g'`
|
||||
|
||||
echo `recho 'foo\\
|
||||
bar'`
|
||||
|
||||
echo `recho 'foo\
|
||||
bar'`
|
||||
|
||||
echo $(recho 'foo\
|
||||
bar')
|
||||
|
||||
a=`echo 'a b c' | sed 's/ /\\
|
||||
/g' | grep 'b'`
|
||||
echo $a
|
||||
a=`echo 'a b c' | sed 's/ /\\
|
||||
/g'`
|
||||
echo "$a"
|
||||
|
||||
recho `echo 'a\' b`
|
||||
|
||||
recho `echo '\$' bab`
|
||||
recho `echo '\$foo' bab`
|
||||
recho `echo '$foo' bab`
|
||||
|
||||
recho `echo '\`' ab`
|
||||
|
||||
recho `echo '\\' ab`
|
||||
|
||||
echo `echo '${'`
|
||||
|
||||
recho `echo "(\\")"`
|
||||
# produces no output
|
||||
: `: "\\""`
|
||||
# ultimate workaround
|
||||
recho `echo "(\")"`
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# inconsistency with quoted pattern substitution patterns through bash-4.2
|
||||
# fixed in a ksh93-compatible (and Posix-compatible, in general) way
|
||||
# NOT backwards compatible
|
||||
|
||||
test="weferfds'dsfsdf"
|
||||
|
||||
# why does this work, this list was born of frustration, I tried
|
||||
# everything I could think of.
|
||||
echo \'${test//"'"/\'\\\'\'}\'" "
|
||||
|
||||
#but none of the following
|
||||
|
||||
echo "'${test//"'"/}'"
|
||||
|
||||
echo "'${test//"'"/"'\\''"}'"
|
||||
|
||||
echo "'${test//"'"/\'\\'\'}'"
|
||||
|
||||
#echo "'${test//'/}'" # hangs waiting for '
|
||||
#echo "'${test//"'"/'\\''}'" # hangs waiting for '
|
||||
|
||||
unset test
|
||||
test=teststrtest
|
||||
echo "${test//str/"dd dd"}"
|
||||
echo ${test//str/"dd '\''dd"}
|
||||
|
||||
unset test
|
||||
test=teststring
|
||||
|
||||
echo "${test//str/"dddd"}"
|
||||
|
||||
echo ${test//str/"dddd"}
|
||||
|
||||
echo ${test//str/"'"}
|
||||
|
||||
echo "${test//str/"'"}"
|
||||
|
||||
#echo "${test//str/'}" # hangs
|
||||
|
||||
test=test\'string
|
||||
echo "${test//"'"/"'"}"
|
||||
@@ -0,0 +1,37 @@
|
||||
test="weferfds'dsfsdf"
|
||||
|
||||
# why does this work, this list was born of frustration, I tried
|
||||
# everything I could think of.
|
||||
echo \'${test//"'"/\'\\\'\'}\'" "
|
||||
|
||||
#but none of the following
|
||||
|
||||
echo "'${test//"'"/}'"
|
||||
|
||||
echo "'${test//"'"/"'\\''"}'"
|
||||
|
||||
echo "'${test//"'"/\'\\'\'}'"
|
||||
|
||||
#echo "'${test//'/}'" # hangs waiting for '
|
||||
#echo "'${test//"'"/'\\''}'" # hangs waiting for '
|
||||
|
||||
unset test
|
||||
test=teststrtest
|
||||
echo "${test//str/"dd dd"}"
|
||||
echo ${test//str/"dd '\''dd"}
|
||||
|
||||
unset test
|
||||
test=teststring
|
||||
|
||||
echo "${test//str/"dddd"}"
|
||||
|
||||
echo ${test//str/"dddd"}
|
||||
|
||||
echo ${test//str/"'"}
|
||||
|
||||
echo "${test//str/"'"}"
|
||||
|
||||
#echo "${test//str/'}" # hangs
|
||||
|
||||
test=test\'string
|
||||
echo "${test//"'"/"'"}"
|
||||
Reference in New Issue
Block a user