summaryrefslogtreecommitdiff
path: root/app-shells/bash/files
diff options
context:
space:
mode:
Diffstat (limited to 'app-shells/bash/files')
-rw-r--r--app-shells/bash/files/bash-5.2_p32-memory-leaks.patch130
-rw-r--r--app-shells/bash/files/bash-5.2_p32-read-delimiter-in-invalid-mbchar.patch297
-rw-r--r--app-shells/bash/files/bashrc-r117
-rw-r--r--app-shells/bash/files/bashrc.d/10-gentoo-color.bash3
-rw-r--r--app-shells/bash/files/bashrc.d/10-gentoo-title-r1.bash81
-rw-r--r--app-shells/bash/files/bashrc.d/10-gentoo-title.bash68
-rw-r--r--app-shells/bash/files/bashrc.d/15-gentoo-bashrc-check.bash24
7 files changed, 573 insertions, 47 deletions
diff --git a/app-shells/bash/files/bash-5.2_p32-memory-leaks.patch b/app-shells/bash/files/bash-5.2_p32-memory-leaks.patch
new file mode 100644
index 000000000000..0c60e70d3cb5
--- /dev/null
+++ b/app-shells/bash/files/bash-5.2_p32-memory-leaks.patch
@@ -0,0 +1,130 @@
+[Compared to bash-5.2_p26-memory-leaks.patch, this drops a hunk for
+builtins/evalstring.c as the open_redir_file issue is fixed in patch 31
+upstream for bash-5.2]
+
+https://lists.gnu.org/archive/html/bug-bash/2024-01/msg00036.html
+https://lists.gnu.org/archive/html/bug-bash/2024-01/txtm8yNNPR9RQ.txt
+
+For evalstring.c:
+* https://lists.gnu.org/archive/html/bug-bash/2024-01/msg00011.html
+* https://git.savannah.gnu.org/cgit/bash.git/diff/builtins/evalstring.c?h=devel&id=81f7b44564cd1510788035cea7c59631865a7db2&dt=1#n766
+
+From 711ab85262884f2b91f09eceb9aefd0e2426ce67 Mon Sep 17 00:00:00 2001
+From: Grisha Levit <grishalevit@gmail.com>
+Date: Sat, 3 Jun 2023 16:51:26 -0400
+Subject: [PATCH] various leaks
+
+Found mostly by normal usage running a no-bash-malloc build with clang's
+LeakSanitizer enabled. So far seems to provide very accurate results.
+
+* arrayfunc.c
+- quote_compound_array_word: make sure to free VALUE
+- bind_assoc_var_internal: if assigning to a dynamic variable, make sure
+ to free the key (usually assoc_insert would do it)
+
+* bashline.c
+- bash_command_name_stat_hook: free original *NAME if we are going to
+ change what it points to (what the callers seem to expect)
+
+* builtins/evalstring.c
+- parse_and_execute: make sure to dispose of the parsed command
+ resulting from a failed function import attempt
+
+* examples/loadables/stat.c
+- loadstat: bind_assoc_variable does not free its VALUE argument so make
+ sure to do it
+
+* subst.c
+- param_expand: free temp1 value for codepaths that don't do it
+---
+ arrayfunc.c | 6 +++++-
+ bashline.c | 1 +
+ builtins/evalstring.c | 4 ++++
+ examples/loadables/stat.c | 1 +
+ subst.c | 2 ++
+ 5 files changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/arrayfunc.c b/arrayfunc.c
+index 2c05d15b..8ba64084 100644
+--- arrayfunc.c
++++ arrayfunc.c
+@@ -208,7 +208,10 @@ bind_assoc_var_internal (entry, hash, key, value, flags)
+ newval = make_array_variable_value (entry, 0, key, value, flags);
+
+ if (entry->assign_func)
+- (*entry->assign_func) (entry, newval, 0, key);
++ {
++ (*entry->assign_func) (entry, newval, 0, key);
++ FREE (key);
++ }
+ else
+ assoc_insert (hash, key, newval);
+
+@@ -985,6 +988,7 @@ quote_compound_array_word (w, type)
+ if (t != w+ind)
+ free (t);
+ strcpy (nword + i, value);
++ free (value);
+
+ return nword;
+ }
+diff --git a/bashline.c b/bashline.c
+index c85b05b6..bd7548cc 100644
+--- bashline.c
++++ bashline.c
+@@ -1928,6 +1928,7 @@ bash_command_name_stat_hook (name)
+ result = search_for_command (cname, 0);
+ if (result)
+ {
++ FREE (*name);
+ *name = result;
+ return 1;
+ }
+diff --git a/builtins/evalstring.c b/builtins/evalstring.c
+index df3dd68e..20c6a4a7 100644
+--- builtins/evalstring.c
++++ builtins/evalstring.c
+@@ -461,6 +461,8 @@ parse_and_execute (string, from_file, flags)
+ should_jump_to_top_level = 0;
+ last_result = last_command_exit_value = EX_BADUSAGE;
+ set_pipestatus_from_exit (last_command_exit_value);
++ dispose_command(command);
++ global_command = (COMMAND *)NULL;
+ reset_parser ();
+ break;
+ }
+
+diff --git a/examples/loadables/stat.c b/examples/loadables/stat.c
+index 1e60e7b6..ed5c9764 100644
+--- examples/loadables/stat.c
++++ examples/loadables/stat.c
+@@ -349,6 +349,7 @@ loadstat (vname, var, fname, flags, fmt, sp)
+ key = savestring (arraysubs[i]);
+ value = statval (i, fname, flags, fmt, sp);
+ v = bind_assoc_variable (var, vname, key, value, ASS_FORCE);
++ free (value);
+ }
+ return 0;
+ }
+diff --git a/subst.c b/subst.c
+index 1ac6eb2d..ff0602da 100644
+--- subst.c
++++ subst.c
+@@ -10727,6 +10727,7 @@ comsub:
+ {
+ chk_atstar (temp, quoted, pflags, quoted_dollar_at_p, contains_dollar_at);
+ tdesc = parameter_brace_expand_word (temp, SPECIAL_VAR (temp, 0), quoted, pflags, 0);
++ free (temp1);
+ if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
+ return (tdesc);
+ ret = tdesc;
+@@ -10739,6 +10740,7 @@ comsub:
+ {
+ set_exit_status (EXECUTION_FAILURE);
+ report_error (_("%s: invalid variable name for name reference"), temp);
++ free (temp1);
+ return (&expand_wdesc_error); /* XXX */
+ }
+ else
+--
+2.43.0
diff --git a/app-shells/bash/files/bash-5.2_p32-read-delimiter-in-invalid-mbchar.patch b/app-shells/bash/files/bash-5.2_p32-read-delimiter-in-invalid-mbchar.patch
new file mode 100644
index 000000000000..832520c6e7ec
--- /dev/null
+++ b/app-shells/bash/files/bash-5.2_p32-read-delimiter-in-invalid-mbchar.patch
@@ -0,0 +1,297 @@
+From 0432ec33408ac124b620c44416c9c58f0c10b63b Mon Sep 17 00:00:00 2001
+From: Kerin Millar <kfm@plushkava.net>
+Date: Fri, 23 Aug 2024 04:14:36 +0100
+Subject: [PATCH] Backport fix for issue with read delimiter in invalid
+ mutibyte char
+
+This addresses a regression introduced by 5.0. Consider the following
+test case.
+
+for i in {194..245}; do printf -v o %o "$i"; printf "\\$o\\n"; done |
+while read -r; do declare -p REPLY; done
+
+BEFORE
+
+declare -- REPLY=$'\302\n\303\n\304\n\305\n\306\n\307\n\310\n\311\n\312\
+n\313\n\314\n\315\n\316\n\317\n\320\n\321\n\322\n\323\n\324\n\325\n\326\
+n\327\n\330\n\331\n\332\n\333\n\334\n\335\n\336\n\337\n\340\n\341\n\342\
+n\343\n\344\n\345\n\346\n\347\n\350\n\351\n\352\n\353\n\354\n\355\n\356\
+n\357\n\360\n\361\n\362\n\363\n\364\n\365'
+
+AFTER
+
+declare -- REPLY=$'\302'
+declare -- REPLY=$'\303'
+declare -- REPLY=$'\304'
+declare -- REPLY=$'\305'
+declare -- REPLY=$'\306'
+declare -- REPLY=$'\307'
+declare -- REPLY=$'\310'
+declare -- REPLY=$'\311'
+declare -- REPLY=$'\312'
+declare -- REPLY=$'\313'
+declare -- REPLY=$'\314'
+declare -- REPLY=$'\315'
+declare -- REPLY=$'\316'
+declare -- REPLY=$'\317'
+declare -- REPLY=$'\320'
+declare -- REPLY=$'\321'
+declare -- REPLY=$'\322'
+declare -- REPLY=$'\323'
+declare -- REPLY=$'\324'
+declare -- REPLY=$'\325'
+declare -- REPLY=$'\326'
+declare -- REPLY=$'\327'
+declare -- REPLY=$'\330'
+declare -- REPLY=$'\331'
+declare -- REPLY=$'\332'
+declare -- REPLY=$'\333'
+declare -- REPLY=$'\334'
+declare -- REPLY=$'\335'
+declare -- REPLY=$'\336'
+declare -- REPLY=$'\337'
+declare -- REPLY=$'\340'
+declare -- REPLY=$'\341'
+declare -- REPLY=$'\342'
+declare -- REPLY=$'\343'
+declare -- REPLY=$'\344'
+declare -- REPLY=$'\345'
+declare -- REPLY=$'\346'
+declare -- REPLY=$'\347'
+declare -- REPLY=$'\350'
+declare -- REPLY=$'\351'
+declare -- REPLY=$'\352'
+declare -- REPLY=$'\353'
+declare -- REPLY=$'\354'
+declare -- REPLY=$'\355'
+declare -- REPLY=$'\356'
+declare -- REPLY=$'\357'
+declare -- REPLY=$'\360'
+declare -- REPLY=$'\361'
+declare -- REPLY=$'\362'
+declare -- REPLY=$'\363'
+declare -- REPLY=$'\364'
+declare -- REPLY=$'\365'
+
+Signed-off-by: Kerin Millar <kfm@plushkava.net>
+---
+ builtins/read.def | 25 ++++++++++++----
+ externs.h | 1 +
+ lib/sh/zread.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 94 insertions(+), 6 deletions(-)
+
+diff --git builtins/read.def builtins/read.def
+index ddd91d32..53b4bd81 100644
+--- builtins/read.def
++++ builtins/read.def
+@@ -130,7 +130,7 @@ static void set_readline_timeout PARAMS((sh_timer *t, time_t, long));
+ #endif
+ static SHELL_VAR *bind_read_variable PARAMS((char *, char *, int));
+ #if defined (HANDLE_MULTIBYTE)
+-static int read_mbchar PARAMS((int, char *, int, int, int));
++static int read_mbchar PARAMS((int, char *, int, int, int, int));
+ #endif
+ static void ttyrestore PARAMS((struct ttsave *));
+
+@@ -806,7 +806,7 @@ add_char:
+ else
+ # endif
+ if (locale_utf8locale == 0 || ((c & 0x80) != 0))
+- i += read_mbchar (fd, input_string, i, c, unbuffered_read);
++ i += read_mbchar (fd, input_string, i, c, delim, unbuffered_read);
+ }
+ #endif
+
+@@ -1064,10 +1064,10 @@ bind_read_variable (name, value, flags)
+
+ #if defined (HANDLE_MULTIBYTE)
+ static int
+-read_mbchar (fd, string, ind, ch, unbuffered)
++read_mbchar (fd, string, ind, ch, delim, unbuffered)
+ int fd;
+ char *string;
+- int ind, ch, unbuffered;
++ int ind, ch, delim, unbuffered;
+ {
+ char mbchar[MB_LEN_MAX + 1];
+ int i, n, r;
+@@ -1101,8 +1101,21 @@ read_mbchar (fd, string, ind, ch, unbuffered)
+ mbchar[i++] = c;
+ continue;
+ }
+- else if (ret == (size_t)-1 || ret == (size_t)0 || ret > (size_t)0)
+- break;
++ else if (ret == (size_t)-1)
++ {
++ /* If we read a delimiter character that makes this an invalid
++ multibyte character, we can't just add it to the input string
++ and treat it as a byte. We need to push it back so a subsequent
++ zread will pick it up. */
++ if (c == delim)
++ {
++ zungetc (c);
++ mbchar[--i] = '\0'; /* unget the delimiter */
++ }
++ break; /* invalid multibyte character */
++ }
++ else if (ret == (size_t)0 || ret > (size_t)0)
++ break; /* valid multibyte character */
+ }
+
+ mbchar_return:
+diff --git externs.h externs.h
+index 931dba9c..1b70a13b 100644
+--- externs.h
++++ externs.h
+@@ -536,6 +536,7 @@ extern ssize_t zreadintr PARAMS((int, char *, size_t));
+ extern ssize_t zreadc PARAMS((int, char *));
+ extern ssize_t zreadcintr PARAMS((int, char *));
+ extern ssize_t zreadn PARAMS((int, char *, size_t));
++extern int zungetc PARAMS((int));
+ extern void zreset PARAMS((void));
+ extern void zsyncfd PARAMS((int));
+
+diff --git lib/sh/zread.c lib/sh/zread.c
+index dafb7f60..7cfbb288 100644
+--- lib/sh/zread.c
++++ lib/sh/zread.c
+@@ -41,6 +41,10 @@ extern int errno;
+ # define ZBUFSIZ 4096
+ #endif
+
++#ifndef EOF
++# define EOF -1
++#endif
++
+ extern int executing_builtin;
+
+ extern void check_signals_and_traps (void);
+@@ -48,6 +52,11 @@ extern void check_signals (void);
+ extern int signal_is_trapped (int);
+ extern int read_builtin_timeout (int);
+
++int zungetc (int);
++
++/* Provide one character of pushback whether we are using read or zread. */
++static int zpushedchar = -1;
++
+ /* Read LEN bytes from FD into BUF. Retry the read on EINTR. Any other
+ error causes the loop to break. */
+ ssize_t
+@@ -59,6 +68,15 @@ zread (fd, buf, len)
+ ssize_t r;
+
+ check_signals (); /* check for signals before a blocking read */
++
++ /* If we pushed a char back, return it immediately */
++ if (zpushedchar != -1)
++ {
++ *buf = (unsigned char)zpushedchar;
++ zpushedchar = -1;
++ return 1;
++ }
++
+ /* should generalize into a mechanism where different parts of the shell can
+ `register' timeouts and have them checked here. */
+ while (((r = read_builtin_timeout (fd)) < 0 || (r = read (fd, buf, len)) < 0) &&
+@@ -95,6 +113,14 @@ zreadretry (fd, buf, len)
+ ssize_t r;
+ int nintr;
+
++ /* If we pushed a char back, return it immediately */
++ if (zpushedchar != -1)
++ {
++ *buf = (unsigned char)zpushedchar;
++ zpushedchar = -1;
++ return 1;
++ }
++
+ for (nintr = 0; ; )
+ {
+ r = read (fd, buf, len);
+@@ -118,6 +144,15 @@ zreadintr (fd, buf, len)
+ size_t len;
+ {
+ check_signals ();
++
++ /* If we pushed a char back, return it immediately */
++ if (zpushedchar != -1)
++ {
++ *buf = (unsigned char)zpushedchar;
++ zpushedchar = -1;
++ return 1;
++ }
++
+ return (read (fd, buf, len));
+ }
+
+@@ -135,6 +170,14 @@ zreadc (fd, cp)
+ {
+ ssize_t nr;
+
++ /* If we pushed a char back, return it immediately */
++ if (zpushedchar != -1 && cp)
++ {
++ *cp = (unsigned char)zpushedchar;
++ zpushedchar = -1;
++ return 1;
++ }
++
+ if (lind == lused || lused == 0)
+ {
+ nr = zread (fd, lbuf, sizeof (lbuf));
+@@ -160,6 +203,14 @@ zreadcintr (fd, cp)
+ {
+ ssize_t nr;
+
++ /* If we pushed a char back, return it immediately */
++ if (zpushedchar != -1 && cp)
++ {
++ *cp = (unsigned char)zpushedchar;
++ zpushedchar = -1;
++ return 1;
++ }
++
+ if (lind == lused || lused == 0)
+ {
+ nr = zreadintr (fd, lbuf, sizeof (lbuf));
+@@ -186,6 +237,13 @@ zreadn (fd, cp, len)
+ {
+ ssize_t nr;
+
++ if (zpushedchar != -1 && cp)
++ {
++ *cp = zpushedchar;
++ zpushedchar = -1;
++ return 1;
++ }
++
+ if (lind == lused || lused == 0)
+ {
+ if (len > sizeof (lbuf))
+@@ -204,6 +262,22 @@ zreadn (fd, cp, len)
+ return 1;
+ }
+
++int
++zungetc (c)
++ int c;
++{
++ if (zpushedchar == -1)
++ {
++ zpushedchar = c;
++ return c;
++ }
++
++ if (c == EOF || lind == 0)
++ return (EOF);
++ lbuf[--lind] = c; /* XXX */
++ return c;
++}
++
+ void
+ zreset ()
+ {
+--
+2.45.2
+
diff --git a/app-shells/bash/files/bashrc-r1 b/app-shells/bash/files/bashrc-r1
index 6f4631568119..deb0ce97d4a7 100644
--- a/app-shells/bash/files/bashrc-r1
+++ b/app-shells/bash/files/bashrc-r1
@@ -5,16 +5,15 @@ if [[ $- != *i* ]]; then
return
fi
-# A convenient function to determine whether bash has readline support.
-genfun_has_readline() [[ $(shopt -p direxpand 2>/dev/null) ]]
+# Disable errexit in case the user enabled it then chose to re-source this file.
+shopt -u -o errexit
-# The following two shell options require for bash to have readline support.
-genfun_has_readline &&
+# Disable completion when the input buffer is empty. Mute STDERR because this
+# option is only present in the case that bash was built with readline support.
+shopt -s no_empty_cmd_completion 2>/dev/null &&
-# Disable completion when the input buffer is empty.
-shopt -s no_empty_cmd_completion &&
-
-# Append to HISTFILE rather than overwrite upon exiting, per bug #139609.
+# Append to HISTFILE rather than overwrite upon exiting, per bug #139609. This
+# option also requires for bash to have been built with readline support.
shopt -s histappend
# Initialise PROMPT_COMMAND as an array, which is permitted as of bash 5.1.
@@ -28,5 +27,3 @@ for _ in /etc/bash/bashrc.d/*; do
source "$_"
fi
done
-
-unset -f genfun_has_readline
diff --git a/app-shells/bash/files/bashrc.d/10-gentoo-color.bash b/app-shells/bash/files/bashrc.d/10-gentoo-color.bash
index 6192bfaf4394..f0c5983b66e1 100644
--- a/app-shells/bash/files/bashrc.d/10-gentoo-color.bash
+++ b/app-shells/bash/files/bashrc.d/10-gentoo-color.bash
@@ -34,7 +34,8 @@ elif (( gentoo_color == 16777216 )); then
export COLORTERM=truecolor
fi
-if (( gentoo_color <= 0 )) || ! genfun_has_readline; then
+# For direxpand to be missing indicates that bash is lacking readline support.
+if (( gentoo_color <= 0 )) || [[ ! $(shopt -p direxpand 2>/dev/null) ]]; then
# Define a prompt without color.
PS1='\u@\h \w \$ '
elif (( EUID == 0 )); then
diff --git a/app-shells/bash/files/bashrc.d/10-gentoo-title-r1.bash b/app-shells/bash/files/bashrc.d/10-gentoo-title-r1.bash
new file mode 100644
index 000000000000..8e78b09a9daf
--- /dev/null
+++ b/app-shells/bash/files/bashrc.d/10-gentoo-title-r1.bash
@@ -0,0 +1,81 @@
+# /etc/bash/bashrc.d/10-gentoo-title.bash
+
+# For information regarding the control sequences used, please refer to
+# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html.
+
+genfun_set_win_title() {
+ # Advertise the fact that the presently running interactive shell will
+ # update the title. Doing so allows for its subprocesses to determine
+ # whether it is safe to set the title of their own accord. Note that 0
+ # refers to the value of Ps within the OSC Ps ; Pt BEL sequence.
+ export SHELL_SETS_TITLE=0
+
+ # Assigns the basename of the current working directory, having
+ # sanitised it with @Q parameter expansion. Useful for paths containing
+ # newlines and such. As a special case, names consisting entirely of
+ # graphemes shall not undergo the expansion, for reasons of cleanliness.
+ genfun_sanitise_cwd() {
+ _cwd=${PWD##*/}
+ if [[ ! ${_cwd} ]]; then
+ _cwd=${PWD}
+ elif [[ ${_cwd} == *[![:graph:]]* ]]; then
+ _cwd=${_cwd@Q}
+ fi
+ }
+
+ # Sets the window title with the Set Text Parameters control sequence.
+ # For screen, the sequence defines the hardstatus (%h) and for tmux, the
+ # pane_title (#T). For graphical terminal emulators, it is normal for
+ # the title bar to be affected.
+ genfun_set_win_title() {
+ genfun_sanitise_cwd
+ printf '\033]0;%s@%s - %s\007' "${USER}" "${HOSTNAME%%.*}" "${_cwd}"
+ }
+
+ genfun_set_win_title
+}
+
+unset -v SHELL_SETS_TITLE
+
+# Determine whether the terminal can handle the Set Text Parameters sequence.
+# The only terminals permitted here are those for which there is empirical
+# evidence that the sequence is supported and that the UTF-8 character encoding
+# is handled correctly. Quite rightly, this precludes many vintage terminals.
+case ${TERM} in
+ alacritty|foot*|tmux*)
+ # The terminal emulator also supports XTWINOPS. If the PTY was
+ # created by sshd(8) then push the current window title to the
+ # stack and arrange for it to be popped upon exiting. Xterm also
+ # supports this but there are far too many terminal emulators
+ # that falsely identify as being xterm-compatible.
+ if [[ ${SSH_TTY} && ${SSH_TTY} == "$(tty)" ]]; then
+ trap 'printf "\033[23;0t"' EXIT
+ printf '\033[22;0t'
+ fi
+ ;;
+ rxvt-unicode*|st-256color|xterm*)
+ # If the PTY was created by sshd(8) then proceed no further.
+ # Alas, there exist many operating environments in which the
+ # title would otherwise not be restored upon ssh(1) exiting.
+ # Those wanting for the title to be set regardless may adjust
+ # ~/.bashrc or create a bashrc.d drop-in to set PROMPT_COMMAND.
+ # For example, PROMPT_COMMAND=(genfun_set_win_title).
+ if [[ ${SSH_TTY} && ${SSH_TTY} == "$(tty)" ]]; then
+ return
+ fi
+ ;;
+ screen*)
+ # If the PTY was created by sshd(8) and screen(1) was launched
+ # prior to the SSH session beginning, as opposed to afterwards,
+ # proceed no further. It is another case in which there would be
+ # no guarantee of the title being restored upon ssh(1) exiting.
+ if [[ ! ${WINDOW} && ${SSH_TTY} && ${SSH_TTY} == "$(tty)" ]]; then
+ return
+ fi
+ ;;
+ *)
+ return
+esac
+
+# Arrange for the title to be updated each time the primary prompt is displayed.
+PROMPT_COMMAND+=('genfun_set_win_title')
diff --git a/app-shells/bash/files/bashrc.d/10-gentoo-title.bash b/app-shells/bash/files/bashrc.d/10-gentoo-title.bash
index 1fbf17c26327..2b2e23347784 100644
--- a/app-shells/bash/files/bashrc.d/10-gentoo-title.bash
+++ b/app-shells/bash/files/bashrc.d/10-gentoo-title.bash
@@ -1,41 +1,41 @@
# /etc/bash/bashrc.d/10-gentoo-title.bash
-# Set window title with the Title Definition String sequence. For screen, the
-# sequence defines the window title (%t) and for tmux, the pane_title (#T).
-# For tmux to be affected requires that its allow-rename option be enabled.
-# https://www.gnu.org/software/screen/manual/html_node/Control-Sequences.html
-case ${TERM} in
- screen*|tmux*)
- genfun_set_pane_title() {
- printf '\033k%s\033\\' "${HOSTNAME%%.*}"
- }
- PROMPT_COMMAND+=('genfun_set_pane_title')
- ;;
- *)
- # If the TTY is that of sshd(8) then proceed no further. Alas,
- # there exist many operating environments in which the window
- # title would otherwise not be restored upon ssh(1) exiting.
- if [[ ${SSH_TTY} && ${SSH_TTY} == "$(tty)" ]]; then
- return
+genfun_set_win_title() {
+ # Assigns the basename of the current working directory, having
+ # sanitised it with @Q parameter expansion. Useful for paths containing
+ # newlines and such. As a special case, names consisting entirely of
+ # graphemes shall not undergo the expansion, for reasons of cleanliness.
+ genfun_sanitise_cwd() {
+ _cwd=${PWD##*/}
+ if [[ ! ${_cwd} ]]; then
+ _cwd=${PWD}
+ elif [[ ${_cwd} == *[![:graph:]]* ]]; then
+ _cwd=${_cwd@Q}
fi
-esac
+ }
-# Assigns the basename of the current working directory, having sanitised it
-# with @Q parameter expansion. Useful for paths containing newlines and such.
-# As a special case, names consisting entirely of graphemes shall not undergo
-# the parameter expansion, for reasons of cleanliness.
-genfun_sanitise_cwd() {
- _cwd=${PWD##*/}
- if [[ ! ${_cwd} ]]; then
- _cwd=${PWD}
- elif [[ ${_cwd} == *[![:graph:]]* ]]; then
- _cwd=${_cwd@Q}
- fi
+ # Sets the window title with the Set Text Parameters sequence. For
+ # screen, the sequence defines the hardstatus (%h) and for tmux, the
+ # pane_title (#T). For graphical terminal emulators, it is normal for
+ # the title bar to be affected.
+ genfun_set_win_title() {
+ genfun_sanitise_cwd
+ printf '\033]0;%s@%s - %s\007' "${USER}" "${HOSTNAME%%.*}" "${_cwd}"
+ }
+
+ genfun_set_win_title
}
-# Set window title with the Set Text Parameters sequence. For screen, the
-# sequence defines the hardstatus (%h) and for tmux, the window_name (#W).
-# For graphical terminal emulators, it is normal for the title bar be affected.
+# Proceed no further if the TTY is that of sshd(8) and if not running a terminal
+# multiplexer. Alas, there exist many operating environments in which the window
+# title would otherwise not be restored upon ssh(1) exiting. Those who wish for
+# the title to be set unconditionally may adjust ~/.bashrc - or create a custom
+# bashrc.d drop-in - to define PROMPT_COMMAND=(genfun_set_win_title).
+if [[ ${SSH_TTY} && ${TERM} != @(screen|tmux)* && ${SSH_TTY} == "$(tty)" ]]; then
+ return
+fi
+
+# Determine whether the terminal can handle the Set Text Parameters sequence.
# The only terminals permitted here are those for which there is empirical
# evidence that the sequence is supported and that the UTF-8 character encoding
# is handled correctly. Quite rightly, this precludes many vintage terminals.
@@ -48,9 +48,5 @@ case ${TERM} in
st-256color |\
tmux* |\
xterm* )
- genfun_set_win_title() {
- genfun_sanitise_cwd
- printf '\033]2;%s@%s - %s\007' "${USER}" "${HOSTNAME%%.*}" "${_cwd}"
- }
PROMPT_COMMAND+=('genfun_set_win_title')
esac
diff --git a/app-shells/bash/files/bashrc.d/15-gentoo-bashrc-check.bash b/app-shells/bash/files/bashrc.d/15-gentoo-bashrc-check.bash
new file mode 100644
index 000000000000..8f2b0405c6b9
--- /dev/null
+++ b/app-shells/bash/files/bashrc.d/15-gentoo-bashrc-check.bash
@@ -0,0 +1,24 @@
+# /etc/bash/bashrc.d/15-gentoo-bashrc-check.bash
+
+# Some users have ~/.bashrc as a copy of ${FILESDIR}/bashrc which either matches
+# exactly or is only trivially modified. Such is an improper state of affairs
+# and results in the bashrc.d drop-ins being sourced twice. Warn them that they
+# should use the skeleton file instead. This drop-in should be removed no sooner
+# than one year from the date of its introduction.
+
+if [[ -e ${TMPDIR:-/tmp}/.gentoo-bashrc-check-${EUID} || ! -f ~/.bashrc ]]; then
+ return
+fi
+
+{
+ if grep -qxF 'for sh in /etc/bash/bashrc.d/* ; do' -- ~/.bashrc; then
+ cat >&3 <<'EOF'
+WARNING! Your ~/.bashrc file is based on an old copy of /etc/bash/bashrc, which
+is not intended for use within a home directory. Please either delete ~/.bashrc
+or replace it with a copy of /etc/skel/.bashrc before optionally customizing it
+further. Neglecting to do so may result in bash behaving unexpectedly.
+
+EOF
+ fi
+ touch -- "${TMPDIR:-/tmp}/.gentoo-bashrc-check-${EUID}"
+} 3>&2 2>/dev/null