gdb: use get_standard_config_dir when looking for .gdbinit
authorAndrew Burgess <andrew.burgess@embecosm.com>
Fri, 25 Sep 2020 13:50:56 +0000 (14:50 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Mon, 2 Nov 2020 17:42:11 +0000 (17:42 +0000)
This commit effectively changes the default location of the .gdbinit
file, while maintaining backward compatibility.

For non Apple hosts the .gdbinit file will now be looked for in the
following locations:

  $XDG_CONFIG_HOME/gdb/gdbinit
  $HOME/.config/gdb/gdbinit
  $HOME/.gdbinit

On Apple hosts the search order is instead:

  $HOME/Library/Preferences/gdb/gdbinit
  $HOME/.gdbinit

I've performed an extensive rewrite of the documentation, moving all
information about initialization files and where to find them into a
new @node, text from other areas has been moved into this one
location, and other areas cross-reference to this new @node as much as
possible.

gdb/ChangeLog:

* NEWS: Mention changes to config file search path.
* main.c

gdb/doc/ChangeLog:

* gdb.texinfo (Mode Options): Descriptions of initialization files
has been moved to 'Initialization Files'.
(Startup): Likewise.
(Initialization Files): New node.
(gdb man): Update to mention alternative file paths.
(gdbinit man): Likewise.

gdb/ChangeLog
gdb/NEWS
gdb/auto-load.c
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/main.c
gdbsupport/pathstuff.cc
gdbsupport/pathstuff.h

index 4528b853ecda1a06eb4611f8329754394fa93814..18b7fb0a53a34edde270c3bd9caedcfcec8cee8e 100644 (file)
@@ -1,3 +1,8 @@
+2020-11-02  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * NEWS: Mention changes to config file search path.
+       * main.c
+
 2020-11-02  Tom Tromey  <tromey@adacore.com>
 
        * python/python.c: Consolidate two HAVE_PYTHON blocks.
index c99d3181a8bc792c2e9126b44576ee6af8a82c21..3e08aee7c6fe012ac3bebd7a3bb6fbe0d9649a78 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
 
 * GDB now supports core file debugging for x86_64 Cygwin programs.
 
+* GDB will now look for the .gdbinit file in a config directory before
+  looking for ~/.gdbinit.  The file is searched for in the following
+  locations: $XDG_CONFIG_HOME/gdb/gdbinit, $HOME/.config/gdb/gdbinit,
+  $HOME/.gdbinit.  On Apple hosts the search order is instead:
+  $HOME/Library/Preferences/gdb/gdbinit, $HOME/.gdbinit.
+
 * New commands
 
 set debug event-loop
index 71f0ecda7a766432b5dd49d624004769f9c62083..79011dbeb24505b9e74275ee6abaf759b5ca3241 100644 (file)
@@ -498,11 +498,26 @@ file_is_auto_load_safe (const char *filename, const char *debug_fmt, ...)
 
   if (!advice_printed)
     {
-      const char *homedir = getenv ("HOME");
-
-      if (homedir == NULL)
-       homedir = "$HOME";
-      std::string homeinit = string_printf ("%s/%s", homedir, GDBINIT);
+      /* Find the existing home directory config file.  */
+      struct stat buf;
+      std::string home_config = find_gdb_home_config_file (GDBINIT, &buf);
+      if (home_config.empty ())
+       {
+         /* The user doesn't have an existing home directory config file,
+            so we should suggest a suitable path for them to use.  */
+         std::string config_dir_file
+           = get_standard_config_filename (GDBINIT);
+         if (!config_dir_file.empty ())
+           home_config = config_dir_file;
+         else
+           {
+             const char *homedir = getenv ("HOME");
+             if (homedir == nullptr)
+               homedir = "$HOME";
+             home_config = (std::string (homedir) + SLASH_STRING
+                            + std::string (GDBINIT));
+           }
+       }
 
       printf_filtered (_("\
 To enable execution of this file add\n\
@@ -515,7 +530,7 @@ For more information about this security protection see the\n\
 \"Auto-loading safe path\" section in the GDB manual.  E.g., run from the shell:\n\
 \tinfo \"(gdb)Auto-loading safe path\"\n"),
                       filename_real.get (),
-                      homeinit.c_str (), homeinit.c_str ());
+                      home_config.c_str (), home_config.c_str ());
       advice_printed = 1;
     }
 
index b8a4429b6613edb73a1c4cb93274f0615164a921..a57a36a4844050f8b733ab1a689185e64ab01e05 100644 (file)
@@ -1,3 +1,12 @@
+2020-11-02  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.texinfo (Mode Options): Descriptions of initialization files
+       has been moved to 'Initialization Files'.
+       (Startup): Likewise.
+       (Initialization Files): New node.
+       (gdb man): Update to mention alternative file paths.
+       (gdbinit man): Likewise.
+
 2020-10-27  Tankut Baris Aktemur  <tankut.baris.aktemur@intel.com>
 
        * gdb.texinfo (Set Breaks): Document the '-force-condition' flag
index d779d4a84f1d890f0639143f34eac5311a366b45..52701560006a330e9ea2c7fef5aad717e10a0682 100644 (file)
@@ -937,6 +937,7 @@ in sequential order.  The order makes a difference when the
 * File Options::                Choosing files
 * Mode Options::                Choosing modes
 * Startup::                     What @value{GDBN} does during startup
+* Initialization Files::        Initialization Files
 @end menu
 
 @node File Options
@@ -1077,47 +1078,16 @@ batch mode or quiet mode.
 @itemx -n
 @cindex @code{--nx}
 @cindex @code{-n}
-Do not execute commands found in any initialization file.
-There are three init files, loaded in the following order:
-
-@table @code
-@item @file{system.gdbinit}
-This is the system-wide init file.
-Its location is specified with the @code{--with-system-gdbinit}
-configure option (@pxref{System-wide configuration}).
-It is loaded first when @value{GDBN} starts, before command line options
-have been processed.
-@item @file{system.gdbinit.d}
-This is the system-wide init directory.
-Its location is specified with the @code{--with-system-gdbinit-dir}
-configure option (@pxref{System-wide configuration}).
-Files in this directory are loaded in alphabetical order immediately after
-system.gdbinit (if enabled) when @value{GDBN} starts, before command line
-options have been processed.  Files need to have a recognized scripting
-language extension (@file{.py}/@file{.scm}) or be named with a @file{.gdb}
-extension to be interpreted as regular @value{GDBN} commands.  @value{GDBN}
-will not recurse into any subdirectories of this directory.
-@item @file{~/.gdbinit}
-This is the init file in your home directory.
-It is loaded next, after @file{system.gdbinit}, and before
-command options have been processed.
-@item @file{./.gdbinit}
-This is the init file in the current directory.
-It is loaded last, after command line options other than @code{-x} and
-@code{-ex} have been processed.  Command line options @code{-x} and
-@code{-ex} are processed last, after @file{./.gdbinit} has been loaded.
-@end table
-
-For further documentation on startup processing, @xref{Startup}.
-For documentation on how to write command files,
-@xref{Command Files,,Command Files}.
+Do not execute commands found in any initialization files
+(@pxref{Initialization Files}).
 
 @anchor{-nh}
 @item -nh
 @cindex @code{--nh}
-Do not execute commands found in @file{~/.gdbinit}, the init file
-in your home directory.
-@xref{Startup}.
+Do not execute commands found in any home directory initialization
+file (@pxref{Initialization Files,,Home directory initialization
+file}).  The system wide and current directory initialization files
+are still loaded.
 
 @item -quiet
 @itemx -silent
@@ -1327,20 +1297,13 @@ Sets up the command interpreter as specified by the command line
 
 @item
 @cindex init file
-Reads the system-wide @dfn{init file} (if @option{--with-system-gdbinit} was
-used when building @value{GDBN}; @pxref{System-wide configuration,
- ,System-wide configuration and settings}) and the files in the system-wide
-gdbinit directory (if @option{--with-system-gdbinit-dir} was used) and executes
-all the commands in those files.  The files need to be named with a @file{.gdb}
-extension to be interpreted as @value{GDBN} commands, or they can be written
-in a supported scripting language with an appropriate file extension.
+Reads the system wide initialization file and the files from the
+system wide initialization directory, @pxref{System Wide Init Files}.
 
-@anchor{Home Directory Init File}
 @item
-Reads the init file (if any) in your home directory@footnote{On
-DOS/Windows systems, the home directory is the one pointed to by the
-@code{HOME} environment variable.} and executes all the commands in
-that file.
+Reads the initialization file (if any) in your home directory and
+executes all the commands in that file, @pxref{Home Directory Init
+File}.
 
 @anchor{Option -init-eval-command}
 @item
@@ -1353,16 +1316,16 @@ gets loaded.
 @item
 Processes command line options and operands.
 
-@anchor{Init File in the Current Directory during Startup}
 @item
-Reads and executes the commands from init file (if any) in the current
-working directory as long as @samp{set auto-load local-gdbinit} is set to
-@samp{on} (@pxref{Init File in the Current Directory}).
-This is only done if the current directory is
-different from your home directory.  Thus, you can have more than one
-init file, one generic in your home directory, and another, specific
-to the program you are debugging, in the directory where you invoke
-@value{GDBN}.
+Reads and executes the commands from the initialization file (if any)
+in the current working directory as long as @samp{set auto-load
+local-gdbinit} is set to @samp{on} (@pxref{Init File in the Current
+Directory}).  This is only done if the current directory is different
+from your home directory.  Thus, you can have more than one init file,
+one generic in your home directory, and another, specific to the
+program you are debugging, in the directory where you invoke
+@value{GDBN}. @xref{Init File in the Current Directory during
+Startup}.
 
 @item
 If the command line specified a program to debug, or a process to
@@ -1391,26 +1354,115 @@ Reads the command history recorded in the @dfn{history file}.
 files where @value{GDBN} records it.
 @end enumerate
 
-Init files use the same syntax as @dfn{command files} (@pxref{Command
-Files}) and are processed by @value{GDBN} in the same way.  The init
-file in your home directory can set options (such as @samp{set
-complaints}) that affect subsequent processing of command line options
-and operands.  Init files are not executed if you use the @samp{-nx}
-option (@pxref{Mode Options, ,Choosing Modes}).
+@node Initialization Files
+@subsection Initialization Files
+@cindex init file name
 
-To display the list of init files loaded by gdb at startup, you
-can use @kbd{gdb --help}.
+During startup (@pxref{Startup}) @value{GDBN} will execute commands
+from several initialization files.  These initialization files use the
+same syntax as @dfn{command files} (@pxref{Command Files}) and are
+processed by @value{GDBN} in the same way.
 
-@cindex init file name
+To display the list of initialization files loaded by @value{GDBN} at
+startup, in the order they will be loaded, you can use @kbd{gdb
+--help}.
+
+As the system wide and home directory initialization files are
+processed before most command line options, changes to settings
+(e.g. @samp{set complaints}) can affect subsequent processing of
+command line options and operands.
+
+The following sections describe where @value{GDBN} looks for the
+initialization and the order that the files are searched for.
+
+@anchor{System Wide Init Files}
+@subsubsection System wide initialization files
+
+There are two locations that are searched for system wide
+initialization files.  Both of these locations are always checked:
+
+@table @code
+
+@item @file{system.gdbinit}
+This is a single system-wide initialization file.  Its location is
+specified with the @code{--with-system-gdbinit} configure option
+(@pxref{System-wide configuration}).  It is loaded first when
+@value{GDBN} starts, before command line options have been processed.
+
+@item @file{system.gdbinit.d}
+This is the system-wide initialization directory.  Its location is
+specified with the @code{--with-system-gdbinit-dir} configure option
+(@pxref{System-wide configuration}).  Files in this directory are
+loaded in alphabetical order immediately after @file{system.gdbinit}
+(if enabled) when @value{GDBN} starts, before command line options
+have been processed.  Files need to have a recognized scripting
+language extension (@file{.py}/@file{.scm}) or be named with a
+@file{.gdb} extension to be interpreted as regular @value{GDBN}
+commands.  @value{GDBN} will not recurse into any subdirectories of
+this directory.
+
+@end table
+
+It is possible to prevent the system wide initialization files from
+being loaded using the @samp{-nx} command line option, @pxref{Mode
+Options,,Choosing Modes}.
+
+@anchor{Home Directory Init File}
+@subsubsection Home directory initialization file
+@cindex @file{gdbinit}
 @cindex @file{.gdbinit}
 @cindex @file{gdb.ini}
-The @value{GDBN} init files are normally called @file{.gdbinit}.
-The DJGPP port of @value{GDBN} uses the name @file{gdb.ini}, due to
-the limitations of file names imposed by DOS filesystems.  The Windows
-port of @value{GDBN} uses the standard name, but if it finds a
-@file{gdb.ini} file in your home directory, it warns you about that
-and suggests to rename the file to the standard name.
 
+After loading the system wide initialization files @value{GDBN} will
+look for an initialization file in the users home
+directory@footnote{On DOS/Windows systems, the home directory is the
+one pointed to by the @code{HOME} environment variable.}.  There are a
+number of locations that @value{GDBN} will search in the home
+directory, these locations are searched in order and @value{GDBN} will
+load the first file that it finds, and subsequent locations will not
+be checked.
+
+On non-Apple hosts the locations searched are:
+@table @file
+@item $XDG_CONFIG_HOME/gdb/gdbinit
+@item $HOME/.config/gdb/gdbinit
+@item $HOME/.gdbinit
+@end table
+
+While on Apple hosts the locations searched are:
+@table @file
+@item $HOME/Library/Preferences/gdb/gdbinit
+@item $HOME/.gdbinit
+@end table
+
+It is possible to prevent the home directory initialization file from
+being loaded using the @samp{-nx} or @samp{-nh} command line options,
+@pxref{Mode Options,,Choosing Modes}.
+
+The DJGPP port of @value{GDBN} uses the name @file{gdb.ini} instead of
+@file{.gdbinit} or @file{gdbinit}, due to the limitations of file
+names imposed by DOS filesystems.  The Windows port of @value{GDBN}
+uses the standard name, but if it finds a @file{gdb.ini} file in your
+home directory, it warns you about that and suggests to rename the
+file to the standard name.
+
+@anchor{Init File in the Current Directory during Startup}
+@subsubsection Local directory initialization file
+
+@value{GDBN} will check the current directory for a file called
+@file{.gdbinit}.  It is loaded last, after command line options
+other than @samp{-x} and @samp{-ex} have been processed.  The command
+line options @samp{-x} and @samp{-ex} are processed last, after
+@file{.gdbinit} has been loaded, @pxref{File Options,,Choosing
+Files}.
+
+If the file in the current directory was already loaded as the home
+directory initialization file then it will not be loaded a second
+time.
+
+It is possible to prevent the local directory initialization file from
+being loaded using the @samp{-nx} command line option, @pxref{Mode
+Options,,Choosing Modes}.
 
 @node Quitting GDB
 @section Quitting @value{GDBN}
@@ -46470,7 +46522,8 @@ Execute given @value{GDBN} @var{command}.
 Add @var{directory} to the path to search for source files.
 
 @item -nh
-Do not execute commands from @file{~/.gdbinit}.
+Do not execute commands from @file{~/.config/gdb/gdbinit} or
+@file{~/.gdbinit}.
 
 @item -nx
 @itemx -n
@@ -46895,6 +46948,8 @@ Richard M. Stallman and Roland H. Pesch, July 1991.
 @value{SYSTEM_GDBINIT_DIR}/*
 @end ifset
 
+~/.config/gdb/gdbinit
+
 ~/.gdbinit
 
 ./.gdbinit
@@ -46954,11 +47009,11 @@ the @value{GDBN} manual in node @code{System-wide configuration}
 @ref{System-wide configuration}.
 @end ifclear
 
-@item ~/.gdbinit
+@item @file{~/.config/gdb/gdbinit} or @file{~/.gdbinit}
 User initialization file.  It is executed unless user specified
 @value{GDBN} options @code{-nx}, @code{-n} or @code{-nh}.
 
-@item ./.gdbinit
+@item @file{.gdbinit}
 Initialization file for current directory.  It may need to be enabled with
 @value{GDBN} security command @code{set auto-load local-gdbinit}.
 See more in
index 7b44bfee36690441b38eb5f3625142e5e502e98f..6232ea3f633a48b4ea027941325b669077e91811 100644 (file)
@@ -301,8 +301,6 @@ get_init_files (std::vector<std::string> *system_gdbinit,
          }
        }
 
-      const char *homedir = getenv ("HOME");
-
       /* If the .gdbinit file in the current directory is the same as
         the $HOME/.gdbinit file, it should not be sourced.  homebuf
         and cwdbuf are used in that purpose.  Make sure that the stats
@@ -312,14 +310,7 @@ get_init_files (std::vector<std::string> *system_gdbinit,
       memset (&homebuf, 0, sizeof (struct stat));
       memset (&cwdbuf, 0, sizeof (struct stat));
 
-      if (homedir)
-       {
-         homeinit = std::string (homedir) + SLASH_STRING + GDBINIT;
-         if (stat (homeinit.c_str (), &homebuf) != 0)
-           {
-             homeinit = "";
-           }
-       }
+      homeinit = find_gdb_home_config_file (GDBINIT, &homebuf);
 
       if (stat (GDBINIT, &cwdbuf) == 0)
        {
@@ -328,7 +319,7 @@ get_init_files (std::vector<std::string> *system_gdbinit,
                         sizeof (struct stat)))
            localinit = GDBINIT;
        }
-      
+
       initialized = 1;
     }
 
index 9fb5e5cf614de123721570a64fd0ab390ca80468..a52e53b8671e2df0f749e7b5e0eb699e986d0bef 100644 (file)
 #include "filenames.h"
 #include "gdb_tilde_expand.h"
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
 #ifdef USE_WIN32API
 #include <windows.h>
 #endif
@@ -298,6 +302,51 @@ get_standard_config_dir ()
   return {};
 }
 
+/* See pathstuff.h. */
+
+std::string
+get_standard_config_filename (const char *filename)
+{
+  std::string config_dir = get_standard_config_dir ();
+  if (config_dir != "")
+    {
+      const char *tmp = (*filename == '.') ? (filename + 1) : filename;
+      std::string path = config_dir + SLASH_STRING + std::string (tmp);
+      return path;
+    }
+
+  return {};
+}
+
+/* See pathstuff.h.  */
+
+std::string
+find_gdb_home_config_file (const char *name, struct stat *buf)
+{
+  gdb_assert (name != nullptr);
+  gdb_assert (*name != '\0');
+
+  std::string config_dir_file = get_standard_config_filename (name);
+  if (!config_dir_file.empty ())
+    {
+      if (stat (config_dir_file.c_str (), buf) == 0)
+       return config_dir_file;
+    }
+
+  const char *homedir = getenv ("HOME");
+  if (homedir != nullptr)
+    {
+      /* Make sure the path is absolute and tilde-expanded.  */
+      gdb::unique_xmalloc_ptr<char> abs (gdb_abspath (homedir));
+      std::string path = (std::string (abs.get ()) + SLASH_STRING
+                         + std::string (name));
+      if (stat (path.c_str (), buf) == 0)
+       return path;
+    }
+
+  return {};
+}
+
 /* See gdbsupport/pathstuff.h.  */
 
 const char *
index 85241bc8c7c483e74c73ec42104ebc42ca7ea64b..996c8f2bbf6a9f144f74157ca395beb395f071a7 100644 (file)
@@ -99,6 +99,29 @@ extern std::string get_standard_temp_dir ();
 
 extern std::string get_standard_config_dir ();
 
+/* Look for FILENAME in the standard configuration directory as returned by
+   GET_STANDARD_CONFIG_DIR and return the path to the file.  No check is
+   performed that the file actually exists or not.
+
+   If FILENAME begins with a '.' then the path returned will remove the
+   leading '.' character, for example passing '.gdbinit' could return the
+   path '/home/username/.config/gdb/gdbinit'.  */
+
+extern std::string get_standard_config_filename (const char *filename);
+
+/* Look for a file called NAME in either the standard config directory or
+   in the users home directory.  If a suitable file is found then *BUF will
+   be filled with the contents of a call to 'stat' on the found file,
+   otherwise *BUF is undefined after this call.
+
+   If NAME starts with a '.' character then, when looking in the standard
+   config directory the file searched for has the '.' removed.  For
+   example, if NAME is '.gdbinit' then on a Linux target GDB might look for
+   '~/.config/gdb/gdbinit' and then '~/.gdbinit'.  */
+
+extern std::string find_gdb_home_config_file (const char *name,
+                                             struct stat *buf);
+
 /* Return the file name of the user's shell.  Normally this comes from
    the SHELL environment variable.  */