reading the emacs git history is so fun and i learn so many things. this one from paul eggert a few days ago was quite fascinating regarding the expectations around system default PATH
Post
reading the emacs git history is so fun and i learn so many things. this one from paul eggert a few days ago was quite fascinating regarding the expectations around system default PATH
and i admired how this comment about not knowing what to do remained even if part of the problem has now been solved
- /* Default PATH is implementation-defined, so we don't know how
- to conduct the search. */
+ /* We don't know how to conduct the search. */
return NULL;
their cgit is going incredibly slowly i presume from corporate inference so here's the diff with the comments lol. love distributed version control systems
commit eb9ec79c13f17d610fcb6de49628b8a7686fbab7
Author: Paul Eggert
Date: Thu Jul 24 14:49:52 2025 -0700
PATH defaults now act more like GNU and POSIX
When PATH is unset or empty, use the system default,
to be consistent with GNU/Linux and with POSIX.
If there is no system default do not default to "."
as that can be dangerous.
* src/callproc.c (init_callproc_1, init_callproc):
Default PATH to the null pointer, not the empty string.
* src/emacs.c (default_PATH): New function.
(find_emacs_executable, decode_env_path): Be consistent with POSIX
and with glibc about what to do when PATH is unset or empty.
diff --git a/doc/emacs/cmdargs.texi b/doc/emacs/cmdargs.texi
index 00167056be1..79ae2d064d1 100644
--- a/doc/emacs/cmdargs.texi
+++ b/doc/emacs/cmdargs.texi
@@ -695,6 +695,7 @@ General Variables
A colon-separated list of directories containing executable files.
This is used to initialize the variable @code{exec-path}
(@pxref{Shell}).
+If unset or empty, an implementation-dependent default is used.
@item PWD
@vindex PWD@r{, environment variable}
If set, this should be the default directory when Emacs was started.
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi
index 88b7bfc7049..2c2c710eea4 100644
--- a/doc/emacs/misc.texi
+++ b/doc/emacs/misc.texi
@@ -753,8 +753,8 @@ Shell
(either in the @var{cmd} argument to one of the above commands, or in
other contexts), Emacs searches for the program in the directories
specified by the variable @code{exec-path}. The value of this
-variable must be a list of directories; the default value is
-initialized from the environment variable @env{PATH} when Emacs is
+variable must be a list of directories; the default value
+depends on the environment variable @env{PATH} when Emacs is
started (@pxref{General Variables}).
@kbd{M-x eshell} invokes a shell implemented entirely in Emacs. It
diff --git a/etc/NEWS b/etc/NEWS
index 865e5e6b6d5..8f396403ba2 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2755,6 +2755,12 @@ option, but can optionally return the equivalent of 'exec-suffixes' from
a remote host. It must be used in conjunction with the function
'exec-path'.
++++
+** The 'exec-path' variable now uses same default PATH as other programs.
+That is, if the PATH environment variable is unset or empty, 'exec-path'
+now acts as if PATH is the system default, which is "/bin:/usr/bin"
+on GNU/Linux systems.
+
* Changes in Emacs 31.1 on Non-Free Operating Systems
diff --git a/src/callproc.c b/src/callproc.c
index 7059a2bac6f..e1a369b47f4 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -1960,7 +1960,7 @@ init_callproc_1 (void)
Vexec_path = decode_env_path ("EMACSPATH", PATH_EXEC, 0);
Vexec_directory = Ffile_name_as_directory (Fcar (Vexec_path));
/* FIXME? For ns, path_exec should go at the front? /
- Vexec_path = nconc2 (decode_env_path ("PATH", "", 0), Vexec_path);
+ Vexec_path = nconc2 (decode_env_path ("PATH", NULL, 0), Vexec_path);
}
/ This is run after init_cmdargs, when Vinstallation_directory is valid. /
@@ -1985,7 +1985,7 @@ init_callproc (void)
{
/ Running uninstalled, so default to tem rather than PATH_EXEC. */
Vexec_path = decode_env_path ("EMACSPATH", SSDATA (tem), 0);
- Vexec_path = nconc2 (decode_env_path ("PATH", "", 0), Vexec_path);
+ Vexec_path = nconc2 (decode_env_path ("PATH", NULL, 0), Vexec_path);
}
Vexec_directory = Ffile_name_as_directory (tem);
diff --git a/src/emacs.c b/src/emacs.c
index 3689c92c8b2..aa762e7edb1 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -737,6 +737,44 @@ argmatch (char **argv, int argc, const char *sstr, const char lstr,
}
}
+/ Return the default PATH if it can be determined, NULL otherwise. */
+
+static char const *
+default_PATH (void)
+{
+ static char const path;
+
+ / A static buffer big enough so that confstr is called just once
+ in GNU/Linux, where the default PATH is "/bin:/usr/bin".
+ If staticbuf[0], path is already initialized. */
+ static char staticbuf[16];
+
+ if (!staticbuf[0])
+ {
+#ifdef _CS_PATH
+ char buf = staticbuf;
+ size_t bufsize = sizeof staticbuf, s;
+
+ / If necessary call confstr a second time with a bigger buffer. /
+ while (bufsize < (s = confstr (_CS_PATH, buf, bufsize)))
+ {
+ buf = xmalloc (s);
+ bufsize = s;
+ }
+
+ if (s == 0)
+ {
+ staticbuf[0] = 1;
+ buf = NULL;
+ }
+
+ path = buf;
+#endif
+ }
+
+ return path;
+}
+
#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
/ Find a name (absolute or relative) of the Emacs executable whose
@@ -778,10 +816,11 @@ find_emacs_executable (char const *argv0, ptrdiff_t *candidate_size)
ptrdiff_t argv0_length = strlen (argv0);
const char *path = getenv ("PATH");
+ if (! (path && path))
+ path = default_PATH ();
if (!path)
{
- / Default PATH is implementation-defined, so we don't know how
- to conduct the search. /
+ / We don't know how to conduct the search. */
return NULL;
}
@@ -3217,15 +3256,19 @@ decode_env_path (const char *evarname, const char *defalt, bool empty)
to initialize variables when Emacs starts up, and isn't called
after that. */
if (evarname != 0)
- path = getenv (evarname);
+ {
+ path = getenv (evarname);
+ if (! (path && *path) && strcmp (evarname, "PATH") == 0)
+ path = default_PATH ();
+ }
else
path = 0;
if (!path)
{
-#ifdef NS_SELF_CONTAINED
- path = ns_relocate (defalt);
-#else
path = defalt;
+#ifdef NS_SELF_CONTAINED
+ if (path)
+ path = ns_relocate (path);
#endif
#ifdef WINDOWSNT
defaulted = 1;
@@ -3277,7 +3320,7 @@ decode_env_path (const char *evarname, const char *defalt, bool empty)
}
#endif
lpath = Qnil;
- while (1)
+ for (; path; path = *p ? p + 1 : NULL)
{
p = strchr (path, SEPCHAR);
if (!p)
@@ -3320,10 +3363,6 @@ decode_env_path (const char *evarname, const char defalt, bool empty)
} / !NILP (element) */
lpath = Fcons (element, lpath);
- if (*p)
- path = p + 1;
- else
- break;
}
return Fnreverse (lpath);
however to be clear i'm only doing this because the build started failing i'm gonna try to fix it before anyone else can
the build broke bc of their tests to avoid unintentional ABI breakage across pdumper versions which is a Good and Cool thing. really need more languages to have image dumping i tried adding it to cpython but it's such a fucking mess
git bisect reminding me that i haven't found a good commit yet i know buddy i'm trying
at least emacs uses real autotools unlike perl which takes forever to build
A space for Bonfire maintainers and contributors to communicate