aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2025-07-24 14:49:52 -0700
committerPaul Eggert2025-07-24 22:13:47 -0700
commiteb9ec79c13f17d610fcb6de49628b8a7686fbab7 (patch)
tree65229f340d83d020275e5f28b640d7b4d2722827 /src
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.
Diffstat (limited to 'src')
-rw-r--r--src/callproc.c4
-rw-r--r--src/emacs.c61
2 files changed, 52 insertions, 13 deletions
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);