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.
This commit is contained in:
Paul Eggert 2025-07-24 14:49:52 -07:00
parent 6a08a9a54d
commit eb9ec79c13
5 changed files with 61 additions and 15 deletions

View file

@ -695,6 +695,7 @@ The name of the organization to which you belong. Used for setting the
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.

View file

@ -753,8 +753,8 @@ available.
(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

View file

@ -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

View file

@ -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);

View file

@ -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);