Commit b1e4db661a for perl
commit b1e4db661a9beb6426fc04fd63853a68e55ad13e
Author: Brad Smith <brad@comstyle.com>
Date: Sun Sep 13 02:32:28 2026 -0400
Where available, use getexecpath() to make $^X absolute
In Configure, check whether getexecpath() can be used to find the
absolute pathname of the executable. If so, set usegetexecpath in
config.sh and USE_GETEXECPATH in config.h. If this is set, then
use this approach in S_set_caret_X() to canonicalise $^X as an
absolute path. This approach works on OpenBSD.
diff --git a/AUTHORS b/AUTHORS
index 6f472d08de..14163224e1 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -206,6 +206,7 @@ Brad Gilbert <b2gills@gmail.com>
Brad Howerter <bhower@wgc.woodward.com>
Brad Hughes <brad@tgsmc.com>
Brad Lanam <bll@gentoo.com>
+Brad Smith <brad@comstyle.com>
Bradley Dean <bjdean@bjdean.id.au>
Bram <perl-rt@wizbit.be>
Brandon Black <blblack@gmail.com>
diff --git a/Configure b/Configure
index 947b4bb8b3..86923a48e6 100755
--- a/Configure
+++ b/Configure
@@ -1371,6 +1371,7 @@ usedefaultstrict=''
dtrace=''
usedtrace=''
usefaststdio=''
+usegetexecpath=''
usekernprocpathname=''
ccflags_uselargefiles=''
ldflags_uselargefiles=''
@@ -23658,6 +23659,44 @@ esac
set usedefaultstrict
eval $setvar
+: Determine if we can use getexecpath to find executing program
+echo " "
+echo "Determining whether we can use getexecpath to find executing program..." >&4
+$cat >try.c <<'EOM'
+
+#include <sys/param.h>
+#include <unistd.h>
+
+int
+main(int argc, char **argv) {
+ char buf[MAXPATHLEN];
+
+ if (getexecpath(buf, sizeof(buf)) != 0)
+ return 2;
+
+ return 0;
+}
+EOM
+
+val=$undef
+set try
+if eval $compile; then
+ if $run ./try; then
+ echo "You can use getexecpath to find the executing program." >&4
+ val="$define"
+ else
+ echo "Nope, getexecpath doesn't work here." >&4
+ val="$undef"
+ fi
+else
+ echo "I'm unable to compile the test program." >&4
+ echo "I'll assume no getexecpath here." >&4
+ val="$undef"
+fi
+$rm_try
+set usegetexecpath
+eval $setvar
+
: Determine if we can use sysctl with KERN_PROC_PATHNAME to find executing program
echo " "
echo "Determining whether we can use sysctl with KERN_PROC_PATHNAME to find executing program..." >&4
@@ -26224,6 +26263,7 @@ usedevel='$usedevel'
usedl='$usedl'
usedtrace='$usedtrace'
usefaststdio='$usefaststdio'
+usegetexecpath='$usegetexecpath'
useithreads='$useithreads'
usekernprocpathname='$usekernprocpathname'
uselanginfo='$uselanginfo'
diff --git a/Cross/config.sh-arm-linux b/Cross/config.sh-arm-linux
index 222fec2086..cd5e6abd96 100644
--- a/Cross/config.sh-arm-linux
+++ b/Cross/config.sh-arm-linux
@@ -1161,6 +1161,7 @@ usedevel='undef'
usedl='define'
usedtrace='undef'
usefaststdio='define'
+usegetexecpath='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='define'
diff --git a/Cross/config.sh-arm-linux-n770 b/Cross/config.sh-arm-linux-n770
index 9d8bf14afb..3aa6213a63 100644
--- a/Cross/config.sh-arm-linux-n770
+++ b/Cross/config.sh-arm-linux-n770
@@ -1159,6 +1159,7 @@ usedevel='undef'
usedl='define'
usedtrace='undef'
usefaststdio='define'
+usegetexecpath='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='define'
diff --git a/Porting/Glossary b/Porting/Glossary
index 6b2f750438..ebfbf25c58 100644
--- a/Porting/Glossary
+++ b/Porting/Glossary
@@ -5707,6 +5707,10 @@ usefaststdio (usefaststdio.U):
and indicates that Perl should be built to use 'fast stdio'.
Defaults to define in Perls 5.8 and earlier, to undef later.
+usegetexecpath (usegetexecpath.U):
+ This variable, indicates that we can use getexecpath to get a full
+ path for the executable, and hence convert $^X to an absolute path.
+
useithreads (usethreads.U):
This variable conditionally defines the USE_ITHREADS symbol,
and indicates that Perl should be built to use the interpreter-based
diff --git a/Porting/config.sh b/Porting/config.sh
index cc1f865a9c..debcd34677 100644
--- a/Porting/config.sh
+++ b/Porting/config.sh
@@ -1187,6 +1187,7 @@ usedevel='define'
usedl='define'
usedtrace='undef'
usefaststdio='undef'
+usegetexecpath='undef'
useithreads='define'
usekernprocpathname='undef'
uselanginfo='true'
diff --git a/caretx.c b/caretx.c
index 855608b5e0..ae9cf4354a 100644
--- a/caretx.c
+++ b/caretx.c
@@ -61,7 +61,14 @@ Perl_set_caret_X(pTHX)
#else
/* We can try a platform-specific one if possible; if it fails, or we
* aren't running on a suitable platform, we'll fall back to argv[0]. */
-# ifdef USE_KERN_PROC_PATHNAME
+# ifdef USE_GETEXECPATH
+ char buf[MAXPATHLEN];
+
+ if (getexecpath(buf, sizeof(buf)) == 0) {
+ sv_setpv(caret_x, buf);
+ return;
+ }
+# elif defined(USE_KERN_PROC_PATHNAME)
size_t size = 0;
int mib[4];
mib[0] = CTL_KERN;
diff --git a/config_h.SH b/config_h.SH
index ce49644220..7d6ccabfc5 100755
--- a/config_h.SH
+++ b/config_h.SH
@@ -4438,6 +4438,13 @@ sed <<!GROK!THIS! >$CONFIG_H -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un
#$usefaststdio USE_FAST_STDIO /**/
#endif
+/* USE_GETEXECPATH:
+ * This symbol, if defined, indicates that we can use getexecpath
+ * to get a full path for the executable, and hence convert $^X to
+ * an absolute path.
+ */
+#$usegetexecpath USE_GETEXECPATH /**/
+
/* USE_KERN_PROC_PATHNAME:
* This symbol, if defined, indicates that we can use sysctl with
* KERN_PROC_PATHNAME to get a full path for the executable, and hence
diff --git a/configure.com b/configure.com
index b73ef85c87..d44c453f81 100644
--- a/configure.com
+++ b/configure.com
@@ -6525,6 +6525,7 @@ $ WC "usefaststdio='" + usefaststdio + "'"
$ WC "useieee='" + useieee + "'" ! VMS-specific
$ WC "useithreads='" + useithreads + "'"
$ WC "usekernelthreads='" + usekernelthreads + "'" ! VMS-specific
+$ WC "usegetexecpath='undef'"
$ WC "usekernprocpathname='undef'"
$ WC "usensgetexecutablepath='undef'"
$ WC "uselargefiles='" + uselargefiles + "'"
diff --git a/plan9/config_sh.sample b/plan9/config_sh.sample
index 606188a107..7dd86e68e1 100644
--- a/plan9/config_sh.sample
+++ b/plan9/config_sh.sample
@@ -1132,6 +1132,7 @@ usedevel='undef'
usedl='undef'
usedtrace='undef'
usefaststdio='undef'
+usegetexecpath='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='define'
diff --git a/t/op/magic.t b/t/op/magic.t
index a3e2b42eac..c11e701ba5 100644
--- a/t/op/magic.t
+++ b/t/op/magic.t
@@ -276,8 +276,8 @@ $$ = $pid; # Tests below use $$
# $^X and $0
{
- my $is_abs = $Config{d_procselfexe} || $Config{usekernprocpathname}
- || $Config{usensgetexecutablepath};
+ my $is_abs = $Config{usegetexecpath} || $Config{d_procselfexe}
+ || $Config{usekernprocpathname} || $Config{usensgetexecutablepath};
if ($^O eq 'qnx') {
chomp($wd = `/usr/bin/fullpath -t`);
}
diff --git a/t/porting/known_pod_issues.dat b/t/porting/known_pod_issues.dat
index f8fc44b91a..f57594a47d 100644
--- a/t/porting/known_pod_issues.dat
+++ b/t/porting/known_pod_issues.dat
@@ -440,3 +440,4 @@ porting/epigraphs.pod Verbatim line length including indents exceeds 78 by -1
porting/release_managers_guide.pod Verbatim line length including indents exceeds 78 by 8
lib/benchmark.pm Verbatim line length including indents exceeds 78 by 2
lib/config.pod ? Should you be using L<...> instead of -1
+lib/config.pod Verbatim line length including indents exceeds 78 by 2
diff --git a/win32/config.gc b/win32/config.gc
index f59de8859b..78cc025761 100644
--- a/win32/config.gc
+++ b/win32/config.gc
@@ -1156,6 +1156,7 @@ usedevel='undef'
usedl='define'
usedtrace='undef'
usefaststdio='undef'
+usegetexecpath='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='define'
diff --git a/win32/config.vc b/win32/config.vc
index d9939f52af..2bd09b5789 100644
--- a/win32/config.vc
+++ b/win32/config.vc
@@ -1155,6 +1155,7 @@ usedevel='undef'
usedl='define'
usedtrace='undef'
usefaststdio='undef'
+usegetexecpath='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='define'