From 7469a9542f6f51045c44b17aed0bdea579c44d06 Mon Sep 17 00:00:00 2001
From: 90 <hi@90.gripe>
Date: Sat, 20 Jan 2024 22:36:31 +0000
Subject: [PATCH] Add XDG Base Directory compliance for Bash startup files

---
 builtins/exit.def | 11 +++++++++-
 shell.c           | 51 +++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 55 insertions(+), 7 deletions(-)

diff --git a/builtins/exit.def b/builtins/exit.def
index 9c85bc58..46f049ec 100644
--- a/builtins/exit.def
+++ b/builtins/exit.def
@@ -161,7 +161,16 @@ bash_logout ()
   /* 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 : "~/.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 --git a/shell.c b/shell.c
index ebd89651..7e614b3f 100644
--- a/shell.c
+++ b/shell.c
@@ -320,6 +320,8 @@ static void add_shopt_to_alist PARAMS((char *, int));
 static void run_shopt_alist PARAMS((void));
 
 static void execute_env_file PARAMS((char *));
+static int find_bash_startup_file PARAMS((char *));
+static void run_bashrc_file PARAMS((void));
 static void run_startup_files PARAMS((void));
 static int open_shell_script PARAMS((char *));
 static void set_bash_input PARAMS((void));
@@ -1120,6 +1122,43 @@ execute_env_file (env_file)
     }
 }
 
+static int
+find_bash_startup_file (fname)
+      const char *fname;
+{
+  char *legacy_path, *xdg_path, *cfg_env;
+  int found_legacy, found_xdg;
+
+  legacy_path = malloc (strlen ("~/.") + strlen (fname));
+  strcpy (legacy_path, "~/.");
+  strcat (legacy_path, fname);
+  found_legacy = maybe_execute_file (legacy_path, 1);
+
+  if (found_legacy == 0) {
+    cfg_env = get_string_value ("XDG_CONFIG_HOME");
+    xdg_path = malloc (strlen (cfg_env ? cfg_env : "~/.config")
+        + strlen ("/bash/") + strlen (fname));
+
+    strcpy (xdg_path, cfg_env ? cfg_env : "~/.config");
+    strcat (xdg_path, "/bash/");
+    strcat (xdg_path, fname);
+
+    return maybe_execute_file (xdg_path, 1);
+  } else {
+    return found_legacy;
+  }
+}
+
+static void
+run_bashrc_file ()
+{
+  if (bashrc_file == DEFAULT_BASHRC && maybe_execute_file (bashrc_file, 1) == 0) {
+    find_bash_startup_file ("bashrc");
+  } else {
+    maybe_execute_file (bashrc_file, 1);
+  }
+}
+
 static void
 run_startup_files ()
 {
@@ -1156,7 +1195,7 @@ run_startup_files ()
 	  maybe_execute_file (SYS_BASHRC, 1);
 #  endif
 #endif
-	  maybe_execute_file (bashrc_file, 1);
+	  run_bashrc_file ();
 	  return;
 	}
     }
@@ -1189,8 +1228,8 @@ run_startup_files ()
 
 	  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_startup_file ("bash_profile") == 0) &&
+		   (find_bash_startup_file ("bash_login") == 0))	/* bash */
 	    maybe_execute_file ("~/.profile", 1);
 	}
 
@@ -1225,8 +1264,8 @@ run_startup_files ()
 
 	      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_startup_file ("bash_profile") == 0) &&
+		       (find_bash_startup_file ("bash_login") == 0))	/* bash */
 		maybe_execute_file ("~/.profile", 1);
 	    }
 	}
@@ -1241,7 +1280,7 @@ run_startup_files ()
 	  maybe_execute_file (SYS_BASHRC, 1);
 #  endif
 #endif
-	  maybe_execute_file (bashrc_file, 1);
+	  run_bashrc_file ();
 	}
       /* sh */
       else if (act_like_sh && privileged_mode == 0 && sourced_env++ == 0)
-- 
2.43.0

