Skip to content

Commit

Permalink
Where available, use sysctl() with KERN_PROC_PATHNAME to make $^X abs…
Browse files Browse the repository at this point in the history
…olute.

In Configure, check whether sysctl() and KERN_PROC_PATHNAME can be used
to find the absolute pathname of the executable. If so, set
usekernprocpathname in config.sh and USE_KERN_PROC_PATHNAME 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 (at least) FreeBSD, and
doesn't rely on the /proc filesystem existing, or /proc/curproc/file being
present.
  • Loading branch information
nwc10 committed Sep 27, 2011
1 parent 2480ae1 commit 2982a34
Show file tree
Hide file tree
Showing 21 changed files with 181 additions and 5 deletions.
117 changes: 117 additions & 0 deletions Configure
Expand Up @@ -1234,6 +1234,7 @@ usesocks=''
d_oldpthreads=''
use5005threads=''
useithreads=''
usekernprocpathname=''
usereentrant=''
usethreads=''
incpath=''
Expand Down Expand Up @@ -19346,6 +19347,121 @@ $rm_try
set ebcdic
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
$cat >try.c <<'EOM'
/* Intentionally a long probe as I'd like to sanity check that the exact
approach is going to work, as thinking it will work, but only having it
part working at runtime is worse than not having it. */

#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/param.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char **argv) {
char *buffer;
char *argv_leaf = strrchr(argv[0], '/');
char *buffer_leaf;
size_t size = 0;
int mib[4];

mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;

if (!argv_leaf) {
fprintf(stderr, "Can't locate / in '%s'\n", argv[0]);
return 1;
}

if (sysctl(mib, 4, NULL, &size, NULL, 0)) {
perror("sysctl");
return 2;
}

if (size < strlen(argv_leaf) + 1) {
fprintf(stderr, "size %lu is too short for a path\n",
(unsigned long) size);
return 3;
}

if (size > MAXPATHLEN * MAXPATHLEN) {
fprintf(stderr, "size %lu is too long for a path\n",
(unsigned long) size);
return 4;
}

buffer = malloc(size);
if (!buffer) {
perror("malloc");
return 5;
}

if (sysctl(mib, 4, buffer, &size, NULL, 0)) {
perror("sysctl");
return 6;
}

if (strlen(buffer) + 1 != size) {
fprintf(stderr, "size != strlen(buffer) + 1 (%lu != %lu)\n",
(unsigned long)size, (unsigned long)strlen(buffer) + 1);
return 7;
}


if (*buffer != '/') {
fprintf(stderr, "Not an absolute path: '%s'\n", buffer);
return 8;
}

if (strstr(buffer, "/./")) {
fprintf(stderr, "Contains /./: '%s'\n", buffer);
return 9;
}

if (strstr(buffer, "/../")) {
fprintf(stderr, "Contains /../: '%s'\n", buffer);
return 10;
}

buffer_leaf = strrchr(buffer, '/');
if (strcmp(buffer_leaf, argv_leaf) != 0) {
fprintf(stderr, "Leafnames differ: '%s' vs '%s'\n", argv[0], buffer);
return 11;
}

free(buffer);

return 0;
}
EOM

val=$undef
set try
if eval $compile_ok; then
if $run ./try; then
echo "You can use sysctl with KERN_PROC_PATHNAME to find the executing program." >&4
val="$define"
else
echo "Nope, sysctl with KERN_PROC_PATHNAME doesn't work here." >&4
val="$undef"
fi
else
echo "I'm unable to compile the test program." >&4
echo "I'll assume no sysctl with KERN_PROC_PATHNAME here." >&4
val="$undef"
fi
$rm_try
set usekernprocpathname
eval $setvar

: Check how to flush
echo " "
$cat >&4 <<EOM
Expand Down Expand Up @@ -23434,6 +23550,7 @@ usedl='$usedl'
usedtrace='$usedtrace'
usefaststdio='$usefaststdio'
useithreads='$useithreads'
usekernprocpathname='$usekernprocpathname'
uselargefiles='$uselargefiles'
uselongdouble='$uselongdouble'
usemallocwrap='$usemallocwrap'
Expand Down
1 change: 1 addition & 0 deletions Cross/config.sh-arm-linux
Expand Up @@ -1024,6 +1024,7 @@ usedl='define'
usedtrace='undef'
usefaststdio='define'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='define'
uselongdouble='undef'
usemallocwrap='define'
Expand Down
1 change: 1 addition & 0 deletions NetWare/config.wc
Expand Up @@ -987,6 +987,7 @@ usedl='define'
usedtrace='undef'
usefaststdio='undef'
useithreads='define'
usekernprocpathname='undef'
uselargefiles='undef'
uselongdouble='undef'
usemallocwrap='undef'
Expand Down
5 changes: 5 additions & 0 deletions Porting/Glossary
Expand Up @@ -5015,6 +5015,11 @@ useithreads (usethreads.U):
and indicates that Perl should be built to use the interpreter-based
threading implementation.

usekernprocpathname (usekernprocpathname.U)
This variable, indicates that we can use sysctl with
KERN_PROC_PATHNAME to get a full path for the executable, and hence
convert $^X to an absolute path.

uselargefiles (uselfs.U):
This variable conditionally defines the USE_LARGE_FILES symbol,
and indicates that large file interfaces should be used when
Expand Down
1 change: 1 addition & 0 deletions Porting/config.sh
Expand Up @@ -1046,6 +1046,7 @@ usedl='define'
usedtrace='undef'
usefaststdio='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='define'
uselongdouble='undef'
usemallocwrap='define'
Expand Down
7 changes: 7 additions & 0 deletions config_h.SH
Expand Up @@ -2689,6 +2689,13 @@ sed <<!GROK!THIS! >$CONFIG_H -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un
*/
#$ebcdic EBCDIC /**/
/* 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
* convert $^X to an absolute path.
*/
#$usekernprocpathname USE_KERN_PROC_PATHNAME /**/
/* Fpos_t:
* This symbol holds the type used to declare file positions in libc.
* It can be fpos_t, long, uint, etc... It may be necessary to include
Expand Down
1 change: 1 addition & 0 deletions configure.com
Expand Up @@ -6717,6 +6717,7 @@ $ WC "usefaststdio='" + usefaststdio + "'"
$ WC "useieee='" + useieee + "'" ! VMS-specific
$ WC "useithreads='" + useithreads + "'"
$ WC "usekernelthreads='" + usekernelthreads + "'" ! VMS-specific
$ WC "usekernprocpathname='undef'"
$ WC "uselargefiles='" + uselargefiles + "'"
$ WC "uselongdouble='" + uselongdouble + "'"
$ WC "usemorebits='" + usemorebits + "'"
Expand Down
1 change: 1 addition & 0 deletions epoc/config.sh
Expand Up @@ -983,6 +983,7 @@ usedl='undef'
usedtrace='undef'
usefaststdio='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='undef'
uselongdouble='undef'
usemallocwrap='undef'
Expand Down
26 changes: 25 additions & 1 deletion perl.c
Expand Up @@ -38,6 +38,10 @@
#include "nwutil.h"
#endif

#ifdef USE_KERN_PROC_PATHNAME
# include <sys/sysctl.h>
#endif

#ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
# ifdef I_SYSUIO
# include <sys/uio.h>
Expand Down Expand Up @@ -1390,7 +1394,27 @@ S_set_caret_X(pTHX) {
#if defined(OS2)
sv_setpv(caret_x, os2_execname(aTHX));
#else
# ifdef HAS_PROCSELFEXE
# ifdef USE_KERN_PROC_PATHNAME
size_t size = 0;
int mib[4];
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;

if (sysctl(mib, 4, NULL, &size, NULL, 0) == 0
&& size > 0 && size < MAXPATHLEN * MAXPATHLEN) {
sv_grow(caret_x, size);

if (sysctl(mib, 4, SvPVX(caret_x), &size, NULL, 0) == 0
&& size > 2) {
SvPOK_only(caret_x);
SvCUR_set(caret_x, size - 1);
SvTAINT(caret_x);
return;
}
}
# elif defined(HAS_PROCSELFEXE)
char buf[MAXPATHLEN];
int len = readlink(PROCSELFEXE_PATH, buf, sizeof(buf) - 1);

Expand Down
1 change: 1 addition & 0 deletions plan9/config_sh.sample
Expand Up @@ -995,6 +995,7 @@ usedl='undef'
usedtrace='undef'
usefaststdio='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='define'
uselongdouble='undef'
usemallocwrap='undef'
Expand Down
1 change: 1 addition & 0 deletions symbian/config.sh
Expand Up @@ -810,6 +810,7 @@ usedl='undef'
usedtrace='undef'
usefaststdio='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='undef'
uselongdouble='undef'
usemallocwrap='define'
Expand Down
5 changes: 3 additions & 2 deletions t/op/magic.t
Expand Up @@ -230,10 +230,11 @@ $$ = $pid; # Tests below use $$

# $^X and $0
{
my $is_abs = $Config{d_procselfexe} || $Config{usekernprocpathname};
if ($^O eq 'qnx') {
chomp($wd = `/usr/bin/fullpath -t`);
}
elsif($Is_Cygwin || $Config{'d_procselfexe'}) {
elsif($Is_Cygwin || $is_abs) {
# Cygwin turns the symlink into the real file
chomp($wd = `pwd`);
$wd =~ s#/t$##;
Expand All @@ -248,7 +249,7 @@ $$ = $pid; # Tests below use $$
else {
$wd = '.';
}
my $perl = $Is_VMS || $Config{d_procselfexe} ? $^X : "$wd/perl";
my $perl = $Is_VMS || $is_abs ? $^X : "$wd/perl";
my $headmaybe = '';
my $middlemaybe = '';
my $tailmaybe = '';
Expand Down
11 changes: 9 additions & 2 deletions uconfig.h
Expand Up @@ -2656,6 +2656,13 @@
*/
/*#define EBCDIC / **/

/* 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
* convert $^X to an absolute path.
*/
/*#define USE_KERN_PROC_PATHNAME / **/

/* Fpos_t:
* This symbol holds the type used to declare file positions in libc.
* It can be fpos_t, long, uint, etc... It may be necessary to include
Expand Down Expand Up @@ -4704,6 +4711,6 @@
#endif

/* Generated from:
* 5c3a0864433ad4da7f3248b108cf8e17c19bd4d71799cd56b6c2a73bb647561a config_h.SH
* e5d6d7ffdf6717946996c0807aa7a247b46adf41f2d98c62cdd7c1bb8ffe19f2 uconfig.sh
* e6513dfa5f1449ab9266aee521d6d5908873d1dc68bf4f049316ebc4921732e1 config_h.SH
* e940950d07a2be0354d6ae7e4316ec8465ed581607bbb958d8bfda024b9941fe uconfig.sh
* ex: set ro: */
1 change: 1 addition & 0 deletions uconfig.sh
Expand Up @@ -777,6 +777,7 @@ usedl='undef'
usedtrace='undef'
usefaststdio='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='undef'
uselongdouble='undef'
usemallocwrap='undef'
Expand Down
1 change: 1 addition & 0 deletions uconfig64.sh
Expand Up @@ -778,6 +778,7 @@ usedl='undef'
usedtrace='undef'
usefaststdio='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='undef'
uselongdouble='undef'
usemallocwrap='undef'
Expand Down
1 change: 1 addition & 0 deletions win32/config.ce
Expand Up @@ -977,6 +977,7 @@ usedl='define'
usedtrace='undef'
usefaststdio='undef'
useithreads='~USE_ITHREADS~'
usekernprocpathname='undef'
uselargefiles='undef'
uselongdouble='undef'
usemallocwrap='define'
Expand Down
1 change: 1 addition & 0 deletions win32/config.gc
Expand Up @@ -1020,6 +1020,7 @@ usedl='define'
usedtrace='undef'
usefaststdio='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='undef'
uselongdouble='undef'
usemallocwrap='define'
Expand Down
1 change: 1 addition & 0 deletions win32/config.gc64
Expand Up @@ -1021,6 +1021,7 @@ usedl='define'
usedtrace='undef'
usefaststdio='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='undef'
uselongdouble='undef'
usemallocwrap='define'
Expand Down
1 change: 1 addition & 0 deletions win32/config.gc64nox
Expand Up @@ -1021,6 +1021,7 @@ usedl='define'
usedtrace='undef'
usefaststdio='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='undef'
uselongdouble='undef'
usemallocwrap='define'
Expand Down
1 change: 1 addition & 0 deletions win32/config.vc
Expand Up @@ -1020,6 +1020,7 @@ usedl='define'
usedtrace='undef'
usefaststdio='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='undef'
uselongdouble='undef'
usemallocwrap='define'
Expand Down
1 change: 1 addition & 0 deletions win32/config.vc64
Expand Up @@ -1020,6 +1020,7 @@ usedl='define'
usedtrace='undef'
usefaststdio='undef'
useithreads='undef'
usekernprocpathname='undef'
uselargefiles='undef'
uselongdouble='undef'
usemallocwrap='define'
Expand Down

0 comments on commit 2982a34

Please sign in to comment.