commit bash-20121207 snapshot

This commit is contained in:
Chet Ramey
2013-01-03 10:46:09 -05:00
parent 8a0d41ab45
commit 8b20235af7
43 changed files with 15640 additions and 29 deletions
+24
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+82
View File
@@ -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.
+544
View File
@@ -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);
}
+50
View File
@@ -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 */
+3
View File
@@ -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
+1233
View File
File diff suppressed because it is too large Load Diff
+5
View File
@@ -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.
+42
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+238
View File
@@ -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
+549
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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_ */
+35
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+112 -12
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+76
View File
@@ -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
+26
View File
@@ -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
View File
@@ -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
View File
@@ -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
+9
View File
@@ -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
View File
@@ -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
+3
View File
@@ -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
+44
View File
@@ -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}
+3
View File
@@ -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>
+430
View File
@@ -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
+1
View File
@@ -39,3 +39,4 @@ cd $dir
rm -rf $GDIR
${THIS_SH} ./globstar1.sub
${THIS_SH} ./globstar2.sub
+41
View File
@@ -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
+80
View File
@@ -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
View File
@@ -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:
+3
View File
@@ -12,6 +12,9 @@ ${THIS_SH} ./jobs3.sub
# active
${THIS_SH} ./jobs4.sub
# test out wait -n framework
${THIS_SH} ./jobs5.sub
jobs
echo $?
+12
View File
@@ -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
+50
View File
@@ -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...
:;
+10
View File
@@ -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
+11
View File
@@ -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
+1
View File
@@ -109,3 +109,4 @@ recho `echo "(\\")"`
# ultimate workaround
recho `echo "(\")"`
${THIS_SH} ./quote1.sub
+111
View File
@@ -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 "(\")"`
+41
View File
@@ -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//"'"/"'"}"
+37
View File
@@ -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//"'"/"'"}"