commit bash-20161118 snapshot

This commit is contained in:
Chet Ramey
2016-11-21 14:50:59 -05:00
parent 5c1f20964a
commit 31a8d95a37
14 changed files with 530 additions and 34 deletions
+69
View File
@@ -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 <jwdevel@gmail.com>
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 <izaberina@gmail.com>
11/20
-----
builtins/common.c
- display_signal_list: make `kill -l 0' print `EXIT', modifying change
from 9/17
+1
View File
@@ -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
+2 -2
View File
@@ -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
{
+3 -1
View File
@@ -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)
+3
View File
@@ -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
+8 -2
View File
@@ -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_ */
+94 -5
View File
@@ -39,8 +39,13 @@
# include <unistd.h>
#endif
#if defined (HAVE_FNMATCH)
# include <fnmatch.h>
#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)
+1
View File
@@ -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
{
+57 -17
View File
@@ -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;
+2 -2
View File
@@ -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);
}
+1 -1
View File
@@ -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);
+16 -3
View File
@@ -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);
+1 -1
View File
@@ -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));
+272
View File
@@ -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 <http://www.gnu.org/licenses/>.
#
# 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" <<EOF
From: ${USER}
To: ${BUGADDR}
Subject: ${INITIAL_SUBJECT}
Configuration Information [Automatically generated, do not change]:
Machine: $MACHINE
OS: $OS
Compiler: $CC
Compilation CFLAGS: $CFLAGS
uname output: $UN
Machine Type: $MACHTYPE
Bash Version: $RELEASE
Patch Level: $PATCHLEVEL
Release Status: $RELSTATUS
Description:
[Detailed description of the problem, suggestion, or complaint.]
Repeat-By:
[Describe the sequence of events that causes the problem
to occur.]
Fix:
[Description of how to fix the problem. If you don't know a
fix for the problem, don't include this section.]
EOF
cp "$TEMPFILE1" "$TEMPFILE2"
chmod u+w "$TEMPFILE1"
trap '' 2 # ignore interrupts while in editor
edstat=1
while [ $edstat -ne 0 ]; do
$EDITOR "$TEMPFILE1"
edstat=$?
if [ $edstat -ne 0 ]; then
echo "$0: editor \`$EDITOR' exited with nonzero status."
echo "$0: Perhaps it was interrupted."
echo "$0: Type \`y' to give up, and lose your bug report;"
echo "$0: type \`n' to re-enter the editor."
echo $n "$0: Do you want to give up? $c"
read ans
case "$ans" in
[Yy]*) exit 1 ;;
esac
continue
fi
# find the subject from the temp file and see if it's been changed
CURR_SUB=`grep '^Subject: ' "$TEMPFILE1" | sed 's|^Subject:[ ]*||' | sed 1q`
case "$CURR_SUB" in
"${INITIAL_SUBJECT}")
echo
echo "$0: You have not changed the subject from the default."
echo "$0: Please use a more descriptive subject header."
echo "$0: Type \`y' to give up, and lose your bug report;"
echo "$0: type \`n' to re-enter the editor."
echo $n "$0: Do you want to give up? $c"
read ans
case "$ans" in
[Yy]*) exit 1 ;;
esac
echo "$0: The editor will be restarted in five seconds."
sleep 5
edstat=1
;;
esac
done
trap 'rm -rf "$TEMPDIR"; exit 1' 2 # restore trap on SIGINT
if cmp -s "$TEMPFILE1" "$TEMPFILE2"
then
echo "File not changed, no bug report submitted."
exit
fi
echo $n "Send bug report to ${BUGADDR}? [y/n] $c"
read ans
case "$ans" in
[Nn]*) exit 0 ;;
esac
${RMAIL} $SMARGS < "$TEMPFILE1" || {
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