Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

If I install a binary with non-standard prefix, e.g. /opt/bin/foo, which needs some static files from /opt/share/foo, how does it find them? Using back references relative to the executable (../share/foo)? Hardcoded at compile time?

What's the idiomatic way for an application to handle variable installation prefix? Should all directories be prefixed? (what about /var?)

share|improve this question
add comment

5 Answers 5

up vote 7 down vote accepted

It's common to hard-code such references at compile time, and perhaps provide a command line option or environment variable to override the compile-time default. Often the program just remembers the location of one configuration file (typically under /etc) where any compile-time defaults can be overridden. This approach makes most sense for open source software that is compiled by the same people that make the operating system, as part of a Linux distribution or BSD ports.

For applications distributed in a binary form, the usual approach is to locate the application binary from its zeroth argument. By convention, the zeroth argument to execve (i.e. argv[0]) is the path to the binary (it's up to the caller, often a shell, to respect the convention). If argv[0] doesn't contain any /, the application should perform $PATH lookup on it.

share|improve this answer
    
Better than argv[0] is to do a readlink() to /proc/self/exe, when this file is available. If that fails, then you check argv[0] and $PATH. –  Juliano Jan 19 '11 at 15:44
1  
@Juliano: This works for Linux, but not all flavors of Unix have a /proc –  KeithB Jan 19 '11 at 18:17
    
@Juliano: Indeed /proc/self/exe is another possibility on Linux, though I'm not sure if it's always preferable. If you invoke a program through a symbolic link, /proc/self/exe links directly to the target, which is not always desirable. –  Gilles Jan 19 '11 at 18:28
    
Do binary distributed programs actually use argv[0] to get the install prefix? I mean, this even does not work when the binary is called via a symbolic link. Usually, binary programs are distributed via package managers, such that there is not a problem to compile-in the installation prefix. I noticed a binary distribution of some program (ghc), where the installer installed a wrapper shell script /usr/bin/foo which called the real foo with the install prefix as parameter. Similar, an installer could binary patch a proprietary distributed application with the correct installation prefix. –  maxschlepzig Jan 19 '11 at 21:29
    
@KeithB Not only that, it's not even required in Linux; it's a kernel option –  Michael Mrozek Mar 26 '11 at 0:04
add comment

I would say that the most common is detecting path provided by --prefix. Different paths can be provided by different prefixes and there are separate for system config ("/etc"), library directory ("/usr/lib") etc. in autotools

share|improve this answer
    
So, in other words, hardcoded? –  Alex B Jan 19 '11 at 0:22
add comment

Tools used to compile the program such as GNU Autotools can take the value of the --prefix option given and put it into a header file as a define.

#define PREFIX "/usr/local/"

And in your code you'd just use PREFIX as part of your path names.

share|improve this answer
add comment

There is also the dladdr() function in libc, which returns the path to the binary in which the given function pointer exists, but:

  • It only exists on Linux and SunOS according to the man page.
  • You have to compile executables with -rdynamic for it to work. I don't think libraries needs that.

For a library your options are far more limited: there is no argv[0] so your options are dladdr(), or the obscure hack of manual parsing of the Linux-only /proc/self/maps and looking for the memory address range containing the memory address of some library internal symbol (eg. a function pointer or a static variable).

Other solutions I've seen in the wild:

  • ./configure --prefix=SOME_UNIQUE_VERY_LONG_STRING, then at install time search and replace that long string in the binary (!!) with /path/to/actual/install/prefix/suffixed/by/enough/slashes////// and hope the user never renames anything in that path.
  • Virtualize the filesystem, either by chroot(), loop-mount, FUSE filesystem, hacked libc (Plash project), virtual machine, etc.
  • ./configure --prefix=.. and then never call chdir(). This will also break things if any path leaks out of the application and goes to another application, since the other application won't be able to correctly resolve the relative path.
  • Launch through a wrapper. Eg. Java applications always know their path via getClass().getProtectionDomain().getCodeSource().getLocation(), C# has Application.StartupPath among others, most scripting languages have some way.

POSIX should really standardize dladdr().

share|improve this answer
add comment

Unded Unix, there is no portable way to detect from which location the binary was started, i.e. a variable installation prefix is compiled in.

share|improve this answer
    
This is not entirely correct. In shell-scripts (Bash, Zsh) you can locate the binary using the first command line argument (i.e $0). In Python it is sys.argv[0]. –  phunehehe Jan 19 '11 at 11:27
2  
@phunehehe: There's no (portable) guarantee that argv[0] is the full path. –  ephemient Jan 19 '11 at 16:47
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.