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