Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Re: Poll: Is your $^X an absolute path? (argv[0])

by tye (Sage)
on Aug 17, 2006 at 14:04 UTC ( [id://567930]=note: print w/replies, xml ) Need Help??


in reply to Poll: Is your $^X an absolute path?

Win32 Perl has always had GetModulePathName() which means that Perl on Win32 will always have an absolute path for $^X. I think that Linux now has similar functionality.

However, other Unix platforms don't have a reliable way for an executable to figure out its filename. A Unix executable just gets argv[0] which can have absolutely nothing to do with the name of the executable. argv[0] will often be a path string that an algorithm like that used (perversely) by FindBin could be used to find the executable path.

If you want to know what happens on those platforms, I'd look at Perl's source code rather than try to conduct a poll.

Update: Here is the best way to prevent Perl from setting $^X to a real path:

system $^X "notPerl", '-le', 'print $^X'
which will produce "notPerl" on most non-Linux Unix platforms (and probably even on Linux for not-the-latest releases of Perl) but will produce the full path to your Perl executable on Win32 (even Win95).

- tye        

Replies are listed 'Best First'.
Re^2: Poll: Is your $^X an absolute path? (argv[0])
by ysth (Canon) on Aug 17, 2006 at 21:45 UTC
    If you want to know what happens on those platforms, I'd look at Perl's source code rather than try to conduct a poll.
    PROCSELFEXE_PATH is /proc/self/exe (Linux) or /proc/curproc/file (BSDish)
    #ifdef HAS_PROCSELFEXE /* This is a function so that we don't hold on to MAXPATHLEN bytes of stack longer than necessary */ STATIC void S_procself_val(pTHX_ SV *sv, const char *arg0) { char buf[MAXPATHLEN]; int len = readlink(PROCSELFEXE_PATH, buf, sizeof(buf) - 1); /* On Playstation2 Linux V1.0 (kernel 2.2.1) readlink(/proc/self/e +xe) includes a spurious NUL which will cause $^X to fail in system or backticks (this will prevent extensions from being built and many tests from working). readlink is not meant to add a NUL. Normal readlink works fine. */ if (len > 0 && buf[len-1] == '\0') { len--; } /* FreeBSD's implementation is acknowledged to be imperfect, somet +imes returning the text "unknown" from the readlink rather than the +path to the executable (or returning an error from the readlink). A +ny valid path has a '/' in it somewhere, so use that to validate the res +ult. See http://www.freebsd.org/cgi/query-pr.cgi?pr=35703 */ if (len > 0 && memchr(buf, '/', len)) { sv_setpvn(sv,buf,len); } else { sv_setpv(sv,arg0); } } #endif /* HAS_PROCSELFEXE */ STATIC void S_set_caret_X(pTHX) { dVAR; GV* tmpgv = gv_fetchpvs("\030", GV_ADD|GV_NOTQUAL, SVt_PV); /* $^X + */ if (tmpgv) { #ifdef HAS_PROCSELFEXE S_procself_val(aTHX_ GvSV(tmpgv), PL_origargv[0]); #else #ifdef OS2 sv_setpv(GvSVn(tmpgv), os2_execname(aTHX)); #else sv_setpv(GvSVn(tmpgv),PL_origargv[0]); #endif #endif } }
Re^2: Poll: Is your $^X an absolute path? (argv[0])
by xdg (Monsignor) on Aug 18, 2006 at 02:53 UTC
    Win32 Perl has always had GetModulePathName()

    At least my cursory grep didn't find that function in the perl source -- but perhaps it's called via some libraries or alias. It looks like it's just getting the name from whatever the compiler sets up as argv[0].

    Based on 'case 3' in this article, I thought it might be possible to spoof the executable name with a bogus argv[0] via CreateProcess, but my experiments with Win32::Process and Win32::Job weren't successful at getting anything other than the absolute path. I didn't try with Win32::API directly as that doesn't (yet) compile for Vanilla Perl.

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      Win32 Perl has always had GetModulePathName()
      At least my cursory grep didn't find that function in the perl source

      Sorry, my transcription error (s/Path/File/):

      perllib.c:171: GetModuleFileName(NULL, szModuleName, sizeof(szModul +eName)); win32.c:135: GetModuleFileName((HMODULE)((w32_perldll_handle == INV +ALID_HANDLE_VALUE) win32.c:136: ? GetModuleHandle(NULL)
      It looks like it's just getting the name from whatever the compiler sets up as argv[0].

      No, Win32 Perl has never figured out $^X based on argv[0] (except before it was released). The function called is os2_execna­me(aTHX) (yes, Win32 is consider OS/2-ish).

      - tye        

        No, Win32 Perl has never figured out $^X based on argv[0]

        I freely admit to being very new to reading the Perl source (what's that line about 'a maze of twisty passages'?) but what about this excerpt from perllib.c around the line you quoted (for Perl 5.8.8 anyway):

        EXTERN_C DllExport int RunPerl(int argc, char **argv, char **env) { int exitstatus; PerlInterpreter *my_perl, *new_perl = NULL; #ifndef __BORLANDC__ /* XXX this _may_ be a problem on some compilers (e.g. Borland) th +at * want to free() argv after main() returns. As luck would have i +t, * Borland's CRT does the right thing to argv[0] already. */ char szModuleName[MAX_PATH]; GetModuleFileName(NULL, szModuleName, sizeof(szModuleName)); (void)win32_longpath(szModuleName); argv[0] = szModuleName; #endif

        It looks like win32 Perl fixes up argv[0] itself -- and that this is what is used later by S_set_caret_X (a new function as of 5.8.7).

        However, that perllib.c line is a great find for Vanilla Perl -- it means we should be able to use relocatable perl pretty easily in most circumstances. (I'm not going to worry about mod_perl on win32 at first.)

        The downside is that the expansion uses the full path -- including spaces if installed somewhere like "C:\Program Files\Perl". That will still be problematic for people who call system("$^X program.pl arg1 arg2 etc") as the shell is going to have problems as the program name is not quoted. Of course -- that's not really a portable call anyway, so maybe we tackle that problem with documentation.

        -xdg

        Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://567930]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2024-04-25 12:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found