+/* Relocate a file or directory. PROGNAME is the name by which gdb
+ was invoked (i.e., argv[0]). INITIAL is the default value for the
+ file or directory. FLAG is true if the value is relocatable, false
+ otherwise. Returns a newly allocated string; this may return NULL
+ under the same conditions as make_relative_prefix. */
+static char *
+relocate_path (const char *progname, const char *initial, int flag)
+{
+ if (flag)
+ return make_relative_prefix (progname, BINDIR, initial);
+ return xstrdup (initial);
+}
+
+/* Like relocate_path, but specifically checks for a directory.
+ INITIAL is relocated according to the rules of relocate_path. If
+ the result is a directory, it is used; otherwise, INITIAL is used.
+ The chosen directory is then canonicalized using lrealpath. This
+ function always returns a newly-allocated string. */
+static char *
+relocate_directory (const char *progname, const char *initial, int flag)
+{
+ char *dir;
+
+ dir = relocate_path (progname, initial, flag);
+ if (dir)
+ {
+ struct stat s;
+
+ if (stat (dir, &s) != 0 || !S_ISDIR (s.st_mode))
+ {
+ xfree (dir);
+ dir = NULL;
+ }
+ }
+ if (!dir)
+ dir = xstrdup (initial);
+
+ /* Canonicalize the directory. */
+ if (*dir)
+ {
+ char *canon_sysroot = lrealpath (dir);
+ if (canon_sysroot)
+ {
+ xfree (dir);
+ dir = canon_sysroot;
+ }
+ }
+
+ return dir;
+}
+
+/* Compute the locations of init files that GDB should source and return
+ them in SYSTEM_GDBINIT, HOME_GDBINIT, LOCAL_GDBINIT. If there is
+ no system gdbinit (resp. home gdbinit and local gdbinit) to be loaded,
+ then SYSTEM_GDBINIT (resp. HOME_GDBINIT and LOCAL_GDBINIT) is set to
+ NULL. */
+static void
+get_init_files (char **system_gdbinit,
+ char **home_gdbinit,
+ char **local_gdbinit)
+{
+ static char *sysgdbinit = NULL;
+ static char *homeinit = NULL;
+ static char *localinit = NULL;
+ static int initialized = 0;
+
+ if (!initialized)
+ {
+ struct stat homebuf, cwdbuf, s;
+ char *homedir, *relocated_sysgdbinit;
+
+ if (SYSTEM_GDBINIT[0])
+ {
+ relocated_sysgdbinit = relocate_path (gdb_program_name,
+ SYSTEM_GDBINIT,
+ SYSTEM_GDBINIT_RELOCATABLE);
+ if (relocated_sysgdbinit && stat (relocated_sysgdbinit, &s) == 0)
+ sysgdbinit = relocated_sysgdbinit;
+ else
+ xfree (relocated_sysgdbinit);
+ }
+
+ 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
+ are zero in case one of them fails (this guarantees that they
+ won't match if either exists). */
+
+ memset (&homebuf, 0, sizeof (struct stat));
+ memset (&cwdbuf, 0, sizeof (struct stat));
+
+ if (homedir)
+ {
+ homeinit = xstrprintf ("%s/%s", homedir, gdbinit);
+ if (stat (homeinit, &homebuf) != 0)
+ {
+ xfree (homeinit);
+ homeinit = NULL;
+ }
+ }
+
+ if (stat (gdbinit, &cwdbuf) == 0)
+ {
+ if (!homeinit
+ || memcmp ((char *) &homebuf, (char *) &cwdbuf,
+ sizeof (struct stat)))
+ localinit = gdbinit;
+ }
+
+ initialized = 1;
+ }
+
+ *system_gdbinit = sysgdbinit;
+ *home_gdbinit = homeinit;
+ *local_gdbinit = localinit;
+}