From 31a8d95a371781250e579e151dc41ea28564bf10 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Mon, 21 Nov 2016 14:50:59 -0500 Subject: [PATCH] commit bash-20161118 snapshot --- CWRU/CWRU.chlog | 69 ++++++++++ MANIFEST | 1 + builtins/common.c | 4 +- builtins/shopt.def | 4 +- config.h.in | 3 + lib/readline/histlib.h | 10 +- lib/readline/histsearch.c | 99 +++++++++++++- lib/readline/rlprivate.h | 1 + lib/readline/search.c | 74 ++++++++--- parse.y | 4 +- pcomplete.c | 2 +- subst.c | 19 ++- subst.h | 2 +- support/bashbug.sh.in | 272 ++++++++++++++++++++++++++++++++++++++ 14 files changed, 530 insertions(+), 34 deletions(-) create mode 100644 support/bashbug.sh.in diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 782a778b..f3ff3e7d 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -12389,3 +12389,72 @@ lib/readline/display.c calls to mbrlen and mbrtowc - rl_redisplay: if in a UTF-8 locale, take advantage of that to avoid calls to mbrtowc + + 11/17 + ----- +lib/readline/histlib.h + - PATTERN_SEARCH: new flag for history search interfaces, means to + search for a pattern as Posix specifies + +lib/readline/histsearch.c + - history_search_internal: now takes a `flags' argument instead of just + an `anchored' argument to accommodate PATTERN_SEARCH + - _hs_history_patsearch: new internal interface to use when flags + specify PATTERN_SEARCH + +lib/readline/rlprivate.h + - SF_PATTERN: new flag for non-incremental search contexts, means to + treat search string as a pattern (maps to PATTERN_SEARCH) + +lib/readline/search.c + - noninc_dosearch: takes an additional `flags' argument for SF_PATTERN + - noninc_search_from_pos: takes an additional `flags' argument for + SF_PATTERN + - noninc_dosearch: pass flags argument through to noninc_search_from_pos + - _rl_nsearch_init: if we are in vi command mode, and `pchar' (key used + to invoke the search) is `?' or `/', add SF_PATTERN to the flags + to conform to Posix spec for vi-mode editing + - _rl_nsearch_dosearch: if cxt->sflags indicates that we should do a + pattern search, pass SF_PATTERN to noninc_search_from_pos + - rl_noninc_forward_search_again: if in vi command mode and key == `N', + make sure flags arg passed to noninc_dosearch includes SF_PATTERN + - rl_noninc_reverse_search_again: if in vi command mode and key == `n', + make sure flags arg passed to noninc_dosearch includes SF_PATTERN + - rl_history_search_internal: pass extra flags arg to noninc_search_from_pos + + 11/18 + ----- +lib/readline/search.c + - noninc_search_from_pos: takes a new argument, a pointer to int where + it stores the offset of the match in the history line (if non-NULL), + modified callers + - rl_history_search_internal: pass newcol pointer to + noninc_search_from_pos to avoid having to recompute the match offset + in the matching history entry + +config.h.in + - define HAVE_FNMATCH if we have the fnmatch function (configure was + already checking for it) + +lib/readline/histsearch.c + - _hs_history_patsearch: transform the pattern into one ending in a + `*' to avoid having to perform multiple match attempts from each + index in the history line + - history_search_internal: changes to handle pattern matching if + PATTERN_SEARCH is in the flags and HAVE_FNMATCH is defined. This + makes vi-mode history searching treat the user-specified search + string as an fnmatch pattern, as Posix requires. Fixes issue + reported by + + 11/19 + ----- +builtins/shopt.def + - shopt_enable_hostname_completion: only declare this if READLINE + defined, since that's the only time it's used. Reported by + isabella parakiss + + 11/20 + ----- +builtins/common.c + - display_signal_list: make `kill -l 0' print `EXIT', modifying change + from 9/17 diff --git a/MANIFEST b/MANIFEST index 26ef622e..dc203c6e 100644 --- a/MANIFEST +++ b/MANIFEST @@ -631,6 +631,7 @@ support/mkversion.sh f 755 support/mksignames.c f support/signames.c f support/bashbug.sh f +support/bashbug.sh.in f support/man2html.c f support/recho.c f support/zecho.c f diff --git a/builtins/common.c b/builtins/common.c index 9e06c1e2..52c5af55 100644 --- a/builtins/common.c +++ b/builtins/common.c @@ -767,7 +767,7 @@ display_signal_list (list, forcecols) mapped into signal numbers. */ if (lsignum > 128) lsignum -= 128; - if (lsignum <= 0 || lsignum >= NSIG) + if (lsignum < 0 || lsignum >= NSIG) { sh_invalidsig (list->word->word); result = EXECUTION_FAILURE; @@ -784,7 +784,7 @@ display_signal_list (list, forcecols) } /* POSIX.2 says that `kill -l signum' prints the signal name without the `SIG' prefix. */ - printf ("%s\n", (this_shell_builtin == kill_builtin) ? name + 3 : name); + printf ("%s\n", (this_shell_builtin == kill_builtin && signum > 0) ? name + 3 : name); } else { diff --git a/builtins/shopt.def b/builtins/shopt.def index 2febb7ee..0d165fa8 100644 --- a/builtins/shopt.def +++ b/builtins/shopt.def @@ -121,7 +121,6 @@ extern int debugging_mode; static void shopt_error __P((char *)); static int set_shellopts_after_change __P((char *, int)); -static int shopt_enable_hostname_completion __P((char *, int)); static int set_compatibility_level __P((char *, int)); #if defined (RESTRICTED_SHELL) @@ -129,6 +128,7 @@ static int set_restricted_shell __P((char *, int)); #endif #if defined (READLINE) +static int shopt_enable_hostname_completion __P((char *, int)); static int shopt_set_complete_direxpand __P((char *, int)); #endif @@ -576,6 +576,7 @@ shopt_set_debug_mode (option_name, mode) return (0); } +#if defined (READLINE) static int shopt_enable_hostname_completion (option_name, mode) char *option_name; @@ -583,6 +584,7 @@ shopt_enable_hostname_completion (option_name, mode) { return (enable_hostname_completion (mode)); } +#endif static int set_compatibility_level (option_name, mode) diff --git a/config.h.in b/config.h.in index 833e3e3f..3de3abd7 100644 --- a/config.h.in +++ b/config.h.in @@ -608,6 +608,9 @@ /* Define if you have the fcntl function. */ #undef HAVE_FCNTL +/* Define if you have the fnmatch function. */ +#undef HAVE_FNMATCH + /* Define if you have the fpurge/__fpurge function. */ #undef HAVE_FPURGE #undef HAVE___FPURGE diff --git a/lib/readline/histlib.h b/lib/readline/histlib.h index 28cad14a..9986a2e4 100644 --- a/lib/readline/histlib.h +++ b/lib/readline/histlib.h @@ -69,11 +69,17 @@ extern char *strchr (); #define NO_PREV_SUBST 4 /* Possible definitions for history starting point specification. */ -#define ANCHORED_SEARCH 1 -#define NON_ANCHORED_SEARCH 0 +#define NON_ANCHORED_SEARCH 0 +#define ANCHORED_SEARCH 0x01 +#define PATTERN_SEARCH 0x02 /* Possible definitions for what style of writing the history file we want. */ #define HISTORY_APPEND 0 #define HISTORY_OVERWRITE 1 +/* internal extern function declarations used by other parts of the library */ + +/* histsearch.c */ +extern int _hs_history_patsearch PARAMS((const char *, int, int)); + #endif /* !_HISTLIB_H_ */ diff --git a/lib/readline/histsearch.c b/lib/readline/histsearch.c index 1ad55d22..ab18f972 100644 --- a/lib/readline/histsearch.c +++ b/lib/readline/histsearch.c @@ -39,8 +39,13 @@ # include #endif +#if defined (HAVE_FNMATCH) +# include +#endif + #include "history.h" #include "histlib.h" +#include "xmalloc.h" /* The list of alternate characters that can delimit a history search string. */ @@ -59,18 +64,24 @@ static int history_search_internal PARAMS((const char *, int, int)); returned. */ static int -history_search_internal (string, direction, anchored) +history_search_internal (string, direction, flags) const char *string; - int direction, anchored; + int direction, flags; { register int i, reverse; register char *line; register int line_index; - int string_len; + int string_len, anchored, patsearch; HIST_ENTRY **the_history; /* local */ i = history_offset; reverse = (direction < 0); + anchored = (flags & ANCHORED_SEARCH); +#if defined (HAVE_FNMATCH) + patsearch = (flags & PATTERN_SEARCH); +#else + patsearch = 0; +#endif /* Take care of trivial cases first. */ if (string == 0 || *string == '\0') @@ -98,7 +109,7 @@ history_search_internal (string, direction, anchored) line_index = strlen (line); /* If STRING is longer than line, no match. */ - if (string_len > line_index) + if (patsearch == 0 && (string_len > line_index)) { NEXT_LINE (); continue; @@ -107,6 +118,17 @@ history_search_internal (string, direction, anchored) /* Handle anchored searches first. */ if (anchored == ANCHORED_SEARCH) { +#if defined (HAVE_FNMATCH) + if (patsearch) + { + if (fnmatch (string, line, 0) == 0) + { + history_offset = i; + return (0); + } + } + else +#endif if (STREQN (string, line, string_len)) { history_offset = i; @@ -120,10 +142,21 @@ history_search_internal (string, direction, anchored) /* Do substring search. */ if (reverse) { - line_index -= string_len; + line_index -= (patsearch == 0) ? string_len : 1; while (line_index >= 0) { +#if defined (HAVE_FNMATCH) + if (patsearch) + { + if (fnmatch (string, line + line_index, 0) == 0) + { + history_offset = i; + return (line_index); + } + } + else +#endif if (STREQN (string, line + line_index, string_len)) { history_offset = i; @@ -141,6 +174,17 @@ history_search_internal (string, direction, anchored) while (line_index < limit) { +#if defined (HAVE_FNMATCH) + if (patsearch) + { + if (fnmatch (string, line + line_index, 0) == 0) + { + history_offset = i; + return (line_index); + } + } + else +#endif if (STREQN (string, line + line_index, string_len)) { history_offset = i; @@ -153,6 +197,51 @@ history_search_internal (string, direction, anchored) } } +int +_hs_history_patsearch (string, direction, flags) + const char *string; + int direction, flags; +{ + char *pat; + size_t len; + int ret, unescaped_backslash; + +#if defined (HAVE_FNMATCH) + /* Assume that the string passed does not have a leading `^' and any + anchored search request is captured in FLAGS */ + len = strlen (string); + ret = len - 1; + /* fnmatch is required to reject a pattern that ends with an unescaped + backslash */ + if (unescaped_backslash = (string[ret] == '\\')) + { + while (ret > 0 && string[--ret] == '\\') + unescaped_backslash = 1 - unescaped_backslash; + } + if (unescaped_backslash) + return -1; + pat = (char *)xmalloc (len + 2); + /* Attempt to reduce the number of searches by tacking a `*' onto the end + of a pattern that doesn't have one. Assume a pattern that ends in a + backslash contains an even number of trailing backslashes; we check + above */ + strcpy (pat, string); + if (pat[len - 1] != '*') + { + pat[len] = '*'; /* XXX */ + pat[len+1] = '\0'; + } +#else + pat = string; +#endif + + ret = history_search_internal (pat, direction, flags|PATTERN_SEARCH); + + if (pat != string) + free (pat); + return ret; +} + /* Do a non-anchored search for STRING through the history in DIRECTION. */ int history_search (string, direction) diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h index 1269e5c4..b11a6bf8 100644 --- a/lib/readline/rlprivate.h +++ b/lib/readline/rlprivate.h @@ -64,6 +64,7 @@ #define SF_FOUND 0x02 #define SF_FAILED 0x04 #define SF_CHGKMAP 0x08 +#define SF_PATTERN 0x10 /* unused so far */ typedef struct __rl_search_context { diff --git a/lib/readline/search.c b/lib/readline/search.c index 45d95d2e..131d12d8 100644 --- a/lib/readline/search.c +++ b/lib/readline/search.c @@ -1,6 +1,6 @@ /* search.c - code for non-incremental searching in emacs and vi modes. */ -/* Copyright (C) 1992-2015 Free Software Foundation, Inc. +/* Copyright (C) 1992-2016 Free Software Foundation, Inc. This file is part of the GNU Readline Library (Readline), a library for reading lines of text with interactive input and history editing. @@ -73,8 +73,8 @@ static char *history_search_string; static int history_string_size; 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_from_pos PARAMS((char *, int, int, int, int *)); +static int noninc_dosearch PARAMS((char *, int, int)); static int noninc_search PARAMS((int, int)); static int rl_history_search_internal PARAMS((int, int)); static void rl_history_search_reinit PARAMS((int)); @@ -112,11 +112,13 @@ make_history_line_current (entry) 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) +noninc_search_from_pos (string, pos, dir, flags, ncp) char *string; - int pos, dir; + int pos, dir, flags; + int *ncp; { - int ret, old; + int ret, old, sflags; + char *s; if (pos < 0) return -1; @@ -126,12 +128,28 @@ noninc_search_from_pos (string, pos, dir) return -1; RL_SETSTATE(RL_STATE_SEARCH); - if (*string == '^') + /* These functions return the match offset in the line; history_offset gives + the matching line in the history list */ + if (flags & SF_PATTERN) + { + s = string; + sflags = 0; /* Non-anchored search */ + if (*s == '^') + { + sflags |= ANCHORED_SEARCH; + s++; + } + ret = _hs_history_patsearch (string, dir, sflags); + } + else if (*string == '^') ret = history_search_prefix (string + 1, dir); else ret = history_search (string, dir); RL_UNSETSTATE(RL_STATE_SEARCH); + if (ncp) + *ncp = ret; /* caller will catch -1 to indicate no-op */ + if (ret != -1) ret = where_history (); @@ -143,9 +161,10 @@ noninc_search_from_pos (string, pos, dir) 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) +noninc_dosearch (string, dir, flags) char *string; int dir; + int flags; { int oldpos, pos; HIST_ENTRY *entry; @@ -156,7 +175,7 @@ noninc_dosearch (string, dir) return 0; } - pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir); + pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir, flags, (int *)0); if (pos == -1) { /* Search failed, current history position unchanged. */ @@ -197,6 +216,10 @@ _rl_nsearch_init (dir, pchar) cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0); if (dir < 0) cxt->sflags |= SF_REVERSE; /* not strictly needed */ +#if defined (VI_MODE) + if (VI_COMMAND_MODE() && (pchar == '?' || pchar == '/')) + cxt->sflags |= SF_PATTERN; +#endif cxt->direction = dir; cxt->history_pos = cxt->save_line; @@ -340,7 +363,7 @@ _rl_nsearch_dosearch (cxt) } rl_restore_prompt (); - return (noninc_dosearch (noninc_search_string, cxt->direction)); + return (noninc_dosearch (noninc_search_string, cxt->direction, cxt->sflags&SF_PATTERN)); } /* Search non-interactively through the history list. DIR < 0 means to @@ -400,7 +423,8 @@ rl_noninc_reverse_search (count, key) } /* Search forward through the history list for the last string searched - for. If there is no saved search string, abort. */ + for. If there is no saved search string, abort. If the vi-mode code + calls this, KEY will be `N'. */ int rl_noninc_forward_search_again (count, key) int count, key; @@ -412,12 +436,18 @@ rl_noninc_forward_search_again (count, key) rl_ding (); return (1); } - r = noninc_dosearch (noninc_search_string, 1); +#if defined (VI_MODE) + if (VI_COMMAND_MODE() && key == 'N') + r = noninc_dosearch (noninc_search_string, 1, SF_PATTERN); + else +#endif + r = noninc_dosearch (noninc_search_string, 1, 0); return (r != 1); } /* Reverse search in the history list for the last string searched - for. If there is no saved search string, abort. */ + for. If there is no saved search string, abort. If the vi-mode code + calls this, KEY will be `n'. */ int rl_noninc_reverse_search_again (count, key) int count, key; @@ -429,7 +459,12 @@ rl_noninc_reverse_search_again (count, key) rl_ding (); return (1); } - r = noninc_dosearch (noninc_search_string, -1); +#if defined (VI_MODE) + if (VI_COMMAND_MODE() && key == 'n') + r = noninc_dosearch (noninc_search_string, -1, SF_PATTERN); + else +#endif + r = noninc_dosearch (noninc_search_string, -1, 0); return (r != 1); } @@ -455,7 +490,7 @@ rl_history_search_internal (count, dir) int count, dir; { HIST_ENTRY *temp; - int ret, oldpos; + int ret, oldpos, newcol; char *t; rl_maybe_save_line (); @@ -469,7 +504,7 @@ rl_history_search_internal (count, dir) while (count) { RL_CHECK_SIGNALS (); - ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir); + ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir, 0, &newcol); if (ret == -1) break; @@ -512,12 +547,17 @@ rl_history_search_internal (count, dir) /* Copy the line we found into the current line buffer. */ make_history_line_current (temp); + /* decide where to put rl_point -- need to change this for pattern search */ if (rl_history_search_flags & ANCHORED_SEARCH) rl_point = rl_history_search_len; /* easy case */ else { - t = strstr (rl_line_buffer, history_search_string); +#if 0 + t = strstr (rl_line_buffer, history_search_string); /* XXX */ rl_point = t ? (int)(t - rl_line_buffer) + rl_history_search_len : rl_end; +#else + rl_point = (newcol >= 0) ? newcol : rl_end; +#endif } rl_mark = rl_end; diff --git a/parse.y b/parse.y index 389a5ac0..5742a63a 100644 --- a/parse.y +++ b/parse.y @@ -2977,9 +2977,9 @@ special_case_tokens (tokstr) the designers disagree. */ if (esacs_needed_count) { - esacs_needed_count--; - if (STREQ (tokstr, "esac")) + if (last_read_token == IN && STREQ (tokstr, "esac")) { + esacs_needed_count--; parser_state &= ~PST_CASEPAT; return (ESAC); } diff --git a/pcomplete.c b/pcomplete.c index ac0903a9..7c629890 100644 --- a/pcomplete.c +++ b/pcomplete.c @@ -1243,7 +1243,7 @@ gen_command_matches (cs, cmd, text, line, ind, lwords, nw, cw) } cscmd[cmdlen] = '\0'; - tw = command_substitute (cscmd, 0); + tw = command_substitute (cscmd, 0, 0); csbuf = tw ? tw->word : (char *)NULL; if (tw) dispose_word_desc (tw); diff --git a/subst.c b/subst.c index 7187b3b0..5664ba1c 100644 --- a/subst.c +++ b/subst.c @@ -3715,7 +3715,14 @@ expand_string_assignment (string, quoted) expand_no_split_dollar_star = 1; +#if 0 + /* Other shells (ksh93) do it this way, affects how $@ is expanded in + constructs like bar=${@#0} (preserves the spaces resulting from the + expansion of $@ in a context where you don't do word splitting) */ + td.flags = W_ASSIGNRHS|W_NOSPLIT2; +#else td.flags = W_ASSIGNRHS; +#endif td.word = savestring (string); value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL); FREE (td.word); @@ -6004,8 +6011,13 @@ read_comsub (fd, quoted, rflag) istring = (char *)NULL; istring_index = istring_size = bufn = tflag = 0; +#if 0 for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++) skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL; +#else + skip_ctlesc = ifs_cmap[CTLESC]; + skip_ctlnul = ifs_cmap[CTLNUL]; +#endif nullbyte = 0; @@ -6108,9 +6120,10 @@ read_comsub (fd, quoted, rflag) /* Perform command substitution on STRING. This returns a WORD_DESC * with the contained string possibly quoted. */ WORD_DESC * -command_substitute (string, quoted) +command_substitute (string, quoted, flags) char *string; int quoted; + int flags; { pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid; char *istring, *s; @@ -8925,7 +8938,7 @@ comsub: temp1 = substring (string, *sindex, zindex+1); else { - tdesc = command_substitute (temp, quoted); + tdesc = command_substitute (temp, quoted, pflags&PF_ASSIGNRHS); temp1 = tdesc ? tdesc->word : (char *)NULL; if (tdesc) dispose_word_desc (tdesc); @@ -9459,7 +9472,7 @@ add_string: else { de_backslash (temp); - tword = command_substitute (temp, quoted); + tword = command_substitute (temp, quoted, 0); temp1 = tword ? tword->word : (char *)NULL; if (tword) dispose_word_desc (tword); diff --git a/subst.h b/subst.h index a2a8294e..5b05f968 100644 --- a/subst.h +++ b/subst.h @@ -258,7 +258,7 @@ extern WORD_LIST *expand_words_no_vars __P((WORD_LIST *)); command substitution, arithmetic expansion, and word splitting. */ extern WORD_LIST *expand_words_shellexp __P((WORD_LIST *)); -extern WORD_DESC *command_substitute __P((char *, int)); +extern WORD_DESC *command_substitute __P((char *, int, int)); extern char *pat_subst __P((char *, char *, char *, int)); extern int fifos_pending __P((void)); diff --git a/support/bashbug.sh.in b/support/bashbug.sh.in new file mode 100644 index 00000000..5e92b995 --- /dev/null +++ b/support/bashbug.sh.in @@ -0,0 +1,272 @@ +#!/bin/sh - +# +# bashbug - create a bug report and mail it to the bug address +# +# The bug address depends on the release status of the shell. Versions +# with status `devel', `alpha', `beta', or `rc' mail bug reports to +# chet@cwru.edu and, optionally, to bash-testers@cwru.edu. +# Other versions send mail to bug-bash@gnu.org. +# +# Copyright (C) 1996-2004 Free Software Foundation, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# +# configuration section: +# these variables are filled in by the make target in Makefile +# +MACHINE="@host_cpu@" +OS="@host_os@" +CC="@CC@" +CFLAGS="@CFLAGS@" +RELEASE="@BASHVERS@" +PATCHLEVEL="!PATCHLEVEL!" +RELSTATUS="@RELSTATUS@" +MACHTYPE="@host@" + +PATH=/bin:/usr/bin:/usr/local/bin:$PATH +export PATH + +# Check if TMPDIR is set, default to /tmp +: ${TMPDIR:=/tmp} + +#Securely create a temporary directory for the temporary files +TEMPDIR=$TMPDIR/bbug.$$ +(umask 077 && mkdir $TEMPDIR) || { + echo "$0: could not create temporary directory" >&2 + exit 1 +} + +TEMPFILE1=$TEMPDIR/bbug1 +TEMPFILE2=$TEMPDIR/bbug2 + +USAGE="Usage: $0 [--help] [--version] [bug-report-email-address]" +VERSTR="GNU bashbug, version ${RELEASE}.${PATCHLEVEL}-${RELSTATUS}" + +do_help= do_version= + +while [ $# -gt 0 ]; do + case "$1" in + --help) shift ; do_help=y ;; + --version) shift ; do_version=y ;; + --) shift ; break ;; + -*) echo "bashbug: ${1}: invalid option" >&2 + echo "$USAGE" >&2 + exit 2 ;; + *) break ;; + esac +done + +if [ -n "$do_version" ]; then + echo "${VERSTR}" + exit 0 +fi + +if [ -n "$do_help" ]; then + echo "${VERSTR}" + echo "${USAGE}" + echo + cat << HERE_EOF +Bashbug is used to send mail to the Bash maintainers +for when Bash doesn't behave like you'd like, or expect. + +Bashbug will start up your editor (as defined by the shell's +EDITOR environment variable) with a preformatted bug report +template for you to fill in. The report will be mailed to the +bug-bash mailing list by default. See the manual for details. + +If you invoke bashbug by accident, just quit your editor without +saving any changes to the template, and no bug report will be sent. +HERE_EOF + exit 0 +fi + +# Figure out how to echo a string without a trailing newline +N=`echo 'hi there\c'` +case "$N" in +*c) n=-n c= ;; +*) n= c='\c' ;; +esac + +BASHTESTERS="bash-testers@cwru.edu" + +case "$RELSTATUS" in +alpha*|beta*|devel*|rc*) BUGBASH=chet@cwru.edu ;; +*) BUGBASH=bug-bash@gnu.org ;; +esac + +case "$RELSTATUS" in +alpha*|beta*|devel*|rc*) + echo "$0: This is a testing release. Would you like your bug report" + echo "$0: to be sent to the bash-testers mailing list?" + echo $n "$0: Send to bash-testers? $c" + read ans + case "$ans" in + y*|Y*) BUGBASH="${BUGBASH},${BASHTESTERS}" ;; + esac ;; +esac + +BUGADDR="${1-$BUGBASH}" + +if [ -z "$DEFEDITOR" ] && [ -z "$EDITOR" ]; then + if [ -x /usr/bin/editor ]; then + DEFEDITOR=editor + elif [ -x /usr/local/bin/ce ]; then + DEFEDITOR=ce + elif [ -x /usr/local/bin/emacs ]; then + DEFEDITOR=emacs + elif [ -x /usr/contrib/bin/emacs ]; then + DEFEDITOR=emacs + elif [ -x /usr/bin/emacs ]; then + DEFEDITOR=emacs + elif [ -x /usr/bin/xemacs ]; then + DEFEDITOR=xemacs + elif [ -x /usr/contrib/bin/jove ]; then + DEFEDITOR=jove + elif [ -x /usr/local/bin/jove ]; then + DEFEDITOR=jove + elif [ -x /usr/bin/vi ]; then + DEFEDITOR=vi + else + echo "$0: No default editor found: attempting to use vi" >&2 + DEFEDITOR=vi + fi +fi + + +: ${EDITOR=$DEFEDITOR} + +: ${USER=${LOGNAME-`whoami`}} + +trap 'rm -rf "$TEMPDIR"; exit 1' 1 2 3 13 15 +trap 'rm -rf "$TEMPDIR"' 0 + +UN= +if (uname) >/dev/null 2>&1; then + UN=`uname -a` +fi + +if [ -f /usr/lib/sendmail ] ; then + RMAIL="/usr/lib/sendmail" + SMARGS="-i -t" +elif [ -f /usr/sbin/sendmail ] ; then + RMAIL="/usr/sbin/sendmail" + SMARGS="-i -t" +else + RMAIL=rmail + SMARGS="$BUGADDR" +fi + +INITIAL_SUBJECT='[50 character or so descriptive subject here (for reference)]' + +cat > "$TEMPFILE1" <> $HOME/dead.bashbug + echo "$0: mail to ${BUGADDR} failed: report saved in $HOME/dead.bashbug" >&2 + echo "$0: please send it manually to ${BUGADDR}" >&2 +} + +exit 0