Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

mpeters (5802)

mpeters
  (email not shown publicly)
http://petersfamily.org/
AOL IM: michael00peters (Add Buddy, Send Message)

Technorati Profile [technorati.com]

Journal of mpeters (5802)

Thursday May 15, 2008
06:05 PM

LD_LIBRARY_PATH trick

[ #36433 ]
I have this problem a lot. I need to link some Perl module against some C library that is not in the standard system libs. Usually this is because it's a locally installed C thingy (like Swish-e or some payment processor API) that I don't want to pollute the system install. Plus it's nice and easy if the whole application is all bundled together.

The easy way to do this is to set the $ENV{LD_LIBRARY_PATH} from your shell to point to the right place. But this is a bother, and not to mention really hard to do if you need some dynamic bits to figure out what the right path is.

And for security reasons, programs can't set their own local version of LD_LIBRARY_PATH and have it be respected by the system's loader. It has to be done by the calling process (in most cases the shell).

This little trick let's a script set it's own LD_LIBRARY_PATH by relaunching the same program with the same arguments as a new sub-process. Simply put a BEGIN block like this in your script:

BEGIN {
    if(! $ENV{LD_LIBRARY_PATH} ) {
        $ENV{LD_LIBRARY_PATH} = join(':', @some_paths_I_need);
        my $self_cmd = "$^X $0 " . join(' ', @ARGV);
        system($self_cmd);
        exit;
    }
}

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • otherwise the shell might hose you.
    • Might? With that broken join I’d say it’s a certainty that at some point the shell will hose him. Plus it’s less and simpler code:

      BEGIN {
          if(! $ENV{LD_LIBRARY_PATH} ) {
              $ENV{LD_LIBRARY_PATH} = join(':', @some_paths_I_need);
              system($^X, $0, @ARGV);
              exit;
          }
      }

      Also: why system(...); exit and not exec?

      • Just out of curiousity, why is that join broken?

        Also, I didn't use exec because I didn't know how the security restrictions around LD_LIBRARY_PATH were enforced. Using exec means the process continues to have the same pid, system gives me an entirely new process. I wasn't sure if having the same pid would allow me to do what I wanted to do.

        But thanks for the clarification. It works correctly (at least on the Linux machine I tried it on).
        • why is that join broken?

          Because you’re not shell-quoting anything. If there happens to be any space in there, the new copy of the script will have different @ARGV contents. That’s before we even get to other shell meta-characters.

    • You're right about using the list. I was actually debugging it to make sure the command was what I wanted it to be so I was combining it into a string so I could print it to the screen before executing. I just forgot to change it after the fact.