mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-29 08:29:54 +02:00
bash-20140425 remove leftover and stray files
This commit is contained in:
-6183
File diff suppressed because it is too large
Load Diff
@@ -1,82 +0,0 @@
|
||||
Starting bash with the `--posix' command-line option or executing
|
||||
`set -o posix' while bash is running will cause bash to conform more
|
||||
closely to the Posix.2 standard by changing the behavior to match that
|
||||
specified by Posix.2 in areas where the bash default differs.
|
||||
|
||||
The following list is what's changed when `posix mode' is in effect:
|
||||
|
||||
1. When a command in the hash table no longer exists, bash will re-search
|
||||
$PATH to find the new location. This is also available with
|
||||
`shopt -s checkhash'.
|
||||
|
||||
2. The >& redirection does not redirect stdout and stderr.
|
||||
|
||||
3. The message printed by the job control code and builtins when a job
|
||||
exits with a non-zero status is `Done(status)'.
|
||||
|
||||
4. Reserved words may not be aliased.
|
||||
|
||||
5. The Posix.2 PS1 and PS2 expansions of `!' -> history number and
|
||||
`!!' -> `!' are enabled, and parameter expansion is performed on
|
||||
the value regardless of the setting of the `promptvars' option.
|
||||
|
||||
6. Interactive comments are enabled by default. (Note that bash has
|
||||
them on by default anyway.)
|
||||
|
||||
7. The Posix.2 startup files are executed ($ENV) rather than the normal
|
||||
bash files.
|
||||
|
||||
8. Tilde expansion is only performed on assignments preceding a command
|
||||
name, rather than on all assignment statements on the line.
|
||||
|
||||
9. The default history file is ~/.sh_history (default value of $HISTFILE).
|
||||
|
||||
10. The output of `kill -l' prints all the signal names on a single line,
|
||||
separated by spaces.
|
||||
|
||||
11. Non-interactive shells exit if `file' in `. file' is not found.
|
||||
|
||||
12. Redirection operators do not perform pathname expansion on the word
|
||||
in the redirection unless the shell is interactive
|
||||
|
||||
13. Function names must be valid shell identifiers. That is, they may not
|
||||
contain characters other than letters, digits, and underscores, and
|
||||
may not start with a digit. Declaring a function with an illegal name
|
||||
causes a fatal syntax error in non-interactive shells.
|
||||
|
||||
14. Posix.2 `special' builtins are found before shell functions during command
|
||||
lookup.
|
||||
|
||||
15. If a Posix.2 special builtin returns an error status, a non-interactive
|
||||
shell exits. The fatal errors are those listed in the POSIX.2 standard,
|
||||
and include things like passing incorrect options, redirection errors,
|
||||
variable assignment errors for assignments preceding the command name,
|
||||
and so on.
|
||||
|
||||
16. The environment passed to executed commands is not sorted. Neither is
|
||||
the output of `set'. This is not strictly Posix.2 behavior, but sh
|
||||
does it this way. Ksh does not. It's not necessary to sort the
|
||||
environment; no program should rely on it being sorted.
|
||||
|
||||
17. If the `cd' builtin finds a directory to change to using $CDPATH, the
|
||||
value it assigns to $PWD does not contain any symbolic links, as if
|
||||
`cd -P' had been executed.
|
||||
|
||||
18. A non-interactive shell exits with an error status if a variable
|
||||
assignment error occurs when no command name follows the assignment
|
||||
statements. A variable assignment error occurs, for example, when
|
||||
trying to assign a value to a read-only variable.
|
||||
|
||||
19. A non-interactive shell exits with an error status if the iteration
|
||||
variable in a for statement or the selection variable in a select
|
||||
statement is a read-only variable.
|
||||
|
||||
20. Process substitution is not available.
|
||||
|
||||
21. Assignment statements preceding POSIX.2 `special' builtins persist in
|
||||
the shell environment after the builtin completes.
|
||||
|
||||
There is other Posix.2 behavior that bash does not implement. Specifically:
|
||||
|
||||
1. Assignment statements affect the execution environment of all builtins,
|
||||
not just special ones.
|
||||
@@ -1,544 +0,0 @@
|
||||
This file is set.def, from which is created set.c.
|
||||
It implements the "set" and "unset" builtins in Bash.
|
||||
|
||||
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 1, or (at your option) any later
|
||||
version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$PRODUCES set.c
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../shell.h"
|
||||
#include "../flags.h"
|
||||
|
||||
#include "bashgetopt.h"
|
||||
|
||||
extern int interactive;
|
||||
extern int noclobber, posixly_correct;
|
||||
#if defined (READLINE)
|
||||
extern int rl_editing_mode, no_line_editing;
|
||||
#endif /* READLINE */
|
||||
|
||||
$BUILTIN set
|
||||
$FUNCTION set_builtin
|
||||
$SHORT_DOC set [--abefhkmnptuvxldBCHP] [-o option] [arg ...]
|
||||
-a Mark variables which are modified or created for export.
|
||||
-b Notify of job termination immediately.
|
||||
-e Exit immediately if a command exits with a non-zero status.
|
||||
-f Disable file name generation (globbing).
|
||||
-h Locate and remember function commands as functions are
|
||||
defined. Function commands are normally looked up when
|
||||
the function is executed.
|
||||
-i Force the shell to be an "interactive" one. Interactive shells
|
||||
always read `~/.bashrc' on startup.
|
||||
-k All keyword arguments are placed in the environment for a
|
||||
command, not just those that precede the command name.
|
||||
-m Job control is enabled.
|
||||
-n Read commands but do not execute them.
|
||||
-o option-name
|
||||
Set the variable corresponding to option-name:
|
||||
allexport same as -a
|
||||
braceexpand same as -B
|
||||
#if defined (READLINE)
|
||||
emacs use an emacs-style line editing interface
|
||||
#endif /* READLINE */
|
||||
errexit same as -e
|
||||
histexpand same as -H
|
||||
ignoreeof the shell will not exit upon reading EOF
|
||||
interactive-comments
|
||||
allow comments to appear in interactive commands
|
||||
monitor same as -m
|
||||
noclobber disallow redirection to existing files
|
||||
noexec same as -n
|
||||
noglob same as -f
|
||||
nohash same as -d
|
||||
notify save as -b
|
||||
nounset same as -u
|
||||
physical same as -P
|
||||
posix change the behavior of bash where the default
|
||||
operation differs from the 1003.2 standard to
|
||||
match the standard
|
||||
privileged same as -p
|
||||
verbose same as -v
|
||||
#if defined (READLINE)
|
||||
vi use a vi-style line editing interface
|
||||
#endif /* READLINE */
|
||||
xtrace same as -x
|
||||
-p Turned on whenever the real and effective user ids do not match.
|
||||
Disables processing of the $ENV file and importing of shell
|
||||
functions. Turning this option off causes the effective uid and
|
||||
gid to be set to the real uid and gid.
|
||||
-t Exit after reading and executing one command.
|
||||
-u Treat unset variables as an error when substituting.
|
||||
-v Print shell input lines as they are read.
|
||||
-x Print commands and their arguments as they are executed.
|
||||
-l Save and restore the binding of the NAME in a FOR command.
|
||||
-d Disable the hashing of commands that are looked up for execution.
|
||||
Normally, commands are remembered in a hash table, and once
|
||||
found, do not have to be looked up again.
|
||||
#if defined (BRACE_EXPANSION)
|
||||
-B the shell will perform brace expansion
|
||||
#endif /* BRACE_EXPANSION */
|
||||
#if defined (BANG_HISTORY)
|
||||
-H Enable ! style history substitution. This flag is on
|
||||
by default.
|
||||
#endif /* BANG_HISTORY */
|
||||
-C If set, disallow existing regular files to be overwritten
|
||||
by redirection of output.
|
||||
-P If set, do not follow symbolic links when executing commands
|
||||
such as cd which change the current directory.
|
||||
|
||||
Using + rather than - causes these flags to be turned off. The
|
||||
flags can also be used upon invocation of the shell. The current
|
||||
set of flags may be found in $-. The remaining n ARGs are positional
|
||||
parameters and are assigned, in order, to $1, $2, .. $n. If no
|
||||
ARGs are given, all shell variables are printed.
|
||||
$END
|
||||
|
||||
/* An a-list used to match long options for set -o to the corresponding
|
||||
option letter. */
|
||||
struct {
|
||||
char *name;
|
||||
int letter;
|
||||
} o_options[] = {
|
||||
{ "allexport", 'a' },
|
||||
#if defined (BRACE_EXPANSION)
|
||||
{ "braceexpand",'B' },
|
||||
#endif
|
||||
{ "errexit", 'e' },
|
||||
{ "histexpand", 'H' },
|
||||
{ "monitor", 'm' },
|
||||
{ "noexec", 'n' },
|
||||
{ "noglob", 'f' },
|
||||
{ "nohash", 'd' },
|
||||
#if defined (JOB_CONTROL)
|
||||
{ "notify", 'b' },
|
||||
#endif /* JOB_CONTROL */
|
||||
{"nounset", 'u' },
|
||||
{"physical", 'P' },
|
||||
{"privileged", 'p' },
|
||||
{"verbose", 'v' },
|
||||
{"xtrace", 'x' },
|
||||
{(char *)NULL, 0},
|
||||
};
|
||||
|
||||
#define MINUS_O_FORMAT "%-15s\t%s\n"
|
||||
|
||||
void
|
||||
list_minus_o_opts ()
|
||||
{
|
||||
register int i;
|
||||
char *on = "on", *off = "off";
|
||||
|
||||
printf (MINUS_O_FORMAT, "noclobber", (noclobber == 1) ? on : off);
|
||||
|
||||
if (find_variable ("ignoreeof") || find_variable ("IGNOREEOF"))
|
||||
printf (MINUS_O_FORMAT, "ignoreeof", on);
|
||||
else
|
||||
printf (MINUS_O_FORMAT, "ignoreeof", off);
|
||||
|
||||
printf (MINUS_O_FORMAT, "interactive-comments",
|
||||
interactive_comments ? on : off);
|
||||
|
||||
printf (MINUS_O_FORMAT, "posix", posixly_correct ? on : off);
|
||||
|
||||
#if defined (READLINE)
|
||||
if (no_line_editing)
|
||||
{
|
||||
printf (MINUS_O_FORMAT, "emacs", off);
|
||||
printf (MINUS_O_FORMAT, "vi", off);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Magic. This code `knows' how readline handles rl_editing_mode. */
|
||||
printf (MINUS_O_FORMAT, "emacs", (rl_editing_mode == 1) ? on : off);
|
||||
printf (MINUS_O_FORMAT, "vi", (rl_editing_mode == 0) ? on : off);
|
||||
}
|
||||
#endif /* READLINE */
|
||||
|
||||
for (i = 0; o_options[i].name; i++)
|
||||
{
|
||||
int *on_or_off, zero = 0;
|
||||
|
||||
on_or_off = find_flag (o_options[i].letter);
|
||||
if (on_or_off == FLAG_UNKNOWN)
|
||||
on_or_off = &zero;
|
||||
printf (MINUS_O_FORMAT, o_options[i].name, (*on_or_off == 1) ? on : off);
|
||||
}
|
||||
}
|
||||
|
||||
set_minus_o_option (on_or_off, option_name)
|
||||
int on_or_off;
|
||||
char *option_name;
|
||||
{
|
||||
int option_char = -1;
|
||||
|
||||
if (STREQ (option_name, "noclobber"))
|
||||
{
|
||||
if (on_or_off == FLAG_ON)
|
||||
bind_variable ("noclobber", "");
|
||||
else
|
||||
unbind_variable ("noclobber");
|
||||
stupidly_hack_special_variables ("noclobber");
|
||||
}
|
||||
else if (STREQ (option_name, "ignoreeof"))
|
||||
{
|
||||
unbind_variable ("ignoreeof");
|
||||
unbind_variable ("IGNOREEOF");
|
||||
if (on_or_off == FLAG_ON)
|
||||
bind_variable ("IGNOREEOF", "10");
|
||||
stupidly_hack_special_variables ("IGNOREEOF");
|
||||
}
|
||||
|
||||
#if defined (READLINE)
|
||||
else if ((STREQ (option_name, "emacs")) || (STREQ (option_name, "vi")))
|
||||
{
|
||||
if (on_or_off == FLAG_ON)
|
||||
{
|
||||
rl_variable_bind ("editing-mode", option_name);
|
||||
|
||||
if (interactive)
|
||||
with_input_from_stdin ();
|
||||
no_line_editing = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int isemacs = (rl_editing_mode == 1);
|
||||
if ((isemacs && STREQ (option_name, "emacs")) ||
|
||||
(!isemacs && STREQ (option_name, "vi")))
|
||||
{
|
||||
if (interactive)
|
||||
with_input_from_stream (stdin, "stdin");
|
||||
no_line_editing = 1;
|
||||
}
|
||||
else
|
||||
builtin_error ("not in %s editing mode", option_name);
|
||||
}
|
||||
}
|
||||
#endif /* READLINE */
|
||||
else if (STREQ (option_name, "interactive-comments"))
|
||||
interactive_comments = (on_or_off == FLAG_ON);
|
||||
else if (STREQ (option_name, "posix"))
|
||||
{
|
||||
posixly_correct = (on_or_off == FLAG_ON);
|
||||
unbind_variable ("POSIXLY_CORRECT");
|
||||
unbind_variable ("POSIX_PEDANTIC");
|
||||
if (on_or_off == FLAG_ON)
|
||||
{
|
||||
bind_variable ("POSIXLY_CORRECT", "");
|
||||
stupidly_hack_special_variables ("POSIXLY_CORRECT");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
register int i;
|
||||
for (i = 0; o_options[i].name; i++)
|
||||
{
|
||||
if (STREQ (option_name, o_options[i].name))
|
||||
{
|
||||
option_char = o_options[i].letter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (option_char == -1)
|
||||
{
|
||||
builtin_error ("%s: unknown option name", option_name);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
if (change_flag (option_char, on_or_off) == FLAG_ERROR)
|
||||
{
|
||||
bad_option (option_name);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
/* Set some flags from the word values in the input list. If LIST is empty,
|
||||
then print out the values of the variables instead. If LIST contains
|
||||
non-flags, then set $1 - $9 to the successive words of LIST. */
|
||||
set_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int on_or_off, flag_name, force_assignment = 0;
|
||||
|
||||
if (!list)
|
||||
{
|
||||
SHELL_VAR **vars;
|
||||
|
||||
vars = all_shell_variables ();
|
||||
if (vars)
|
||||
{
|
||||
print_var_list (vars);
|
||||
free (vars);
|
||||
}
|
||||
|
||||
vars = all_shell_functions ();
|
||||
if (vars)
|
||||
{
|
||||
print_var_list (vars);
|
||||
free (vars);
|
||||
}
|
||||
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
/* Check validity of flag arguments. */
|
||||
if (*list->word->word == '-' || *list->word->word == '+')
|
||||
{
|
||||
register char *arg;
|
||||
WORD_LIST *save_list = list;
|
||||
|
||||
while (list && (arg = list->word->word))
|
||||
{
|
||||
char c;
|
||||
|
||||
if (arg[0] != '-' && arg[0] != '+')
|
||||
break;
|
||||
|
||||
/* `-' or `--' signifies end of flag arguments. */
|
||||
if (arg[0] == '-' &&
|
||||
(!arg[1] || (arg[1] == '-' && !arg[2])))
|
||||
break;
|
||||
|
||||
while (c = *++arg)
|
||||
{
|
||||
if (find_flag (c) == FLAG_UNKNOWN && c != 'o')
|
||||
{
|
||||
char s[2];
|
||||
s[0] = c; s[1] = '\0';
|
||||
bad_option (s);
|
||||
if (c == '?')
|
||||
builtin_usage ();
|
||||
return (c == '?' ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
list = save_list;
|
||||
}
|
||||
|
||||
/* Do the set command. While the list consists of words starting with
|
||||
'-' or '+' treat them as flags, otherwise, start assigning them to
|
||||
$1 ... $n. */
|
||||
while (list)
|
||||
{
|
||||
char *string = list->word->word;
|
||||
|
||||
/* If the argument is `--' or `-' then signal the end of the list
|
||||
and remember the remaining arguments. */
|
||||
if (string[0] == '-' && (!string[1] || (string[1] == '-' && !string[2])))
|
||||
{
|
||||
list = list->next;
|
||||
|
||||
/* `set --' unsets the positional parameters. */
|
||||
if (string[1] == '-')
|
||||
force_assignment = 1;
|
||||
|
||||
/* Until told differently, the old shell behaviour of
|
||||
`set - [arg ...]' being equivalent to `set +xv [arg ...]'
|
||||
stands. Posix.2 says the behaviour is marked as obsolescent. */
|
||||
else
|
||||
{
|
||||
change_flag ('x', '+');
|
||||
change_flag ('v', '+');
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ((on_or_off = *string) &&
|
||||
(on_or_off == '-' || on_or_off == '+'))
|
||||
{
|
||||
int i = 1;
|
||||
while (flag_name = string[i++])
|
||||
{
|
||||
if (flag_name == '?')
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
else if (flag_name == 'o') /* -+o option-name */
|
||||
{
|
||||
char *option_name;
|
||||
WORD_LIST *opt;
|
||||
|
||||
opt = list->next;
|
||||
|
||||
if (!opt)
|
||||
{
|
||||
list_minus_o_opts ();
|
||||
continue;
|
||||
}
|
||||
|
||||
option_name = opt->word->word;
|
||||
|
||||
if (!option_name || !*option_name || (*option_name == '-'))
|
||||
{
|
||||
list_minus_o_opts ();
|
||||
continue;
|
||||
}
|
||||
list = list->next; /* Skip over option name. */
|
||||
|
||||
if (set_minus_o_option (on_or_off, option_name) != EXECUTION_SUCCESS)
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
|
||||
{
|
||||
char opt[3];
|
||||
opt[0] = on_or_off;
|
||||
opt[1] = flag_name;
|
||||
opt[2] = '\0';
|
||||
bad_option (opt);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
/* Assigning $1 ... $n */
|
||||
if (list || force_assignment)
|
||||
remember_args (list, 1);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
$BUILTIN unset
|
||||
$FUNCTION unset_builtin
|
||||
$SHORT_DOC unset [-f] [-v] [name ...]
|
||||
For each NAME, remove the corresponding variable or function. Given
|
||||
the `-v', unset will only act on variables. Given the `-f' flag,
|
||||
unset will only act on functions. With neither flag, unset first
|
||||
tries to unset a variable, and if that fails, then tries to unset a
|
||||
function. Some variables (such as PATH and IFS) cannot be unset; also
|
||||
see readonly.
|
||||
$END
|
||||
|
||||
#define NEXT_VARIABLE() any_failed++; list = list->next; continue;
|
||||
|
||||
unset_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int unset_function, unset_variable, unset_array, opt, any_failed;
|
||||
char *name;
|
||||
|
||||
unset_function = unset_variable = unset_array = any_failed = 0;
|
||||
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "fv")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'f':
|
||||
unset_function = 1;
|
||||
break;
|
||||
case 'v':
|
||||
unset_variable = 1;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
list = loptend;
|
||||
|
||||
if (unset_function && unset_variable)
|
||||
{
|
||||
builtin_error ("cannot simultaneously unset a function and a variable");
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
while (list)
|
||||
{
|
||||
SHELL_VAR *var;
|
||||
int tem;
|
||||
#if defined (ARRAY_VARS)
|
||||
char *t;
|
||||
#endif
|
||||
|
||||
name = list->word->word;
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
if (!unset_function && valid_array_reference (name))
|
||||
{
|
||||
t = strchr (name, '[');
|
||||
*t++ = '\0';
|
||||
unset_array++;
|
||||
}
|
||||
#endif
|
||||
|
||||
var = unset_function ? find_function (name) : find_variable (name);
|
||||
|
||||
if (var && !unset_function && non_unsettable_p (var))
|
||||
{
|
||||
builtin_error ("%s: cannot unset", name);
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
/* Posix.2 says that unsetting readonly variables is an error. */
|
||||
if (var && readonly_p (var))
|
||||
{
|
||||
builtin_error ("%s: cannot unset: readonly %s",
|
||||
name, unset_function ? "function" : "variable");
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
/* Unless the -f option is supplied, the name refers to a variable. */
|
||||
#if defined (ARRAY_VARS)
|
||||
if (var && unset_array)
|
||||
{
|
||||
if (array_p (var) == 0)
|
||||
{
|
||||
builtin_error ("%s: not an array variable", name);
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
else
|
||||
tem = unbind_array_element (var, t);
|
||||
}
|
||||
else
|
||||
#endif /* ARRAY_VARS */
|
||||
tem = makunbound (name, unset_function ? shell_functions : shell_variables);
|
||||
|
||||
/* This is what Posix.2 draft 11+ says. ``If neither -f nor -v
|
||||
is specified, the name refers to a variable; if a variable by
|
||||
that name does not exist, a function by that name, if any,
|
||||
shall be unset.'' */
|
||||
if ((tem == -1) && !unset_function && !unset_variable)
|
||||
tem = makunbound (name, shell_functions);
|
||||
|
||||
if (tem == -1)
|
||||
any_failed++;
|
||||
else if (!unset_function)
|
||||
stupidly_hack_special_variables (name);
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
if (any_failed)
|
||||
return (EXECUTION_FAILURE);
|
||||
else
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/* unwind_prot.h - Macros and functions for hacking unwind protection. */
|
||||
|
||||
/* Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#if !defined (_UNWIND_PROT_H)
|
||||
#define _UNWIND_PROT_H
|
||||
|
||||
/* Run a function without interrupts. */
|
||||
extern void begin_unwind_frame ();
|
||||
extern void discard_unwind_frame ();
|
||||
extern void run_unwind_frame ();
|
||||
extern void add_unwind_protect ();
|
||||
extern void remove_unwind_protect ();
|
||||
extern void run_unwind_protects ();
|
||||
extern void unwind_protect_var ();
|
||||
|
||||
/* Define for people who like their code to look a certain way. */
|
||||
#define end_unwind_frame()
|
||||
|
||||
/* How to protect an integer. */
|
||||
#define unwind_protect_int(X) unwind_protect_var (&(X), (char *)(X), sizeof (int))
|
||||
|
||||
/* How to protect a pointer to a string. */
|
||||
#define unwind_protect_string(X) \
|
||||
unwind_protect_var ((int *)&(X), (X), sizeof (char *))
|
||||
|
||||
/* How to protect any old pointer. */
|
||||
#define unwind_protect_pointer(X) unwind_protect_string (X)
|
||||
|
||||
/* How to protect the contents of a jmp_buf. */
|
||||
#define unwind_protect_jmp_buf(X) \
|
||||
unwind_protect_var ((int *)(X), (char *)(X), sizeof (procenv_t))
|
||||
|
||||
#endif /* _UNWIND_PROT_H */
|
||||
-923
@@ -1,923 +0,0 @@
|
||||
/* bashhist.c -- bash interface to the GNU history library. */
|
||||
|
||||
/* Copyright (C) 1993-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined (HISTORY)
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "bashtypes.h"
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "bashansi.h"
|
||||
#include "posixstat.h"
|
||||
#include "filecntl.h"
|
||||
|
||||
#include "bashintl.h"
|
||||
|
||||
#if defined (SYSLOG_HISTORY)
|
||||
# include <syslog.h>
|
||||
#endif
|
||||
|
||||
#include "shell.h"
|
||||
#include "flags.h"
|
||||
#include "input.h"
|
||||
#include "parser.h" /* for the struct dstack stuff. */
|
||||
#include "pathexp.h" /* for the struct ignorevar stuff */
|
||||
#include "bashhist.h" /* matching prototypes and declarations */
|
||||
#include "builtins/common.h"
|
||||
|
||||
#include <readline/history.h>
|
||||
#include <glob/glob.h>
|
||||
#include <glob/strmatch.h>
|
||||
|
||||
#if defined (READLINE)
|
||||
# include "bashline.h"
|
||||
extern int rl_done, rl_dispatching; /* should really include readline.h */
|
||||
#endif
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
static int histignore_item_func __P((struct ign *));
|
||||
static int check_history_control __P((char *));
|
||||
static void hc_erasedups __P((char *));
|
||||
static void really_add_history __P((char *));
|
||||
|
||||
static struct ignorevar histignore =
|
||||
{
|
||||
"HISTIGNORE",
|
||||
(struct ign *)0,
|
||||
0,
|
||||
(char *)0,
|
||||
(sh_iv_item_func_t *)histignore_item_func,
|
||||
};
|
||||
|
||||
#define HIGN_EXPAND 0x01
|
||||
|
||||
/* Declarations of bash history variables. */
|
||||
/* Non-zero means to remember lines typed to the shell on the history
|
||||
list. This is different than the user-controlled behaviour; this
|
||||
becomes zero when we read lines from a file, for example. */
|
||||
int remember_on_history = 1;
|
||||
int enable_history_list = 1; /* value for `set -o history' */
|
||||
|
||||
/* The number of lines that Bash has added to this history session. The
|
||||
difference between the number of the top element in the history list
|
||||
(offset from history_base) and the number of lines in the history file.
|
||||
Appending this session's history to the history file resets this to 0. */
|
||||
int history_lines_this_session;
|
||||
|
||||
/* The number of lines that Bash has read from the history file. */
|
||||
int history_lines_in_file;
|
||||
|
||||
#if defined (BANG_HISTORY)
|
||||
/* Non-zero means do no history expansion on this line, regardless
|
||||
of what history_expansion says. */
|
||||
int history_expansion_inhibited;
|
||||
#endif
|
||||
|
||||
/* With the old default, every line was saved in the history individually.
|
||||
I.e., if the user enters:
|
||||
bash$ for i in a b c
|
||||
> do
|
||||
> echo $i
|
||||
> done
|
||||
Each line will be individually saved in the history.
|
||||
bash$ history
|
||||
10 for i in a b c
|
||||
11 do
|
||||
12 echo $i
|
||||
13 done
|
||||
14 history
|
||||
If the variable command_oriented_history is set, multiple lines
|
||||
which form one command will be saved as one history entry.
|
||||
bash$ for i in a b c
|
||||
> do
|
||||
> echo $i
|
||||
> done
|
||||
bash$ history
|
||||
10 for i in a b c
|
||||
do
|
||||
echo $i
|
||||
done
|
||||
11 history
|
||||
The user can then recall the whole command all at once instead
|
||||
of just being able to recall one line at a time.
|
||||
|
||||
This is now enabled by default.
|
||||
*/
|
||||
int command_oriented_history = 1;
|
||||
|
||||
/* Set to 1 if the first line of a possibly-multi-line command was saved
|
||||
in the history list. Managed by maybe_add_history(), but global so
|
||||
the history-manipluating builtins can see it. */
|
||||
int current_command_first_line_saved = 0;
|
||||
|
||||
/* Non-zero means to store newlines in the history list when using
|
||||
command_oriented_history rather than trying to use semicolons. */
|
||||
int literal_history;
|
||||
|
||||
/* Non-zero means to append the history to the history file at shell
|
||||
exit, even if the history has been stifled. */
|
||||
int force_append_history;
|
||||
|
||||
/* A nit for picking at history saving. Flags have the following values:
|
||||
|
||||
Value == 0 means save all lines parsed by the shell on the history.
|
||||
Value & HC_IGNSPACE means save all lines that do not start with a space.
|
||||
Value & HC_IGNDUPS means save all lines that do not match the last
|
||||
line saved.
|
||||
Value & HC_ERASEDUPS means to remove all other matching lines from the
|
||||
history list before saving the latest line. */
|
||||
int history_control;
|
||||
|
||||
/* Set to 1 if the last command was added to the history list successfully
|
||||
as a separate history entry; set to 0 if the line was ignored or added
|
||||
to a previous entry as part of command-oriented-history processing. */
|
||||
int hist_last_line_added;
|
||||
|
||||
/* Set to 1 if builtins/history.def:push_history added the last history
|
||||
entry. */
|
||||
int hist_last_line_pushed;
|
||||
|
||||
#if defined (READLINE)
|
||||
/* If non-zero, and readline is being used, the user is offered the
|
||||
chance to re-edit a failed history expansion. */
|
||||
int history_reediting;
|
||||
|
||||
/* If non-zero, and readline is being used, don't directly execute a
|
||||
line with history substitution. Reload it into the editing buffer
|
||||
instead and let the user further edit and confirm with a newline. */
|
||||
int hist_verify;
|
||||
|
||||
#endif /* READLINE */
|
||||
|
||||
/* Non-zero means to not save function definitions in the history list. */
|
||||
int dont_save_function_defs;
|
||||
|
||||
/* Variables declared in other files used here. */
|
||||
extern int current_command_line_count;
|
||||
|
||||
extern struct dstack dstack;
|
||||
extern int parser_state;
|
||||
|
||||
static int bash_history_inhibit_expansion __P((char *, int));
|
||||
#if defined (READLINE)
|
||||
static void re_edit __P((char *));
|
||||
#endif
|
||||
static int history_expansion_p __P((char *));
|
||||
static int shell_comment __P((char *));
|
||||
static int should_expand __P((char *));
|
||||
static HIST_ENTRY *last_history_entry __P((void));
|
||||
static char *expand_histignore_pattern __P((char *));
|
||||
static int history_should_ignore __P((char *));
|
||||
|
||||
/* Is the history expansion starting at string[i] one that should not
|
||||
be expanded? */
|
||||
static int
|
||||
bash_history_inhibit_expansion (string, i)
|
||||
char *string;
|
||||
int i;
|
||||
{
|
||||
/* The shell uses ! as a pattern negation character in globbing [...]
|
||||
expressions, so let those pass without expansion. */
|
||||
if (i > 0 && (string[i - 1] == '[') && member (']', string + i + 1))
|
||||
return (1);
|
||||
/* The shell uses ! as the indirect expansion character, so let those
|
||||
expansions pass as well. */
|
||||
else if (i > 1 && string[i - 1] == '{' && string[i - 2] == '$' &&
|
||||
member ('}', string + i + 1))
|
||||
return (1);
|
||||
/* The shell uses $! as a defined parameter expansion. */
|
||||
else if (i > 1 && string[i - 1] == '$' && string[i] == '!')
|
||||
return (1);
|
||||
#if defined (EXTENDED_GLOB)
|
||||
else if (extended_glob && i > 1 && string[i+1] == '(' && member (')', string + i + 2))
|
||||
return (1);
|
||||
#endif
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
bash_initialize_history ()
|
||||
{
|
||||
history_quotes_inhibit_expansion = 1;
|
||||
history_search_delimiter_chars = ";&()|<>";
|
||||
history_inhibit_expansion_function = bash_history_inhibit_expansion;
|
||||
#if defined (BANG_HISTORY)
|
||||
sv_histchars ("histchars");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
bash_history_reinit (interact)
|
||||
int interact;
|
||||
{
|
||||
#if defined (BANG_HISTORY)
|
||||
history_expansion = interact != 0;
|
||||
history_expansion_inhibited = 1;
|
||||
#endif
|
||||
remember_on_history = enable_history_list = interact != 0;
|
||||
history_inhibit_expansion_function = bash_history_inhibit_expansion;
|
||||
}
|
||||
|
||||
void
|
||||
bash_history_disable ()
|
||||
{
|
||||
remember_on_history = 0;
|
||||
#if defined (BANG_HISTORY)
|
||||
history_expansion_inhibited = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
bash_history_enable ()
|
||||
{
|
||||
remember_on_history = 1;
|
||||
#if defined (BANG_HISTORY)
|
||||
history_expansion_inhibited = 0;
|
||||
#endif
|
||||
history_inhibit_expansion_function = bash_history_inhibit_expansion;
|
||||
sv_history_control ("HISTCONTROL");
|
||||
sv_histignore ("HISTIGNORE");
|
||||
}
|
||||
|
||||
/* Load the history list from the history file. */
|
||||
void
|
||||
load_history ()
|
||||
{
|
||||
char *hf;
|
||||
|
||||
/* Truncate history file for interactive shells which desire it.
|
||||
Note that the history file is automatically truncated to the
|
||||
size of HISTSIZE if the user does not explicitly set the size
|
||||
differently. */
|
||||
set_if_not ("HISTSIZE", "500");
|
||||
sv_histsize ("HISTSIZE");
|
||||
|
||||
set_if_not ("HISTFILESIZE", get_string_value ("HISTSIZE"));
|
||||
sv_histsize ("HISTFILESIZE");
|
||||
|
||||
/* Read the history in HISTFILE into the history list. */
|
||||
hf = get_string_value ("HISTFILE");
|
||||
|
||||
if (hf && *hf && file_exists (hf))
|
||||
{
|
||||
read_history (hf);
|
||||
using_history ();
|
||||
history_lines_in_file = where_history ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bash_clear_history ()
|
||||
{
|
||||
clear_history ();
|
||||
history_lines_this_session = 0;
|
||||
}
|
||||
|
||||
/* Delete and free the history list entry at offset I. */
|
||||
int
|
||||
bash_delete_histent (i)
|
||||
int i;
|
||||
{
|
||||
HIST_ENTRY *discard;
|
||||
|
||||
discard = remove_history (i);
|
||||
if (discard)
|
||||
free_history_entry (discard);
|
||||
history_lines_this_session--;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
bash_delete_last_history ()
|
||||
{
|
||||
register int i;
|
||||
HIST_ENTRY **hlist, *histent;
|
||||
int r;
|
||||
|
||||
hlist = history_list ();
|
||||
if (hlist == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; hlist[i]; i++)
|
||||
;
|
||||
i--;
|
||||
|
||||
/* History_get () takes a parameter that must be offset by history_base. */
|
||||
histent = history_get (history_base + i); /* Don't free this */
|
||||
if (histent == NULL)
|
||||
return 0;
|
||||
|
||||
r = bash_delete_histent (i);
|
||||
|
||||
if (where_history () > history_length)
|
||||
history_set_pos (history_length);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_UNUSED
|
||||
/* Write the existing history out to the history file. */
|
||||
void
|
||||
save_history ()
|
||||
{
|
||||
char *hf;
|
||||
int r;
|
||||
|
||||
hf = get_string_value ("HISTFILE");
|
||||
if (hf && *hf && file_exists (hf))
|
||||
{
|
||||
/* Append only the lines that occurred this session to
|
||||
the history file. */
|
||||
using_history ();
|
||||
|
||||
if (history_lines_this_session <= where_history () || force_append_history)
|
||||
r = append_history (history_lines_this_session, hf);
|
||||
else
|
||||
r = write_history (hf);
|
||||
sv_histsize ("HISTFILESIZE");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
maybe_append_history (filename)
|
||||
char *filename;
|
||||
{
|
||||
int fd, result;
|
||||
struct stat buf;
|
||||
|
||||
result = EXECUTION_SUCCESS;
|
||||
if (history_lines_this_session && (history_lines_this_session <= where_history ()))
|
||||
{
|
||||
/* If the filename was supplied, then create it if necessary. */
|
||||
if (stat (filename, &buf) == -1 && errno == ENOENT)
|
||||
{
|
||||
fd = open (filename, O_WRONLY|O_CREAT, 0600);
|
||||
if (fd < 0)
|
||||
{
|
||||
builtin_error (_("%s: cannot create: %s"), filename, strerror (errno));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
result = append_history (history_lines_this_session, filename);
|
||||
history_lines_in_file += history_lines_this_session;
|
||||
history_lines_this_session = 0;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* If this is an interactive shell, then append the lines executed
|
||||
this session to the history file. */
|
||||
int
|
||||
maybe_save_shell_history ()
|
||||
{
|
||||
int result;
|
||||
char *hf;
|
||||
|
||||
result = 0;
|
||||
if (history_lines_this_session)
|
||||
{
|
||||
hf = get_string_value ("HISTFILE");
|
||||
|
||||
if (hf && *hf)
|
||||
{
|
||||
/* If the file doesn't exist, then create it. */
|
||||
if (file_exists (hf) == 0)
|
||||
{
|
||||
int file;
|
||||
file = open (hf, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
||||
if (file != -1)
|
||||
close (file);
|
||||
}
|
||||
|
||||
/* Now actually append the lines if the history hasn't been
|
||||
stifled. If the history has been stifled, rewrite the
|
||||
history file. */
|
||||
using_history ();
|
||||
if (history_lines_this_session <= where_history () || force_append_history)
|
||||
{
|
||||
result = append_history (history_lines_this_session, hf);
|
||||
history_lines_in_file += history_lines_this_session;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = write_history (hf);
|
||||
history_lines_in_file = history_lines_this_session;
|
||||
}
|
||||
history_lines_this_session = 0;
|
||||
|
||||
sv_histsize ("HISTFILESIZE");
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
#if defined (READLINE)
|
||||
/* Tell readline () that we have some text for it to edit. */
|
||||
static void
|
||||
re_edit (text)
|
||||
char *text;
|
||||
{
|
||||
if (bash_input.type == st_stdin)
|
||||
bash_re_edit (text);
|
||||
}
|
||||
#endif /* READLINE */
|
||||
|
||||
/* Return 1 if this line needs history expansion. */
|
||||
static int
|
||||
history_expansion_p (line)
|
||||
char *line;
|
||||
{
|
||||
register char *s;
|
||||
|
||||
for (s = line; *s; s++)
|
||||
if (*s == history_expansion_char || *s == history_subst_char)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Do pre-processing on LINE. If PRINT_CHANGES is non-zero, then
|
||||
print the results of expanding the line if there were any changes.
|
||||
If there is an error, return NULL, otherwise the expanded line is
|
||||
returned. If ADDIT is non-zero the line is added to the history
|
||||
list after history expansion. ADDIT is just a suggestion;
|
||||
REMEMBER_ON_HISTORY can veto, and does.
|
||||
Right now this does history expansion. */
|
||||
char *
|
||||
pre_process_line (line, print_changes, addit)
|
||||
char *line;
|
||||
int print_changes, addit;
|
||||
{
|
||||
char *history_value;
|
||||
char *return_value;
|
||||
int expanded;
|
||||
|
||||
return_value = line;
|
||||
expanded = 0;
|
||||
|
||||
# if defined (BANG_HISTORY)
|
||||
/* History expand the line. If this results in no errors, then
|
||||
add that line to the history if ADDIT is non-zero. */
|
||||
if (!history_expansion_inhibited && history_expansion && history_expansion_p (line))
|
||||
{
|
||||
expanded = history_expand (line, &history_value);
|
||||
|
||||
if (expanded)
|
||||
{
|
||||
if (print_changes)
|
||||
{
|
||||
if (expanded < 0)
|
||||
internal_error ("%s", history_value);
|
||||
#if defined (READLINE)
|
||||
else if (hist_verify == 0 || expanded == 2)
|
||||
#else
|
||||
else
|
||||
#endif
|
||||
fprintf (stderr, "%s\n", history_value);
|
||||
}
|
||||
|
||||
/* If there was an error, return NULL. */
|
||||
if (expanded < 0 || expanded == 2) /* 2 == print only */
|
||||
{
|
||||
# if defined (READLINE)
|
||||
if (expanded == 2 && rl_dispatching == 0 && *history_value)
|
||||
# else
|
||||
if (expanded == 2 && *history_value)
|
||||
# endif /* !READLINE */
|
||||
maybe_add_history (history_value);
|
||||
|
||||
free (history_value);
|
||||
|
||||
# if defined (READLINE)
|
||||
/* New hack. We can allow the user to edit the
|
||||
failed history expansion. */
|
||||
if (history_reediting && expanded < 0 && rl_done)
|
||||
re_edit (line);
|
||||
# endif /* READLINE */
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
# if defined (READLINE)
|
||||
if (hist_verify && expanded == 1)
|
||||
{
|
||||
re_edit (history_value);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
/* Let other expansions know that return_value can be free'ed,
|
||||
and that a line has been added to the history list. Note
|
||||
that we only add lines that have something in them. */
|
||||
expanded = 1;
|
||||
return_value = history_value;
|
||||
}
|
||||
# endif /* BANG_HISTORY */
|
||||
|
||||
if (addit && remember_on_history && *return_value)
|
||||
maybe_add_history (return_value);
|
||||
|
||||
#if 0
|
||||
if (expanded == 0)
|
||||
return_value = savestring (line);
|
||||
#endif
|
||||
|
||||
return (return_value);
|
||||
}
|
||||
|
||||
/* Return 1 if the first non-whitespace character in LINE is a `#', indicating
|
||||
* that the line is a shell comment. */
|
||||
static int
|
||||
shell_comment (line)
|
||||
char *line;
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = line; p && *p && whitespace (*p); p++)
|
||||
;
|
||||
return (p && *p == '#');
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_UNUSED
|
||||
/* Remove shell comments from LINE. A `#' and anything after it is a comment.
|
||||
This isn't really useful yet, since it doesn't handle quoting. */
|
||||
static char *
|
||||
filter_comments (line)
|
||||
char *line;
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = line; p && *p && *p != '#'; p++)
|
||||
;
|
||||
if (p && *p == '#')
|
||||
*p = '\0';
|
||||
return (line);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check LINE against what HISTCONTROL says to do. Returns 1 if the line
|
||||
should be saved; 0 if it should be discarded. */
|
||||
static int
|
||||
check_history_control (line)
|
||||
char *line;
|
||||
{
|
||||
HIST_ENTRY *temp;
|
||||
int r;
|
||||
|
||||
if (history_control == 0)
|
||||
return 1;
|
||||
|
||||
/* ignorespace or ignoreboth */
|
||||
if ((history_control & HC_IGNSPACE) && *line == ' ')
|
||||
return 0;
|
||||
|
||||
/* ignoredups or ignoreboth */
|
||||
if (history_control & HC_IGNDUPS)
|
||||
{
|
||||
using_history ();
|
||||
temp = previous_history ();
|
||||
|
||||
r = (temp == 0 || STREQ (temp->line, line) == 0);
|
||||
|
||||
using_history ();
|
||||
|
||||
if (r == 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Remove all entries matching LINE from the history list. Triggered when
|
||||
HISTCONTROL includes `erasedups'. */
|
||||
static void
|
||||
hc_erasedups (line)
|
||||
char *line;
|
||||
{
|
||||
HIST_ENTRY *temp;
|
||||
int r;
|
||||
|
||||
using_history ();
|
||||
while (temp = previous_history ())
|
||||
{
|
||||
if (STREQ (temp->line, line))
|
||||
{
|
||||
r = where_history ();
|
||||
remove_history (r);
|
||||
}
|
||||
}
|
||||
using_history ();
|
||||
}
|
||||
|
||||
/* Add LINE to the history list, handling possibly multi-line compound
|
||||
commands. We note whether or not we save the first line of each command
|
||||
(which is usually the entire command and history entry), and don't add
|
||||
the second and subsequent lines of a multi-line compound command if we
|
||||
didn't save the first line. We don't usually save shell comment lines in
|
||||
compound commands in the history, because they could have the effect of
|
||||
commenting out the rest of the command when the entire command is saved as
|
||||
a single history entry (when COMMAND_ORIENTED_HISTORY is enabled). If
|
||||
LITERAL_HISTORY is set, we're saving lines in the history with embedded
|
||||
newlines, so it's OK to save comment lines. If we're collecting the body
|
||||
of a here-document, we should act as if literal_history is enabled, because
|
||||
we want to save the entire contents of the here-document as it was
|
||||
entered. We also make sure to save multiple-line quoted strings or other
|
||||
constructs. */
|
||||
void
|
||||
maybe_add_history (line)
|
||||
char *line;
|
||||
{
|
||||
hist_last_line_added = 0;
|
||||
|
||||
/* Don't use the value of history_control to affect the second
|
||||
and subsequent lines of a multi-line command (old code did
|
||||
this only when command_oriented_history is enabled). */
|
||||
if (current_command_line_count > 1)
|
||||
{
|
||||
if (current_command_first_line_saved &&
|
||||
((parser_state & PST_HEREDOC) || literal_history || dstack.delimiter_depth != 0 || shell_comment (line) == 0))
|
||||
bash_add_history (line);
|
||||
return;
|
||||
}
|
||||
|
||||
/* This is the first line of a (possible multi-line) command. Note whether
|
||||
or not we should save the first line and remember it. */
|
||||
current_command_first_line_saved = check_add_history (line, 0);
|
||||
}
|
||||
|
||||
/* Just check LINE against HISTCONTROL and HISTIGNORE and add it to the
|
||||
history if it's OK. Used by `history -s' as well as maybe_add_history().
|
||||
Returns 1 if the line was saved in the history, 0 otherwise. */
|
||||
int
|
||||
check_add_history (line, force)
|
||||
char *line;
|
||||
int force;
|
||||
{
|
||||
if (check_history_control (line) && history_should_ignore (line) == 0)
|
||||
{
|
||||
/* We're committed to saving the line. If the user has requested it,
|
||||
remove other matching lines from the history. */
|
||||
if (history_control & HC_ERASEDUPS)
|
||||
hc_erasedups (line);
|
||||
|
||||
if (force)
|
||||
{
|
||||
really_add_history (line);
|
||||
using_history ();
|
||||
}
|
||||
else
|
||||
bash_add_history (line);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined (SYSLOG_HISTORY)
|
||||
#define SYSLOG_MAXLEN 600
|
||||
|
||||
void
|
||||
bash_syslog_history (line)
|
||||
const char *line;
|
||||
{
|
||||
char trunc[SYSLOG_MAXLEN];
|
||||
|
||||
if (strlen(line) < SYSLOG_MAXLEN)
|
||||
syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY: PID=%d UID=%d %s", getpid(), current_user.uid, line);
|
||||
else
|
||||
{
|
||||
strncpy (trunc, line, SYSLOG_MAXLEN);
|
||||
trunc[SYSLOG_MAXLEN - 1] = '\0';
|
||||
syslog (SYSLOG_FACILITY|SYSLOG_LEVEL, "HISTORY (TRUNCATED): PID=%d UID=%d %s", getpid(), current_user.uid, trunc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Add a line to the history list.
|
||||
The variable COMMAND_ORIENTED_HISTORY controls the style of history
|
||||
remembering; when non-zero, and LINE is not the first line of a
|
||||
complete parser construct, append LINE to the last history line instead
|
||||
of adding it as a new line. */
|
||||
void
|
||||
bash_add_history (line)
|
||||
char *line;
|
||||
{
|
||||
int add_it, offset, curlen;
|
||||
HIST_ENTRY *current, *old;
|
||||
char *chars_to_add, *new_line;
|
||||
|
||||
add_it = 1;
|
||||
if (command_oriented_history && current_command_line_count > 1)
|
||||
{
|
||||
/* The second and subsequent lines of a here document have the trailing
|
||||
newline preserved. We don't want to add extra newlines here, but we
|
||||
do want to add one after the first line (which is the command that
|
||||
contains the here-doc specifier). parse.y:history_delimiting_chars()
|
||||
does the right thing to take care of this for us. We don't want to
|
||||
add extra newlines if the user chooses to enable literal_history,
|
||||
so we have to duplicate some of what that function does here. */
|
||||
if ((parser_state & PST_HEREDOC) && literal_history && current_command_line_count > 2 && line[strlen (line) - 1] == '\n')
|
||||
chars_to_add = "";
|
||||
else
|
||||
chars_to_add = literal_history ? "\n" : history_delimiting_chars (line);
|
||||
|
||||
using_history ();
|
||||
current = previous_history ();
|
||||
|
||||
if (current)
|
||||
{
|
||||
/* If the previous line ended with an escaped newline (escaped
|
||||
with backslash, but otherwise unquoted), then remove the quoted
|
||||
newline, since that is what happens when the line is parsed. */
|
||||
curlen = strlen (current->line);
|
||||
|
||||
if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\\' &&
|
||||
current->line[curlen - 2] != '\\')
|
||||
{
|
||||
current->line[curlen - 1] = '\0';
|
||||
curlen--;
|
||||
chars_to_add = "";
|
||||
}
|
||||
|
||||
/* If we're not in some kind of quoted construct, the current history
|
||||
entry ends with a newline, and we're going to add a semicolon,
|
||||
don't. In some cases, it results in a syntax error (e.g., before
|
||||
a close brace), and it should not be needed. */
|
||||
if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\n' && *chars_to_add == ';')
|
||||
chars_to_add++;
|
||||
|
||||
new_line = (char *)xmalloc (1
|
||||
+ curlen
|
||||
+ strlen (line)
|
||||
+ strlen (chars_to_add));
|
||||
sprintf (new_line, "%s%s%s", current->line, chars_to_add, line);
|
||||
offset = where_history ();
|
||||
old = replace_history_entry (offset, new_line, current->data);
|
||||
free (new_line);
|
||||
|
||||
if (old)
|
||||
free_history_entry (old);
|
||||
|
||||
add_it = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (add_it)
|
||||
really_add_history (line);
|
||||
|
||||
#if defined (SYSLOG_HISTORY)
|
||||
bash_syslog_history (line);
|
||||
#endif
|
||||
|
||||
using_history ();
|
||||
}
|
||||
|
||||
static void
|
||||
really_add_history (line)
|
||||
char *line;
|
||||
{
|
||||
hist_last_line_added = 1;
|
||||
hist_last_line_pushed = 0;
|
||||
add_history (line);
|
||||
history_lines_this_session++;
|
||||
}
|
||||
|
||||
int
|
||||
history_number ()
|
||||
{
|
||||
using_history ();
|
||||
return (remember_on_history ? history_base + where_history () : 1);
|
||||
}
|
||||
|
||||
static int
|
||||
should_expand (s)
|
||||
char *s;
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = s; p && *p; p++)
|
||||
{
|
||||
if (*p == '\\')
|
||||
p++;
|
||||
else if (*p == '&')
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
histignore_item_func (ign)
|
||||
struct ign *ign;
|
||||
{
|
||||
if (should_expand (ign->val))
|
||||
ign->flags |= HIGN_EXPAND;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
setup_history_ignore (varname)
|
||||
char *varname;
|
||||
{
|
||||
setup_ignore_patterns (&histignore);
|
||||
}
|
||||
|
||||
static HIST_ENTRY *
|
||||
last_history_entry ()
|
||||
{
|
||||
HIST_ENTRY *he;
|
||||
|
||||
using_history ();
|
||||
he = previous_history ();
|
||||
using_history ();
|
||||
return he;
|
||||
}
|
||||
|
||||
char *
|
||||
last_history_line ()
|
||||
{
|
||||
HIST_ENTRY *he;
|
||||
|
||||
he = last_history_entry ();
|
||||
if (he == 0)
|
||||
return ((char *)NULL);
|
||||
return he->line;
|
||||
}
|
||||
|
||||
static char *
|
||||
expand_histignore_pattern (pat)
|
||||
char *pat;
|
||||
{
|
||||
HIST_ENTRY *phe;
|
||||
char *ret;
|
||||
|
||||
phe = last_history_entry ();
|
||||
|
||||
if (phe == (HIST_ENTRY *)0)
|
||||
return (savestring (pat));
|
||||
|
||||
ret = strcreplace (pat, '&', phe->line, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return 1 if we should not put LINE into the history according to the
|
||||
patterns in HISTIGNORE. */
|
||||
static int
|
||||
history_should_ignore (line)
|
||||
char *line;
|
||||
{
|
||||
register int i, match;
|
||||
char *npat;
|
||||
|
||||
if (histignore.num_ignores == 0)
|
||||
return 0;
|
||||
|
||||
for (i = match = 0; i < histignore.num_ignores; i++)
|
||||
{
|
||||
if (histignore.ignores[i].flags & HIGN_EXPAND)
|
||||
npat = expand_histignore_pattern (histignore.ignores[i].val);
|
||||
else
|
||||
npat = histignore.ignores[i].val;
|
||||
|
||||
match = strmatch (npat, line, FNMATCH_EXTFLAG) != FNM_NOMATCH;
|
||||
|
||||
if (histignore.ignores[i].flags & HIGN_EXPAND)
|
||||
free (npat);
|
||||
|
||||
if (match)
|
||||
break;
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
#endif /* HISTORY */
|
||||
@@ -1,341 +0,0 @@
|
||||
This file is bind.def, from which is created bind.c.
|
||||
It implements the builtin "bind" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$PRODUCES bind.c
|
||||
|
||||
#include <config.h>
|
||||
|
||||
$BUILTIN bind
|
||||
$DEPENDS_ON READLINE
|
||||
$FUNCTION bind_builtin
|
||||
$SHORT_DOC bind [-lpsvPSVX] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function or readline-command]
|
||||
Set Readline key bindings and variables.
|
||||
|
||||
Bind a key sequence to a Readline function or a macro, or set a
|
||||
Readline variable. The non-option argument syntax is equivalent to
|
||||
that found in ~/.inputrc, but must be passed as a single argument:
|
||||
e.g., bind '"\C-x\C-r": re-read-init-file'.
|
||||
|
||||
Options:
|
||||
-m keymap Use KEYMAP as the keymap for the duration of this
|
||||
command. Acceptable keymap names are emacs,
|
||||
emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,
|
||||
vi-command, and vi-insert.
|
||||
-l List names of functions.
|
||||
-P List function names and bindings.
|
||||
-p List functions and bindings in a form that can be
|
||||
reused as input.
|
||||
-S List key sequences that invoke macros and their values
|
||||
-s List key sequences that invoke macros and their values
|
||||
in a form that can be reused as input.
|
||||
-V List variable names and values
|
||||
-v List variable names and values in a form that can
|
||||
be reused as input.
|
||||
-q function-name Query about which keys invoke the named function.
|
||||
-u function-name Unbind all keys which are bound to the named function.
|
||||
-r keyseq Remove the binding for KEYSEQ.
|
||||
-f filename Read key bindings from FILENAME.
|
||||
-x keyseq:shell-command Cause SHELL-COMMAND to be executed when
|
||||
KEYSEQ is entered.
|
||||
-X List key sequences bound with -x and associated commands
|
||||
in a form that can be reused as input.
|
||||
|
||||
Exit Status:
|
||||
bind returns 0 unless an unrecognized option is given or an error occurs.
|
||||
$END
|
||||
|
||||
#if defined (READLINE)
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
#include "../bashintl.h"
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../bashline.h"
|
||||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
static int query_bindings __P((char *));
|
||||
static int unbind_command __P((char *));
|
||||
|
||||
extern int no_line_editing;
|
||||
|
||||
#define BIND_RETURN(x) do { return_code = x; goto bind_exit; } while (0)
|
||||
|
||||
#define LFLAG 0x0001
|
||||
#define PFLAG 0x0002
|
||||
#define FFLAG 0x0004
|
||||
#define VFLAG 0x0008
|
||||
#define QFLAG 0x0010
|
||||
#define MFLAG 0x0020
|
||||
#define RFLAG 0x0040
|
||||
#define PPFLAG 0x0080
|
||||
#define VVFLAG 0x0100
|
||||
#define SFLAG 0x0200
|
||||
#define SSFLAG 0x0400
|
||||
#define UFLAG 0x0800
|
||||
#define XFLAG 0x1000
|
||||
#define XXFLAG 0x2000
|
||||
|
||||
int
|
||||
bind_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int return_code;
|
||||
Keymap kmap, saved_keymap;
|
||||
int flags, opt;
|
||||
char *initfile, *map_name, *fun_name, *unbind_name, *remove_seq, *cmd_seq;
|
||||
|
||||
if (no_line_editing)
|
||||
{
|
||||
#if 0
|
||||
builtin_error (_("line editing not enabled"));
|
||||
return (EXECUTION_FAILURE);
|
||||
#else
|
||||
builtin_warning (_("line editing not enabled"));
|
||||
#endif
|
||||
}
|
||||
|
||||
kmap = saved_keymap = (Keymap) NULL;
|
||||
flags = 0;
|
||||
initfile = map_name = fun_name = unbind_name = remove_seq = (char *)NULL;
|
||||
return_code = EXECUTION_SUCCESS;
|
||||
|
||||
if (bash_readline_initialized == 0)
|
||||
initialize_readline ();
|
||||
|
||||
begin_unwind_frame ("bind_builtin");
|
||||
unwind_protect_var (rl_outstream);
|
||||
|
||||
rl_outstream = stdout;
|
||||
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "lvpVPsSXf:q:u:m:r:x:")) != EOF)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'l':
|
||||
flags |= LFLAG;
|
||||
break;
|
||||
case 'v':
|
||||
flags |= VFLAG;
|
||||
break;
|
||||
case 'p':
|
||||
flags |= PFLAG;
|
||||
break;
|
||||
case 'f':
|
||||
flags |= FFLAG;
|
||||
initfile = list_optarg;
|
||||
break;
|
||||
case 'm':
|
||||
flags |= MFLAG;
|
||||
map_name = list_optarg;
|
||||
break;
|
||||
case 'q':
|
||||
flags |= QFLAG;
|
||||
fun_name = list_optarg;
|
||||
break;
|
||||
case 'u':
|
||||
flags |= UFLAG;
|
||||
unbind_name = list_optarg;
|
||||
break;
|
||||
case 'r':
|
||||
flags |= RFLAG;
|
||||
remove_seq = list_optarg;
|
||||
break;
|
||||
case 'V':
|
||||
flags |= VVFLAG;
|
||||
break;
|
||||
case 'P':
|
||||
flags |= PPFLAG;
|
||||
break;
|
||||
case 's':
|
||||
flags |= SFLAG;
|
||||
break;
|
||||
case 'S':
|
||||
flags |= SSFLAG;
|
||||
break;
|
||||
case 'x':
|
||||
flags |= XFLAG;
|
||||
cmd_seq = list_optarg;
|
||||
break;
|
||||
case 'X':
|
||||
flags |= XXFLAG;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
BIND_RETURN (EX_USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
list = loptend;
|
||||
|
||||
/* First, see if we need to install a special keymap for this
|
||||
command. Then start on the arguments. */
|
||||
|
||||
if ((flags & MFLAG) && map_name)
|
||||
{
|
||||
kmap = rl_get_keymap_by_name (map_name);
|
||||
if (kmap == 0)
|
||||
{
|
||||
builtin_error (_("`%s': invalid keymap name"), map_name);
|
||||
BIND_RETURN (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (kmap)
|
||||
{
|
||||
saved_keymap = rl_get_keymap ();
|
||||
rl_set_keymap (kmap);
|
||||
}
|
||||
|
||||
/* XXX - we need to add exclusive use tests here. It doesn't make sense
|
||||
to use some of these options together. */
|
||||
/* Now hack the option arguments */
|
||||
if (flags & LFLAG)
|
||||
rl_list_funmap_names ();
|
||||
|
||||
if (flags & PFLAG)
|
||||
rl_function_dumper (1);
|
||||
|
||||
if (flags & PPFLAG)
|
||||
rl_function_dumper (0);
|
||||
|
||||
if (flags & SFLAG)
|
||||
rl_macro_dumper (1);
|
||||
|
||||
if (flags & SSFLAG)
|
||||
rl_macro_dumper (0);
|
||||
|
||||
if (flags & VFLAG)
|
||||
rl_variable_dumper (1);
|
||||
|
||||
if (flags & VVFLAG)
|
||||
rl_variable_dumper (0);
|
||||
|
||||
if ((flags & FFLAG) && initfile)
|
||||
{
|
||||
if (rl_read_init_file (initfile) != 0)
|
||||
{
|
||||
builtin_error (_("%s: cannot read: %s"), initfile, strerror (errno));
|
||||
BIND_RETURN (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & QFLAG) && fun_name)
|
||||
return_code = query_bindings (fun_name);
|
||||
|
||||
if ((flags & UFLAG) && unbind_name)
|
||||
return_code = unbind_command (unbind_name);
|
||||
|
||||
if ((flags & RFLAG) && remove_seq)
|
||||
{
|
||||
if (rl_bind_keyseq (remove_seq, (rl_command_func_t *)NULL) != 0)
|
||||
{
|
||||
builtin_error (_("`%s': cannot unbind"), remove_seq);
|
||||
BIND_RETURN (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & XFLAG)
|
||||
return_code = bind_keyseq_to_unix_command (cmd_seq);
|
||||
|
||||
if (flags & XXFLAG)
|
||||
return_code = print_unix_command_map ();
|
||||
|
||||
/* Process the rest of the arguments as binding specifications. */
|
||||
while (list)
|
||||
{
|
||||
rl_parse_and_bind (list->word->word);
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
bind_exit:
|
||||
if (saved_keymap)
|
||||
rl_set_keymap (saved_keymap);
|
||||
|
||||
run_unwind_frame ("bind_builtin");
|
||||
|
||||
return (sh_chkwrite (return_code));
|
||||
}
|
||||
|
||||
static int
|
||||
query_bindings (name)
|
||||
char *name;
|
||||
{
|
||||
rl_command_func_t *function;
|
||||
char **keyseqs;
|
||||
int j;
|
||||
|
||||
function = rl_named_function (name);
|
||||
if (function == 0)
|
||||
{
|
||||
builtin_error (_("`%s': unknown function name"), name);
|
||||
return EXECUTION_FAILURE;
|
||||
}
|
||||
|
||||
keyseqs = rl_invoking_keyseqs (function);
|
||||
|
||||
if (!keyseqs)
|
||||
{
|
||||
printf (_("%s is not bound to any keys.\n"), name);
|
||||
return EXECUTION_FAILURE;
|
||||
}
|
||||
|
||||
printf (_("%s can be invoked via "), name);
|
||||
for (j = 0; j < 5 && keyseqs[j]; j++)
|
||||
printf ("\"%s\"%s", keyseqs[j], keyseqs[j + 1] ? ", " : ".\n");
|
||||
if (keyseqs[j])
|
||||
printf ("...\n");
|
||||
strvec_dispose (keyseqs);
|
||||
return EXECUTION_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
unbind_command (name)
|
||||
char *name;
|
||||
{
|
||||
rl_command_func_t *function;
|
||||
|
||||
function = rl_named_function (name);
|
||||
if (function == 0)
|
||||
{
|
||||
builtin_error (_("`%s': unknown function name"), name);
|
||||
return EXECUTION_FAILURE;
|
||||
}
|
||||
|
||||
rl_unbind_function_in_map (function, rl_get_keymap ());
|
||||
return EXECUTION_SUCCESS;
|
||||
}
|
||||
#endif /* READLINE */
|
||||
@@ -1,283 +0,0 @@
|
||||
This file is hash.def, from which is created hash.c.
|
||||
It implements the builtin "hash" in Bash.
|
||||
|
||||
Copyright (C) 1987-2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$PRODUCES hash.c
|
||||
|
||||
$BUILTIN hash
|
||||
$FUNCTION hash_builtin
|
||||
$SHORT_DOC hash [-lr] [-p pathname] [-dt] [name ...]
|
||||
Remember or display program locations.
|
||||
|
||||
Determine and remember the full pathname of each command NAME. If
|
||||
no arguments are given, information about remembered commands is displayed.
|
||||
|
||||
Options:
|
||||
-d forget the remembered location of each NAME
|
||||
-l display in a format that may be reused as input
|
||||
-p pathname use PATHNAME as the full pathname of NAME
|
||||
-r forget all remembered locations
|
||||
-t print the remembered location of each NAME, preceding
|
||||
each location with the corresponding NAME if multiple
|
||||
NAMEs are given
|
||||
Arguments:
|
||||
NAME Each NAME is searched for in $PATH and added to the list
|
||||
of remembered commands.
|
||||
|
||||
Exit Status:
|
||||
Returns success unless NAME is not found or an invalid option is given.
|
||||
$END
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../bashtypes.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "../bashansi.h"
|
||||
#include "../bashintl.h"
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../builtins.h"
|
||||
#include "../flags.h"
|
||||
#include "../findcmd.h"
|
||||
#include "../hashcmd.h"
|
||||
#include "common.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
extern int posixly_correct;
|
||||
extern int dot_found_in_search;
|
||||
extern char *this_command_name;
|
||||
|
||||
static int add_hashed_command __P((char *, int));
|
||||
static int print_hash_info __P((BUCKET_CONTENTS *));
|
||||
static int print_portable_hash_info __P((BUCKET_CONTENTS *));
|
||||
static int print_hashed_commands __P((int));
|
||||
static int list_hashed_filename_targets __P((WORD_LIST *, int));
|
||||
|
||||
/* Print statistics on the current state of hashed commands. If LIST is
|
||||
not empty, then rehash (or hash in the first place) the specified
|
||||
commands. */
|
||||
int
|
||||
hash_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int expunge_hash_table, list_targets, list_portably, delete, opt;
|
||||
char *w, *pathname;
|
||||
|
||||
if (hashing_enabled == 0)
|
||||
{
|
||||
builtin_error (_("hashing disabled"));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
expunge_hash_table = list_targets = list_portably = delete = 0;
|
||||
pathname = (char *)NULL;
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "dlp:rt")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'd':
|
||||
delete = 1;
|
||||
break;
|
||||
case 'l':
|
||||
list_portably = 1;
|
||||
break;
|
||||
case 'p':
|
||||
pathname = list_optarg;
|
||||
break;
|
||||
case 'r':
|
||||
expunge_hash_table = 1;
|
||||
break;
|
||||
case 't':
|
||||
list_targets = 1;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
/* hash -t requires at least one argument. */
|
||||
if (list == 0 && list_targets)
|
||||
{
|
||||
sh_needarg ("-t");
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
/* We want hash -r to be silent, but hash -- to print hashing info, so
|
||||
we test expunge_hash_table. */
|
||||
if (list == 0 && expunge_hash_table == 0)
|
||||
{
|
||||
opt = print_hashed_commands (list_portably);
|
||||
if (opt == 0 && posixly_correct == 0)
|
||||
printf (_("%s: hash table empty\n"), this_command_name);
|
||||
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
if (expunge_hash_table)
|
||||
phash_flush ();
|
||||
|
||||
/* If someone runs `hash -r -t xyz' he will be disappointed. */
|
||||
if (list_targets)
|
||||
return (list_hashed_filename_targets (list, list_portably));
|
||||
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
if (restricted && pathname && strchr (pathname, '/'))
|
||||
{
|
||||
sh_restricted (pathname);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (opt = EXECUTION_SUCCESS; list; list = list->next)
|
||||
{
|
||||
/* Add, remove or rehash the specified commands. */
|
||||
w = list->word->word;
|
||||
if (absolute_program (w))
|
||||
continue;
|
||||
else if (pathname)
|
||||
{
|
||||
if (is_directory (pathname))
|
||||
{
|
||||
#ifdef EISDIR
|
||||
builtin_error ("%s: %s", pathname, strerror (EISDIR));
|
||||
#else
|
||||
builtin_error (_("%s: is a directory"), pathname);
|
||||
#endif
|
||||
opt = EXECUTION_FAILURE;
|
||||
}
|
||||
else
|
||||
phash_insert (w, pathname, 0, 0);
|
||||
}
|
||||
else if (delete)
|
||||
{
|
||||
if (phash_remove (w))
|
||||
{
|
||||
sh_notfound (w);
|
||||
opt = EXECUTION_FAILURE;
|
||||
}
|
||||
}
|
||||
else if (add_hashed_command (w, 0))
|
||||
opt = EXECUTION_FAILURE;
|
||||
}
|
||||
|
||||
fflush (stdout);
|
||||
return (opt);
|
||||
}
|
||||
|
||||
static int
|
||||
add_hashed_command (w, quiet)
|
||||
char *w;
|
||||
int quiet;
|
||||
{
|
||||
int rv;
|
||||
char *full_path;
|
||||
|
||||
rv = 0;
|
||||
if (find_function (w) == 0 && find_shell_builtin (w) == 0)
|
||||
{
|
||||
phash_remove (w);
|
||||
full_path = find_user_command (w);
|
||||
if (full_path && executable_file (full_path))
|
||||
phash_insert (w, full_path, dot_found_in_search, 0);
|
||||
else
|
||||
{
|
||||
if (quiet == 0)
|
||||
sh_notfound (w);
|
||||
rv++;
|
||||
}
|
||||
FREE (full_path);
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/* Print information about current hashed info. */
|
||||
static int
|
||||
print_hash_info (item)
|
||||
BUCKET_CONTENTS *item;
|
||||
{
|
||||
printf ("%4d\t%s\n", item->times_found, pathdata(item)->path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
print_portable_hash_info (item)
|
||||
BUCKET_CONTENTS *item;
|
||||
{
|
||||
printf ("builtin hash -p %s %s\n", pathdata(item)->path, item->key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
print_hashed_commands (fmt)
|
||||
int fmt;
|
||||
{
|
||||
if (hashed_filenames == 0 || HASH_ENTRIES (hashed_filenames) == 0)
|
||||
return (0);
|
||||
|
||||
if (fmt == 0)
|
||||
printf (_("hits\tcommand\n"));
|
||||
hash_walk (hashed_filenames, fmt ? print_portable_hash_info : print_hash_info);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
list_hashed_filename_targets (list, fmt)
|
||||
WORD_LIST *list;
|
||||
int fmt;
|
||||
{
|
||||
int all_found, multiple;
|
||||
char *target;
|
||||
WORD_LIST *l;
|
||||
|
||||
all_found = 1;
|
||||
multiple = list->next != 0;
|
||||
|
||||
for (l = list; l; l = l->next)
|
||||
{
|
||||
target = phash_search (l->word->word);
|
||||
if (target == 0)
|
||||
{
|
||||
all_found = 0;
|
||||
sh_notfound (l->word->word);
|
||||
continue;
|
||||
}
|
||||
if (fmt)
|
||||
printf ("builtin hash -p %s %s\n", target, l->word->word);
|
||||
else
|
||||
{
|
||||
if (multiple)
|
||||
printf ("%s\t", l->word->word);
|
||||
printf ("%s\n", target);
|
||||
}
|
||||
free (target);
|
||||
}
|
||||
|
||||
return (all_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
||||
}
|
||||
@@ -1,517 +0,0 @@
|
||||
This file is help.def, from which is created help.c.
|
||||
It implements the builtin "help" in Bash.
|
||||
|
||||
Copyright (C) 1987-2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$PRODUCES help.c
|
||||
|
||||
$BUILTIN help
|
||||
$FUNCTION help_builtin
|
||||
$DEPENDS_ON HELP_BUILTIN
|
||||
$SHORT_DOC help [-dms] [pattern ...]
|
||||
Display information about builtin commands.
|
||||
|
||||
Displays brief summaries of builtin commands. If PATTERN is
|
||||
specified, gives detailed help on all commands matching PATTERN,
|
||||
otherwise the list of help topics is printed.
|
||||
|
||||
Options:
|
||||
-d output short description for each topic
|
||||
-m display usage in pseudo-manpage format
|
||||
-s output only a short usage synopsis for each topic matching
|
||||
PATTERN
|
||||
|
||||
Arguments:
|
||||
PATTERN Pattern specifiying a help topic
|
||||
|
||||
Exit Status:
|
||||
Returns success unless PATTERN is not found or an invalid option is given.
|
||||
$END
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (HELP_BUILTIN)
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <filecntl.h>
|
||||
|
||||
#include "../bashintl.h"
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../builtins.h"
|
||||
#include "../pathexp.h"
|
||||
#include "common.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
#include <glob/strmatch.h>
|
||||
#include <glob/glob.h>
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
extern const char * const bash_copyright;
|
||||
extern const char * const bash_license;
|
||||
|
||||
static void show_builtin_command_help __P((void));
|
||||
static int open_helpfile __P((char *));
|
||||
static void show_desc __P((char *, int));
|
||||
static void show_manpage __P((char *, int));
|
||||
static void show_longdoc __P((int));
|
||||
|
||||
/* Print out a list of the known functions in the shell, and what they do.
|
||||
If LIST is supplied, print out the list which matches for each pattern
|
||||
specified. */
|
||||
int
|
||||
help_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
register int i;
|
||||
char *pattern, *name;
|
||||
int plen, match_found, sflag, dflag, mflag, m, pass, this_found;
|
||||
|
||||
dflag = sflag = mflag = 0;
|
||||
reset_internal_getopt ();
|
||||
while ((i = internal_getopt (list, "dms")) != -1)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 'd':
|
||||
dflag = 1;
|
||||
break;
|
||||
case 'm':
|
||||
mflag = 1;
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
show_shell_version (0);
|
||||
show_builtin_command_help ();
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
/* We should consider making `help bash' do something. */
|
||||
|
||||
if (glob_pattern_p (list->word->word))
|
||||
{
|
||||
printf (ngettext ("Shell commands matching keyword `", "Shell commands matching keywords `", (list->next ? 2 : 1)));
|
||||
print_word_list (list, ", ");
|
||||
printf ("'\n\n");
|
||||
}
|
||||
|
||||
for (match_found = 0, pattern = ""; list; list = list->next)
|
||||
{
|
||||
pattern = list->word->word;
|
||||
plen = strlen (pattern);
|
||||
|
||||
for (pass = 1, this_found = 0; pass < 3; pass++)
|
||||
{
|
||||
for (i = 0; name = shell_builtins[i].name; i++)
|
||||
{
|
||||
QUIT;
|
||||
|
||||
/* First pass: look for exact string or pattern matches.
|
||||
Second pass: look for prefix matches like bash-4.2 */
|
||||
if (pass == 1)
|
||||
m = (strcmp (pattern, name) == 0) ||
|
||||
(strmatch (pattern, name, FNMATCH_EXTFLAG) != FNM_NOMATCH);
|
||||
else
|
||||
m = strncmp (pattern, name, plen) == 0;
|
||||
|
||||
if (m)
|
||||
{
|
||||
this_found = 1;
|
||||
match_found++;
|
||||
if (dflag)
|
||||
{
|
||||
show_desc (name, i);
|
||||
continue;
|
||||
}
|
||||
else if (mflag)
|
||||
{
|
||||
show_manpage (name, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf ("%s: %s\n", name, _(shell_builtins[i].short_doc));
|
||||
|
||||
if (sflag == 0)
|
||||
show_longdoc (i);
|
||||
}
|
||||
}
|
||||
if (pass == 1 && this_found == 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (match_found == 0)
|
||||
{
|
||||
builtin_error (_("no help topics match `%s'. Try `help help' or `man -k %s' or `info %s'."), pattern, pattern, pattern);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
fflush (stdout);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
open_helpfile (name)
|
||||
char *name;
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open (name, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
builtin_error (_("%s: cannot open: %s"), name, strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* By convention, enforced by mkbuiltins.c, if separate help files are being
|
||||
used, the long_doc array contains one string -- the full pathname of the
|
||||
help file for this builtin. */
|
||||
static void
|
||||
show_longdoc (i)
|
||||
int i;
|
||||
{
|
||||
register int j;
|
||||
char * const *doc;
|
||||
int fd;
|
||||
|
||||
doc = shell_builtins[i].long_doc;
|
||||
|
||||
if (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL)
|
||||
{
|
||||
fd = open_helpfile (doc[0]);
|
||||
if (fd < 0)
|
||||
return;
|
||||
zcatfd (fd, 1, doc[0]);
|
||||
close (fd);
|
||||
}
|
||||
else if (doc)
|
||||
for (j = 0; doc[j]; j++)
|
||||
printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j]));
|
||||
}
|
||||
|
||||
static void
|
||||
show_desc (name, i)
|
||||
char *name;
|
||||
int i;
|
||||
{
|
||||
register int j;
|
||||
char **doc, *line;
|
||||
int fd, usefile;
|
||||
|
||||
doc = (char **)shell_builtins[i].long_doc;
|
||||
|
||||
usefile = (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL);
|
||||
if (usefile)
|
||||
{
|
||||
fd = open_helpfile (doc[0]);
|
||||
if (fd < 0)
|
||||
return;
|
||||
zmapfd (fd, &line, doc[0]);
|
||||
close (fd);
|
||||
}
|
||||
else
|
||||
line = doc ? doc[0] : (char *)NULL;
|
||||
|
||||
printf ("%s - ", name);
|
||||
for (j = 0; line && line[j]; j++)
|
||||
{
|
||||
putchar (line[j]);
|
||||
if (line[j] == '\n')
|
||||
break;
|
||||
}
|
||||
|
||||
fflush (stdout);
|
||||
|
||||
if (usefile)
|
||||
free (line);
|
||||
}
|
||||
|
||||
/* Print builtin help in pseudo-manpage format. */
|
||||
static void
|
||||
show_manpage (name, i)
|
||||
char *name;
|
||||
int i;
|
||||
{
|
||||
register int j;
|
||||
char **doc, *line;
|
||||
int fd, usefile;
|
||||
|
||||
doc = (char **)shell_builtins[i].long_doc;
|
||||
|
||||
usefile = (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL);
|
||||
if (usefile)
|
||||
{
|
||||
fd = open_helpfile (doc[0]);
|
||||
if (fd < 0)
|
||||
return;
|
||||
zmapfd (fd, &line, doc[0]);
|
||||
close (fd);
|
||||
}
|
||||
else
|
||||
line = doc ? _(doc[0]) : (char *)NULL;
|
||||
|
||||
/* NAME */
|
||||
printf ("NAME\n");
|
||||
printf ("%*s%s - ", BASE_INDENT, " ", name);
|
||||
for (j = 0; line && line[j]; j++)
|
||||
{
|
||||
putchar (line[j]);
|
||||
if (line[j] == '\n')
|
||||
break;
|
||||
}
|
||||
printf ("\n");
|
||||
|
||||
/* SYNOPSIS */
|
||||
printf ("SYNOPSIS\n");
|
||||
printf ("%*s%s\n\n", BASE_INDENT, " ", _(shell_builtins[i].short_doc));
|
||||
|
||||
/* DESCRIPTION */
|
||||
printf ("DESCRIPTION\n");
|
||||
if (usefile == 0)
|
||||
{
|
||||
for (j = 0; doc[j]; j++)
|
||||
printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j]));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; line && line[j]; j++)
|
||||
{
|
||||
putchar (line[j]);
|
||||
if (line[j] == '\n')
|
||||
printf ("%*s", BASE_INDENT, " ");
|
||||
}
|
||||
}
|
||||
putchar ('\n');
|
||||
|
||||
/* SEE ALSO */
|
||||
printf ("SEE ALSO\n");
|
||||
printf ("%*sbash(1)\n\n", BASE_INDENT, " ");
|
||||
|
||||
/* IMPLEMENTATION */
|
||||
printf ("IMPLEMENTATION\n");
|
||||
printf ("%*s", BASE_INDENT, " ");
|
||||
show_shell_version (0);
|
||||
printf ("%*s", BASE_INDENT, " ");
|
||||
printf ("%s\n", _(bash_copyright));
|
||||
printf ("%*s", BASE_INDENT, " ");
|
||||
printf ("%s\n", _(bash_license));
|
||||
|
||||
fflush (stdout);
|
||||
if (usefile)
|
||||
free (line);
|
||||
}
|
||||
|
||||
static void
|
||||
dispcolumn (i, buf, bufsize, width, height)
|
||||
int i;
|
||||
char *buf;
|
||||
size_t bufsize;
|
||||
int width, height;
|
||||
{
|
||||
int j;
|
||||
int displen;
|
||||
char *helpdoc;
|
||||
|
||||
/* first column */
|
||||
helpdoc = _(shell_builtins[i].short_doc);
|
||||
|
||||
buf[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*';
|
||||
strncpy (buf + 1, helpdoc, width - 2);
|
||||
buf[width - 2] = '>'; /* indicate truncation */
|
||||
buf[width - 1] = '\0';
|
||||
printf ("%s", buf);
|
||||
if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
|
||||
{
|
||||
printf ("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
displen = strlen (buf);
|
||||
/* two spaces */
|
||||
for (j = displen; j < width; j++)
|
||||
putc (' ', stdout);
|
||||
|
||||
/* second column */
|
||||
helpdoc = _(shell_builtins[i+height].short_doc);
|
||||
|
||||
buf[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*';
|
||||
strncpy (buf + 1, helpdoc, width - 3);
|
||||
buf[width - 3] = '>'; /* indicate truncation */
|
||||
buf[width - 2] = '\0';
|
||||
|
||||
printf ("%s\n", buf);
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
static void
|
||||
wdispcolumn (i, buf, bufsize, width, height)
|
||||
int i;
|
||||
char *buf;
|
||||
size_t bufsize;
|
||||
int width, height;
|
||||
{
|
||||
int j;
|
||||
int displen;
|
||||
char *helpdoc;
|
||||
wchar_t *wcstr;
|
||||
size_t slen, n;
|
||||
int wclen;
|
||||
|
||||
/* first column */
|
||||
helpdoc = _(shell_builtins[i].short_doc);
|
||||
|
||||
wcstr = 0;
|
||||
slen = mbstowcs ((wchar_t *)0, helpdoc, 0);
|
||||
if (slen == -1)
|
||||
{
|
||||
dispcolumn (i, buf, bufsize, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
/* No bigger than the passed max width */
|
||||
if (slen >= width)
|
||||
slen = width - 2;
|
||||
wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (width + 2));
|
||||
n = mbstowcs (wcstr+1, helpdoc, slen + 1);
|
||||
wcstr[n+1] = L'\0';
|
||||
|
||||
/* Turn tabs and newlines into spaces for column display, since wcwidth
|
||||
returns -1 for them */
|
||||
for (j = 1; j < n; j++)
|
||||
if (wcstr[j] == L'\n' || wcstr[j] == L'\t')
|
||||
wcstr[j] = L' ';
|
||||
|
||||
displen = wcsnwidth (wcstr+1, slen, width - 2) + 1; /* +1 for ' ' or '*' */
|
||||
|
||||
wcstr[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? L' ' : L'*';
|
||||
|
||||
/* This assumes each wide char takes up one column position when displayed */
|
||||
wcstr[width - 2] = L'>'; /* indicate truncation */
|
||||
wcstr[width - 1] = L'\0';
|
||||
|
||||
printf ("%ls", wcstr);
|
||||
if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
|
||||
{
|
||||
printf ("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* at least one space */
|
||||
for (j = displen; j < width; j++)
|
||||
putc (' ', stdout);
|
||||
|
||||
/* second column */
|
||||
helpdoc = _(shell_builtins[i+height].short_doc);
|
||||
slen = mbstowcs ((wchar_t *)0, helpdoc, 0);
|
||||
if (slen == -1)
|
||||
{
|
||||
/* for now */
|
||||
printf ("%c%s\n", (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*', helpdoc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reuse wcstr since it is already width wide chars long */
|
||||
if (slen >= width)
|
||||
slen = width - 2;
|
||||
n = mbstowcs (wcstr+1, helpdoc, slen + 1);
|
||||
wcstr[n+1] = L'\0'; /* make sure null-terminated */
|
||||
|
||||
/* Turn tabs and newlines into spaces for column display */
|
||||
for (j = 1; j < n; j++)
|
||||
if (wcstr[j] == L'\n' || wcstr[j] == L'\t')
|
||||
wcstr[j] = L' ';
|
||||
|
||||
displen = wcsnwidth (wcstr+1, slen, width - 2);
|
||||
|
||||
wcstr[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? L' ' : L'*';
|
||||
|
||||
/* This assumes each wide char takes up one column position when displayed */
|
||||
wcstr[width - 3] = L'>'; /* indicate truncation */
|
||||
wcstr[width - 2] = L'\0';
|
||||
|
||||
printf ("%ls\n", wcstr);
|
||||
|
||||
free (wcstr);
|
||||
}
|
||||
#endif /* HANDLE_MULTIBYTE */
|
||||
|
||||
static void
|
||||
show_builtin_command_help ()
|
||||
{
|
||||
int i, j;
|
||||
int height, width;
|
||||
char *t, blurb[128];
|
||||
|
||||
printf (
|
||||
_("These shell commands are defined internally. Type `help' to see this list.\n\
|
||||
Type `help name' to find out more about the function `name'.\n\
|
||||
Use `info bash' to find out more about the shell in general.\n\
|
||||
Use `man -k' or `info' to find out more about commands not in this list.\n\
|
||||
\n\
|
||||
A star (*) next to a name means that the command is disabled.\n\
|
||||
\n"));
|
||||
|
||||
t = get_string_value ("COLUMNS");
|
||||
width = (t && *t) ? atoi (t) : 80;
|
||||
if (width <= 0)
|
||||
width = 80;
|
||||
|
||||
width /= 2;
|
||||
if (width > sizeof (blurb))
|
||||
width = sizeof (blurb);
|
||||
if (width <= 3)
|
||||
width = 40;
|
||||
height = (num_shell_builtins + 1) / 2; /* number of rows */
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
QUIT;
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1)
|
||||
wdispcolumn (i, blurb, sizeof (blurb), width, height);
|
||||
else
|
||||
#endif
|
||||
dispcolumn (i, blurb, sizeof (blurb), width, height);
|
||||
}
|
||||
}
|
||||
#endif /* HELP_BUILTIN */
|
||||
@@ -1,405 +0,0 @@
|
||||
This file is type.def, from which is created type.c.
|
||||
It implements the builtin "type" in Bash.
|
||||
|
||||
Copyright (C) 1987-2011 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$PRODUCES type.c
|
||||
|
||||
$BUILTIN type
|
||||
$FUNCTION type_builtin
|
||||
$SHORT_DOC type [-afptP] name [name ...]
|
||||
Display information about command type.
|
||||
|
||||
For each NAME, indicate how it would be interpreted if used as a
|
||||
command name.
|
||||
|
||||
Options:
|
||||
-a display all locations containing an executable named NAME;
|
||||
includes aliases, builtins, and functions, if and only if
|
||||
the `-p' option is not also used
|
||||
-f suppress shell function lookup
|
||||
-P force a PATH search for each NAME, even if it is an alias,
|
||||
builtin, or function, and returns the name of the disk file
|
||||
that would be executed
|
||||
-p returns either the name of the disk file that would be executed,
|
||||
or nothing if `type -t NAME' would not return `file'.
|
||||
-t output a single word which is one of `alias', `keyword',
|
||||
`function', `builtin', `file' or `', if NAME is an alias, shell
|
||||
reserved word, shell function, shell builtin, disk file, or not
|
||||
found, respectively
|
||||
|
||||
Arguments:
|
||||
NAME Command name to be interpreted.
|
||||
|
||||
Exit Status:
|
||||
Returns success if all of the NAMEs are found; fails if any are not found.
|
||||
$END
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "../bashtypes.h"
|
||||
#include "posixstat.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../bashansi.h"
|
||||
#include "../bashintl.h"
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../findcmd.h"
|
||||
#include "../hashcmd.h"
|
||||
|
||||
#if defined (ALIAS)
|
||||
#include "../alias.h"
|
||||
#endif /* ALIAS */
|
||||
|
||||
#include "common.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
extern int find_reserved_word __P((char *));
|
||||
|
||||
extern char *this_command_name;
|
||||
extern int expand_aliases, posixly_correct;
|
||||
|
||||
/* For each word in LIST, find out what the shell is going to do with
|
||||
it as a simple command. i.e., which file would this shell use to
|
||||
execve, or if it is a builtin command, or an alias. Possible flag
|
||||
arguments:
|
||||
-t Returns the "type" of the object, one of
|
||||
`alias', `keyword', `function', `builtin',
|
||||
or `file'.
|
||||
|
||||
-p Returns the pathname of the file if -type is
|
||||
a file.
|
||||
|
||||
-a Returns all occurrences of words, whether they
|
||||
be a filename in the path, alias, function,
|
||||
or builtin.
|
||||
|
||||
-f Suppress shell function lookup, like `command'.
|
||||
|
||||
-P Force a path search even in the presence of other
|
||||
definitions.
|
||||
|
||||
Order of evaluation:
|
||||
alias
|
||||
keyword
|
||||
function
|
||||
builtin
|
||||
file
|
||||
*/
|
||||
|
||||
int
|
||||
type_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int dflags, any_failed, opt;
|
||||
WORD_LIST *this;
|
||||
|
||||
if (list == 0)
|
||||
return (EXECUTION_SUCCESS);
|
||||
|
||||
dflags = CDESC_SHORTDESC; /* default */
|
||||
any_failed = 0;
|
||||
|
||||
/* Handle the obsolescent `-type', `-path', and `-all' by prescanning
|
||||
the arguments and converting those options to the form that
|
||||
internal_getopt recognizes. Converts `--type', `--path', and `--all'
|
||||
also. THIS SHOULD REALLY GO AWAY. */
|
||||
for (this = list; this && this->word->word[0] == '-'; this = this->next)
|
||||
{
|
||||
char *flag = &(this->word->word[1]);
|
||||
|
||||
if (STREQ (flag, "type") || STREQ (flag, "-type"))
|
||||
{
|
||||
this->word->word[1] = 't';
|
||||
this->word->word[2] = '\0';
|
||||
}
|
||||
else if (STREQ (flag, "path") || STREQ (flag, "-path"))
|
||||
{
|
||||
this->word->word[1] = 'p';
|
||||
this->word->word[2] = '\0';
|
||||
}
|
||||
else if (STREQ (flag, "all") || STREQ (flag, "-all"))
|
||||
{
|
||||
this->word->word[1] = 'a';
|
||||
this->word->word[2] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "afptP")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'a':
|
||||
dflags |= CDESC_ALL;
|
||||
break;
|
||||
case 'f':
|
||||
dflags |= CDESC_NOFUNCS;
|
||||
break;
|
||||
case 'p':
|
||||
dflags |= CDESC_PATH_ONLY;
|
||||
dflags &= ~(CDESC_TYPE|CDESC_SHORTDESC);
|
||||
break;
|
||||
case 't':
|
||||
dflags |= CDESC_TYPE;
|
||||
dflags &= ~(CDESC_PATH_ONLY|CDESC_SHORTDESC);
|
||||
break;
|
||||
case 'P': /* shorthand for type -ap */
|
||||
dflags |= (CDESC_PATH_ONLY|CDESC_FORCE_PATH);
|
||||
dflags &= ~(CDESC_TYPE|CDESC_SHORTDESC);
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
while (list)
|
||||
{
|
||||
int found;
|
||||
|
||||
found = describe_command (list->word->word, dflags);
|
||||
|
||||
if (!found && (dflags & (CDESC_PATH_ONLY|CDESC_TYPE)) == 0)
|
||||
sh_notfound (list->word->word);
|
||||
|
||||
any_failed += found == 0;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
opt = (any_failed == 0) ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
|
||||
return (sh_chkwrite (opt));
|
||||
}
|
||||
|
||||
/*
|
||||
* Describe COMMAND as required by the type and command builtins.
|
||||
*
|
||||
* Behavior is controlled by DFLAGS. Flag values are
|
||||
* CDESC_ALL print all descriptions of a command
|
||||
* CDESC_SHORTDESC print the description for type and command -V
|
||||
* CDESC_REUSABLE print in a format that may be reused as input
|
||||
* CDESC_TYPE print the type for type -t
|
||||
* CDESC_PATH_ONLY print the path for type -p
|
||||
* CDESC_FORCE_PATH force a path search for type -P
|
||||
* CDESC_NOFUNCS skip function lookup for type -f
|
||||
* CDESC_ABSPATH convert to absolute path, no ./ prefix
|
||||
*
|
||||
* CDESC_ALL says whether or not to look for all occurrences of COMMAND, or
|
||||
* return after finding it once.
|
||||
*/
|
||||
int
|
||||
describe_command (command, dflags)
|
||||
char *command;
|
||||
int dflags;
|
||||
{
|
||||
int found, i, found_file, f, all;
|
||||
char *full_path, *x;
|
||||
SHELL_VAR *func;
|
||||
#if defined (ALIAS)
|
||||
alias_t *alias;
|
||||
#endif
|
||||
|
||||
all = (dflags & CDESC_ALL) != 0;
|
||||
found = found_file = 0;
|
||||
full_path = (char *)NULL;
|
||||
|
||||
#if defined (ALIAS)
|
||||
/* Command is an alias? */
|
||||
if (((dflags & CDESC_FORCE_PATH) == 0) && expand_aliases && (alias = find_alias (command)))
|
||||
{
|
||||
if (dflags & CDESC_TYPE)
|
||||
puts ("alias");
|
||||
else if (dflags & CDESC_SHORTDESC)
|
||||
printf (_("%s is aliased to `%s'\n"), command, alias->value);
|
||||
else if (dflags & CDESC_REUSABLE)
|
||||
{
|
||||
x = sh_single_quote (alias->value);
|
||||
printf ("alias %s=%s\n", command, x);
|
||||
free (x);
|
||||
}
|
||||
|
||||
found = 1;
|
||||
|
||||
if (all == 0)
|
||||
return (1);
|
||||
}
|
||||
#endif /* ALIAS */
|
||||
|
||||
/* Command is a shell reserved word? */
|
||||
if (((dflags & CDESC_FORCE_PATH) == 0) && (i = find_reserved_word (command)) >= 0)
|
||||
{
|
||||
if (dflags & CDESC_TYPE)
|
||||
puts ("keyword");
|
||||
else if (dflags & CDESC_SHORTDESC)
|
||||
printf (_("%s is a shell keyword\n"), command);
|
||||
else if (dflags & CDESC_REUSABLE)
|
||||
printf ("%s\n", command);
|
||||
|
||||
found = 1;
|
||||
|
||||
if (all == 0)
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Command is a function? */
|
||||
if (((dflags & (CDESC_FORCE_PATH|CDESC_NOFUNCS)) == 0) && (func = find_function (command)))
|
||||
{
|
||||
if (dflags & CDESC_TYPE)
|
||||
puts ("function");
|
||||
else if (dflags & CDESC_SHORTDESC)
|
||||
{
|
||||
char *result;
|
||||
|
||||
printf (_("%s is a function\n"), command);
|
||||
|
||||
/* We're blowing away THE_PRINTED_COMMAND here... */
|
||||
|
||||
result = named_function_string (command, function_cell (func), FUNC_MULTILINE|FUNC_EXTERNAL);
|
||||
printf ("%s\n", result);
|
||||
}
|
||||
else if (dflags & CDESC_REUSABLE)
|
||||
printf ("%s\n", command);
|
||||
|
||||
found = 1;
|
||||
|
||||
if (all == 0)
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Command is a builtin? */
|
||||
if (((dflags & CDESC_FORCE_PATH) == 0) && find_shell_builtin (command))
|
||||
{
|
||||
if (dflags & CDESC_TYPE)
|
||||
puts ("builtin");
|
||||
else if (dflags & CDESC_SHORTDESC)
|
||||
printf (_("%s is a shell builtin\n"), command);
|
||||
else if (dflags & CDESC_REUSABLE)
|
||||
printf ("%s\n", command);
|
||||
|
||||
found = 1;
|
||||
|
||||
if (all == 0)
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Command is a disk file? */
|
||||
/* If the command name given is already an absolute command, just
|
||||
check to see if it is executable. */
|
||||
if (absolute_program (command))
|
||||
{
|
||||
f = file_status (command);
|
||||
if (f & FS_EXECABLE)
|
||||
{
|
||||
if (dflags & CDESC_TYPE)
|
||||
puts ("file");
|
||||
else if (dflags & CDESC_SHORTDESC)
|
||||
printf (_("%s is %s\n"), command, command);
|
||||
else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
|
||||
printf ("%s\n", command);
|
||||
|
||||
/* There's no use looking in the hash table or in $PATH,
|
||||
because they're not consulted when an absolute program
|
||||
name is supplied. */
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the user isn't doing "-a", then we might care about
|
||||
whether the file is present in our hash table. */
|
||||
if (all == 0 || (dflags & CDESC_FORCE_PATH))
|
||||
{
|
||||
if (full_path = phash_search (command))
|
||||
{
|
||||
if (dflags & CDESC_TYPE)
|
||||
puts ("file");
|
||||
else if (dflags & CDESC_SHORTDESC)
|
||||
printf (_("%s is hashed (%s)\n"), command, full_path);
|
||||
else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
|
||||
printf ("%s\n", full_path);
|
||||
|
||||
free (full_path);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now search through $PATH. */
|
||||
while (1)
|
||||
{
|
||||
if (all == 0)
|
||||
full_path = find_user_command (command);
|
||||
else
|
||||
full_path =
|
||||
user_command_matches (command, FS_EXEC_ONLY, found_file);
|
||||
/* XXX - should that be FS_EXEC_PREFERRED? */
|
||||
|
||||
if (full_path == 0)
|
||||
break;
|
||||
|
||||
/* If we found the command as itself by looking through $PATH, it
|
||||
probably doesn't exist. Check whether or not the command is an
|
||||
executable file. If it's not, don't report a match. This is
|
||||
the default posix mode behavior */
|
||||
if (STREQ (full_path, command) || posixly_correct)
|
||||
{
|
||||
f = file_status (full_path);
|
||||
if ((f & FS_EXECABLE) == 0)
|
||||
{
|
||||
free (full_path);
|
||||
full_path = (char *)NULL;
|
||||
if (all == 0)
|
||||
break;
|
||||
}
|
||||
else if (ABSPATH (full_path))
|
||||
; /* placeholder; don't need to do anything yet */
|
||||
else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY|CDESC_SHORTDESC))
|
||||
{
|
||||
f = MP_DOCWD | ((dflags & CDESC_ABSPATH) ? MP_RMDOT : 0);
|
||||
x = sh_makepath ((char *)NULL, full_path, f);
|
||||
free (full_path);
|
||||
full_path = x;
|
||||
}
|
||||
}
|
||||
/* If we require a full path and don't have one, make one */
|
||||
else if ((dflags & CDESC_ABSPATH) && ABSPATH (full_path) == 0)
|
||||
full_path = sh_makepath ((char *)NULL, full_path, MP_DOCWD|MP_RMDOT);
|
||||
|
||||
found_file++;
|
||||
found = 1;
|
||||
|
||||
if (dflags & CDESC_TYPE)
|
||||
puts ("file");
|
||||
else if (dflags & CDESC_SHORTDESC)
|
||||
printf (_("%s is %s\n"), command, full_path);
|
||||
else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
|
||||
printf ("%s\n", full_path);
|
||||
|
||||
free (full_path);
|
||||
full_path = (char *)NULL;
|
||||
|
||||
if (all == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return (found);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
# This file is a shell script that caches the results of configure
|
||||
# tests for CYGWIN32 so they don't need to be done when cross-compiling.
|
||||
|
||||
# AC_FUNC_GETPGRP should also define GETPGRP_VOID
|
||||
ac_cv_func_getpgrp_void=${ac_cv_func_getpgrp_void='yes'}
|
||||
# AC_FUNC_SETVBUF_REVERSED should not define anything else
|
||||
ac_cv_func_setvbuf_reversed=${ac_cv_func_setvbuf_reversed='no'}
|
||||
# on CYGWIN32, system calls do not restart
|
||||
ac_cv_sys_restartable_syscalls=${ac_cv_sys_restartable_syscalls='no'}
|
||||
bash_cv_sys_restartable_syscalls=${bash_cv_sys_restartable_syscalls='no'}
|
||||
|
||||
# these may be necessary, but they are currently commented out
|
||||
#ac_cv_c_bigendian=${ac_cv_c_bigendian='no'}
|
||||
ac_cv_sizeof_char_p=${ac_cv_sizeof_char_p='4'}
|
||||
ac_cv_sizeof_int=${ac_cv_sizeof_int='4'}
|
||||
ac_cv_sizeof_long=${ac_cv_sizeof_long='4'}
|
||||
ac_cv_sizeof_double=${ac_cv_sizeof_double='8'}
|
||||
|
||||
bash_cv_dup2_broken=${bash_cv_dup2_broken='no'}
|
||||
bash_cv_pgrp_pipe=${bash_cv_pgrp_pipe='no'}
|
||||
bash_cv_type_rlimit=${bash_cv_type_rlimit='long'}
|
||||
bash_cv_decl_under_sys_siglist=${bash_cv_decl_under_sys_siglist='no'}
|
||||
bash_cv_under_sys_siglist=${bash_cv_under_sys_siglist='no'}
|
||||
bash_cv_sys_siglist=${bash_cv_sys_siglist='no'}
|
||||
bash_cv_opendir_not_robust=${bash_cv_opendir_not_robust='no'}
|
||||
bash_cv_getenv_redef=${bash_cv_getenv_redef='yes'}
|
||||
bash_cv_printf_declared=${bash_cv_printf_declared='yes'}
|
||||
bash_cv_ulimit_maxfds=${bash_cv_ulimit_maxfds='no'}
|
||||
bash_cv_getcwd_calls_popen=${bash_cv_getcwd_calls_popen='no'}
|
||||
bash_cv_must_reinstall_sighandlers=${bash_cv_must_reinstall_sighandlers='no'}
|
||||
bash_cv_job_control_missing=${bash_cv_job_control_missing='present'}
|
||||
bash_cv_sys_named_pipes=${bash_cv_sys_named_pipes='missing'}
|
||||
bash_cv_func_sigsetjmp=${bash_cv_func_sigsetjmp='missing'}
|
||||
bash_cv_mail_dir=${bash_cv_mail_dir='unknown'}
|
||||
bash_cv_func_strcoll_broken=${bash_cv_func_strcoll_broken='no'}
|
||||
|
||||
bash_cv_type_int32_t=${bash_cv_type_int32_t='int'}
|
||||
bash_cv_type_u_int32_t=${bash_cv_type_u_int32_t='int'}
|
||||
|
||||
ac_cv_type_bits64_t=${ac_cv_type_bits64_t='no'}
|
||||
|
||||
# end of cross-build/cygwin32.cache
|
||||
@@ -1,61 +0,0 @@
|
||||
*** ../bash-4.3-patched/lib/readline/display.c 2014-04-08 18:19:36.000000000 -0400
|
||||
--- lib/readline/display.c 2014-04-20 18:32:52.000000000 -0400
|
||||
***************
|
||||
*** 1036,1040 ****
|
||||
_rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))
|
||||
_rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
|
||||
!
|
||||
/* If this is the line with the prompt, we might need to
|
||||
compensate for invisible characters in the new line. Do
|
||||
--- 1036,1040 ----
|
||||
_rl_last_c_pos > (prompt_last_invisible - _rl_screenwidth - prompt_invis_chars_first_line))
|
||||
_rl_last_c_pos -= (wrap_offset-prompt_invis_chars_first_line);
|
||||
!
|
||||
/* If this is the line with the prompt, we might need to
|
||||
compensate for invisible characters in the new line. Do
|
||||
***************
|
||||
*** 1638,1642 ****
|
||||
the spot of first difference is before the end of the invisible chars,
|
||||
lendiff needs to be adjusted. */
|
||||
! if (current_line == 0 && !_rl_horizontal_scroll_mode &&
|
||||
current_invis_chars != visible_wrap_offset)
|
||||
{
|
||||
--- 1638,1642 ----
|
||||
the spot of first difference is before the end of the invisible chars,
|
||||
lendiff needs to be adjusted. */
|
||||
! if (current_line == 0 && /* !_rl_horizontal_scroll_mode && */
|
||||
current_invis_chars != visible_wrap_offset)
|
||||
{
|
||||
***************
|
||||
*** 1826,1831 ****
|
||||
_rl_last_c_pos += bytes_to_insert;
|
||||
|
||||
if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
|
||||
! goto clear_rest_of_line;
|
||||
}
|
||||
}
|
||||
--- 1826,1836 ----
|
||||
_rl_last_c_pos += bytes_to_insert;
|
||||
|
||||
+ /* XXX - we only want to do this if we are at the end of the line
|
||||
+ so we move there with _rl_move_cursor_relative */
|
||||
if (_rl_horizontal_scroll_mode && ((oe-old) > (ne-new)))
|
||||
! {
|
||||
! _rl_move_cursor_relative (ne-new, new);
|
||||
! goto clear_rest_of_line;
|
||||
! }
|
||||
}
|
||||
}
|
||||
***************
|
||||
*** 2695,2698 ****
|
||||
--- 2700,2709 ----
|
||||
}
|
||||
|
||||
+ void
|
||||
+ _rl_ttyflush ()
|
||||
+ {
|
||||
+ fflush (rl_outstream);
|
||||
+ }
|
||||
+
|
||||
/* return the `current display line' of the cursor -- the number of lines to
|
||||
move up to get to the first screen line of the current readline line. */
|
||||
-1745
File diff suppressed because it is too large
Load Diff
@@ -1,238 +0,0 @@
|
||||
#
|
||||
# Simple makefile for the sample loadable builtins
|
||||
#
|
||||
# Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
# Include some boilerplate Gnu makefile definitions.
|
||||
prefix = @prefix@
|
||||
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
includedir = @includedir@
|
||||
|
||||
topdir = @top_srcdir@
|
||||
BUILD_DIR = @BUILD_DIR@
|
||||
srcdir = @srcdir@
|
||||
VPATH = .:@srcdir@
|
||||
|
||||
@SET_MAKE@
|
||||
CC = @CC@
|
||||
RM = rm -f
|
||||
|
||||
SHELL = @MAKE_SHELL@
|
||||
|
||||
host_os = @host_os@
|
||||
host_cpu = @host_cpu@
|
||||
host_vendor = @host_vendor@
|
||||
|
||||
CFLAGS = @CFLAGS@
|
||||
LOCAL_CFLAGS = @LOCAL_CFLAGS@
|
||||
DEFS = @DEFS@
|
||||
LOCAL_DEFS = @LOCAL_DEFS@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
|
||||
BASHINCDIR = ${topdir}/include
|
||||
|
||||
LIBBUILD = ${BUILD_DIR}/lib
|
||||
|
||||
INTL_LIBSRC = ${topdir}/lib/intl
|
||||
INTL_BUILDDIR = ${LIBBUILD}/intl
|
||||
INTL_INC = @INTL_INC@
|
||||
LIBINTL_H = @LIBINTL_H@
|
||||
|
||||
CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CFLAGS)
|
||||
|
||||
#
|
||||
# These values are generated for configure by ${topdir}/support/shobj-conf.
|
||||
# If your system is not supported by that script, but includes facilities for
|
||||
# dynamic loading of shared objects, please update the script and send the
|
||||
# changes to bash-maintainers@gnu.org.
|
||||
#
|
||||
SHOBJ_CC = @SHOBJ_CC@
|
||||
SHOBJ_CFLAGS = @SHOBJ_CFLAGS@
|
||||
SHOBJ_LD = @SHOBJ_LD@
|
||||
SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@
|
||||
SHOBJ_XLDFLAGS = @SHOBJ_XLDFLAGS@
|
||||
SHOBJ_LIBS = @SHOBJ_LIBS@
|
||||
SHOBJ_STATUS = @SHOBJ_STATUS@
|
||||
|
||||
INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins \
|
||||
-I$(BASHINCDIR) -I$(BUILD_DIR) -I$(LIBBUILD) \
|
||||
-I$(BUILD_DIR)/builtins $(INTL_INC)
|
||||
|
||||
.c.o:
|
||||
$(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CCFLAGS) $(INC) -c -o $@ $<
|
||||
|
||||
|
||||
ALLPROG = print truefalse sleep pushd finfo logname basename dirname \
|
||||
tty pathchk tee head mkdir rmdir printenv id whoami \
|
||||
uname sync push ln unlink cut realpath getconf strftime
|
||||
OTHERPROG = necho hello cat
|
||||
|
||||
all: $(SHOBJ_STATUS)
|
||||
|
||||
supported: $(ALLPROG)
|
||||
others: $(OTHERPROG)
|
||||
|
||||
unsupported:
|
||||
@echo "Your system (${host_os}) is not supported by the"
|
||||
@echo "${topdir}/support/shobj-conf script."
|
||||
@echo "If your operating system provides facilities for dynamic"
|
||||
@echo "loading of shared objects using the dlopen(3) interface,"
|
||||
@echo "please update the script and re-run configure.
|
||||
@echo "Please send the changes you made to bash-maintainers@gnu.org"
|
||||
@echo "for inclusion in future bash releases."
|
||||
|
||||
everything: supported others
|
||||
|
||||
print: print.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ print.o $(SHOBJ_LIBS)
|
||||
|
||||
necho: necho.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ necho.o $(SHOBJ_LIBS)
|
||||
|
||||
getconf: getconf.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ getconf.o $(SHOBJ_LIBS)
|
||||
|
||||
hello: hello.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ hello.o $(SHOBJ_LIBS)
|
||||
|
||||
truefalse: truefalse.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ truefalse.o $(SHOBJ_LIBS)
|
||||
|
||||
sleep: sleep.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sleep.o $(SHOBJ_LIBS)
|
||||
|
||||
finfo: finfo.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ finfo.o $(SHOBJ_LIBS)
|
||||
|
||||
cat: cat.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cat.o $(SHOBJ_LIBS)
|
||||
|
||||
logname: logname.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ logname.o $(SHOBJ_LIBS)
|
||||
|
||||
basename: basename.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ basename.o $(SHOBJ_LIBS)
|
||||
|
||||
dirname: dirname.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ dirname.o $(SHOBJ_LIBS)
|
||||
|
||||
tty: tty.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tty.o $(SHOBJ_LIBS)
|
||||
|
||||
pathchk: pathchk.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pathchk.o $(SHOBJ_LIBS)
|
||||
|
||||
tee: tee.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tee.o $(SHOBJ_LIBS)
|
||||
|
||||
mkdir: mkdir.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ mkdir.o $(SHOBJ_LIBS)
|
||||
|
||||
rmdir: rmdir.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ rmdir.o $(SHOBJ_LIBS)
|
||||
|
||||
head: head.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ head.o $(SHOBJ_LIBS)
|
||||
|
||||
printenv: printenv.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ printenv.o $(SHOBJ_LIBS)
|
||||
|
||||
id: id.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ id.o $(SHOBJ_LIBS)
|
||||
|
||||
whoami: whoami.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ whoami.o $(SHOBJ_LIBS)
|
||||
|
||||
uname: uname.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ uname.o $(SHOBJ_LIBS)
|
||||
|
||||
sync: sync.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sync.o $(SHOBJ_LIBS)
|
||||
|
||||
push: push.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ push.o $(SHOBJ_LIBS)
|
||||
|
||||
ln: ln.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ ln.o $(SHOBJ_LIBS)
|
||||
|
||||
unlink: unlink.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ unlink.o $(SHOBJ_LIBS)
|
||||
|
||||
cut: cut.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cut.o $(SHOBJ_LIBS)
|
||||
|
||||
realpath: realpath.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ realpath.o $(SHOBJ_LIBS)
|
||||
|
||||
strftime: strftime.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ strftime.o $(SHOBJ_LIBS)
|
||||
|
||||
# pushd is a special case. We use the same source that the builtin version
|
||||
# uses, with special compilation options.
|
||||
#
|
||||
pushd.c: ${topdir}/builtins/pushd.def
|
||||
$(RM) $@
|
||||
${BUILD_DIR}/builtins/mkbuiltins -D ${topdir}/builtins ${topdir}/builtins/pushd.def
|
||||
|
||||
pushd.o: pushd.c
|
||||
$(RM) $@
|
||||
$(SHOBJ_CC) -DHAVE_CONFIG_H -DPUSHD_AND_POPD -DLOADABLE_BUILTIN $(SHOBJ_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(INC) -c -o $@ $<
|
||||
|
||||
pushd: pushd.o
|
||||
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pushd.o $(SHOBJ_LIBS)
|
||||
|
||||
clean:
|
||||
$(RM) $(ALLPROG) $(OTHERPROG) *.o
|
||||
-( cd perl && ${MAKE} ${MFLAGS} $@ )
|
||||
|
||||
mostlyclean: clean
|
||||
-( cd perl && ${MAKE} ${MFLAGS} $@ )
|
||||
|
||||
distclean maintainer-clean: clean
|
||||
$(RM) Makefile pushd.c
|
||||
-( cd perl && ${MAKE} ${MFLAGS} $@ )
|
||||
|
||||
print.o: print.c
|
||||
truefalse.o: truefalse.c
|
||||
sleep.o: sleep.c
|
||||
finfo.o: finfo.c
|
||||
logname.o: logname.c
|
||||
basename.o: basename.c
|
||||
dirname.o: dirname.c
|
||||
tty.o: tty.c
|
||||
pathchk.o: pathchk.c
|
||||
tee.o: tee.c
|
||||
head.o: head.c
|
||||
rmdir.o: rmdir.c
|
||||
necho.o: necho.c
|
||||
getconf.o: getconf.c
|
||||
hello.o: hello.c
|
||||
cat.o: cat.c
|
||||
printenv.o: printenv.c
|
||||
id.o: id.c
|
||||
whoami.o: whoami.c
|
||||
uname.o: uname.c
|
||||
sync.o: sync.c
|
||||
push.o: push.c
|
||||
mkdir.o: mkdir.c
|
||||
realpath.o: realpath.c
|
||||
strftime.o: strftime.c
|
||||
-5467
File diff suppressed because it is too large
Load Diff
-1381
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,424 +0,0 @@
|
||||
/* localealias.c - Handle aliases for locale names. */
|
||||
|
||||
/* Copyright (C) 1995-1999, 2000-2001, 2003, 2005-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash.
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
/* Tell glibc's <string.h> to provide a prototype for mempcpy().
|
||||
This must come before <config.h> because <config.h> may include
|
||||
<features.h>, and once <features.h> has been included, it's too late. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#if defined _LIBC || defined HAVE___FSETLOCKING
|
||||
# include <stdio_ext.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
# undef alloca
|
||||
# define alloca __builtin_alloca
|
||||
# define HAVE_ALLOCA 1
|
||||
#else
|
||||
# ifdef _MSC_VER
|
||||
# include <malloc.h>
|
||||
# define alloca _alloca
|
||||
# else
|
||||
# if defined HAVE_ALLOCA_H || defined _LIBC
|
||||
# include <alloca.h>
|
||||
# else
|
||||
# ifdef _AIX
|
||||
#pragma alloca
|
||||
# else
|
||||
# ifndef alloca
|
||||
char *alloca ();
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gettextP.h"
|
||||
|
||||
#if ENABLE_RELOCATABLE
|
||||
# include "relocatable.h"
|
||||
#else
|
||||
# define relocate(pathname) (pathname)
|
||||
#endif
|
||||
|
||||
/* @@ end of prolog @@ */
|
||||
|
||||
#ifdef _LIBC
|
||||
/* Rename the non ANSI C functions. This is required by the standard
|
||||
because some ANSI C functions will require linking with this object
|
||||
file and the name space must not be polluted. */
|
||||
# define strcasecmp __strcasecmp
|
||||
|
||||
# ifndef mempcpy
|
||||
# define mempcpy __mempcpy
|
||||
# endif
|
||||
# define HAVE_MEMPCPY 1
|
||||
# define HAVE___FSETLOCKING 1
|
||||
|
||||
/* We need locking here since we can be called from different places. */
|
||||
# include <bits/libc-lock.h>
|
||||
|
||||
__libc_lock_define_initialized (static, lock);
|
||||
#endif
|
||||
|
||||
#ifndef internal_function
|
||||
# define internal_function
|
||||
#endif
|
||||
|
||||
/* Some optimizations for glibc. */
|
||||
#ifdef _LIBC
|
||||
# define FEOF(fp) feof_unlocked (fp)
|
||||
# define FGETS(buf, n, fp) fgets_unlocked (buf, n, fp)
|
||||
#else
|
||||
# define FEOF(fp) feof (fp)
|
||||
# define FGETS(buf, n, fp) fgets (buf, n, fp)
|
||||
#endif
|
||||
|
||||
/* For those losing systems which don't have `alloca' we have to add
|
||||
some additional code emulating it. */
|
||||
#ifdef HAVE_ALLOCA
|
||||
# define freea(p) /* nothing */
|
||||
#else
|
||||
# define alloca(n) malloc (n)
|
||||
# define freea(p) free (p)
|
||||
#endif
|
||||
|
||||
#if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED
|
||||
# undef fgets
|
||||
# define fgets(buf, len, s) fgets_unlocked (buf, len, s)
|
||||
#endif
|
||||
#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED
|
||||
# undef feof
|
||||
# define feof(s) feof_unlocked (s)
|
||||
#endif
|
||||
|
||||
|
||||
struct alias_map
|
||||
{
|
||||
const char *alias;
|
||||
const char *value;
|
||||
};
|
||||
|
||||
|
||||
#ifndef _LIBC
|
||||
# define libc_freeres_ptr(decl) decl
|
||||
#endif
|
||||
|
||||
libc_freeres_ptr (static char *string_space);
|
||||
static size_t string_space_act;
|
||||
static size_t string_space_max;
|
||||
libc_freeres_ptr (static struct alias_map *map);
|
||||
static size_t nmap;
|
||||
static size_t maxmap;
|
||||
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
static size_t read_alias_file PARAMS ((const char *fname, int fname_len))
|
||||
internal_function;
|
||||
static int extend_alias_table PARAMS ((void));
|
||||
static int alias_compare PARAMS ((const struct alias_map *map1,
|
||||
const struct alias_map *map2));
|
||||
|
||||
|
||||
const char *
|
||||
_nl_expand_alias (name)
|
||||
const char *name;
|
||||
{
|
||||
static const char *locale_alias_path;
|
||||
struct alias_map *retval;
|
||||
const char *result = NULL;
|
||||
size_t added;
|
||||
|
||||
#ifdef _LIBC
|
||||
__libc_lock_lock (lock);
|
||||
#endif
|
||||
|
||||
if (locale_alias_path == NULL)
|
||||
locale_alias_path = LOCALE_ALIAS_PATH;
|
||||
|
||||
do
|
||||
{
|
||||
struct alias_map item;
|
||||
|
||||
item.alias = name;
|
||||
|
||||
if (nmap > 0)
|
||||
retval = (struct alias_map *) bsearch (&item, map, nmap,
|
||||
sizeof (struct alias_map),
|
||||
(int (*) PARAMS ((const void *,
|
||||
const void *))
|
||||
) alias_compare);
|
||||
else
|
||||
retval = NULL;
|
||||
|
||||
/* We really found an alias. Return the value. */
|
||||
if (retval != NULL)
|
||||
{
|
||||
result = retval->value;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Perhaps we can find another alias file. */
|
||||
added = 0;
|
||||
while (added == 0 && locale_alias_path[0] != '\0')
|
||||
{
|
||||
const char *start;
|
||||
|
||||
while (locale_alias_path[0] == PATH_SEPARATOR)
|
||||
++locale_alias_path;
|
||||
start = locale_alias_path;
|
||||
|
||||
while (locale_alias_path[0] != '\0'
|
||||
&& locale_alias_path[0] != PATH_SEPARATOR)
|
||||
++locale_alias_path;
|
||||
|
||||
if (start < locale_alias_path)
|
||||
added = read_alias_file (start, locale_alias_path - start);
|
||||
}
|
||||
}
|
||||
while (added != 0);
|
||||
|
||||
#ifdef _LIBC
|
||||
__libc_lock_unlock (lock);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
internal_function
|
||||
read_alias_file (fname, fname_len)
|
||||
const char *fname;
|
||||
int fname_len;
|
||||
{
|
||||
FILE *fp;
|
||||
char *full_fname;
|
||||
size_t added;
|
||||
static const char aliasfile[] = "/locale.alias";
|
||||
|
||||
full_fname = (char *) alloca (fname_len + sizeof aliasfile);
|
||||
#ifdef HAVE_MEMPCPY
|
||||
mempcpy (mempcpy (full_fname, fname, fname_len),
|
||||
aliasfile, sizeof aliasfile);
|
||||
#else
|
||||
memcpy (full_fname, fname, fname_len);
|
||||
memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
|
||||
#endif
|
||||
|
||||
fp = fopen (relocate (full_fname), "r");
|
||||
freea (full_fname);
|
||||
if (fp == NULL)
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE___FSETLOCKING
|
||||
/* No threads present. */
|
||||
__fsetlocking (fp, FSETLOCKING_BYCALLER);
|
||||
#endif
|
||||
|
||||
added = 0;
|
||||
while (!FEOF (fp))
|
||||
{
|
||||
/* It is a reasonable approach to use a fix buffer here because
|
||||
a) we are only interested in the first two fields
|
||||
b) these fields must be usable as file names and so must not
|
||||
be that long
|
||||
We avoid a multi-kilobyte buffer here since this would use up
|
||||
stack space which we might not have if the program ran out of
|
||||
memory. */
|
||||
char buf[400];
|
||||
char *alias;
|
||||
char *value;
|
||||
char *cp;
|
||||
|
||||
if (FGETS (buf, sizeof buf, fp) == NULL)
|
||||
/* EOF reached. */
|
||||
break;
|
||||
|
||||
cp = buf;
|
||||
/* Ignore leading white space. */
|
||||
while (isspace ((unsigned char) cp[0]))
|
||||
++cp;
|
||||
|
||||
/* A leading '#' signals a comment line. */
|
||||
if (cp[0] != '\0' && cp[0] != '#')
|
||||
{
|
||||
alias = cp++;
|
||||
while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
|
||||
++cp;
|
||||
/* Terminate alias name. */
|
||||
if (cp[0] != '\0')
|
||||
*cp++ = '\0';
|
||||
|
||||
/* Now look for the beginning of the value. */
|
||||
while (isspace ((unsigned char) cp[0]))
|
||||
++cp;
|
||||
|
||||
if (cp[0] != '\0')
|
||||
{
|
||||
size_t alias_len;
|
||||
size_t value_len;
|
||||
|
||||
value = cp++;
|
||||
while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
|
||||
++cp;
|
||||
/* Terminate value. */
|
||||
if (cp[0] == '\n')
|
||||
{
|
||||
/* This has to be done to make the following test
|
||||
for the end of line possible. We are looking for
|
||||
the terminating '\n' which do not overwrite here. */
|
||||
*cp++ = '\0';
|
||||
*cp = '\n';
|
||||
}
|
||||
else if (cp[0] != '\0')
|
||||
*cp++ = '\0';
|
||||
|
||||
if (nmap >= maxmap)
|
||||
if (__builtin_expect (extend_alias_table (), 0))
|
||||
{
|
||||
fclose (fp);
|
||||
return added;
|
||||
}
|
||||
|
||||
alias_len = strlen (alias) + 1;
|
||||
value_len = strlen (value) + 1;
|
||||
|
||||
if (string_space_act + alias_len + value_len > string_space_max)
|
||||
{
|
||||
/* Increase size of memory pool. */
|
||||
size_t new_size = (string_space_max
|
||||
+ (alias_len + value_len > 1024
|
||||
? alias_len + value_len : 1024));
|
||||
char *new_pool = (char *) realloc (string_space, new_size);
|
||||
if (new_pool == NULL)
|
||||
return added;
|
||||
|
||||
if (__builtin_expect (string_space != new_pool, 0))
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < nmap; i++)
|
||||
{
|
||||
map[i].alias += new_pool - string_space;
|
||||
map[i].value += new_pool - string_space;
|
||||
}
|
||||
}
|
||||
|
||||
string_space = new_pool;
|
||||
string_space_max = new_size;
|
||||
}
|
||||
|
||||
map[nmap].alias = memcpy (&string_space[string_space_act],
|
||||
alias, alias_len);
|
||||
string_space_act += alias_len;
|
||||
|
||||
map[nmap].value = memcpy (&string_space[string_space_act],
|
||||
value, value_len);
|
||||
string_space_act += value_len;
|
||||
|
||||
++nmap;
|
||||
++added;
|
||||
}
|
||||
}
|
||||
|
||||
/* Possibly not the whole line fits into the buffer. Ignore
|
||||
the rest of the line. */
|
||||
while (strchr (buf, '\n') == NULL)
|
||||
if (FGETS (buf, sizeof buf, fp) == NULL)
|
||||
/* Make sure the inner loop will be left. The outer loop
|
||||
will exit at the `feof' test. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Should we test for ferror()? I think we have to silently ignore
|
||||
errors. --drepper */
|
||||
fclose (fp);
|
||||
|
||||
if (added > 0)
|
||||
qsort (map, nmap, sizeof (struct alias_map),
|
||||
(int (*) PARAMS ((const void *, const void *))) alias_compare);
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
extend_alias_table ()
|
||||
{
|
||||
size_t new_size;
|
||||
struct alias_map *new_map;
|
||||
|
||||
new_size = maxmap == 0 ? 100 : 2 * maxmap;
|
||||
new_map = (struct alias_map *) realloc (map, (new_size
|
||||
* sizeof (struct alias_map)));
|
||||
if (new_map == NULL)
|
||||
/* Simply don't extend: we don't have any more core. */
|
||||
return -1;
|
||||
|
||||
map = new_map;
|
||||
maxmap = new_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
alias_compare (map1, map2)
|
||||
const struct alias_map *map1;
|
||||
const struct alias_map *map2;
|
||||
{
|
||||
#if defined _LIBC || defined HAVE_STRCASECMP
|
||||
return strcasecmp (map1->alias, map2->alias);
|
||||
#else
|
||||
const unsigned char *p1 = (const unsigned char *) map1->alias;
|
||||
const unsigned char *p2 = (const unsigned char *) map2->alias;
|
||||
unsigned char c1, c2;
|
||||
|
||||
if (p1 == p2)
|
||||
return 0;
|
||||
|
||||
do
|
||||
{
|
||||
/* I know this seems to be odd but the tolower() function in
|
||||
some systems libc cannot handle nonalpha characters. */
|
||||
c1 = isupper (*p1) ? tolower (*p1) : *p1;
|
||||
c2 = isupper (*p2) ? tolower (*p2) : *p2;
|
||||
if (c1 == '\0')
|
||||
break;
|
||||
++p1;
|
||||
++p2;
|
||||
}
|
||||
while (c1 == c2);
|
||||
|
||||
return c1 - c2;
|
||||
#endif
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,76 +0,0 @@
|
||||
# This makefile for Readline library documentation is in -*- text -*- mode.
|
||||
# Emacs likes it that way.
|
||||
RM = rm -f
|
||||
|
||||
MAKEINFO = makeinfo
|
||||
TEXI2DVI = texi2dvi
|
||||
TEXI2HTML = texi2html
|
||||
QUIETPS = #set this to -q to shut up dvips
|
||||
DVIPS = dvips -D 300 $(QUIETPS) -o $@ # tricky
|
||||
|
||||
INSTALL_DATA = cp
|
||||
infodir = /usr/local/info
|
||||
|
||||
RLSRC = rlman.texinfo rluser.texinfo rltech.texinfo
|
||||
HISTSRC = hist.texinfo hsuser.texinfo hstech.texinfo
|
||||
|
||||
DVIOBJ = readline.dvi history.dvi
|
||||
INFOOBJ = readline.info history.info
|
||||
PSOBJ = readline.ps history.ps
|
||||
HTMLOBJ = readline.html history.html
|
||||
|
||||
all: info dvi html ps
|
||||
nodvi: info html
|
||||
|
||||
readline.dvi: $(RLSRC)
|
||||
$(TEXI2DVI) rlman.texinfo
|
||||
mv rlman.dvi readline.dvi
|
||||
|
||||
readline.info: $(RLSRC)
|
||||
$(MAKEINFO) --no-split -o $@ rlman.texinfo
|
||||
|
||||
history.dvi: ${HISTSRC}
|
||||
$(TEXI2DVI) hist.texinfo
|
||||
mv hist.dvi history.dvi
|
||||
|
||||
history.info: ${HISTSRC}
|
||||
$(MAKEINFO) --no-split -o $@ hist.texinfo
|
||||
|
||||
readline.ps: readline.dvi
|
||||
$(RM) $@
|
||||
$(DVIPS) readline.dvi
|
||||
|
||||
history.ps: history.dvi
|
||||
$(RM) $@
|
||||
$(DVIPS) history.dvi
|
||||
|
||||
readline.html: ${RLSRC}
|
||||
$(TEXI2HTML) rlman.texinfo
|
||||
sed -e 's:rlman.html:readline.html:' -e 's:rlman_toc.html:readline_toc.html:' rlman.html > readline.html
|
||||
sed -e 's:rlman.html:readline.html:' -e 's:rlman_toc.html:readline_toc.html:' rlman_toc.html > readline_toc.html
|
||||
$(RM) rlman.html rlman_toc.html
|
||||
|
||||
history.html: ${HISTSRC}
|
||||
$(TEXI2HTML) hist.texinfo
|
||||
sed -e 's:hist.html:history.html:' -e 's:hist_toc.html:history_toc.html:' hist.html > history.html
|
||||
sed -e 's:hist.html:history.html:' -e 's:hist_toc.html:history_toc.html:' hist_toc.html > history_toc.html
|
||||
$(RM) hist.html hist_toc.html
|
||||
|
||||
info: $(INFOOBJ)
|
||||
dvi: $(DVIOBJ)
|
||||
ps: $(PSOBJ)
|
||||
html: $(HTMLOBJ)
|
||||
|
||||
clean:
|
||||
$(RM) *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.cps *.pgs \
|
||||
*.fns *.kys *.tps *.vrs *.o core
|
||||
|
||||
distclean: clean
|
||||
mostlyclean: clean
|
||||
|
||||
maintainer-clean: clean
|
||||
$(RM) *.dvi *.info *.info-* *.ps *.html
|
||||
|
||||
install: info
|
||||
${INSTALL_DATA} readline.info $(infodir)/readline.info
|
||||
${INSTALL_DATA} history.info $(infodir)/history.info
|
||||
@@ -1,423 +0,0 @@
|
||||
/* mktime - convert struct tm to a time_t value */
|
||||
|
||||
/* Copyright (C) 1993-2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
Contributed by Paul Eggert (eggert@twinsun.com).
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* Define this to have a standalone program to test this implementation of
|
||||
mktime. */
|
||||
/* #define DEBUG 1 */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
# define HAVE_LIMITS_H 1
|
||||
# define HAVE_LOCALTIME_R 1
|
||||
# define STDC_HEADERS 1
|
||||
#endif
|
||||
|
||||
/* Assume that leap seconds are possible, unless told otherwise.
|
||||
If the host has a `zic' command with a `-L leapsecondfilename' option,
|
||||
then it supports leap seconds; otherwise it probably doesn't. */
|
||||
#ifndef LEAP_SECONDS_POSSIBLE
|
||||
#define LEAP_SECONDS_POSSIBLE 1
|
||||
#endif
|
||||
|
||||
#ifndef VMS
|
||||
#include <sys/types.h> /* Some systems define `time_t' here. */
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#if HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#include "bashansi.h"
|
||||
|
||||
#if DEBUG
|
||||
#include <stdio.h>
|
||||
/* Make it work even if the system's libc has its own mktime routine. */
|
||||
#define mktime my_mktime
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifndef __P
|
||||
#if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
|
||||
#define __P(args) args
|
||||
#else
|
||||
#define __P(args) ()
|
||||
#endif /* GCC. */
|
||||
#endif /* Not __P. */
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
#define CHAR_BIT 8
|
||||
#endif
|
||||
|
||||
#ifndef INT_MIN
|
||||
#define INT_MIN (~0 << (sizeof (int) * CHAR_BIT - 1))
|
||||
#endif
|
||||
#ifndef INT_MAX
|
||||
#define INT_MAX (~0 - INT_MIN)
|
||||
#endif
|
||||
|
||||
#ifndef TIME_T_MIN
|
||||
#define TIME_T_MIN (0 < (time_t) -1 ? (time_t) 0 \
|
||||
: ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
|
||||
#endif
|
||||
#ifndef TIME_T_MAX
|
||||
#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
|
||||
#endif
|
||||
|
||||
#define TM_YEAR_BASE 1900
|
||||
#define EPOCH_YEAR 1970
|
||||
|
||||
#ifndef __isleap
|
||||
/* Nonzero if YEAR is a leap year (every 4 years,
|
||||
except every 100th isn't, and every 400th is). */
|
||||
#define __isleap(year) \
|
||||
((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
|
||||
#endif
|
||||
|
||||
/* How many days come before each month (0-12). */
|
||||
const unsigned short int __mon_yday[2][13] =
|
||||
{
|
||||
/* Normal years. */
|
||||
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
|
||||
/* Leap years. */
|
||||
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
|
||||
};
|
||||
|
||||
static time_t ydhms_tm_diff __P ((int, int, int, int, int, const struct tm *));
|
||||
time_t __mktime_internal __P ((struct tm *,
|
||||
struct tm *(*) (const time_t *, struct tm *),
|
||||
time_t *));
|
||||
|
||||
|
||||
static struct tm *my_localtime_r __P ((const time_t *, struct tm *));
|
||||
static struct tm *
|
||||
my_localtime_r (t, tp)
|
||||
const time_t *t;
|
||||
struct tm *tp;
|
||||
{
|
||||
struct tm *l = localtime (t);
|
||||
if (! l)
|
||||
return 0;
|
||||
*tp = *l;
|
||||
return tp;
|
||||
}
|
||||
|
||||
|
||||
/* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
|
||||
measured in seconds, ignoring leap seconds.
|
||||
YEAR uses the same numbering as TM->tm_year.
|
||||
All values are in range, except possibly YEAR.
|
||||
If overflow occurs, yield the low order bits of the correct answer. */
|
||||
static time_t
|
||||
ydhms_tm_diff (year, yday, hour, min, sec, tp)
|
||||
int year, yday, hour, min, sec;
|
||||
const struct tm *tp;
|
||||
{
|
||||
/* Compute intervening leap days correctly even if year is negative.
|
||||
Take care to avoid int overflow. time_t overflow is OK, since
|
||||
only the low order bits of the correct time_t answer are needed.
|
||||
Don't convert to time_t until after all divisions are done, since
|
||||
time_t might be unsigned. */
|
||||
int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
|
||||
int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
|
||||
int a100 = a4 / 25 - (a4 % 25 < 0);
|
||||
int b100 = b4 / 25 - (b4 % 25 < 0);
|
||||
int a400 = a100 >> 2;
|
||||
int b400 = b100 >> 2;
|
||||
int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
|
||||
time_t years = year - (time_t) tp->tm_year;
|
||||
time_t days = (365 * years + intervening_leap_days
|
||||
+ (yday - tp->tm_yday));
|
||||
return (60 * (60 * (24 * days + (hour - tp->tm_hour))
|
||||
+ (min - tp->tm_min))
|
||||
+ (sec - tp->tm_sec));
|
||||
}
|
||||
|
||||
|
||||
static time_t localtime_offset;
|
||||
|
||||
/* Convert *TP to a time_t value. */
|
||||
time_t
|
||||
mktime (tp)
|
||||
struct tm *tp;
|
||||
{
|
||||
#ifdef _LIBC
|
||||
/* POSIX.1 8.1.1 requires that whenever mktime() is called, the
|
||||
time zone names contained in the external variable `tzname' shall
|
||||
be set as if the tzset() function had been called. */
|
||||
__tzset ();
|
||||
#endif
|
||||
|
||||
return __mktime_internal (tp, my_localtime_r, &localtime_offset);
|
||||
}
|
||||
|
||||
/* Convert *TP to a time_t value, inverting
|
||||
the monotonic and mostly-unit-linear conversion function CONVERT.
|
||||
Use *OFFSET to keep track of a guess at the offset of the result,
|
||||
compared to what the result would be for UTC without leap seconds.
|
||||
If *OFFSET's guess is correct, only one CONVERT call is needed. */
|
||||
time_t
|
||||
__mktime_internal (tp, convert, offset)
|
||||
struct tm *tp;
|
||||
struct tm *(*convert) __P ((const time_t *, struct tm *));
|
||||
time_t *offset;
|
||||
{
|
||||
time_t t, dt, t0;
|
||||
struct tm tm;
|
||||
|
||||
/* The maximum number of probes (calls to CONVERT) should be enough
|
||||
to handle any combinations of time zone rule changes, solar time,
|
||||
and leap seconds. Posix.1 prohibits leap seconds, but some hosts
|
||||
have them anyway. */
|
||||
int remaining_probes = 4;
|
||||
|
||||
/* Time requested. Copy it in case CONVERT modifies *TP; this can
|
||||
occur if TP is localtime's returned value and CONVERT is localtime. */
|
||||
int sec = tp->tm_sec;
|
||||
int min = tp->tm_min;
|
||||
int hour = tp->tm_hour;
|
||||
int mday = tp->tm_mday;
|
||||
int mon = tp->tm_mon;
|
||||
int year_requested = tp->tm_year;
|
||||
int isdst = tp->tm_isdst;
|
||||
|
||||
/* Ensure that mon is in range, and set year accordingly. */
|
||||
int mon_remainder = mon % 12;
|
||||
int negative_mon_remainder = mon_remainder < 0;
|
||||
int mon_years = mon / 12 - negative_mon_remainder;
|
||||
int year = year_requested + mon_years;
|
||||
|
||||
/* The other values need not be in range:
|
||||
the remaining code handles minor overflows correctly,
|
||||
assuming int and time_t arithmetic wraps around.
|
||||
Major overflows are caught at the end. */
|
||||
|
||||
/* Calculate day of year from year, month, and day of month.
|
||||
The result need not be in range. */
|
||||
int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
|
||||
[mon_remainder + 12 * negative_mon_remainder])
|
||||
+ mday - 1);
|
||||
|
||||
#if LEAP_SECONDS_POSSIBLE
|
||||
/* Handle out-of-range seconds specially,
|
||||
since ydhms_tm_diff assumes every minute has 60 seconds. */
|
||||
int sec_requested = sec;
|
||||
if (sec < 0)
|
||||
sec = 0;
|
||||
if (59 < sec)
|
||||
sec = 59;
|
||||
#endif
|
||||
|
||||
/* Invert CONVERT by probing. First assume the same offset as last time.
|
||||
Then repeatedly use the error to improve the guess. */
|
||||
|
||||
tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
|
||||
tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
|
||||
t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
|
||||
|
||||
for (t = t0 + *offset;
|
||||
(dt = ydhms_tm_diff (year, yday, hour, min, sec, (*convert) (&t, &tm)));
|
||||
t += dt)
|
||||
if (--remaining_probes == 0)
|
||||
return -1;
|
||||
|
||||
/* Check whether tm.tm_isdst has the requested value, if any. */
|
||||
if (0 <= isdst && 0 <= tm.tm_isdst)
|
||||
{
|
||||
int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
|
||||
if (dst_diff)
|
||||
{
|
||||
/* Move two hours in the direction indicated by the disagreement,
|
||||
probe some more, and switch to a new time if found.
|
||||
The largest known fallback due to daylight savings is two hours:
|
||||
once, in Newfoundland, 1988-10-30 02:00 -> 00:00. */
|
||||
time_t ot = t - 2 * 60 * 60 * dst_diff;
|
||||
while (--remaining_probes != 0)
|
||||
{
|
||||
struct tm otm;
|
||||
if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
|
||||
(*convert) (&ot, &otm))))
|
||||
{
|
||||
t = ot;
|
||||
tm = otm;
|
||||
break;
|
||||
}
|
||||
if ((ot += dt) == t)
|
||||
break; /* Avoid a redundant probe. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*offset = t - t0;
|
||||
|
||||
#if LEAP_SECONDS_POSSIBLE
|
||||
if (sec_requested != tm.tm_sec)
|
||||
{
|
||||
/* Adjust time to reflect the tm_sec requested, not the normalized value.
|
||||
Also, repair any damage from a false match due to a leap second. */
|
||||
t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
|
||||
(*convert) (&t, &tm);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
|
||||
{
|
||||
/* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
|
||||
so check for major overflows. A gross check suffices,
|
||||
since if t has overflowed, it is off by a multiple of
|
||||
TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of
|
||||
the difference that is bounded by a small value. */
|
||||
|
||||
double dyear = (double) year_requested + mon_years - tm.tm_year;
|
||||
double dday = 366 * dyear + mday;
|
||||
double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
|
||||
|
||||
if (TIME_T_MAX / 3 - TIME_T_MIN / 3 < (dsec < 0 ? - dsec : dsec))
|
||||
return -1;
|
||||
}
|
||||
|
||||
*tp = tm;
|
||||
return t;
|
||||
}
|
||||
|
||||
#ifdef weak_alias
|
||||
weak_alias (mktime, timelocal)
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
|
||||
static int
|
||||
not_equal_tm (a, b)
|
||||
struct tm *a;
|
||||
struct tm *b;
|
||||
{
|
||||
return ((a->tm_sec ^ b->tm_sec)
|
||||
| (a->tm_min ^ b->tm_min)
|
||||
| (a->tm_hour ^ b->tm_hour)
|
||||
| (a->tm_mday ^ b->tm_mday)
|
||||
| (a->tm_mon ^ b->tm_mon)
|
||||
| (a->tm_year ^ b->tm_year)
|
||||
| (a->tm_mday ^ b->tm_mday)
|
||||
| (a->tm_yday ^ b->tm_yday)
|
||||
| (a->tm_isdst ^ b->tm_isdst));
|
||||
}
|
||||
|
||||
static void
|
||||
print_tm (tp)
|
||||
struct tm *tp;
|
||||
{
|
||||
printf ("%04d-%02d-%02d %02d:%02d:%02d yday %03d wday %d isdst %d",
|
||||
tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
|
||||
tp->tm_hour, tp->tm_min, tp->tm_sec,
|
||||
tp->tm_yday, tp->tm_wday, tp->tm_isdst);
|
||||
}
|
||||
|
||||
static int
|
||||
check_result (tk, tmk, tl, tml)
|
||||
time_t tk;
|
||||
struct tm tmk;
|
||||
time_t tl;
|
||||
struct tm tml;
|
||||
{
|
||||
if (tk != tl || not_equal_tm (&tmk, &tml))
|
||||
{
|
||||
printf ("mktime (");
|
||||
print_tm (&tmk);
|
||||
printf (")\nyields (");
|
||||
print_tm (&tml);
|
||||
printf (") == %ld, should be %ld\n", (long) tl, (long) tk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int status = 0;
|
||||
struct tm tm, tmk, tml;
|
||||
time_t tk, tl;
|
||||
char trailer;
|
||||
|
||||
if ((argc == 3 || argc == 4)
|
||||
&& (sscanf (argv[1], "%d-%d-%d%c",
|
||||
&tm.tm_year, &tm.tm_mon, &tm.tm_mday, &trailer)
|
||||
== 3)
|
||||
&& (sscanf (argv[2], "%d:%d:%d%c",
|
||||
&tm.tm_hour, &tm.tm_min, &tm.tm_sec, &trailer)
|
||||
== 3))
|
||||
{
|
||||
tm.tm_year -= TM_YEAR_BASE;
|
||||
tm.tm_mon--;
|
||||
tm.tm_isdst = argc == 3 ? -1 : atoi (argv[3]);
|
||||
tmk = tm;
|
||||
tl = mktime (&tmk);
|
||||
tml = *localtime (&tl);
|
||||
printf ("mktime returns %ld == ", (long) tl);
|
||||
print_tm (&tmk);
|
||||
printf ("\n");
|
||||
status = check_result (tl, tmk, tl, tml);
|
||||
}
|
||||
else if (argc == 4 || (argc == 5 && strcmp (argv[4], "-") == 0))
|
||||
{
|
||||
time_t from = atol (argv[1]);
|
||||
time_t by = atol (argv[2]);
|
||||
time_t to = atol (argv[3]);
|
||||
|
||||
if (argc == 4)
|
||||
for (tl = from; tl <= to; tl += by)
|
||||
{
|
||||
tml = *localtime (&tl);
|
||||
tmk = tml;
|
||||
tk = mktime (&tmk);
|
||||
status |= check_result (tk, tmk, tl, tml);
|
||||
}
|
||||
else
|
||||
for (tl = from; tl <= to; tl += by)
|
||||
{
|
||||
/* Null benchmark. */
|
||||
tml = *localtime (&tl);
|
||||
tmk = tml;
|
||||
tk = tl;
|
||||
status |= check_result (tk, tmk, tl, tml);
|
||||
}
|
||||
}
|
||||
else
|
||||
printf ("Usage:\
|
||||
\t%s YYYY-MM-DD HH:MM:SS [ISDST] # Test given time.\n\
|
||||
\t%s FROM BY TO # Test values FROM, FROM+BY, ..., TO.\n\
|
||||
\t%s FROM BY TO - # Do not test those values (for benchmark).\n",
|
||||
argv[0], argv[0], argv[0]);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
Local Variables:
|
||||
compile-command: "gcc -DDEBUG=1 -Wall -O -g mktime.c -o mktime"
|
||||
End:
|
||||
*/
|
||||
@@ -1,9 +0,0 @@
|
||||
BUILD_DIR=/usr/local/build/chet/bash/bash-current
|
||||
THIS_SH=$BUILD_DIR/bash
|
||||
PATH=$PATH:$BUILD_DIR
|
||||
|
||||
export THIS_SH PATH
|
||||
|
||||
rm -f /tmp/xx
|
||||
|
||||
/bin/sh "$@"
|
||||
@@ -1,260 +0,0 @@
|
||||
# first, let's start with the basics
|
||||
|
||||
recho "$@"
|
||||
recho "$*"
|
||||
|
||||
recho $@
|
||||
recho $*
|
||||
|
||||
set a b
|
||||
|
||||
recho "$*"
|
||||
|
||||
# If IFS is null, the parameters are joined without separators
|
||||
IFS=''
|
||||
recho "$*"
|
||||
|
||||
# If IFS is unset, the parameters are separated by spaces
|
||||
unset IFS
|
||||
recho "${*}"
|
||||
|
||||
recho "$@"
|
||||
recho $@
|
||||
|
||||
IFS='/'
|
||||
set bob 'tom dick harry' joe
|
||||
set $*
|
||||
recho $#
|
||||
recho $1
|
||||
recho $2
|
||||
recho $3
|
||||
|
||||
set bob 'tom dick harry' joe
|
||||
set ${*}
|
||||
recho $#
|
||||
recho $1
|
||||
recho $2
|
||||
recho $3
|
||||
|
||||
set bob 'tom dick harry' joe
|
||||
set $@
|
||||
recho $#
|
||||
recho $1
|
||||
recho $2
|
||||
recho $3
|
||||
|
||||
set bob 'tom dick harry' joe
|
||||
set ${@}
|
||||
recho $#
|
||||
recho $1
|
||||
recho $2
|
||||
recho $3
|
||||
|
||||
# according to POSIX.2, unquoted $* should expand to multiple words if
|
||||
# $IFS is null, just like unquoted $@
|
||||
IFS=''
|
||||
set bob 'tom dick harry' joe
|
||||
set $*
|
||||
recho $#
|
||||
recho $1
|
||||
recho $2
|
||||
recho $3
|
||||
|
||||
set bob 'tom dick harry' joe
|
||||
set $@
|
||||
recho $#
|
||||
recho $1
|
||||
recho $2
|
||||
recho $3
|
||||
|
||||
# if IFS is unset, the individual positional parameters are split on
|
||||
# " \t\n" if $* or $@ are unquoted
|
||||
unset IFS
|
||||
set bob 'tom dick harry' joe
|
||||
set $*
|
||||
recho $#
|
||||
recho $1
|
||||
recho $2
|
||||
recho $3
|
||||
|
||||
set bob 'tom dick harry' joe
|
||||
set $@
|
||||
recho $#
|
||||
recho $1
|
||||
recho $2
|
||||
recho $3
|
||||
|
||||
# but not for "$@" or "$*"
|
||||
set bob 'tom dick harry' joe
|
||||
set "$*"
|
||||
recho $#
|
||||
recho $1
|
||||
recho $2
|
||||
recho $3
|
||||
|
||||
set bob 'tom dick harry' joe
|
||||
set "$@"
|
||||
recho $#
|
||||
recho $1
|
||||
recho $2
|
||||
recho $3
|
||||
|
||||
# POSIX.2 says these should both expand the positional parameters
|
||||
# to multiple words
|
||||
set a b c d e
|
||||
IFS=""
|
||||
recho $@
|
||||
recho "$@"
|
||||
|
||||
# this example is straight from the POSIX.2 rationale
|
||||
set foo bar bam
|
||||
|
||||
recho "$@"
|
||||
recho "$*"
|
||||
|
||||
unset IFS
|
||||
|
||||
recho "$@"
|
||||
recho $@
|
||||
recho "$*"
|
||||
|
||||
IFS=:
|
||||
|
||||
# special variables
|
||||
set -- 1 2 3 4 5 6 7 8 9 10
|
||||
|
||||
bar=${*}
|
||||
foo=$*
|
||||
echo foo = "$foo"
|
||||
echo bar = "$bar"
|
||||
|
||||
foo1=$@
|
||||
bar1=${@}
|
||||
|
||||
echo foo1 = "$foo1"
|
||||
echo bar1 = "$bar1"
|
||||
|
||||
foo2="$*"
|
||||
bar2="${*}"
|
||||
|
||||
echo foo2 = "$foo2"
|
||||
echo bar2 = "$bar2"
|
||||
|
||||
eval foo3='$*' bar3='${*}'
|
||||
echo foo3 = "$foo3"
|
||||
echo bar3 = "$bar3"
|
||||
|
||||
case $* in
|
||||
*\:*) echo ok 1;;
|
||||
*) echo bad 1;;
|
||||
esac
|
||||
|
||||
case $@ in
|
||||
*\:*) echo bad 2;;
|
||||
*) echo ok 2;;
|
||||
esac
|
||||
|
||||
case "$*" in
|
||||
*\:*) echo ok 3;;
|
||||
*) echo bad 3;;
|
||||
esac
|
||||
|
||||
case "$@" in
|
||||
*\:*) echo bad 4;;
|
||||
*) echo ok 4;;
|
||||
esac
|
||||
|
||||
IFS=$' \t\n'
|
||||
|
||||
bar=${*}
|
||||
foo=$*
|
||||
echo foo = "$foo"
|
||||
echo bar = "$bar"
|
||||
|
||||
foo1=$@
|
||||
bar1=${@}
|
||||
|
||||
echo foo1 = "$foo1"
|
||||
echo bar1 = "$bar1"
|
||||
|
||||
foo2="$*"
|
||||
bar2="${*}"
|
||||
|
||||
echo foo2 = "$foo2"
|
||||
echo bar2 = "$bar2"
|
||||
|
||||
eval foo3='$*' bar3='${*}'
|
||||
echo foo3 = "$foo3"
|
||||
echo bar3 = "$bar3"
|
||||
|
||||
case $* in
|
||||
*\ *) echo ok 1;;
|
||||
*) echo bad 1;;
|
||||
esac
|
||||
|
||||
case $@ in
|
||||
*\ *) echo ok 2;;
|
||||
*) echo bad 2;;
|
||||
esac
|
||||
|
||||
case "$*" in
|
||||
*\ *) echo ok 3;;
|
||||
*) echo bad 3;;
|
||||
esac
|
||||
|
||||
case "$@" in
|
||||
*\ *) echo ok 4;;
|
||||
*) echo bad 4;;
|
||||
esac
|
||||
|
||||
# tests for the effect of quoting $* and $@ in an assignment context (plus
|
||||
# arrays) -- bugs through bash 4.2
|
||||
${THIS_SH} ./dollar-at-star1.sub
|
||||
|
||||
# tests for special expansion of "$*" and "${array[*]}" when used with other
|
||||
# expansions -- bugs through bash-2.05b
|
||||
${THIS_SH} ./dollar-star1.sub
|
||||
|
||||
# tests for expansion of "$@" on rhs of things like ${param:+word}. Bugs
|
||||
# though bash-2.05b
|
||||
${THIS_SH} ./dollar-at1.sub
|
||||
|
||||
# tests for expansion of other variables in double-quoted strings containing
|
||||
# $@. Bugs through bash-2.05b
|
||||
${THIS_SH} ./dollar-at2.sub
|
||||
|
||||
# tests for various expansions of $* in different contexts -- word split,
|
||||
# no splitting, etc. when $IFS is NUL
|
||||
${THIS_SH} ./dollar-star2.sub
|
||||
|
||||
# tests for expansions of "${array[*]}" and "${array[@]}" when $IFS is not the
|
||||
# default and the array contains null elements
|
||||
${THIS_SH} ./dollar-star3.sub
|
||||
|
||||
# test for set -u and expansions of $@ when there are no positional parameters
|
||||
${THIS_SH} ./dollar-at3.sub
|
||||
# test for set -u and expansions of $* when there are no positional parameters
|
||||
${THIS_SH} ./dollar-star4.sub
|
||||
|
||||
# tests for expansions of $* when IFS is null
|
||||
${THIS_SH} ./dollar-star5.sub
|
||||
|
||||
# tests for inappropriate word splitting through bash-4.2
|
||||
${THIS_SH} ./dollar-at4.sub
|
||||
|
||||
# tests for problems with "$@" preceded and followed by other quoted expansions
|
||||
# through bash-4.2
|
||||
${THIS_SH} ./dollar-at5.sub
|
||||
|
||||
# tests for problems with "${@:1}" and other expansions with null entries
|
||||
# in positional parameters
|
||||
${THIS_SH} ./dollar-at6.sub
|
||||
|
||||
# tests for expansions of $* when $1 == ""; problem through bash-4.2
|
||||
${THIS_SH} ./dollar-star6.sub
|
||||
|
||||
# tests for expansions of $* (unquoted) when IFS changes (e.g., ${IFS:=-})
|
||||
# problem through bash-4.2
|
||||
${THIS_SH} ./dollar-star7.sub
|
||||
|
||||
exit 0
|
||||
@@ -1,50 +0,0 @@
|
||||
:; ./shx
|
||||
|
||||
sh:
|
||||
<&$fd ok
|
||||
nlbq Mon Aug 3 02:45:00 EDT 1992
|
||||
bang geoff
|
||||
quote 712824302
|
||||
setbq defmsgid=<1992Aug3.024502.6176@host>
|
||||
bgwait sleep done... wait 6187
|
||||
|
||||
|
||||
bash:
|
||||
<&$fd ok
|
||||
nlbq Mon Aug 3 02:45:09 EDT 1992
|
||||
bang geoff
|
||||
quote 712824311
|
||||
setbq defmsgid=<1992Aug3.024512.6212@host>
|
||||
bgwait sleep done... wait 6223
|
||||
|
||||
|
||||
ash:
|
||||
<&$fd shx1: 4: Syntax error: Bad fd number
|
||||
nlbq Mon Aug 3 02:45:19 EDT 1992
|
||||
bang geoff
|
||||
quote getdate: `"now"' not a valid date
|
||||
|
||||
setbq defmsgid=<1992Aug3.` echo 024521
|
||||
bgwait sleep done... wait 6241
|
||||
|
||||
|
||||
ksh:
|
||||
<&$fd ok
|
||||
nlbq ./shx: 6248 Memory fault - core dumped
|
||||
bang geoff
|
||||
quote getdate: `"now"' not a valid date
|
||||
|
||||
setbq defmsgid=<1992Aug3.024530.6257@host>
|
||||
bgwait no such job: 6265
|
||||
wait 6265
|
||||
sleep done...
|
||||
|
||||
zsh:
|
||||
<&$fd ok
|
||||
nlbq Mon Aug 3 02:45:36 EDT 1992
|
||||
bang shx3: event not found: /s/ [4]
|
||||
quote 712824337
|
||||
setbq defmsgid=<..6290@host>
|
||||
bgwait shx7: unmatched " [9]
|
||||
sleep done...
|
||||
:;
|
||||
@@ -1,10 +0,0 @@
|
||||
#! /bin/sh
|
||||
for cmd in sh bash ash ksh zsh
|
||||
do
|
||||
echo
|
||||
echo $cmd:
|
||||
for demo in shx?
|
||||
do
|
||||
$cmd $demo
|
||||
done
|
||||
done
|
||||
Reference in New Issue
Block a user