4 * by Larry Wall and others
6 * You may distribute under the terms of either the GNU General Public
7 * License or the Artistic License, as specified in the README file.
15 /* This file contains a single function, set_caret_X, to set the $^X
16 * variable. It's only used in perl.c, but has various OS dependencies,
17 * so its been moved to its own file to reduce header pollution.
18 * See RT 120314 for details.
21 #if defined(PERL_IS_MINIPERL) && !defined(USE_SITECUSTOMIZE)
22 # define USE_SITECUSTOMIZE
33 #ifdef USE_KERN_PROC_PATHNAME
34 # include <sys/sysctl.h>
37 #ifdef USE_NSGETEXECUTABLEPATH
38 # include <mach-o/dyld.h>
41 /* Note: Functions in this file must not have bool parameters. When
42 PERL_BOOL_AS_CHAR is #defined, mach-o/dyld.h overrides it in this file
43 by #including stdbool.h, so the function parameters here would conflict
44 with those in proto.h.
48 Perl_set_caret_X(pTHX) {
50 GV* tmpgv = gv_fetchpvs("\030", GV_ADD|GV_NOTQUAL, SVt_PV); /* $^X */
52 SV *const caret_x = GvSV(tmpgv);
54 sv_setpv(caret_x, os2_execname(aTHX));
56 # ifdef USE_KERN_PROC_PATHNAME
61 mib[2] = KERN_PROC_PATHNAME;
64 if (sysctl(mib, 4, NULL, &size, NULL, 0) == 0
65 && size > 0 && size < MAXPATHLEN * MAXPATHLEN) {
66 sv_grow(caret_x, size);
68 if (sysctl(mib, 4, SvPVX(caret_x), &size, NULL, 0) == 0
71 SvCUR_set(caret_x, size - 1);
76 # elif defined(USE_NSGETEXECUTABLEPATH)
78 uint32_t size = sizeof(buf);
80 _NSGetExecutablePath(buf, &size);
81 if (size < MAXPATHLEN * MAXPATHLEN) {
82 sv_grow(caret_x, size);
83 if (_NSGetExecutablePath(SvPVX(caret_x), &size) == 0) {
84 char *const tidied = realpath(SvPVX(caret_x), NULL);
86 sv_setpv(caret_x, tidied);
90 SvCUR_set(caret_x, size);
95 # elif defined(HAS_PROCSELFEXE)
97 int len = readlink(PROCSELFEXE_PATH, buf, sizeof(buf) - 1);
99 /* On Playstation2 Linux V1.0 (kernel 2.2.1) readlink(/proc/self/exe)
100 includes a spurious NUL which will cause $^X to fail in system
101 or backticks (this will prevent extensions from being built and
102 many tests from working). readlink is not meant to add a NUL.
103 Normal readlink works fine.
105 if (len > 0 && buf[len-1] == '\0') {
109 /* FreeBSD's implementation is acknowledged to be imperfect, sometimes
110 returning the text "unknown" from the readlink rather than the path
111 to the executable (or returning an error from the readlink). Any
112 valid path has a '/' in it somewhere, so use that to validate the
113 result. See http://www.freebsd.org/cgi/query-pr.cgi?pr=35703
115 if (len > 0 && memchr(buf, '/', len)) {
116 sv_setpvn(caret_x, buf, len);
120 /* Fallback to this: */
121 sv_setpv(caret_x, PL_origargv[0]);
128 * c-indentation-style: bsd
130 * indent-tabs-mode: nil
133 * ex: set ts=8 sts=4 sw=4 et: