scripts/wrapper.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Sun Mar 20 00:02:21 2011 +0100 (2011-03-20)
changeset 2339 730e2d63296b
parent 1964 f02cfced8f55
permissions -rw-r--r--
scripts: leave changelog in build dir, copy to install dir

Users tend to look for the build log in the current working directory,
rather than in the toolchain's installation dir. While bundling the build
log in the toolchain installation dir is nice for distribution and review,
it can be easier to have the build log readily available in the working
directory, as it is quicker to get to it.

So, the build log stays in the working directory until the toolchain is
completely and successfully built, and then a (compressed) copy is made.

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