From ff247e749e608ab4347949ef9796456d3e395743 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Sat, 3 Dec 2011 13:50:17 -0500 Subject: [PATCH] commit bash-20050825 snapshot --- CWRU/CWRU.chlog | 95 ++++++ CWRU/CWRU.chlog~ | 95 ++++++ bashline.c | 6 +- bashline.c~ | 2 + builtins/cd.def | 7 +- builtins/fc.def | 40 +-- builtins/fc.def~ | 54 ++-- builtins/fg_bg.def | 10 +- builtins/history.def | 7 +- builtins/kill.def | 2 +- builtins/type.def | 2 + doc/bash.1 | 15 +- doc/bash.1~ | 10 +- doc/bashref.texi | 9 +- doc/bashref.texi~ | 13 +- doc/version.texi | 10 +- doc/version.texi~ | 10 +- execute_cmd.c | 1 + general.c | 61 ++-- general.c~ | 2 +- general.h | 4 +- general.h~ | 12 +- jobs.c | 53 +++- jobs.h | 2 + lib/readline/bind.c | 15 +- lib/readline/bind.c~ | 27 +- lib/readline/doc/readline.3 | 8 +- lib/readline/doc/readline.3~ | 4 +- lib/readline/doc/rluser.texi | 6 +- lib/readline/doc/rluser.texi~ | 2 +- lib/readline/doc/version.texi | 6 +- lib/readline/doc/version.texi~ | 8 +- lib/readline/history.c | 4 +- lib/readline/isearch.c | 2 + lib/readline/isearch.c~ | 656 +++++++++++++++++++++++++++++++++++++++++ lib/readline/rlprivate.h | 2 + lib/readline/rlprivate.h~ | 418 ++++++++++++++++++++++++++ lib/readline/search.c | 19 +- lib/readline/search.c~ | 572 +++++++++++++++++++++++++++++++++++ lib/sh/pathphys.c | 1 + lib/sh/pathphys.c~ | 295 ++++++++++++++++++ nojobs.c | 11 +- 42 files changed, 2405 insertions(+), 173 deletions(-) create mode 100644 lib/readline/isearch.c~ create mode 100644 lib/readline/rlprivate.h~ create mode 100644 lib/readline/search.c~ create mode 100644 lib/sh/pathphys.c~ diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index bb67b2f..257da55 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -11949,3 +11949,98 @@ builtins/read.def `read', call sync_buffered_stream to seek backward in the input stream if necessary (XXX - should we do this for all shell builtins?) + 8/23 + ---- +builtins/cd.def + - in posix mode, if canonicalization of the absolute pathname fails + because the path length exceeds PATH_MAX, but the length of the passed + (non-absolute) pathname does not, attempt the chdir, just as when + not in posix mode + +builtins/type.def + - don't have describe_command call sh_makepath if the full path found + is already an absolute pathname (sh_makepath will stick $PWD onto the + front of it) + + 8/24 + ---- + +jobs.c + - in posix mode, don't have start_job print out and indication of + whether the job started by `bg' is the current or previous job + - change start_job to return success if a job to be resumed in the + background is already running. This means that bg won't fail when + asked to bg a background job, as SUSv3/XPG6 requires + - new function, init_job_stats, to zero out the global jobstats struct + +{jobs,nojobs}.c + - change kill_pid to handle pids < -1 by killing process groups + +jobs.h + - extern declaration for init_job_stats + +lib/readline/history.c + - check whether or not the history list is null in remove_history + +builtins/history.def + - delete_last_history is no longer static so fc builtin can use it + +builtins/fc.def + - use free_history_entry in fc_replhist instead of freeing struct + members individually + - call delete_last_history from fc_replhist instead of using inline + code + - if editing (-l not specified), make sure the fc command that caused + the editing is removed from the history list, as POSIX specifies + +builtins/kill.def + - just call kill_pid with any pid argument and let it handle pids < -1 + This is the only way to let kill_pid know whether a negative pid or + a job spec was supplied as an argument to kill + +builtins/fg_bg.def + - force fg_bg to return EXECUTION_SUCCESS explicitly if called by bg + and start_job returns successfully + - bg now returns success only if all the specified jobs were resumed + successfully + +execute_cmd.c + - call init_job_stats from initialize_subshell to zero out the global + job stats structure + + 8/25 + ---- +bashline.c + - change vi_edit_and_execute_command to just call vi when in posix + mode, instead of checking $FCEDIT and $EDITOR + +lib/readline/search.c + - if in vi_mode, call rl_free_undo_list in make_history_line_current + to dispose of undo list accumulated while reading the search string + (if this isn't done, since vi mode leaves the current history + position at the entry which matched the search, the call to + rl_revert_line in rl_internal_teardown will mangle the matched + history entry using a bogus rl_undo_list) + - call rl_free_undo_list after reading a non-incremental search string + into rl_line_buffer -- that undo list should be discarded + +lib/readline/rlprivate.h + - add UNDO_LIST * member to search context struct + +lib/readline/isearch.c + - initialize UNDO_LIST *save_undo_list member of search context struct + + 8/27 + ---- +lib/readline/bind.c + - change rl_parse_and_bind to strip whitespace from the end of a + variable value assignment before calling rl_variable_bind + +doc/bash.1,lib/readline/doc/{rluser.texi,readline.3} + - clarified the language concerning parsing values for boolean + variables in assignment statements + + 8/28 + ---- +lib/sh/pathphys.c + - fix small memory leak in sh_realpath reported by Eric Blake diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index 1fb4487..baa76bd 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -11944,3 +11944,98 @@ builtins/cd.def - in posix mode, pwd needs to check that the value it prints and `.' are the same file +builtins/read.def + - if reading input from stdin in a non-interactive shell and calling + `read', call sync_buffered_stream to seek backward in the input + stream if necessary (XXX - should we do this for all shell builtins?) + + 8/23 + ---- +builtins/cd.def + - in posix mode, if canonicalization of the absolute pathname fails + because the path length exceeds PATH_MAX, but the length of the passed + (non-absolute) pathname does not, attempt the chdir, just as when + not in posix mode + +builtins/type.def + - don't have describe_command call sh_makepath if the full path found + is already an absolute pathname (sh_makepath will stick $PWD onto the + front of it) + + 8/24 + ---- + +jobs.c + - in posix mode, don't have start_job print out and indication of + whether the job started by `bg' is the current or previous job + - change start_job to return success if a job to be resumed in the + background is already running. This means that bg won't fail when + asked to bg a background job, as SUSv3/XPG6 requires + - new function, init_job_stats, to zero out the global jobstats struct + +{jobs,nojobs}.c + - change kill_pid to handle pids < -1 by killing process groups + +jobs.h + - extern declaration for init_job_stats + +lib/readline/history.c + - check whether or not the history list is null in remove_history + +builtins/history.def + - delete_last_history is no longer static so fc builtin can use it + +builtins/fc.def + - use free_history_entry in fc_replhist instead of freeing struct + members individually + - call delete_last_history from fc_replhist instead of using inline + code + - if editing (-l not specified), make sure the fc command that caused + the editing is removed from the history list, as POSIX specifies + +builtins/kill.def + - just call kill_pid with any pid argument and let it handle pids < -1 + This is the only way to let kill_pid know whether a negative pid or + a job spec was supplied as an argument to kill + +builtins/fg_bg.def + - force fg_bg to return EXECUTION_SUCCESS explicitly if called by bg + and start_job returns successfully + - bg now returns success only if all the specified jobs were resumed + successfully + +execute_cmd.c + - call init_job_stats from initialize_subshell to zero out the global + job stats structure + + 8/25 + ---- +bashline.c + - change vi_edit_and_execute_command to just call vi when in posix + mode, instead of checking $FCEDIT and $EDITOR + +lib/readline/search.c + - if in vi_mode, call rl_free_undo_list in make_history_line_current + to dispose of undo list accumulated while reading the search string + (if this isn't done, since vi mode leaves the current history + position at the entry which matched the search, the call to + rl_revert_line in rl_internal_teardown will mangle the matched + history entry using a bogus rl_undo_list) + - call rl_free_undo_list after reading a non-incremental search string + into rl_line_buffer -- that undo list should be discarded + +lib/readline/rlprivate.h + - add UNDO_LIST * member to search context struct + +lib/readline/isearch.c + - initialize UNDO_LIST *save_undo_list member of search context struct + + 8/27 + ---- +lib/readline/bind.c + - change rl_parse_and_bind to strip whitespace from the end of a + variable value assignment before calling rl_variable_bind + +doc/bash.1,lib/readline/doc/{rluser.texi,readline.3} + - clarified the language concerning parsing values for boolean + variables in assignment statements diff --git a/bashline.c b/bashline.c index ed33b53..3fdee66 100644 --- a/bashline.c +++ b/bashline.c @@ -798,6 +798,7 @@ operate_and_get_next (count, c) #define VI_EDIT_COMMAND "fc -e \"${VISUAL:-${EDITOR:-vi}}\"" #define EMACS_EDIT_COMMAND "fc -e \"${VISUAL:-${EDITOR:-emacs}}\"" +#define POSIX_VI_EDIT_COMMAND "fc -e vi" static int edit_and_execute_command (count, c, editing_mode, edit_command) @@ -857,7 +858,10 @@ static int vi_edit_and_execute_command (count, c) int count, c; { - return (edit_and_execute_command (count, c, VI_EDITING_MODE, VI_EDIT_COMMAND)); + if (posixly_correct) + return (edit_and_execute_command (count, c, VI_EDITING_MODE, POSIX_VI_EDIT_COMMAND)); + else + return (edit_and_execute_command (count, c, VI_EDITING_MODE, VI_EDIT_COMMAND)); } #endif /* VI_MODE */ diff --git a/bashline.c~ b/bashline.c~ index 76d0f18..ed33b53 100644 --- a/bashline.c~ +++ b/bashline.c~ @@ -1522,6 +1522,8 @@ command_subst_completion_function (text, state) put the lcd in matches[0]. Skip over it. */ cmd_index = matches && matches[0] && matches[1]; + /* If there's a single match and it's a directory, set the append char + to the expected `/'. Otherwise, don't append anything. */ if (matches && matches[0] && matches[1] == 0 && test_for_directory (matches[0])) rl_completion_append_character = '/'; else diff --git a/builtins/cd.def b/builtins/cd.def index e9be35a..dad6251 100644 --- a/builtins/cd.def +++ b/builtins/cd.def @@ -400,7 +400,7 @@ change_to_directory (newdir, nolinks) int nolinks; { char *t, *tdir; - int err, canon_failed, r; + int err, canon_failed, r, ndlen, dlen; tdir = (char *)NULL; @@ -418,6 +418,9 @@ change_to_directory (newdir, nolinks) 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; @@ -433,7 +436,7 @@ change_to_directory (newdir, nolinks) /* 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) + if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX)) { #if defined ENAMETOOLONG if (errno != ENOENT && errno != ENAMETOOLONG) diff --git a/builtins/fc.def b/builtins/fc.def index a2bf881..6645d8b 100644 --- a/builtins/fc.def +++ b/builtins/fc.def @@ -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-2003 Free Software Foundation, Inc. +Copyright (C) 1987-2005 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -89,6 +89,7 @@ extern int posixly_correct; extern int unlink __P((const char *)); extern FILE *sh_mktmpfp __P((char *, int, char **)); +extern int delete_last_history __P((void)); /* **************************************************************** */ /* */ @@ -286,6 +287,11 @@ fc_builtin (list) line was actually added (HISTIGNORE may have caused it to not be), so we check hist_last_line_added. */ + /* "When not listing, he fc command that caused the editing shall not be + entered into the history list." */ + if (listing == 0 && hist_last_line_added) + delete_last_history (); + last_hist = i - 1 - hist_last_line_added; if (list) @@ -497,7 +503,7 @@ fc_gethist (command, hlist) { int i; - if (!hlist) + if (hlist == 0) return ((char *)NULL); i = fc_gethnum (command, hlist); @@ -581,41 +587,18 @@ static void fc_replhist (command) char *command; { - register int i; - HIST_ENTRY **hlist, *histent, *discard; int n; if (command == 0 || *command == '\0') return; - hlist = history_list (); - - if (hlist == NULL) - return; - - for (i = 0; hlist[i]; i++); - i--; - - /* History_get () takes a parameter that should be - offset by history_base. */ - - histent = history_get (history_base + i); /* Don't free this */ - if (histent == NULL) - return; - n = strlen (command); - if (command[n - 1] == '\n') command[n - 1] = '\0'; if (command && *command) { - discard = remove_history (i); - if (discard) - { - FREE (discard->line); - free ((char *) discard); - } + delete_last_history (); maybe_add_history (command); /* Obeys HISTCONTROL setting. */ } } @@ -628,13 +611,16 @@ fc_addhist (line) { register int n; + if (line == 0 || *line == 0) + return; + n = strlen (line); if (line[n - 1] == '\n') line[n - 1] = '\0'; if (line && *line) - maybe_add_history (line); + maybe_add_history (line); /* Obeys HISTCONTROL setting. */ } #endif diff --git a/builtins/fc.def~ b/builtins/fc.def~ index 93c7ae3..57b5384 100644 --- a/builtins/fc.def~ +++ b/builtins/fc.def~ @@ -84,10 +84,12 @@ extern int errno; extern int echo_input_at_read; extern int current_command_line_count; extern int literal_history; +extern int posixly_correct; extern int unlink __P((const char *)); extern FILE *sh_mktmpfp __P((char *, int, char **)); +extern int delete_last_history __P((void)); /* **************************************************************** */ /* */ @@ -155,6 +157,7 @@ static void fc_addhist __P((char *)); /* String to execute on a file that we want to edit. */ #define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}" +#define POSIX_FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-ed}}" int fc_builtin (list) @@ -166,7 +169,7 @@ fc_builtin (list) int histbeg, histend, last_hist, retval, opt; FILE *stream; REPL *rlist, *rl; - char *ename, *command, *newcom; + char *ename, *command, *newcom, *fcedit; HIST_ENTRY **hlist; char *fn; @@ -284,6 +287,11 @@ fc_builtin (list) line was actually added (HISTIGNORE may have caused it to not be), so we check hist_last_line_added. */ + /* "When not listing, he fc command that caused the editing shall not be + entered into the history list." */ + if (listing == 0 && hist_last_line_added) + delete_last_history (); + last_hist = i - 1 - hist_last_line_added; if (list) @@ -302,7 +310,7 @@ fc_builtin (list) if (listing) { histend = last_hist; - histbeg = histend - 16; + histbeg = histend - 16 + 1; /* +1 because loop below uses >= */ if (histbeg < 0) histbeg = 0; } @@ -347,7 +355,12 @@ fc_builtin (list) if (numbering) fprintf (stream, "%d", i + history_base); if (listing) - fprintf (stream, "\t%c", histdata (i) ? '*' : ' '); + { + if (posixly_correct) + fputs ("\t", stream); + else + fprintf (stream, "\t%c", histdata (i) ? '*' : ' '); + } fprintf (stream, "%s\n", histline (i)); } @@ -364,7 +377,8 @@ fc_builtin (list) } else { - command = (char *)xmalloc (3 + strlen (FC_EDIT_COMMAND) + strlen (fn)); + fcedit = posixly_correct ? POSIX_FC_EDIT_COMMAND : FC_EDIT_COMMAND; + command = (char *)xmalloc (3 + strlen (fcedit) + strlen (fn)); sprintf (command, "%s %s", FC_EDIT_COMMAND, fn); } retval = parse_and_execute (command, "fc", SEVAL_NOHIST); @@ -489,7 +503,7 @@ fc_gethist (command, hlist) { int i; - if (!hlist) + if (hlist == 0) return ((char *)NULL); i = fc_gethnum (command, hlist); @@ -573,41 +587,18 @@ static void fc_replhist (command) char *command; { - register int i; - HIST_ENTRY **hlist, *histent, *discard; int n; if (command == 0 || *command == '\0') return; - hlist = history_list (); - - if (hlist == NULL) - return; - - for (i = 0; hlist[i]; i++); - i--; - - /* History_get () takes a parameter that should be - offset by history_base. */ - - histent = history_get (history_base + i); /* Don't free this */ - if (histent == NULL) - return; - n = strlen (command); - if (command[n - 1] == '\n') command[n - 1] = '\0'; if (command && *command) { - discard = remove_history (i); - if (discard) - { - FREE (discard->line); - free ((char *) discard); - } + delete_last_history (); maybe_add_history (command); /* Obeys HISTCONTROL setting. */ } } @@ -620,13 +611,16 @@ fc_addhist (line) { register int n; + if (line == 0 || *line == 0) + return; + n = strlen (line); if (line[n - 1] == '\n') line[n - 1] = '\0'; if (line && *line) - maybe_add_history (line); + maybe_add_history (line); /* Obeys HISTCONTROL setting. */ } #endif diff --git a/builtins/fg_bg.def b/builtins/fg_bg.def index c5e2e47..c14381b 100644 --- a/builtins/fg_bg.def +++ b/builtins/fg_bg.def @@ -82,8 +82,8 @@ fg_builtin (list) $BUILTIN bg $FUNCTION bg_builtin $DEPENDS_ON JOB_CONTROL -$SHORT_DOC bg [job_spec] -Place JOB_SPEC in the background, as if it had been started with +$SHORT_DOC bg [job_spec ...] +Place each JOB_SPEC in the background, as if it had been started with `&'. If JOB_SPEC is not present, the shell's notion of the current job is used. $END @@ -108,9 +108,11 @@ bg_builtin (list) /* This relies on the fact that fg_bg() takes a WORD_LIST *, but only acts on the first member (if any) of that list. */ + r = EXECUTION_SUCCESS; do { - r = fg_bg (list, 0); + if (fg_bg (list, 0) == EXECUTION_FAILURE) + r = EXECUTION_FAILURE; if (list) list = list->next; } @@ -160,7 +162,7 @@ fg_bg (list, foreground) { /* win: */ UNBLOCK_CHILD (oset); - return (status); + return (foreground ? status : EXECUTION_SUCCESS); } else { diff --git a/builtins/history.def b/builtins/history.def index 40708da..0086b0b 100644 --- a/builtins/history.def +++ b/builtins/history.def @@ -78,10 +78,11 @@ extern int errno; extern int current_command_line_count; +int delete_last_history __P((void)); + static char *histtime __P((HIST_ENTRY *, const char *)); static void display_history __P((WORD_LIST *)); static int delete_histent __P((int)); -static int delete_last_history __P((void)); static void push_history __P((WORD_LIST *)); static int expand_and_print_history __P((WORD_LIST *)); @@ -310,7 +311,7 @@ delete_histent (i) return 1; } -static int +int delete_last_history () { register int i; @@ -346,8 +347,6 @@ push_history (list) { char *s; -if (current_command_line_count == 0) - itrace("push_history: current_command_line_count == 0"); /* Delete the last history entry if it was a single entry added to the history list (generally the `history -s' itself), or if `history -s' is being used in a compound command and the compound command was diff --git a/builtins/kill.def b/builtins/kill.def index 6bcfad1..bedbb1a 100644 --- a/builtins/kill.def +++ b/builtins/kill.def @@ -170,7 +170,7 @@ kill_builtin (list) { pid = (pid_t) pid_value; - if ((pid < -1 ? kill_pid (-pid, sig, 1) : kill_pid (pid, sig, 0)) < 0) + if (kill_pid (pid, sig, pid < -1) < 0) { if (errno == EINVAL) sh_invalidsig (sigspec); diff --git a/builtins/type.def b/builtins/type.def index 4d91cd8..d03ccb2 100644 --- a/builtins/type.def +++ b/builtins/type.def @@ -372,6 +372,8 @@ describe_command (command, dflags) if (all == 0) break; } + else if (ABSPATH (full_path)) + ; /* placeholder; don't need to do anything yet */ else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY|CDESC_SHORTDESC)) { f = MP_DOCWD | ((dflags & CDESC_ABSPATH) ? MP_RMDOT : 0); diff --git a/doc/bash.1 b/doc/bash.1 index 4b7843d..3a5fa59 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -6,12 +6,12 @@ .\" Case Western Reserve University .\" chet@po.CWRU.Edu .\" -.\" Last Change: Fri Jul 15 23:15:01 EDT 2005 +.\" Last Change: Sat Aug 27 13:28:44 EDT 2005 .\" .\" bash_builtins, strip all but Built-Ins section .if \n(zZ=1 .ig zZ .if \n(zY=1 .ig zY -.TH BASH 1 "2005 Jul 15" "GNU Bash-3.1-devel" +.TH BASH 1 "2005 Aug 27" "GNU Bash-3.1-alpha1" .\" .\" There's some problem with having a `@' .\" in a tagged paragraph with the BSD man macros. @@ -4565,7 +4565,12 @@ file with a statement of the form Except where noted, readline variables can take the values .B On or -.BR Off . +.B Off +(without regard to case). +Unrecognized variable names are ignored. +When a variable value is read, empty or null values, "on" (case-insensitive), +and "1" are equivalent to \fBOn\fP. All other values are equivalent to +\fBOff\fP. The variables and their default values are: .PP .PD 0 @@ -5968,8 +5973,8 @@ If \fIjobspec\fP is not present, the shell's notion of the .B bg .I jobspec returns 0 unless run when job control is disabled or, when run with -job control enabled, if the last \fIjobspec\fP was not found or was -started without job control. +job control enabled, any specified \fIjobspec\fP was not found +or was started without job control. .TP \fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSV\fP] .PD 0 diff --git a/doc/bash.1~ b/doc/bash.1~ index fc1318b..ffe92b6 100644 --- a/doc/bash.1~ +++ b/doc/bash.1~ @@ -6,12 +6,12 @@ .\" Case Western Reserve University .\" chet@po.CWRU.Edu .\" -.\" Last Change: Fri Jul 15 23:15:01 EDT 2005 +.\" Last Change: Wed Aug 24 17:20:03 EDT 2005 .\" .\" bash_builtins, strip all but Built-Ins section .if \n(zZ=1 .ig zZ .if \n(zY=1 .ig zY -.TH BASH 1 "2005 Jul 15" "GNU Bash-3.1-devel" +.TH BASH 1 "2005 Aug 24" "GNU Bash-3.1-alpha1" .\" .\" There's some problem with having a `@' .\" in a tagged paragraph with the BSD man macros. @@ -4634,7 +4634,7 @@ arrow keys. If set to \fBon\fP, tilde expansion is performed when readline attempts word completion. .TP -.B history-preserve-point +.B history\-preserve\-point (Off) If set to \fBon\fP, the history code attempts to place point at the same location on each history line retrieved with \fBprevious-history\fP or \fBnext-history\fP. @@ -5968,8 +5968,8 @@ If \fIjobspec\fP is not present, the shell's notion of the .B bg .I jobspec returns 0 unless run when job control is disabled or, when run with -job control enabled, if the last \fIjobspec\fP was not found or was -started without job control. +job control enabled, any specified \fIjobspec\fP was not found +or was started without job control. .TP \fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSV\fP] .PD 0 diff --git a/doc/bashref.texi b/doc/bashref.texi index a0870b6..8abe4fe 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -6090,6 +6090,11 @@ but without a leading @samp{#!}, Bash sets @code{$0} to the full pathname of the script as found by searching @code{$PATH}, rather than the command as typed by the user. +@item +The @code{fc} builtin checks @code{$EDITOR} as a program to edit history lines +if @code{FCEDIT} is unset, rather than defaulting directly to @code{ed}. +@code{fc} uses @code{ed} if @code{EDITOR} is unset. + @end enumerate @node Job Control @@ -6219,8 +6224,8 @@ Resume each suspended job @var{jobspec} in the background, as if it had been started with @samp{&}. If @var{jobspec} is not supplied, the current job is used. The return status is zero unless it is run when job control is not -enabled, or, when run with job control enabled, if the last -@var{jobspec} was not found or the last @var{jobspec} specifies a job +enabled, or, when run with job control enabled, any +@var{jobspec} was not found or specifies a job that was started without job control. @item fg diff --git a/doc/bashref.texi~ b/doc/bashref.texi~ index 401bc66..224ccc6 100644 --- a/doc/bashref.texi~ +++ b/doc/bashref.texi~ @@ -4784,6 +4784,10 @@ prompt when the shell is interactive. Bash terminates after that number of seconds if input does not arrive. +@item TMPDIR +If set, Bash uses its value as the name of a directory in which +Bash creates temporary files for the shell's use. + @item UID The numeric real user id of the current user. This variable is readonly. @@ -6086,11 +6090,6 @@ but without a leading @samp{#!}, Bash sets @code{$0} to the full pathname of the script as found by searching @code{$PATH}, rather than the command as typed by the user. -@item -When using @samp{.} to source a shell script found in @code{$PATH}, bash -checks execute permission bits rather than read permission bits, just as -if it were searching for a command. - @end enumerate @node Job Control @@ -6220,8 +6219,8 @@ Resume each suspended job @var{jobspec} in the background, as if it had been started with @samp{&}. If @var{jobspec} is not supplied, the current job is used. The return status is zero unless it is run when job control is not -enabled, or, when run with job control enabled, if the last -@var{jobspec} was not found or the last @var{jobspec} specifies a job +enabled, or, when run with job control enabled, any +@var{jobspec} was not found or specifies a job that was started without job control. @item fg diff --git a/doc/version.texi b/doc/version.texi index 638db25..52d2c4b 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -2,9 +2,9 @@ Copyright (C) 1988-2005 Free Software Foundation, Inc. @end ignore -@set LASTCHANGE Fri Jul 15 23:14:38 EDT 2005 +@set LASTCHANGE Sat Aug 27 13:54:54 EDT 2005 -@set EDITION 3.1-devel -@set VERSION 3.1-devel -@set UPDATED 15 July 2005 -@set UPDATED-MONTH July 2005 +@set EDITION 3.1-alpha1 +@set VERSION 3.1-alpha1 +@set UPDATED 27 August 2005 +@set UPDATED-MONTH August 2005 diff --git a/doc/version.texi~ b/doc/version.texi~ index 292eee5..f53d193 100644 --- a/doc/version.texi~ +++ b/doc/version.texi~ @@ -2,9 +2,9 @@ Copyright (C) 1988-2005 Free Software Foundation, Inc. @end ignore -@set LASTCHANGE Thu Jun 23 09:48:04 EDT 2005 +@set LASTCHANGE Wed Aug 24 17:22:10 EDT 2005 -@set EDITION 3.1-devel -@set VERSION 3.1-devel -@set UPDATED 30 April 2005 -@set UPDATED-MONTH April 2005 +@set EDITION 3.1-alpha1 +@set VERSION 3.1-alpha1 +@set UPDATED 24 August 2005 +@set UPDATED-MONTH August 2005 diff --git a/execute_cmd.c b/execute_cmd.c index 63da5a9..d05981b 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -3780,6 +3780,7 @@ initialize_subshell () /* Forget about the way job control was working. We are in a subshell. */ without_job_control (); set_sigchld_handler (); + init_job_stats (); #endif /* JOB_CONTROL */ /* Reset the values of the shell flags and options. */ diff --git a/general.c b/general.c index d399f06..3384e84 100644 --- a/general.c +++ b/general.c @@ -506,6 +506,36 @@ file_iswdir (fn) return (file_isdir (fn) && test_eaccess (fn, W_OK) == 0); } +/* Return 1 if STRING contains an absolute pathname, else 0. Used by `cd' + to decide whether or not to look up a directory name in $CDPATH. */ +int +absolute_pathname (string) + const char *string; +{ + if (string == 0 || *string == '\0') + return (0); + + if (ABSPATH(string)) + return (1); + + if (string[0] == '.' && PATHSEP(string[1])) /* . and ./ */ + return (1); + + if (string[0] == '.' && string[1] == '.' && PATHSEP(string[2])) /* .. and ../ */ + return (1); + + return (0); +} + +/* Return 1 if STRING is an absolute program name; it is absolute if it + contains any slashes. This is used to decide whether or not to look + up through $PATH. */ +int +absolute_program (string) + const char *string; +{ + return ((char *)xstrchr (string, '/') != (char *)NULL); +} /* **************************************************************** */ /* */ @@ -540,37 +570,6 @@ make_absolute (string, dot_path) return (result); } -/* Return 1 if STRING contains an absolute pathname, else 0. Used by `cd' - to decide whether or not to look up a directory name in $CDPATH. */ -int -absolute_pathname (string) - const char *string; -{ - if (string == 0 || *string == '\0') - return (0); - - if (ABSPATH(string)) - return (1); - - if (string[0] == '.' && PATHSEP(string[1])) /* . and ./ */ - return (1); - - if (string[0] == '.' && string[1] == '.' && PATHSEP(string[2])) /* .. and ../ */ - return (1); - - return (0); -} - -/* Return 1 if STRING is an absolute program name; it is absolute if it - contains any slashes. This is used to decide whether or not to look - up through $PATH. */ -int -absolute_program (string) - const char *string; -{ - return ((char *)xstrchr (string, '/') != (char *)NULL); -} - /* Return the `basename' of the pathname in STRING (the stuff after the last '/'). If STRING is `/', just return it. */ char * diff --git a/general.c~ b/general.c~ index 7b97ea9..d399f06 100644 --- a/general.c~ +++ b/general.c~ @@ -289,7 +289,7 @@ assignment (string, flags) if (string[newi++] != ']') return (0); if (string[newi] == '+' && string[newi+1] == '=') - return (flags ? 0 : (newi + 1)); + return (newi + 1); return ((string[newi] == '=') ? newi : 0); } #endif /* ARRAY_VARS */ diff --git a/general.h b/general.h index 9e73e62..e1d01f5 100644 --- a/general.h +++ b/general.h @@ -299,10 +299,10 @@ extern int same_file __P((char *, char *, struct stat *, struct stat *)); extern int file_isdir __P((char *)); extern int file_iswdir __P((char *)); - -extern char *make_absolute __P((char *, char *)); extern int absolute_pathname __P((const char *)); extern int absolute_program __P((const char *)); + +extern char *make_absolute __P((char *, char *)); extern char *base_pathname __P((char *)); extern char *full_pathname __P((char *)); extern char *polite_directory_format __P((char *)); diff --git a/general.h~ b/general.h~ index 97e4293..9e73e62 100644 --- a/general.h~ +++ b/general.h~ @@ -24,6 +24,7 @@ #include "stdc.h" #include "bashtypes.h" +#include "chartypes.h" #if defined (HAVE_SYS_RESOURCE_H) && defined (RLIMTYPE) # if defined (HAVE_SYS_TIME_H) @@ -231,6 +232,7 @@ typedef int sh_builtin_func_t __P((WORD_LIST *)); /* sh_wlist_func_t */ #define FS_EXEC_ONLY 0x8 #define FS_DIRECTORY 0x10 #define FS_NODIRS 0x20 +#define FS_READABLE 0x40 /* Default maximum for move_to_high_fd */ #define HIGH_FD_MAX 256 @@ -249,14 +251,18 @@ typedef int QSFUNC (); # define ABSPATH(x) ((x)[0] == '/') # define RELPATH(x) ((x)[0] != '/') #else /* __CYGWIN__ */ -# define ABSPATH(x) (((x)[0] && ISALPHA((unsigned char)(x)[0]) && (x)[1] == ':' && (x)[2] == '/') || (x)[0] == '/') -# define RELPATH(x) (!(x)[0] || ((x)[1] != ':' && (x)[0] != '/')) +# define ABSPATH(x) (((x)[0] && ISALPHA((unsigned char)(x)[0]) && (x)[1] == ':') || ISDIRSEP((x)[0])) +# define RELPATH(x) (ABSPATH(x) == 0) #endif /* __CYGWIN__ */ #define ROOTEDPATH(x) (ABSPATH(x)) #define DIRSEP '/' -#define ISDIRSEP(c) ((c) == '/') +#if !defined (__CYGWIN__) +# define ISDIRSEP(c) ((c) == '/') +#else +# define ISDIRSEP(c) ((c) == '/' || (c) == '\\') +#endif /* __CYGWIN__ */ #define PATHSEP(c) (ISDIRSEP(c) || (c) == 0) #if 0 diff --git a/jobs.c b/jobs.c index 5e8b53d..5a70b5f 100644 --- a/jobs.c +++ b/jobs.c @@ -160,6 +160,7 @@ extern procenv_t wait_intr_buf; extern int wait_signal_received; extern WORD_LIST *subst_assign_varlist; +static struct jobstats zerojs = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB, 0, 0 }; struct jobstats js = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB, 0, 0 }; struct bgpids bgpids = { 0, 0, 0 }; @@ -349,6 +350,13 @@ tcgetpgrp (fd) #endif /* !_POSIX_VERSION */ +/* Initialize the global job stats structure. */ +void +init_job_stats () +{ + js = zerojs; +} + /* Return the working directory for the current process. Unlike job_working_directory, this does not call malloc (), nor do any of the functions it calls. This is so that it can safely be called @@ -2639,7 +2647,7 @@ start_job (job, foreground) register PROCESS *p; int already_running; sigset_t set, oset; - char *wd; + char *wd, *s; static TTYSTRUCT save_stty; BLOCK_CHILD (set, oset); @@ -2657,7 +2665,7 @@ start_job (job, foreground) { internal_error (_("%s: job %d already in background"), this_command_name, job + 1); UNBLOCK_CHILD (oset); - return (-1); + return (0); /* XPG6/SUSv3 says this is not an error */ } wd = current_working_directory (); @@ -2675,8 +2683,15 @@ start_job (job, foreground) p = jobs[job]->pipe; if (foreground == 0) - printf ("[%d]%c ", job + 1, - (job == js.j_current) ? '+': ((job == js.j_previous) ? '-' : ' ')); + { + /* POSIX.2 says `bg' doesn't give any indication about current or + previous job. */ + if (posixly_correct == 0) + s = (job == js.j_current) ? "+ ": ((job == js.j_previous) ? "- " : " "); + else + s = " "; + printf ("[%d]%s", job + 1, s); + } do { @@ -2748,9 +2763,17 @@ kill_pid (pid, sig, group) int sig, group; { register PROCESS *p; - int job, result; + int job, result, negative; sigset_t set, oset; + if (pid < -1) + { + pid = -pid; + group = negative = 1; + } + else + negative = 0; + result = EXECUTION_SUCCESS; if (group) { @@ -2762,8 +2785,26 @@ kill_pid (pid, sig, group) jobs[job]->flags &= ~J_NOTIFIED; /* Kill process in backquotes or one started without job control? */ - if (jobs[job]->pgrp == shell_pgrp) + + /* If we're passed a pid < -1, just call killpg and see what happens */ + if (negative && jobs[job]->pgrp == shell_pgrp) result = killpg (pid, sig); + /* If we're killing using job control notification, for example, + without job control active, we have to do things ourselves. */ + else if (jobs[job]->pgrp == shell_pgrp) + { + p = jobs[job]->pipe; + do + { + if (PALIVE (p) == 0) + continue; /* avoid pid recycling problem */ + kill (p->pid, sig); + if (PEXITED (p) && (sig == SIGTERM || sig == SIGHUP)) + kill (p->pid, SIGCONT); + p = p->next; + } + while (p != jobs[job]->pipe); + } else { result = killpg (jobs[job]->pgrp, sig); diff --git a/jobs.h b/jobs.h index ee1bd38..72ae227 100644 --- a/jobs.h +++ b/jobs.h @@ -230,6 +230,8 @@ extern void set_sigchld_handler __P((void)); extern void ignore_tty_job_signals __P((void)); extern void default_tty_job_signals __P((void)); +extern void init_job_stats __P((void)); + #if defined (JOB_CONTROL) extern int job_control; #endif diff --git a/lib/readline/bind.c b/lib/readline/bind.c index e752753..8db8209 100644 --- a/lib/readline/bind.c +++ b/lib/readline/bind.c @@ -1192,9 +1192,9 @@ rl_parse_and_bind (string) /* If this is a command to set a variable, then do that. */ if (_rl_stricmp (string, "set") == 0) { - char *var = string + i; - char *value; + char *var, *value, *e; + var = string + i; /* Make VAR point to start of variable name. */ while (*var && whitespace (*var)) var++; @@ -1205,6 +1205,14 @@ rl_parse_and_bind (string) *value++ = '\0'; while (*value && whitespace (*value)) value++; + /* remove trailing whitespace */ + e = value + strlen (value) - 1; + while (e >= value && whitespace (*e)) + e--; + e++; /* skip back to whitespace or EOS */ + if (*e && e >= value) + *e = '\0'; + rl_variable_bind (var, value); return 0; } @@ -1225,8 +1233,9 @@ rl_parse_and_bind (string) the quoted string delimiter, like the shell. */ if (*funname == '\'' || *funname == '"') { - int delimiter = string[i++], passc; + int delimiter, passc; + delimiter = string[i++]; for (passc = 0; c = string[i]; i++) { if (passc) diff --git a/lib/readline/bind.c~ b/lib/readline/bind.c~ index 8c88240..b57be1f 100644 --- a/lib/readline/bind.c~ +++ b/lib/readline/bind.c~ @@ -369,7 +369,7 @@ rl_generic_bind (type, keyseq, data, map) if (ic < 0 || ic >= KEYMAP_SIZE) return -1; - if (_rl_convert_meta_chars_to_ascii && META_CHAR (ic)) + if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii) { ic = UNMETA (ic); if (map[ESC].type == ISKMAP) @@ -460,7 +460,14 @@ rl_translate_keyseq (seq, array, len) else if (c == 'M') { i++; - array[l++] = ESC; /* ESC is meta-prefix */ + /* XXX - should obey convert-meta setting? */ + if (_rl_convert_meta_chars_to_ascii && _rl_keymap[ESC].type == ISKMAP) + array[l++] = ESC; /* ESC is meta-prefix */ + else + { + i++; + array[l++] = META (seq[i]); + } } else if (c == 'C') { @@ -1185,9 +1192,9 @@ rl_parse_and_bind (string) /* If this is a command to set a variable, then do that. */ if (_rl_stricmp (string, "set") == 0) { - char *var = string + i; - char *value; + char *var, *value, *e; + var = string + i; /* Make VAR point to start of variable name. */ while (*var && whitespace (*var)) var++; @@ -1198,6 +1205,13 @@ rl_parse_and_bind (string) *value++ = '\0'; while (*value && whitespace (*value)) value++; + /* remove trailing whitespace */ + e = value + strlen (value) - 1; + while (e >= value && whitespace (*e)) + e--; + if (*e && e >= value) + *e = '\0'; + rl_variable_bind (var, value); return 0; } @@ -1218,8 +1232,9 @@ rl_parse_and_bind (string) the quoted string delimiter, like the shell. */ if (*funname == '\'' || *funname == '"') { - int delimiter = string[i++], passc; + int delimiter, passc; + delimiter = string[i++]; for (passc = 0; c = string[i]; i++) { if (passc) @@ -1469,7 +1484,7 @@ find_string_var (name) values result in 0 (false). */ static int bool_to_int (value) - char *value; + const char *value; { return (value == 0 || *value == '\0' || (_rl_stricmp (value, "on") == 0) || diff --git a/lib/readline/doc/readline.3 b/lib/readline/doc/readline.3 index e86922d..a719b2a 100644 --- a/lib/readline/doc/readline.3 +++ b/lib/readline/doc/readline.3 @@ -6,9 +6,9 @@ .\" Case Western Reserve University .\" chet@ins.CWRU.Edu .\" -.\" Last Change: Mon Nov 22 11:10:14 EST 2004 +.\" Last Change: Sat Aug 27 13:29:08 EDT 2005 .\" -.TH READLINE 3 "2004 Nov 22" "GNU Readline 5.1-devel" +.TH READLINE 3 "2005 Aug 27" "GNU Readline 5.1-alpha1" .\" .\" File Name macro. This used to be `.PN', for Path Name, .\" but Sun doesn't seem to like that very much. @@ -328,6 +328,10 @@ Except where noted, readline variables can take the values or .B Off (without regard to case). +Unrecognized variable names are ignored. +When a variable value is read, empty or null values, "on" (case-insensitive), +and "1" are equivalent to \fBOn\fP. All other values are equivalent to +\fBOff\fP. The variables and their default values are: .PP .PD 0 diff --git a/lib/readline/doc/readline.3~ b/lib/readline/doc/readline.3~ index 3bdf6e1..e86922d 100644 --- a/lib/readline/doc/readline.3~ +++ b/lib/readline/doc/readline.3~ @@ -396,9 +396,9 @@ arrow keys. If set to \fBon\fP, tilde expansion is performed when readline attempts word completion. .TP -.B history-preserve-point +.B history\-preserve\-point (Off) If set to \fBon\fP, the history code attempts to place point at the -same location on each history line retrived with \fBprevious-history\fP +same location on each history line retrieved with \fBprevious-history\fP or \fBnext-history\fP. .TP .B horizontal\-scroll\-mode (Off) diff --git a/lib/readline/doc/rluser.texi b/lib/readline/doc/rluser.texi index 8f0459b..1444f85 100644 --- a/lib/readline/doc/rluser.texi +++ b/lib/readline/doc/rluser.texi @@ -383,7 +383,11 @@ set editing-mode vi @end example Variable names and values, where appropriate, are recognized without regard -to case. +to case. Unrecognized variable names are ignored. + +Boolean variables (those that can be set to on or off) are set to on if +the value is null or empty, @var{on} (case-insensitive), or 1. Any other +value results in the variable being set to off. @ifset BashFeatures The @w{@code{bind -V}} command lists the current Readline variable names diff --git a/lib/readline/doc/rluser.texi~ b/lib/readline/doc/rluser.texi~ index bffb0c8..8f0459b 100644 --- a/lib/readline/doc/rluser.texi~ +++ b/lib/readline/doc/rluser.texi~ @@ -10,7 +10,7 @@ use these features. There is a document entitled "readline.texinfo" which contains both end-user and programmer documentation for the GNU Readline Library. -Copyright (C) 1988-2004 Free Software Foundation, Inc. +Copyright (C) 1988-2005 Free Software Foundation, Inc. Authored by Brian Fox and Chet Ramey. diff --git a/lib/readline/doc/version.texi b/lib/readline/doc/version.texi index cd41234..7afafd7 100644 --- a/lib/readline/doc/version.texi +++ b/lib/readline/doc/version.texi @@ -4,7 +4,7 @@ Copyright (C) 1988-2005 Free Software Foundation, Inc. @set EDITION 5.1-devel @set VERSION 5.1-devel -@set UPDATED 4 January 2005 -@set UPDATED-MONTH January 2005 +@set UPDATED 27 August 2005 +@set UPDATED-MONTH August 2005 -@set LASTCHANGE Tue Jan 4 17:26:58 EST 2005 +@set LASTCHANGE Sat Aug 27 13:28:14 EDT 2005 diff --git a/lib/readline/doc/version.texi~ b/lib/readline/doc/version.texi~ index 69ff2ae..cd41234 100644 --- a/lib/readline/doc/version.texi~ +++ b/lib/readline/doc/version.texi~ @@ -1,10 +1,10 @@ @ignore -Copyright (C) 1988-2004 Free Software Foundation, Inc. +Copyright (C) 1988-2005 Free Software Foundation, Inc. @end ignore @set EDITION 5.1-devel @set VERSION 5.1-devel -@set UPDATED 15 October 2004 -@set UPDATED-MONTH October 2004 +@set UPDATED 4 January 2005 +@set UPDATED-MONTH January 2005 -@set LASTCHANGE Fri Oct 15 14:52:31 EDT 2004 +@set LASTCHANGE Tue Jan 4 17:26:58 EST 2005 diff --git a/lib/readline/history.c b/lib/readline/history.c index 3da5748..a538f91 100644 --- a/lib/readline/history.c +++ b/lib/readline/history.c @@ -204,7 +204,7 @@ history_get (offset) int local_index; local_index = offset - history_base; - return (local_index >= history_length || local_index < 0 || !the_history) + return (local_index >= history_length || local_index < 0 || the_history == 0) ? (HIST_ENTRY *)NULL : the_history[local_index]; } @@ -364,7 +364,7 @@ remove_history (which) HIST_ENTRY *return_value; register int i; - if (which < 0 || which >= history_length || history_length == 0) + if (which < 0 || which >= history_length || history_length == 0 || the_history == 0) return ((HIST_ENTRY *)NULL); return_value = the_history[which]; diff --git a/lib/readline/isearch.c b/lib/readline/isearch.c index 88b3985..31aa0a4 100644 --- a/lib/readline/isearch.c +++ b/lib/readline/isearch.c @@ -101,6 +101,8 @@ _rl_scxt_alloc (type, flags) cxt->last_found_line = cxt->save_line; cxt->prev_line_found = 0; + cxt->save_undo_list = 0; + cxt->history_pos = 0; cxt->direction = 0; diff --git a/lib/readline/isearch.c~ b/lib/readline/isearch.c~ new file mode 100644 index 0000000..88b3985 --- /dev/null +++ b/lib/readline/isearch.c~ @@ -0,0 +1,656 @@ +/* **************************************************************** */ +/* */ +/* I-Search and Searching */ +/* */ +/* **************************************************************** */ + +/* Copyright (C) 1987-2005 Free Software Foundation, Inc. + + This file contains the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include + +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif + +#include "rldefs.h" +#include "rlmbutil.h" + +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +/* Variables exported to other files in the readline library. */ +char *_rl_isearch_terminators = (char *)NULL; + +_rl_search_cxt *_rl_iscxt = 0; + +/* Variables imported from other files in the readline library. */ +extern HIST_ENTRY *_rl_saved_line_for_history; + +static int rl_search_history PARAMS((int, int)); + +static _rl_search_cxt *_rl_isearch_init PARAMS((int)); +static void _rl_isearch_fini PARAMS((_rl_search_cxt *)); +static int _rl_isearch_cleanup PARAMS((_rl_search_cxt *, int)); + +/* Last line found by the current incremental search, so we don't `find' + identical lines many times in a row. */ +static char *prev_line_found; + +/* Last search string and its length. */ +static char *last_isearch_string; +static int last_isearch_string_len; + +static char *default_isearch_terminators = "\033\012"; + +_rl_search_cxt * +_rl_scxt_alloc (type, flags) + int type, flags; +{ + _rl_search_cxt *cxt; + + cxt = (_rl_search_cxt *)xmalloc (sizeof (_rl_search_cxt)); + + cxt->type = type; + cxt->sflags = flags; + + cxt->search_string = 0; + cxt->search_string_size = cxt->search_string_index = 0; + + cxt->lines = 0; + cxt->allocated_line = 0; + cxt->hlen = cxt->hindex = 0; + + cxt->save_point = rl_point; + cxt->save_mark = rl_mark; + cxt->save_line = where_history (); + cxt->last_found_line = cxt->save_line; + cxt->prev_line_found = 0; + + cxt->history_pos = 0; + cxt->direction = 0; + + cxt->lastc = 0; + + cxt->sline = 0; + cxt->sline_len = cxt->sline_index = 0; + + cxt->search_terminators = 0; + + return cxt; +} + +void +_rl_scxt_dispose (cxt, flags) + _rl_search_cxt *cxt; + int flags; +{ + FREE (cxt->search_string); + FREE (cxt->allocated_line); + FREE (cxt->lines); + + free (cxt); +} + +/* Search backwards through the history looking for a string which is typed + interactively. Start with the current line. */ +int +rl_reverse_search_history (sign, key) + int sign, key; +{ + return (rl_search_history (-sign, key)); +} + +/* Search forwards through the history looking for a string which is typed + interactively. Start with the current line. */ +int +rl_forward_search_history (sign, key) + int sign, key; +{ + return (rl_search_history (sign, key)); +} + +/* Display the current state of the search in the echo-area. + SEARCH_STRING contains the string that is being searched for, + DIRECTION is zero for forward, or 1 for reverse, + WHERE is the history list number of the current line. If it is + -1, then this line is the starting one. */ +static void +rl_display_search (search_string, reverse_p, where) + char *search_string; + int reverse_p, where; +{ + char *message; + int msglen, searchlen; + + searchlen = (search_string && *search_string) ? strlen (search_string) : 0; + + message = (char *)xmalloc (searchlen + 33); + msglen = 0; + +#if defined (NOTDEF) + if (where != -1) + { + sprintf (message, "[%d]", where + history_base); + msglen = strlen (message); + } +#endif /* NOTDEF */ + + message[msglen++] = '('; + + if (reverse_p) + { + strcpy (message + msglen, "reverse-"); + msglen += 8; + } + + strcpy (message + msglen, "i-search)`"); + msglen += 10; + + if (search_string) + { + strcpy (message + msglen, search_string); + msglen += searchlen; + } + + strcpy (message + msglen, "': "); + + rl_message ("%s", message); + free (message); + (*rl_redisplay_function) (); +} + +static _rl_search_cxt * +_rl_isearch_init (direction) + int direction; +{ + _rl_search_cxt *cxt; + register int i; + HIST_ENTRY **hlist; + + cxt = _rl_scxt_alloc (RL_SEARCH_ISEARCH, 0); + if (direction < 0) + cxt->sflags |= SF_REVERSE; + + cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators + : default_isearch_terminators; + + /* Create an arrary of pointers to the lines that we want to search. */ + hlist = history_list (); + rl_maybe_replace_line (); + i = 0; + if (hlist) + for (i = 0; hlist[i]; i++); + + /* Allocate space for this many lines, +1 for the current input line, + and remember those lines. */ + cxt->lines = (char **)xmalloc ((1 + (cxt->hlen = i)) * sizeof (char *)); + for (i = 0; i < cxt->hlen; i++) + cxt->lines[i] = hlist[i]->line; + + if (_rl_saved_line_for_history) + cxt->lines[i] = _rl_saved_line_for_history->line; + else + { + /* Keep track of this so we can free it. */ + cxt->allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer)); + strcpy (cxt->allocated_line, &rl_line_buffer[0]); + cxt->lines[i] = cxt->allocated_line; + } + + cxt->hlen++; + + /* The line where we start the search. */ + cxt->history_pos = cxt->save_line; + + rl_save_prompt (); + + /* Initialize search parameters. */ + cxt->search_string = (char *)xmalloc (cxt->search_string_size = 128); + cxt->search_string[cxt->search_string_index = 0] = '\0'; + + /* Normalize DIRECTION into 1 or -1. */ + cxt->direction = (direction >= 0) ? 1 : -1; + + cxt->sline = rl_line_buffer; + cxt->sline_len = strlen (cxt->sline); + cxt->sline_index = rl_point; + + _rl_iscxt = cxt; /* save globally */ + + return cxt; +} + +static void +_rl_isearch_fini (cxt) + _rl_search_cxt *cxt; +{ + /* First put back the original state. */ + strcpy (rl_line_buffer, cxt->lines[cxt->save_line]); + + rl_restore_prompt (); + + /* Save the search string for possible later use. */ + FREE (last_isearch_string); + last_isearch_string = cxt->search_string; + last_isearch_string_len = cxt->search_string_index; + cxt->search_string = 0; + + if (cxt->last_found_line < cxt->save_line) + rl_get_previous_history (cxt->save_line - cxt->last_found_line, 0); + else + rl_get_next_history (cxt->last_found_line - cxt->save_line, 0); + + /* If the string was not found, put point at the end of the last matching + line. If last_found_line == orig_line, we didn't find any matching + history lines at all, so put point back in its original position. */ + if (cxt->sline_index < 0) + { + if (cxt->last_found_line == cxt->save_line) + cxt->sline_index = cxt->save_point; + else + cxt->sline_index = strlen (rl_line_buffer); + rl_mark = cxt->save_mark; + } + + rl_point = cxt->sline_index; + /* Don't worry about where to put the mark here; rl_get_previous_history + and rl_get_next_history take care of it. */ + + rl_clear_message (); +} + +int +_rl_search_getchar (cxt) + _rl_search_cxt *cxt; +{ + int c; + + /* Read a key and decide how to proceed. */ + RL_SETSTATE(RL_STATE_MOREINPUT); + c = cxt->lastc = rl_read_key (); + RL_UNSETSTATE(RL_STATE_MOREINPUT); + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX); +#endif + + return c; +} + +/* Process just-read character C according to isearch context CXT. Return + -1 if the caller should just free the context and return, 0 if we should + break out of the loop, and 1 if we should continue to read characters. */ +int +_rl_isearch_dispatch (cxt, c) + _rl_search_cxt *cxt; + int c; +{ + int n, wstart, wlen, limit; + rl_command_func_t *f; + + f = (rl_command_func_t *)NULL; + + /* Translate the keys we do something with to opcodes. */ + if (c >= 0 && _rl_keymap[c].type == ISFUNC) + { + f = _rl_keymap[c].function; + + if (f == rl_reverse_search_history) + cxt->lastc = (cxt->sflags & SF_REVERSE) ? -1 : -2; + else if (f == rl_forward_search_history) + cxt->lastc = (cxt->sflags & SF_REVERSE) ? -2 : -1; + else if (f == rl_rubout) + cxt->lastc = -3; + else if (c == CTRL ('G')) + cxt->lastc = -4; + else if (c == CTRL ('W')) /* XXX */ + cxt->lastc = -5; + else if (c == CTRL ('Y')) /* XXX */ + cxt->lastc = -6; + } + + /* The characters in isearch_terminators (set from the user-settable + variable isearch-terminators) are used to terminate the search but + not subsequently execute the character as a command. The default + value is "\033\012" (ESC and C-J). */ + if (strchr (cxt->search_terminators, cxt->lastc)) + { + /* ESC still terminates the search, but if there is pending + input or if input arrives within 0.1 seconds (on systems + with select(2)) it is used as a prefix character + with rl_execute_next. WATCH OUT FOR THIS! This is intended + to allow the arrow keys to be used like ^F and ^B are used + to terminate the search and execute the movement command. + XXX - since _rl_input_available depends on the application- + settable keyboard timeout value, this could alternatively + use _rl_input_queued(100000) */ + if (cxt->lastc == ESC && _rl_input_available ()) + rl_execute_next (ESC); + return (0); + } + +#define ENDSRCH_CHAR(c) \ + ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G'))) + +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + if (cxt->lastc >= 0 && (cxt->mb[0] && cxt->mb[1] == '\0') && ENDSRCH_CHAR (cxt->lastc)) + { + /* This sets rl_pending_input to c; it will be picked up the next + time rl_read_key is called. */ + rl_execute_next (cxt->lastc); + return (0); + } + } + else +#endif + if (cxt->lastc >= 0 && ENDSRCH_CHAR (cxt->lastc)) + { + /* This sets rl_pending_input to LASTC; it will be picked up the next + time rl_read_key is called. */ + rl_execute_next (cxt->lastc); + return (0); + } + + /* Now dispatch on the character. `Opcodes' affect the search string or + state. Other characters are added to the string. */ + switch (cxt->lastc) + { + /* search again */ + case -1: + if (cxt->search_string_index == 0) + { + if (last_isearch_string) + { + cxt->search_string_size = 64 + last_isearch_string_len; + cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); + strcpy (cxt->search_string, last_isearch_string); + cxt->search_string_index = last_isearch_string_len; + rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1); + break; + } + return (1); + } + else if (cxt->sflags & SF_REVERSE) + cxt->sline_index--; + else if (cxt->sline_index != cxt->sline_len) + cxt->sline_index++; + else + rl_ding (); + break; + + /* switch directions */ + case -2: + cxt->direction = -cxt->direction; + if (cxt->direction < 0) + cxt->sflags |= SF_REVERSE; + break; + + /* delete character from search string. */ + case -3: /* C-H, DEL */ + /* This is tricky. To do this right, we need to keep a + stack of search positions for the current search, with + sentinels marking the beginning and end. But this will + do until we have a real isearch-undo. */ + if (cxt->search_string_index == 0) + rl_ding (); + else + cxt->search_string[--cxt->search_string_index] = '\0'; + break; + + case -4: /* C-G, abort */ + rl_replace_line (cxt->lines[cxt->save_line], 0); + rl_point = cxt->save_point; + rl_mark = cxt->save_mark; + rl_restore_prompt(); + rl_clear_message (); + + return -1; + + case -5: /* C-W */ + /* skip over portion of line we already matched and yank word */ + wstart = rl_point + cxt->search_string_index; + if (wstart >= rl_end) + { + rl_ding (); + break; + } + + /* if not in a word, move to one. */ + if (rl_alphabetic(rl_line_buffer[wstart]) == 0) + { + rl_ding (); + break; + } + n = wstart; + while (n < rl_end && rl_alphabetic(rl_line_buffer[n])) + n++; + wlen = n - wstart + 1; + if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size) + { + cxt->search_string_size += wlen + 1; + cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); + } + for (; wstart < n; wstart++) + cxt->search_string[cxt->search_string_index++] = rl_line_buffer[wstart]; + cxt->search_string[cxt->search_string_index] = '\0'; + break; + + case -6: /* C-Y */ + /* skip over portion of line we already matched and yank rest */ + wstart = rl_point + cxt->search_string_index; + if (wstart >= rl_end) + { + rl_ding (); + break; + } + n = rl_end - wstart + 1; + if (cxt->search_string_index + n + 1 >= cxt->search_string_size) + { + cxt->search_string_size += n + 1; + cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); + } + for (n = wstart; n < rl_end; n++) + cxt->search_string[cxt->search_string_index++] = rl_line_buffer[n]; + cxt->search_string[cxt->search_string_index] = '\0'; + break; + + /* Add character to search string and continue search. */ + default: + if (cxt->search_string_index + 2 >= cxt->search_string_size) + { + cxt->search_string_size += 128; + cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size); + } +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + { + int j, l; + for (j = 0, l = strlen (cxt->mb); j < l; ) + cxt->search_string[cxt->search_string_index++] = cxt->mb[j++]; + } + else +#endif + cxt->search_string[cxt->search_string_index++] = c; + cxt->search_string[cxt->search_string_index] = '\0'; + break; + } + + for (cxt->sflags &= ~(SF_FOUND|SF_FAILED);; ) + { + limit = cxt->sline_len - cxt->search_string_index + 1; + + /* Search the current line. */ + while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit)) + { + if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index)) + { + cxt->sflags |= SF_FOUND; + break; + } + else + cxt->sline_index += cxt->direction; + } + if (cxt->sflags & SF_FOUND) + break; + + /* Move to the next line, but skip new copies of the line + we just found and lines shorter than the string we're + searching for. */ + do + { + /* Move to the next line. */ + cxt->history_pos += cxt->direction; + + /* At limit for direction? */ + if ((cxt->sflags & SF_REVERSE) ? (cxt->history_pos < 0) : (cxt->history_pos == cxt->hlen)) + { + cxt->sflags |= SF_FAILED; + break; + } + + /* We will need these later. */ + cxt->sline = cxt->lines[cxt->history_pos]; + cxt->sline_len = strlen (cxt->sline); + } + while ((cxt->prev_line_found && STREQ (cxt->prev_line_found, cxt->lines[cxt->history_pos])) || + (cxt->search_string_index > cxt->sline_len)); + + if (cxt->sflags & SF_FAILED) + break; + + /* Now set up the line for searching... */ + cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0; + } + + if (cxt->sflags & SF_FAILED) + { + /* We cannot find the search string. Ding the bell. */ + rl_ding (); + cxt->history_pos = cxt->last_found_line; + return 1; + } + + /* We have found the search string. Just display it. But don't + actually move there in the history list until the user accepts + the location. */ + if (cxt->sflags & SF_FOUND) + { + cxt->prev_line_found = cxt->lines[cxt->history_pos]; + rl_replace_line (cxt->lines[cxt->history_pos], 0); + rl_point = cxt->sline_index; + cxt->last_found_line = cxt->history_pos; + rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos); + } + + return 1; +} + +static int +_rl_isearch_cleanup (cxt, r) + _rl_search_cxt *cxt; + int r; +{ + if (r >= 0) + _rl_isearch_fini (cxt); + _rl_scxt_dispose (cxt, 0); + _rl_iscxt = 0; + + RL_UNSETSTATE(RL_STATE_ISEARCH); + + return (r != 0); +} + +/* Search through the history looking for an interactively typed string. + This is analogous to i-search. We start the search in the current line. + DIRECTION is which direction to search; >= 0 means forward, < 0 means + backwards. */ +static int +rl_search_history (direction, invoking_key) + int direction, invoking_key; +{ + _rl_search_cxt *cxt; /* local for now, but saved globally */ + int c, r; + + RL_SETSTATE(RL_STATE_ISEARCH); + cxt = _rl_isearch_init (direction); + + rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1); + + /* If we are using the callback interface, all we do is set up here and + return. The key is that we leave RL_STATE_ISEARCH set. */ + if (RL_ISSTATE (RL_STATE_CALLBACK)) + return (0); + + r = -1; + for (;;) + { + c = _rl_search_getchar (cxt); + /* We might want to handle EOF here (c == 0) */ + r = _rl_isearch_dispatch (cxt, cxt->lastc); + if (r <= 0) + break; + } + + /* The searching is over. The user may have found the string that she + was looking for, or else she may have exited a failing search. If + LINE_INDEX is -1, then that shows that the string searched for was + not found. We use this to determine where to place rl_point. */ + return (_rl_isearch_cleanup (cxt, r)); +} + +#if defined (READLINE_CALLBACKS) +/* Called from the callback functions when we are ready to read a key. The + callback functions know to call this because RL_ISSTATE(RL_STATE_ISEARCH). + If _rl_isearch_dispatch finishes searching, this function is responsible + for turning off RL_STATE_ISEARCH, which it does using _rl_isearch_cleanup. */ +int +_rl_isearch_callback (cxt) + _rl_search_cxt *cxt; +{ + int c, r; + + c = _rl_search_getchar (cxt); + /* We might want to handle EOF here */ + r = _rl_isearch_dispatch (cxt, cxt->lastc); + + return (r <= 0) ? _rl_isearch_cleanup (cxt, r) : 0; +} +#endif diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h index efc954c..1c216ea 100644 --- a/lib/readline/rlprivate.h +++ b/lib/readline/rlprivate.h @@ -63,6 +63,8 @@ typedef struct __rl_search_context int last_found_line; char *prev_line_found; + UNDO_LIST *save_undo_list; + int history_pos; int direction; diff --git a/lib/readline/rlprivate.h~ b/lib/readline/rlprivate.h~ new file mode 100644 index 0000000..efc954c --- /dev/null +++ b/lib/readline/rlprivate.h~ @@ -0,0 +1,418 @@ +/* rlprivate.h -- functions and variables global to the readline library, + but not intended for use by applications. */ + +/* Copyright (C) 1999-2005 Free Software Foundation, Inc. + + This file is part of the GNU Readline Library, a library for + reading lines of text with interactive input and history editing. + + The GNU Readline Library is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2, or + (at your option) any later version. + + The GNU Readline Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#if !defined (_RL_PRIVATE_H_) +#define _RL_PRIVATE_H_ + +#include "rlconf.h" /* for VISIBLE_STATS */ +#include "rlstdc.h" +#include "posixjmp.h" /* defines procenv_t */ + +/************************************************************************* + * * + * Global structs undocumented in texinfo manual and not in readline.h * + * * + *************************************************************************/ +/* search types */ +#define RL_SEARCH_ISEARCH 0x01 /* incremental search */ +#define RL_SEARCH_NSEARCH 0x02 /* non-incremental search */ +#define RL_SEARCH_CSEARCH 0x04 /* intra-line char search */ + +/* search flags */ +#define SF_REVERSE 0x01 +#define SF_FOUND 0x02 +#define SF_FAILED 0x04 + +typedef struct __rl_search_context +{ + int type; + int sflags; + + char *search_string; + int search_string_index; + int search_string_size; + + char **lines; + char *allocated_line; + int hlen; + int hindex; + + int save_point; + int save_mark; + int save_line; + int last_found_line; + char *prev_line_found; + + int history_pos; + int direction; + + int lastc; +#if defined (HANDLE_MULTIBYTE) + char mb[MB_LEN_MAX]; +#endif + + char *sline; + int sline_len; + int sline_index; + + char *search_terminators; +} _rl_search_cxt; + +/* Callback data for reading numeric arguments */ +#define NUM_SAWMINUS 0x01 +#define NUM_SAWDIGITS 0x02 +#define NUM_READONE 0x04 + +typedef int _rl_arg_cxt; + +/* A context for reading key sequences longer than a single character when + using the callback interface. */ +#define KSEQ_DISPATCHED 0x01 +#define KSEQ_SUBSEQ 0x02 +#define KSEQ_RECURSIVE 0x04 + +typedef struct __rl_keyseq_context +{ + int flags; + int subseq_arg; + int subseq_retval; /* XXX */ + Keymap dmap; + + Keymap oldmap; + int okey; + struct __rl_keyseq_context *ocxt; + int childval; +} _rl_keyseq_cxt; + + /* fill in more as needed */ +/* `Generic' callback data and functions */ +typedef struct __rl_callback_generic_arg +{ + int count; + int i1, i2; + /* add here as needed */ +} _rl_callback_generic_arg; + +typedef int _rl_callback_func_t PARAMS((_rl_callback_generic_arg *)); + +/************************************************************************* + * * + * Global functions undocumented in texinfo manual and not in readline.h * + * * + *************************************************************************/ + +/************************************************************************* + * * + * Global variables undocumented in texinfo manual and not in readline.h * + * * + *************************************************************************/ + +/* complete.c */ +extern int rl_complete_with_tilde_expansion; +#if defined (VISIBLE_STATS) +extern int rl_visible_stats; +#endif /* VISIBLE_STATS */ + +/* readline.c */ +extern int rl_line_buffer_len; +extern int rl_arg_sign; +extern int rl_visible_prompt_length; +extern int readline_echoing_p; +extern int rl_key_sequence_length; +extern int rl_byte_oriented; + +extern _rl_keyseq_cxt *_rl_kscxt; + +/* display.c */ +extern int rl_display_fixed; + +/* parens.c */ +extern int rl_blink_matching_paren; + +/************************************************************************* + * * + * Global functions and variables unsed and undocumented * + * * + *************************************************************************/ + +/* kill.c */ +extern int rl_set_retained_kills PARAMS((int)); + +/* terminal.c */ +extern void _rl_set_screen_size PARAMS((int, int)); + +/* undo.c */ +extern int _rl_fix_last_undo_of_type PARAMS((int, int, int)); + +/* util.c */ +extern char *_rl_savestring PARAMS((const char *)); + +/************************************************************************* + * * + * Functions and variables private to the readline library * + * * + *************************************************************************/ + +/* NOTE: Functions and variables prefixed with `_rl_' are + pseudo-global: they are global so they can be shared + between files in the readline library, but are not intended + to be visible to readline callers. */ + +/************************************************************************* + * Undocumented private functions * + *************************************************************************/ + +#if defined(READLINE_CALLBACKS) + +/* readline.c */ +extern void readline_internal_setup PARAMS((void)); +extern char *readline_internal_teardown PARAMS((int)); +extern int readline_internal_char PARAMS((void)); + +extern _rl_keyseq_cxt *_rl_keyseq_cxt_alloc PARAMS((void)); +extern void _rl_keyseq_cxt_dispose PARAMS((_rl_keyseq_cxt *)); +extern void _rl_keyseq_chain_dispose PARAMS((void)); + +extern int _rl_dispatch_callback PARAMS((_rl_keyseq_cxt *)); + +/* callback.c */ +extern _rl_callback_generic_arg *_rl_callback_data_alloc PARAMS((int)); +extern void _rl_callback_data_dispose PARAMS((_rl_callback_generic_arg *)); + +#endif /* READLINE_CALLBACKS */ + +/* bind.c */ + +/* complete.c */ +extern char _rl_find_completion_word PARAMS((int *, int *)); +extern void _rl_free_match_list PARAMS((char **)); + +/* display.c */ +extern char *_rl_strip_prompt PARAMS((char *)); +extern void _rl_move_cursor_relative PARAMS((int, const char *)); +extern void _rl_move_vert PARAMS((int)); +extern void _rl_save_prompt PARAMS((void)); +extern void _rl_restore_prompt PARAMS((void)); +extern char *_rl_make_prompt_for_search PARAMS((int)); +extern void _rl_erase_at_end_of_line PARAMS((int)); +extern void _rl_clear_to_eol PARAMS((int)); +extern void _rl_clear_screen PARAMS((void)); +extern void _rl_update_final PARAMS((void)); +extern void _rl_redisplay_after_sigwinch PARAMS((void)); +extern void _rl_clean_up_for_exit PARAMS((void)); +extern void _rl_erase_entire_line PARAMS((void)); +extern int _rl_current_display_line PARAMS((void)); + +/* input.c */ +extern int _rl_any_typein PARAMS((void)); +extern int _rl_input_available PARAMS((void)); +extern int _rl_input_queued PARAMS((int)); +extern void _rl_insert_typein PARAMS((int)); +extern int _rl_unget_char PARAMS((int)); +extern int _rl_pushed_input_available PARAMS((void)); + +/* isearch.c */ +extern _rl_search_cxt *_rl_scxt_alloc PARAMS((int, int)); +extern void _rl_scxt_dispose PARAMS((_rl_search_cxt *, int)); + +extern int _rl_isearch_dispatch PARAMS((_rl_search_cxt *, int)); +extern int _rl_isearch_callback PARAMS((_rl_search_cxt *)); + +extern int _rl_search_getchar PARAMS((_rl_search_cxt *)); + +/* macro.c */ +extern void _rl_with_macro_input PARAMS((char *)); +extern int _rl_next_macro_key PARAMS((void)); +extern void _rl_push_executing_macro PARAMS((void)); +extern void _rl_pop_executing_macro PARAMS((void)); +extern void _rl_add_macro_char PARAMS((int)); +extern void _rl_kill_kbd_macro PARAMS((void)); + +/* misc.c */ +extern int _rl_arg_overflow PARAMS((void)); +extern void _rl_arg_init PARAMS((void)); +extern int _rl_arg_getchar PARAMS((void)); +extern int _rl_arg_callback PARAMS((_rl_arg_cxt)); +extern void _rl_reset_argument PARAMS((void)); + +extern void _rl_start_using_history PARAMS((void)); +extern int _rl_free_saved_history_line PARAMS((void)); +extern void _rl_set_insert_mode PARAMS((int, int)); + +/* nls.c */ +extern int _rl_init_eightbit PARAMS((void)); + +/* parens.c */ +extern void _rl_enable_paren_matching PARAMS((int)); + +/* readline.c */ +extern void _rl_init_line_state PARAMS((void)); +extern void _rl_set_the_line PARAMS((void)); +extern int _rl_dispatch PARAMS((int, Keymap)); +extern int _rl_dispatch_subseq PARAMS((int, Keymap, int)); +extern void _rl_internal_char_cleanup PARAMS((void)); + +/* rltty.c */ +extern int _rl_disable_tty_signals PARAMS((void)); +extern int _rl_restore_tty_signals PARAMS((void)); + +/* search.c */ +extern int _rl_nsearch_callback PARAMS((_rl_search_cxt *)); + +/* terminal.c */ +extern void _rl_get_screen_size PARAMS((int, int)); +extern int _rl_init_terminal_io PARAMS((const char *)); +#ifdef _MINIX +extern void _rl_output_character_function PARAMS((int)); +#else +extern int _rl_output_character_function PARAMS((int)); +#endif +extern void _rl_output_some_chars PARAMS((const char *, int)); +extern int _rl_backspace PARAMS((int)); +extern void _rl_enable_meta_key PARAMS((void)); +extern void _rl_control_keypad PARAMS((int)); +extern void _rl_set_cursor PARAMS((int, int)); + +/* text.c */ +extern void _rl_fix_point PARAMS((int)); +extern int _rl_replace_text PARAMS((const char *, int, int)); +extern int _rl_insert_char PARAMS((int, int)); +extern int _rl_overwrite_char PARAMS((int, int)); +extern int _rl_overwrite_rubout PARAMS((int, int)); +extern int _rl_rubout_char PARAMS((int, int)); +#if defined (HANDLE_MULTIBYTE) +extern int _rl_char_search_internal PARAMS((int, int, char *, int)); +#else +extern int _rl_char_search_internal PARAMS((int, int, int)); +#endif +extern int _rl_set_mark_at_pos PARAMS((int)); + +/* util.c */ +extern int _rl_abort_internal PARAMS((void)); +extern char *_rl_strindex PARAMS((const char *, const char *)); +extern int _rl_qsort_string_compare PARAMS((char **, char **)); +extern int (_rl_uppercase_p) PARAMS((int)); +extern int (_rl_lowercase_p) PARAMS((int)); +extern int (_rl_pure_alphabetic) PARAMS((int)); +extern int (_rl_digit_p) PARAMS((int)); +extern int (_rl_to_lower) PARAMS((int)); +extern int (_rl_to_upper) PARAMS((int)); +extern int (_rl_digit_value) PARAMS((int)); + +/* vi_mode.c */ +extern void _rl_vi_initialize_line PARAMS((void)); +extern void _rl_vi_reset_last PARAMS((void)); +extern void _rl_vi_set_last PARAMS((int, int, int)); +extern int _rl_vi_textmod_command PARAMS((int)); +extern void _rl_vi_done_inserting PARAMS((void)); + +/************************************************************************* + * Undocumented private variables * + *************************************************************************/ + +/* bind.c */ +extern const char *_rl_possible_control_prefixes[]; +extern const char *_rl_possible_meta_prefixes[]; + +/* callback.c */ +extern _rl_callback_func_t *_rl_callback_func; +extern _rl_callback_generic_arg *_rl_callback_data; + +/* complete.c */ +extern int _rl_complete_show_all; +extern int _rl_complete_show_unmodified; +extern int _rl_complete_mark_directories; +extern int _rl_complete_mark_symlink_dirs; +extern int _rl_print_completions_horizontally; +extern int _rl_completion_case_fold; +extern int _rl_match_hidden_files; +extern int _rl_page_completions; + +/* display.c */ +extern int _rl_vis_botlin; +extern int _rl_last_c_pos; +extern int _rl_suppress_redisplay; +extern int _rl_want_redisplay; +extern char *rl_display_prompt; + +/* isearch.c */ +extern char *_rl_isearch_terminators; + +extern _rl_search_cxt *_rl_iscxt; + +/* macro.c */ +extern char *_rl_executing_macro; + +/* misc.c */ +extern int _rl_history_preserve_point; +extern int _rl_history_saved_point; + +extern _rl_arg_cxt _rl_argcxt; + +/* readline.c */ +extern int _rl_horizontal_scroll_mode; +extern int _rl_mark_modified_lines; +extern int _rl_bell_preference; +extern int _rl_meta_flag; +extern int _rl_convert_meta_chars_to_ascii; +extern int _rl_output_meta_chars; +extern int _rl_bind_stty_chars; +extern char *_rl_comment_begin; +extern unsigned char _rl_parsing_conditionalized_out; +extern Keymap _rl_keymap; +extern FILE *_rl_in_stream; +extern FILE *_rl_out_stream; +extern int _rl_last_command_was_kill; +extern int _rl_eof_char; +extern procenv_t readline_top_level; + +/* search.c */ +extern _rl_search_cxt *_rl_nscxt; + +/* terminal.c */ +extern int _rl_enable_keypad; +extern int _rl_enable_meta; +extern char *_rl_term_clreol; +extern char *_rl_term_clrpag; +extern char *_rl_term_im; +extern char *_rl_term_ic; +extern char *_rl_term_ei; +extern char *_rl_term_DC; +extern char *_rl_term_up; +extern char *_rl_term_dc; +extern char *_rl_term_cr; +extern char *_rl_term_IC; +extern int _rl_screenheight; +extern int _rl_screenwidth; +extern int _rl_screenchars; +extern int _rl_terminal_can_insert; +extern int _rl_term_autowrap; + +/* undo.c */ +extern int _rl_doing_an_undo; +extern int _rl_undo_group_level; + +/* vi_mode.c */ +extern int _rl_vi_last_command; + +#endif /* _RL_PRIVATE_H_ */ diff --git a/lib/readline/search.c b/lib/readline/search.c index b4c174d..8013916 100644 --- a/lib/readline/search.c +++ b/lib/readline/search.c @@ -70,6 +70,7 @@ static int rl_history_search_pos; static char *history_search_string; static int history_string_size; +static UNDO_LIST *noninc_saved_undo_list; static void make_history_line_current PARAMS((HIST_ENTRY *)); static int noninc_search_from_pos PARAMS((char *, int, int)); static int noninc_dosearch PARAMS((char *, int)); @@ -89,12 +90,15 @@ static void make_history_line_current (entry) HIST_ENTRY *entry; { -#if 0 - rl_replace_line (entry->line, 1); - rl_undo_list = (UNDO_LIST *)entry->data; -#else _rl_replace_text (entry->line, 0, rl_end); _rl_fix_point (1); +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + /* POSIX.2 says that the `U' command doesn't affect the copy of any + command lines to the edit line. We're going to implement that by + making the undo list start after the matching line is copied to the + current editing buffer. */ + rl_free_undo_list (); #endif if (_rl_saved_line_for_history) @@ -325,6 +329,13 @@ _rl_nsearch_dosearch (cxt) noninc_history_pos = cxt->save_line; FREE (noninc_search_string); noninc_search_string = savestring (rl_line_buffer); + + /* If we don't want the subsequent undo list generated by the search + matching a history line to include the contents of the search string, + we need to clear rl_line_buffer here. For now, we just clear the + undo list generated by reading the search string. (If the search + fails, the old undo list will be restored by rl_maybe_unsave_line.) */ + rl_free_undo_list (); } rl_restore_prompt (); diff --git a/lib/readline/search.c~ b/lib/readline/search.c~ new file mode 100644 index 0000000..764c33a --- /dev/null +++ b/lib/readline/search.c~ @@ -0,0 +1,572 @@ +/* search.c - code for non-incremental searching in emacs and vi modes. */ + +/* Copyright (C) 1992-2005 Free Software Foundation, Inc. + + This file is part of the Readline Library (the Library), a set of + routines for providing Emacs style line input to programs that ask + for it. + + The Library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + The Library 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. + + The GNU General Public License is often shipped with GNU software, and + is generally kept in a file called COPYING or LICENSE. If you do not + have a copy of the license, write to the Free Software Foundation, + 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ +#define READLINE_LIBRARY + +#if defined (HAVE_CONFIG_H) +# include +#endif + +#include +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#if defined (HAVE_STDLIB_H) +# include +#else +# include "ansi_stdlib.h" +#endif + +#include "rldefs.h" +#include "rlmbutil.h" + +#include "readline.h" +#include "history.h" + +#include "rlprivate.h" +#include "xmalloc.h" + +#ifdef abs +# undef abs +#endif +#define abs(x) (((x) >= 0) ? (x) : -(x)) + +_rl_search_cxt *_rl_nscxt = 0; + +extern HIST_ENTRY *_rl_saved_line_for_history; + +/* Functions imported from the rest of the library. */ +extern int _rl_free_history_entry PARAMS((HIST_ENTRY *)); + +static char *noninc_search_string = (char *) NULL; +static int noninc_history_pos; + +static char *prev_line_found = (char *) NULL; + +static int rl_history_search_len; +static int rl_history_search_pos; +static char *history_search_string; +static int history_string_size; + +static UNDO_LIST *noninc_saved_undo_list; +static void make_history_line_current PARAMS((HIST_ENTRY *)); +static int noninc_search_from_pos PARAMS((char *, int, int)); +static int noninc_dosearch PARAMS((char *, int)); +static int noninc_search PARAMS((int, int)); +static int rl_history_search_internal PARAMS((int, int)); +static void rl_history_search_reinit PARAMS((void)); + +static _rl_search_cxt *_rl_nsearch_init PARAMS((int, int)); +static int _rl_nsearch_cleanup PARAMS((_rl_search_cxt *, int)); +static void _rl_nsearch_abort PARAMS((_rl_search_cxt *)); +static int _rl_nsearch_dispatch PARAMS((_rl_search_cxt *, int)); + +/* Make the data from the history entry ENTRY be the contents of the + current line. This doesn't do anything with rl_point; the caller + must set it. */ +static void +make_history_line_current (entry) + HIST_ENTRY *entry; +{ + _rl_replace_text (entry->line, 0, rl_end); + _rl_fix_point (1); +#if defined (VI_MODE) + if (rl_editing_mode == vi_mode) + /* POSIX.2 says that the `U' command doesn't affect command lines copied + to the edit line. That's ambiguous, but we're going to interpret it + to mean that the undo list starts after the matching line is copied to + the current editing buffer. */ + rl_free_undo_list (); +#endif + + if (_rl_saved_line_for_history) + _rl_free_history_entry (_rl_saved_line_for_history); + _rl_saved_line_for_history = (HIST_ENTRY *)NULL; +} + +/* Search the history list for STRING starting at absolute history position + POS. If STRING begins with `^', the search must match STRING at the + beginning of a history line, otherwise a full substring match is performed + for STRING. DIR < 0 means to search backwards through the history list, + DIR >= 0 means to search forward. */ +static int +noninc_search_from_pos (string, pos, dir) + char *string; + int pos, dir; +{ + int ret, old; + + if (pos < 0) + return -1; + + old = where_history (); + if (history_set_pos (pos) == 0) + return -1; + + RL_SETSTATE(RL_STATE_SEARCH); + if (*string == '^') + ret = history_search_prefix (string + 1, dir); + else + ret = history_search (string, dir); + RL_UNSETSTATE(RL_STATE_SEARCH); + + if (ret != -1) + ret = where_history (); + + history_set_pos (old); + return (ret); +} + +/* Search for a line in the history containing STRING. If DIR is < 0, the + search is backwards through previous entries, else through subsequent + entries. Returns 1 if the search was successful, 0 otherwise. */ +static int +noninc_dosearch (string, dir) + char *string; + int dir; +{ + int oldpos, pos; + HIST_ENTRY *entry; + + if (string == 0 || *string == '\0' || noninc_history_pos < 0) + { + rl_ding (); + return 0; + } + + pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir); + if (pos == -1) + { + /* Search failed, current history position unchanged. */ + rl_maybe_unsave_line (); + rl_clear_message (); + rl_point = 0; + rl_ding (); + return 0; + } + + noninc_history_pos = pos; + + oldpos = where_history (); + history_set_pos (noninc_history_pos); + entry = current_history (); +#if defined (VI_MODE) + if (rl_editing_mode != vi_mode) +#endif + history_set_pos (oldpos); + + make_history_line_current (entry); + + rl_point = 0; + rl_mark = rl_end; + + rl_clear_message (); + return 1; +} + +static _rl_search_cxt * +_rl_nsearch_init (dir, pchar) + int dir, pchar; +{ + _rl_search_cxt *cxt; + char *p; + + cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0); + if (dir < 0) + cxt->sflags |= SF_REVERSE; /* not strictly needed */ + + cxt->direction = dir; + cxt->history_pos = cxt->save_line; + + rl_maybe_save_line (); + + /* Clear the undo list, since reading the search string should create its + own undo list, and the whole list will end up being freed when we + finish reading the search string. */ + rl_undo_list = 0; + + /* Use the line buffer to read the search string. */ + rl_line_buffer[0] = 0; + rl_end = rl_point = 0; + + p = _rl_make_prompt_for_search (pchar ? pchar : ':'); + rl_message (p, 0, 0); + free (p); + + RL_SETSTATE(RL_STATE_NSEARCH); + + _rl_nscxt = cxt; + + return cxt; +} + +static int +_rl_nsearch_cleanup (cxt, r) + _rl_search_cxt *cxt; + int r; +{ + _rl_scxt_dispose (cxt, 0); + _rl_nscxt = 0; + + RL_UNSETSTATE(RL_STATE_NSEARCH); + + return (r != 1); +} + +static void +_rl_nsearch_abort (cxt) + _rl_search_cxt *cxt; +{ + rl_maybe_unsave_line (); + rl_clear_message (); + rl_point = cxt->save_point; + rl_mark = cxt->save_mark; + rl_restore_prompt (); + + RL_UNSETSTATE (RL_STATE_NSEARCH); +} + +/* Process just-read character C according to search context CXT. Return -1 + if the caller should abort the search, 0 if we should break out of the + loop, and 1 if we should continue to read characters. */ +static int +_rl_nsearch_dispatch (cxt, c) + _rl_search_cxt *cxt; + int c; +{ + switch (c) + { + case CTRL('W'): + rl_unix_word_rubout (1, c); + break; + + case CTRL('U'): + rl_unix_line_discard (1, c); + break; + + case RETURN: + case NEWLINE: + return 0; + + case CTRL('H'): + case RUBOUT: + if (rl_point == 0) + { + _rl_nsearch_abort (cxt); + return -1; + } + _rl_rubout_char (1, c); + break; + + case CTRL('C'): + case CTRL('G'): + rl_ding (); + _rl_nsearch_abort (cxt); + return -1; + + default: +#if defined (HANDLE_MULTIBYTE) + if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) + rl_insert_text (cxt->mb); + else +#endif + _rl_insert_char (1, c); + break; + } + + (*rl_redisplay_function) (); + return 1; +} + +/* Perform one search according to CXT, using NONINC_SEARCH_STRING. Return + -1 if the search should be aborted, any other value means to clean up + using _rl_nsearch_cleanup (). Returns 1 if the search was successful, + 0 otherwise. */ +static int +_rl_nsearch_dosearch (cxt) + _rl_search_cxt *cxt; +{ + rl_mark = cxt->save_mark; + + /* If rl_point == 0, we want to re-use the previous search string and + start from the saved history position. If there's no previous search + string, punt. */ + if (rl_point == 0) + { + if (noninc_search_string == 0) + { + rl_ding (); + rl_restore_prompt (); + RL_UNSETSTATE (RL_STATE_NSEARCH); + return -1; + } + } + else + { + /* We want to start the search from the current history position. */ + noninc_history_pos = cxt->save_line; + FREE (noninc_search_string); + noninc_search_string = savestring (rl_line_buffer); + + /* If we don't want the subsequent undo list generated by the search + matching a history line to include the contents of the search string, + we need to clear rl_line_buffer here. For now, we just clear the + undo list generated by reading the search string. (If the search + fails, the old undo list will be restored by rl_maybe_unsave_line.) */ + rl_free_undo_list (); + } + + rl_restore_prompt (); + return (noninc_dosearch (noninc_search_string, cxt->direction)); +} + +/* Search non-interactively through the history list. DIR < 0 means to + search backwards through the history of previous commands; otherwise + the search is for commands subsequent to the current position in the + history list. PCHAR is the character to use for prompting when reading + the search string; if not specified (0), it defaults to `:'. */ +static int +noninc_search (dir, pchar) + int dir; + int pchar; +{ + _rl_search_cxt *cxt; + int c, r; + + cxt = _rl_nsearch_init (dir, pchar); + + if (RL_ISSTATE (RL_STATE_CALLBACK)) + return (0); + + /* Read the search string. */ + r = 0; + while (1) + { + c = _rl_search_getchar (cxt); + + if (c == 0) + break; + + r = _rl_nsearch_dispatch (cxt, c); + if (r < 0) + return 1; + else if (r == 0) + break; + } + + r = _rl_nsearch_dosearch (cxt); + return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1)); +} + +/* Search forward through the history list for a string. If the vi-mode + code calls this, KEY will be `?'. */ +int +rl_noninc_forward_search (count, key) + int count, key; +{ + return noninc_search (1, (key == '?') ? '?' : 0); +} + +/* Reverse search the history list for a string. If the vi-mode code + calls this, KEY will be `/'. */ +int +rl_noninc_reverse_search (count, key) + int count, key; +{ + return noninc_search (-1, (key == '/') ? '/' : 0); +} + +/* Search forward through the history list for the last string searched + for. If there is no saved search string, abort. */ +int +rl_noninc_forward_search_again (count, key) + int count, key; +{ + int r; + + if (!noninc_search_string) + { + rl_ding (); + return (-1); + } + r = noninc_dosearch (noninc_search_string, 1); + return (r != 1); +} + +/* Reverse search in the history list for the last string searched + for. If there is no saved search string, abort. */ +int +rl_noninc_reverse_search_again (count, key) + int count, key; +{ + int r; + + if (!noninc_search_string) + { + rl_ding (); + return (-1); + } + r = noninc_dosearch (noninc_search_string, -1); + return (r != 1); +} + +#if defined (READLINE_CALLBACKS) +int +_rl_nsearch_callback (cxt) + _rl_search_cxt *cxt; +{ + int c, r; + + c = _rl_search_getchar (cxt); + r = _rl_nsearch_dispatch (cxt, c); + if (r != 0) + return 1; + + r = _rl_nsearch_dosearch (cxt); + return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1)); +} +#endif + +static int +rl_history_search_internal (count, dir) + int count, dir; +{ + HIST_ENTRY *temp; + int ret, oldpos; + + rl_maybe_save_line (); + temp = (HIST_ENTRY *)NULL; + + /* Search COUNT times through the history for a line whose prefix + matches history_search_string. When this loop finishes, TEMP, + if non-null, is the history line to copy into the line buffer. */ + while (count) + { + ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir); + if (ret == -1) + break; + + /* Get the history entry we found. */ + rl_history_search_pos = ret; + oldpos = where_history (); + history_set_pos (rl_history_search_pos); + temp = current_history (); + history_set_pos (oldpos); + + /* Don't find multiple instances of the same line. */ + if (prev_line_found && STREQ (prev_line_found, temp->line)) + continue; + prev_line_found = temp->line; + count--; + } + + /* If we didn't find anything at all, return. */ + if (temp == 0) + { + rl_maybe_unsave_line (); + rl_ding (); + /* If you don't want the saved history line (last match) to show up + in the line buffer after the search fails, change the #if 0 to + #if 1 */ +#if 0 + if (rl_point > rl_history_search_len) + { + rl_point = rl_end = rl_history_search_len; + rl_line_buffer[rl_end] = '\0'; + rl_mark = 0; + } +#else + rl_point = rl_history_search_len; /* rl_maybe_unsave_line changes it */ + rl_mark = rl_end; +#endif + return 1; + } + + /* Copy the line we found into the current line buffer. */ + make_history_line_current (temp); + + rl_point = rl_history_search_len; + rl_mark = rl_end; + + return 0; +} + +static void +rl_history_search_reinit () +{ + rl_history_search_pos = where_history (); + rl_history_search_len = rl_point; + prev_line_found = (char *)NULL; + if (rl_point) + { + if (rl_history_search_len >= history_string_size - 2) + { + history_string_size = rl_history_search_len + 2; + history_search_string = (char *)xrealloc (history_search_string, history_string_size); + } + history_search_string[0] = '^'; + strncpy (history_search_string + 1, rl_line_buffer, rl_point); + history_search_string[rl_point + 1] = '\0'; + } + _rl_free_saved_history_line (); +} + +/* Search forward in the history for the string of characters + from the start of the line to rl_point. This is a non-incremental + search. */ +int +rl_history_search_forward (count, ignore) + int count, ignore; +{ + if (count == 0) + return (0); + + if (rl_last_func != rl_history_search_forward && + rl_last_func != rl_history_search_backward) + rl_history_search_reinit (); + + if (rl_history_search_len == 0) + return (rl_get_next_history (count, ignore)); + return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1)); +} + +/* Search backward through the history for the string of characters + from the start of the line to rl_point. This is a non-incremental + search. */ +int +rl_history_search_backward (count, ignore) + int count, ignore; +{ + if (count == 0) + return (0); + + if (rl_last_func != rl_history_search_forward && + rl_last_func != rl_history_search_backward) + rl_history_search_reinit (); + + if (rl_history_search_len == 0) + return (rl_get_previous_history (count, ignore)); + return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1)); +} diff --git a/lib/sh/pathphys.c b/lib/sh/pathphys.c index 4d6304c..1f73944 100644 --- a/lib/sh/pathphys.c +++ b/lib/sh/pathphys.c @@ -285,6 +285,7 @@ sh_realpath (pathname, resolved) { strncpy (resolved, wd, PATH_MAX - 1); resolved[PATH_MAX - 1] = '\0'; + free (wd); return resolved; } else diff --git a/lib/sh/pathphys.c~ b/lib/sh/pathphys.c~ new file mode 100644 index 0000000..4d6304c --- /dev/null +++ b/lib/sh/pathphys.c~ @@ -0,0 +1,295 @@ +/* pathphys.c -- Return pathname with all symlinks expanded. */ + +/* Copyright (C) 2000 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + Bash is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with Bash; see the file COPYING. If not, write to the Free Software + Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#include + +#include +#ifndef _MINIX +# include +#endif +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include +#include +#include +#include +#include + +#include "shell.h" + +#if !defined (MAXSYMLINKS) +# define MAXSYMLINKS 32 +#endif + +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +extern char *get_working_directory __P((char *)); + +static int +_path_readlink (path, buf, bufsiz) + char *path; + char *buf; + int bufsiz; +{ +#ifdef HAVE_READLINK + return readlink (path, buf, bufsiz); +#else + errno = EINVAL; + return -1; +#endif +} + +/* Look for ROOTEDPATH, PATHSEP, DIRSEP, and ISDIRSEP in ../../general.h */ + +#define DOUBLE_SLASH(p) ((p[0] == '/') && (p[1] == '/') && p[2] != '/') + +/* + * Return PATH with all symlinks expanded in newly-allocated memory. + * This always gets an absolute pathname. + */ + +char * +sh_physpath (path, flags) + char *path; + int flags; +{ + char tbuf[PATH_MAX+1], linkbuf[PATH_MAX+1]; + char *result, *p, *q, *qsave, *qbase, *workpath; + int double_slash_path, linklen, nlink; + + linklen = strlen (path); + +#if 0 + /* First sanity check -- punt immediately if the name is too long. */ + if (linklen >= PATH_MAX) + return (savestring (path)); +#endif + + nlink = 0; + q = result = (char *)xmalloc (PATH_MAX + 1); + + /* Even if we get something longer than PATH_MAX, we might be able to + shorten it, so we try. */ + if (linklen >= PATH_MAX) + workpath = savestring (path); + else + { + workpath = (char *)xmalloc (PATH_MAX + 1); + strcpy (workpath, path); + } + + /* This always gets an absolute pathname. */ + + /* POSIX.2 says to leave a leading `//' alone. On cygwin, we skip over any + leading `x:' (dos drive name). */ +#if defined (__CYGWIN__) + qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1; +#else + qbase = workpath + 1; +#endif + double_slash_path = DOUBLE_SLASH (workpath); + qbase += double_slash_path; + + for (p = workpath; p < qbase; ) + *q++ = *p++; + qbase = q; + + /* + * invariants: + * qbase points to the portion of the result path we want to modify + * p points at beginning of path element we're considering. + * q points just past the last path element we wrote (no slash). + * + * XXX -- need to fix error checking for too-long pathnames + */ + + while (*p) + { + if (ISDIRSEP(p[0])) /* null element */ + p++; + else if(p[0] == '.' && PATHSEP(p[1])) /* . and ./ */ + p += 1; /* don't count the separator in case it is nul */ + else if (p[0] == '.' && p[1] == '.' && PATHSEP(p[2])) /* .. and ../ */ + { + p += 2; /* skip `..' */ + if (q > qbase) + { + while (--q > qbase && ISDIRSEP(*q) == 0) + ; + } + } + else /* real path element */ + { + /* add separator if not at start of work portion of result */ + qsave = q; + if (q != qbase) + *q++ = DIRSEP; + while (*p && (ISDIRSEP(*p) == 0)) + { + if (q - result >= PATH_MAX) + { +#ifdef ENAMETOOLONG + errno = ENAMETOOLONG; +#else + errno = EINVAL; +#endif + goto error; + } + + *q++ = *p++; + } + + *q = '\0'; + + linklen = _path_readlink (result, linkbuf, PATH_MAX); + if (linklen < 0) /* if errno == EINVAL, it's not a symlink */ + { + if (errno != EINVAL) + goto error; + continue; + } + + /* It's a symlink, and the value is in LINKBUF. */ + nlink++; + if (nlink > MAXSYMLINKS) + { +#ifdef ELOOP + errno = ELOOP; +#else + errno = EINVAL; +#endif +error: + free (result); + free (workpath); + return ((char *)NULL); + } + + linkbuf[linklen] = '\0'; + + /* If the new path length would overrun PATH_MAX, punt now. */ + if ((strlen (p) + linklen + 2) >= PATH_MAX) + { +#ifdef ENAMETOOLONG + errno = ENAMETOOLONG; +#else + errno = EINVAL; +#endif + goto error; + } + + /* Form the new pathname by copying the link value to a temporary + buffer and appending the rest of `workpath'. Reset p to point + to the start of the rest of the path. If the link value is an + absolute pathname, reset p, q, and qbase. If not, reset p + and q. */ + strcpy (tbuf, linkbuf); + tbuf[linklen] = '/'; + strcpy (tbuf + linklen, p); + strcpy (workpath, tbuf); + + if (ABSPATH(linkbuf)) + { + q = result; + /* Duplicating some code here... */ +#if defined (__CYGWIN__) + qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1; +#else + qbase = workpath + 1; +#endif + double_slash_path = DOUBLE_SLASH (workpath); + qbase += double_slash_path; + + for (p = workpath; p < qbase; ) + *q++ = *p++; + qbase = q; + } + else + { + p = workpath; + q = qsave; + } + } + } + + *q = '\0'; + free (workpath); + + /* If the result starts with `//', but the original path does not, we + can turn the // into /. Because of how we set `qbase', this should never + be true, but it's a sanity check. */ + if (DOUBLE_SLASH(result) && double_slash_path == 0) + { + if (result[2] == '\0') /* short-circuit for bare `//' */ + result[1] = '\0'; + else + strcpy (result, result + 1); + } + + return (result); +} + +char * +sh_realpath (pathname, resolved) + const char *pathname; + char *resolved; +{ + char *tdir, *wd; + + if (pathname == 0 || *pathname == '\0') + { + errno = (pathname == 0) ? EINVAL : ENOENT; + return ((char *)NULL); + } + + if (ABSPATH (pathname) == 0) + { + wd = get_working_directory ("sh_realpath"); + if (wd == 0) + return ((char *)NULL); + tdir = sh_makepath ((char *)pathname, wd, 0); + free (wd); + } + else + tdir = savestring (pathname); + + wd = sh_physpath (tdir, 0); + free (tdir); + + if (resolved == 0) + return (wd); + + if (wd) + { + strncpy (resolved, wd, PATH_MAX - 1); + resolved[PATH_MAX - 1] = '\0'; + return resolved; + } + else + { + resolved[0] = '\0'; + return wd; + } +} diff --git a/nojobs.c b/nojobs.c index df543ac..494e76d 100644 --- a/nojobs.c +++ b/nojobs.c @@ -887,10 +887,8 @@ wait_for (pid) return (return_val); } -/* Give PID SIGNAL. This determines what job the pid belongs to (if any). - If PID does belong to a job, and the job is stopped, then CONTinue the - job after giving it SIGNAL. Returns -1 on failure. If GROUP is non-null, - then kill the process group associated with PID. */ +/* Send PID SIGNAL. Returns -1 on failure, 0 on success. If GROUP is non-zero, + or PID is less than -1, then kill the process group associated with PID. */ int kill_pid (pid, signal, group) pid_t pid; @@ -898,6 +896,11 @@ kill_pid (pid, signal, group) { int result; + if (pid < -1) + { + pid = -pid; + group = 1; + } result = group ? killpg (pid, signal) : kill (pid, signal); return (result); } -- 2.7.4