Skip to content

Instantly share code, notes, and snippets.

@skull-squadron
Last active July 20, 2025 03:31
Show Gist options
  • Save skull-squadron/ef6ff349cae0167733fefb32d844705a to your computer and use it in GitHub Desktop.
Save skull-squadron/ef6ff349cae0167733fefb32d844705a to your computer and use it in GitHub Desktop.
Bash 5.3 XDG patch
diff -ur a/bashhist.c b/bashhist.c
--- a/bashhist.c 2024-05-06 15:38:27.000000000 +0000
+++ b/bashhist.c 2025-07-20 03:02:01.549901005 +0000
@@ -419,7 +419,7 @@
char *
bash_default_histfile (void)
{
- return (bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history", 0));
+ return find_bash_user_file(posixly_correct ? "sh_history" : "bash_history", "XDG_STATE_HOME", "~/.local/state");
}
#ifdef INCLUDE_UNUSED
diff -ur a/builtins/exit.def b/builtins/exit.def
--- a/builtins/exit.def 2024-10-25 15:06:36.000000000 +0000
+++ b/builtins/exit.def 2025-07-20 02:53:45.342481012 +0000
@@ -159,7 +159,16 @@
/* Run our `~/.bash_logout' file if it exists, and this is a login shell. */
if (login_shell && sourced_logout++ == 0 && subshell_environment == 0)
{
- maybe_execute_file ("~/.bash_logout", 1);
+ if (maybe_execute_file ("~/.bash_logout", 1) == 0) {
+ char *cfg_env = get_string_value ("XDG_CONFIG_HOME");
+ char *xdg_path = malloc (strlen (cfg_env && cfg_env[0] == '/'
+ ? cfg_env : "~/.config") + strlen ("/bash/bash_logout"));
+
+ strcpy (xdg_path, cfg_env ? cfg_env : "~/.config");
+ strcat (xdg_path, "/bash/bash_logout");
+
+ maybe_execute_file (xdg_path, 1);
+ }
#ifdef SYS_BASH_LOGOUT
maybe_execute_file (SYS_BASH_LOGOUT, 1);
#endif
diff -ur a/config-top.h b/config-top.h
--- a/config-top.h 2024-10-24 18:14:21.000000000 +0000
+++ b/config-top.h 2025-07-20 02:53:45.342481012 +0000
@@ -88,9 +88,6 @@
reply to the select query is an empty line. */
#define KSH_COMPATIBLE_SELECT
-/* Default interactive shell startup file. */
-#define DEFAULT_BASHRC "~/.bashrc"
-
/* System-wide .bashrc file for interactive shells. */
/* #define SYS_BASHRC "/etc/bash.bashrc" */
diff -ur a/shell.c b/shell.c
--- a/shell.c 2025-03-26 20:40:19.000000000 +0000
+++ b/shell.c 2025-07-20 03:09:11.670770010 +0000
@@ -105,6 +105,10 @@
extern char **environ; /* used if no third argument to main() */
#endif
+#if !HAVE_ASPRINTF
+extern int asprintf PARAMS((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
+#endif
+
extern int gnu_error_format;
/* Non-zero means that this shell has already been run; i.e. you should
@@ -326,6 +330,8 @@
static void execute_env_file (char *);
static void execute_profile_file (void);
static void execute_bashrc_file (void);
+static int find_bash_config_file(const char *);
+static void init_bashrc_file (void);
static void run_startup_files (void);
static int open_shell_script (char *);
static void set_bash_input (void);
@@ -1121,11 +1127,49 @@
if (act_like_sh) /* sh */
maybe_execute_file ("~/.profile", 1);
- else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) &&
- (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */
+ else if ((find_bash_config_file ("bash_profile") == 0) &&
+ (find_bash_config_file ("bash_login") == 0)) /* bash */
maybe_execute_file ("~/.profile", 1);
}
+char *
+find_bash_user_file (fname, xdgvar, xdgdef)
+ const char *fname, *xdgvar, *xdgdef;
+{
+ struct stat sb;
+ char *legacy_path, *xdg_path, *cfg_env;
+ int len;
+
+ len = asprintf(&legacy_path, "~/.%s", fname);
+ legacy_path = bash_tilde_expand (legacy_path, 0);
+
+ if (stat (legacy_path, &sb)) {
+ cfg_env = get_string_value (xdgvar);
+ xdgdef = bash_tilde_expand (xdgdef, 0);
+ len = asprintf(&xdg_path, "%s/bash/%s", cfg_env && cfg_env[0] == '/'
+ ? cfg_env : xdgdef, fname);
+ return stat (xdg_path, &sb) ? legacy_path : xdg_path;
+ } else
+ return legacy_path;
+}
+
+static int
+find_bash_config_file (fname)
+ const char *fname;
+{
+ return maybe_execute_file (find_bash_user_file
+ (fname, "XDG_CONFIG_HOME", "~/.config"), 1);
+}
+
+static void
+init_bashrc_file ()
+{
+ if (!bashrc_file)
+ bashrc_file = get_string_value ("BASHRC") ?
+ get_string_value ("BASHRC") : find_bash_user_file ("bashrc",
+ "XDG_CONFIG_HOME", "~/.config");
+}
+
static void
execute_bashrc_file (void)
{
@@ -1137,10 +1181,7 @@
# endif
#endif
- if (bashrc_file)
- maybe_execute_file (bashrc_file, 1);
- else
- maybe_execute_file (DEFAULT_BASHRC, 1);
+ maybe_execute_file (bashrc_file, 1);
}
static void
@@ -1151,6 +1192,9 @@
#endif
int sourced_login, run_by_ssh;
+ /* Initialise bashrc_file to be run when in interactive mode */
+ init_bashrc_file ();
+
/* TAG:bash-5.3 [email protected] 2/21/2022 */
/* get the rshd/sshd case out of the way first. */
if (interactive_shell == 0 && no_rc == 0 && login_shell == 0 &&
diff -ur a/shell.h b/shell.h
--- a/shell.h 2024-10-26 17:03:04.000000000 +0000
+++ b/shell.h 2025-07-20 02:53:45.345481012 +0000
@@ -237,6 +237,8 @@
#endif
} sh_input_line_state_t;
+char *find_bash_user_file PARAMS((const char *, const char *, const char *));
+
/* Let's try declaring these here. */
extern void shell_ungets (char *);
extern void rewind_input_string (void);
diff -ur a/variables.c b/variables.c
--- a/variables.c 2025-06-25 19:48:04.000000000 +0000
+++ b/variables.c 2025-07-20 02:53:45.347481012 +0000
@@ -638,6 +638,9 @@
if (command_execution_string)
bind_variable ("BASH_EXECUTION_STRING", command_execution_string, 0);
+ if (interactive_shell)
+ set_if_not ("BASHRC", find_bash_user_file ("bashrc", "XDG_CONFIG_HOME", "~/.config"));
+
/* Find out if we're supposed to be in Posix.2 mode via an
environment variable. */
temp_var = find_variable ("POSIXLY_CORRECT");
@skull-squadron
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment