scripts/wrapper.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Sun Aug 30 16:54:30 2009 +0200 (2009-08-30)
changeset 1502 472cfde636a1
child 1504 4e8dd617a1ca
permissions -rw-r--r--
config: move the "build shared libraries" option to the OS menu

The "Build shared libraries" config option is dependant on the type of
"Target OS".

Moving this options to the "Target OS" sub-menu is also better in the user
perspective: he/she no longer needs to go back and forth to see if he/she
missed any option.
     1 #include <limits.h>
     2 #include <stdlib.h>
     3 #include <stdio.h>
     4 #include <string.h>
     5 #include <sys/types.h>
     6 #include <sys/stat.h>
     7 #include <unistd.h>
     8 #include <errno.h>
     9 
    10 
    11 /* Needed for execve */
    12 extern char **environ;
    13 
    14 int main( int argc,
    15           char** argv )
    16 {
    17   char *fullname;   /* 'fullname' is used to store the absolute path to the
    18                        tool being executed; it serves as a base to compute
    19                        the realname of that tool, and the directory holding
    20                        our runtime libraries */
    21   char *realname;   /* 'realname' is the real name of the tool, that is what
    22                        the wrapper is currently impersonating */
    23   char *basedir;    /* 'libdir' contains our runtime libraries */
    24 
    25   char *lastslash;  /* Temporary variables now */
    26   char *ldlibpath;
    27   size_t len;
    28   int execve_ret;
    29 
    30   /* In case we have a relative or absolute pathname (ie. contains a slash),
    31    * then realpath wll work. But if the tool was found in the PATH, realpath
    32    * won't work, and we'll have to search ourselves.
    33    * This if{}else{} block allocates memory for fullname. */
    34   if( strchr( argv[0], '/' ) ) {
    35     fullname = (char*) malloc( PATH_MAX * sizeof(char) );
    36     if( ! realpath( argv[0], fullname ) ) {
    37       perror( "tool wrapper" );
    38       exit( 1 );
    39     }
    40   } else {
    41     char *path;
    42     char *mypath;
    43     char *colon;
    44     char *testname;
    45     struct stat st;
    46 
    47     fullname = NULL;
    48     colon = mypath = path = strdup( getenv( "PATH" ) );
    49     while( colon ) {
    50       colon = strchr( mypath, ':' );
    51       if( colon ) {
    52         *colon = '\0';
    53       }
    54       testname = strdup( mypath );
    55       testname = (char*) realloc( testname,   strlen( testname )
    56                                             + strlen( argv[0] )
    57                                             + 2 * sizeof(char) );
    58       memset( testname + strlen( testname ),
    59               0,
    60               strlen( argv[0] ) + 2 * sizeof(char) );
    61       strcat( testname, "/" );
    62       strcat( testname, argv[0] );
    63       if( stat( testname, &st ) == 0 ) {
    64         /* OK, exists. Is it a regular file, or a
    65          * symlink, which the current user may execute? */
    66         if( S_ISREG( st.st_mode ) && ! access( testname, X_OK || R_OK ) ) {
    67           fullname = strdup( testname );
    68           break;
    69         }
    70       }
    71       free( testname );
    72       mypath = colon + 1;
    73     }
    74     free( path );
    75     if( ! fullname ) {
    76       fprintf( stderr, "tool wrapper: %s: command not found\n", argv[0] );
    77       exit( 1 );
    78     }
    79   }
    80 
    81   /* Duplicate my own name to add the 'dot' to tool name */
    82   realname = strdup( fullname );
    83   realname = (char*) realloc( realname, strlen( realname) + 2 * sizeof(char) );
    84   realname[ strlen( realname ) + 1 ] = '\0';
    85 
    86   /* Add the dot after the last '/' */
    87   lastslash = strrchr( realname, '/' );
    88   memmove( lastslash + 1, lastslash, strlen( lastslash ) );
    89   *( lastslash + 1 ) = '.';
    90 
    91   /* Compute the basedir of the tool */
    92   basedir = strdup( fullname );
    93   lastslash = strrchr( basedir, '/' );
    94   *lastslash = '\0';
    95   lastslash = strrchr( basedir, '/' );
    96   *lastslash = '\0';
    97 
    98   /* Append '/lib' */
    99   len = strlen( basedir );
   100   basedir = (char*) realloc( basedir, len + 5 );
   101   *( basedir + len ) = '\0';
   102   strcat( basedir, "/lib" );
   103 
   104   /* Now add the directory with our runtime libraries to the
   105      front of the library search path, LD_LIBRARY_PATH */
   106   ldlibpath = getenv( "LD_LIBRARY_PATH" );
   107   if( ldlibpath ) {
   108     basedir = (char*) realloc( basedir,   strlen( basedir )
   109                                         + strlen( ldlibpath )
   110                                         + 2 * sizeof(char) );
   111     strcat( basedir, ":" );
   112     strcat( basedir, ldlibpath );
   113   }
   114 
   115   if( setenv( "LD_LIBRARY_PATH", basedir, 1 ) ) {
   116     errno = ENOMEM;
   117     perror( "tool wrapper" );
   118     exit( 1 );
   119   }
   120 
   121   /* Execute the real tool, now */
   122   execve_ret = execve( realname, argv, environ );
   123 
   124   /* In case something went wrong above, print a
   125      diagnostic message, and exit with error code 1 */
   126   perror( "tool wrapper" );
   127   return 1;
   128 }