relocatable binaries and scripts

Once, somebody asked me about how to relocate scripts and binaries in a safe manner . Depending on what

you do it may not be as easy as looking in argv[0]. Hope this helps somebody else.


  • From shell script.
  
 #!/bin/sh

where_am_i () {
cmd=`dirname $1`
case ${cmd} in
    /\*)
    cannon_cmd=${cmd}
    ;;
    \*/\*)
    _pwd=`pwd 2>/dev/null`
    cannon_cmd="${_pwd}/${cmd}"
    ;;
    \*)
    echo "ousp..."
    exit 1
    ;;
esac
echo "$cannon_cmd" | awk -F/ '{
    realpath="";
    skip_it=0;
    for (i=NF; i>0; i--) {
        if ($i         == ".")                         continue;
        if (length($i) == 0&& i != 1)       continue;
        if ($i         == "..") {skip_it++; continue;}
        if (skip_it    > 0 )    {
            skip_it--;
            continue;
        }
        if (length(realpath) > 0) {
                   realpath=$i"/"realpath;
                } else {
                   realpath=$i;
                }
    }
    } END {print realpath}' 2>/dev/null
}

res=`where_am_i $0`

echo "resolved command line <$res>"

 

 this will produce output like

#/tmp/a.sh
resolved command line </tmp/>
#/var/tmp/..//../tmp/a.sh
resolved command line </tmp/>
#/var/tmp/..//../tmp/./a.sh
resolved command line </tmp/>


  • from BAT file

    @ECHO OFF
    setlocal

    set canonBaseDir=%~dp0 

     ....

    endlocal

    .
  •  From perl module

 

use FindBin;

# add our module repository to perl @INC
use lib "$FindBin::RealBin";

#.... later in a sub module

my ($mod_package,$mod_name) = split (/::/,__PACKAGE__);
 
  my $modnameToPath=catfile($mod_package,$mod_name);
  $modnameToPath.=".pm";
 
  foreach my $v (@INC) {   
    my $loaded_file = catfile($v,$modnameToPath);
    if ( -e $loaded_file ) {
      # we were loaded from $loaded_file
      $relocation_base = canonpath(dirname($loaded_file));
      last;
    }
  }




 

  • From a binary on Solaris

#include <dlfcn.h>

Dl_info dli;
dladdr((void\*)&main,&dli);
printf("resolved cmd : %s\\n",(char\*)mydlinfo.dli_fname);


  • From a binary on Linux
max = pathconf("/",_PC_PATH_MAX);
buf = (char\*)malloc(max + 1);
end = readlink("/proc/self/exe",buf,max);
buf[end] = '\\0';
printf("resolved cmd : %s\\n",buf);

  • From a binary on AIX
struct ld_info \*myld_info;
loadquery(L_GETINFO, buf, size);
myld_info = (struct ld_info \*)buf;
printf("resolved cmd : %s\\n",myld_info->ldinfo_filename);

  • From a binary on HP-UX
struct shl_descriptor \*desc;
shl_gethandle(PROG_HANDLE,&desc);
//Note : may need to prepend pwd to desc->filename
printf("resolved cmd : %s\\n",desc->filename);



  • From a win32 binary
GetModuleFileName(NULL, buffer,<buffer length>);
printf("resolved cmd : %s\\n",desc->filename);



Comments:

On solaris there is getexecname as well. You can also use dlinfo with RTLD_SELF so this also works for libraries.

Posted by Marc on février 06, 2008 at 06:05 AM CET #

Hi,

dladdr also works for libraries , no ?
In my example I choose the 'main' function but it
can be any symbol.

Posted by ejannett on février 06, 2008 at 07:54 AM CET #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Emmanuel Jannetti blog

Search

Archives
« juillet 2014
lun.mar.mer.jeu.ven.sam.dim.
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   
       
Today