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

Resolving correct directory path in a symlinked directory

by beermad (Novice)
on Apr 29, 2011 at 12:55 UTC ( [id://901973]=perlquestion: print w/replies, xml ) Need Help??

beermad has asked for the wisdom of the Perl Monks concerning the following question:

I need to re-use a common cgi-bin subdirectory for a number of websites I'm developing on my server. So the logical method would be:

$ mkdir /www/common/cgi-bin $ cd /www/site1 $ ln -s /www/common/cgi-bin $ cd /www/site2 $ ln -s /www/common/cgi-bin

which works perfectly, EXCEPT that in order to extract site-specific parameters, the cgi scripts need to read files in each individual site's own directory structure. But when resolving relative paths (I can't use absolute because of the nature of the eventual deployment environments) or even the current directory itself, my Perl scripts consider themselves to be in the original directory, not the one it SHOULD think it's in. To clarify:

#!/usr/bin/perl # whereami.pl use Cwd; print(cwd / "\n");
$ cd /www/global/cgi-bin $ whereami.pl /www/global/cgi-bin $ cd /www/site1/cgi-bin $ whereami.pl /www/global/cgi-bin

Similarly, trying to open a file with a relative path from /www/site1/cgi-bin fails because Perl's trying to open it relative to /www/global/cgi-bin.

So, is there a way to either resolve the "correct" path to the current directory in this situation, or at least to persuade it to open files with relative paths as I need?

The problem seems to be as much related to the Linux filesystem as to Perl itself, as

$ cd /www/site1/cgi-bin $ ls ..

Shows the contents of /www/global, not /www/site1.

Thanks in advance for any suggestions.

Replies are listed 'Best First'.
Re: Resolving correct directory path in a symlinked directory
by moritz (Cardinal) on Apr 29, 2011 at 13:02 UTC
Re: Resolving correct directory path in a symlinked directory
by toolic (Bishop) on Apr 29, 2011 at 13:05 UTC
    Likely to be unrelated to your problem, but does your whereami.pl have a typo? I get an error when I run it:
    $ whereami.pl Search pattern not terminated at whereami.pl line 4.
    No error if I change the print to:
    print cwd(), "\n";
      You're right - typed it wrong when I was putting in the example.
Re: Resolving correct directory path in a symlinked directory
by jpl (Monk) on Apr 29, 2011 at 13:53 UTC

    According to perldoc Cwd, you might get better results if you invoke getcwd() rather than cwd(). The documentation is a bit vague about how symlinks are treated, but what you need is something that will walk its way up the directory hierarchy, ignoring possible hints from environment variables like PWD, or invoking commands that might employ such hints,

      Unfortunately getcwd() returns the same result as cwd.

      However, your other comments prompted me to look at $ENV{PWD} - and that variable actually contains the correct path (as I was hoping to find it). So that solves my problem. Thanks.

        $ENV{'PWD'} is set by the shell (or by the Cwd module when importing the modified chdir function from it) -- but there is no shell when CGI programs are invoked (except when the CGI program is a shell script). And to make things worse, the CGI specification (no longer available at the original site) has no common specification for the current working directory (cwd). Even the CGI RFC 3875, written much later, has only a very restricted specification:

        AmigaDOS
        The current working directory for the script is set to the directory containing the script.
        UNIX compatible operating systems
        The current working directory for the script SHOULD be set to the directory containing the script.
        POSIX compatible operating systems using the EBCDIC character set
        The current working directory for the script SHOULD be set to the directory containing the script.

        So, the cwd problem is only solved for AmigaDOS, which is really common among web hosters today. ;-) If you consider your OS "UNIX compatible" or "POSIX compatible using the EBCDIC character set", you SHOULD set the cwd to the directory containing the script, but you DON'T HAVE TO do so. You can freely set the cwd to any other directory you like, e.g. / or /var/empty, without violating the RFC or the original specification. For every other operating system, you are free to set the cwd to whatever directory you like, if the operating system has the concept of a cwd.

        Next problem: Even if your operating system looks roughly like UNIX, is it really UNIX? Probably NOT. Wikipedia lists: Systems licensed to use the UNIX trademark include AIX, HP-UX, IRIX, Solaris, Tru64 (formerly "Digital UNIX"), A/UX, Mac OS X, and a part of z/OS. No Linux. No BSD.

        So, your operating system looks like UNIX, but it is not "UNIX" in that sense. Perhaps it is POSIX compatible? Well, the RFC does not specify the cwd except if your operating system also uses the EBCDIC charset, and even then, the wording is "SHOULD", not "MUST". Neither Linux nor *BSD uses EBCDIC, perhaps except on machines rarely used for web hosting.

        Windows? POSIX compatible? It doesn't even implement fork() and exec() -- but you can add some compatibility layers. But even then, Windows won't use EBCDIC.

        So, the cwd is undefined except for AmigaDOS. Unless you know what web server you use, how it implements the CGI, and what parts of the implementation are guaranteed (i.e. documented).

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

        ...and as a bonus, Apache exports a very useful environment variable for the purposes of this: SCRIPT_FILENAME.

Re: Resolving correct directory path in a symlinked directory
by graff (Chancellor) on May 01, 2011 at 18:20 UTC
    I don't know if the previous replies actually gave you satisfaction, but just for my own edification, I tried a little script like this:
    #!/usr/bin/perl use strict; use CGI; use Data::Dumper 'Dumper'; my $c = new CGI; print $c->header, $c->start_html, "<p> The script name is $0 </p>", '<pre>', Dumper( \%ENV ), '</pre>',$c->end_html;

    When I put that in the cgi-bin directory for the apache server on my macosx laptop, I found that the value of $0 was the absolute physical path of the script; this happens to match the value of $ENV{SCRIPT_FILENAME}.

    I think what you want is $ENV{SCRIPT_NAME} (note the difference), which (in my case at least) was the path as given in the url requested by the browser. So try that on your various server urls, and see if that %ENV element behaves as hoped for (i.e. gives a different name depending on which url you use).

    If it does, then all you need is to add site-specific config files (or site-specific directories of config data) in your common (symlinked) path, and make sure the common cgi script checks the SCRIPT_NAME environment variable first, so it knows which config data to use for the given server.

    UPDATE -- Ah, I just noticed the reply above that mentions $ENV{SCRIPT_NAME} -- so my post is redundant (except that it shows an easy way to confirm what you already found out).

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (7)
As of 2024-03-28 12:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found