From: Paul Eggert Date: Thu, 24 Jul 2025 21:49:52 +0000 (-0700) Subject: PATH defaults now act more like GNU and POSIX X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=0d6661777cdae6b7223f64bcfa535f11fb98f545;p=emacs.git 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. (cherry picked from commit eb9ec79c13f17d610fcb6de49628b8a7686fbab7) --- 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 @@ 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. diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index ad47dfa49f4..a8268f20721 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -742,8 +742,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 diff --git a/etc/NEWS b/etc/NEWS index 83c8271c3da..b1d6908ad7e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1038,6 +1038,12 @@ It offers a more concise way to create a completion table with metadata. +++ ** 'all-completions' and 'unintern' no longer support their old calling conventions. ++++ +** 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 7ea90931478..c67b5eb74f9 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);