mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 15:43:18 +02:00
commit bash-20100525 snapshot
This commit is contained in:
+214
@@ -9831,3 +9831,217 @@ lib/sh/strtrans.c
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document new \u and \U escape sequences for $'...' and echo (printf
|
||||
defers to the system's man page or Posix)
|
||||
|
||||
5/24
|
||||
----
|
||||
execute_cmd.c
|
||||
- change execute_disk_command to return a status, instead of just
|
||||
leaving it in `last_command_exit_value', since the parent's return
|
||||
value is sometimes uses (e.g., when a restricted shell refuses to
|
||||
run a command with a `/'). Fixes bug reported by David Pitt
|
||||
<David.Pitt@anz.com>
|
||||
|
||||
5/25
|
||||
----
|
||||
bashline.c
|
||||
- change bash completion functions to save and restore the value of
|
||||
rl_ignore_some_completions_function, and set it to the bash default
|
||||
of filename_completion_ignore where appropriate. Fixes bug
|
||||
reported by Henning Bekel <h.bekel@googlemail.com>
|
||||
|
||||
variables.c
|
||||
- new convenience function: find_global_variable (name). Looks for
|
||||
NAME in the global variables table, skipping any local and
|
||||
temporary environment variables
|
||||
|
||||
builtins/declare.def
|
||||
- add new -g option to declare/typeset/local, forces variables to be
|
||||
created or modified at the global scope when executing inside a
|
||||
shell function. Requested by many, most recently by
|
||||
konsolebox@gmail.com
|
||||
|
||||
5/27
|
||||
----
|
||||
test.c
|
||||
- added new `-v var' unary test operator; returns TRUE if var is set
|
||||
(i.e., has been assigned a value). Works in both test builtin and
|
||||
[[ conditional command
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- documented new `-v var' unary conditional operator
|
||||
|
||||
tests/test.tests
|
||||
- added tests for new -v var operator
|
||||
|
||||
builtins/kill.def
|
||||
- change kill builtin so -PID (pgrp specification) following a
|
||||
-s sig or -n sig option is not interpreted as a signal specification.
|
||||
Fixes bug reported by Roman Rakus <rrakus@redhat.com>
|
||||
|
||||
builtins/evalstring.c
|
||||
- in parse_and_execute, if parse_command() returns non-zero,
|
||||
indicating a parse error, exit the shell if the conditions require
|
||||
a posix-mode non-interactive shell to abort (parse error in a `.'
|
||||
script or eval string). Bash-4.1 only printed a warning. This is
|
||||
from Austin Group interp 114
|
||||
|
||||
doc/bashref.texi
|
||||
- add note to the posix mode section of the texinfo manual noting
|
||||
the changed behavior for `.' and `eval'
|
||||
|
||||
parse.y
|
||||
- change time_command_acceptable to allow TIME token to appear after
|
||||
BANG token (to allow `! time foo', which is supposed to be valid)
|
||||
- change pipeline_command production to allow multiple instances of
|
||||
`!' (which toggle inverting the return status) and `time' (which
|
||||
have no effect)
|
||||
|
||||
execute_cmd.c
|
||||
- In posix mode, `time' without a following pipeline prints the
|
||||
elapsed user, system, and real time for the shell and its
|
||||
children since the shell was invoked.
|
||||
It's like `times' but obeys the setting of TIMEFORMAT. A future
|
||||
revision of Posix will require this
|
||||
|
||||
doc/{bashref.texi,bash.1}
|
||||
- document new posix mode use of `time'
|
||||
|
||||
parse.y
|
||||
- add production to pipeline_command that permits `!' by itself to
|
||||
be equivalent to `false' (and, with the changes above, permits
|
||||
`! !' to be roughly equivalent to `true'). A future revision of
|
||||
Posix will require this
|
||||
|
||||
5/28
|
||||
----
|
||||
parse.y
|
||||
- fix \W prompt expansion to use memmove instead of strcpy, since the
|
||||
source and target strings overlap (though you think it wouldn't
|
||||
matter, since the overlapping regions are never touched at the same
|
||||
time). Fixes bug reported by Stéphane Jourdoi
|
||||
<sjourdois@gmail.com>
|
||||
|
||||
parse.y
|
||||
- Posix interp 217 states that $(( must be parsed first as an
|
||||
arithmetic expansion, so avoid attempting to parse it as a nested
|
||||
command substitution. Fixes bug reported by several, most recently
|
||||
<jwm@horde.net>
|
||||
|
||||
subst.c
|
||||
- change extract_delimited_string to process nested $( as a possible
|
||||
command substitution, but only if already parsing an arithmetic
|
||||
expansion. Rest of fix for Posix interp 217
|
||||
- change parameter_brace_expand_rhs to make the := expansion operator
|
||||
perform quote removal and both assign the result to the variable and
|
||||
return it as the result of the expansion, rather than assign the
|
||||
value after quote removal but return the value before quote removal.
|
||||
Posix interp 221
|
||||
- introduce new internal quoting flag: Q_DOLBRACE. Denotes a double-
|
||||
quoted ${...} expansion. In this case, Posix interp 221 requires
|
||||
that a backslash quoting an embedded `}' be removed, even though it's
|
||||
not one of the characters marked as special inside double quotes.
|
||||
Set in parameter_brace_expand, used by expand_word_internal.
|
||||
|
||||
parse.y
|
||||
- introduce new parsing state, P_DOLBRACE, set when parsing a ${...}
|
||||
expansion
|
||||
- set a "dolbrace operator state" in parse_matched_pair to decide
|
||||
whether the lexer is reading the param, op, or word in
|
||||
${paramOPword}. Will be used to decide whether or not to treat
|
||||
single quotes specially in a double-quoted "${...}
|
||||
|
||||
5/29
|
||||
----
|
||||
parse.y
|
||||
- change parse_matched_pair so that a single quote appearing in a
|
||||
double-quoted ${...} expansion is not special unless the expansion
|
||||
operator is `#[#]' or `%[%]'. Posix interp 221
|
||||
|
||||
subst.c
|
||||
- change string_extract_double_quoted so that a single quote appearing
|
||||
in a double-quoted ${...} expansion is not special unless the
|
||||
expansion operator is `#[#]' or `%[%]'. Posix interp 221
|
||||
|
||||
doc/bashref.texi
|
||||
- document posix-mode effects of Posix interp 221
|
||||
- add section describing GNU parallel as requested by Stallman
|
||||
|
||||
lib/readline/complete.c
|
||||
- broke code that compares filenames read from the file system (and
|
||||
possibly converted) to words being completed out into a separate
|
||||
function: complete_fncmp
|
||||
- augment complete_fncmp to treat hyphen and underscore as equivalent
|
||||
when comparing filenames if _rl_completion_case_map is set
|
||||
|
||||
lib/readline/rlprivate.h
|
||||
- new extern declaration for _rl_completion_case_map
|
||||
|
||||
lib/readline/util.c
|
||||
- change _rl_strnicmp to return the difference between the characters,
|
||||
like strcasecmp, and not modify the pointers it is passed
|
||||
- change _rl_stricmp to not modify the pointers it is passed
|
||||
|
||||
lib/readline/bind.c
|
||||
- new bindable variable, "completion-case-map", toggles value of
|
||||
_rl_completion_case_map
|
||||
|
||||
lib/readline/doc/{rluser.texi,readline.3}
|
||||
- document new bindable readline variable "completion-case-map"
|
||||
|
||||
execute_cmd.c
|
||||
- change execute_function to reset funcnest and jump back to top level
|
||||
if funcnest exceeds funcnest_max
|
||||
- use funcnest_max as a max function nesting level, if set to numeric
|
||||
value greater than 0 (defaults to 0, so inactive)
|
||||
|
||||
variables.c
|
||||
- new variable FUNCNEST, controls funcnest_max value if set to numeric
|
||||
value > 0
|
||||
sig.c
|
||||
- reset funcnest to 0 when throw_to_top_level occurs
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document FUNCNEST variable and its effect on function execution
|
||||
|
||||
lib/readline/funmap.c
|
||||
- add new bindable command names to avoid case-insensitive matching
|
||||
problems between, for instance, vi-fword and vi-fWord:
|
||||
|
||||
vi-forward-word
|
||||
vi-forward-bigword
|
||||
vi-backward-word
|
||||
vi-backward-bigword
|
||||
vi-end-word
|
||||
vi-end-bigword
|
||||
|
||||
Suggested in a different form in 2006 (!) by Servatius Brandt
|
||||
<servatius.brandt@arcor.de>
|
||||
|
||||
builtins/mapfile.def
|
||||
- run_callback now takes a new third argument: curline, the line
|
||||
currently being read and about to be assigned
|
||||
- the callback function/command now takes an additional argument:
|
||||
the line to be assigned to the array index. Feature suggested by
|
||||
Dennis Williamson <dennistwilliamson@gmail.com>
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document new additional `line' argument to mapfile callback
|
||||
|
||||
5/30
|
||||
----
|
||||
builtins/printf.def
|
||||
- add new %(fmt)T format specifier, where FMT is a strftime format.
|
||||
Argument is number of seconds since the epoch, with -1 meaning
|
||||
current time (roughly date +%s) and -2 meaning shell start time
|
||||
(roughly $SECONDS, unless it's been assigned a value or unset).
|
||||
Fieldwidth and precision are preserved, strftime result is printed
|
||||
as with %[-][[fieldwidth][.[precision]]]s
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document new %(datefmt)T printf format specifier and special
|
||||
arguments
|
||||
|
||||
builtins/hash.def
|
||||
- don't permit programs with slashes to be entered into the hash table
|
||||
at all, even with the -p option. Inconsistency pointed out by
|
||||
Jan Schampera <jan.schampera@web.de>
|
||||
|
||||
@@ -9827,3 +9827,217 @@ builtins/printf.def
|
||||
lib/sh/strtrans.c
|
||||
- add code to handle \u and \U escapes as unicode characters, works for
|
||||
both `echo -e' and $'...'
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document new \u and \U escape sequences for $'...' and echo (printf
|
||||
defers to the system's man page or Posix)
|
||||
|
||||
5/24
|
||||
----
|
||||
execute_cmd.c
|
||||
- change execute_disk_command to return a status, instead of just
|
||||
leaving it in `last_command_exit_value', since the parent's return
|
||||
value is sometimes uses (e.g., when a restricted shell refuses to
|
||||
run a command with a `/'). Fixes bug reported by David Pitt
|
||||
<David.Pitt@anz.com>
|
||||
|
||||
5/25
|
||||
----
|
||||
bashline.c
|
||||
- change bash completion functions to save and restore the value of
|
||||
rl_ignore_some_completions_function, and set it to the bash default
|
||||
of filename_completion_ignore where appropriate. Fixes bug
|
||||
reported by Henning Bekel <h.bekel@googlemail.com>
|
||||
|
||||
variables.c
|
||||
- new convenience function: find_global_variable (name). Looks for
|
||||
NAME in the global variables table, skipping any local and
|
||||
temporary environment variables
|
||||
|
||||
builtins/declare.def
|
||||
- add new -g option to declare/typeset/local, forces variables to be
|
||||
created or modified at the global scope when executing inside a
|
||||
shell function. Requested by many, most recently by
|
||||
konsolebox@gmail.com
|
||||
|
||||
5/27
|
||||
----
|
||||
test.c
|
||||
- added new `-v var' unary test operator; returns TRUE if var is set
|
||||
(i.e., has been assigned a value). Works in both test builtin and
|
||||
[[ conditional command
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- documented new `-v var' unary conditional operator
|
||||
|
||||
tests/test.tests
|
||||
- added tests for new -v var operator
|
||||
|
||||
builtins/kill.def
|
||||
- change kill builtin so -PID (pgrp specification) following a
|
||||
-s sig or -n sig option is not interpreted as a signal specification.
|
||||
Fixes bug reported by Roman Rakus <rrakus@redhat.com>
|
||||
|
||||
builtins/evalstring.c
|
||||
- in parse_and_execute, if parse_command() returns non-zero,
|
||||
indicating a parse error, exit the shell if the conditions require
|
||||
a posix-mode non-interactive shell to abort (parse error in a `.'
|
||||
script or eval string). Bash-4.1 only printed a warning. This is
|
||||
from Austin Group interp 114
|
||||
|
||||
doc/bashref.texi
|
||||
- add note to the posix mode section of the texinfo manual noting
|
||||
the changed behavior for `.' and `eval'
|
||||
|
||||
parse.y
|
||||
- change time_command_acceptable to allow TIME token to appear after
|
||||
BANG token (to allow `! time foo', which is supposed to be valid)
|
||||
- change pipeline_command production to allow multiple instances of
|
||||
`!' (which toggle inverting the return status) and `time' (which
|
||||
have no effect)
|
||||
|
||||
execute_cmd.c
|
||||
- In posix mode, `time' without a following pipeline prints the
|
||||
elapsed user, system, and real time for the shell and its
|
||||
children since the shell was invoked.
|
||||
It's like `times' but obeys the setting of TIMEFORMAT. A future
|
||||
revision of Posix will require this
|
||||
|
||||
doc/{bashref.texi,bash.1}
|
||||
- document new posix mode use of `time'
|
||||
|
||||
parse.y
|
||||
- add production to pipeline_command that permits `!' by itself to
|
||||
be equivalent to `false' (and, with the changes above, permits
|
||||
`! !' to be roughly equivalent to `true'). A future revision of
|
||||
Posix will require this
|
||||
|
||||
5/28
|
||||
----
|
||||
parse.y
|
||||
- fix \W prompt expansion to use memmove instead of strcpy, since the
|
||||
source and target strings overlap (though you think it wouldn't
|
||||
matter, since the overlapping regions are never touched at the same
|
||||
time). Fixes bug reported by Stéphane Jourdoi
|
||||
<sjourdois@gmail.com>
|
||||
|
||||
parse.y
|
||||
- Posix interp 217 states that $(( must be parsed first as an
|
||||
arithmetic expansion, so avoid attempting to parse it as a nested
|
||||
command substitution. Fixes bug reported by several, most recently
|
||||
<jwm@horde.net>
|
||||
|
||||
subst.c
|
||||
- change extract_delimited_string to process nested $( as a possible
|
||||
command substitution, but only if already parsing an arithmetic
|
||||
expansion. Rest of fix for Posix interp 217
|
||||
- change parameter_brace_expand_rhs to make the := expansion operator
|
||||
perform quote removal and both assign the result to the variable and
|
||||
return it as the result of the expansion, rather than assign the
|
||||
value after quote removal but return the value before quote removal.
|
||||
Posix interp 221
|
||||
- introduce new internal quoting flag: Q_DOLBRACE. Denotes a double-
|
||||
quoted ${...} expansion. In this case, Posix interp 221 requires
|
||||
that a backslash quoting an embedded `}' be removed, even though it's
|
||||
not one of the characters marked as special inside double quotes.
|
||||
Set in parameter_brace_expand, used by expand_word_internal.
|
||||
|
||||
parse.y
|
||||
- introduce new parsing state, P_DOLBRACE, set when parsing a ${...}
|
||||
expansion
|
||||
- set a "dolbrace operator state" in parse_matched_pair to decide
|
||||
whether the lexer is reading the param, op, or word in
|
||||
${paramOPword}. Will be used to decide whether or not to treat
|
||||
single quotes specially in a double-quoted "${...}
|
||||
|
||||
5/29
|
||||
----
|
||||
parse.y
|
||||
- change parse_matched_pair so that a single quote appearing in a
|
||||
double-quoted ${...} expansion is not special unless the expansion
|
||||
operator is `#[#]' or `%[%]'. Posix interp 221
|
||||
|
||||
subst.c
|
||||
- change string_extract_double_quoted so that a single quote appearing
|
||||
in a double-quoted ${...} expansion is not special unless the
|
||||
expansion operator is `#[#]' or `%[%]'. Posix interp 221
|
||||
|
||||
doc/bashref.texi
|
||||
- document posix-mode effects of Posix interp 221
|
||||
- add section describing GNU parallel as requested by Stallman
|
||||
|
||||
lib/readline/complete.c
|
||||
- broke code that compares filenames read from the file system (and
|
||||
possibly converted) to words being completed out into a separate
|
||||
function: complete_fncmp
|
||||
- augment complete_fncmp to treat hyphen and underscore as equivalent
|
||||
when comparing filenames if _rl_completion_case_map is set
|
||||
|
||||
lib/readline/rlprivate.h
|
||||
- new extern declaration for _rl_completion_case_map
|
||||
|
||||
lib/readline/util.c
|
||||
- change _rl_strnicmp to return the difference between the characters,
|
||||
like strcasecmp, and not modify the pointers it is passed
|
||||
- change _rl_stricmp to not modify the pointers it is passed
|
||||
|
||||
lib/readline/bind.c
|
||||
- new bindable variable, "completion-case-map", toggles value of
|
||||
_rl_completion_case_map
|
||||
|
||||
lib/readline/doc/{rluser.texi,readline.3}
|
||||
- document new bindable readline variable "completion-case-map"
|
||||
|
||||
execute_cmd.c
|
||||
- change execute_function to reset funcnest and jump back to top level
|
||||
if funcnest exceeds funcnest_max
|
||||
- use funcnest_max as a max function nesting level, if set to numeric
|
||||
value greater than 0 (defaults to 0, so inactive)
|
||||
|
||||
variables.c
|
||||
- new variable FUNCNEST, controls funcnest_max value if set to numeric
|
||||
value > 0
|
||||
sig.c
|
||||
- reset funcnest to 0 when throw_to_top_level occurs
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document FUNCNEST variable and its effect on function execution
|
||||
|
||||
lib/readline/funmap.c
|
||||
- add new bindable command names to avoid case-insensitive matching
|
||||
problems between, for instance, vi-fword and vi-fWord:
|
||||
|
||||
vi-forward-word
|
||||
vi-forward-bigword
|
||||
vi-backward-word
|
||||
vi-backward-bigword
|
||||
vi-end-word
|
||||
vi-end-bigword
|
||||
|
||||
Suggested in a different form in 2006 (!) by Servatius Brandt
|
||||
<servatius.brandt@arcor.de>
|
||||
|
||||
builtins/mapfile.def
|
||||
- run_callback now takes a new third argument: curline, the line
|
||||
currently being read and about to be assigned
|
||||
- the callback function/command now takes an additional argument:
|
||||
the line to be assigned to the array index. Feature suggested by
|
||||
Dennis Williamson <dennistwilliamson@gmail.com>
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document new additional `line' argument to mapfile callback
|
||||
|
||||
5/30
|
||||
----
|
||||
builtins/printf.def
|
||||
- add new %(fmt)T format specifier, where FMT is a strftime format.
|
||||
Argument is number of seconds since the epoch, with -1 meaning
|
||||
current time (roughly date +%s) and -2 meaning shell start time
|
||||
(roughly $SECONDS, unless it's been assigned a value or unset).
|
||||
Fieldwidth and precision are preserved, strftime result is printed
|
||||
as with %[-][[fieldwidth][.[precision]]]s
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document new %(datefmt)T printf format specifier and special
|
||||
arguments
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* sigs - print signal dispositions for a process */
|
||||
|
||||
/* Copyright (C) 1990-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1990-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern char *sys_siglist[];
|
||||
extern const char * const sys_siglist[];
|
||||
|
||||
typedef void sighandler();
|
||||
|
||||
|
||||
@@ -799,6 +799,7 @@ tests/comsub-eof.right f
|
||||
tests/comsub-posix.tests f
|
||||
tests/comsub-posix.right f
|
||||
tests/comsub-posix1.sub f
|
||||
tests/comsub-posix2.sub f
|
||||
tests/cond.tests f
|
||||
tests/cond.right f
|
||||
tests/cond-regexp.sub f
|
||||
@@ -855,6 +856,7 @@ tests/func.right f
|
||||
tests/func1.sub f
|
||||
tests/func2.sub f
|
||||
tests/func3.sub f
|
||||
tests/func4.sub f
|
||||
tests/getopts.tests f
|
||||
tests/getopts.right f
|
||||
tests/getopts1.sub f
|
||||
@@ -932,13 +934,17 @@ tests/nquote5.tests f
|
||||
tests/nquote5.right f
|
||||
tests/posix2.tests f
|
||||
tests/posix2.right f
|
||||
tests/posixexp.tests f
|
||||
tests/posixexp.right f
|
||||
tests/posixpat.tests f
|
||||
tests/posixpat.right f
|
||||
tests/prec.right f
|
||||
tests/precedence f
|
||||
tests/printf.tests f
|
||||
tests/printf.right f
|
||||
tests/printf1.sub f
|
||||
tests/printf2.sub f
|
||||
tests/printf3.sub f
|
||||
tests/quote.tests f
|
||||
tests/quote.right f
|
||||
tests/read.tests f
|
||||
@@ -1021,6 +1027,7 @@ tests/run-nquote3 f
|
||||
tests/run-nquote4 f
|
||||
tests/run-nquote5 f
|
||||
tests/run-posix2 f
|
||||
tests/run-posixexp f
|
||||
tests/run-posixpat f
|
||||
tests/run-precedence f
|
||||
tests/run-printf f
|
||||
|
||||
@@ -436,6 +436,7 @@ lib/sh/timeval.c f
|
||||
lib/sh/tmpfile.c f
|
||||
lib/sh/uconvert.c f
|
||||
lib/sh/ufuncs.c f
|
||||
lib/sh/unicode.c f
|
||||
lib/sh/vprint.c f
|
||||
lib/sh/wcsdup.c f
|
||||
lib/sh/winsize.c f
|
||||
@@ -798,6 +799,7 @@ tests/comsub-eof.right f
|
||||
tests/comsub-posix.tests f
|
||||
tests/comsub-posix.right f
|
||||
tests/comsub-posix1.sub f
|
||||
tests/comsub-posix2.sub f
|
||||
tests/cond.tests f
|
||||
tests/cond.right f
|
||||
tests/cond-regexp.sub f
|
||||
@@ -854,6 +856,7 @@ tests/func.right f
|
||||
tests/func1.sub f
|
||||
tests/func2.sub f
|
||||
tests/func3.sub f
|
||||
tests/func4.sub f
|
||||
tests/getopts.tests f
|
||||
tests/getopts.right f
|
||||
tests/getopts1.sub f
|
||||
@@ -931,6 +934,8 @@ tests/nquote5.tests f
|
||||
tests/nquote5.right f
|
||||
tests/posix2.tests f
|
||||
tests/posix2.right f
|
||||
tests/posixexp.tests f
|
||||
tests/posixexp.right f
|
||||
tests/posixpat.tests f
|
||||
tests/posixpat.right f
|
||||
tests/prec.right f
|
||||
@@ -938,6 +943,7 @@ tests/precedence f
|
||||
tests/printf.tests f
|
||||
tests/printf.right f
|
||||
tests/printf2.sub f
|
||||
tests/printf3.sub f
|
||||
tests/quote.tests f
|
||||
tests/quote.right f
|
||||
tests/read.tests f
|
||||
@@ -1020,6 +1026,7 @@ tests/run-nquote3 f
|
||||
tests/run-nquote4 f
|
||||
tests/run-nquote5 f
|
||||
tests/run-posix2 f
|
||||
tests/run-posixexp f
|
||||
tests/run-posixpat f
|
||||
tests/run-precedence f
|
||||
tests/run-printf f
|
||||
@@ -1066,6 +1073,7 @@ tests/type.tests f
|
||||
tests/type.right f
|
||||
tests/type1.sub f
|
||||
tests/type2.sub f
|
||||
tests/type3.sub f
|
||||
tests/varenv.right f
|
||||
tests/varenv.sh f
|
||||
tests/varenv1.sub f
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* arrayfunc.c -- High-level array functions used by other parts of the shell. */
|
||||
|
||||
/* Copyright (C) 2001-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2001-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+2
-2
@@ -883,7 +883,7 @@ array_value_internal (s, quoted, allow_all, rtype, indp)
|
||||
err_badarraysub (s);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
else if (var == 0 || value_cell (var) == 0)
|
||||
else if (var == 0 || value_cell (var) == 0) /* XXX - check for invisible_p(var) ? */
|
||||
return ((char *)NULL);
|
||||
else if (array_p (var) == 0 && assoc_p (var) == 0)
|
||||
l = add_string_to_list (value_cell (var), (WORD_LIST *)NULL);
|
||||
@@ -943,7 +943,7 @@ index_error:
|
||||
goto index_error;
|
||||
}
|
||||
|
||||
if (var == 0)
|
||||
if (var == 0 || value_cell (var) == 0) /* XXX - check invisible_p(var) ? */
|
||||
return ((char *)NULL);
|
||||
if (array_p (var) == 0 && assoc_p (var) == 0)
|
||||
return (ind == 0 ? value_cell (var) : (char *)NULL);
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* arrayfunc.h -- declarations for miscellaneous array functions in arrayfunc.c */
|
||||
|
||||
/* Copyright (C) 2001-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2001-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ extern void print_assoc_assignment __P((SHELL_VAR *, int));
|
||||
|
||||
extern arrayind_t array_expand_index __P((char *, int));
|
||||
extern int valid_array_reference __P((char *));
|
||||
extern char *array_value __P((char *, int, int *));
|
||||
extern char *array_value __P((char *, int, int *, arrayind_t *));
|
||||
extern char *get_array_value __P((char *, int, int *, arrayind_t *));
|
||||
|
||||
extern char *array_keys __P((char *, int));
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* bashhist.c -- bash interface to the GNU history library. */
|
||||
|
||||
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -733,7 +733,6 @@ bash_add_history (line)
|
||||
if (command_oriented_history && current_command_line_count > 1)
|
||||
{
|
||||
chars_to_add = literal_history ? "\n" : history_delimiting_chars (line);
|
||||
itrace("bash_add_history: `%s' PST_HEREDOC = %d chars_to_add = `%s'", line, (parser_state&PST_HEREDOC), chars_to_add);
|
||||
|
||||
using_history ();
|
||||
current = previous_history ();
|
||||
@@ -753,14 +752,12 @@ itrace("bash_add_history: `%s' PST_HEREDOC = %d chars_to_add = `%s'", line, (par
|
||||
chars_to_add = "";
|
||||
}
|
||||
|
||||
#if 1 /* XXX - bash-4.2 */
|
||||
/* 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++;
|
||||
#endif
|
||||
|
||||
new_line = (char *)xmalloc (1
|
||||
+ curlen
|
||||
|
||||
+18
-1
@@ -1,6 +1,6 @@
|
||||
/* bashline.c -- Bash's interface to the readline library. */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -2876,12 +2876,15 @@ dynamic_complete_history (count, key)
|
||||
int r;
|
||||
rl_compentry_func_t *orig_func;
|
||||
rl_completion_func_t *orig_attempt_func;
|
||||
rl_compignore_func_t *orig_ignore_func;
|
||||
|
||||
orig_func = rl_completion_entry_function;
|
||||
orig_attempt_func = rl_attempted_completion_function;
|
||||
orig_ignore_func = rl_ignore_some_completions_function;
|
||||
|
||||
rl_completion_entry_function = history_completion_generator;
|
||||
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
|
||||
rl_ignore_some_completions_function = filename_completion_ignore;
|
||||
|
||||
/* XXX - use rl_completion_mode here? */
|
||||
if (rl_last_func == dynamic_complete_history)
|
||||
@@ -2891,6 +2894,8 @@ dynamic_complete_history (count, key)
|
||||
|
||||
rl_completion_entry_function = orig_func;
|
||||
rl_attempted_completion_function = orig_attempt_func;
|
||||
rl_ignore_some_completions_function = orig_ignore_func;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -2901,14 +2906,17 @@ bash_dabbrev_expand (count, key)
|
||||
int r, orig_suppress, orig_sort;
|
||||
rl_compentry_func_t *orig_func;
|
||||
rl_completion_func_t *orig_attempt_func;
|
||||
rl_compignore_func_t *orig_ignore_func;
|
||||
|
||||
orig_func = rl_menu_completion_entry_function;
|
||||
orig_attempt_func = rl_attempted_completion_function;
|
||||
orig_ignore_func = rl_ignore_some_completions_function;
|
||||
orig_suppress = rl_completion_suppress_append;
|
||||
orig_sort = rl_sort_completion_matches;
|
||||
|
||||
rl_menu_completion_entry_function = history_completion_generator;
|
||||
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
|
||||
rl_ignore_some_completions_function = filename_completion_ignore;
|
||||
rl_filename_completion_desired = 0;
|
||||
rl_completion_suppress_append = 1;
|
||||
rl_sort_completion_matches = 0;
|
||||
@@ -2923,6 +2931,7 @@ bash_dabbrev_expand (count, key)
|
||||
rl_last_func = bash_dabbrev_expand;
|
||||
rl_menu_completion_entry_function = orig_func;
|
||||
rl_attempted_completion_function = orig_attempt_func;
|
||||
rl_ignore_some_completions_function = orig_ignore_func;
|
||||
rl_completion_suppress_append = orig_suppress;
|
||||
rl_sort_completion_matches = orig_sort;
|
||||
|
||||
@@ -2972,16 +2981,19 @@ bash_complete_filename_internal (what_to_do)
|
||||
rl_compentry_func_t *orig_func;
|
||||
rl_completion_func_t *orig_attempt_func;
|
||||
rl_icppfunc_t *orig_dir_func;
|
||||
rl_compignore_func_t *orig_ignore_func;
|
||||
/*const*/ char *orig_rl_completer_word_break_characters;
|
||||
int r;
|
||||
|
||||
orig_func = rl_completion_entry_function;
|
||||
orig_attempt_func = rl_attempted_completion_function;
|
||||
orig_dir_func = rl_directory_completion_hook;
|
||||
orig_ignore_func = rl_ignore_some_completions_function;
|
||||
orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
|
||||
rl_completion_entry_function = rl_filename_completion_function;
|
||||
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
|
||||
rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
|
||||
rl_ignore_some_completions_function = filename_completion_ignore;
|
||||
rl_completer_word_break_characters = " \t\n\"\'";
|
||||
|
||||
r = rl_complete_internal (what_to_do);
|
||||
@@ -2989,6 +3001,7 @@ bash_complete_filename_internal (what_to_do)
|
||||
rl_completion_entry_function = orig_func;
|
||||
rl_attempted_completion_function = orig_attempt_func;
|
||||
rl_directory_completion_hook = orig_dir_func;
|
||||
rl_ignore_some_completions_function = orig_ignore_func;
|
||||
rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
|
||||
|
||||
return r;
|
||||
@@ -3166,17 +3179,21 @@ bash_specific_completion (what_to_do, generator)
|
||||
{
|
||||
rl_compentry_func_t *orig_func;
|
||||
rl_completion_func_t *orig_attempt_func;
|
||||
rl_compignore_func_t *orig_ignore_func;
|
||||
int r;
|
||||
|
||||
orig_func = rl_completion_entry_function;
|
||||
orig_attempt_func = rl_attempted_completion_function;
|
||||
orig_ignore_func = rl_ignore_some_completions_function;
|
||||
rl_completion_entry_function = generator;
|
||||
rl_attempted_completion_function = NULL;
|
||||
rl_ignore_some_completions_function = orig_ignore_func;
|
||||
|
||||
r = rl_complete_internal (what_to_do);
|
||||
|
||||
rl_completion_entry_function = orig_func;
|
||||
rl_attempted_completion_function = orig_attempt_func;
|
||||
rl_ignore_some_completions_function = orig_ignore_func;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
+21
-4
@@ -175,7 +175,7 @@ static char **prog_complete_matches;
|
||||
extern int hist_verify;
|
||||
#endif
|
||||
|
||||
extern int current_command_line_count, fc_command_line_count;
|
||||
extern int current_command_line_count, saved_command_line_count;
|
||||
extern int last_command_exit_value;
|
||||
extern int array_needs_making;
|
||||
extern int posixly_correct, no_symbolic_links;
|
||||
@@ -863,11 +863,11 @@ edit_and_execute_command (count, c, editing_mode, edit_command)
|
||||
char *edit_command;
|
||||
{
|
||||
char *command, *metaval;
|
||||
int r, cclc, rrs, metaflag;
|
||||
int r, rrs, metaflag;
|
||||
sh_parser_state_t ps;
|
||||
|
||||
rrs = rl_readline_state;
|
||||
cclc = current_command_line_count;
|
||||
saved_command_line_count = current_command_line_count;
|
||||
|
||||
/* Accept the current line. */
|
||||
rl_newline (1, c);
|
||||
@@ -907,7 +907,7 @@ edit_and_execute_command (count, c, editing_mode, edit_command)
|
||||
if (rl_prep_term_function)
|
||||
(*rl_prep_term_function) (metaflag);
|
||||
|
||||
current_command_line_count = cclc;
|
||||
current_command_line_count = saved_command_line_count;
|
||||
|
||||
/* Now erase the contents of the current line and undo the effects of the
|
||||
rl_accept_line() above. We don't even want to make the text we just
|
||||
@@ -2876,12 +2876,15 @@ dynamic_complete_history (count, key)
|
||||
int r;
|
||||
rl_compentry_func_t *orig_func;
|
||||
rl_completion_func_t *orig_attempt_func;
|
||||
rl_compignore_func_t *orig_ignore_func;
|
||||
|
||||
orig_func = rl_completion_entry_function;
|
||||
orig_attempt_func = rl_attempted_completion_function;
|
||||
orig_ignore_func = rl_ignore_some_completions_function;
|
||||
|
||||
rl_completion_entry_function = history_completion_generator;
|
||||
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
|
||||
rl_ignore_some_completions_function = filename_completion_ignore;
|
||||
|
||||
/* XXX - use rl_completion_mode here? */
|
||||
if (rl_last_func == dynamic_complete_history)
|
||||
@@ -2891,6 +2894,8 @@ dynamic_complete_history (count, key)
|
||||
|
||||
rl_completion_entry_function = orig_func;
|
||||
rl_attempted_completion_function = orig_attempt_func;
|
||||
rl_ignore_some_completions_function = orig_ignore_func;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -2901,14 +2906,17 @@ bash_dabbrev_expand (count, key)
|
||||
int r, orig_suppress, orig_sort;
|
||||
rl_compentry_func_t *orig_func;
|
||||
rl_completion_func_t *orig_attempt_func;
|
||||
rl_compignore_func_t *orig_ignore_func;
|
||||
|
||||
orig_func = rl_menu_completion_entry_function;
|
||||
orig_attempt_func = rl_attempted_completion_function;
|
||||
orig_ignore_func = rl_ignore_some_completions_function;
|
||||
orig_suppress = rl_completion_suppress_append;
|
||||
orig_sort = rl_sort_completion_matches;
|
||||
|
||||
rl_menu_completion_entry_function = history_completion_generator;
|
||||
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
|
||||
rl_ignore_some_completions_function = filename_completion_ignore;
|
||||
rl_filename_completion_desired = 0;
|
||||
rl_completion_suppress_append = 1;
|
||||
rl_sort_completion_matches = 0;
|
||||
@@ -2923,6 +2931,7 @@ bash_dabbrev_expand (count, key)
|
||||
rl_last_func = bash_dabbrev_expand;
|
||||
rl_menu_completion_entry_function = orig_func;
|
||||
rl_attempted_completion_function = orig_attempt_func;
|
||||
rl_ignore_some_completions_function = orig_ignore_func;
|
||||
rl_completion_suppress_append = orig_suppress;
|
||||
rl_sort_completion_matches = orig_sort;
|
||||
|
||||
@@ -2972,16 +2981,19 @@ bash_complete_filename_internal (what_to_do)
|
||||
rl_compentry_func_t *orig_func;
|
||||
rl_completion_func_t *orig_attempt_func;
|
||||
rl_icppfunc_t *orig_dir_func;
|
||||
rl_compignore_func_t *orig_ignore_func;
|
||||
/*const*/ char *orig_rl_completer_word_break_characters;
|
||||
int r;
|
||||
|
||||
orig_func = rl_completion_entry_function;
|
||||
orig_attempt_func = rl_attempted_completion_function;
|
||||
orig_dir_func = rl_directory_completion_hook;
|
||||
orig_ignore_func = rl_ignore_some_completions_function;
|
||||
orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
|
||||
rl_completion_entry_function = rl_filename_completion_function;
|
||||
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
|
||||
rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
|
||||
rl_ignore_some_completions_function = filename_completion_ignore;
|
||||
rl_completer_word_break_characters = " \t\n\"\'";
|
||||
|
||||
r = rl_complete_internal (what_to_do);
|
||||
@@ -2989,6 +3001,7 @@ bash_complete_filename_internal (what_to_do)
|
||||
rl_completion_entry_function = orig_func;
|
||||
rl_attempted_completion_function = orig_attempt_func;
|
||||
rl_directory_completion_hook = orig_dir_func;
|
||||
rl_ignore_some_completions_function = orig_ignore_func;
|
||||
rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
|
||||
|
||||
return r;
|
||||
@@ -3166,17 +3179,21 @@ bash_specific_completion (what_to_do, generator)
|
||||
{
|
||||
rl_compentry_func_t *orig_func;
|
||||
rl_completion_func_t *orig_attempt_func;
|
||||
rl_compignore_func_t *orig_ignore_func;
|
||||
int r;
|
||||
|
||||
orig_func = rl_completion_entry_function;
|
||||
orig_attempt_func = rl_attempted_completion_function;
|
||||
orig_ignore_func = rl_ignore_some_completions_function;
|
||||
rl_completion_entry_function = generator;
|
||||
rl_attempted_completion_function = NULL;
|
||||
rl_ignore_some_completions_function = orig_ignore_func;
|
||||
|
||||
r = rl_complete_internal (what_to_do);
|
||||
|
||||
rl_completion_entry_function = orig_func;
|
||||
rl_attempted_completion_function = orig_attempt_func;
|
||||
rl_ignore_some_completions_function = orig_ignore_func;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
This file is cd.def, from which is created cd.c. It implements the
|
||||
builtins "cd" and "pwd" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -0,0 +1,513 @@
|
||||
This file is cd.def, from which is created cd.c. It implements the
|
||||
builtins "cd" and "pwd" 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 cd.c
|
||||
#include <config.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "../bashtypes.h"
|
||||
#include "posixdir.h"
|
||||
#include "posixstat.h"
|
||||
#ifndef _MINIX
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../bashansi.h"
|
||||
#include "../bashintl.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <tilde/tilde.h>
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../flags.h"
|
||||
#include "maxpath.h"
|
||||
#include "common.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
extern int posixly_correct;
|
||||
extern int array_needs_making;
|
||||
extern const char * const bash_getcwd_errstr;
|
||||
|
||||
static int bindpwd __P((int));
|
||||
static void setpwd __P((char *));
|
||||
static char *resetpwd __P((char *));
|
||||
static int change_to_directory __P((char *, int));
|
||||
|
||||
/* Change this to 1 to get cd spelling correction by default. */
|
||||
int cdspelling = 0;
|
||||
|
||||
int cdable_vars;
|
||||
|
||||
$BUILTIN cd
|
||||
$FUNCTION cd_builtin
|
||||
$SHORT_DOC cd [-L|-P] [dir]
|
||||
Change the shell working directory.
|
||||
|
||||
Change the current directory to DIR. The default DIR is the value of the
|
||||
HOME shell variable.
|
||||
|
||||
The variable CDPATH defines the search path for the directory containing
|
||||
DIR. Alternative directory names in CDPATH are separated by a colon (:).
|
||||
A null directory name is the same as the current directory. If DIR begins
|
||||
with a slash (/), then CDPATH is not used.
|
||||
|
||||
If the directory is not found, and the shell option `cdable_vars' is set,
|
||||
the word is assumed to be a variable name. If that variable has a value,
|
||||
its value is used for DIR.
|
||||
|
||||
Options:
|
||||
-L force symbolic links to be followed
|
||||
-P use the physical directory structure without following symbolic
|
||||
links
|
||||
|
||||
The default is to follow symbolic links, as if `-L' were specified.
|
||||
|
||||
Exit Status:
|
||||
Returns 0 if the directory is changed; non-zero otherwise.
|
||||
$END
|
||||
|
||||
/* Just set $PWD, don't change OLDPWD. Used by `pwd -P' in posix mode. */
|
||||
static void
|
||||
setpwd (dirname)
|
||||
char *dirname;
|
||||
{
|
||||
int old_anm;
|
||||
SHELL_VAR *tvar;
|
||||
|
||||
old_anm = array_needs_making;
|
||||
tvar = bind_variable ("PWD", dirname ? dirname : "", 0);
|
||||
if (old_anm == 0 && array_needs_making && exported_p (tvar))
|
||||
{
|
||||
update_export_env_inplace ("PWD=", 4, dirname ? dirname : "");
|
||||
array_needs_making = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
bindpwd (no_symlinks)
|
||||
int no_symlinks;
|
||||
{
|
||||
char *dirname, *pwdvar;
|
||||
int old_anm, r;
|
||||
SHELL_VAR *tvar;
|
||||
|
||||
r = sh_chkwrite (EXECUTION_SUCCESS);
|
||||
|
||||
#define tcwd the_current_working_directory
|
||||
dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd)
|
||||
: get_working_directory ("cd");
|
||||
#undef tcwd
|
||||
|
||||
old_anm = array_needs_making;
|
||||
pwdvar = get_string_value ("PWD");
|
||||
|
||||
tvar = bind_variable ("OLDPWD", pwdvar, 0);
|
||||
if (old_anm == 0 && array_needs_making && exported_p (tvar))
|
||||
{
|
||||
update_export_env_inplace ("OLDPWD=", 7, pwdvar);
|
||||
array_needs_making = 0;
|
||||
}
|
||||
|
||||
setpwd (dirname);
|
||||
|
||||
if (dirname && dirname != the_current_working_directory)
|
||||
free (dirname);
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
/* Call get_working_directory to reset the value of
|
||||
the_current_working_directory () */
|
||||
static char *
|
||||
resetpwd (caller)
|
||||
char *caller;
|
||||
{
|
||||
char *tdir;
|
||||
|
||||
FREE (the_current_working_directory);
|
||||
the_current_working_directory = (char *)NULL;
|
||||
tdir = get_working_directory (caller);
|
||||
return (tdir);
|
||||
}
|
||||
|
||||
#define LCD_DOVARS 0x001
|
||||
#define LCD_DOSPELL 0x002
|
||||
#define LCD_PRINTPATH 0x004
|
||||
#define LCD_FREEDIRNAME 0x008
|
||||
|
||||
/* This builtin is ultimately the way that all user-visible commands should
|
||||
change the current working directory. It is called by cd_to_string (),
|
||||
so the programming interface is simple, and it handles errors and
|
||||
restrictions properly. */
|
||||
int
|
||||
cd_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
char *dirname, *cdpath, *path, *temp;
|
||||
int path_index, no_symlinks, opt, lflag;
|
||||
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
if (restricted)
|
||||
{
|
||||
sh_restricted ((char *)NULL);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
#endif /* RESTRICTED_SHELL */
|
||||
|
||||
no_symlinks = no_symbolic_links;
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "LP")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'P':
|
||||
no_symlinks = 1;
|
||||
break;
|
||||
case 'L':
|
||||
no_symlinks = 0;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
lflag = (cdable_vars ? LCD_DOVARS : 0) |
|
||||
((interactive && cdspelling) ? LCD_DOSPELL : 0);
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
/* `cd' without arguments is equivalent to `cd $HOME' */
|
||||
dirname = get_string_value ("HOME");
|
||||
|
||||
if (dirname == 0)
|
||||
{
|
||||
builtin_error (_("HOME not set"));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
lflag = 0;
|
||||
}
|
||||
else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
|
||||
{
|
||||
/* This is `cd -', equivalent to `cd $OLDPWD' */
|
||||
dirname = get_string_value ("OLDPWD");
|
||||
|
||||
if (dirname == 0)
|
||||
{
|
||||
builtin_error (_("OLDPWD not set"));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
#if 0
|
||||
lflag = interactive ? LCD_PRINTPATH : 0;
|
||||
#else
|
||||
lflag = LCD_PRINTPATH; /* According to SUSv3 */
|
||||
#endif
|
||||
}
|
||||
else if (absolute_pathname (list->word->word))
|
||||
dirname = list->word->word;
|
||||
else if (privileged_mode == 0 && (cdpath = get_string_value ("CDPATH")))
|
||||
{
|
||||
dirname = list->word->word;
|
||||
|
||||
/* Find directory in $CDPATH. */
|
||||
path_index = 0;
|
||||
while (path = extract_colon_unit (cdpath, &path_index))
|
||||
{
|
||||
/* OPT is 1 if the path element is non-empty */
|
||||
opt = path[0] != '\0';
|
||||
temp = sh_makepath (path, dirname, MP_DOTILDE);
|
||||
free (path);
|
||||
|
||||
if (change_to_directory (temp, no_symlinks))
|
||||
{
|
||||
/* POSIX.2 says that if a nonempty directory from CDPATH
|
||||
is used to find the directory to change to, the new
|
||||
directory name is echoed to stdout, whether or not
|
||||
the shell is interactive. */
|
||||
if (opt && (path = no_symlinks ? temp : the_current_working_directory))
|
||||
printf ("%s\n", path);
|
||||
|
||||
free (temp);
|
||||
#if 0
|
||||
/* Posix.2 says that after using CDPATH, the resultant
|
||||
value of $PWD will not contain `.' or `..'. */
|
||||
return (bindpwd (posixly_correct || no_symlinks));
|
||||
#else
|
||||
return (bindpwd (no_symlinks));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
free (temp);
|
||||
}
|
||||
|
||||
/* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
|
||||
try the current directory, so we just punt now with an error
|
||||
message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
|
||||
is so we don't mistakenly treat a CDPATH value of "" as not
|
||||
specifying the current directory. */
|
||||
if (posixly_correct && cdpath[0])
|
||||
{
|
||||
builtin_error ("%s: %s", dirname, strerror (ENOENT));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
dirname = list->word->word;
|
||||
|
||||
/* When we get here, DIRNAME is the directory to change to. If we
|
||||
chdir successfully, just return. */
|
||||
if (change_to_directory (dirname, no_symlinks))
|
||||
{
|
||||
if (lflag & LCD_PRINTPATH)
|
||||
printf ("%s\n", dirname);
|
||||
return (bindpwd (no_symlinks));
|
||||
}
|
||||
|
||||
/* If the user requests it, then perhaps this is the name of
|
||||
a shell variable, whose value contains the directory to
|
||||
change to. */
|
||||
if (lflag & LCD_DOVARS)
|
||||
{
|
||||
temp = get_string_value (dirname);
|
||||
if (temp && change_to_directory (temp, no_symlinks))
|
||||
{
|
||||
printf ("%s\n", temp);
|
||||
return (bindpwd (no_symlinks));
|
||||
}
|
||||
}
|
||||
|
||||
/* If the user requests it, try to find a directory name similar in
|
||||
spelling to the one requested, in case the user made a simple
|
||||
typo. This is similar to the UNIX 8th and 9th Edition shells. */
|
||||
if (lflag & LCD_DOSPELL)
|
||||
{
|
||||
temp = dirspell (dirname);
|
||||
if (temp && change_to_directory (temp, no_symlinks))
|
||||
{
|
||||
printf ("%s\n", temp);
|
||||
return (bindpwd (no_symlinks));
|
||||
}
|
||||
else
|
||||
FREE (temp);
|
||||
}
|
||||
|
||||
builtin_error ("%s: %s", dirname, strerror (errno));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
$BUILTIN pwd
|
||||
$FUNCTION pwd_builtin
|
||||
$SHORT_DOC pwd [-LP]
|
||||
Print the name of the current working directory.
|
||||
|
||||
Options:
|
||||
-L print the value of $PWD if it names the current working
|
||||
directory
|
||||
-P print the physical directory, without any symbolic links
|
||||
|
||||
By default, `pwd' behaves as if `-L' were specified.
|
||||
|
||||
Exit Status:
|
||||
Returns 0 unless an invalid option is given or the current directory
|
||||
cannot be read.
|
||||
$END
|
||||
|
||||
/* Non-zero means that pwd always prints the physical directory, without
|
||||
symbolic links. */
|
||||
static int verbatim_pwd;
|
||||
|
||||
/* Print the name of the current working directory. */
|
||||
int
|
||||
pwd_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
char *directory;
|
||||
int opt, pflag;
|
||||
|
||||
verbatim_pwd = no_symbolic_links;
|
||||
pflag = 0;
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "LP")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'P':
|
||||
verbatim_pwd = pflag = 1;
|
||||
break;
|
||||
case 'L':
|
||||
verbatim_pwd = 0;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
#define tcwd the_current_working_directory
|
||||
|
||||
directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd)
|
||||
: get_working_directory ("pwd");
|
||||
|
||||
/* Try again using getcwd() if canonicalization fails (for instance, if
|
||||
the file system has changed state underneath bash). */
|
||||
if ((tcwd && directory == 0) ||
|
||||
(posixly_correct && same_file (".", tcwd, (struct stat *)0, (struct stat *)0) == 0))
|
||||
directory = resetpwd ("pwd");
|
||||
|
||||
#undef tcwd
|
||||
|
||||
if (directory)
|
||||
{
|
||||
printf ("%s\n", directory);
|
||||
/* This is dumb but posix-mandated. */
|
||||
if (posixly_correct && pflag)
|
||||
setpwd (directory);
|
||||
if (directory != the_current_working_directory)
|
||||
free (directory);
|
||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
||||
}
|
||||
else
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
/* Do the work of changing to the directory NEWDIR. Handle symbolic
|
||||
link following, etc. This function *must* return with
|
||||
the_current_working_directory either set to NULL (in which case
|
||||
getcwd() will eventually be called), or set to a string corresponding
|
||||
to the working directory. Return 1 on success, 0 on failure. */
|
||||
|
||||
static int
|
||||
change_to_directory (newdir, nolinks)
|
||||
char *newdir;
|
||||
int nolinks;
|
||||
{
|
||||
char *t, *tdir;
|
||||
int err, canon_failed, r, ndlen, dlen;
|
||||
|
||||
tdir = (char *)NULL;
|
||||
|
||||
if (the_current_working_directory == 0)
|
||||
{
|
||||
t = get_working_directory ("chdir");
|
||||
FREE (t);
|
||||
}
|
||||
|
||||
t = make_absolute (newdir, the_current_working_directory);
|
||||
|
||||
/* TDIR is either the canonicalized absolute pathname of NEWDIR
|
||||
(nolinks == 0) or the absolute physical pathname of NEWDIR
|
||||
(nolinks != 0). */
|
||||
tdir = nolinks ? sh_physpath (t, 0)
|
||||
: sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
|
||||
|
||||
ndlen = strlen (newdir);
|
||||
dlen = strlen (t);
|
||||
|
||||
/* Use the canonicalized version of NEWDIR, or, if canonicalization
|
||||
failed, use the non-canonical form. */
|
||||
canon_failed = 0;
|
||||
if (tdir && *tdir)
|
||||
free (t);
|
||||
else
|
||||
{
|
||||
FREE (tdir);
|
||||
tdir = t;
|
||||
canon_failed = 1;
|
||||
}
|
||||
|
||||
/* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
|
||||
returns NULL (because it checks the path, it will return NULL if the
|
||||
resolved path doesn't exist), fail immediately. */
|
||||
if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX))
|
||||
{
|
||||
#if defined ENAMETOOLONG
|
||||
if (errno != ENOENT && errno != ENAMETOOLONG)
|
||||
#else
|
||||
if (errno != ENOENT)
|
||||
#endif
|
||||
errno = ENOTDIR;
|
||||
free (tdir);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* If the chdir succeeds, update the_current_working_directory. */
|
||||
if (chdir (nolinks ? newdir : tdir) == 0)
|
||||
{
|
||||
/* If canonicalization failed, but the chdir succeeded, reset the
|
||||
shell's idea of the_current_working_directory. */
|
||||
if (canon_failed)
|
||||
{
|
||||
t = resetpwd ("cd");
|
||||
if (t == 0)
|
||||
set_working_directory (tdir);
|
||||
}
|
||||
else
|
||||
set_working_directory (tdir);
|
||||
|
||||
free (tdir);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* We failed to change to the appropriate directory name. If we tried
|
||||
what the user passed (nolinks != 0), punt now. */
|
||||
if (nolinks)
|
||||
{
|
||||
free (tdir);
|
||||
return (0);
|
||||
}
|
||||
|
||||
err = errno;
|
||||
|
||||
/* We're not in physical mode (nolinks == 0), but we failed to change to
|
||||
the canonicalized directory name (TDIR). Try what the user passed
|
||||
verbatim. If we succeed, reinitialize the_current_working_directory. */
|
||||
if (chdir (newdir) == 0)
|
||||
{
|
||||
t = resetpwd ("cd");
|
||||
if (t == 0)
|
||||
set_working_directory (tdir);
|
||||
else
|
||||
free (t);
|
||||
|
||||
r = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
errno = err;
|
||||
r = 0;
|
||||
}
|
||||
|
||||
free (tdir);
|
||||
return r;
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* common.c - utility functions for all builtins */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+1
-1
@@ -367,7 +367,7 @@ make_builtin_argv (list, ip)
|
||||
return argv;
|
||||
}
|
||||
|
||||
/* Remember LIST in $0 ... $9, and REST_OF_ARGS. If DESTRUCTIVE is
|
||||
/* Remember LIST in $1 ... $9, and REST_OF_ARGS. If DESTRUCTIVE is
|
||||
non-zero, then discard whatever the existing arguments are, else
|
||||
only discard the ones that are to be replaced. */
|
||||
void
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* common.h -- extern declarations for functions defined in common.c. */
|
||||
|
||||
/* Copyright (C) 1993-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/* common.h -- extern declarations for functions defined in common.c. */
|
||||
|
||||
/* Copyright (C) 1993-2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (__COMMON_H)
|
||||
# define __COMMON_H
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
#define ISOPTION(s, c) (s[0] == '-' && !s[2] && s[1] == c)
|
||||
|
||||
/* Flag values for parse_and_execute () */
|
||||
#define SEVAL_NONINT 0x001
|
||||
#define SEVAL_INTERACT 0x002
|
||||
#define SEVAL_NOHIST 0x004
|
||||
#define SEVAL_NOFREE 0x008
|
||||
#define SEVAL_RESETLINE 0x010
|
||||
#define SEVAL_PARSEONLY 0x020
|
||||
#define SEVAL_NOLONGJMP 0x040
|
||||
|
||||
/* Flags for describe_command, shared between type.def and command.def */
|
||||
#define CDESC_ALL 0x001 /* type -a */
|
||||
#define CDESC_SHORTDESC 0x002 /* command -V */
|
||||
#define CDESC_REUSABLE 0x004 /* command -v */
|
||||
#define CDESC_TYPE 0x008 /* type -t */
|
||||
#define CDESC_PATH_ONLY 0x010 /* type -p */
|
||||
#define CDESC_FORCE_PATH 0x020 /* type -ap or type -P */
|
||||
#define CDESC_NOFUNCS 0x040 /* type -f */
|
||||
#define CDESC_ABSPATH 0x080 /* convert to absolute path, no ./ */
|
||||
|
||||
/* Flags for get_job_by_name */
|
||||
#define JM_PREFIX 0x01 /* prefix of job name */
|
||||
#define JM_SUBSTRING 0x02 /* substring of job name */
|
||||
#define JM_EXACT 0x04 /* match job name exactly */
|
||||
#define JM_STOPPED 0x08 /* match stopped jobs only */
|
||||
#define JM_FIRSTMATCH 0x10 /* return first matching job */
|
||||
|
||||
/* Flags for remember_args and value of changed_dollar_vars */
|
||||
#define ARGS_NONE 0x0
|
||||
#define ARGS_INVOC 0x01
|
||||
#define ARGS_FUNC 0x02
|
||||
#define ARGS_SETBLTIN 0x04
|
||||
|
||||
/* Functions from common.c */
|
||||
extern void builtin_error __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
|
||||
extern void builtin_warning __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
|
||||
extern void builtin_usage __P((void));
|
||||
extern void no_args __P((WORD_LIST *));
|
||||
extern int no_options __P((WORD_LIST *));
|
||||
|
||||
/* common error message functions */
|
||||
extern void sh_needarg __P((char *));
|
||||
extern void sh_neednumarg __P((char *));
|
||||
extern void sh_notfound __P((char *));
|
||||
extern void sh_invalidopt __P((char *));
|
||||
extern void sh_invalidoptname __P((char *));
|
||||
extern void sh_invalidid __P((char *));
|
||||
extern void sh_invalidnum __P((char *));
|
||||
extern void sh_invalidsig __P((char *));
|
||||
extern void sh_erange __P((char *, char *));
|
||||
extern void sh_badpid __P((char *));
|
||||
extern void sh_badjob __P((char *));
|
||||
extern void sh_readonly __P((const char *));
|
||||
extern void sh_nojobs __P((char *));
|
||||
extern void sh_restricted __P((char *));
|
||||
extern void sh_notbuiltin __P((char *));
|
||||
extern void sh_wrerror __P((void));
|
||||
extern void sh_ttyerror __P((int));
|
||||
extern int sh_chkwrite __P((int));
|
||||
|
||||
extern char **make_builtin_argv __P((WORD_LIST *, int *));
|
||||
extern void remember_args __P((WORD_LIST *, int));
|
||||
|
||||
extern int dollar_vars_changed __P((void));
|
||||
extern void set_dollar_vars_unchanged __P((void));
|
||||
extern void set_dollar_vars_changed __P((void));
|
||||
|
||||
extern int get_numeric_arg __P((WORD_LIST *, int, intmax_t *));
|
||||
extern int get_exitstat __P((WORD_LIST *));
|
||||
extern int read_octal __P((char *));
|
||||
|
||||
/* Keeps track of the current working directory. */
|
||||
extern char *the_current_working_directory;
|
||||
extern char *get_working_directory __P((char *));
|
||||
extern void set_working_directory __P((char *));
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
extern int get_job_by_name __P((const char *, int));
|
||||
extern int get_job_spec __P((WORD_LIST *));
|
||||
#endif
|
||||
extern int display_signal_list __P((WORD_LIST *, int));
|
||||
|
||||
/* It's OK to declare a function as returning a Function * without
|
||||
providing a definition of what a `Function' is. */
|
||||
extern struct builtin *builtin_address_internal __P((char *, int));
|
||||
extern sh_builtin_func_t *find_shell_builtin __P((char *));
|
||||
extern sh_builtin_func_t *builtin_address __P((char *));
|
||||
extern sh_builtin_func_t *find_special_builtin __P((char *));
|
||||
extern void initialize_shell_builtins __P((void));
|
||||
|
||||
/* Functions from exit.def */
|
||||
extern void bash_logout __P((void));
|
||||
|
||||
/* Functions from getopts.def */
|
||||
extern void getopts_reset __P((int));
|
||||
|
||||
/* Functions from set.def */
|
||||
extern int minus_o_option_value __P((char *));
|
||||
extern void list_minus_o_opts __P((int, int));
|
||||
extern char **get_minus_o_opts __P((void));
|
||||
extern int set_minus_o_option __P((int, char *));
|
||||
|
||||
extern void set_shellopts __P((void));
|
||||
extern void parse_shellopts __P((char *));
|
||||
extern void initialize_shell_options __P((int));
|
||||
|
||||
extern void reset_shell_options __P((void));
|
||||
|
||||
/* Functions from shopt.def */
|
||||
extern void reset_shopt_options __P((void));
|
||||
extern char **get_shopt_options __P((void));
|
||||
|
||||
extern int shopt_setopt __P((char *, int));
|
||||
extern int shopt_listopt __P((char *, int));
|
||||
|
||||
extern int set_login_shell __P((char *, int));
|
||||
|
||||
extern void set_bashopts __P((void));
|
||||
extern void parse_bashopts __P((char *));
|
||||
extern void initialize_bashopts __P((int));
|
||||
|
||||
/* Functions from type.def */
|
||||
extern int describe_command __P((char *, int));
|
||||
|
||||
/* Functions from setattr.def */
|
||||
extern int set_or_show_attributes __P((WORD_LIST *, int, int));
|
||||
extern int show_all_var_attributes __P((int, int));
|
||||
extern int show_var_attributes __P((SHELL_VAR *, int, int));
|
||||
extern int show_name_attributes __P((char *, int));
|
||||
extern void set_var_attribute __P((char *, int, int));
|
||||
|
||||
/* Functions from pushd.def */
|
||||
extern char *get_dirstack_from_string __P((char *));
|
||||
extern char *get_dirstack_element __P((intmax_t, int));
|
||||
extern void set_dirstack_element __P((intmax_t, int, char *));
|
||||
extern WORD_LIST *get_directory_stack __P((int));
|
||||
|
||||
/* Functions from evalstring.c */
|
||||
extern int parse_and_execute __P((char *, const char *, int));
|
||||
extern void parse_and_execute_cleanup __P((void));
|
||||
extern int parse_string __P((char *, const char *, int, char **));
|
||||
|
||||
/* Functions from evalfile.c */
|
||||
extern int maybe_execute_file __P((const char *, int));
|
||||
extern int source_file __P((const char *, int));
|
||||
extern int fc_execute_file __P((const char *));
|
||||
|
||||
#endif /* !__COMMON_H */
|
||||
@@ -1,7 +1,7 @@
|
||||
This file is complete.def, from which is created complete.c.
|
||||
It implements the builtins "complete", "compgen", and "compopt" in Bash.
|
||||
|
||||
Copyright (C) 1999-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -753,7 +753,7 @@ $SHORT_DOC compopt [-o|+o option] [-DE] [name ...]
|
||||
Modify or display completion options.
|
||||
|
||||
Modify the completion options for each NAME, or, if no NAMEs are supplied,
|
||||
the completion currently begin executed. If no OPTIONs are givenm, print
|
||||
the completion currently being executed. If no OPTIONs are given, print
|
||||
the completion options for each NAME or the current completion specification.
|
||||
|
||||
Options:
|
||||
|
||||
+16
-10
@@ -1,7 +1,7 @@
|
||||
This file is declare.def, from which is created declare.c.
|
||||
It implements the builtins "declare" and "local" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -22,7 +22,7 @@ $PRODUCES declare.c
|
||||
|
||||
$BUILTIN declare
|
||||
$FUNCTION declare_builtin
|
||||
$SHORT_DOC declare [-aAfFilrtux] [-p] [name[=value] ...]
|
||||
$SHORT_DOC declare [-aAfFgilrtux] [-p] [name[=value] ...]
|
||||
Set variable values and attributes.
|
||||
|
||||
Declare variables and give them attributes. If no NAMEs are given,
|
||||
@@ -32,6 +32,8 @@ Options:
|
||||
-f restrict action or display to function names and definitions
|
||||
-F restrict display to function names only (plus line number and
|
||||
source file when debugging)
|
||||
-g create global variables when used in a shell function; otherwise
|
||||
ignored
|
||||
-p display the attributes and value of each NAME
|
||||
|
||||
Options which set attributes:
|
||||
@@ -50,7 +52,7 @@ Variables with the integer attribute have arithmetic evaluation (see
|
||||
the `let' command) performed when the variable is assigned a value.
|
||||
|
||||
When used in a function, `declare' makes NAMEs local, as with the `local'
|
||||
command.
|
||||
command. The `-g' option suppresses this behavior.
|
||||
|
||||
Exit Status:
|
||||
Returns success unless an invalid option is supplied or an error occurs.
|
||||
@@ -58,7 +60,7 @@ $END
|
||||
|
||||
$BUILTIN typeset
|
||||
$FUNCTION declare_builtin
|
||||
$SHORT_DOC typeset [-aAfFilrtux] [-p] name[=value] ...
|
||||
$SHORT_DOC typeset [-aAfFgilrtux] [-p] name[=value] ...
|
||||
Set variable values and attributes.
|
||||
|
||||
Obsolete. See `help declare'.
|
||||
@@ -125,9 +127,9 @@ local_builtin (list)
|
||||
}
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
# define DECLARE_OPTS "+acfilprtuxAF"
|
||||
# define DECLARE_OPTS "+acfgilprtuxAF"
|
||||
#else
|
||||
# define DECLARE_OPTS "+cfilprtuxF"
|
||||
# define DECLARE_OPTS "+cfgilprtuxF"
|
||||
#endif
|
||||
|
||||
/* The workhorse function. */
|
||||
@@ -137,12 +139,12 @@ declare_internal (list, local_var)
|
||||
int local_var;
|
||||
{
|
||||
int flags_on, flags_off, *flags;
|
||||
int any_failed, assign_error, pflag, nodefs, opt;
|
||||
int any_failed, assign_error, pflag, nodefs, opt, mkglobal;
|
||||
char *t, *subscript_start;
|
||||
SHELL_VAR *var;
|
||||
FUNCTION_DEF *shell_fn;
|
||||
|
||||
flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0;
|
||||
flags_on = flags_off = any_failed = assign_error = pflag = nodefs = mkglobal = 0;
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF)
|
||||
{
|
||||
@@ -177,6 +179,10 @@ declare_internal (list, local_var)
|
||||
case 'f':
|
||||
*flags |= att_function;
|
||||
break;
|
||||
case 'g':
|
||||
if (flags == &flags_on)
|
||||
mkglobal = 1;
|
||||
break;
|
||||
case 'i':
|
||||
*flags |= att_integer;
|
||||
break;
|
||||
@@ -328,7 +334,7 @@ declare_internal (list, local_var)
|
||||
/* XXX - this has consequences when we're making a local copy of a
|
||||
variable that was in the temporary environment. Watch out
|
||||
for this. */
|
||||
if (variable_context && ((flags_on & att_function) == 0))
|
||||
if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0))
|
||||
{
|
||||
#if defined (ARRAY_VARS)
|
||||
if (flags_on & att_assoc)
|
||||
@@ -410,7 +416,7 @@ declare_internal (list, local_var)
|
||||
{
|
||||
/* Non-null if we just created or fetched a local variable. */
|
||||
if (var == 0)
|
||||
var = find_variable (name);
|
||||
var = mkglobal ? find_global_variable (name) : find_variable (name);
|
||||
|
||||
if (var == 0)
|
||||
{
|
||||
|
||||
+16
-10
@@ -22,7 +22,7 @@ $PRODUCES declare.c
|
||||
|
||||
$BUILTIN declare
|
||||
$FUNCTION declare_builtin
|
||||
$SHORT_DOC declare [-aAfFilrtux] [-p] [name[=value] ...]
|
||||
$SHORT_DOC declare [-aAfFgilrtux] [-p] [name[=value] ...]
|
||||
Set variable values and attributes.
|
||||
|
||||
Declare variables and give them attributes. If no NAMEs are given,
|
||||
@@ -32,6 +32,8 @@ Options:
|
||||
-f restrict action or display to function names and definitions
|
||||
-F restrict display to function names only (plus line number and
|
||||
source file when debugging)
|
||||
-g create global variables when used in a shell function; otherwise
|
||||
ignored
|
||||
-p display the attributes and value of each NAME
|
||||
|
||||
Options which set attributes:
|
||||
@@ -50,7 +52,7 @@ Variables with the integer attribute have arithmetic evaluation (see
|
||||
the `let' command) performed when the variable is assigned a value.
|
||||
|
||||
When used in a function, `declare' makes NAMEs local, as with the `local'
|
||||
command.
|
||||
command. The `-g' option suppresses this behavior.
|
||||
|
||||
Exit Status:
|
||||
Returns success unless an invalid option is supplied or an error occurs.
|
||||
@@ -58,7 +60,7 @@ $END
|
||||
|
||||
$BUILTIN typeset
|
||||
$FUNCTION declare_builtin
|
||||
$SHORT_DOC typeset [-aAfFilrtux] [-p] name[=value] ...
|
||||
$SHORT_DOC typeset [-aAfFgilrtux] [-p] name[=value] ...
|
||||
Set variable values and attributes.
|
||||
|
||||
Obsolete. See `help declare'.
|
||||
@@ -125,9 +127,9 @@ local_builtin (list)
|
||||
}
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
# define DECLARE_OPTS "+acfilprtuxAF"
|
||||
# define DECLARE_OPTS "+acfgilprtuxAF"
|
||||
#else
|
||||
# define DECLARE_OPTS "+cfilprtuxF"
|
||||
# define DECLARE_OPTS "+cfgilprtuxF"
|
||||
#endif
|
||||
|
||||
/* The workhorse function. */
|
||||
@@ -137,12 +139,12 @@ declare_internal (list, local_var)
|
||||
int local_var;
|
||||
{
|
||||
int flags_on, flags_off, *flags;
|
||||
int any_failed, assign_error, pflag, nodefs, opt;
|
||||
int any_failed, assign_error, pflag, nodefs, opt, mkglobal;
|
||||
char *t, *subscript_start;
|
||||
SHELL_VAR *var;
|
||||
FUNCTION_DEF *shell_fn;
|
||||
|
||||
flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0;
|
||||
flags_on = flags_off = any_failed = assign_error = pflag = nodefs = mkglobal = 0;
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF)
|
||||
{
|
||||
@@ -177,6 +179,10 @@ declare_internal (list, local_var)
|
||||
case 'f':
|
||||
*flags |= att_function;
|
||||
break;
|
||||
case 'g':
|
||||
if (flags == &flags_on)
|
||||
mkglobal = 1;
|
||||
break;
|
||||
case 'i':
|
||||
*flags |= att_integer;
|
||||
break;
|
||||
@@ -328,7 +334,7 @@ declare_internal (list, local_var)
|
||||
/* XXX - this has consequences when we're making a local copy of a
|
||||
variable that was in the temporary environment. Watch out
|
||||
for this. */
|
||||
if (variable_context && ((flags_on & att_function) == 0))
|
||||
if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0))
|
||||
{
|
||||
#if defined (ARRAY_VARS)
|
||||
if (flags_on & att_assoc)
|
||||
@@ -410,7 +416,7 @@ declare_internal (list, local_var)
|
||||
{
|
||||
/* Non-null if we just created or fetched a local variable. */
|
||||
if (var == 0)
|
||||
var = find_variable (name);
|
||||
var = mkglobal ? find_global_variable (name) : find_variable (name);
|
||||
|
||||
if (var == 0)
|
||||
{
|
||||
@@ -512,7 +518,7 @@ declare_internal (list, local_var)
|
||||
{
|
||||
/* let bind_{array,assoc}_variable take care of this. */
|
||||
if (assoc_p (var))
|
||||
bind_assoc_variable (var, name, "0", value, aflags);
|
||||
bind_assoc_variable (var, name, savestring ("0"), value, aflags);
|
||||
else
|
||||
bind_array_variable (name, 0, value, aflags);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* evalstring.c - evaluate a string as one or more shell commands.
|
||||
|
||||
/* Copyright (C) 1996-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -331,13 +331,9 @@ parse_and_execute (string, from_file, flags)
|
||||
(this_shell_builtin == source_builtin || this_shell_builtin == eval_builtin) &&
|
||||
last_command_exit_value == EX_BADSYNTAX && posixly_correct)
|
||||
{
|
||||
#if 0 /* XXX - for bash-4.2 */
|
||||
should_jump_to_top_level = 1;
|
||||
code = ERREXIT;
|
||||
last_command_exit_value = EX_BADUSAGE;
|
||||
#else
|
||||
internal_warning (_("syntax errors in . or eval will cause future versions of the shell to abort as Posix requires"));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Since we are shell compatible, syntax errors in a script
|
||||
|
||||
@@ -0,0 +1,508 @@
|
||||
/* evalstring.c - evaluate a string as one or more shell commands.
|
||||
|
||||
/* Copyright (C) 1996-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/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "filecntl.h"
|
||||
#include "../bashansi.h"
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../jobs.h"
|
||||
#include "../builtins.h"
|
||||
#include "../flags.h"
|
||||
#include "../input.h"
|
||||
#include "../execute_cmd.h"
|
||||
#include "../redir.h"
|
||||
#include "../trap.h"
|
||||
#include "../bashintl.h"
|
||||
|
||||
#include <y.tab.h>
|
||||
|
||||
#if defined (HISTORY)
|
||||
# include "../bashhist.h"
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "builtext.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#define IS_BUILTIN(s) (builtin_address_internal(s, 0) != (struct builtin *)NULL)
|
||||
|
||||
extern int indirection_level, subshell_environment;
|
||||
extern int line_number;
|
||||
extern int current_token, shell_eof_token;
|
||||
extern int last_command_exit_value;
|
||||
extern int running_trap;
|
||||
extern int loop_level;
|
||||
extern int executing_list;
|
||||
extern int comsub_ignore_return;
|
||||
extern int posixly_correct;
|
||||
extern sh_builtin_func_t *this_shell_builtin;
|
||||
|
||||
int parse_and_execute_level = 0;
|
||||
|
||||
static int cat_file __P((REDIRECT *));
|
||||
|
||||
#define PE_TAG "parse_and_execute top"
|
||||
#define PS_TAG "parse_string top"
|
||||
|
||||
#if defined (HISTORY)
|
||||
static void
|
||||
set_history_remembering ()
|
||||
{
|
||||
remember_on_history = enable_history_list;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* How to force parse_and_execute () to clean up after itself. */
|
||||
void
|
||||
parse_and_execute_cleanup ()
|
||||
{
|
||||
if (running_trap)
|
||||
{
|
||||
run_trap_cleanup (running_trap - 1);
|
||||
unfreeze_jobs_list ();
|
||||
}
|
||||
|
||||
if (have_unwind_protects ())
|
||||
run_unwind_frame (PE_TAG);
|
||||
else
|
||||
parse_and_execute_level = 0; /* XXX */
|
||||
}
|
||||
|
||||
static void
|
||||
parse_prologue (string, flags, tag)
|
||||
char *string;
|
||||
int flags;
|
||||
char *tag;
|
||||
{
|
||||
char *orig_string;
|
||||
int x;
|
||||
|
||||
orig_string = string;
|
||||
/* Unwind protect this invocation of parse_and_execute (). */
|
||||
begin_unwind_frame (tag);
|
||||
unwind_protect_int (parse_and_execute_level);
|
||||
unwind_protect_jmp_buf (top_level);
|
||||
unwind_protect_int (indirection_level);
|
||||
unwind_protect_int (line_number);
|
||||
unwind_protect_int (loop_level);
|
||||
unwind_protect_int (executing_list);
|
||||
unwind_protect_int (comsub_ignore_return);
|
||||
if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
|
||||
unwind_protect_int (interactive);
|
||||
|
||||
#if defined (HISTORY)
|
||||
if (parse_and_execute_level == 0)
|
||||
add_unwind_protect (set_history_remembering, (char *)NULL);
|
||||
else
|
||||
unwind_protect_int (remember_on_history); /* can be used in scripts */
|
||||
# if defined (BANG_HISTORY)
|
||||
if (interactive_shell)
|
||||
unwind_protect_int (history_expansion_inhibited);
|
||||
# endif /* BANG_HISTORY */
|
||||
#endif /* HISTORY */
|
||||
|
||||
if (interactive_shell)
|
||||
{
|
||||
x = get_current_prompt_level ();
|
||||
add_unwind_protect (set_current_prompt_level, x);
|
||||
}
|
||||
|
||||
add_unwind_protect (pop_stream, (char *)NULL);
|
||||
if (orig_string && ((flags & SEVAL_NOFREE) == 0))
|
||||
add_unwind_protect (xfree, orig_string);
|
||||
end_unwind_frame ();
|
||||
|
||||
if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
|
||||
interactive = (flags & SEVAL_NONINT) ? 0 : 1;
|
||||
|
||||
#if defined (HISTORY)
|
||||
if (flags & SEVAL_NOHIST)
|
||||
bash_history_disable ();
|
||||
#endif /* HISTORY */
|
||||
}
|
||||
|
||||
/* Parse and execute the commands in STRING. Returns whatever
|
||||
execute_command () returns. This frees STRING. FLAGS is a
|
||||
flags word; look in common.h for the possible values. Actions
|
||||
are:
|
||||
(flags & SEVAL_NONINT) -> interactive = 0;
|
||||
(flags & SEVAL_INTERACT) -> interactive = 1;
|
||||
(flags & SEVAL_NOHIST) -> call bash_history_disable ()
|
||||
(flags & SEVAL_NOFREE) -> don't free STRING when finished
|
||||
(flags & SEVAL_RESETLINE) -> reset line_number to 1
|
||||
*/
|
||||
|
||||
int
|
||||
parse_and_execute (string, from_file, flags)
|
||||
char *string;
|
||||
const char *from_file;
|
||||
int flags;
|
||||
{
|
||||
int code, lreset;
|
||||
volatile int should_jump_to_top_level, last_result;
|
||||
COMMAND *volatile command;
|
||||
|
||||
parse_prologue (string, flags, PE_TAG);
|
||||
|
||||
parse_and_execute_level++;
|
||||
|
||||
lreset = flags & SEVAL_RESETLINE;
|
||||
|
||||
/* Reset the line number if the caller wants us to. If we don't reset the
|
||||
line number, we have to subtract one, because we will add one just
|
||||
before executing the next command (resetting the line number sets it to
|
||||
0; the first line number is 1). */
|
||||
push_stream (lreset);
|
||||
if (lreset == 0)
|
||||
line_number--;
|
||||
|
||||
indirection_level++;
|
||||
|
||||
code = should_jump_to_top_level = 0;
|
||||
last_result = EXECUTION_SUCCESS;
|
||||
|
||||
with_input_from_string (string, from_file);
|
||||
while (*(bash_input.location.string))
|
||||
{
|
||||
command = (COMMAND *)NULL;
|
||||
|
||||
if (interrupt_state)
|
||||
{
|
||||
last_result = EXECUTION_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Provide a location for functions which `longjmp (top_level)' to
|
||||
jump to. This prevents errors in substitution from restarting
|
||||
the reader loop directly, for example. */
|
||||
code = setjmp (top_level);
|
||||
|
||||
if (code)
|
||||
{
|
||||
should_jump_to_top_level = 0;
|
||||
switch (code)
|
||||
{
|
||||
case FORCE_EOF:
|
||||
case ERREXIT:
|
||||
case EXITPROG:
|
||||
if (command)
|
||||
run_unwind_frame ("pe_dispose");
|
||||
/* Remember to call longjmp (top_level) after the old
|
||||
value for it is restored. */
|
||||
should_jump_to_top_level = 1;
|
||||
goto out;
|
||||
|
||||
case DISCARD:
|
||||
if (command)
|
||||
run_unwind_frame ("pe_dispose");
|
||||
last_result = last_command_exit_value = EXECUTION_FAILURE; /* XXX */
|
||||
if (subshell_environment)
|
||||
{
|
||||
should_jump_to_top_level = 1;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
dispose_command (command); /* pe_dispose does this */
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
default:
|
||||
command_error ("parse_and_execute", CMDERR_BADJUMP, code, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (parse_command () == 0)
|
||||
{
|
||||
if ((flags & SEVAL_PARSEONLY) || (interactive_shell == 0 && read_but_dont_execute))
|
||||
{
|
||||
last_result = EXECUTION_SUCCESS;
|
||||
dispose_command (global_command);
|
||||
global_command = (COMMAND *)NULL;
|
||||
}
|
||||
else if (command = global_command)
|
||||
{
|
||||
struct fd_bitmap *bitmap;
|
||||
|
||||
bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
|
||||
begin_unwind_frame ("pe_dispose");
|
||||
add_unwind_protect (dispose_fd_bitmap, bitmap);
|
||||
add_unwind_protect (dispose_command, command); /* XXX */
|
||||
|
||||
global_command = (COMMAND *)NULL;
|
||||
|
||||
if ((subshell_environment & SUBSHELL_COMSUB) && comsub_ignore_return)
|
||||
command->flags |= CMD_IGNORE_RETURN;
|
||||
|
||||
#if defined (ONESHOT)
|
||||
/*
|
||||
* IF
|
||||
* we were invoked as `bash -c' (startup_state == 2) AND
|
||||
* parse_and_execute has not been called recursively AND
|
||||
* we're not running a trap AND
|
||||
* we have parsed the full command (string == '\0') AND
|
||||
* we're not going to run the exit trap AND
|
||||
* we have a simple command without redirections AND
|
||||
* the command is not being timed AND
|
||||
* the command's return status is not being inverted
|
||||
* THEN
|
||||
* tell the execution code that we don't need to fork
|
||||
*/
|
||||
if (startup_state == 2 && parse_and_execute_level == 1 &&
|
||||
running_trap == 0 &&
|
||||
*bash_input.location.string == '\0' &&
|
||||
command->type == cm_simple &&
|
||||
signal_is_trapped (EXIT_TRAP) == 0 &&
|
||||
command->redirects == 0 && command->value.Simple->redirects == 0 &&
|
||||
((command->flags & CMD_TIME_PIPELINE) == 0) &&
|
||||
((command->flags & CMD_INVERT_RETURN) == 0))
|
||||
{
|
||||
command->flags |= CMD_NO_FORK;
|
||||
command->value.Simple->flags |= CMD_NO_FORK;
|
||||
}
|
||||
#endif /* ONESHOT */
|
||||
|
||||
/* See if this is a candidate for $( <file ). */
|
||||
if (startup_state == 2 &&
|
||||
(subshell_environment & SUBSHELL_COMSUB) &&
|
||||
*bash_input.location.string == '\0' &&
|
||||
command->type == cm_simple && !command->redirects &&
|
||||
(command->flags & CMD_TIME_PIPELINE) == 0 &&
|
||||
command->value.Simple->words == 0 &&
|
||||
command->value.Simple->redirects &&
|
||||
command->value.Simple->redirects->next == 0 &&
|
||||
command->value.Simple->redirects->instruction == r_input_direction)
|
||||
{
|
||||
int r;
|
||||
r = cat_file (command->value.Simple->redirects);
|
||||
last_result = (r < 0) ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
|
||||
}
|
||||
else
|
||||
last_result = execute_command_internal
|
||||
(command, 0, NO_PIPE, NO_PIPE, bitmap);
|
||||
|
||||
dispose_command (command);
|
||||
dispose_fd_bitmap (bitmap);
|
||||
discard_unwind_frame ("pe_dispose");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
last_result = EXECUTION_FAILURE;
|
||||
|
||||
if (interactive_shell == 0 && this_shell_builtin &&
|
||||
(this_shell_builtin == source_builtin || this_shell_builtin == eval_builtin) &&
|
||||
last_command_exit_value == EX_BADSYNTAX && posixly_correct)
|
||||
{
|
||||
should_jump_to_top_level = 1;
|
||||
code = ERREXIT;
|
||||
last_command_exit_value = EX_BADUSAGE;
|
||||
}
|
||||
|
||||
/* Since we are shell compatible, syntax errors in a script
|
||||
abort the execution of the script. Right? */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
run_unwind_frame (PE_TAG);
|
||||
|
||||
if (interrupt_state && parse_and_execute_level == 0)
|
||||
{
|
||||
/* An interrupt during non-interactive execution in an
|
||||
interactive shell (e.g. via $PROMPT_COMMAND) should
|
||||
not cause the shell to exit. */
|
||||
interactive = interactive_shell;
|
||||
throw_to_top_level ();
|
||||
}
|
||||
|
||||
if (should_jump_to_top_level)
|
||||
jump_to_top_level (code);
|
||||
|
||||
return (last_result);
|
||||
}
|
||||
|
||||
/* Parse a command contained in STRING according to FLAGS and return the
|
||||
number of characters consumed from the string. If non-NULL, set *ENDP
|
||||
to the position in the string where the parse ended. Used to validate
|
||||
command substitutions during parsing to obey Posix rules about finding
|
||||
the end of the command and balancing parens. */
|
||||
int
|
||||
parse_string (string, from_file, flags, endp)
|
||||
char *string;
|
||||
const char *from_file;
|
||||
int flags;
|
||||
char **endp;
|
||||
{
|
||||
int code, nc;
|
||||
volatile int should_jump_to_top_level;
|
||||
COMMAND *volatile command, *oglobal;
|
||||
char *ostring;
|
||||
|
||||
parse_prologue (string, flags, PS_TAG);
|
||||
|
||||
/* Reset the line number if the caller wants us to. If we don't reset the
|
||||
line number, we have to subtract one, because we will add one just
|
||||
before executing the next command (resetting the line number sets it to
|
||||
0; the first line number is 1). */
|
||||
push_stream (0);
|
||||
|
||||
code = should_jump_to_top_level = 0;
|
||||
oglobal = global_command;
|
||||
ostring = string;
|
||||
|
||||
with_input_from_string (string, from_file);
|
||||
while (*(bash_input.location.string))
|
||||
{
|
||||
command = (COMMAND *)NULL;
|
||||
|
||||
#if 0
|
||||
if (interrupt_state)
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* Provide a location for functions which `longjmp (top_level)' to
|
||||
jump to. */
|
||||
code = setjmp (top_level);
|
||||
|
||||
if (code)
|
||||
{
|
||||
#if defined (DEBUG)
|
||||
itrace("parse_string: longjmp executed: code = %d", code);
|
||||
#endif
|
||||
should_jump_to_top_level = 0;
|
||||
switch (code)
|
||||
{
|
||||
case FORCE_EOF:
|
||||
case ERREXIT:
|
||||
case EXITPROG:
|
||||
case DISCARD: /* XXX */
|
||||
if (command)
|
||||
dispose_command (command);
|
||||
/* Remember to call longjmp (top_level) after the old
|
||||
value for it is restored. */
|
||||
should_jump_to_top_level = 1;
|
||||
goto out;
|
||||
|
||||
default:
|
||||
command_error ("parse_string", CMDERR_BADJUMP, code, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (parse_command () == 0)
|
||||
{
|
||||
dispose_command (global_command);
|
||||
global_command = (COMMAND *)NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((flags & SEVAL_NOLONGJMP) == 0)
|
||||
{
|
||||
should_jump_to_top_level = 1;
|
||||
code = DISCARD;
|
||||
}
|
||||
else
|
||||
reset_parser (); /* XXX - sets token_to_read */
|
||||
break;
|
||||
}
|
||||
|
||||
if (current_token == yacc_EOF || current_token == shell_eof_token)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
global_command = oglobal;
|
||||
nc = bash_input.location.string - ostring;
|
||||
if (endp)
|
||||
*endp = bash_input.location.string;
|
||||
|
||||
run_unwind_frame (PS_TAG);
|
||||
|
||||
if (should_jump_to_top_level)
|
||||
jump_to_top_level (code);
|
||||
|
||||
return (nc);
|
||||
}
|
||||
|
||||
/* Handle a $( < file ) command substitution. This expands the filename,
|
||||
returning errors as appropriate, then just cats the file to the standard
|
||||
output. */
|
||||
static int
|
||||
cat_file (r)
|
||||
REDIRECT *r;
|
||||
{
|
||||
char *fn;
|
||||
int fd, rval;
|
||||
|
||||
if (r->instruction != r_input_direction)
|
||||
return -1;
|
||||
|
||||
/* Get the filename. */
|
||||
if (posixly_correct && !interactive_shell)
|
||||
disallow_filename_globbing++;
|
||||
fn = redirection_expand (r->redirectee.filename);
|
||||
if (posixly_correct && !interactive_shell)
|
||||
disallow_filename_globbing--;
|
||||
|
||||
if (fn == 0)
|
||||
{
|
||||
redirection_error (r, AMBIGUOUS_REDIRECT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = open(fn, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
file_error (fn);
|
||||
free (fn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rval = zcatfd (fd, 1, fn);
|
||||
|
||||
free (fn);
|
||||
close (fd);
|
||||
|
||||
return (rval);
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
This file is exec.def, from which is created exec.c.
|
||||
It implements the builtin "exec" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+2
-1
@@ -164,7 +164,8 @@ exec_builtin (list)
|
||||
if (argv0)
|
||||
{
|
||||
free (args[0]);
|
||||
exec_argv0 = args[0] = login ? mkdashname (argv0) : savestring (argv0);
|
||||
args[0] = login ? mkdashname (argv0) : savestring (argv0);
|
||||
exec_argv0 = savestring (args[0]);
|
||||
}
|
||||
else if (login)
|
||||
{
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
This file is fc.def, from which is created fc.c.
|
||||
It implements the builtin "fc" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+2
-2
@@ -304,8 +304,8 @@ fc_builtin (list)
|
||||
last_hist = i - rh - hist_last_line_added;
|
||||
|
||||
/* XXX */
|
||||
if (i == last_hist && hlist[last_hist] == 0)
|
||||
while (saved_command_line_count > 0 && last_hist >= 0 && hlist[last_hist] == 0)
|
||||
if (saved_command_line_count > 0 && i == last_hist && hlist[last_hist] == 0)
|
||||
while (last_hist >= 0 && hlist[last_hist] == 0)
|
||||
last_hist--;
|
||||
if (last_hist < 0)
|
||||
{
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
This file is hash.def, from which is created hash.c.
|
||||
It implements the builtin "hash" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -159,7 +159,9 @@ hash_builtin (list)
|
||||
{
|
||||
/* Add, remove or rehash the specified commands. */
|
||||
w = list->word->word;
|
||||
if (pathname)
|
||||
if (absolute_program (w))
|
||||
continue;
|
||||
else if (pathname)
|
||||
{
|
||||
if (is_directory (pathname))
|
||||
{
|
||||
@@ -173,8 +175,6 @@ hash_builtin (list)
|
||||
else
|
||||
phash_insert (w, pathname, 0, 0);
|
||||
}
|
||||
else if (absolute_program (w))
|
||||
continue;
|
||||
else if (delete)
|
||||
{
|
||||
if (phash_remove (w))
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
This file is hash.def, from which is created hash.c.
|
||||
It implements the builtin "hash" 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 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 is 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);
|
||||
}
|
||||
}
|
||||
|
||||
return (all_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
||||
}
|
||||
+2
-4
@@ -1,7 +1,7 @@
|
||||
This file is kill.def, from which is created kill.c.
|
||||
It implements the builtin "kill" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -121,9 +121,7 @@ kill_builtin (list)
|
||||
else
|
||||
sig = decode_signal (sigspec, dflags);
|
||||
list = list->next;
|
||||
#if 0
|
||||
saw_signal++; /* XXX - for bash-4.2 */
|
||||
#endif
|
||||
saw_signal++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
This file is kill.def, from which is created kill.c.
|
||||
It implements the builtin "kill" 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 kill.c
|
||||
|
||||
$BUILTIN kill
|
||||
$FUNCTION kill_builtin
|
||||
$SHORT_DOC kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
|
||||
Send a signal to a job.
|
||||
|
||||
Send the processes identified by PID or JOBSPEC the signal named by
|
||||
SIGSPEC or SIGNUM. If neither SIGSPEC nor SIGNUM is present, then
|
||||
SIGTERM is assumed.
|
||||
|
||||
Options:
|
||||
-s sig SIG is a signal name
|
||||
-n sig SIG is a signal number
|
||||
-l list the signal names; if arguments follow `-l' they are
|
||||
assumed to be signal numbers for which names should be listed
|
||||
|
||||
Kill is a shell builtin for two reasons: it allows job IDs to be used
|
||||
instead of process IDs, and allows processes to be killed if the limit
|
||||
on processes that you can create is reached.
|
||||
|
||||
Exit Status:
|
||||
Returns success unless an invalid option is given or an error occurs.
|
||||
$END
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "../bashansi.h"
|
||||
#include "../bashintl.h"
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../trap.h"
|
||||
#include "../jobs.h"
|
||||
#include "common.h"
|
||||
|
||||
/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
extern int posixly_correct;
|
||||
|
||||
static void kill_error __P((pid_t, int));
|
||||
|
||||
#if !defined (CONTINUE_AFTER_KILL_ERROR)
|
||||
# define CONTINUE_OR_FAIL return (EXECUTION_FAILURE)
|
||||
#else
|
||||
# define CONTINUE_OR_FAIL goto continue_killing
|
||||
#endif /* CONTINUE_AFTER_KILL_ERROR */
|
||||
|
||||
/* Here is the kill builtin. We only have it so that people can type
|
||||
kill -KILL %1? No, if you fill up the process table this way you
|
||||
can still kill some. */
|
||||
int
|
||||
kill_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int sig, any_succeeded, listing, saw_signal, dflags;
|
||||
char *sigspec, *word;
|
||||
pid_t pid;
|
||||
intmax_t pid_value;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
any_succeeded = listing = saw_signal = 0;
|
||||
sig = SIGTERM;
|
||||
sigspec = "TERM";
|
||||
|
||||
dflags = DSIG_NOCASE | ((posixly_correct == 0) ? DSIG_SIGPREFIX : 0);
|
||||
/* Process options. */
|
||||
while (list)
|
||||
{
|
||||
word = list->word->word;
|
||||
|
||||
if (ISOPTION (word, 'l'))
|
||||
{
|
||||
listing++;
|
||||
list = list->next;
|
||||
}
|
||||
else if (ISOPTION (word, 's') || ISOPTION (word, 'n'))
|
||||
{
|
||||
list = list->next;
|
||||
if (list)
|
||||
{
|
||||
sigspec = list->word->word;
|
||||
if (sigspec[0] == '0' && sigspec[1] == '\0')
|
||||
sig = 0;
|
||||
else
|
||||
sig = decode_signal (sigspec, dflags);
|
||||
list = list->next;
|
||||
saw_signal++;
|
||||
}
|
||||
else
|
||||
{
|
||||
sh_needarg (word);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
else if (ISOPTION (word, '-'))
|
||||
{
|
||||
list = list->next;
|
||||
break;
|
||||
}
|
||||
else if (ISOPTION (word, '?'))
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
/* If this is a signal specification then process it. We only process
|
||||
the first one seen; other arguments may signify process groups (e.g,
|
||||
-num == process group num). */
|
||||
else if (*word == '-' && saw_signal == 0)
|
||||
{
|
||||
sigspec = word + 1;
|
||||
sig = decode_signal (sigspec, dflags);
|
||||
saw_signal++;
|
||||
list = list->next;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (listing)
|
||||
return (display_signal_list (list, 0));
|
||||
|
||||
/* OK, we are killing processes. */
|
||||
if (sig == NO_SIG)
|
||||
{
|
||||
sh_invalidsig (sigspec);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
while (list)
|
||||
{
|
||||
word = list->word->word;
|
||||
|
||||
if (*word == '-')
|
||||
word++;
|
||||
|
||||
/* Use the entire argument in case of minus sign presence. */
|
||||
if (*word && legal_number (list->word->word, &pid_value) && (pid_value == (pid_t)pid_value))
|
||||
{
|
||||
pid = (pid_t) pid_value;
|
||||
|
||||
if (kill_pid (pid, sig, pid < -1) < 0)
|
||||
{
|
||||
if (errno == EINVAL)
|
||||
sh_invalidsig (sigspec);
|
||||
else
|
||||
kill_error (pid, errno);
|
||||
CONTINUE_OR_FAIL;
|
||||
}
|
||||
else
|
||||
any_succeeded++;
|
||||
}
|
||||
#if defined (JOB_CONTROL)
|
||||
else if (*list->word->word && *list->word->word != '%')
|
||||
{
|
||||
builtin_error (_("%s: arguments must be process or job IDs"), list->word->word);
|
||||
CONTINUE_OR_FAIL;
|
||||
}
|
||||
else if (*word)
|
||||
/* Posix.2 says you can kill without job control active (4.32.4) */
|
||||
{ /* Must be a job spec. Check it out. */
|
||||
int job;
|
||||
sigset_t set, oset;
|
||||
JOB *j;
|
||||
|
||||
BLOCK_CHILD (set, oset);
|
||||
job = get_job_spec (list);
|
||||
|
||||
if (INVALID_JOB (job))
|
||||
{
|
||||
if (job != DUP_JOB)
|
||||
sh_badjob (list->word->word);
|
||||
UNBLOCK_CHILD (oset);
|
||||
CONTINUE_OR_FAIL;
|
||||
}
|
||||
|
||||
j = get_job_by_jid (job);
|
||||
/* Job spec used. Kill the process group. If the job was started
|
||||
without job control, then its pgrp == shell_pgrp, so we have
|
||||
to be careful. We take the pid of the first job in the pipeline
|
||||
in that case. */
|
||||
pid = IS_JOBCONTROL (job) ? j->pgrp : j->pipe->pid;
|
||||
|
||||
UNBLOCK_CHILD (oset);
|
||||
|
||||
if (kill_pid (pid, sig, 1) < 0)
|
||||
{
|
||||
if (errno == EINVAL)
|
||||
sh_invalidsig (sigspec);
|
||||
else
|
||||
kill_error (pid, errno);
|
||||
CONTINUE_OR_FAIL;
|
||||
}
|
||||
else
|
||||
any_succeeded++;
|
||||
}
|
||||
#endif /* !JOB_CONTROL */
|
||||
else
|
||||
{
|
||||
sh_badpid (list->word->word);
|
||||
CONTINUE_OR_FAIL;
|
||||
}
|
||||
continue_killing:
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return (any_succeeded ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
static void
|
||||
kill_error (pid, e)
|
||||
pid_t pid;
|
||||
int e;
|
||||
{
|
||||
char *x;
|
||||
|
||||
x = strerror (e);
|
||||
if (x == 0)
|
||||
x = _("Unknown error");
|
||||
builtin_error ("(%ld) - %s", (long)pid, x);
|
||||
}
|
||||
+18
-11
@@ -2,7 +2,7 @@ This file is mapfile.def, from which is created mapfile.c.
|
||||
It implements the builtin "mapfile" in Bash.
|
||||
|
||||
Copyright (C) 2005-2006 Rocky Bernstein for Free Software Foundation, Inc.
|
||||
Copyright (C) 2008,2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 2008-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -44,7 +44,8 @@ Arguments:
|
||||
|
||||
If -C is supplied without -c, the default quantum is 5000. When
|
||||
CALLBACK is evaluated, it is supplied the index of the next array
|
||||
element to be assigned as an additional argument.
|
||||
element to be assigned and the line to be assigned to that element
|
||||
as additional arguments.
|
||||
|
||||
If not supplied with an explicit origin, mapfile will clear ARRAY before
|
||||
assigning to it.
|
||||
@@ -88,7 +89,10 @@ extern int errno;
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
|
||||
static int run_callback __P((const char *, unsigned int, const char *));
|
||||
|
||||
#define DEFAULT_ARRAY_NAME "MAPFILE"
|
||||
#define DEFAULT_VARIABLE_NAME "MAPLINE" /* not used right now */
|
||||
|
||||
/* The value specifying how frequently `mapfile' calls the callback. */
|
||||
#define DEFAULT_QUANTUM 5000
|
||||
@@ -98,18 +102,20 @@ extern int errno;
|
||||
#define MAPF_CHOP 0x02
|
||||
|
||||
static int
|
||||
run_callback(callback, current_index)
|
||||
run_callback (callback, curindex, curline)
|
||||
const char *callback;
|
||||
unsigned int current_index;
|
||||
unsigned int curindex;
|
||||
const char *curline;
|
||||
{
|
||||
unsigned int execlen;
|
||||
char *execstr;
|
||||
char *execstr, *qline;
|
||||
int flags;
|
||||
|
||||
execlen = strlen (callback) + 10;
|
||||
/* 1 for space between %s and %d,
|
||||
qline = sh_single_quote (curline);
|
||||
execlen = strlen (callback) + strlen (qline) + 10;
|
||||
/* 1 for each space between %s and %d,
|
||||
another 1 for the last nul char for C string. */
|
||||
execlen += 2;
|
||||
execlen += 3;
|
||||
execstr = xmalloc (execlen);
|
||||
|
||||
flags = SEVAL_NOHIST;
|
||||
@@ -117,8 +123,9 @@ run_callback(callback, current_index)
|
||||
if (interactive)
|
||||
flags |= SEVAL_INTERACT;
|
||||
#endif
|
||||
snprintf (execstr, execlen, "%s %d", callback, current_index);
|
||||
return parse_and_execute(execstr, NULL, flags);
|
||||
snprintf (execstr, execlen, "%s %d %s", callback, curindex, qline);
|
||||
free (qline);
|
||||
return parse_and_execute (execstr, NULL, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -202,7 +209,7 @@ mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_n
|
||||
/* Has a callback been registered and if so is it time to call it? */
|
||||
if (callback && line_count && (line_count % callback_quantum) == 0)
|
||||
{
|
||||
run_callback (callback, array_index);
|
||||
run_callback (callback, array_index, line);
|
||||
|
||||
/* Reset the buffer for bash own stream. */
|
||||
if (unbuffered_read == 0)
|
||||
|
||||
@@ -0,0 +1,357 @@
|
||||
This file is mapfile.def, from which is created mapfile.c.
|
||||
It implements the builtin "mapfile" in Bash.
|
||||
|
||||
Copyright (C) 2005-2006 Rocky Bernstein for Free Software Foundation, Inc.
|
||||
Copyright (C) 2008-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$PRODUCES mapfile.c
|
||||
|
||||
$BUILTIN mapfile
|
||||
$FUNCTION mapfile_builtin
|
||||
$SHORT_DOC mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
|
||||
Read lines from the standard input into an indexed array variable.
|
||||
|
||||
Read lines from the standard input into the indexed array variable ARRAY, or
|
||||
from file descriptor FD if the -u option is supplied. The variable MAPFILE
|
||||
is the default ARRAY.
|
||||
|
||||
Options:
|
||||
-n count Copy at most COUNT lines. If COUNT is 0, all lines are copied.
|
||||
-O origin Begin assigning to ARRAY at index ORIGIN. The default index is 0.
|
||||
-s count Discard the first COUNT lines read.
|
||||
-t Remove a trailing newline from each line read.
|
||||
-u fd Read lines from file descriptor FD instead of the standard input.
|
||||
-C callback Evaluate CALLBACK each time QUANTUM lines are read.
|
||||
-c quantum Specify the number of lines read between each call to CALLBACK.
|
||||
|
||||
Arguments:
|
||||
ARRAY Array variable name to use for file data.
|
||||
|
||||
If -C is supplied without -c, the default quantum is 5000. When
|
||||
CALLBACK is evaluated, it is supplied the index of the next array
|
||||
element to be assigned as an additional argument.
|
||||
|
||||
If not supplied with an explicit origin, mapfile will clear ARRAY before
|
||||
assigning to it.
|
||||
|
||||
Exit Status:
|
||||
Returns success unless an invalid option is given or ARRAY is readonly or
|
||||
not an indexed array.
|
||||
$END
|
||||
|
||||
$BUILTIN readarray
|
||||
$FUNCTION mapfile_builtin
|
||||
$SHORT_DOC readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
|
||||
Read lines from a file into an array variable.
|
||||
|
||||
A synonym for `mapfile'.
|
||||
$END
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "builtins.h"
|
||||
#include "posixstat.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "bashansi.h"
|
||||
#include "bashintl.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../bashintl.h"
|
||||
#include "../shell.h"
|
||||
#include "common.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
|
||||
static int run_callback __P((const char *, unsigned int, const char *));
|
||||
|
||||
#define DEFAULT_ARRAY_NAME "MAPFILE"
|
||||
#define DEFAULT_VARIABLE_NAME "MAPLINE" /* not used right now */
|
||||
|
||||
/* The value specifying how frequently `mapfile' calls the callback. */
|
||||
#define DEFAULT_QUANTUM 5000
|
||||
|
||||
/* Values for FLAGS */
|
||||
#define MAPF_CLEARARRAY 0x01
|
||||
#define MAPF_CHOP 0x02
|
||||
|
||||
static int
|
||||
run_callback (callback, curindex, curline)
|
||||
const char *callback;
|
||||
unsigned int curindex;
|
||||
const char *curline;
|
||||
{
|
||||
unsigned int execlen;
|
||||
char *execstr, *qline;
|
||||
int flags;
|
||||
|
||||
qline = sh_single_quote (curline);
|
||||
execlen = strlen (callback) + strlen (qline) + 10;
|
||||
/* 1 for each space between %s and %d,
|
||||
another 1 for the last nul char for C string. */
|
||||
execlen += 3;
|
||||
execstr = xmalloc (execlen);
|
||||
|
||||
flags = SEVAL_NOHIST;
|
||||
#if 0
|
||||
if (interactive)
|
||||
flags |= SEVAL_INTERACT;
|
||||
#endif
|
||||
snprintf (execstr, execlen, "%s %d %s", callback, curindex, qline);
|
||||
free (qline);
|
||||
return parse_and_execute (execstr, NULL, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
do_chop(line)
|
||||
char * line;
|
||||
{
|
||||
int length;
|
||||
|
||||
length = strlen (line);
|
||||
if (length && line[length-1] == '\n')
|
||||
line[length-1] = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_name, flags)
|
||||
int fd;
|
||||
long line_count_goal, origin, nskip, callback_quantum;
|
||||
char *callback, *array_name;
|
||||
int flags;
|
||||
{
|
||||
char *line;
|
||||
size_t line_length;
|
||||
unsigned int array_index, line_count;
|
||||
SHELL_VAR *entry;
|
||||
int unbuffered_read;
|
||||
|
||||
line = NULL;
|
||||
line_length = 0;
|
||||
unbuffered_read = 0;
|
||||
|
||||
/* The following check should be done before reading any lines. Doing it
|
||||
here allows us to call bind_array_element instead of bind_array_variable
|
||||
and skip the variable lookup on every call. */
|
||||
entry = find_or_make_array_variable (array_name, 1);
|
||||
if (entry == 0 || readonly_p (entry) || noassign_p (entry))
|
||||
{
|
||||
if (entry && readonly_p (entry))
|
||||
err_readonly (array_name);
|
||||
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else if (array_p (entry) == 0)
|
||||
{
|
||||
builtin_error (_("%s: not an indexed array"), array_name);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
if (flags & MAPF_CLEARARRAY)
|
||||
array_flush (array_cell (entry));
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
unbuffered_read = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
|
||||
#else
|
||||
unbuffered_read = 1;
|
||||
#endif
|
||||
|
||||
zreset ();
|
||||
|
||||
/* Skip any lines at beginning of file? */
|
||||
for (line_count = 0; line_count < nskip; line_count++)
|
||||
if (zgetline (fd, &line, &line_length, unbuffered_read) < 0)
|
||||
break;
|
||||
|
||||
line = 0;
|
||||
line_length = 0;
|
||||
|
||||
/* Reset the buffer for bash own stream */
|
||||
interrupt_immediately++;
|
||||
for (array_index = origin, line_count = 1;
|
||||
zgetline (fd, &line, &line_length, unbuffered_read) != -1;
|
||||
array_index++, line_count++)
|
||||
{
|
||||
/* Have we exceeded # of lines to store? */
|
||||
if (line_count_goal != 0 && line_count > line_count_goal)
|
||||
break;
|
||||
|
||||
/* Remove trailing newlines? */
|
||||
if (flags & MAPF_CHOP)
|
||||
do_chop (line);
|
||||
|
||||
/* Has a callback been registered and if so is it time to call it? */
|
||||
if (callback && line_count && (line_count % callback_quantum) == 0)
|
||||
{
|
||||
run_callback (callback, array_index, line);
|
||||
|
||||
/* Reset the buffer for bash own stream. */
|
||||
if (unbuffered_read == 0)
|
||||
zsyncfd (fd);
|
||||
}
|
||||
|
||||
bind_array_element (entry, array_index, line, 0);
|
||||
}
|
||||
|
||||
xfree (line);
|
||||
|
||||
if (unbuffered_read == 0)
|
||||
zsyncfd (fd);
|
||||
|
||||
interrupt_immediately--;
|
||||
return EXECUTION_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
mapfile_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int opt, code, fd, clear_array, flags;
|
||||
intmax_t intval;
|
||||
long lines, origin, nskip, callback_quantum;
|
||||
char *array_name, *callback;
|
||||
|
||||
clear_array = 1;
|
||||
fd = 0;
|
||||
lines = origin = nskip = 0;
|
||||
flags = MAPF_CLEARARRAY;
|
||||
callback_quantum = DEFAULT_QUANTUM;
|
||||
callback = 0;
|
||||
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "u:n:O:tC:c:s:")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'u':
|
||||
code = legal_number (list_optarg, &intval);
|
||||
if (code == 0 || intval < 0 || intval != (int)intval)
|
||||
{
|
||||
builtin_error (_("%s: invalid file descriptor specification"), list_optarg);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else
|
||||
fd = intval;
|
||||
|
||||
if (sh_validfd (fd) == 0)
|
||||
{
|
||||
builtin_error (_("%d: invalid file descriptor: %s"), fd, strerror (errno));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
code = legal_number (list_optarg, &intval);
|
||||
if (code == 0 || intval < 0 || intval != (unsigned)intval)
|
||||
{
|
||||
builtin_error (_("%s: invalid line count"), list_optarg);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else
|
||||
lines = intval;
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
code = legal_number (list_optarg, &intval);
|
||||
if (code == 0 || intval < 0 || intval != (unsigned)intval)
|
||||
{
|
||||
builtin_error (_("%s: invalid array origin"), list_optarg);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else
|
||||
origin = intval;
|
||||
flags &= ~MAPF_CLEARARRAY;
|
||||
break;
|
||||
case 't':
|
||||
flags |= MAPF_CHOP;
|
||||
break;
|
||||
case 'C':
|
||||
callback = list_optarg;
|
||||
break;
|
||||
case 'c':
|
||||
code = legal_number (list_optarg, &intval);
|
||||
if (code == 0 || intval <= 0 || intval != (unsigned)intval)
|
||||
{
|
||||
builtin_error (_("%s: invalid callback quantum"), list_optarg);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else
|
||||
callback_quantum = intval;
|
||||
break;
|
||||
case 's':
|
||||
code = legal_number (list_optarg, &intval);
|
||||
if (code == 0 || intval < 0 || intval != (unsigned)intval)
|
||||
{
|
||||
builtin_error (_("%s: invalid line count"), list_optarg);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else
|
||||
nskip = intval;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
if (list == 0)
|
||||
array_name = DEFAULT_ARRAY_NAME;
|
||||
else if (list->word == 0 || list->word->word == 0)
|
||||
{
|
||||
builtin_error ("internal error: getting variable name");
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else if (list->word->word[0] == '\0')
|
||||
{
|
||||
builtin_error (_("empty array variable name"));
|
||||
return (EX_USAGE);
|
||||
}
|
||||
else
|
||||
array_name = list->word->word;
|
||||
|
||||
if (legal_identifier (array_name) == 0 && valid_array_reference (array_name) == 0)
|
||||
{
|
||||
sh_invalidid (array_name);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
return mapfile (fd, lines, origin, nskip, callback_quantum, callback, array_name, flags);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int
|
||||
mapfile_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
builtin_error (_("array variable support required"));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
#endif /* ARRAY_VARS */
|
||||
@@ -1,7 +1,7 @@
|
||||
/* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
|
||||
a single source file called builtins.def. */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -1380,7 +1380,7 @@ write_documentation (stream, documentation, indentation, flags)
|
||||
{
|
||||
register int i, j;
|
||||
register char *line;
|
||||
int string_array, texinfo, base_indent, last_cpp, filename_p;
|
||||
int string_array, texinfo, base_indent, filename_p;
|
||||
|
||||
if (stream == 0)
|
||||
return;
|
||||
@@ -1407,7 +1407,7 @@ write_documentation (stream, documentation, indentation, flags)
|
||||
|
||||
base_indent = (string_array && single_longdoc_strings && filename_p == 0) ? BASE_INDENT : 0;
|
||||
|
||||
for (i = last_cpp = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
|
||||
for (i = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
|
||||
{
|
||||
/* Allow #ifdef's to be written out verbatim, but don't put them into
|
||||
separate help files. */
|
||||
@@ -1415,11 +1415,8 @@ write_documentation (stream, documentation, indentation, flags)
|
||||
{
|
||||
if (string_array && filename_p == 0 && single_longdoc_strings == 0)
|
||||
fprintf (stream, "%s\n", line);
|
||||
last_cpp = 1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
last_cpp = 0;
|
||||
|
||||
/* prefix with N_( for gettext */
|
||||
if (string_array && single_longdoc_strings == 0)
|
||||
|
||||
+85
-12
@@ -1,7 +1,7 @@
|
||||
This file is printf.def, from which is created printf.c.
|
||||
It implements the builtin "printf" in Bash.
|
||||
|
||||
Copyright (C) 1997-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -72,9 +72,12 @@ $END
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#include "posixtime.h"
|
||||
#include "../bashansi.h"
|
||||
#include "../bashintl.h"
|
||||
|
||||
#define NEED_STRFTIME_DECL
|
||||
|
||||
#include "../shell.h"
|
||||
#include "shmbutil.h"
|
||||
#include "stdc.h"
|
||||
@@ -167,6 +170,8 @@ extern int errno;
|
||||
#define SKIP1 "#'-+ 0"
|
||||
#define LENMODS "hjlLtz"
|
||||
|
||||
extern time_t shell_start_time;
|
||||
|
||||
#if !HAVE_ASPRINTF
|
||||
extern int asprintf __P((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
|
||||
#endif
|
||||
@@ -177,7 +182,7 @@ extern int vsnprintf __P((char *, size_t, const char *, va_list)) __attribute__(
|
||||
|
||||
static void printf_erange __P((char *));
|
||||
static int printstr __P((char *, char *, int, int, int));
|
||||
static int tescape __P((char *, char *, int *));
|
||||
static int tescape __P((char *, char *, int *, int *));
|
||||
static char *bexpand __P((char *, int, int *, int *));
|
||||
static char *vbadd __P((char *, int));
|
||||
static int vbprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
|
||||
@@ -226,7 +231,7 @@ printf_builtin (list)
|
||||
char convch, thisch, nextch, *format, *modstart, *fmt, *start;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
char mbch[25]; /* 25 > MB_LEN_MAX, plus can handle 4-byte UTF-8 and large Unicode characters*/
|
||||
int mbind;
|
||||
int mbind, mblen;
|
||||
#endif
|
||||
|
||||
conversion_error = 0;
|
||||
@@ -309,11 +314,11 @@ printf_builtin (list)
|
||||
/* Accommodate possible use of \u or \U, which can result in
|
||||
multibyte characters */
|
||||
memset (mbch, '\0', sizeof (mbch));
|
||||
fmt += tescape (fmt, mbch, (int *)NULL);
|
||||
for (mbind = 0; mbch[mbind]; mbind++)
|
||||
fmt += tescape (fmt, mbch, &mblen, (int *)NULL);
|
||||
for (mbind = 0; mbind < mblen; mbind++)
|
||||
PC (mbch[mbind]);
|
||||
#else
|
||||
fmt += tescape (fmt, &nextch, (int *)NULL);
|
||||
fmt += tescape (fmt, &nextch, (int *)NULL, (int *)NULL);
|
||||
PC (nextch);
|
||||
#endif
|
||||
fmt--; /* for loop will increment it for us again */
|
||||
@@ -414,6 +419,70 @@ printf_builtin (list)
|
||||
break;
|
||||
}
|
||||
|
||||
case '(':
|
||||
{
|
||||
char *timefmt, timebuf[128], *t;
|
||||
int n;
|
||||
intmax_t arg;
|
||||
time_t secs;
|
||||
struct tm *tm;
|
||||
|
||||
modstart[1] = nextch; /* restore char after left paren */
|
||||
timefmt = xmalloc (strlen (fmt) + 3);
|
||||
fmt++; /* skip over left paren */
|
||||
for (t = timefmt, n = 1; *fmt; )
|
||||
{
|
||||
if (*fmt == '(')
|
||||
n++;
|
||||
else if (*fmt == ')')
|
||||
n--;
|
||||
if (n == 0)
|
||||
break;
|
||||
*t++ = *fmt++;
|
||||
}
|
||||
*t = '\0';
|
||||
if (*++fmt != 'T')
|
||||
{
|
||||
builtin_warning (_("`%c': invalid time format specification"), *fmt);
|
||||
fmt = start;
|
||||
free (timefmt);
|
||||
PC (*fmt);
|
||||
continue;
|
||||
}
|
||||
if (timefmt[0] == '\0')
|
||||
{
|
||||
timefmt[0] = '%';
|
||||
timefmt[1] = 'X'; /* locale-specific current time - should we use `+'? */
|
||||
timefmt[2] = '\0';
|
||||
}
|
||||
/* argument is seconds since the epoch with special -1 and -2 */
|
||||
arg = getintmax ();
|
||||
if (arg == -1)
|
||||
secs = NOW; /* roughly date +%s */
|
||||
else if (arg == -2)
|
||||
secs = shell_start_time; /* roughly $SECONDS */
|
||||
else
|
||||
secs = arg;
|
||||
tm = localtime (&secs);
|
||||
n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
|
||||
free (timefmt);
|
||||
if (n == 0)
|
||||
timebuf[0] = '\0';
|
||||
else
|
||||
timebuf[sizeof(timebuf) - 1] = '\0';
|
||||
/* convert to %s format that preserves fieldwidth and precision */
|
||||
modstart[0] = 's';
|
||||
modstart[1] = '\0';
|
||||
n = printstr (start, timebuf, strlen (timebuf), fieldwidth, precision); /* XXX - %s for now */
|
||||
if (n < 0)
|
||||
{
|
||||
sh_wrerror ();
|
||||
clearerr (stdout);
|
||||
PRETURN (EXECUTION_FAILURE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'n':
|
||||
{
|
||||
char *var;
|
||||
@@ -712,15 +781,17 @@ printstr (fmt, string, len, fieldwidth, precision)
|
||||
do the \c short-circuiting, and \c is treated as an unrecognized escape
|
||||
sequence; we also bypass the other processing specific to %b arguments. */
|
||||
static int
|
||||
tescape (estart, cp, sawc)
|
||||
tescape (estart, cp, lenp, sawc)
|
||||
char *estart;
|
||||
char *cp;
|
||||
int *sawc;
|
||||
int *lenp, *sawc;
|
||||
{
|
||||
register char *p;
|
||||
int temp, c, evalue;
|
||||
|
||||
p = estart;
|
||||
if (lenp)
|
||||
*lenp = 1;
|
||||
|
||||
switch (c = *p++)
|
||||
{
|
||||
@@ -788,6 +859,8 @@ tescape (estart, cp, sawc)
|
||||
{
|
||||
temp = u32cconv (evalue, cp);
|
||||
cp[temp] = '\0';
|
||||
if (lenp)
|
||||
*lenp = temp;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -832,7 +905,7 @@ bexpand (string, len, sawc, lenp)
|
||||
char *ret, *r, *s, c;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
char mbch[25];
|
||||
int mbind;
|
||||
int mbind, mblen;
|
||||
#endif
|
||||
|
||||
if (string == 0 || len == 0)
|
||||
@@ -856,9 +929,9 @@ bexpand (string, len, sawc, lenp)
|
||||
temp = 0;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
memset (mbch, '\0', sizeof (mbch));
|
||||
s += tescape (s, mbch, &temp);
|
||||
s += tescape (s, mbch, &mblen, &temp);
|
||||
#else
|
||||
s += tescape (s, &c, &temp);
|
||||
s += tescape (s, &c, (int *)NULL, &temp);
|
||||
#endif
|
||||
if (temp)
|
||||
{
|
||||
@@ -868,7 +941,7 @@ bexpand (string, len, sawc, lenp)
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
for (mbind = 0; mbch[mbind]; mbind++)
|
||||
for (mbind = 0; mbind < mblen; mbind++)
|
||||
*r++ = mbch[mbind];
|
||||
#else
|
||||
*r++ = c;
|
||||
|
||||
+91
-13
@@ -72,9 +72,12 @@ $END
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#include "posixtime.h"
|
||||
#include "../bashansi.h"
|
||||
#include "../bashintl.h"
|
||||
|
||||
#define NEED_STRFTIME_DECL
|
||||
|
||||
#include "../shell.h"
|
||||
#include "shmbutil.h"
|
||||
#include "stdc.h"
|
||||
@@ -167,6 +170,8 @@ extern int errno;
|
||||
#define SKIP1 "#'-+ 0"
|
||||
#define LENMODS "hjlLtz"
|
||||
|
||||
extern time_t shell_start_time;
|
||||
|
||||
#if !HAVE_ASPRINTF
|
||||
extern int asprintf __P((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
|
||||
#endif
|
||||
@@ -177,7 +182,7 @@ extern int vsnprintf __P((char *, size_t, const char *, va_list)) __attribute__(
|
||||
|
||||
static void printf_erange __P((char *));
|
||||
static int printstr __P((char *, char *, int, int, int));
|
||||
static int tescape __P((char *, char *, int *));
|
||||
static int tescape __P((char *, char *, int *, int *));
|
||||
static char *bexpand __P((char *, int, int *, int *));
|
||||
static char *vbadd __P((char *, int));
|
||||
static int vbprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
|
||||
@@ -226,7 +231,7 @@ printf_builtin (list)
|
||||
char convch, thisch, nextch, *format, *modstart, *fmt, *start;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
char mbch[25]; /* 25 > MB_LEN_MAX, plus can handle 4-byte UTF-8 and large Unicode characters*/
|
||||
int mbind;
|
||||
int mbind, mblen;
|
||||
#endif
|
||||
|
||||
conversion_error = 0;
|
||||
@@ -309,11 +314,11 @@ printf_builtin (list)
|
||||
/* Accommodate possible use of \u or \U, which can result in
|
||||
multibyte characters */
|
||||
memset (mbch, '\0', sizeof (mbch));
|
||||
fmt += tescape (fmt, mbch, (int *)NULL);
|
||||
for (mbind = 0; mbch[mbind]; mbind++)
|
||||
fmt += tescape (fmt, mbch, &mblen, (int *)NULL);
|
||||
for (mbind = 0; mbind < mblen; mbind++)
|
||||
PC (mbch[mbind]);
|
||||
#else
|
||||
fmt += tescape (fmt, &nextch, (int *)NULL);
|
||||
fmt += tescape (fmt, &nextch, (int *)NULL, (int *)NULL);
|
||||
PC (nextch);
|
||||
#endif
|
||||
fmt--; /* for loop will increment it for us again */
|
||||
@@ -414,6 +419,70 @@ printf_builtin (list)
|
||||
break;
|
||||
}
|
||||
|
||||
case '(':
|
||||
{
|
||||
char *timefmt, timebuf[128], *t;
|
||||
int n;
|
||||
intmax_t arg;
|
||||
time_t secs;
|
||||
struct tm *tm;
|
||||
|
||||
modstart[1] = nextch; /* restore char after left paren */
|
||||
timefmt = xmalloc (strlen (fmt) + 3);
|
||||
fmt++; /* skip over left paren */
|
||||
for (t = timefmt, n = 1; *fmt; )
|
||||
{
|
||||
if (*fmt == '(')
|
||||
n++;
|
||||
else if (*fmt == ')')
|
||||
n--;
|
||||
if (n == 0)
|
||||
break;
|
||||
*t++ = *fmt++;
|
||||
}
|
||||
*t = '\0';
|
||||
if (*++fmt != 'T')
|
||||
{
|
||||
builtin_warning (_("`%c': invalid time format specification"), *fmt);
|
||||
fmt = start;
|
||||
free (timefmt);
|
||||
PC (*fmt);
|
||||
continue;
|
||||
}
|
||||
if (timefmt[0] == '\0')
|
||||
{
|
||||
timefmt[0] = '%';
|
||||
timefmt[1] = 'X'; /* locale-specific current time - should we use `+'? */
|
||||
timefmt[2] = '\0';
|
||||
}
|
||||
/* argument is seconds since the epoch with special -1 and -2 */
|
||||
arg = getintmax ();
|
||||
if (arg == -1)
|
||||
secs = NOW; /* roughly date +%s */
|
||||
else if (arg == -2)
|
||||
secs = shell_start_time; /* roughly $SECONDS */
|
||||
else
|
||||
secs = arg;
|
||||
tm = localtime (&secs);
|
||||
n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
|
||||
free (timefmt);
|
||||
if (n == 0)
|
||||
timebuf[0] = '\0';
|
||||
else
|
||||
timebuf[sizeof(timebuf) - 1] = '\0';
|
||||
/* convert to %s format that preserves fieldwidth and precision */
|
||||
modstart[0] = 's';
|
||||
modstart[1] = '\0';
|
||||
n = printstr (start, timebuf, strlen (timebuf), fieldwidth, precision); /* XXX - %s for now */
|
||||
if (n < 0)
|
||||
{
|
||||
sh_wrerror ();
|
||||
clearerr (stdout);
|
||||
PRETURN (EXECUTION_FAILURE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'n':
|
||||
{
|
||||
char *var;
|
||||
@@ -712,15 +781,17 @@ printstr (fmt, string, len, fieldwidth, precision)
|
||||
do the \c short-circuiting, and \c is treated as an unrecognized escape
|
||||
sequence; we also bypass the other processing specific to %b arguments. */
|
||||
static int
|
||||
tescape (estart, cp, sawc)
|
||||
tescape (estart, cp, lenp, sawc)
|
||||
char *estart;
|
||||
char *cp;
|
||||
int *sawc;
|
||||
int *lenp, *sawc;
|
||||
{
|
||||
register char *p;
|
||||
int temp, c, evalue;
|
||||
|
||||
p = estart;
|
||||
if (lenp)
|
||||
*lenp = 1;
|
||||
|
||||
switch (c = *p++)
|
||||
{
|
||||
@@ -782,8 +853,15 @@ tescape (estart, cp, sawc)
|
||||
*cp = '\\';
|
||||
return 0;
|
||||
}
|
||||
temp = u32cconv (evalue, cp);
|
||||
cp[temp] = '\0';
|
||||
if (evalue <= UCHAR_MAX)
|
||||
*cp = evalue;
|
||||
else
|
||||
{
|
||||
temp = u32cconv (evalue, cp);
|
||||
cp[temp] = '\0';
|
||||
if (lenp)
|
||||
*lenp = temp;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -827,7 +905,7 @@ bexpand (string, len, sawc, lenp)
|
||||
char *ret, *r, *s, c;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
char mbch[25];
|
||||
int mbind;
|
||||
int mbind, mblen;
|
||||
#endif
|
||||
|
||||
if (string == 0 || len == 0)
|
||||
@@ -851,9 +929,9 @@ bexpand (string, len, sawc, lenp)
|
||||
temp = 0;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
memset (mbch, '\0', sizeof (mbch));
|
||||
s += tescape (s, mbch, &temp);
|
||||
s += tescape (s, mbch, &mblen, &temp);
|
||||
#else
|
||||
s += tescape (s, &c, &temp);
|
||||
s += tescape (s, &c, (int *)NULL, &temp);
|
||||
#endif
|
||||
if (temp)
|
||||
{
|
||||
@@ -863,7 +941,7 @@ bexpand (string, len, sawc, lenp)
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
for (mbind = 0; mbch[mbind]; mbind++)
|
||||
for (mbind = 0; mbind < mblen; mbind++)
|
||||
*r++ = mbch[mbind];
|
||||
#else
|
||||
*r++ = c;
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
This file is read.def, from which is created read.c.
|
||||
It implements the builtin "read" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+2
-2
@@ -390,7 +390,6 @@ read_builtin (list)
|
||||
run_unwind_frame ("read_builtin");
|
||||
input_string[i] = '\0'; /* make sure it's terminated */
|
||||
retval = 128+SIGALRM;
|
||||
itrace("read_builtin: before goto assign_vars: interrupt_immediately = %d", interrupt_immediately);
|
||||
goto assign_vars;
|
||||
}
|
||||
old_alrm = set_signal_handler (SIGALRM, sigalrm);
|
||||
@@ -616,13 +615,14 @@ add_char:
|
||||
if (unbuffered_read == 0)
|
||||
zsyncfd (fd);
|
||||
|
||||
discard_unwind_frame ("read_builtin");
|
||||
|
||||
retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
|
||||
|
||||
assign_vars:
|
||||
|
||||
interrupt_immediately--;
|
||||
terminate_immediately--;
|
||||
discard_unwind_frame ("read_builtin");
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
/* If -a was given, take the string read, break it into a list of words,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
This file is setattr.def, from which is created setattr.c.
|
||||
It implements the builtins "export" and "readonly", in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -433,7 +433,7 @@ show_var_attributes (var, pattr, nodefs)
|
||||
printf ("%s\n", var->name);
|
||||
else if (function_p (var))
|
||||
printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
|
||||
else if (invisible_p (var) || var_isnull (var))
|
||||
else if (invisible_p (var) || var_isset (var) == 0)
|
||||
printf ("%s\n", var->name);
|
||||
else
|
||||
{
|
||||
|
||||
+3
-1
@@ -1,7 +1,7 @@
|
||||
This file is shopt.def, from which is created shopt.c.
|
||||
It implements the Bash `shopt' builtin.
|
||||
|
||||
Copyright (C) 1994-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1994-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -124,6 +124,7 @@ static int shopt_login_shell;
|
||||
static int shopt_compat31;
|
||||
static int shopt_compat32;
|
||||
static int shopt_compat40;
|
||||
static int shopt_compat41;
|
||||
|
||||
typedef int shopt_set_func_t __P((char *, int));
|
||||
|
||||
@@ -146,6 +147,7 @@ static struct {
|
||||
{ "compat31", &shopt_compat31, set_compatibility_level },
|
||||
{ "compat32", &shopt_compat32, set_compatibility_level },
|
||||
{ "compat40", &shopt_compat40, set_compatibility_level },
|
||||
{ "compat41", &shopt_compat41, set_compatibility_level },
|
||||
#if defined (READLINE)
|
||||
{ "dirspell", &dircomplete_spelling, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,717 @@
|
||||
This file is shopt.def, from which is created shopt.c.
|
||||
It implements the Bash `shopt' builtin.
|
||||
|
||||
Copyright (C) 1994-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 shopt.c
|
||||
|
||||
$BUILTIN shopt
|
||||
$FUNCTION shopt_builtin
|
||||
$SHORT_DOC shopt [-pqsu] [-o] [optname ...]
|
||||
Set and unset shell options.
|
||||
|
||||
Change the setting of each shell option OPTNAME. Without any option
|
||||
arguments, list all shell options with an indication of whether or not each
|
||||
is set.
|
||||
|
||||
Options:
|
||||
-o restrict OPTNAMEs to those defined for use with `set -o'
|
||||
-p print each shell option with an indication of its status
|
||||
-q suppress output
|
||||
-s enable (set) each OPTNAME
|
||||
-u disable (unset) each OPTNAME
|
||||
|
||||
Exit Status:
|
||||
Returns success if OPTNAME is enabled; fails if an invalid option is
|
||||
given or OPTNAME is disabled.
|
||||
$END
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#include "../bashintl.h"
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../flags.h"
|
||||
#include "common.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
#if defined (HISTORY)
|
||||
# include "../bashhist.h"
|
||||
#endif
|
||||
|
||||
#define UNSETOPT 0
|
||||
#define SETOPT 1
|
||||
|
||||
#define OPTFMT "%-15s\t%s\n"
|
||||
|
||||
extern int allow_null_glob_expansion, fail_glob_expansion, glob_dot_filenames;
|
||||
extern int cdable_vars, mail_warning, source_uses_path;
|
||||
extern int no_exit_on_failed_exec, print_shift_error;
|
||||
extern int check_hashed_filenames, promptvars;
|
||||
extern int cdspelling, expand_aliases;
|
||||
extern int extended_quote;
|
||||
extern int check_window_size;
|
||||
extern int glob_ignore_case, match_ignore_case;
|
||||
extern int hup_on_exit;
|
||||
extern int xpg_echo;
|
||||
extern int gnu_error_format;
|
||||
extern int check_jobs_at_exit;
|
||||
extern int autocd;
|
||||
extern int glob_star;
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
extern int extended_glob;
|
||||
#endif
|
||||
|
||||
#if defined (READLINE)
|
||||
extern int hist_verify, history_reediting, perform_hostname_completion;
|
||||
extern int no_empty_command_completion;
|
||||
extern int force_fignore;
|
||||
extern int dircomplete_spelling;
|
||||
|
||||
extern int enable_hostname_completion __P((int));
|
||||
#endif
|
||||
|
||||
#if defined (PROGRAMMABLE_COMPLETION)
|
||||
extern int prog_completion_enabled;
|
||||
#endif
|
||||
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
extern char *shell_name;
|
||||
#endif
|
||||
|
||||
#if defined (DEBUGGER)
|
||||
extern int debugging_mode;
|
||||
#endif
|
||||
|
||||
static void shopt_error __P((char *));
|
||||
|
||||
static int set_shellopts_after_change __P((char *, int));
|
||||
static int shopt_enable_hostname_completion __P((char *, int));
|
||||
static int set_compatibility_level __P((char *, int));
|
||||
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
static int set_restricted_shell __P((char *, int));
|
||||
#endif
|
||||
|
||||
static int shopt_login_shell;
|
||||
static int shopt_compat31;
|
||||
static int shopt_compat32;
|
||||
static int shopt_compat40;
|
||||
static int shopt_compat41;
|
||||
|
||||
typedef int shopt_set_func_t __P((char *, int));
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
int *value;
|
||||
shopt_set_func_t *set_func;
|
||||
} shopt_vars[] = {
|
||||
{ "autocd", &autocd, (shopt_set_func_t *)NULL },
|
||||
{ "cdable_vars", &cdable_vars, (shopt_set_func_t *)NULL },
|
||||
{ "cdspell", &cdspelling, (shopt_set_func_t *)NULL },
|
||||
{ "checkhash", &check_hashed_filenames, (shopt_set_func_t *)NULL },
|
||||
#if defined (JOB_CONTROL)
|
||||
{ "checkjobs", &check_jobs_at_exit, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
{ "checkwinsize", &check_window_size, (shopt_set_func_t *)NULL },
|
||||
#if defined (HISTORY)
|
||||
{ "cmdhist", &command_oriented_history, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
{ "compat31", &shopt_compat31, set_compatibility_level },
|
||||
{ "compat32", &shopt_compat32, set_compatibility_level },
|
||||
{ "compat40", &shopt_compat40, set_compatibility_level },
|
||||
{ "compat41", &shopt_compat41, set_compatibility_level },
|
||||
#if defined (READLINE)
|
||||
{ "dirspell", &dircomplete_spelling, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
{ "dotglob", &glob_dot_filenames, (shopt_set_func_t *)NULL },
|
||||
{ "execfail", &no_exit_on_failed_exec, (shopt_set_func_t *)NULL },
|
||||
{ "expand_aliases", &expand_aliases, (shopt_set_func_t *)NULL },
|
||||
#if defined (DEBUGGER)
|
||||
{ "extdebug", &debugging_mode, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
#if defined (EXTENDED_GLOB)
|
||||
{ "extglob", &extended_glob, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
{ "extquote", &extended_quote, (shopt_set_func_t *)NULL },
|
||||
{ "failglob", &fail_glob_expansion, (shopt_set_func_t *)NULL },
|
||||
#if defined (READLINE)
|
||||
{ "force_fignore", &force_fignore, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
{ "globstar", &glob_star, (shopt_set_func_t *)NULL },
|
||||
{ "gnu_errfmt", &gnu_error_format, (shopt_set_func_t *)NULL },
|
||||
#if defined (HISTORY)
|
||||
{ "histappend", &force_append_history, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
#if defined (READLINE)
|
||||
{ "histreedit", &history_reediting, (shopt_set_func_t *)NULL },
|
||||
{ "histverify", &hist_verify, (shopt_set_func_t *)NULL },
|
||||
{ "hostcomplete", &perform_hostname_completion, shopt_enable_hostname_completion },
|
||||
#endif
|
||||
{ "huponexit", &hup_on_exit, (shopt_set_func_t *)NULL },
|
||||
{ "interactive_comments", &interactive_comments, set_shellopts_after_change },
|
||||
#if defined (HISTORY)
|
||||
{ "lithist", &literal_history, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
{ "login_shell", &shopt_login_shell, set_login_shell },
|
||||
{ "mailwarn", &mail_warning, (shopt_set_func_t *)NULL },
|
||||
#if defined (READLINE)
|
||||
{ "no_empty_cmd_completion", &no_empty_command_completion, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
{ "nocaseglob", &glob_ignore_case, (shopt_set_func_t *)NULL },
|
||||
{ "nocasematch", &match_ignore_case, (shopt_set_func_t *)NULL },
|
||||
{ "nullglob", &allow_null_glob_expansion, (shopt_set_func_t *)NULL },
|
||||
#if defined (PROGRAMMABLE_COMPLETION)
|
||||
{ "progcomp", &prog_completion_enabled, (shopt_set_func_t *)NULL },
|
||||
#endif
|
||||
{ "promptvars", &promptvars, (shopt_set_func_t *)NULL },
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
{ "restricted_shell", &restricted_shell, set_restricted_shell },
|
||||
#endif
|
||||
{ "shift_verbose", &print_shift_error, (shopt_set_func_t *)NULL },
|
||||
{ "sourcepath", &source_uses_path, (shopt_set_func_t *)NULL },
|
||||
{ "xpg_echo", &xpg_echo, (shopt_set_func_t *)NULL },
|
||||
{ (char *)0, (int *)0, (shopt_set_func_t *)NULL }
|
||||
};
|
||||
|
||||
#define N_SHOPT_OPTIONS (sizeof (shopt_vars) / sizeof (shopt_vars[0]))
|
||||
|
||||
#define GET_SHOPT_OPTION_VALUE(i) (*shopt_vars[i].value)
|
||||
|
||||
static const char * const on = "on";
|
||||
static const char * const off = "off";
|
||||
|
||||
static int find_shopt __P((char *));
|
||||
static int toggle_shopts __P((int, WORD_LIST *, int));
|
||||
static void print_shopt __P((char *, int, int));
|
||||
static int list_shopts __P((WORD_LIST *, int));
|
||||
static int list_some_shopts __P((int, int));
|
||||
static int list_shopt_o_options __P((WORD_LIST *, int));
|
||||
static int list_some_o_options __P((int, int));
|
||||
static int set_shopt_o_options __P((int, WORD_LIST *, int));
|
||||
|
||||
#define SFLAG 0x01
|
||||
#define UFLAG 0x02
|
||||
#define QFLAG 0x04
|
||||
#define OFLAG 0x08
|
||||
#define PFLAG 0x10
|
||||
|
||||
int
|
||||
shopt_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int opt, flags, rval;
|
||||
|
||||
flags = 0;
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, "psuoq")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 's':
|
||||
flags |= SFLAG;
|
||||
break;
|
||||
case 'u':
|
||||
flags |= UFLAG;
|
||||
break;
|
||||
case 'q':
|
||||
flags |= QFLAG;
|
||||
break;
|
||||
case 'o':
|
||||
flags |= OFLAG;
|
||||
break;
|
||||
case 'p':
|
||||
flags |= PFLAG;
|
||||
break;
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
list = loptend;
|
||||
|
||||
if ((flags & (SFLAG|UFLAG)) == (SFLAG|UFLAG))
|
||||
{
|
||||
builtin_error (_("cannot set and unset shell options simultaneously"));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
rval = EXECUTION_SUCCESS;
|
||||
if ((flags & OFLAG) && ((flags & (SFLAG|UFLAG)) == 0)) /* shopt -o */
|
||||
rval = list_shopt_o_options (list, flags);
|
||||
else if (list && (flags & OFLAG)) /* shopt -so args */
|
||||
rval = set_shopt_o_options ((flags & SFLAG) ? FLAG_ON : FLAG_OFF, list, flags & QFLAG);
|
||||
else if (flags & OFLAG) /* shopt -so */
|
||||
rval = list_some_o_options ((flags & SFLAG) ? 1 : 0, flags);
|
||||
else if (list && (flags & (SFLAG|UFLAG))) /* shopt -su args */
|
||||
rval = toggle_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, list, flags & QFLAG);
|
||||
else if ((flags & (SFLAG|UFLAG)) == 0) /* shopt [args] */
|
||||
rval = list_shopts (list, flags);
|
||||
else /* shopt -su */
|
||||
rval = list_some_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, flags);
|
||||
return (rval);
|
||||
}
|
||||
|
||||
/* Reset the options managed by `shopt' to the values they would have at
|
||||
shell startup. */
|
||||
void
|
||||
reset_shopt_options ()
|
||||
{
|
||||
allow_null_glob_expansion = glob_dot_filenames = 0;
|
||||
cdable_vars = mail_warning = 0;
|
||||
no_exit_on_failed_exec = print_shift_error = 0;
|
||||
check_hashed_filenames = cdspelling = expand_aliases = check_window_size = 0;
|
||||
|
||||
source_uses_path = promptvars = 1;
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
extended_glob = 0;
|
||||
#endif
|
||||
|
||||
#if defined (HISTORY)
|
||||
literal_history = force_append_history = 0;
|
||||
command_oriented_history = 1;
|
||||
#endif
|
||||
|
||||
#if defined (READLINE)
|
||||
hist_verify = history_reediting = 0;
|
||||
perform_hostname_completion = 1;
|
||||
#endif
|
||||
|
||||
shopt_login_shell = login_shell;
|
||||
}
|
||||
|
||||
static int
|
||||
find_shopt (name)
|
||||
char *name;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; shopt_vars[i].name; i++)
|
||||
if (STREQ (name, shopt_vars[i].name))
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
shopt_error (s)
|
||||
char *s;
|
||||
{
|
||||
builtin_error (_("%s: invalid shell option name"), s);
|
||||
}
|
||||
|
||||
static int
|
||||
toggle_shopts (mode, list, quiet)
|
||||
int mode;
|
||||
WORD_LIST *list;
|
||||
int quiet;
|
||||
{
|
||||
WORD_LIST *l;
|
||||
int ind, rval;
|
||||
|
||||
for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
|
||||
{
|
||||
ind = find_shopt (l->word->word);
|
||||
if (ind < 0)
|
||||
{
|
||||
shopt_error (l->word->word);
|
||||
rval = EXECUTION_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*shopt_vars[ind].value = mode; /* 1 for set, 0 for unset */
|
||||
if (shopt_vars[ind].set_func)
|
||||
(*shopt_vars[ind].set_func) (shopt_vars[ind].name, mode);
|
||||
}
|
||||
}
|
||||
|
||||
set_bashopts ();
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static void
|
||||
print_shopt (name, val, flags)
|
||||
char *name;
|
||||
int val, flags;
|
||||
{
|
||||
if (flags & PFLAG)
|
||||
printf ("shopt %s %s\n", val ? "-s" : "-u", name);
|
||||
else
|
||||
printf (OPTFMT, name, val ? on : off);
|
||||
}
|
||||
|
||||
/* List the values of all or any of the `shopt' options. Returns 0 if
|
||||
all were listed or all variables queried were on; 1 otherwise. */
|
||||
static int
|
||||
list_shopts (list, flags)
|
||||
WORD_LIST *list;
|
||||
int flags;
|
||||
{
|
||||
WORD_LIST *l;
|
||||
int i, val, rval;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
for (i = 0; shopt_vars[i].name; i++)
|
||||
{
|
||||
val = *shopt_vars[i].value;
|
||||
if ((flags & QFLAG) == 0)
|
||||
print_shopt (shopt_vars[i].name, val, flags);
|
||||
}
|
||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
||||
}
|
||||
|
||||
for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
|
||||
{
|
||||
i = find_shopt (l->word->word);
|
||||
if (i < 0)
|
||||
{
|
||||
shopt_error (l->word->word);
|
||||
rval = EXECUTION_FAILURE;
|
||||
continue;
|
||||
}
|
||||
val = *shopt_vars[i].value;
|
||||
if (val == 0)
|
||||
rval = EXECUTION_FAILURE;
|
||||
if ((flags & QFLAG) == 0)
|
||||
print_shopt (l->word->word, val, flags);
|
||||
}
|
||||
|
||||
return (sh_chkwrite (rval));
|
||||
}
|
||||
|
||||
static int
|
||||
list_some_shopts (mode, flags)
|
||||
int mode, flags;
|
||||
{
|
||||
int val, i;
|
||||
|
||||
for (i = 0; shopt_vars[i].name; i++)
|
||||
{
|
||||
val = *shopt_vars[i].value;
|
||||
if (((flags & QFLAG) == 0) && mode == val)
|
||||
print_shopt (shopt_vars[i].name, val, flags);
|
||||
}
|
||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
||||
}
|
||||
|
||||
static int
|
||||
list_shopt_o_options (list, flags)
|
||||
WORD_LIST *list;
|
||||
int flags;
|
||||
{
|
||||
WORD_LIST *l;
|
||||
int val, rval;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
if ((flags & QFLAG) == 0)
|
||||
list_minus_o_opts (-1, (flags & PFLAG));
|
||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
||||
}
|
||||
|
||||
for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
|
||||
{
|
||||
val = minus_o_option_value (l->word->word);
|
||||
if (val == -1)
|
||||
{
|
||||
sh_invalidoptname (l->word->word);
|
||||
rval = EXECUTION_FAILURE;
|
||||
continue;
|
||||
}
|
||||
if (val == 0)
|
||||
rval = EXECUTION_FAILURE;
|
||||
if ((flags & QFLAG) == 0)
|
||||
{
|
||||
if (flags & PFLAG)
|
||||
printf ("set %co %s\n", val ? '-' : '+', l->word->word);
|
||||
else
|
||||
printf (OPTFMT, l->word->word, val ? on : off);
|
||||
}
|
||||
}
|
||||
return (sh_chkwrite (rval));
|
||||
}
|
||||
|
||||
static int
|
||||
list_some_o_options (mode, flags)
|
||||
int mode, flags;
|
||||
{
|
||||
if ((flags & QFLAG) == 0)
|
||||
list_minus_o_opts (mode, (flags & PFLAG));
|
||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
||||
}
|
||||
|
||||
static int
|
||||
set_shopt_o_options (mode, list, quiet)
|
||||
int mode;
|
||||
WORD_LIST *list;
|
||||
int quiet;
|
||||
{
|
||||
WORD_LIST *l;
|
||||
int rval;
|
||||
|
||||
for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
|
||||
{
|
||||
if (set_minus_o_option (mode, l->word->word) == EXECUTION_FAILURE)
|
||||
rval = EXECUTION_FAILURE;
|
||||
}
|
||||
set_shellopts ();
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* If we set or unset interactive_comments with shopt, make sure the
|
||||
change is reflected in $SHELLOPTS. */
|
||||
static int
|
||||
set_shellopts_after_change (option_name, mode)
|
||||
char *option_name;
|
||||
int mode;
|
||||
{
|
||||
set_shellopts ();
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
shopt_enable_hostname_completion (option_name, mode)
|
||||
char *option_name;
|
||||
int mode;
|
||||
{
|
||||
return (enable_hostname_completion (mode));
|
||||
}
|
||||
|
||||
static int
|
||||
set_compatibility_level (option_name, mode)
|
||||
char *option_name;
|
||||
int mode;
|
||||
{
|
||||
/* Need to change logic here as we add more compatibility levels */
|
||||
|
||||
/* First, check option_name so we can turn off other compat options when
|
||||
one is set. */
|
||||
if (mode && option_name[6] == '3' && option_name[7] == '1')
|
||||
shopt_compat32 = shopt_compat40 = 0;
|
||||
else if (mode && option_name[6] == '3' && option_name[7] == '2')
|
||||
shopt_compat31 = shopt_compat40 = 0;
|
||||
else if (mode && option_name[6] == '4' && option_name[7] == '0')
|
||||
shopt_compat31 = shopt_compat32 = 0;
|
||||
|
||||
/* Then set shell_compatibility_level based on what remains */
|
||||
if (shopt_compat31)
|
||||
shell_compatibility_level = 31;
|
||||
else if (shopt_compat32)
|
||||
shell_compatibility_level = 32;
|
||||
else if (shopt_compat40)
|
||||
shell_compatibility_level = 40;
|
||||
else
|
||||
shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
/* Don't allow the value of restricted_shell to be modified. */
|
||||
|
||||
static int
|
||||
set_restricted_shell (option_name, mode)
|
||||
char *option_name;
|
||||
int mode;
|
||||
{
|
||||
static int save_restricted = -1;
|
||||
|
||||
if (save_restricted == -1)
|
||||
save_restricted = shell_is_restricted (shell_name);
|
||||
|
||||
restricted_shell = save_restricted;
|
||||
return (0);
|
||||
}
|
||||
#endif /* RESTRICTED_SHELL */
|
||||
|
||||
/* Not static so shell.c can call it to initialize shopt_login_shell */
|
||||
int
|
||||
set_login_shell (option_name, mode)
|
||||
char *option_name;
|
||||
int mode;
|
||||
{
|
||||
shopt_login_shell = login_shell != 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
char **
|
||||
get_shopt_options ()
|
||||
{
|
||||
char **ret;
|
||||
int n, i;
|
||||
|
||||
n = sizeof (shopt_vars) / sizeof (shopt_vars[0]);
|
||||
ret = strvec_create (n + 1);
|
||||
for (i = 0; shopt_vars[i].name; i++)
|
||||
ret[i] = savestring (shopt_vars[i].name);
|
||||
ret[i] = (char *)NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* External interface for other parts of the shell. NAME is a string option;
|
||||
* MODE is 0 if we want to unset an option; 1 if we want to set an option.
|
||||
* REUSABLE is 1 if we want to print output in a form that may be reused.
|
||||
*/
|
||||
int
|
||||
shopt_setopt (name, mode)
|
||||
char *name;
|
||||
int mode;
|
||||
{
|
||||
WORD_LIST *wl;
|
||||
int r;
|
||||
|
||||
wl = add_string_to_list (name, (WORD_LIST *)NULL);
|
||||
r = toggle_shopts (mode, wl, 0);
|
||||
dispose_words (wl);
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
shopt_listopt (name, reusable)
|
||||
char *name;
|
||||
int reusable;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (name == 0)
|
||||
return (list_shopts ((WORD_LIST *)NULL, reusable ? PFLAG : 0));
|
||||
|
||||
i = find_shopt (name);
|
||||
if (i < 0)
|
||||
{
|
||||
shopt_error (name);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
print_shopt (name, *shopt_vars[i].value, reusable ? PFLAG : 0);
|
||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
||||
}
|
||||
|
||||
void
|
||||
set_bashopts ()
|
||||
{
|
||||
char *value;
|
||||
char tflag[N_SHOPT_OPTIONS];
|
||||
int vsize, i, vptr, *ip, exported;
|
||||
SHELL_VAR *v;
|
||||
|
||||
for (vsize = i = 0; shopt_vars[i].name; i++)
|
||||
{
|
||||
tflag[i] = 0;
|
||||
if (GET_SHOPT_OPTION_VALUE (i))
|
||||
{
|
||||
vsize += strlen (shopt_vars[i].name) + 1;
|
||||
tflag[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
value = (char *)xmalloc (vsize + 1);
|
||||
|
||||
for (i = vptr = 0; shopt_vars[i].name; i++)
|
||||
{
|
||||
if (tflag[i])
|
||||
{
|
||||
strcpy (value + vptr, shopt_vars[i].name);
|
||||
vptr += strlen (shopt_vars[i].name);
|
||||
value[vptr++] = ':';
|
||||
}
|
||||
}
|
||||
|
||||
if (vptr)
|
||||
vptr--; /* cut off trailing colon */
|
||||
value[vptr] = '\0';
|
||||
|
||||
v = find_variable ("BASHOPTS");
|
||||
|
||||
/* Turn off the read-only attribute so we can bind the new value, and
|
||||
note whether or not the variable was exported. */
|
||||
if (v)
|
||||
{
|
||||
VUNSETATTR (v, att_readonly);
|
||||
exported = exported_p (v);
|
||||
}
|
||||
else
|
||||
exported = 0;
|
||||
|
||||
v = bind_variable ("BASHOPTS", value, 0);
|
||||
|
||||
/* Turn the read-only attribute back on, and turn off the export attribute
|
||||
if it was set implicitly by mark_modified_vars and SHELLOPTS was not
|
||||
exported before we bound the new value. */
|
||||
VSETATTR (v, att_readonly);
|
||||
if (mark_modified_vars && exported == 0 && exported_p (v))
|
||||
VUNSETATTR (v, att_exported);
|
||||
|
||||
free (value);
|
||||
}
|
||||
|
||||
void
|
||||
parse_bashopts (value)
|
||||
char *value;
|
||||
{
|
||||
char *vname;
|
||||
int vptr, ind;
|
||||
|
||||
vptr = 0;
|
||||
while (vname = extract_colon_unit (value, &vptr))
|
||||
{
|
||||
ind = find_shopt (vname);
|
||||
if (ind >= 0)
|
||||
*shopt_vars[ind].value = 1;
|
||||
free (vname);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
initialize_bashopts (no_bashopts)
|
||||
int no_bashopts;
|
||||
{
|
||||
char *temp;
|
||||
SHELL_VAR *var;
|
||||
|
||||
if (no_bashopts == 0)
|
||||
{
|
||||
var = find_variable ("BASHOPTS");
|
||||
/* set up any shell options we may have inherited. */
|
||||
if (var && imported_p (var))
|
||||
{
|
||||
temp = (array_p (var) || assoc_p (var)) ? (char *)NULL : savestring (value_cell (var));
|
||||
if (temp)
|
||||
{
|
||||
parse_bashopts (temp);
|
||||
free (temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up the $BASHOPTS variable. */
|
||||
set_bashopts ();
|
||||
}
|
||||
+2
-1
@@ -1,7 +1,7 @@
|
||||
This file is test.def, from which is created test.c.
|
||||
It implements the builtin "test" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -80,6 +80,7 @@ String operators:
|
||||
Other operators:
|
||||
|
||||
-o OPTION True if the shell option OPTION is enabled.
|
||||
-v VAR True if the shell variable VAR is set
|
||||
! EXPR True if expr is false.
|
||||
EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.
|
||||
EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
This file is test.def, from which is created test.c.
|
||||
It implements the builtin "test" 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 test.c
|
||||
|
||||
$BUILTIN test
|
||||
$FUNCTION test_builtin
|
||||
$SHORT_DOC test [expr]
|
||||
Evaluate conditional expression.
|
||||
|
||||
Exits with a status of 0 (true) or 1 (false) depending on
|
||||
the evaluation of EXPR. Expressions may be unary or binary. Unary
|
||||
expressions are often used to examine the status of a file. There
|
||||
are string operators as well, and numeric comparison operators.
|
||||
|
||||
File operators:
|
||||
|
||||
-a FILE True if file exists.
|
||||
-b FILE True if file is block special.
|
||||
-c FILE True if file is character special.
|
||||
-d FILE True if file is a directory.
|
||||
-e FILE True if file exists.
|
||||
-f FILE True if file exists and is a regular file.
|
||||
-g FILE True if file is set-group-id.
|
||||
-h FILE True if file is a symbolic link.
|
||||
-L FILE True if file is a symbolic link.
|
||||
-k FILE True if file has its `sticky' bit set.
|
||||
-p FILE True if file is a named pipe.
|
||||
-r FILE True if file is readable by you.
|
||||
-s FILE True if file exists and is not empty.
|
||||
-S FILE True if file is a socket.
|
||||
-t FD True if FD is opened on a terminal.
|
||||
-u FILE True if the file is set-user-id.
|
||||
-w FILE True if the file is writable by you.
|
||||
-x FILE True if the file is executable by you.
|
||||
-O FILE True if the file is effectively owned by you.
|
||||
-G FILE True if the file is effectively owned by your group.
|
||||
-N FILE True if the file has been modified since it was last read.
|
||||
|
||||
FILE1 -nt FILE2 True if file1 is newer than file2 (according to
|
||||
modification date).
|
||||
|
||||
FILE1 -ot FILE2 True if file1 is older than file2.
|
||||
|
||||
FILE1 -ef FILE2 True if file1 is a hard link to file2.
|
||||
|
||||
String operators:
|
||||
|
||||
-z STRING True if string is empty.
|
||||
|
||||
-n STRING
|
||||
STRING True if string is not empty.
|
||||
|
||||
STRING1 = STRING2
|
||||
True if the strings are equal.
|
||||
STRING1 != STRING2
|
||||
True if the strings are not equal.
|
||||
STRING1 < STRING2
|
||||
True if STRING1 sorts before STRING2 lexicographically.
|
||||
STRING1 > STRING2
|
||||
True if STRING1 sorts after STRING2 lexicographically.
|
||||
|
||||
Other operators:
|
||||
|
||||
-o OPTION True if the shell option OPTION is enabled.
|
||||
-v VAR True if the shell variable VAR is set
|
||||
! EXPR True if expr is false.
|
||||
EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.
|
||||
EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.
|
||||
|
||||
arg1 OP arg2 Arithmetic tests. OP is one of -eq, -ne,
|
||||
-lt, -le, -gt, or -ge.
|
||||
|
||||
Arithmetic binary operators return true if ARG1 is equal, not-equal,
|
||||
less-than, less-than-or-equal, greater-than, or greater-than-or-equal
|
||||
than ARG2.
|
||||
|
||||
Exit Status:
|
||||
Returns success if EXPR evaluates to true; fails if EXPR evaluates to
|
||||
false or an invalid argument is given.
|
||||
$END
|
||||
|
||||
$BUILTIN [
|
||||
$DOCNAME test_bracket
|
||||
$FUNCTION test_builtin
|
||||
$SHORT_DOC [ arg... ]
|
||||
Evaluate conditional expression.
|
||||
|
||||
This is a synonym for the "test" builtin, but the last argument must
|
||||
be a literal `]', to match the opening `['.
|
||||
$END
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "../bashansi.h"
|
||||
#include "../bashintl.h"
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../test.h"
|
||||
#include "common.h"
|
||||
|
||||
extern char *this_command_name;
|
||||
|
||||
/* TEST/[ builtin. */
|
||||
int
|
||||
test_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
char **argv;
|
||||
int argc, result;
|
||||
|
||||
/* We let Matthew Bradburn and Kevin Braunsdorf's code do the
|
||||
actual test command. So turn the list of args into an array
|
||||
of strings, since that is what their code wants. */
|
||||
if (list == 0)
|
||||
{
|
||||
if (this_command_name[0] == '[' && !this_command_name[1])
|
||||
{
|
||||
builtin_error (_("missing `]'"));
|
||||
return (EX_BADUSAGE);
|
||||
}
|
||||
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
argv = make_builtin_argv (list, &argc);
|
||||
result = test_command (argc, argv);
|
||||
free ((char *)argv);
|
||||
|
||||
return (result);
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
This file is trap.def, from which is created trap.c.
|
||||
It implements the builtin "trap" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ trap_builtin (list)
|
||||
else if (display || list == 0)
|
||||
{
|
||||
initialize_terminating_signals ();
|
||||
get_all_original_signals ();
|
||||
return (sh_chkwrite (display_traps (list)));
|
||||
}
|
||||
else
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
This file is ulimit.def, from which is created ulimit.c.
|
||||
It implements the builtin "ulimit" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ extern int errno;
|
||||
# undef HAVE_RESOURCE
|
||||
#endif
|
||||
|
||||
#if !HAVE_RESOURCE && HAVE_ULIMIT_H
|
||||
#if !defined (HAVE_RESOURCE) && defined (HAVE_ULIMIT_H)
|
||||
# include <ulimit.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* command.h -- The structures used internally to represent commands, and
|
||||
the extern declarations of the functions used to create them. */
|
||||
|
||||
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
|
||||
#define SUBSHELL_PIPE 0x10 /* subshell from a pipeline element */
|
||||
#define SUBSHELL_PROCSUB 0x20 /* subshell caused by <(command) or >(command) */
|
||||
#define SUBSHELL_COPROC 0x40 /* subshell from a coproc pipeline */
|
||||
#define SUBSHELL_RESETTRAP 0x80 /* subshell needs to reset trap strings on first call to trap */
|
||||
|
||||
/* A structure which represents a word. */
|
||||
typedef struct word_desc {
|
||||
|
||||
+66
-19
@@ -5,12 +5,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.cwru.edu
|
||||
.\"
|
||||
.\" Last Change: Sat Apr 17 23:24:15 EDT 2010
|
||||
.\" Last Change: Sun May 30 17:03:08 EDT 2010
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2010 April 17" "GNU Bash-4.1"
|
||||
.TH BASH 1 "2010 May 30" "GNU Bash-4.1"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -565,6 +565,15 @@ under
|
||||
.B "Shell Variables"
|
||||
below.
|
||||
.PP
|
||||
When the shell is in \fIposix mode\fP, \fBtime\fP
|
||||
may be followed by a newline. In this case, the shell displays the
|
||||
total user and system time consumed by the shell and its children.
|
||||
The
|
||||
.SM
|
||||
.B TIMEFORMAT
|
||||
variable may be used to specify the format of
|
||||
the time information.
|
||||
.PP
|
||||
Each command in a pipeline is executed as a separate process (i.e., in a
|
||||
subshell).
|
||||
.SS Lists
|
||||
@@ -1881,6 +1890,11 @@ A sample value is
|
||||
.if t \f(CW".o:~"\fP.
|
||||
.if n ".o:~".
|
||||
.TP
|
||||
.B FUNCNEST
|
||||
If set to a numeric value greater than 0, defines a maximum function
|
||||
nesting level. Function invocations that exceed this nesting level
|
||||
will cause the current command to abort.
|
||||
.TP
|
||||
.B GLOBIGNORE
|
||||
A colon-separated list of patterns defining the set of filenames to
|
||||
be ignored by pathname expansion.
|
||||
@@ -3781,6 +3795,11 @@ Variables local to the function may be declared with the
|
||||
builtin command. Ordinarily, variables and their values
|
||||
are shared between the function and its caller.
|
||||
.PP
|
||||
The \fBFUNCNEST\fP variable, if set to a numeric value greater
|
||||
than 0, defines a maximum function nesting level. Function
|
||||
invocations that exceed the limit cause the entire command to
|
||||
abort.
|
||||
.PP
|
||||
If the builtin command
|
||||
.B return
|
||||
is executed in a function, the function completes and
|
||||
@@ -4021,7 +4040,7 @@ True if \fIfile1\fP is older than \fIfile2\fP, or if \fIfile2\fP exists
|
||||
and \fIfile1\fP does not.
|
||||
.TP
|
||||
.B \-o \fIoptname\fP
|
||||
True if shell option
|
||||
True if the shell option
|
||||
.I optname
|
||||
is enabled.
|
||||
See the list of options under the description of the
|
||||
@@ -4030,6 +4049,11 @@ option to the
|
||||
.B set
|
||||
builtin below.
|
||||
.TP
|
||||
.B \-v \fIvarname\fP
|
||||
True if the shell variable
|
||||
.I varname
|
||||
is set (has been assigned a value).
|
||||
.TP
|
||||
.B \-z \fIstring\fP
|
||||
True if the length of \fIstring\fP is zero.
|
||||
.TP
|
||||
@@ -7058,10 +7082,10 @@ is greater than the number of enclosing loops, the last enclosing loop
|
||||
(the ``top-level'' loop) is resumed.
|
||||
The return value is 0 unless \fIn\fP is not greater than or equal to 1.
|
||||
.TP
|
||||
\fBdeclare\fP [\fB\-aAfFilrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
|
||||
\fBdeclare\fP [\fB\-aAfFgilrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
|
||||
.PD 0
|
||||
.TP
|
||||
\fBtypeset\fP [\fB\-aAfFilrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
|
||||
\fBtypeset\fP [\fB\-aAfFgilrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
|
||||
.PD
|
||||
Declare variables and/or give them attributes.
|
||||
If no \fIname\fPs are given then display the values of variables.
|
||||
@@ -7090,6 +7114,11 @@ are displayed as well. The
|
||||
.B \-F
|
||||
option implies
|
||||
.BR \-f .
|
||||
The
|
||||
.B \-g
|
||||
option forces variables to be created or modified at the global scope,
|
||||
even when \fBdeclare\fP is executed in a shell function.
|
||||
It is ignored in all other cases.
|
||||
The following options can
|
||||
be used to restrict output to variables with the specified attribute or
|
||||
to give variables attributes:
|
||||
@@ -7144,11 +7173,11 @@ turns off the attribute instead,
|
||||
with the exceptions that \fB+a\fP
|
||||
may not be used to destroy an array variable and \fB+r\fP will not
|
||||
remove the readonly attribute.
|
||||
When used in a function,
|
||||
makes each
|
||||
When used in a function, makes each
|
||||
\fIname\fP local, as with the
|
||||
.B local
|
||||
command.
|
||||
command,
|
||||
unless the \fB\-g\P option is supplied,
|
||||
If a variable name is followed by =\fIvalue\fP, the value of
|
||||
the variable is set to \fIvalue\fP.
|
||||
The return value is 0 unless an invalid option is encountered,
|
||||
@@ -8004,7 +8033,8 @@ is specified without
|
||||
.BR \-c ,
|
||||
the default quantum is 5000.
|
||||
When \fIcallback\fP is evaluated, it is supplied the index of the next
|
||||
array element to be assigned as an additional argument.
|
||||
array element to be assigned and the line to be assigned to that element
|
||||
as additional arguments.
|
||||
\fIcallback\fP is evaluated after the line is read but before the
|
||||
array element is assigned.
|
||||
.PP
|
||||
@@ -8068,32 +8098,49 @@ directory change fails.
|
||||
\fBprintf\fP [\fB\-v\fP \fIvar\fP] \fIformat\fP [\fIarguments\fP]
|
||||
Write the formatted \fIarguments\fP to the standard output under the
|
||||
control of the \fIformat\fP.
|
||||
The \fB\-v\fP option causes the output to be assigned to the variable
|
||||
\fIvar\fP rather than being printed to the standard output.
|
||||
.sp 1
|
||||
The \fIformat\fP is a character string which contains three types of objects:
|
||||
plain characters, which are simply copied to standard output, character
|
||||
escape sequences, which are converted and copied to the standard output, and
|
||||
format specifications, each of which causes printing of the next successive
|
||||
\fIargument\fP.
|
||||
In addition to the standard \fIprintf\fP(1) formats, \fB%b\fP causes
|
||||
In addition to the standard \fIprintf\fP(1) format specifications,
|
||||
\fBprintf\fP interprets the following extensions:
|
||||
.RS
|
||||
.PD 0
|
||||
.TP
|
||||
.B %b
|
||||
causes
|
||||
\fBprintf\fP to expand backslash escape sequences in the corresponding
|
||||
\fIargument\fP (except that \fB\ec\fP terminates output, backslashes in
|
||||
\fB\e\(aq\fP, \fB\e"\fP, and \fB\e?\fP are not removed, and octal escapes
|
||||
beginning with \fB\e0\fP may contain up to four digits),
|
||||
and \fB%q\fP causes \fBprintf\fP to output the corresponding
|
||||
beginning with \fB\e0\fP may contain up to four digits).
|
||||
.TP
|
||||
.B %q
|
||||
causes \fBprintf\fP to output the corresponding
|
||||
\fIargument\fP in a format that can be reused as shell input.
|
||||
.sp 1
|
||||
.TP
|
||||
.B %(\fIdatefmt\fP)T
|
||||
causes \fBprintf\fP to output the date-time string resulting from using
|
||||
\fIdatefmt\fP as a format string for \fIstrftime\fP(3). The corresponding
|
||||
\fIargument\fP is an integer representing the number of seconds since the
|
||||
epoch. Two special argument values may be used: -1 represents the current
|
||||
time, and -2 represents the time the shell was invoked.
|
||||
.PD
|
||||
.PP
|
||||
Arguments to non-string format specifiers are treated as C constants,
|
||||
except that a leading plus or minus sign is allowed, and if the leading
|
||||
character is a single or double quote, the value is the ASCII value of
|
||||
the following character.
|
||||
.sp 1
|
||||
The \fB\-v\fP option causes the output to be assigned to the variable
|
||||
\fIvar\fP rather than being printed to the standard output.
|
||||
.sp 1
|
||||
.PP
|
||||
The \fIformat\fP is reused as necessary to consume all of the \fIarguments\fP.
|
||||
If the \fIformat\fP requires more \fIarguments\fP than are supplied, the
|
||||
extra format specifications behave as if a zero value or null string, as
|
||||
appropriate, had been supplied. The return value is zero on success,
|
||||
non-zero on failure.
|
||||
appropriate, had been supplied.
|
||||
The return value is zero on success, non-zero on failure.
|
||||
.RE
|
||||
.TP
|
||||
\fBpushd\fP [\fB\-n\fP] [+\fIn\fP] [\-\fIn\fP]
|
||||
.PD 0
|
||||
|
||||
+82
-19
@@ -5,12 +5,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.cwru.edu
|
||||
.\"
|
||||
.\" Last Change: Sat Apr 17 23:24:15 EDT 2010
|
||||
.\" Last Change: Sat May 29 20:59:17 EDT 2010
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2010 April 17" "GNU Bash-4.1"
|
||||
.TH BASH 1 "2010 May 29" "GNU Bash-4.1"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -565,6 +565,15 @@ under
|
||||
.B "Shell Variables"
|
||||
below.
|
||||
.PP
|
||||
When the shell is in \fIposix mode\fP, \fBtime\fP
|
||||
may be followed by a newline. In this case, the shell displays the
|
||||
total user and system time consumed by the shell and its children.
|
||||
The
|
||||
.SM
|
||||
.B TIMEFORMAT
|
||||
variable may be used to specify the format of
|
||||
the time information.
|
||||
.PP
|
||||
Each command in a pipeline is executed as a separate process (i.e., in a
|
||||
subshell).
|
||||
.SS Lists
|
||||
@@ -1104,6 +1113,14 @@ the eight-bit character whose value is the octal value \fInnn\fP
|
||||
the eight-bit character whose value is the hexadecimal value \fIHH\fP
|
||||
(one or two hex digits)
|
||||
.TP
|
||||
.B \eu\fIHHHH\fP
|
||||
the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
|
||||
\fIHHHH\fP (one to four hex digits)
|
||||
.TP
|
||||
.B \eU\fIHHHHHHHH\fP
|
||||
the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
|
||||
\fIHHHHHHHH\fP (one to eight hex digits)
|
||||
.TP
|
||||
.B \ec\fIx\fP
|
||||
a control-\fIx\fP character
|
||||
.PD
|
||||
@@ -1873,6 +1890,11 @@ A sample value is
|
||||
.if t \f(CW".o:~"\fP.
|
||||
.if n ".o:~".
|
||||
.TP
|
||||
.B FUNCNEST
|
||||
If set to a numeric value greater than 0, defines a maximum function
|
||||
nesting level. Function invocations that exceed this nesting level
|
||||
will cause the current command to abort.
|
||||
.TP
|
||||
.B GLOBIGNORE
|
||||
A colon-separated list of patterns defining the set of filenames to
|
||||
be ignored by pathname expansion.
|
||||
@@ -3773,6 +3795,11 @@ Variables local to the function may be declared with the
|
||||
builtin command. Ordinarily, variables and their values
|
||||
are shared between the function and its caller.
|
||||
.PP
|
||||
The \fBFUNCNEST\fP variable, if set to a numeric value greater
|
||||
than 0, defines a maximum function nesting level. Function
|
||||
invocations that exceed the limit cause the entire command to
|
||||
abort.
|
||||
.PP
|
||||
If the builtin command
|
||||
.B return
|
||||
is executed in a function, the function completes and
|
||||
@@ -4013,7 +4040,7 @@ True if \fIfile1\fP is older than \fIfile2\fP, or if \fIfile2\fP exists
|
||||
and \fIfile1\fP does not.
|
||||
.TP
|
||||
.B \-o \fIoptname\fP
|
||||
True if shell option
|
||||
True if the shell option
|
||||
.I optname
|
||||
is enabled.
|
||||
See the list of options under the description of the
|
||||
@@ -4022,6 +4049,11 @@ option to the
|
||||
.B set
|
||||
builtin below.
|
||||
.TP
|
||||
.B \-v \fIvarname\fP
|
||||
True if the shell variable
|
||||
.I varname
|
||||
is set (has been assigned a value).
|
||||
.TP
|
||||
.B \-z \fIstring\fP
|
||||
True if the length of \fIstring\fP is zero.
|
||||
.TP
|
||||
@@ -7050,10 +7082,10 @@ is greater than the number of enclosing loops, the last enclosing loop
|
||||
(the ``top-level'' loop) is resumed.
|
||||
The return value is 0 unless \fIn\fP is not greater than or equal to 1.
|
||||
.TP
|
||||
\fBdeclare\fP [\fB\-aAfFilrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
|
||||
\fBdeclare\fP [\fB\-aAfFgilrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
|
||||
.PD 0
|
||||
.TP
|
||||
\fBtypeset\fP [\fB\-aAfFilrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
|
||||
\fBtypeset\fP [\fB\-aAfFgilrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
|
||||
.PD
|
||||
Declare variables and/or give them attributes.
|
||||
If no \fIname\fPs are given then display the values of variables.
|
||||
@@ -7082,6 +7114,11 @@ are displayed as well. The
|
||||
.B \-F
|
||||
option implies
|
||||
.BR \-f .
|
||||
The
|
||||
.B \-g
|
||||
option forces variables to be created or modified at the global scope,
|
||||
even when \fBdeclare\fP is executed in a shell function.
|
||||
It is ignored in all other cases.
|
||||
The following options can
|
||||
be used to restrict output to variables with the specified attribute or
|
||||
to give variables attributes:
|
||||
@@ -7136,11 +7173,11 @@ turns off the attribute instead,
|
||||
with the exceptions that \fB+a\fP
|
||||
may not be used to destroy an array variable and \fB+r\fP will not
|
||||
remove the readonly attribute.
|
||||
When used in a function,
|
||||
makes each
|
||||
When used in a function, makes each
|
||||
\fIname\fP local, as with the
|
||||
.B local
|
||||
command.
|
||||
command,
|
||||
unless the \fB\-g\P option is supplied,
|
||||
If a variable name is followed by =\fIvalue\fP, the value of
|
||||
the variable is set to \fIvalue\fP.
|
||||
The return value is 0 unless an invalid option is encountered,
|
||||
@@ -7293,6 +7330,14 @@ the eight-bit character whose value is the octal value \fInnn\fP
|
||||
.B \ex\fIHH\fP
|
||||
the eight-bit character whose value is the hexadecimal value \fIHH\fP
|
||||
(one or two hex digits)
|
||||
.TP
|
||||
.B \eu\fIHHHH\fP
|
||||
the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
|
||||
\fIHHHH\fP (one to four hex digits)
|
||||
.TP
|
||||
.B \eU\fIHHHHHHHH\fP
|
||||
the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
|
||||
\fIHHHHHHHH\fP (one to eight hex digits)
|
||||
.PD
|
||||
.RE
|
||||
.TP
|
||||
@@ -7988,7 +8033,8 @@ is specified without
|
||||
.BR \-c ,
|
||||
the default quantum is 5000.
|
||||
When \fIcallback\fP is evaluated, it is supplied the index of the next
|
||||
array element to be assigned as an additional argument.
|
||||
array element to be assigned and the line to be assigned to that element
|
||||
as additional arguments.
|
||||
\fIcallback\fP is evaluated after the line is read but before the
|
||||
array element is assigned.
|
||||
.PP
|
||||
@@ -8052,32 +8098,49 @@ directory change fails.
|
||||
\fBprintf\fP [\fB\-v\fP \fIvar\fP] \fIformat\fP [\fIarguments\fP]
|
||||
Write the formatted \fIarguments\fP to the standard output under the
|
||||
control of the \fIformat\fP.
|
||||
The \fB\-v\fP option causes the output to be assigned to the variable
|
||||
\fIvar\fP rather than being printed to the standard output.
|
||||
.sp 1
|
||||
The \fIformat\fP is a character string which contains three types of objects:
|
||||
plain characters, which are simply copied to standard output, character
|
||||
escape sequences, which are converted and copied to the standard output, and
|
||||
format specifications, each of which causes printing of the next successive
|
||||
\fIargument\fP.
|
||||
In addition to the standard \fIprintf\fP(1) formats, \fB%b\fP causes
|
||||
In addition to the standard \fIprintf\fP(1) format specifications,
|
||||
\fBprintf\fP interprets the following extensions:
|
||||
.RS
|
||||
.PD 0
|
||||
.TP
|
||||
.B %b
|
||||
causes
|
||||
\fBprintf\fP to expand backslash escape sequences in the corresponding
|
||||
\fIargument\fP (except that \fB\ec\fP terminates output, backslashes in
|
||||
\fB\e\(aq\fP, \fB\e"\fP, and \fB\e?\fP are not removed, and octal escapes
|
||||
beginning with \fB\e0\fP may contain up to four digits),
|
||||
and \fB%q\fP causes \fBprintf\fP to output the corresponding
|
||||
beginning with \fB\e0\fP may contain up to four digits).
|
||||
.TP
|
||||
.B %q
|
||||
causes \fBprintf\fP to output the corresponding
|
||||
\fIargument\fP in a format that can be reused as shell input.
|
||||
.sp 1
|
||||
.TP
|
||||
.B %(\fIdatefmt\fP)T
|
||||
causes \fBprintf\fP to output the date-time string resulting from using
|
||||
\fIdatefmt\fP as a format string for \fIstrftime\fP(3). The corresponding
|
||||
\fIargument\fP is an integer representing the number of seconds since the
|
||||
epoch. Two special argument values may be used: -1 represents the current
|
||||
time, and -2 represents the time the shell was invoked.
|
||||
.PD
|
||||
.PP
|
||||
Arguments to non-string format specifiers are treated as C constants,
|
||||
except that a leading plus or minus sign is allowed, and if the leading
|
||||
character is a single or double quote, the value is the ASCII value of
|
||||
the following character.
|
||||
.sp 1
|
||||
The \fB\-v\fP option causes the output to be assigned to the variable
|
||||
\fIvar\fP rather than being printed to the standard output.
|
||||
.sp 1
|
||||
.PP
|
||||
The \fIformat\fP is reused as necessary to consume all of the \fIarguments\fP.
|
||||
If the \fIformat\fP requires more \fIarguments\fP than are supplied, the
|
||||
extra format specifications behave as if a zero value or null string, as
|
||||
appropriate, had been supplied. The return value is zero on success,
|
||||
non-zero on failure.
|
||||
appropriate, had been supplied.
|
||||
The return value is zero on success, non-zero on failure.
|
||||
.RE
|
||||
.TP
|
||||
\fBpushd\fP [\fB\-n\fP] [+\fIn\fP] [\-\fIn\fP]
|
||||
.PD 0
|
||||
|
||||
+143
-12
@@ -596,6 +596,7 @@ some other grouping.
|
||||
* Lists:: How to execute commands sequentially.
|
||||
* Compound Commands:: Shell commands for control flow.
|
||||
* Coprocesses:: Two-way communication between commands.
|
||||
* GNU Parallel:: Running commands in parallel.
|
||||
@end menu
|
||||
|
||||
@node Simple Commands
|
||||
@@ -654,6 +655,12 @@ The use of @code{time} as a reserved word permits the timing of
|
||||
shell builtins, shell functions, and pipelines. An external
|
||||
@code{time} command cannot time these easily.
|
||||
|
||||
When the shell is in @sc{posix} mode (@pxref{Bash POSIX Mode}), @code{time}
|
||||
may be followed by a newline. In this case, the shell displays the
|
||||
total user and system time consumed by the shell and its children.
|
||||
The @env{TIMEFORMAT} variable may be used to specify the format of
|
||||
the time information.
|
||||
|
||||
If the pipeline is not executed asynchronously (@pxref{Lists}), the
|
||||
shell waits for all commands in the pipeline to complete.
|
||||
|
||||
@@ -1132,6 +1139,79 @@ builtin command may be used to wait for the coprocess to terminate.
|
||||
|
||||
The return status of a coprocess is the exit status of @var{command}.
|
||||
|
||||
@node GNU Parallel
|
||||
@subsection GNU Parallel
|
||||
|
||||
GNU Parallel, as its name suggests, can be used to build and run commands
|
||||
in parallel. You may run the same command with different arguments, whether
|
||||
they are filenames, usernames, hostnames, or lines read from files.
|
||||
|
||||
For a complete description, refer to the GNU Parallel documentation. A few
|
||||
examples should provide a brief introduction to its use.
|
||||
|
||||
For example, it is easy to prefix each line in a text file with a specified
|
||||
string:
|
||||
@example
|
||||
cat file | parallel -k echo prefix_string
|
||||
@end example
|
||||
|
||||
The @option{-k} option is required to preserve the lines' order.
|
||||
|
||||
Similarly, you can append a specified string to each line in a text file:
|
||||
@example
|
||||
cat file | parallel -k echo @{@} append_string
|
||||
@end example
|
||||
|
||||
You can use Parallel to move files from the current directory when the
|
||||
number of files is too large to process with one @code{mv} invocation:
|
||||
@example
|
||||
ls | parallel mv @{@} destdir
|
||||
@end example
|
||||
|
||||
As you can see, the @{@} is replaced with each line read from standard input.
|
||||
This will run as many @code{mv} commands as there are files in the current
|
||||
directory. You can emulate a parallel @code{xargs} by adding the @option{-X}
|
||||
option:
|
||||
@example
|
||||
ls | parallel -X mv @{@} destdir
|
||||
@end example
|
||||
|
||||
GNU Parallel can replace certain common idioms that operate on lines read
|
||||
from a file (in this case, filenames):
|
||||
@example
|
||||
for x in $(cat list); do
|
||||
do-something1 $x config-$x
|
||||
do-something2 < $x
|
||||
done | process-output
|
||||
@end example
|
||||
|
||||
with a more compact syntax reminiscent of lambdas:
|
||||
@example
|
||||
cat list | parallel "do-something1 @{@} config-@{@} ; do-something2 < @{@}" | process-output
|
||||
@end example
|
||||
|
||||
Parallel provides a built-in mechanism to remove filename extensions, which
|
||||
lends itself to batch file transformations or renaming:
|
||||
@example
|
||||
ls *.gz | parallel -j+0 "zcat @{@} | bzip2 >@{.@}.bz2 && rm @{@}"
|
||||
@end example
|
||||
|
||||
This will recompress all files in the current directory with names ending
|
||||
in .gz using bzip2, running one job per CPU (-j+0) in parallel.
|
||||
|
||||
If a command generates output, you may want to preserve the input order in
|
||||
the output. For instance, the following command
|
||||
@example
|
||||
@{ echo foss.org.my ; echo debian.org; echo freenetproject.org; @} | parallel traceroute
|
||||
@end example
|
||||
|
||||
will display as output the traceroute invocation that finishes first. Using
|
||||
the @option{-k} option, as we saw above
|
||||
@example
|
||||
@{ echo foss.org.my ; echo debian.org; echo freenetproject.org; @} | parallel -k traceroute
|
||||
@end example
|
||||
will ensure that the output of @code{traceroute foss.org.my} is displayed first.
|
||||
|
||||
@node Shell Functions
|
||||
@section Shell Functions
|
||||
@cindex shell function
|
||||
@@ -1204,6 +1284,11 @@ shell option has been enabled.
|
||||
@xref{Bourne Shell Builtins}, for the description of the
|
||||
@code{trap} builtin.
|
||||
|
||||
The @env{FUNCNEST} variable, if set to a numeric value greater
|
||||
than 0, defines a maximum function nesting level. Function
|
||||
invocations that exceed the limit cause the entire command to
|
||||
abort.
|
||||
|
||||
If the builtin command @code{return}
|
||||
is executed in a function, the function completes and
|
||||
execution resumes with the next command after the function
|
||||
@@ -3456,6 +3541,11 @@ If the @code{extdebug} shell option is enabled using @code{shopt}
|
||||
(@pxref{The Shopt Builtin}), the source file name and line number where
|
||||
the function is defined are displayed as well.
|
||||
@option{-F} implies @option{-f}.
|
||||
|
||||
The @option{-g} option forces variables to be created or modified at
|
||||
the global scope, even when \fBdeclare\fP is executed in a shell function.
|
||||
It is ignored in all other cases.
|
||||
|
||||
The following options can be used to restrict output to variables with
|
||||
the specified attributes or to give variables attributes:
|
||||
|
||||
@@ -3504,8 +3594,9 @@ with the exceptions that @samp{+a}
|
||||
may not be used to destroy an array variable and @samp{+r} will not
|
||||
remove the readonly attribute.
|
||||
When used in a function, @code{declare} makes each @var{name} local,
|
||||
as with the @code{local} command. If a variable name is followed by
|
||||
=@var{value}, the value of the variable is set to @var{value}.
|
||||
as with the @code{local} command, unless the @samp{-g} option is used.
|
||||
If a variable name is followed by =@var{value}, the value of the variable
|
||||
is set to @var{value}.
|
||||
|
||||
The return status is zero unless an invalid option is encountered,
|
||||
an attempt is made to define a function using @samp{-f foo=bar},
|
||||
@@ -3693,7 +3784,8 @@ Specify the number of lines read between each call to @var{callback}.
|
||||
If @option{-C} is specified without @option{-c},
|
||||
the default quantum is 5000.
|
||||
When @var{callback} is evaluated, it is supplied the index of the next
|
||||
array element to be assigned as an additional argument.
|
||||
array element to be assigned and the line to be assigned to that element
|
||||
as additional arguments.
|
||||
@var{callback} is evaluated after the line is read but before the
|
||||
array element is assigned.
|
||||
|
||||
@@ -3711,28 +3803,41 @@ printf [-v @var{var}] @var{format} [@var{arguments}]
|
||||
@end example
|
||||
Write the formatted @var{arguments} to the standard output under the
|
||||
control of the @var{format}.
|
||||
The @option{-v} option causes the output to be assigned to the variable
|
||||
@var{var} rather than being printed to the standard output.
|
||||
|
||||
The @var{format} is a character string which contains three types of objects:
|
||||
plain characters, which are simply copied to standard output, character
|
||||
escape sequences, which are converted and copied to the standard output, and
|
||||
format specifications, each of which causes printing of the next successive
|
||||
@var{argument}.
|
||||
In addition to the standard @code{printf(1)} formats, @samp{%b} causes
|
||||
@code{printf} to expand backslash escape sequences in the corresponding
|
||||
@var{argument},
|
||||
In addition to the standard @code{printf(1)} formats, @code{printf}
|
||||
interprets the following extensions:
|
||||
|
||||
@table @code
|
||||
@item %b
|
||||
causes @code{printf} to expand backslash escape sequences in the
|
||||
corresponding @var{argument},
|
||||
(except that @samp{\c} terminates output, backslashes in
|
||||
@samp{\'}, @samp{\"}, and @samp{\?} are not removed, and octal escapes
|
||||
beginning with @samp{\0} may contain up to four digits),
|
||||
and @samp{%q} causes @code{printf} to output the
|
||||
beginning with @samp{\0} may contain up to four digits).
|
||||
@item %q
|
||||
causes @code{printf} to output the
|
||||
corresponding @var{argument} in a format that can be reused as shell input.
|
||||
@item %(@var{datefmt})T
|
||||
causes @code{printf} to output the date-time string resulting from using
|
||||
@var{datefmt} as a format string for @code{strftime}(3). The corresponding
|
||||
@var{argument} is an integer representing the number of seconds since the
|
||||
epoch. Two special argument values may be used: -1 represents the current
|
||||
time, and -2 represents the time the shell was invoked.
|
||||
@end table
|
||||
|
||||
@noindent
|
||||
Arguments to non-string format specifiers are treated as C language constants,
|
||||
except that a leading plus or minus sign is allowed, and if the leading
|
||||
character is a single or double quote, the value is the ASCII value of
|
||||
the following character.
|
||||
|
||||
The @option{-v} option causes the output to be assigned to the variable
|
||||
@var{var} rather than being printed to the standard output.
|
||||
|
||||
The @var{format} is reused as necessary to consume all of the @var{arguments}.
|
||||
If the @var{format} requires more @var{arguments} than are supplied, the
|
||||
extra format specifications behave as if a zero value or null string, as
|
||||
@@ -4954,6 +5059,11 @@ Assignments to @env{FUNCNAME} have no effect and return an error status.
|
||||
If @env{FUNCNAME} is unset, it loses its special properties, even if
|
||||
it is subsequently reset.
|
||||
|
||||
@item FUNCNEST
|
||||
If set to a numeric value greater than 0, defines a maximum function
|
||||
nesting level. Function invocations that exceed this nesting level
|
||||
will cause the current command to abort.
|
||||
|
||||
@item GLOBIGNORE
|
||||
A colon-separated list of patterns defining the set of filenames to
|
||||
be ignored by filename expansion.
|
||||
@@ -5855,10 +5965,13 @@ True if @var{file1} is older than @var{file2},
|
||||
or if @var{file2} exists and @var{file1} does not.
|
||||
|
||||
@item -o @var{optname}
|
||||
True if shell option @var{optname} is enabled.
|
||||
True if the shell option @var{optname} is enabled.
|
||||
The list of options appears in the description of the @option{-o}
|
||||
option to the @code{set} builtin (@pxref{The Set Builtin}).
|
||||
|
||||
@item -v @var{varname}
|
||||
True if the shell variable @var{varname} is set (has been assigned a value).
|
||||
|
||||
@item -z @var{string}
|
||||
True if the length of @var{string} is zero.
|
||||
|
||||
@@ -6489,6 +6602,11 @@ is not found.
|
||||
Non-interactive shells exit if a syntax error in an arithmetic expansion
|
||||
results in an invalid expression.
|
||||
|
||||
@item
|
||||
Non-interactive shells exit if there is a syntax error in a script read
|
||||
with the @code{.} or @code{source} builtins, or in a string processed by
|
||||
the @code{eval} builtin.
|
||||
|
||||
@item
|
||||
Redirection operators do not perform filename expansion on the word
|
||||
in the redirection unless the shell is interactive.
|
||||
@@ -6507,6 +6625,19 @@ causes a fatal syntax error in non-interactive shells.
|
||||
@sc{posix} special builtins are found before shell functions
|
||||
during command lookup.
|
||||
|
||||
@item
|
||||
The @code{time} reserved word may be used by itself as a command. When
|
||||
used in this way, it displays timing statistics for the shell and its
|
||||
completed children. The @env{TIMEFORMAT} variable controls the format
|
||||
of the timing information.
|
||||
|
||||
@item
|
||||
When parsing and expanding a $@{@dots{}@} expansion that appears within
|
||||
double quotes, single quotes are no longer special and cannot be used to
|
||||
quote a closing brace or other special character, unless the operator is
|
||||
one of those defined to perform pattern removal. In this case, they do
|
||||
not have to appear as matched pairs.
|
||||
|
||||
@item
|
||||
If a @sc{posix} special builtin returns an error status, a
|
||||
non-interactive shell exits. The fatal errors are those listed in
|
||||
|
||||
+134
-4
@@ -522,6 +522,12 @@ the eight-bit character whose value is the octal value @var{nnn}
|
||||
@item \x@var{HH}
|
||||
the eight-bit character whose value is the hexadecimal value @var{HH}
|
||||
(one or two hex digits)
|
||||
@item \u@var{HHHH}
|
||||
the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
|
||||
@var{HHHH} (one to four hex digits)
|
||||
@item \U@var{HHHHHHHH}
|
||||
the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
|
||||
@var{HHHHHHHH} (one to eight hex digits)
|
||||
@item \c@var{x}
|
||||
a control-@var{x} character
|
||||
@end table
|
||||
@@ -590,6 +596,7 @@ some other grouping.
|
||||
* Lists:: How to execute commands sequentially.
|
||||
* Compound Commands:: Shell commands for control flow.
|
||||
* Coprocesses:: Two-way communication between commands.
|
||||
* GNU Parallel:: Running commands in parallel.
|
||||
@end menu
|
||||
|
||||
@node Simple Commands
|
||||
@@ -648,6 +655,12 @@ The use of @code{time} as a reserved word permits the timing of
|
||||
shell builtins, shell functions, and pipelines. An external
|
||||
@code{time} command cannot time these easily.
|
||||
|
||||
When the shell is in @sc{posix} mode (@pxref{Bash POSIX Mode}), @code{time}
|
||||
may be followed by a newline. In this case, the shell displays the
|
||||
total user and system time consumed by the shell and its children.
|
||||
The @env{TIMEFORMAT} variable may be used to specify the format of
|
||||
the time information.
|
||||
|
||||
If the pipeline is not executed asynchronously (@pxref{Lists}), the
|
||||
shell waits for all commands in the pipeline to complete.
|
||||
|
||||
@@ -1126,6 +1139,79 @@ builtin command may be used to wait for the coprocess to terminate.
|
||||
|
||||
The return status of a coprocess is the exit status of @var{command}.
|
||||
|
||||
@node GNU Parallel
|
||||
@subsection GNU Parallel
|
||||
|
||||
GNU Parallel, as its name suggests, can be used to build and run commands
|
||||
in parallel. You may run the same command with different arguments, whether
|
||||
they are filenames, usernames, hostnames, or lines read from files.
|
||||
|
||||
For a complete description, refer to the GNU Parallel documentation. A few
|
||||
examples should provide a brief introduction to its use.
|
||||
|
||||
For example, it is easy to prefix each line in a text file with a specified
|
||||
string:
|
||||
@example
|
||||
cat file | parallel -k echo prefix_string
|
||||
@end example
|
||||
|
||||
The @option{-k} option is required to preserve the lines' order.
|
||||
|
||||
Similarly, you can append a specified string to each line in a text file:
|
||||
@example
|
||||
cat file | parallel -k echo @{@} append_string
|
||||
@end example
|
||||
|
||||
You can use Parallel to move files from the current directory when the
|
||||
number of files is too large to process with one @code{mv} invocation:
|
||||
@example
|
||||
ls | parallel mv @{@} destdir
|
||||
@end example
|
||||
|
||||
As you can see, the @{@} is replaced with each line read from standard input.
|
||||
This will run as many @code{mv} commands as there are files in the current
|
||||
directory. You can emulate a parallel @code{xargs} by adding the @option{-X}
|
||||
option:
|
||||
@example
|
||||
ls | parallel -X mv @{@} destdir
|
||||
@end example
|
||||
|
||||
GNU Parallel can replace certain common idioms that operate on lines read
|
||||
from a file (in this case, filenames):
|
||||
@example
|
||||
for x in $(cat list); do
|
||||
do-something1 $x config-$x
|
||||
do-something2 < $x
|
||||
done | process-output
|
||||
@end example
|
||||
|
||||
with a more compact syntax reminiscent of lambdas:
|
||||
@example
|
||||
cat list | parallel "do-something1 @{@} config-@{@} ; do-something2 < @{@}" | process-output
|
||||
@end example
|
||||
|
||||
Parallel provides a built-in mechanism to remove filename extensions, which
|
||||
lends itself to batch file transformations or renaming:
|
||||
@example
|
||||
ls *.gz | parallel -j+0 "zcat @{@} | bzip2 >@{.@}.bz2 && rm @{@}"
|
||||
@end example
|
||||
|
||||
This will recompress all files in the current directory with names ending
|
||||
in .gz using bzip2, running one job per CPU (-j+0) in parallel.
|
||||
|
||||
If a command generates output, you may want to preserve the input order in
|
||||
the output. For instance, the following command
|
||||
@example
|
||||
@{ echo foss.org.my ; echo debian.org; echo freenetproject.org; @} | parallel traceroute
|
||||
@end example
|
||||
|
||||
will display as output the traceroute invocation that finishes first. Using
|
||||
the @option{-k} option, as we saw above
|
||||
@example
|
||||
@{ echo foss.org.my ; echo debian.org; echo freenetproject.org; @} | parallel -k traceroute
|
||||
@end example
|
||||
will ensure that the output of @code{traceroute foss.org.my} is displayed first.
|
||||
|
||||
@node Shell Functions
|
||||
@section Shell Functions
|
||||
@cindex shell function
|
||||
@@ -1198,6 +1284,11 @@ shell option has been enabled.
|
||||
@xref{Bourne Shell Builtins}, for the description of the
|
||||
@code{trap} builtin.
|
||||
|
||||
The @env{FUNCNEST} variable, if set to a numeric value greater
|
||||
than 0, defines a maximum function nesting level. Function
|
||||
invocations that exceed the limit cause the entire command to
|
||||
abort.
|
||||
|
||||
If the builtin command @code{return}
|
||||
is executed in a function, the function completes and
|
||||
execution resumes with the next command after the function
|
||||
@@ -3450,6 +3541,11 @@ If the @code{extdebug} shell option is enabled using @code{shopt}
|
||||
(@pxref{The Shopt Builtin}), the source file name and line number where
|
||||
the function is defined are displayed as well.
|
||||
@option{-F} implies @option{-f}.
|
||||
|
||||
The @option{-g} option forces variables to be created or modified at
|
||||
the global scope, even when \fBdeclare\fP is executed in a shell function.
|
||||
It is ignored in all other cases.
|
||||
|
||||
The following options can be used to restrict output to variables with
|
||||
the specified attributes or to give variables attributes:
|
||||
|
||||
@@ -3498,8 +3594,9 @@ with the exceptions that @samp{+a}
|
||||
may not be used to destroy an array variable and @samp{+r} will not
|
||||
remove the readonly attribute.
|
||||
When used in a function, @code{declare} makes each @var{name} local,
|
||||
as with the @code{local} command. If a variable name is followed by
|
||||
=@var{value}, the value of the variable is set to @var{value}.
|
||||
as with the @code{local} command, unless the @samp{-g} option is used.
|
||||
If a variable name is followed by =@var{value}, the value of the variable
|
||||
is set to @var{value}.
|
||||
|
||||
The return status is zero unless an invalid option is encountered,
|
||||
an attempt is made to define a function using @samp{-f foo=bar},
|
||||
@@ -3557,6 +3654,12 @@ the eight-bit character whose value is the octal value @var{nnn}
|
||||
@item \x@var{HH}
|
||||
the eight-bit character whose value is the hexadecimal value @var{HH}
|
||||
(one or two hex digits)
|
||||
@item \u@var{HHHH}
|
||||
the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
|
||||
@var{HHHH} (one to four hex digits)
|
||||
@item \U@var{HHHHHHHH}
|
||||
the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
|
||||
@var{HHHHHHHH} (one to eight hex digits)
|
||||
@end table
|
||||
|
||||
@item enable
|
||||
@@ -3681,7 +3784,8 @@ Specify the number of lines read between each call to @var{callback}.
|
||||
If @option{-C} is specified without @option{-c},
|
||||
the default quantum is 5000.
|
||||
When @var{callback} is evaluated, it is supplied the index of the next
|
||||
array element to be assigned as an additional argument.
|
||||
array element to be assigned and the line to be assigned to that element
|
||||
as additional arguments.
|
||||
@var{callback} is evaluated after the line is read but before the
|
||||
array element is assigned.
|
||||
|
||||
@@ -4942,6 +5046,11 @@ Assignments to @env{FUNCNAME} have no effect and return an error status.
|
||||
If @env{FUNCNAME} is unset, it loses its special properties, even if
|
||||
it is subsequently reset.
|
||||
|
||||
@item FUNCNEST
|
||||
If set to a numeric value greater than 0, defines a maximum function
|
||||
nesting level. Function invocations that exceed this nesting level
|
||||
will cause the current command to abort.
|
||||
|
||||
@item GLOBIGNORE
|
||||
A colon-separated list of patterns defining the set of filenames to
|
||||
be ignored by filename expansion.
|
||||
@@ -5843,10 +5952,13 @@ True if @var{file1} is older than @var{file2},
|
||||
or if @var{file2} exists and @var{file1} does not.
|
||||
|
||||
@item -o @var{optname}
|
||||
True if shell option @var{optname} is enabled.
|
||||
True if the shell option @var{optname} is enabled.
|
||||
The list of options appears in the description of the @option{-o}
|
||||
option to the @code{set} builtin (@pxref{The Set Builtin}).
|
||||
|
||||
@item -v @var{varname}
|
||||
True if the shell variable @var{varname} is set (has been assigned a value).
|
||||
|
||||
@item -z @var{string}
|
||||
True if the length of @var{string} is zero.
|
||||
|
||||
@@ -6477,6 +6589,11 @@ is not found.
|
||||
Non-interactive shells exit if a syntax error in an arithmetic expansion
|
||||
results in an invalid expression.
|
||||
|
||||
@item
|
||||
Non-interactive shells exit if there is a syntax error in a script read
|
||||
with the @code{.} or @code{source} builtins, or in a string processed by
|
||||
the @code{eval} builtin.
|
||||
|
||||
@item
|
||||
Redirection operators do not perform filename expansion on the word
|
||||
in the redirection unless the shell is interactive.
|
||||
@@ -6495,6 +6612,19 @@ causes a fatal syntax error in non-interactive shells.
|
||||
@sc{posix} special builtins are found before shell functions
|
||||
during command lookup.
|
||||
|
||||
@item
|
||||
The @code{time} reserved word may be used by itself as a command. When
|
||||
used in this way, it displays timing statistics for the shell and its
|
||||
completed children. The @env{TIMEFORMAT} variable controls the format
|
||||
of the timing information.
|
||||
|
||||
@item
|
||||
When parsing and expanding a $@{@dots{}@} expansion that appears within
|
||||
double quotes, single quotes are no longer special and cannot be used to
|
||||
quote a closing brace or other special character, unless the operator is
|
||||
one of those defined to perform pattern removal. In this case, they do
|
||||
not have to appear as matched pairs.
|
||||
|
||||
@item
|
||||
If a @sc{posix} special builtin returns an error status, a
|
||||
non-interactive shell exits. The fatal errors are those listed in
|
||||
|
||||
+3
-3
@@ -2,9 +2,9 @@
|
||||
Copyright (C) 1988-2010 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Sat Apr 17 23:23:55 EDT 2010
|
||||
@set LASTCHANGE Sun May 30 17:03:21 EDT 2010
|
||||
|
||||
@set EDITION 4.1
|
||||
@set VERSION 4.1
|
||||
@set UPDATED 17 April 2010
|
||||
@set UPDATED-MONTH April 2010
|
||||
@set UPDATED 30 May 2010
|
||||
@set UPDATED-MONTH May 2010
|
||||
|
||||
+3
-3
@@ -2,9 +2,9 @@
|
||||
Copyright (C) 1988-2010 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Fri Jan 15 10:50:20 EST 2010
|
||||
@set LASTCHANGE Sat May 29 21:00:00 EDT 2010
|
||||
|
||||
@set EDITION 4.1
|
||||
@set VERSION 4.1
|
||||
@set UPDATED 15 January 2010
|
||||
@set UPDATED-MONTH January 2010
|
||||
@set UPDATED 29 May 2010
|
||||
@set UPDATED-MONTH May 2010
|
||||
|
||||
+10
-13
@@ -1,6 +1,6 @@
|
||||
/* execute_cmd.c -- Execute a COMMAND structure. */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -179,7 +179,7 @@ static void execute_subshell_builtin_or_function __P((WORD_LIST *, REDIRECT *,
|
||||
int, int, int,
|
||||
struct fd_bitmap *,
|
||||
int));
|
||||
static void execute_disk_command __P((WORD_LIST *, REDIRECT *, char *,
|
||||
static int execute_disk_command __P((WORD_LIST *, REDIRECT *, char *,
|
||||
int, int, int, struct fd_bitmap *, int));
|
||||
|
||||
static char *getinterp __P((char *, int, int *));
|
||||
@@ -271,7 +271,7 @@ static int showing_function_line;
|
||||
static int line_number_for_err_trap;
|
||||
|
||||
/* A sort of function nesting level counter */
|
||||
static int funcnest = 0;
|
||||
int funcnest = 0;
|
||||
int funcnest_max = 0; /* XXX - bash-4.2 */
|
||||
|
||||
struct fd_bitmap *current_fds_to_close = (struct fd_bitmap *)NULL;
|
||||
@@ -1219,7 +1219,6 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
|
||||
|
||||
posix_time = (command->flags & CMD_TIME_POSIX);
|
||||
|
||||
#if 0 /* XXX - bash-4.2 */
|
||||
nullcmd = (command == 0) || (command->type == cm_simple && command->value.Simple->words == 0 && command->value.Simple->redirects == 0);
|
||||
if (posixly_correct && nullcmd)
|
||||
{
|
||||
@@ -1233,7 +1232,6 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
|
||||
tbefore = shell_start_time;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
old_flags = command->flags;
|
||||
command->flags &= ~(CMD_TIME_PIPELINE|CMD_TIME_POSIX);
|
||||
@@ -1289,11 +1287,9 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
|
||||
time_format = POSIX_TIMEFORMAT;
|
||||
else if ((time_format = get_string_value ("TIMEFORMAT")) == 0)
|
||||
{
|
||||
#if 0 /* XXX - bash-4.2 */
|
||||
if (posixly_correct && nullcmd)
|
||||
time_format = "user\t%2lU\nsys\t%2lS";
|
||||
else
|
||||
#endif
|
||||
time_format = BASH_TIMEFORMAT;
|
||||
}
|
||||
if (time_format && *time_format)
|
||||
@@ -3878,7 +3874,7 @@ run_builtin:
|
||||
simple_command->flags &= ~CMD_NO_FORK;
|
||||
#endif
|
||||
|
||||
execute_disk_command (words, simple_command->redirects, command_line,
|
||||
result = execute_disk_command (words, simple_command->redirects, command_line,
|
||||
pipe_in, pipe_out, async, fds_to_close,
|
||||
simple_command->flags);
|
||||
|
||||
@@ -4040,13 +4036,12 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
|
||||
|
||||
USE_VAR(fc);
|
||||
|
||||
#if 0 /* XXX - bash-4.2 */
|
||||
if (funcnest_max > 0 && funcnest >= funcnest_max)
|
||||
{
|
||||
internal_error ("%s: maximum function nesting level exceeded (%d)", var->name, funcnest);
|
||||
funcnest = 0; /* XXX - should we reset it somewhere else? */
|
||||
jump_to_top_level (DISCARD);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
|
||||
@@ -4505,7 +4500,7 @@ setup_async_signals ()
|
||||
# define NOTFOUND_HOOK "command_not_found_handle"
|
||||
#endif
|
||||
|
||||
static void
|
||||
static int
|
||||
execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
|
||||
async, fds_to_close, cmdflags)
|
||||
WORD_LIST *words;
|
||||
@@ -4516,7 +4511,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
|
||||
int cmdflags;
|
||||
{
|
||||
char *pathname, *command, **args;
|
||||
int nofork;
|
||||
int nofork, result;
|
||||
pid_t pid;
|
||||
SHELL_VAR *hookf;
|
||||
WORD_LIST *wl;
|
||||
@@ -4524,13 +4519,14 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
|
||||
nofork = (cmdflags & CMD_NO_FORK); /* Don't fork, just exec, if no pipes */
|
||||
pathname = words->word->word;
|
||||
|
||||
result = EXECUTION_SUCCESS;
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
command = (char *)NULL;
|
||||
if (restricted && mbschr (pathname, '/'))
|
||||
{
|
||||
internal_error (_("%s: restricted: cannot specify `/' in command names"),
|
||||
pathname);
|
||||
last_command_exit_value = EXECUTION_FAILURE;
|
||||
result = last_command_exit_value = EXECUTION_FAILURE;
|
||||
|
||||
/* If we're not going to fork below, we must already be in a child
|
||||
process or a context in which it's safe to call exit(2). */
|
||||
@@ -4644,6 +4640,7 @@ parent_return:
|
||||
unlink_fifo_list ();
|
||||
#endif
|
||||
FREE (command);
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-21
@@ -179,7 +179,7 @@ static void execute_subshell_builtin_or_function __P((WORD_LIST *, REDIRECT *,
|
||||
int, int, int,
|
||||
struct fd_bitmap *,
|
||||
int));
|
||||
static void execute_disk_command __P((WORD_LIST *, REDIRECT *, char *,
|
||||
static int execute_disk_command __P((WORD_LIST *, REDIRECT *, char *,
|
||||
int, int, int, struct fd_bitmap *, int));
|
||||
|
||||
static char *getinterp __P((char *, int, int *));
|
||||
@@ -271,7 +271,7 @@ static int showing_function_line;
|
||||
static int line_number_for_err_trap;
|
||||
|
||||
/* A sort of function nesting level counter */
|
||||
static int funcnest = 0;
|
||||
int funcnest = 0;
|
||||
int funcnest_max = 0; /* XXX - bash-4.2 */
|
||||
|
||||
struct fd_bitmap *current_fds_to_close = (struct fd_bitmap *)NULL;
|
||||
@@ -1219,7 +1219,6 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
|
||||
|
||||
posix_time = (command->flags & CMD_TIME_POSIX);
|
||||
|
||||
#if 0 /* XXX - bash-4.2 */
|
||||
nullcmd = (command == 0) || (command->type == cm_simple && command->value.Simple->words == 0 && command->value.Simple->redirects == 0);
|
||||
if (posixly_correct && nullcmd)
|
||||
{
|
||||
@@ -1233,7 +1232,6 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
|
||||
tbefore = shell_start_time;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
old_flags = command->flags;
|
||||
command->flags &= ~(CMD_TIME_PIPELINE|CMD_TIME_POSIX);
|
||||
@@ -1289,11 +1287,9 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
|
||||
time_format = POSIX_TIMEFORMAT;
|
||||
else if ((time_format = get_string_value ("TIMEFORMAT")) == 0)
|
||||
{
|
||||
#if 0 /* XXX - bash-4.2 */
|
||||
if (posixly_correct && nullcmd)
|
||||
time_format = "user\t%2lU\nsys\t%2lS";
|
||||
else
|
||||
#endif
|
||||
time_format = BASH_TIMEFORMAT;
|
||||
}
|
||||
if (time_format && *time_format)
|
||||
@@ -1390,15 +1386,11 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
|
||||
|
||||
reset_terminating_signals (); /* in sig.c */
|
||||
/* Cancel traps, in trap.c. */
|
||||
#if 0 /* XXX - bash-4.2 */
|
||||
/* Reset the signal handlers in the child, but don't free the
|
||||
trap strings. Set a flag noting that we have to free the
|
||||
trap strings if we run trap to change a signal disposition. */
|
||||
reset_signal_handlers ();
|
||||
subshell_environment |= SUBSHELL_RESETTRAP;
|
||||
#else
|
||||
restore_original_signals ();
|
||||
#endif
|
||||
|
||||
/* Make sure restore_original_signals doesn't undo the work done by
|
||||
make_child to ensure that asynchronous children are immune to SIGINT
|
||||
@@ -3812,16 +3804,11 @@ run_builtin:
|
||||
if (already_forked)
|
||||
{
|
||||
/* reset_terminating_signals (); */ /* XXX */
|
||||
#if 0 /* XXX - bash-4.2 */
|
||||
/* Reset the signal handlers in the child, but don't free the
|
||||
trap strings. Set a flag noting that we have to free the
|
||||
trap strings if we run trap to change a signal disposition. */
|
||||
reset_signal_handlers ();
|
||||
subshell_environment |= SUBSHELL_RESETTRAP;
|
||||
#else
|
||||
/* Cancel traps, in trap.c. */
|
||||
restore_original_signals ();
|
||||
#endif
|
||||
|
||||
if (async)
|
||||
{
|
||||
@@ -3887,7 +3874,7 @@ run_builtin:
|
||||
simple_command->flags &= ~CMD_NO_FORK;
|
||||
#endif
|
||||
|
||||
execute_disk_command (words, simple_command->redirects, command_line,
|
||||
result = execute_disk_command (words, simple_command->redirects, command_line,
|
||||
pipe_in, pipe_out, async, fds_to_close,
|
||||
simple_command->flags);
|
||||
|
||||
@@ -4049,13 +4036,12 @@ execute_function (var, words, flags, fds_to_close, async, subshell)
|
||||
|
||||
USE_VAR(fc);
|
||||
|
||||
#if 0 /* XXX - bash-4.2 */
|
||||
if (funcnest_max > 0 && funcnest >= funcnest_max)
|
||||
{
|
||||
internal_error ("%s: maximum function nesting level exceeded (%d)", var->name, funcnest);
|
||||
funcnest = 0; /* XXX - should we reset it somewhere else? */
|
||||
jump_to_top_level (DISCARD);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
|
||||
@@ -4514,7 +4500,7 @@ setup_async_signals ()
|
||||
# define NOTFOUND_HOOK "command_not_found_handle"
|
||||
#endif
|
||||
|
||||
static void
|
||||
static int
|
||||
execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
|
||||
async, fds_to_close, cmdflags)
|
||||
WORD_LIST *words;
|
||||
@@ -4525,7 +4511,7 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
|
||||
int cmdflags;
|
||||
{
|
||||
char *pathname, *command, **args;
|
||||
int nofork;
|
||||
int nofork, result;
|
||||
pid_t pid;
|
||||
SHELL_VAR *hookf;
|
||||
WORD_LIST *wl;
|
||||
@@ -4533,13 +4519,14 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
|
||||
nofork = (cmdflags & CMD_NO_FORK); /* Don't fork, just exec, if no pipes */
|
||||
pathname = words->word->word;
|
||||
|
||||
result = EXECUTION_SUCCESS;
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
command = (char *)NULL;
|
||||
if (restricted && mbschr (pathname, '/'))
|
||||
{
|
||||
internal_error (_("%s: restricted: cannot specify `/' in command names"),
|
||||
pathname);
|
||||
last_command_exit_value = EXECUTION_FAILURE;
|
||||
result = last_command_exit_value = EXECUTION_FAILURE;
|
||||
|
||||
/* If we're not going to fork below, we must already be in a child
|
||||
process or a context in which it's safe to call exit(2). */
|
||||
@@ -4653,6 +4640,7 @@ parent_return:
|
||||
unlink_fifo_list ();
|
||||
#endif
|
||||
FREE (command);
|
||||
return (result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* expr.c -- arithmetic expression evaluation. */
|
||||
|
||||
/* Copyright (C) 1990-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1990-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -176,6 +176,10 @@ static struct lvalue lastlval = {0, 0, 0, -1};
|
||||
static int _is_arithop __P((int));
|
||||
static void readtok __P((void)); /* lexical analyzer */
|
||||
|
||||
static void init_lvalue __P((struct lvalue *));
|
||||
static struct lvalue *alloc_lvalue __P((void));
|
||||
static void free_lvalue __P((struct lvalue *));
|
||||
|
||||
static intmax_t expr_streval __P((char *, int, struct lvalue *));
|
||||
static intmax_t strlong __P((char *));
|
||||
static void evalerror __P((const char *));
|
||||
@@ -321,7 +325,7 @@ expr_bind_array_element (tok, ind, rhs)
|
||||
size_t llen;
|
||||
char ibuf[INT_STRLEN_BOUND (arrayind_t) + 1], *istr;
|
||||
|
||||
istr = fmtulong (ind, 10, ibuf, sizeof (ibuf), 0);
|
||||
istr = fmtumax (ind, 10, ibuf, sizeof (ibuf), 0);
|
||||
vname = array_variable_name (tok, (char **)NULL, (int *)NULL);
|
||||
|
||||
llen = strlen (vname) + sizeof (ibuf) + 3;
|
||||
@@ -401,12 +405,14 @@ subexpr (expr)
|
||||
return (0);
|
||||
|
||||
pushexp ();
|
||||
curtok = lasttok = 0;
|
||||
expression = savestring (expr);
|
||||
tp = expression;
|
||||
|
||||
curtok = lasttok = 0;
|
||||
tokstr = (char *)NULL;
|
||||
tokval = 0;
|
||||
init_lvalue (&curlval);
|
||||
lastlval = curlval;
|
||||
|
||||
readtok ();
|
||||
|
||||
@@ -955,15 +961,22 @@ exp0 ()
|
||||
return (val);
|
||||
}
|
||||
|
||||
static void
|
||||
init_lvalue (lv)
|
||||
struct lvalue *lv;
|
||||
{
|
||||
lv->tokstr = 0;
|
||||
lv->tokvar = 0;
|
||||
lv->tokval = lv->ind = -1;
|
||||
}
|
||||
|
||||
static struct lvalue *
|
||||
alloc_lvalue ()
|
||||
{
|
||||
struct lvalue *lv;
|
||||
|
||||
lv = xmalloc (sizeof (struct lvalue));
|
||||
lv->tokstr = 0;
|
||||
lv->tokvar = 0;
|
||||
lv->tokval = lv->ind = -1;
|
||||
init_lvalue (lv);
|
||||
return (lv);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* externs.h -- extern function declarations which do not appear in their
|
||||
own header file. */
|
||||
|
||||
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+4
-1
@@ -114,7 +114,7 @@ extern int get_current_prompt_level __P((void));
|
||||
extern void set_current_prompt_level __P((int));
|
||||
|
||||
#if defined (HISTORY)
|
||||
extern char *history_delimiting_chars __P((void));
|
||||
extern char *history_delimiting_chars __P((const char *));
|
||||
#endif
|
||||
|
||||
/* Declarations for functions defined in locale.c */
|
||||
@@ -455,6 +455,9 @@ extern int uconvert __P((char *, long *, long *));
|
||||
extern unsigned int falarm __P((unsigned int, unsigned int));
|
||||
extern unsigned int fsleep __P((unsigned int, unsigned int));
|
||||
|
||||
/* declarations for functions defined in lib/sh/unicode.c */
|
||||
extern int u32cconv __P((unsigned long, char *));
|
||||
|
||||
/* declarations for functions defined in lib/sh/winsize.c */
|
||||
extern void get_new_window_size __P((int, int *, int *));
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/* This file works with both POSIX and BSD systems. It implements job
|
||||
control. */
|
||||
|
||||
/* Copyright (C) 1989-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -2351,7 +2351,6 @@ wait_for (pid)
|
||||
WAIT s;
|
||||
register PROCESS *child;
|
||||
sigset_t set, oset;
|
||||
register PROCESS *p;
|
||||
|
||||
/* In the case that this code is interrupted, and we longjmp () out of it,
|
||||
we are relying on the code in throw_to_top_level () to restore the
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* xmbsrtowcs.c -- replacement function for mbsrtowcs */
|
||||
|
||||
/* Copyright (C) 2002-2004 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -219,7 +219,6 @@ xdupmbstowcs2 (destp, src)
|
||||
}
|
||||
#endif /* HAVE_MBSNRTOWCS */
|
||||
|
||||
|
||||
/* Convert a multibyte string to a wide character string. Memory for the
|
||||
new wide character string is obtained with malloc.
|
||||
|
||||
@@ -255,6 +254,11 @@ xdupmbstowcs (destp, indicesp, src)
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
#if HAVE_MBSNRTOWCS
|
||||
if (indicesp == NULL)
|
||||
return (xdupmbstowcs2 (destp, src));
|
||||
#endif
|
||||
|
||||
memset (&state, '\0', sizeof(mbstate_t));
|
||||
wsbuf_size = WSBUF_INC;
|
||||
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
/* bind.c -- key binding and startup file support for the readline library. */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -1424,6 +1424,7 @@ static const struct {
|
||||
{ "blink-matching-paren", &rl_blink_matching_paren, V_SPECIAL },
|
||||
{ "byte-oriented", &rl_byte_oriented, 0 },
|
||||
{ "completion-ignore-case", &_rl_completion_case_fold, 0 },
|
||||
{ "completion-map-case", &_rl_completion_case_map, 0 },
|
||||
{ "convert-meta", &_rl_convert_meta_chars_to_ascii, 0 },
|
||||
{ "disable-completion", &rl_inhibit_completion, 0 },
|
||||
{ "echo-control-characters", &_rl_echo_control_chars, 0 },
|
||||
|
||||
@@ -1424,6 +1424,7 @@ static const struct {
|
||||
{ "blink-matching-paren", &rl_blink_matching_paren, V_SPECIAL },
|
||||
{ "byte-oriented", &rl_byte_oriented, 0 },
|
||||
{ "completion-ignore-case", &_rl_completion_case_fold, 0 },
|
||||
{ "completion-map-case", &_rl_completion_case_map, 0 },
|
||||
{ "convert-meta", &_rl_convert_meta_chars_to_ascii, 0 },
|
||||
{ "disable-completion", &rl_inhibit_completion, 0 },
|
||||
{ "echo-control-characters", &_rl_echo_control_chars, 0 },
|
||||
@@ -2283,6 +2284,11 @@ _rl_get_string_variable_value (name)
|
||||
}
|
||||
else if (_rl_stricmp (name, "comment-begin") == 0)
|
||||
return (_rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
|
||||
else if (_rl_stricmp (name, "completion-display-width") == 0)
|
||||
{
|
||||
sprintf (numbuf, "%d", _rl_completion_columns);
|
||||
return (numbuf);
|
||||
}
|
||||
else if (_rl_stricmp (name, "completion-prefix-display-length") == 0)
|
||||
{
|
||||
sprintf (numbuf, "%d", _rl_completion_prefix_display_length);
|
||||
|
||||
+64
-17
@@ -119,6 +119,7 @@ static char **remove_duplicate_matches PARAMS((char **));
|
||||
static void insert_match PARAMS((char *, int, int, char *));
|
||||
static int append_to_match PARAMS((char *, int, int, int));
|
||||
static void insert_all_matches PARAMS((char **, int, char *));
|
||||
static int complete_fncmp PARAMS((const char *, int, const char *, int));
|
||||
static void display_matches PARAMS((char **));
|
||||
static int compute_lcd_of_matches PARAMS((char **, int, const char *));
|
||||
static int postprocess_matches PARAMS((char ***, int));
|
||||
@@ -158,9 +159,13 @@ int _rl_print_completions_horizontally;
|
||||
#if defined (__MSDOS__) && !defined (__DJGPP__)
|
||||
int _rl_completion_case_fold = 1;
|
||||
#else
|
||||
int _rl_completion_case_fold;
|
||||
int _rl_completion_case_fold = 0;
|
||||
#endif
|
||||
|
||||
/* Non-zero means that `-' and `_' are equivalent when comparing filenames
|
||||
for completion. */
|
||||
int _rl_completion_case_map = 0;
|
||||
|
||||
/* If zero, don't match hidden files (filenames beginning with a `.' on
|
||||
Unix) when doing filename completion. */
|
||||
int _rl_match_hidden_files = 1;
|
||||
@@ -2056,6 +2061,62 @@ rl_username_completion_function (text, state)
|
||||
#endif /* !__WIN32__ && !__OPENNT */
|
||||
}
|
||||
|
||||
/* Return non-zero if CONVFN matches FILENAME up to the length of FILENAME
|
||||
(FILENAME_LEN). If _rl_completion_case_fold is set, compare without
|
||||
regard to the alphabetic case of characters. CONVFN is the possibly-
|
||||
converted directory entry; FILENAME is what the user typed. */
|
||||
static int
|
||||
complete_fncmp (convfn, convlen, filename, filename_len)
|
||||
const char *convfn;
|
||||
int convlen;
|
||||
const char *filename;
|
||||
int filename_len;
|
||||
{
|
||||
register char *s1, *s2;
|
||||
int d, len;
|
||||
|
||||
/* Otherwise, if these match up to the length of filename, then
|
||||
it is a match. */
|
||||
if (_rl_completion_case_fold && _rl_completion_case_map)
|
||||
{
|
||||
/* Case-insensitive comparison treating _ and - as equivalent */
|
||||
if (filename_len == 0)
|
||||
return 1;
|
||||
if (convlen < filename_len)
|
||||
return 0;
|
||||
s1 = convfn;
|
||||
s2 = filename;
|
||||
len = filename_len;
|
||||
do
|
||||
{
|
||||
d = _rl_to_lower (*s1) - _rl_to_lower (*s2);
|
||||
/* *s1 == [-_] && *s2 == [-_] */
|
||||
if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
|
||||
d = 0;
|
||||
if (d != 0)
|
||||
return 0;
|
||||
s1++; s2++; /* already checked convlen >= filename_len */
|
||||
}
|
||||
while (--len != 0);
|
||||
return 1;
|
||||
}
|
||||
else if (_rl_completion_case_fold)
|
||||
{
|
||||
if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
|
||||
(convlen >= filename_len) &&
|
||||
(_rl_strnicmp (filename, convfn, filename_len) == 0))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((convfn[0] == filename[0]) &&
|
||||
(convlen >= filename_len) &&
|
||||
(strncmp (filename, convfn, filename_len) == 0))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Okay, now we write the entry_function for filename completion. In the
|
||||
general case. Note that completion in the shell is a little different
|
||||
because of all the pathnames that must be followed when looking up the
|
||||
@@ -2198,22 +2259,8 @@ rl_filename_completion_function (text, state)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, if these match up to the length of filename, then
|
||||
it is a match. */
|
||||
if (_rl_completion_case_fold)
|
||||
{
|
||||
if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
|
||||
(convlen >= filename_len) &&
|
||||
(_rl_strnicmp (filename, convfn, filename_len) == 0))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((convfn[0] == filename[0]) &&
|
||||
(convlen >= filename_len) &&
|
||||
(strncmp (filename, convfn, filename_len) == 0))
|
||||
break;
|
||||
}
|
||||
if (complete_fncmp (convfn, convlen, filename, filename_len))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+89
-18
@@ -119,6 +119,7 @@ static char **remove_duplicate_matches PARAMS((char **));
|
||||
static void insert_match PARAMS((char *, int, int, char *));
|
||||
static int append_to_match PARAMS((char *, int, int, int));
|
||||
static void insert_all_matches PARAMS((char **, int, char *));
|
||||
static int complete_fncmp PARAMS((const char *, int, const char *, int));
|
||||
static void display_matches PARAMS((char **));
|
||||
static int compute_lcd_of_matches PARAMS((char **, int, const char *));
|
||||
static int postprocess_matches PARAMS((char ***, int));
|
||||
@@ -158,9 +159,13 @@ int _rl_print_completions_horizontally;
|
||||
#if defined (__MSDOS__) && !defined (__DJGPP__)
|
||||
int _rl_completion_case_fold = 1;
|
||||
#else
|
||||
int _rl_completion_case_fold;
|
||||
int _rl_completion_case_fold = 0;
|
||||
#endif
|
||||
|
||||
/* Non-zero means that `-' and `_' are equivalent when comparing filenames
|
||||
for completion. */
|
||||
int _rl_completion_case_map = 1;
|
||||
|
||||
/* If zero, don't match hidden files (filenames beginning with a `.' on
|
||||
Unix) when doing filename completion. */
|
||||
int _rl_match_hidden_files = 1;
|
||||
@@ -173,7 +178,7 @@ int _rl_completion_prefix_display_length = 0;
|
||||
|
||||
/* The readline-private number of screen columns to use when displaying
|
||||
matches. If < 0 or > _rl_screenwidth, it is ignored. */
|
||||
int _rl_completion_columns = 0;
|
||||
int _rl_completion_columns = -1;
|
||||
|
||||
/* Global variables available to applications using readline. */
|
||||
|
||||
@@ -1784,6 +1789,9 @@ rl_complete_internal (what_to_do)
|
||||
int start, end, delimiter, found_quote, i, nontrivial_lcd;
|
||||
char *text, *saved_line_buffer;
|
||||
char quote_char;
|
||||
#if 1
|
||||
int tlen, mlen;
|
||||
#endif
|
||||
|
||||
RL_SETSTATE(RL_STATE_COMPLETING);
|
||||
|
||||
@@ -1811,6 +1819,10 @@ rl_complete_internal (what_to_do)
|
||||
/* nontrivial_lcd is set if the common prefix adds something to the word
|
||||
being completed. */
|
||||
nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
|
||||
#if 1
|
||||
if (what_to_do == '!' || what_to_do == '@')
|
||||
tlen = strlen (text);
|
||||
#endif
|
||||
free (text);
|
||||
|
||||
if (matches == 0)
|
||||
@@ -1844,8 +1856,25 @@ rl_complete_internal (what_to_do)
|
||||
case '!':
|
||||
case '@':
|
||||
/* Insert the first match with proper quoting. */
|
||||
#if 0
|
||||
if (*matches[0])
|
||||
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
|
||||
#else
|
||||
if (what_to_do == TAB)
|
||||
{
|
||||
if (*matches[0])
|
||||
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
|
||||
}
|
||||
else if (*matches[0] && matches[1] == 0)
|
||||
/* should we perform the check only if there are multiple matches? */
|
||||
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
|
||||
else if (*matches[0]) /* what_to_do != TAB && multiple matches */
|
||||
{
|
||||
mlen = *matches[0] ? strlen (matches[0]) : 0;
|
||||
if (mlen >= tlen)
|
||||
insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If there are more matches, ring the bell to indicate.
|
||||
If we are in vi mode, Posix.2 says to not ring the bell.
|
||||
@@ -2032,6 +2061,62 @@ rl_username_completion_function (text, state)
|
||||
#endif /* !__WIN32__ && !__OPENNT */
|
||||
}
|
||||
|
||||
/* Return non-zero if CONVFN matches FILENAME up to the length of FILENAME
|
||||
(FILENAME_LEN). If _rl_completion_case_fold is set, compare without
|
||||
regard to the alphabetic case of characters. CONVFN is the possibly-
|
||||
converted directory entry; FILENAME is what the user typed. */
|
||||
static int
|
||||
complete_fncmp (convfn, convlen, filename, filename_len)
|
||||
const char *convfn;
|
||||
int convlen;
|
||||
const char *filename;
|
||||
int filename_len;
|
||||
{
|
||||
register char *s1, *s2;
|
||||
int d, len;
|
||||
|
||||
/* Otherwise, if these match up to the length of filename, then
|
||||
it is a match. */
|
||||
if (_rl_completion_case_fold && _rl_completion_case_map)
|
||||
{
|
||||
/* Case-insensitive comparison treating _ and - as equivalent */
|
||||
if (filename_len == 0)
|
||||
return 1;
|
||||
if (convlen < filename_len)
|
||||
return 0;
|
||||
s1 = convfn;
|
||||
s2 = filename;
|
||||
len = filename_len;
|
||||
do
|
||||
{
|
||||
d = _rl_to_lower (*s1) - _rl_to_lower (*s2);
|
||||
/* *s1 == [-_] && *s2 == [-_] */
|
||||
if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
|
||||
d = 0;
|
||||
if (d != 0)
|
||||
return 0;
|
||||
s1++; s2++; /* already checked convlen >= filename_len */
|
||||
}
|
||||
while (--len != 0);
|
||||
return 1;
|
||||
}
|
||||
else if (_rl_completion_case_fold)
|
||||
{
|
||||
if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
|
||||
(convlen >= filename_len) &&
|
||||
(_rl_strnicmp (filename, convfn, filename_len) == 0))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((convfn[0] == filename[0]) &&
|
||||
(convlen >= filename_len) &&
|
||||
(strncmp (filename, convfn, filename_len) == 0))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Okay, now we write the entry_function for filename completion. In the
|
||||
general case. Note that completion in the shell is a little different
|
||||
because of all the pathnames that must be followed when looking up the
|
||||
@@ -2174,22 +2259,8 @@ rl_filename_completion_function (text, state)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, if these match up to the length of filename, then
|
||||
it is a match. */
|
||||
if (_rl_completion_case_fold)
|
||||
{
|
||||
if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
|
||||
(convlen >= filename_len) &&
|
||||
(_rl_strnicmp (filename, convfn, filename_len) == 0))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((convfn[0] == filename[0]) &&
|
||||
(convlen >= filename_len) &&
|
||||
(strncmp (filename, convfn, filename_len) == 0))
|
||||
break;
|
||||
}
|
||||
if (complete_fncmp (convfn, convlen, filename, filename_len))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
.\"
|
||||
.\" Last Change: Thu Apr 22 18:59:21 EDT 2010
|
||||
.\"
|
||||
.TH READLINE 3 "2009 April 22" "GNU Readline 6.1"
|
||||
.TH READLINE 3 "2010 April 22" "GNU Readline 6.1"
|
||||
.\"
|
||||
.\" File Name macro. This used to be `.PN', for Path Name,
|
||||
.\" but Sun doesn't seem to like that very much.
|
||||
@@ -373,6 +373,11 @@ The default value is -1.
|
||||
If set to \fBOn\fP, readline performs filename matching and completion
|
||||
in a case\-insensitive fashion.
|
||||
.TP
|
||||
.B completion\-map\-case (Off)
|
||||
If set to \fBOn\fP, and \fBcompletion\-ignore\-case\fP is enabled, readline
|
||||
treats hyphens (\fI\-\fP) and underscores (\fI_\fP) as equivalent when
|
||||
performing case\-insensitive filename matching and completion.
|
||||
.TP
|
||||
.B completion\-prefix\-display\-length (0)
|
||||
The length in characters of the common prefix of a list of possible
|
||||
completions that is displayed without modification. When set to a
|
||||
|
||||
@@ -373,6 +373,11 @@ The default value is -1.
|
||||
If set to \fBOn\fP, readline performs filename matching and completion
|
||||
in a case\-insensitive fashion.
|
||||
.TP
|
||||
.B completion\-map\-case (Off)
|
||||
If set to \fBOn\fP, and \fBcompletion\-ignore\-case\fP is enabled, readline
|
||||
treats hyphens (\fI\-\fP) and underscores (\fI_\fP) as equivalent when
|
||||
performing case\-insensitive filename matching and completion.
|
||||
.TP
|
||||
.B completion\-prefix\-display\-length (0)
|
||||
The length in characters of the common prefix of a list of possible
|
||||
completions that is displayed without modification. When set to a
|
||||
@@ -931,6 +936,12 @@ only attempts filename completion under certain circumstances.
|
||||
.TP
|
||||
.B possible\-completions (M\-?)
|
||||
List the possible completions of the text before point.
|
||||
When displaying completions, readline sets the number of columns used
|
||||
for display to the value of \fBcompletion-display-width\fP, the value of
|
||||
the environment variable
|
||||
.SM
|
||||
.BR COLUMNS ,
|
||||
or the screen width, in that order.
|
||||
.TP
|
||||
.B insert\-completions (M\-*)
|
||||
Insert all completions of the text before point
|
||||
|
||||
@@ -446,6 +446,12 @@ If set to @samp{on}, Readline performs filename matching and completion
|
||||
in a case-insensitive fashion.
|
||||
The default value is @samp{off}.
|
||||
|
||||
@item completion-map-case
|
||||
@vindex completion-map-case
|
||||
If set to @samp{on}, and @var{completion-ignore-case} is enabled, Readline
|
||||
treats hyphens (@samp{-}) and underscores (@samp{_}) as equivalent when
|
||||
performing case-insensitive filename matching and completion.
|
||||
|
||||
@item completion-prefix-display-length
|
||||
@vindex completion-prefix-display-length
|
||||
The length in characters of the common prefix of a list of possible
|
||||
|
||||
@@ -4,7 +4,7 @@ Copyright (C) 1988-2010 Free Software Foundation, Inc.
|
||||
|
||||
@set EDITION 6.1
|
||||
@set VERSION 6.1
|
||||
@set UPDATED April 22 2010
|
||||
@set UPDATED-MONTH April 2010
|
||||
@set UPDATED May 292010
|
||||
@set UPDATED-MONTH May 2010
|
||||
|
||||
@set LASTCHANGE Thu Apr 22 18:59:44 EDT 2010
|
||||
@set LASTCHANGE Sat May 29 17:14:10 EDT 2010
|
||||
|
||||
@@ -4,7 +4,7 @@ Copyright (C) 1988-2010 Free Software Foundation, Inc.
|
||||
|
||||
@set EDITION 6.1
|
||||
@set VERSION 6.1
|
||||
@set UPDATED April 17 2010
|
||||
@set UPDATED April 22 2010
|
||||
@set UPDATED-MONTH April 2010
|
||||
|
||||
@set LASTCHANGE Sat Apr 17 23:45:29 EDT 2010
|
||||
@set LASTCHANGE Thu Apr 22 18:59:44 EDT 2010
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* funmap.c -- attach names to functions. */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -148,6 +148,8 @@ static const FUNMAP default_funmap[] = {
|
||||
{ "vi-append-mode", rl_vi_append_mode },
|
||||
{ "vi-arg-digit", rl_vi_arg_digit },
|
||||
{ "vi-back-to-indent", rl_vi_back_to_indent },
|
||||
{ "vi-backward-bigword", rl_vi_bWord },
|
||||
{ "vi-backward-word", rl_vi_bword },
|
||||
{ "vi-bWord", rl_vi_bWord },
|
||||
{ "vi-bword", rl_vi_bword },
|
||||
{ "vi-change-case", rl_vi_change_case },
|
||||
@@ -160,12 +162,15 @@ static const FUNMAP default_funmap[] = {
|
||||
{ "vi-delete-to", rl_vi_delete_to },
|
||||
{ "vi-eWord", rl_vi_eWord },
|
||||
{ "vi-editing-mode", rl_vi_editing_mode },
|
||||
{ "vi-end-bigword", rl_vi_eWord },
|
||||
{ "vi-end-word", rl_vi_end_word },
|
||||
{ "vi-eof-maybe", rl_vi_eof_maybe },
|
||||
{ "vi-eword", rl_vi_eword },
|
||||
{ "vi-fWord", rl_vi_fWord },
|
||||
{ "vi-fetch-history", rl_vi_fetch_history },
|
||||
{ "vi-first-print", rl_vi_first_print },
|
||||
{ "vi-forward-bigword", rl_vi_fWord },
|
||||
{ "vi-forward-word", rl_vi_fword },
|
||||
{ "vi-fword", rl_vi_fword },
|
||||
{ "vi-goto-mark", rl_vi_goto_mark },
|
||||
{ "vi-insert-beg", rl_vi_insert_beg },
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
/* funmap.c -- attach names to functions. */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
|
||||
Readline is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Readline is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Readline. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define READLINE_LIBRARY
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if !defined (BUFSIZ)
|
||||
#include <stdio.h>
|
||||
#endif /* BUFSIZ */
|
||||
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#include "rlconf.h"
|
||||
#include "readline.h"
|
||||
|
||||
#include "xmalloc.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
typedef int QSFUNC (const void *, const void *);
|
||||
#else
|
||||
typedef int QSFUNC ();
|
||||
#endif
|
||||
|
||||
extern int _rl_qsort_string_compare PARAMS((char **, char **));
|
||||
|
||||
FUNMAP **funmap;
|
||||
static int funmap_size;
|
||||
static int funmap_entry;
|
||||
|
||||
/* After initializing the function map, this is the index of the first
|
||||
program specific function. */
|
||||
int funmap_program_specific_entry_start;
|
||||
|
||||
static const FUNMAP default_funmap[] = {
|
||||
{ "abort", rl_abort },
|
||||
{ "accept-line", rl_newline },
|
||||
{ "arrow-key-prefix", rl_arrow_keys },
|
||||
{ "backward-byte", rl_backward_byte },
|
||||
{ "backward-char", rl_backward_char },
|
||||
{ "backward-delete-char", rl_rubout },
|
||||
{ "backward-kill-line", rl_backward_kill_line },
|
||||
{ "backward-kill-word", rl_backward_kill_word },
|
||||
{ "backward-word", rl_backward_word },
|
||||
{ "beginning-of-history", rl_beginning_of_history },
|
||||
{ "beginning-of-line", rl_beg_of_line },
|
||||
{ "call-last-kbd-macro", rl_call_last_kbd_macro },
|
||||
{ "capitalize-word", rl_capitalize_word },
|
||||
{ "character-search", rl_char_search },
|
||||
{ "character-search-backward", rl_backward_char_search },
|
||||
{ "clear-screen", rl_clear_screen },
|
||||
{ "complete", rl_complete },
|
||||
{ "copy-backward-word", rl_copy_backward_word },
|
||||
{ "copy-forward-word", rl_copy_forward_word },
|
||||
{ "copy-region-as-kill", rl_copy_region_to_kill },
|
||||
{ "delete-char", rl_delete },
|
||||
{ "delete-char-or-list", rl_delete_or_show_completions },
|
||||
{ "delete-horizontal-space", rl_delete_horizontal_space },
|
||||
{ "digit-argument", rl_digit_argument },
|
||||
{ "do-lowercase-version", rl_do_lowercase_version },
|
||||
{ "downcase-word", rl_downcase_word },
|
||||
{ "dump-functions", rl_dump_functions },
|
||||
{ "dump-macros", rl_dump_macros },
|
||||
{ "dump-variables", rl_dump_variables },
|
||||
{ "emacs-editing-mode", rl_emacs_editing_mode },
|
||||
{ "end-kbd-macro", rl_end_kbd_macro },
|
||||
{ "end-of-history", rl_end_of_history },
|
||||
{ "end-of-line", rl_end_of_line },
|
||||
{ "exchange-point-and-mark", rl_exchange_point_and_mark },
|
||||
{ "forward-backward-delete-char", rl_rubout_or_delete },
|
||||
{ "forward-byte", rl_forward_byte },
|
||||
{ "forward-char", rl_forward_char },
|
||||
{ "forward-search-history", rl_forward_search_history },
|
||||
{ "forward-word", rl_forward_word },
|
||||
{ "history-search-backward", rl_history_search_backward },
|
||||
{ "history-search-forward", rl_history_search_forward },
|
||||
{ "insert-comment", rl_insert_comment },
|
||||
{ "insert-completions", rl_insert_completions },
|
||||
{ "kill-whole-line", rl_kill_full_line },
|
||||
{ "kill-line", rl_kill_line },
|
||||
{ "kill-region", rl_kill_region },
|
||||
{ "kill-word", rl_kill_word },
|
||||
{ "menu-complete", rl_menu_complete },
|
||||
{ "menu-complete-backward", rl_backward_menu_complete },
|
||||
{ "next-history", rl_get_next_history },
|
||||
{ "non-incremental-forward-search-history", rl_noninc_forward_search },
|
||||
{ "non-incremental-reverse-search-history", rl_noninc_reverse_search },
|
||||
{ "non-incremental-forward-search-history-again", rl_noninc_forward_search_again },
|
||||
{ "non-incremental-reverse-search-history-again", rl_noninc_reverse_search_again },
|
||||
{ "old-menu-complete", rl_old_menu_complete },
|
||||
{ "overwrite-mode", rl_overwrite_mode },
|
||||
#ifdef __CYGWIN__
|
||||
{ "paste-from-clipboard", rl_paste_from_clipboard },
|
||||
#endif
|
||||
{ "possible-completions", rl_possible_completions },
|
||||
{ "previous-history", rl_get_previous_history },
|
||||
{ "quoted-insert", rl_quoted_insert },
|
||||
{ "re-read-init-file", rl_re_read_init_file },
|
||||
{ "redraw-current-line", rl_refresh_line},
|
||||
{ "reverse-search-history", rl_reverse_search_history },
|
||||
{ "revert-line", rl_revert_line },
|
||||
{ "self-insert", rl_insert },
|
||||
{ "set-mark", rl_set_mark },
|
||||
{ "skip-csi-sequence", rl_skip_csi_sequence },
|
||||
{ "start-kbd-macro", rl_start_kbd_macro },
|
||||
{ "tab-insert", rl_tab_insert },
|
||||
{ "tilde-expand", rl_tilde_expand },
|
||||
{ "transpose-chars", rl_transpose_chars },
|
||||
{ "transpose-words", rl_transpose_words },
|
||||
{ "tty-status", rl_tty_status },
|
||||
{ "undo", rl_undo_command },
|
||||
{ "universal-argument", rl_universal_argument },
|
||||
{ "unix-filename-rubout", rl_unix_filename_rubout },
|
||||
{ "unix-line-discard", rl_unix_line_discard },
|
||||
{ "unix-word-rubout", rl_unix_word_rubout },
|
||||
{ "upcase-word", rl_upcase_word },
|
||||
{ "yank", rl_yank },
|
||||
{ "yank-last-arg", rl_yank_last_arg },
|
||||
{ "yank-nth-arg", rl_yank_nth_arg },
|
||||
{ "yank-pop", rl_yank_pop },
|
||||
|
||||
#if defined (VI_MODE)
|
||||
{ "vi-append-eol", rl_vi_append_eol },
|
||||
{ "vi-append-mode", rl_vi_append_mode },
|
||||
{ "vi-arg-digit", rl_vi_arg_digit },
|
||||
{ "vi-back-to-indent", rl_vi_back_to_indent },
|
||||
{ "vi-backward-bigword", rl_vi_bWord },
|
||||
{ "vi-backward-word", rl_vi_bword },
|
||||
{ "vi-bWord", rl_vi_bWord },
|
||||
{ "vi-bword", rl_vi_bword },
|
||||
{ "vi-change-case", rl_vi_change_case },
|
||||
{ "vi-change-char", rl_vi_change_char },
|
||||
{ "vi-change-to", rl_vi_change_to },
|
||||
{ "vi-char-search", rl_vi_char_search },
|
||||
{ "vi-column", rl_vi_column },
|
||||
{ "vi-complete", rl_vi_complete },
|
||||
{ "vi-delete", rl_vi_delete },
|
||||
{ "vi-delete-to", rl_vi_delete_to },
|
||||
{ "vi-eWord", rl_vi_eWord },
|
||||
{ "vi-editing-mode", rl_vi_editing_mode },
|
||||
{ "vi-end-bigword", rl_vi_eWord },
|
||||
{ "vi-end-word", rl_vi_end_word },
|
||||
{ "vi-eof-maybe", rl_vi_eof_maybe },
|
||||
{ "vi-eword", rl_vi_eword },
|
||||
{ "vi-fWord", rl_vi_fWord },
|
||||
{ "vi-fetch-history", rl_vi_fetch_history },
|
||||
{ "vi-first-print", rl_vi_first_print },
|
||||
{ "vi-forward-bigword", rl_vi_fWord },
|
||||
{ "vi-forward-word", rl_vi_fword },
|
||||
{ "vi-fword", rl_vi_fword },
|
||||
{ "vi-goto-mark", rl_vi_goto_mark },
|
||||
{ "vi-insert-beg", rl_vi_insert_beg },
|
||||
{ "vi-insertion-mode", rl_vi_insertion_mode },
|
||||
{ "vi-match", rl_vi_match },
|
||||
{ "vi-movement-mode", rl_vi_movement_mode },
|
||||
{ "vi-next-word", rl_vi_next_word },
|
||||
{ "vi-overstrike", rl_vi_overstrike },
|
||||
{ "vi-overstrike-delete", rl_vi_overstrike_delete },
|
||||
{ "vi-prev-word", rl_vi_prev_word },
|
||||
{ "vi-put", rl_vi_put },
|
||||
{ "vi-redo", rl_vi_redo },
|
||||
{ "vi-replace", rl_vi_replace },
|
||||
{ "vi-rubout", rl_vi_rubout },
|
||||
{ "vi-search", rl_vi_search },
|
||||
{ "vi-search-again", rl_vi_search_again },
|
||||
{ "vi-set-mark", rl_vi_set_mark },
|
||||
{ "vi-subst", rl_vi_subst },
|
||||
{ "vi-tilde-expand", rl_vi_tilde_expand },
|
||||
{ "vi-yank-arg", rl_vi_yank_arg },
|
||||
{ "vi-yank-to", rl_vi_yank_to },
|
||||
#endif /* VI_MODE */
|
||||
|
||||
{(char *)NULL, (rl_command_func_t *)NULL }
|
||||
};
|
||||
|
||||
int
|
||||
rl_add_funmap_entry (name, function)
|
||||
const char *name;
|
||||
rl_command_func_t *function;
|
||||
{
|
||||
if (funmap_entry + 2 >= funmap_size)
|
||||
{
|
||||
funmap_size += 64;
|
||||
funmap = (FUNMAP **)xrealloc (funmap, funmap_size * sizeof (FUNMAP *));
|
||||
}
|
||||
|
||||
funmap[funmap_entry] = (FUNMAP *)xmalloc (sizeof (FUNMAP));
|
||||
funmap[funmap_entry]->name = name;
|
||||
funmap[funmap_entry]->function = function;
|
||||
|
||||
funmap[++funmap_entry] = (FUNMAP *)NULL;
|
||||
return funmap_entry;
|
||||
}
|
||||
|
||||
static int funmap_initialized;
|
||||
|
||||
/* Make the funmap contain all of the default entries. */
|
||||
void
|
||||
rl_initialize_funmap ()
|
||||
{
|
||||
register int i;
|
||||
|
||||
if (funmap_initialized)
|
||||
return;
|
||||
|
||||
for (i = 0; default_funmap[i].name; i++)
|
||||
rl_add_funmap_entry (default_funmap[i].name, default_funmap[i].function);
|
||||
|
||||
funmap_initialized = 1;
|
||||
funmap_program_specific_entry_start = i;
|
||||
}
|
||||
|
||||
/* Produce a NULL terminated array of known function names. The array
|
||||
is sorted. The array itself is allocated, but not the strings inside.
|
||||
You should free () the array when you done, but not the pointrs. */
|
||||
const char **
|
||||
rl_funmap_names ()
|
||||
{
|
||||
const char **result;
|
||||
int result_size, result_index;
|
||||
|
||||
/* Make sure that the function map has been initialized. */
|
||||
rl_initialize_funmap ();
|
||||
|
||||
for (result_index = result_size = 0, result = (const char **)NULL; funmap[result_index]; result_index++)
|
||||
{
|
||||
if (result_index + 2 > result_size)
|
||||
{
|
||||
result_size += 20;
|
||||
result = (const char **)xrealloc (result, result_size * sizeof (char *));
|
||||
}
|
||||
|
||||
result[result_index] = funmap[result_index]->name;
|
||||
result[result_index + 1] = (char *)NULL;
|
||||
}
|
||||
|
||||
qsort (result, result_index, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare);
|
||||
return (result);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/* histexpand.c -- history expansion. */
|
||||
|
||||
/* Copyright (C) 1989-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (History), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
|
||||
@@ -1472,7 +1472,7 @@ history_tokenize_word (string, ind)
|
||||
}
|
||||
}
|
||||
|
||||
/* same mechanism also used for <(...)/>(...) above */
|
||||
/* same code also used for $(...)/<(...)/>(...) above */
|
||||
if (member (string[i], "!@?+*"))
|
||||
{
|
||||
int peek = string[i + 1];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* histfile.c - functions to manipulate the history file. */
|
||||
|
||||
/* Copyright (C) 1989-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the GNU History Library (History), a set of
|
||||
routines for managing the text of previously typed lines.
|
||||
|
||||
@@ -126,8 +126,12 @@ history_filename (filename)
|
||||
|
||||
if (home == 0)
|
||||
{
|
||||
#if 0
|
||||
home = ".";
|
||||
home_len = 1;
|
||||
#else
|
||||
return (NULL);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
home_len = strlen (home);
|
||||
@@ -179,7 +183,7 @@ read_history_range (filename, from, to)
|
||||
|
||||
buffer = last_ts = (char *)NULL;
|
||||
input = history_filename (filename);
|
||||
file = open (input, O_RDONLY|O_BINARY, 0666);
|
||||
file = input ? open (input, O_RDONLY|O_BINARY, 0666) : -1;
|
||||
|
||||
if ((file < 0) || (fstat (file, &finfo) == -1))
|
||||
goto error_and_exit;
|
||||
@@ -314,7 +318,7 @@ history_truncate_file (fname, lines)
|
||||
|
||||
buffer = (char *)NULL;
|
||||
filename = history_filename (fname);
|
||||
file = open (filename, O_RDONLY|O_BINARY, 0666);
|
||||
file = filename ? open (filename, O_RDONLY|O_BINARY, 0666) : -1;
|
||||
rv = 0;
|
||||
|
||||
/* Don't try to truncate non-regular files. */
|
||||
@@ -436,9 +440,10 @@ history_do_write (filename, nelements, overwrite)
|
||||
mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
|
||||
#endif
|
||||
output = history_filename (filename);
|
||||
file = output ? open (output, mode, 0600) : -1;
|
||||
rv = 0;
|
||||
|
||||
if ((file = open (output, mode, 0600)) == -1)
|
||||
if (file == -1)
|
||||
{
|
||||
FREE (output);
|
||||
return (errno);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* input.c -- character input functions for readline. */
|
||||
|
||||
/* Copyright (C) 1994-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1994-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
|
||||
@@ -133,7 +133,6 @@ rl_get_char (key)
|
||||
#endif
|
||||
pop_index = 0;
|
||||
|
||||
fprintf(stderr, "rl_get_char: returning 1 (key = %d)\n", *key);
|
||||
return (1);
|
||||
}
|
||||
|
||||
@@ -428,17 +427,19 @@ rl_read_key ()
|
||||
/* If the user has an event function, then call it periodically. */
|
||||
if (rl_event_hook)
|
||||
{
|
||||
while (rl_event_hook && rl_get_char (&c) == 0)
|
||||
while (rl_event_hook)
|
||||
{
|
||||
(*rl_event_hook) ();
|
||||
RL_CHECK_SIGNALS ();
|
||||
if (rl_done) /* XXX - experimental */
|
||||
return ('\n');
|
||||
if (rl_gather_tyi () < 0) /* XXX - EIO */
|
||||
{
|
||||
rl_done = 1;
|
||||
return ('\n');
|
||||
}
|
||||
RL_CHECK_SIGNALS ();
|
||||
if (rl_get_char (&c) != 0)
|
||||
break;
|
||||
if (rl_done) /* XXX - experimental */
|
||||
return ('\n');
|
||||
(*rl_event_hook) ();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* rlprivate.h -- functions and variables global to the readline library,
|
||||
but not intended for use by applications. */
|
||||
|
||||
/* Copyright (C) 1999-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1999-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -120,7 +120,28 @@ typedef struct __rl_keyseq_context
|
||||
int childval;
|
||||
} _rl_keyseq_cxt;
|
||||
|
||||
/* fill in more as needed */
|
||||
/* vi-mode commands that use result of motion command to define boundaries */
|
||||
#define VIM_DELETE 0x01
|
||||
#define VIM_CHANGE 0x02
|
||||
#define VIM_YANK 0x04
|
||||
|
||||
/* various states for vi-mode commands that use motion commands. reflects
|
||||
RL_READLINE_STATE */
|
||||
#define VMSTATE_READ 0x01
|
||||
#define VMSTATE_NUMARG 0x02
|
||||
|
||||
typedef struct __rl_vimotion_context
|
||||
{
|
||||
int op;
|
||||
int state;
|
||||
int flags; /* reserved */
|
||||
_rl_arg_cxt ncxt;
|
||||
int numeric_arg;
|
||||
int start, end; /* rl_point, rl_end */
|
||||
int key, motion; /* initial key, motion command */
|
||||
} _rl_vimotion_cxt;
|
||||
|
||||
/* fill in more as needed */
|
||||
/* `Generic' callback data and functions */
|
||||
typedef struct __rl_callback_generic_arg
|
||||
{
|
||||
@@ -388,6 +409,7 @@ extern int _rl_completion_prefix_display_length;
|
||||
extern int _rl_completion_columns;
|
||||
extern int _rl_print_completions_horizontally;
|
||||
extern int _rl_completion_case_fold;
|
||||
extern int _rl_completion_case_map;
|
||||
extern int _rl_match_hidden_files;
|
||||
extern int _rl_page_completions;
|
||||
extern int _rl_skip_completed_text;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* rlprivate.h -- functions and variables global to the readline library,
|
||||
but not intended for use by applications. */
|
||||
|
||||
/* Copyright (C) 1999-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1999-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -120,7 +120,23 @@ typedef struct __rl_keyseq_context
|
||||
int childval;
|
||||
} _rl_keyseq_cxt;
|
||||
|
||||
/* fill in more as needed */
|
||||
/* vi-mode commands that use result of motion command to define boundaries */
|
||||
#define VIM_DELETE 0x01
|
||||
#define VIM_CHANGE 0x02
|
||||
#define VIM_YANK 0x04
|
||||
|
||||
typedef struct __rl_vimotion_context
|
||||
{
|
||||
int op;
|
||||
int state;
|
||||
int flags; /* reserved */
|
||||
_rl_arg_cxt ncxt;
|
||||
int numeric_arg;
|
||||
int start, end; /* rl_point, rl_end */
|
||||
int key, motion; /* initial key, motion command */
|
||||
} _rl_vimotion_cxt;
|
||||
|
||||
/* fill in more as needed */
|
||||
/* `Generic' callback data and functions */
|
||||
typedef struct __rl_callback_generic_arg
|
||||
{
|
||||
@@ -385,8 +401,10 @@ extern int _rl_complete_show_unmodified;
|
||||
extern int _rl_complete_mark_directories;
|
||||
extern int _rl_complete_mark_symlink_dirs;
|
||||
extern int _rl_completion_prefix_display_length;
|
||||
extern int _rl_completion_columns;
|
||||
extern int _rl_print_completions_horizontally;
|
||||
extern int _rl_completion_case_fold;
|
||||
extern int _rl_completion_case_map;
|
||||
extern int _rl_match_hidden_files;
|
||||
extern int _rl_page_completions;
|
||||
extern int _rl_skip_completed_text;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* text.c -- text handling commands for readline. */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
|
||||
@@ -1495,6 +1495,9 @@ _rl_char_search_internal (count, dir, schar)
|
||||
int prepos;
|
||||
#endif
|
||||
|
||||
if (dir == 0)
|
||||
return -1;
|
||||
|
||||
pos = rl_point;
|
||||
inc = (dir < 0) ? -1 : 1;
|
||||
while (count)
|
||||
|
||||
+33
-18
@@ -1,6 +1,6 @@
|
||||
/* util.c -- readline utility functions */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -366,41 +366,56 @@ _rl_strpbrk (string1, string2)
|
||||
|
||||
#if !defined (HAVE_STRCASECMP)
|
||||
/* Compare at most COUNT characters from string1 to string2. Case
|
||||
doesn't matter. */
|
||||
doesn't matter (strncasecmp). */
|
||||
int
|
||||
_rl_strnicmp (string1, string2, count)
|
||||
char *string1, *string2;
|
||||
int count;
|
||||
{
|
||||
register char ch1, ch2;
|
||||
register char *s1, *s2;
|
||||
int d;
|
||||
|
||||
while (count)
|
||||
if (count <= 0 || (string1 == string2))
|
||||
return 0;
|
||||
|
||||
s1 = string1;
|
||||
s2 = string2;
|
||||
do
|
||||
{
|
||||
ch1 = *string1++;
|
||||
ch2 = *string2++;
|
||||
if (_rl_to_upper(ch1) == _rl_to_upper(ch2))
|
||||
count--;
|
||||
else
|
||||
d = _rl_to_lower (*s1) - _rl_to_lower (*s2); /* XXX - cast to unsigned char? */
|
||||
if (d != 0)
|
||||
return d;
|
||||
if (*s1++ == '\0')
|
||||
break;
|
||||
s2++;
|
||||
}
|
||||
return (count);
|
||||
while (--count != 0)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* strcmp (), but caseless. */
|
||||
/* strcmp (), but caseless (strcasecmp). */
|
||||
int
|
||||
_rl_stricmp (string1, string2)
|
||||
char *string1, *string2;
|
||||
{
|
||||
register char ch1, ch2;
|
||||
register char *s1, *s2;
|
||||
int d;
|
||||
|
||||
while (*string1 && *string2)
|
||||
s1 = string1;
|
||||
s2 = string2;
|
||||
|
||||
if (s1 == s2)
|
||||
return 0;
|
||||
|
||||
while ((d = _rl_to_lower (*s1) - _rl_to_lower (*s2)) == 0)
|
||||
{
|
||||
ch1 = *string1++;
|
||||
ch2 = *string2++;
|
||||
if (_rl_to_upper(ch1) != _rl_to_upper(ch2))
|
||||
return (1);
|
||||
if (*s1++ == '\0')
|
||||
return 0;
|
||||
s2++;
|
||||
}
|
||||
return (*string1 - *string2);
|
||||
|
||||
return (d);
|
||||
}
|
||||
#endif /* !HAVE_STRCASECMP */
|
||||
|
||||
|
||||
@@ -0,0 +1,526 @@
|
||||
/* util.c -- readline utility functions */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
|
||||
Readline is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Readline is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Readline. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define READLINE_LIBRARY
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include "posixjmp.h"
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h> /* for _POSIX_VERSION */
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* System-specific feature definitions and include files. */
|
||||
#include "rldefs.h"
|
||||
#include "rlmbutil.h"
|
||||
|
||||
#if defined (TIOCSTAT_IN_SYS_IOCTL)
|
||||
# include <sys/ioctl.h>
|
||||
#endif /* TIOCSTAT_IN_SYS_IOCTL */
|
||||
|
||||
/* Some standard library routines. */
|
||||
#include "readline.h"
|
||||
|
||||
#include "rlprivate.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Utility Functions */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Return 0 if C is not a member of the class of characters that belong
|
||||
in words, or 1 if it is. */
|
||||
|
||||
int _rl_allow_pathname_alphabetic_chars = 0;
|
||||
static const char * const pathname_alphabetic_chars = "/-_=~.#$";
|
||||
|
||||
int
|
||||
rl_alphabetic (c)
|
||||
int c;
|
||||
{
|
||||
if (ALPHABETIC (c))
|
||||
return (1);
|
||||
|
||||
return (_rl_allow_pathname_alphabetic_chars &&
|
||||
strchr (pathname_alphabetic_chars, c) != NULL);
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
int
|
||||
_rl_walphabetic (wchar_t wc)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (iswalnum (wc))
|
||||
return (1);
|
||||
|
||||
c = wc & 0177;
|
||||
return (_rl_allow_pathname_alphabetic_chars &&
|
||||
strchr (pathname_alphabetic_chars, c) != NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* How to abort things. */
|
||||
int
|
||||
_rl_abort_internal ()
|
||||
{
|
||||
rl_ding ();
|
||||
rl_clear_message ();
|
||||
_rl_reset_argument ();
|
||||
rl_clear_pending_input ();
|
||||
|
||||
RL_UNSETSTATE (RL_STATE_MACRODEF);
|
||||
while (rl_executing_macro)
|
||||
_rl_pop_executing_macro ();
|
||||
|
||||
rl_last_func = (rl_command_func_t *)NULL;
|
||||
longjmp (_rl_top_level, 1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
rl_abort (count, key)
|
||||
int count, key;
|
||||
{
|
||||
return (_rl_abort_internal ());
|
||||
}
|
||||
|
||||
int
|
||||
_rl_null_function (count, key)
|
||||
int count, key;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rl_tty_status (count, key)
|
||||
int count, key;
|
||||
{
|
||||
#if defined (TIOCSTAT)
|
||||
ioctl (1, TIOCSTAT, (char *)0);
|
||||
rl_refresh_line (count, key);
|
||||
#else
|
||||
rl_ding ();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return a copy of the string between FROM and TO.
|
||||
FROM is inclusive, TO is not. */
|
||||
char *
|
||||
rl_copy_text (from, to)
|
||||
int from, to;
|
||||
{
|
||||
register int length;
|
||||
char *copy;
|
||||
|
||||
/* Fix it if the caller is confused. */
|
||||
if (from > to)
|
||||
SWAP (from, to);
|
||||
|
||||
length = to - from;
|
||||
copy = (char *)xmalloc (1 + length);
|
||||
strncpy (copy, rl_line_buffer + from, length);
|
||||
copy[length] = '\0';
|
||||
return (copy);
|
||||
}
|
||||
|
||||
/* Increase the size of RL_LINE_BUFFER until it has enough space to hold
|
||||
LEN characters. */
|
||||
void
|
||||
rl_extend_line_buffer (len)
|
||||
int len;
|
||||
{
|
||||
while (len >= rl_line_buffer_len)
|
||||
{
|
||||
rl_line_buffer_len += DEFAULT_BUFFER_SIZE;
|
||||
rl_line_buffer = (char *)xrealloc (rl_line_buffer, rl_line_buffer_len);
|
||||
}
|
||||
|
||||
_rl_set_the_line ();
|
||||
}
|
||||
|
||||
|
||||
/* A function for simple tilde expansion. */
|
||||
int
|
||||
rl_tilde_expand (ignore, key)
|
||||
int ignore, key;
|
||||
{
|
||||
register int start, end;
|
||||
char *homedir, *temp;
|
||||
int len;
|
||||
|
||||
end = rl_point;
|
||||
start = end - 1;
|
||||
|
||||
if (rl_point == rl_end && rl_line_buffer[rl_point] == '~')
|
||||
{
|
||||
homedir = tilde_expand ("~");
|
||||
_rl_replace_text (homedir, start, end);
|
||||
xfree (homedir);
|
||||
return (0);
|
||||
}
|
||||
else if (rl_line_buffer[start] != '~')
|
||||
{
|
||||
for (; !whitespace (rl_line_buffer[start]) && start >= 0; start--)
|
||||
;
|
||||
start++;
|
||||
}
|
||||
|
||||
end = start;
|
||||
do
|
||||
end++;
|
||||
while (whitespace (rl_line_buffer[end]) == 0 && end < rl_end);
|
||||
|
||||
if (whitespace (rl_line_buffer[end]) || end >= rl_end)
|
||||
end--;
|
||||
|
||||
/* If the first character of the current word is a tilde, perform
|
||||
tilde expansion and insert the result. If not a tilde, do
|
||||
nothing. */
|
||||
if (rl_line_buffer[start] == '~')
|
||||
{
|
||||
len = end - start + 1;
|
||||
temp = (char *)xmalloc (len + 1);
|
||||
strncpy (temp, rl_line_buffer + start, len);
|
||||
temp[len] = '\0';
|
||||
homedir = tilde_expand (temp);
|
||||
xfree (temp);
|
||||
|
||||
_rl_replace_text (homedir, start, end);
|
||||
xfree (homedir);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if defined (USE_VARARGS)
|
||||
void
|
||||
#if defined (PREFER_STDARG)
|
||||
_rl_ttymsg (const char *format, ...)
|
||||
#else
|
||||
_rl_ttymsg (va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#if defined (PREFER_VARARGS)
|
||||
char *format;
|
||||
#endif
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
va_start (args, format);
|
||||
#else
|
||||
va_start (args);
|
||||
format = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
fprintf (stderr, "readline: ");
|
||||
vfprintf (stderr, format, args);
|
||||
fprintf (stderr, "\n");
|
||||
fflush (stderr);
|
||||
|
||||
va_end (args);
|
||||
|
||||
rl_forced_update_display ();
|
||||
}
|
||||
|
||||
void
|
||||
#if defined (PREFER_STDARG)
|
||||
_rl_errmsg (const char *format, ...)
|
||||
#else
|
||||
_rl_errmsg (va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#if defined (PREFER_VARARGS)
|
||||
char *format;
|
||||
#endif
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
va_start (args, format);
|
||||
#else
|
||||
va_start (args);
|
||||
format = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
fprintf (stderr, "readline: ");
|
||||
vfprintf (stderr, format, args);
|
||||
fprintf (stderr, "\n");
|
||||
fflush (stderr);
|
||||
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
#else /* !USE_VARARGS */
|
||||
void
|
||||
_rl_ttymsg (format, arg1, arg2)
|
||||
char *format;
|
||||
{
|
||||
fprintf (stderr, "readline: ");
|
||||
fprintf (stderr, format, arg1, arg2);
|
||||
fprintf (stderr, "\n");
|
||||
|
||||
rl_forced_update_display ();
|
||||
}
|
||||
|
||||
void
|
||||
_rl_errmsg (format, arg1, arg2)
|
||||
char *format;
|
||||
{
|
||||
fprintf (stderr, "readline: ");
|
||||
fprintf (stderr, format, arg1, arg2);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
#endif /* !USE_VARARGS */
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* String Utility Functions */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Determine if s2 occurs in s1. If so, return a pointer to the
|
||||
match in s1. The compare is case insensitive. */
|
||||
char *
|
||||
_rl_strindex (s1, s2)
|
||||
register const char *s1, *s2;
|
||||
{
|
||||
register int i, l, len;
|
||||
|
||||
for (i = 0, l = strlen (s2), len = strlen (s1); (len - i) >= l; i++)
|
||||
if (_rl_strnicmp (s1 + i, s2, l) == 0)
|
||||
return ((char *) (s1 + i));
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
#ifndef HAVE_STRPBRK
|
||||
/* Find the first occurrence in STRING1 of any character from STRING2.
|
||||
Return a pointer to the character in STRING1. */
|
||||
char *
|
||||
_rl_strpbrk (string1, string2)
|
||||
const char *string1, *string2;
|
||||
{
|
||||
register const char *scan;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
mbstate_t ps;
|
||||
register int i, v;
|
||||
|
||||
memset (&ps, 0, sizeof (mbstate_t));
|
||||
#endif
|
||||
|
||||
for (; *string1; string1++)
|
||||
{
|
||||
for (scan = string2; *scan; scan++)
|
||||
{
|
||||
if (*string1 == *scan)
|
||||
return ((char *)string1);
|
||||
}
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
v = _rl_get_char_len (string1, &ps);
|
||||
if (v > 1)
|
||||
string1 += v - 1; /* -1 to account for auto-increment in loop */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return ((char *)NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined (HAVE_STRCASECMP)
|
||||
/* Compare at most COUNT characters from string1 to string2. Case
|
||||
doesn't matter (strncasecmp). */
|
||||
int
|
||||
_rl_strnicmp (string1, string2, count)
|
||||
char *string1, *string2;
|
||||
int count;
|
||||
{
|
||||
register char *s1, *s2;
|
||||
int d;
|
||||
|
||||
if (count <= 0 || (string1 == string2))
|
||||
return 0;
|
||||
|
||||
s1 = string1;
|
||||
s2 = string2;
|
||||
do
|
||||
{
|
||||
d = _rl_to_lower (*s1) - _rl_to_lower (*s2); /* XXX - cast to unsigned char? */
|
||||
if (d != 0)
|
||||
return d;
|
||||
if (*s1++ == '\0')
|
||||
break;
|
||||
s2++;
|
||||
}
|
||||
while (--count != 0)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* strcmp (), but caseless (strcasecmp). */
|
||||
int
|
||||
_rl_stricmp (string1, string2)
|
||||
char *string1, *string2;
|
||||
{
|
||||
register char *s1, *s2;
|
||||
int d;
|
||||
|
||||
s1 = string1;
|
||||
s2 = string2;
|
||||
|
||||
if (s1 == s2)
|
||||
return 0;
|
||||
|
||||
while ((d = _rl_to_lower (*s1) - _rl_to_lower (*s2)) == 0)
|
||||
{
|
||||
if (*s1++ == '\0')
|
||||
return 0;
|
||||
s2++;
|
||||
}
|
||||
|
||||
return (d);
|
||||
}
|
||||
#endif /* !HAVE_STRCASECMP */
|
||||
|
||||
/* Stupid comparison routine for qsort () ing strings. */
|
||||
int
|
||||
_rl_qsort_string_compare (s1, s2)
|
||||
char **s1, **s2;
|
||||
{
|
||||
#if defined (HAVE_STRCOLL)
|
||||
return (strcoll (*s1, *s2));
|
||||
#else
|
||||
int result;
|
||||
|
||||
result = **s1 - **s2;
|
||||
if (result == 0)
|
||||
result = strcmp (*s1, *s2);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Function equivalents for the macros defined in chardefs.h. */
|
||||
#define FUNCTION_FOR_MACRO(f) int (f) (c) int c; { return f (c); }
|
||||
|
||||
FUNCTION_FOR_MACRO (_rl_digit_p)
|
||||
FUNCTION_FOR_MACRO (_rl_digit_value)
|
||||
FUNCTION_FOR_MACRO (_rl_lowercase_p)
|
||||
FUNCTION_FOR_MACRO (_rl_pure_alphabetic)
|
||||
FUNCTION_FOR_MACRO (_rl_to_lower)
|
||||
FUNCTION_FOR_MACRO (_rl_to_upper)
|
||||
FUNCTION_FOR_MACRO (_rl_uppercase_p)
|
||||
|
||||
/* A convenience function, to force memory deallocation to be performed
|
||||
by readline. DLLs on Windows apparently require this. */
|
||||
void
|
||||
rl_free (mem)
|
||||
void *mem;
|
||||
{
|
||||
if (mem)
|
||||
free (mem);
|
||||
}
|
||||
|
||||
/* Backwards compatibility, now that savestring has been removed from
|
||||
all `public' readline header files. */
|
||||
#undef _rl_savestring
|
||||
char *
|
||||
_rl_savestring (s)
|
||||
const char *s;
|
||||
{
|
||||
return (strcpy ((char *)xmalloc (1 + (int)strlen (s)), (s)));
|
||||
}
|
||||
|
||||
#if defined (USE_VARARGS)
|
||||
static FILE *_rl_tracefp;
|
||||
|
||||
void
|
||||
#if defined (PREFER_STDARG)
|
||||
_rl_trace (const char *format, ...)
|
||||
#else
|
||||
_rl_trace (va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#if defined (PREFER_VARARGS)
|
||||
char *format;
|
||||
#endif
|
||||
|
||||
#if defined (PREFER_STDARG)
|
||||
va_start (args, format);
|
||||
#else
|
||||
va_start (args);
|
||||
format = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
if (_rl_tracefp == 0)
|
||||
_rl_tropen ();
|
||||
vfprintf (_rl_tracefp, format, args);
|
||||
fprintf (_rl_tracefp, "\n");
|
||||
fflush (_rl_tracefp);
|
||||
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
int
|
||||
_rl_tropen ()
|
||||
{
|
||||
char fnbuf[128];
|
||||
|
||||
if (_rl_tracefp)
|
||||
fclose (_rl_tracefp);
|
||||
sprintf (fnbuf, "/var/tmp/rltrace.%ld", getpid());
|
||||
unlink(fnbuf);
|
||||
_rl_tracefp = fopen (fnbuf, "w+");
|
||||
return _rl_tracefp != 0;
|
||||
}
|
||||
|
||||
int
|
||||
_rl_trclose ()
|
||||
{
|
||||
int r;
|
||||
|
||||
r = fclose (_rl_tracefp);
|
||||
_rl_tracefp = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
+158
-37
@@ -1,7 +1,7 @@
|
||||
/* vi_mode.c -- A vi emulation mode for Bash.
|
||||
Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -65,6 +65,8 @@
|
||||
|
||||
int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
|
||||
|
||||
_rl_vimotion_cxt *_rl_vimvcxt = 0;
|
||||
|
||||
/* Non-zero means enter insertion mode. */
|
||||
static int _rl_vi_doing_insert;
|
||||
|
||||
@@ -128,6 +130,12 @@ static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *));
|
||||
static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *));
|
||||
#endif
|
||||
|
||||
static int vi_change_dispatch PARAMS((_rl_vimotion_cxt *));
|
||||
static int vi_delete_dispatch PARAMS((_rl_vimotion_cxt *));
|
||||
static int vi_yank_dispatch PARAMS((_rl_vimotion_cxt *));
|
||||
|
||||
static int vidomove_dispatch PARAMS((_rl_vimotion_cxt *));
|
||||
|
||||
void
|
||||
_rl_vi_initialize_line ()
|
||||
{
|
||||
@@ -1076,28 +1084,60 @@ rl_digit_loop1 ()
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
rl_vi_delete_to (count, key)
|
||||
int count, key;
|
||||
static void
|
||||
_rl_mvcxt_init (m, op, key)
|
||||
_rl_vimotion_cxt *m;
|
||||
int op, key;
|
||||
{
|
||||
int c, start_pos;
|
||||
m->op = op;
|
||||
m->state = m->flags = 0;
|
||||
m->ncxt = 0;
|
||||
m->numeric_arg = -1;
|
||||
m->start = rl_point;
|
||||
m->end = rl_end;
|
||||
m->key = key;
|
||||
m->motion = -1;
|
||||
}
|
||||
|
||||
if (_rl_uppercase_p (key))
|
||||
rl_stuff_char ('$');
|
||||
else if (vi_redoing)
|
||||
rl_stuff_char (_rl_vi_last_motion);
|
||||
static _rl_vimotion_cxt *
|
||||
_rl_mvcxt_alloc (op, key)
|
||||
int op, key;
|
||||
{
|
||||
_rl_vimotion_cxt *m;
|
||||
|
||||
start_pos = rl_point;
|
||||
m = xmalloc (sizeof (_rl_vimotion_cxt));
|
||||
_rl_mvcxt_init (m, op, key);
|
||||
return m;
|
||||
}
|
||||
|
||||
if (rl_vi_domove (key, &c))
|
||||
{
|
||||
rl_ding ();
|
||||
return -1;
|
||||
}
|
||||
static void
|
||||
_rl_mvcxt_dispose (m)
|
||||
_rl_vimotion_cxt *m;
|
||||
{
|
||||
free (m);
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Create context, set initial values
|
||||
* 2. Pass to rl_vi_domove to populate
|
||||
* 3. Use returned context to finish rest of command
|
||||
*
|
||||
* Context:
|
||||
* op
|
||||
* state
|
||||
* flags
|
||||
* numeric arg
|
||||
* start, end positions
|
||||
* initial key (key), motion key (c)
|
||||
*/
|
||||
|
||||
static int
|
||||
vi_delete_dispatch (m)
|
||||
_rl_vimotion_cxt *m;
|
||||
{
|
||||
/* These are the motion commands that do not require adjusting the
|
||||
mark. */
|
||||
if (((strchr (" l|h^0bBFT`", c) == 0) && (rl_point >= start_pos)) &&
|
||||
if (((strchr (" l|h^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
|
||||
(rl_mark < rl_end))
|
||||
rl_mark++;
|
||||
|
||||
@@ -1106,34 +1146,47 @@ rl_vi_delete_to (count, key)
|
||||
}
|
||||
|
||||
int
|
||||
rl_vi_change_to (count, key)
|
||||
rl_vi_delete_to (count, key)
|
||||
int count, key;
|
||||
{
|
||||
int c, start_pos;
|
||||
int c, r;
|
||||
|
||||
if (_rl_uppercase_p (key))
|
||||
rl_stuff_char ('$');
|
||||
else if (vi_redoing)
|
||||
rl_stuff_char (_rl_vi_last_motion);
|
||||
|
||||
start_pos = rl_point;
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
|
||||
_rl_vimvcxt->start = rl_point;
|
||||
|
||||
/* XXX -- TODO -- pass and use context in rl_vi_domove */
|
||||
if (rl_vi_domove (key, &c))
|
||||
{
|
||||
rl_ding ();
|
||||
return -1;
|
||||
}
|
||||
_rl_vimvcxt->motion = c;
|
||||
|
||||
r = vidomove_dispatch (_rl_vimvcxt);
|
||||
_rl_mvcxt_dispose (_rl_vimvcxt);
|
||||
_rl_vimvcxt = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
vi_change_dispatch (m)
|
||||
_rl_vimotion_cxt *m;
|
||||
{
|
||||
/* These are the motion commands that do not require adjusting the
|
||||
mark. c[wW] are handled by special-case code in rl_vi_domove(),
|
||||
and already leave the mark at the correct location. */
|
||||
if (((strchr (" l|hwW^0bBFT`", c) == 0) && (rl_point >= start_pos)) &&
|
||||
if (((strchr (" l|hwW^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
|
||||
(rl_mark < rl_end))
|
||||
rl_mark++;
|
||||
|
||||
/* The cursor never moves with c[wW]. */
|
||||
if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
|
||||
rl_point = start_pos;
|
||||
if ((_rl_to_upper (m->motion) == 'W') && rl_point < m->start)
|
||||
rl_point = m->start;
|
||||
|
||||
if (vi_redoing)
|
||||
{
|
||||
@@ -1151,44 +1204,112 @@ rl_vi_change_to (count, key)
|
||||
rl_begin_undo_group (); /* to make the `u' command work */
|
||||
rl_kill_text (rl_point, rl_mark);
|
||||
/* `C' does not save the text inserted for undoing or redoing. */
|
||||
if (_rl_uppercase_p (key) == 0)
|
||||
if (_rl_uppercase_p (m->key) == 0)
|
||||
_rl_vi_doing_insert = 1;
|
||||
rl_vi_start_inserting (key, rl_numeric_arg, rl_arg_sign);
|
||||
/* XXX -- TODO -- use m->numericarg? */
|
||||
rl_vi_start_inserting (m->key, rl_numeric_arg, rl_arg_sign);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
rl_vi_change_to (count, key)
|
||||
int count, key;
|
||||
{
|
||||
int c, r;
|
||||
|
||||
if (_rl_uppercase_p (key))
|
||||
rl_stuff_char ('$');
|
||||
else if (vi_redoing)
|
||||
rl_stuff_char (_rl_vi_last_motion);
|
||||
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
|
||||
_rl_vimvcxt->start = rl_point;
|
||||
|
||||
/* XXX -- TODO -- pass and use context in rl_vi_domove */
|
||||
if (rl_vi_domove (key, &c))
|
||||
{
|
||||
rl_ding ();
|
||||
return -1;
|
||||
}
|
||||
_rl_vimvcxt->motion = c;
|
||||
|
||||
r = vidomove_dispatch (_rl_vimvcxt);
|
||||
_rl_mvcxt_dispose (_rl_vimvcxt);
|
||||
_rl_vimvcxt = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
vi_yank_dispatch (m)
|
||||
_rl_vimotion_cxt *m;
|
||||
{
|
||||
/* These are the motion commands that do not require adjusting the
|
||||
mark. */
|
||||
if (((strchr (" l|h^0%bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
|
||||
(rl_mark < rl_end))
|
||||
rl_mark++;
|
||||
|
||||
rl_begin_undo_group ();
|
||||
rl_kill_text (rl_point, rl_mark);
|
||||
rl_end_undo_group ();
|
||||
rl_do_undo ();
|
||||
rl_point = m->start;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
rl_vi_yank_to (count, key)
|
||||
int count, key;
|
||||
{
|
||||
int c, start_pos;
|
||||
int c, r;
|
||||
|
||||
if (_rl_uppercase_p (key))
|
||||
rl_stuff_char ('$');
|
||||
|
||||
start_pos = rl_point;
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
|
||||
_rl_vimvcxt->start = rl_point;
|
||||
|
||||
/* XXX -- TODO -- pass and use context in rl_vi_domove */
|
||||
if (rl_vi_domove (key, &c))
|
||||
{
|
||||
rl_ding ();
|
||||
return -1;
|
||||
}
|
||||
_rl_vimvcxt->motion = c;
|
||||
|
||||
/* These are the motion commands that do not require adjusting the
|
||||
mark. */
|
||||
if (((strchr (" l|h^0%bBFT`", c) == 0) && (rl_point >= start_pos)) &&
|
||||
(rl_mark < rl_end))
|
||||
rl_mark++;
|
||||
r = vidomove_dispatch (_rl_vimvcxt);
|
||||
_rl_mvcxt_dispose (_rl_vimvcxt);
|
||||
_rl_vimvcxt = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
rl_begin_undo_group ();
|
||||
rl_kill_text (rl_point, rl_mark);
|
||||
rl_end_undo_group ();
|
||||
rl_do_undo ();
|
||||
rl_point = start_pos;
|
||||
static int
|
||||
vidomove_dispatch (m)
|
||||
_rl_vimotion_cxt *m;
|
||||
{
|
||||
int r;
|
||||
|
||||
return (0);
|
||||
switch (m->op)
|
||||
{
|
||||
case VIM_DELETE:
|
||||
r = vi_delete_dispatch (m);
|
||||
break;
|
||||
case VIM_CHANGE:
|
||||
r = vi_change_dispatch (m);
|
||||
break;
|
||||
case VIM_YANK:
|
||||
r = vi_yank_dispatch (m);
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "vidomove_dispatch: unknown operator %d", m->op);
|
||||
r = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+170
-48
@@ -1,7 +1,7 @@
|
||||
/* vi_mode.c -- A vi emulation mode for Bash.
|
||||
Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
|
||||
|
||||
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
@@ -65,6 +65,8 @@
|
||||
|
||||
int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
|
||||
|
||||
_rl_vimotion_cxt *_rl_vimvcxt = 0;
|
||||
|
||||
/* Non-zero means enter insertion mode. */
|
||||
static int _rl_vi_doing_insert;
|
||||
|
||||
@@ -128,6 +130,12 @@ static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *));
|
||||
static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *));
|
||||
#endif
|
||||
|
||||
static int vi_change_dispatch PARAMS((_rl_vimotion_cxt *));
|
||||
static int vi_delete_dispatch PARAMS((_rl_vimotion_cxt *));
|
||||
static int vi_yank_dispatch PARAMS((_rl_vimotion_cxt *));
|
||||
|
||||
static int vidomove_dispatch PARAMS((_rl_vimotion_cxt *));
|
||||
|
||||
void
|
||||
_rl_vi_initialize_line ()
|
||||
{
|
||||
@@ -1076,28 +1084,60 @@ rl_digit_loop1 ()
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
rl_vi_delete_to (count, key)
|
||||
int count, key;
|
||||
static void
|
||||
_rl_mvcxt_init (m, op, key)
|
||||
_rl_vimotion_cxt *m;
|
||||
int op, key;
|
||||
{
|
||||
int c, start_pos;
|
||||
m->op = op;
|
||||
m->state = m->flags = 0;
|
||||
m->ncxt = 0;
|
||||
m->numeric_arg = -1;
|
||||
m->start = rl_point;
|
||||
m->end = rl_end;
|
||||
m->key = key;
|
||||
m->motion = -1;
|
||||
}
|
||||
|
||||
if (_rl_uppercase_p (key))
|
||||
rl_stuff_char ('$');
|
||||
else if (vi_redoing)
|
||||
rl_stuff_char (_rl_vi_last_motion);
|
||||
static _rl_vimotion_cxt *
|
||||
_rl_mvcxt_alloc (op, key)
|
||||
int op, key;
|
||||
{
|
||||
_rl_vimotion_cxt *m;
|
||||
|
||||
start_pos = rl_point;
|
||||
m = xmalloc (sizeof (_rl_vimotion_cxt));
|
||||
_rl_mvcxt_init (m, op, key);
|
||||
return m;
|
||||
}
|
||||
|
||||
if (rl_vi_domove (key, &c))
|
||||
{
|
||||
rl_ding ();
|
||||
return -1;
|
||||
}
|
||||
static void
|
||||
_rl_mvcxt_dispose (m)
|
||||
_rl_vimotion_cxt *m;
|
||||
{
|
||||
free (m);
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Create context, set initial values
|
||||
* 2. Pass to rl_vi_domove to populate
|
||||
* 3. Use returned context to finish rest of command
|
||||
*
|
||||
* Context:
|
||||
* op
|
||||
* state
|
||||
* flags
|
||||
* numeric arg
|
||||
* start, end positions
|
||||
* initial key (key), motion key (c)
|
||||
*/
|
||||
|
||||
static int
|
||||
vi_delete_dispatch (m)
|
||||
_rl_vimotion_cxt *m;
|
||||
{
|
||||
/* These are the motion commands that do not require adjusting the
|
||||
mark. */
|
||||
if (((strchr (" l|h^0bBFT`", c) == 0) && (rl_point >= start_pos)) &&
|
||||
if (((strchr (" l|h^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
|
||||
(rl_mark < rl_end))
|
||||
rl_mark++;
|
||||
|
||||
@@ -1106,34 +1146,47 @@ rl_vi_delete_to (count, key)
|
||||
}
|
||||
|
||||
int
|
||||
rl_vi_change_to (count, key)
|
||||
rl_vi_delete_to (count, key)
|
||||
int count, key;
|
||||
{
|
||||
int c, start_pos;
|
||||
int c, r;
|
||||
|
||||
if (_rl_uppercase_p (key))
|
||||
rl_stuff_char ('$');
|
||||
else if (vi_redoing)
|
||||
rl_stuff_char (_rl_vi_last_motion);
|
||||
|
||||
start_pos = rl_point;
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
|
||||
_rl_vimvcxt->start = rl_point;
|
||||
|
||||
/* XXX -- TODO -- pass and use context in rl_vi_domove */
|
||||
if (rl_vi_domove (key, &c))
|
||||
{
|
||||
rl_ding ();
|
||||
return -1;
|
||||
}
|
||||
_rl_vimvcxt->motion = c;
|
||||
|
||||
r = vidomove_dispatch (_rl_vimvcxt);
|
||||
_rl_mvcxt_dispose (_rl_vimvcxt);
|
||||
_rl_vimvcxt = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
vi_change_dispatch (m)
|
||||
_rl_vimotion_cxt *m;
|
||||
{
|
||||
/* These are the motion commands that do not require adjusting the
|
||||
mark. c[wW] are handled by special-case code in rl_vi_domove(),
|
||||
and already leave the mark at the correct location. */
|
||||
if (((strchr (" l|hwW^0bBFT`", c) == 0) && (rl_point >= start_pos)) &&
|
||||
if (((strchr (" l|hwW^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
|
||||
(rl_mark < rl_end))
|
||||
rl_mark++;
|
||||
|
||||
/* The cursor never moves with c[wW]. */
|
||||
if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
|
||||
rl_point = start_pos;
|
||||
if ((_rl_to_upper (m->motion) == 'W') && rl_point < m->start)
|
||||
rl_point = m->start;
|
||||
|
||||
if (vi_redoing)
|
||||
{
|
||||
@@ -1151,44 +1204,112 @@ rl_vi_change_to (count, key)
|
||||
rl_begin_undo_group (); /* to make the `u' command work */
|
||||
rl_kill_text (rl_point, rl_mark);
|
||||
/* `C' does not save the text inserted for undoing or redoing. */
|
||||
if (_rl_uppercase_p (key) == 0)
|
||||
if (_rl_uppercase_p (m->key) == 0)
|
||||
_rl_vi_doing_insert = 1;
|
||||
rl_vi_start_inserting (key, rl_numeric_arg, rl_arg_sign);
|
||||
/* XXX -- TODO -- use m->numericarg? */
|
||||
rl_vi_start_inserting (m->key, rl_numeric_arg, rl_arg_sign);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
rl_vi_change_to (count, key)
|
||||
int count, key;
|
||||
{
|
||||
int c, r;
|
||||
|
||||
if (_rl_uppercase_p (key))
|
||||
rl_stuff_char ('$');
|
||||
else if (vi_redoing)
|
||||
rl_stuff_char (_rl_vi_last_motion);
|
||||
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
|
||||
_rl_vimvcxt->start = rl_point;
|
||||
|
||||
/* XXX -- TODO -- pass and use context in rl_vi_domove */
|
||||
if (rl_vi_domove (key, &c))
|
||||
{
|
||||
rl_ding ();
|
||||
return -1;
|
||||
}
|
||||
_rl_vimvcxt->motion = c;
|
||||
|
||||
r = vidomove_dispatch (_rl_vimvcxt);
|
||||
_rl_mvcxt_dispose (_rl_vimvcxt);
|
||||
_rl_vimvcxt = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
vi_yank_dispatch (m)
|
||||
_rl_vimotion_cxt *m;
|
||||
{
|
||||
/* These are the motion commands that do not require adjusting the
|
||||
mark. */
|
||||
if (((strchr (" l|h^0%bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
|
||||
(rl_mark < rl_end))
|
||||
rl_mark++;
|
||||
|
||||
rl_begin_undo_group ();
|
||||
rl_kill_text (rl_point, rl_mark);
|
||||
rl_end_undo_group ();
|
||||
rl_do_undo ();
|
||||
rl_point = m->start;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
rl_vi_yank_to (count, key)
|
||||
int count, key;
|
||||
{
|
||||
int c, start_pos;
|
||||
int c, r;
|
||||
|
||||
if (_rl_uppercase_p (key))
|
||||
rl_stuff_char ('$');
|
||||
|
||||
start_pos = rl_point;
|
||||
_rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
|
||||
_rl_vimvcxt->start = rl_point;
|
||||
|
||||
/* XXX -- TODO -- pass and use context in rl_vi_domove */
|
||||
if (rl_vi_domove (key, &c))
|
||||
{
|
||||
rl_ding ();
|
||||
return -1;
|
||||
}
|
||||
_rl_vimvcxt->motion = c;
|
||||
|
||||
/* These are the motion commands that do not require adjusting the
|
||||
mark. */
|
||||
if (((strchr (" l|h^0%bBFT`", c) == 0) && (rl_point >= start_pos)) &&
|
||||
(rl_mark < rl_end))
|
||||
rl_mark++;
|
||||
r = vidomove_dispatch (_rl_vimvcxt);
|
||||
_rl_mvcxt_dispose (_rl_vimvcxt);
|
||||
_rl_vimvcxt = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
rl_begin_undo_group ();
|
||||
rl_kill_text (rl_point, rl_mark);
|
||||
rl_end_undo_group ();
|
||||
rl_do_undo ();
|
||||
rl_point = start_pos;
|
||||
static int
|
||||
vidomove_dispatch (m)
|
||||
_rl_vimotion_cxt *m;
|
||||
{
|
||||
int r;
|
||||
|
||||
return (0);
|
||||
switch (m->op)
|
||||
{
|
||||
case VIM_DELETE:
|
||||
r = vi_delete_callback (m);
|
||||
break;
|
||||
case VIM_CHANGE:
|
||||
r = vi_change_callback (m);
|
||||
break;
|
||||
case VIM_YANK:
|
||||
r = vi_yank_callback (m);
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "vidomove_dispatch: unknown operator %d", m->op);
|
||||
r = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -1316,18 +1437,19 @@ rl_vi_char_search (count, key)
|
||||
static char target;
|
||||
#endif
|
||||
|
||||
if (_rl_cs_orig_dir == 0)
|
||||
return -1;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (_rl_vi_last_search_mblen == 0)
|
||||
return -1;
|
||||
#else
|
||||
if (_rl_vi_last_search_char == 0)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
if (key == ';' || key == ',')
|
||||
_rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir;
|
||||
{
|
||||
if (_rl_cs_orig_dir == 0)
|
||||
return -1;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (_rl_vi_last_search_mblen == 0)
|
||||
return -1;
|
||||
#else
|
||||
if (_rl_vi_last_search_char == 0)
|
||||
return -1;
|
||||
#endif
|
||||
_rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (key)
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* dprintf -- printf to a file descriptor */
|
||||
|
||||
/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2008-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
/* fdprintf -- printf to a file descriptor */
|
||||
/* dprintf -- printf to a file descriptor */
|
||||
|
||||
/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
|
||||
|
||||
@@ -38,9 +38,9 @@
|
||||
|
||||
int
|
||||
#if defined (PREFER_STDARG)
|
||||
fdprintf(int fd, const char *format, ...)
|
||||
dprintf(int fd, const char *format, ...)
|
||||
#else
|
||||
fdprintf(fd, format, va_alist)
|
||||
dprintf(fd, format, va_alist)
|
||||
int fd;
|
||||
const char *format;
|
||||
va_dcl
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* eaccess.c - eaccess replacement for the shell, plus other access functions. */
|
||||
|
||||
/* Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2006-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+6
-1
@@ -206,7 +206,12 @@ sh_eaccess (path, mode)
|
||||
#if defined (HAVE_FACCESSAT) && defined (AT_EACCESS)
|
||||
return (faccessat (AT_FDCWD, path, mode, AT_EACCESS));
|
||||
#elif defined (HAVE_EACCESS) /* FreeBSD */
|
||||
return (eaccess (path, mode)); /* XXX -- not always correct for X_OK */
|
||||
ret = eaccess (path, mode); /* XXX -- not always correct for X_OK */
|
||||
# if defined (__FreeBSD__)
|
||||
if (ret == 0 && current_user.euid == 0 && mode == X_OK)
|
||||
return (sh_stataccess (path, mode));
|
||||
# endif
|
||||
return ret;
|
||||
#elif defined (EFF_ONLY_OK) /* SVR4(?), SVR4.2 */
|
||||
return access (path, mode|EFF_ONLY_OK);
|
||||
#else
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user