From ae60cb464cebf89579ec0ff91db8b792b2f1e7cd Mon Sep 17 00:00:00 2001 From: Nicholas Clark Date: Wed, 21 Sep 2011 15:33:09 +0100 Subject: [PATCH] Where available, use _NSGetExecutablePath() to make $^X absolute. In Configure, check whether _NSGetExecutablePath() can be used to find the absolute pathname of the executable. If so, set usensgetexecutablepath in config.sh and USE_NSGETEXECUTABLEPATH 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 OS X, and possible on other platforms that use dyld. --- Configure | 102 ++++++++++++++++++++++++++++++++++++++++++++++ Cross/config.sh-arm-linux | 1 + NetWare/config.wc | 1 + Porting/Glossary | 5 +++ Porting/config.sh | 1 + config_h.SH | 7 ++++ configure.com | 1 + epoc/config.sh | 1 + perl.c | 24 +++++++++++ plan9/config_sh.sample | 1 + symbian/config.sh | 1 + t/op/magic.t | 3 +- uconfig.h | 11 ++++- uconfig.sh | 1 + uconfig64.sh | 1 + win32/config.ce | 1 + win32/config.gc | 1 + win32/config.gc64 | 1 + win32/config.gc64nox | 1 + win32/config.vc | 1 + win32/config.vc64 | 1 + 21 files changed, 164 insertions(+), 3 deletions(-) diff --git a/Configure b/Configure index 691bd81..1f0dbef 100755 --- a/Configure +++ b/Configure @@ -1229,6 +1229,7 @@ nm_opt='' nm_so_opt='' runnm='' usenm='' +usensgetexecutablepath='' useperlio='' usesocks='' d_oldpthreads='' @@ -19462,6 +19463,106 @@ $rm_try set usekernprocpathname eval $setvar +: Determine if we can use _NSGetExecutablePath to find executing program +echo " " +echo "Determining whether we can use _NSGetExecutablePath 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 +#include +#include +#include +#include + +int +main(int argc, char **argv) { + char buf[1]; + uint32_t size = sizeof(buf); + int result; + char *buffer; + char *tidied; + char *argv_leaf = strrchr(argv[0], '/'); + char *tidied_leaf; + + if (!argv_leaf) { + fprintf(stderr, "Can't locate / in '%s'\n", argv[0]); + return 1; + } + + _NSGetExecutablePath(buf, &size); + if (size > MAXPATHLEN * MAXPATHLEN) { + fprintf(stderr, "_NSGetExecutablePath size %u is too long for a path\n", + (unsigned int) size); + return 2; + } + + buffer = malloc(size); + if (!buffer) { + perror("malloc"); + return 3; + } + + result = _NSGetExecutablePath(buffer, &size); + if (result != 0) { + fprintf(stderr, "_NSGetExecutablePath returned %i for a size of %u\n", + result, (unsigned int) size); + return 4; + } + + tidied = realpath(buffer, NULL); + if (!tidied) { + perror("realpath"); + return 5; + } + + free(buffer); + + if (*tidied != '/') { + fprintf(stderr, "Not an absolute path: '%s'\n", tidied); + return 6; + } + + if (strstr(tidied, "/./")) { + fprintf(stderr, "Contains /./: '%s'\n", tidied); + return 7; + } + + if (strstr(tidied, "/../")) { + fprintf(stderr, "Contains /../: '%s'\n", tidied); + return 8; + } + + tidied_leaf = strrchr(tidied, '/'); + if (strcmp(tidied_leaf, argv_leaf) != 0) { + fprintf(stderr, "Leafnames differ: '%s' vs '%s'\n", argv[0], tidied); + return 9; + } + + free(tidied); + + return 0; +} +EOM + +val=$undef +set try +if eval $compile_ok; then + if $run ./try; then + echo "You can use _NSGetExecutablePath to find the executing program." >&4 + val="$define" + else + echo "Nope, _NSGetExecutablePath doesn't work here." >&4 + fi +else + echo "I'm unable to compile the test program." >&4 + echo "I'll assume no _NSGetExecutablePath here." >&4 +fi +$rm_try +set usensgetexecutablepath +eval $setvar + : Check how to flush echo " " $cat >&4 <$CONFIG_H -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un */ #$usekernprocpathname USE_KERN_PROC_PATHNAME /**/ +/* USE_NSGETEXECUTABLEPATH: + * This symbol, if defined, indicates that we can use _NSGetExecutablePath + * and realpath to get a full path for the executable, and hence convert + * $^X to an absolute path. + */ +#$usensgetexecutablepath USE_NSGETEXECUTABLEPATH /**/ + /* 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 diff --git a/configure.com b/configure.com index a58f77e..5da5973 100644 --- a/configure.com +++ b/configure.com @@ -6718,6 +6718,7 @@ $ WC "useieee='" + useieee + "'" ! VMS-specific $ WC "useithreads='" + useithreads + "'" $ WC "usekernelthreads='" + usekernelthreads + "'" ! VMS-specific $ WC "usekernprocpathname='undef'" +$ WC "usensgetexecutablepath='undef'" $ WC "uselargefiles='" + uselargefiles + "'" $ WC "uselongdouble='" + uselongdouble + "'" $ WC "usemorebits='" + usemorebits + "'" diff --git a/epoc/config.sh b/epoc/config.sh index b71d62e..c805890 100644 --- a/epoc/config.sh +++ b/epoc/config.sh @@ -991,6 +991,7 @@ usemorebits='undef' usemultiplicity='undef' usemymalloc='n' usenm='' +usensgetexecutablepath='undef' useopcode='' useperlio='undef' useposix='' diff --git a/perl.c b/perl.c index 5d2159d..4285834 100644 --- a/perl.c +++ b/perl.c @@ -42,6 +42,10 @@ # include #endif +#ifdef USE_NSGETEXECUTABLEPATH +# include +#endif + #ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP # ifdef I_SYSUIO # include @@ -1414,6 +1418,26 @@ S_set_caret_X(pTHX) { return; } } +# elif defined(USE_NSGETEXECUTABLEPATH) + char buf[1]; + uint32_t size = sizeof(buf); + int result; + + _NSGetExecutablePath(buf, &size); + if (size < MAXPATHLEN * MAXPATHLEN) { + sv_grow(caret_x, size); + if (_NSGetExecutablePath(SvPVX(caret_x), &size) == 0) { + char *const tidied = realpath(SvPVX(caret_x), NULL); + if (tidied) { + sv_setpv(caret_x, tidied); + free(tidied); + } else { + SvPOK_only(caret_x); + SvCUR_set(caret_x, size); + } + return; + } + } # elif defined(HAS_PROCSELFEXE) char buf[MAXPATHLEN]; int len = readlink(PROCSELFEXE_PATH, buf, sizeof(buf) - 1); diff --git a/plan9/config_sh.sample b/plan9/config_sh.sample index b87320d..bd5da2f 100644 --- a/plan9/config_sh.sample +++ b/plan9/config_sh.sample @@ -1003,6 +1003,7 @@ usemorebits='undef' usemultiplicity='undef' usemymalloc='y' usenm='false' +usensgetexecutablepath='undef' useopcode='true' useperlio='define' useposix='true' diff --git a/symbian/config.sh b/symbian/config.sh index c72d8c3..a62577b 100644 --- a/symbian/config.sh +++ b/symbian/config.sh @@ -818,6 +818,7 @@ usemorebits='undef' usemultiplicity='undef' usemymalloc='n' usenm='false' +usensgetexecutablepath='undef' useopcode='true' useperlio='define' useposix='true' diff --git a/t/op/magic.t b/t/op/magic.t index 5569154..8c2c508 100644 --- a/t/op/magic.t +++ b/t/op/magic.t @@ -230,7 +230,8 @@ $$ = $pid; # Tests below use $$ # $^X and $0 { - my $is_abs = $Config{d_procselfexe} || $Config{usekernprocpathname}; + my $is_abs = $Config{d_procselfexe} || $Config{usekernprocpathname} + || $Config{usensgetexecutablepath}; if ($^O eq 'qnx') { chomp($wd = `/usr/bin/fullpath -t`); } diff --git a/uconfig.h b/uconfig.h index c5f19f7..c379902 100644 --- a/uconfig.h +++ b/uconfig.h @@ -2663,6 +2663,13 @@ */ /*#define USE_KERN_PROC_PATHNAME / **/ +/* USE_NSGETEXECUTABLEPATH: + * This symbol, if defined, indicates that we can use _NSGetExecutablePath + * and realpath to get a full path for the executable, and hence convert + * $^X to an absolute path. + */ +/*#define USE_NSGETEXECUTABLEPATH / **/ + /* 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 @@ -4711,6 +4718,6 @@ #endif /* Generated from: - * e6513dfa5f1449ab9266aee521d6d5908873d1dc68bf4f049316ebc4921732e1 config_h.SH - * e940950d07a2be0354d6ae7e4316ec8465ed581607bbb958d8bfda024b9941fe uconfig.sh + * 5b5dacbb00f53ae9b440c79cf6d5c8bbf80a7adfa1db3f3814aa77dc6f461fa7 config_h.SH + * b5e74633486412bbc4d2a1c3847f3e85b10a86e96fb5d1efb7b8bc885956d746 uconfig.sh * ex: set ro: */ diff --git a/uconfig.sh b/uconfig.sh index ee84d35..e7692dc 100644 --- a/uconfig.sh +++ b/uconfig.sh @@ -785,6 +785,7 @@ usemorebits='undef' usemultiplicity='undef' usemymalloc='n' usenm='false' +usensgetexecutablepath='undef' useopcode='true' useperlio='undef' useposix='true' diff --git a/uconfig64.sh b/uconfig64.sh index e3346e7..1ae544f 100644 --- a/uconfig64.sh +++ b/uconfig64.sh @@ -786,6 +786,7 @@ usemorebits='undef' usemultiplicity='undef' usemymalloc='n' usenm='false' +usensgetexecutablepath='undef' useopcode='true' useperlio='undef' useposix='true' diff --git a/win32/config.ce b/win32/config.ce index 8028928..62d2123 100644 --- a/win32/config.ce +++ b/win32/config.ce @@ -985,6 +985,7 @@ usemorebits='undef' usemultiplicity='undef' usemymalloc='n' usenm='false' +usensgetexecutablepath='undef' useopcode='true' useperlio='~USE_PERLIO~' useposix='true' diff --git a/win32/config.gc b/win32/config.gc index ff6eb6f..cb963fb 100644 --- a/win32/config.gc +++ b/win32/config.gc @@ -1028,6 +1028,7 @@ usemorebits='undef' usemultiplicity='undef' usemymalloc='n' usenm='false' +usensgetexecutablepath='undef' useopcode='true' useperlio='undef' useposix='true' diff --git a/win32/config.gc64 b/win32/config.gc64 index e46b55a..7e06e2a 100644 --- a/win32/config.gc64 +++ b/win32/config.gc64 @@ -1029,6 +1029,7 @@ usemorebits='undef' usemultiplicity='undef' usemymalloc='n' usenm='false' +usensgetexecutablepath='undef' useopcode='true' useperlio='undef' useposix='true' diff --git a/win32/config.gc64nox b/win32/config.gc64nox index 82226e9..92ef05f 100644 --- a/win32/config.gc64nox +++ b/win32/config.gc64nox @@ -1029,6 +1029,7 @@ usemorebits='undef' usemultiplicity='undef' usemymalloc='n' usenm='false' +usensgetexecutablepath='undef' useopcode='true' useperlio='undef' useposix='true' diff --git a/win32/config.vc b/win32/config.vc index f578057..379a125 100644 --- a/win32/config.vc +++ b/win32/config.vc @@ -1028,6 +1028,7 @@ usemorebits='undef' usemultiplicity='undef' usemymalloc='n' usenm='false' +usensgetexecutablepath='undef' useopcode='true' useperlio='undef' useposix='true' diff --git a/win32/config.vc64 b/win32/config.vc64 index 86b4040..d429f20 100644 --- a/win32/config.vc64 +++ b/win32/config.vc64 @@ -1028,6 +1028,7 @@ usemorebits='undef' usemultiplicity='undef' usemymalloc='n' usenm='false' +usensgetexecutablepath='undef' useopcode='true' useperlio='undef' useposix='true' -- 2.7.4