aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2025-07-24 14:49:52 -0700
committerPaul Eggert2025-07-24 22:13:47 -0700
commiteb9ec79c13f17d610fcb6de49628b8a7686fbab7 (patch)
tree65229f340d83d020275e5f28b640d7b4d2722827
parent6a08a9a54d4ff5aafe795c7a079709993c08dff3 (diff)
downloademacs-eb9ec79c13f17d610fcb6de49628b8a7686fbab7.tar.gz
emacs-eb9ec79c13f17d610fcb6de49628b8a7686fbab7.zip
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.
-rw-r--r--doc/emacs/cmdargs.texi1
-rw-r--r--doc/emacs/misc.texi4
-rw-r--r--etc/NEWS6
-rw-r--r--src/callproc.c4
-rw-r--r--src/emacs.c61
5 files changed, 61 insertions, 15 deletions
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
695A colon-separated list of directories containing executable files. 695A colon-separated list of directories containing executable files.
696This is used to initialize the variable @code{exec-path} 696This is used to initialize the variable @code{exec-path}
697(@pxref{Shell}). 697(@pxref{Shell}).
698If unset or empty, an implementation-dependent default is used.
698@item PWD 699@item PWD
699@vindex PWD@r{, environment variable} 700@vindex PWD@r{, environment variable}
700If set, this should be the default directory when Emacs was started. 701If 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 @@ available.
753(either in the @var{cmd} argument to one of the above commands, or in 753(either in the @var{cmd} argument to one of the above commands, or in
754other contexts), Emacs searches for the program in the directories 754other contexts), Emacs searches for the program in the directories
755specified by the variable @code{exec-path}. The value of this 755specified by the variable @code{exec-path}. The value of this
756variable must be a list of directories; the default value is 756variable must be a list of directories; the default value
757initialized from the environment variable @env{PATH} when Emacs is 757depends on the environment variable @env{PATH} when Emacs is
758started (@pxref{General Variables}). 758started (@pxref{General Variables}).
759 759
760 @kbd{M-x eshell} invokes a shell implemented entirely in Emacs. It 760 @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
2755a remote host. It must be used in conjunction with the function 2755a remote host. It must be used in conjunction with the function
2756'exec-path'. 2756'exec-path'.
2757 2757
2758+++
2759** The 'exec-path' variable now uses same default PATH as other programs.
2760That is, if the PATH environment variable is unset or empty, 'exec-path'
2761now acts as if PATH is the system default, which is "/bin:/usr/bin"
2762on GNU/Linux systems.
2763
2758 2764
2759* Changes in Emacs 31.1 on Non-Free Operating Systems 2765* Changes in Emacs 31.1 on Non-Free Operating Systems
2760 2766
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)
1960 Vexec_path = decode_env_path ("EMACSPATH", PATH_EXEC, 0); 1960 Vexec_path = decode_env_path ("EMACSPATH", PATH_EXEC, 0);
1961 Vexec_directory = Ffile_name_as_directory (Fcar (Vexec_path)); 1961 Vexec_directory = Ffile_name_as_directory (Fcar (Vexec_path));
1962 /* FIXME? For ns, path_exec should go at the front? */ 1962 /* FIXME? For ns, path_exec should go at the front? */
1963 Vexec_path = nconc2 (decode_env_path ("PATH", "", 0), Vexec_path); 1963 Vexec_path = nconc2 (decode_env_path ("PATH", NULL, 0), Vexec_path);
1964} 1964}
1965 1965
1966/* This is run after init_cmdargs, when Vinstallation_directory is valid. */ 1966/* This is run after init_cmdargs, when Vinstallation_directory is valid. */
@@ -1985,7 +1985,7 @@ init_callproc (void)
1985 { 1985 {
1986 /* Running uninstalled, so default to tem rather than PATH_EXEC. */ 1986 /* Running uninstalled, so default to tem rather than PATH_EXEC. */
1987 Vexec_path = decode_env_path ("EMACSPATH", SSDATA (tem), 0); 1987 Vexec_path = decode_env_path ("EMACSPATH", SSDATA (tem), 0);
1988 Vexec_path = nconc2 (decode_env_path ("PATH", "", 0), Vexec_path); 1988 Vexec_path = nconc2 (decode_env_path ("PATH", NULL, 0), Vexec_path);
1989 } 1989 }
1990 1990
1991 Vexec_directory = Ffile_name_as_directory (tem); 1991 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,
737 } 737 }
738} 738}
739 739
740/* Return the default PATH if it can be determined, NULL otherwise. */
741
742static char const *
743default_PATH (void)
744{
745 static char const *path;
746
747 /* A static buffer big enough so that confstr is called just once
748 in GNU/Linux, where the default PATH is "/bin:/usr/bin".
749 If staticbuf[0], path is already initialized. */
750 static char staticbuf[16];
751
752 if (!staticbuf[0])
753 {
754#ifdef _CS_PATH
755 char *buf = staticbuf;
756 size_t bufsize = sizeof staticbuf, s;
757
758 /* If necessary call confstr a second time with a bigger buffer. */
759 while (bufsize < (s = confstr (_CS_PATH, buf, bufsize)))
760 {
761 buf = xmalloc (s);
762 bufsize = s;
763 }
764
765 if (s == 0)
766 {
767 staticbuf[0] = 1;
768 buf = NULL;
769 }
770
771 path = buf;
772#endif
773 }
774
775 return path;
776}
777
740#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY 778#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
741 779
742/* Find a name (absolute or relative) of the Emacs executable whose 780/* 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)
778 ptrdiff_t argv0_length = strlen (argv0); 816 ptrdiff_t argv0_length = strlen (argv0);
779 817
780 const char *path = getenv ("PATH"); 818 const char *path = getenv ("PATH");
819 if (! (path && *path))
820 path = default_PATH ();
781 if (!path) 821 if (!path)
782 { 822 {
783 /* Default PATH is implementation-defined, so we don't know how 823 /* We don't know how to conduct the search. */
784 to conduct the search. */
785 return NULL; 824 return NULL;
786 } 825 }
787 826
@@ -3217,15 +3256,19 @@ decode_env_path (const char *evarname, const char *defalt, bool empty)
3217 to initialize variables when Emacs starts up, and isn't called 3256 to initialize variables when Emacs starts up, and isn't called
3218 after that. */ 3257 after that. */
3219 if (evarname != 0) 3258 if (evarname != 0)
3220 path = getenv (evarname); 3259 {
3260 path = getenv (evarname);
3261 if (! (path && *path) && strcmp (evarname, "PATH") == 0)
3262 path = default_PATH ();
3263 }
3221 else 3264 else
3222 path = 0; 3265 path = 0;
3223 if (!path) 3266 if (!path)
3224 { 3267 {
3225#ifdef NS_SELF_CONTAINED
3226 path = ns_relocate (defalt);
3227#else
3228 path = defalt; 3268 path = defalt;
3269#ifdef NS_SELF_CONTAINED
3270 if (path)
3271 path = ns_relocate (path);
3229#endif 3272#endif
3230#ifdef WINDOWSNT 3273#ifdef WINDOWSNT
3231 defaulted = 1; 3274 defaulted = 1;
@@ -3277,7 +3320,7 @@ decode_env_path (const char *evarname, const char *defalt, bool empty)
3277 } 3320 }
3278#endif 3321#endif
3279 lpath = Qnil; 3322 lpath = Qnil;
3280 while (1) 3323 for (; path; path = *p ? p + 1 : NULL)
3281 { 3324 {
3282 p = strchr (path, SEPCHAR); 3325 p = strchr (path, SEPCHAR);
3283 if (!p) 3326 if (!p)
@@ -3320,10 +3363,6 @@ decode_env_path (const char *evarname, const char *defalt, bool empty)
3320 } /* !NILP (element) */ 3363 } /* !NILP (element) */
3321 3364
3322 lpath = Fcons (element, lpath); 3365 lpath = Fcons (element, lpath);
3323 if (*p)
3324 path = p + 1;
3325 else
3326 break;
3327 } 3366 }
3328 3367
3329 return Fnreverse (lpath); 3368 return Fnreverse (lpath);