1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/scripts/wrapper.c Sun Aug 30 16:47:51 2009 +0200
1.3 @@ -0,0 +1,128 @@
1.4 +#include <limits.h>
1.5 +#include <stdlib.h>
1.6 +#include <stdio.h>
1.7 +#include <string.h>
1.8 +#include <sys/types.h>
1.9 +#include <sys/stat.h>
1.10 +#include <unistd.h>
1.11 +#include <errno.h>
1.12 +
1.13 +
1.14 +/* Needed for execve */
1.15 +extern char **environ;
1.16 +
1.17 +int main( int argc,
1.18 + char** argv )
1.19 +{
1.20 + char *fullname; /* 'fullname' is used to store the absolute path to the
1.21 + tool being executed; it serves as a base to compute
1.22 + the realname of that tool, and the directory holding
1.23 + our runtime libraries */
1.24 + char *realname; /* 'realname' is the real name of the tool, that is what
1.25 + the wrapper is currently impersonating */
1.26 + char *basedir; /* 'libdir' contains our runtime libraries */
1.27 +
1.28 + char *lastslash; /* Temporary variables now */
1.29 + char *ldlibpath;
1.30 + size_t len;
1.31 + int execve_ret;
1.32 +
1.33 + /* In case we have a relative or absolute pathname (ie. contains a slash),
1.34 + * then realpath wll work. But if the tool was found in the PATH, realpath
1.35 + * won't work, and we'll have to search ourselves.
1.36 + * This if{}else{} block allocates memory for fullname. */
1.37 + if( strchr( argv[0], '/' ) ) {
1.38 + fullname = (char*) malloc( PATH_MAX * sizeof(char) );
1.39 + if( ! realpath( argv[0], fullname ) ) {
1.40 + perror( "tool wrapper" );
1.41 + exit( 1 );
1.42 + }
1.43 + } else {
1.44 + char *path;
1.45 + char *mypath;
1.46 + char *colon;
1.47 + char *testname;
1.48 + struct stat st;
1.49 +
1.50 + fullname = NULL;
1.51 + colon = mypath = path = strdup( getenv( "PATH" ) );
1.52 + while( colon ) {
1.53 + colon = strchr( mypath, ':' );
1.54 + if( colon ) {
1.55 + *colon = '\0';
1.56 + }
1.57 + testname = strdup( mypath );
1.58 + testname = (char*) realloc( testname, strlen( testname )
1.59 + + strlen( argv[0] )
1.60 + + 2 * sizeof(char) );
1.61 + memset( testname + strlen( testname ),
1.62 + 0,
1.63 + strlen( argv[0] ) + 2 * sizeof(char) );
1.64 + strcat( testname, "/" );
1.65 + strcat( testname, argv[0] );
1.66 + if( stat( testname, &st ) == 0 ) {
1.67 + /* OK, exists. Is it a regular file, or a
1.68 + * symlink, which the current user may execute? */
1.69 + if( S_ISREG( st.st_mode ) && ! access( testname, X_OK || R_OK ) ) {
1.70 + fullname = strdup( testname );
1.71 + break;
1.72 + }
1.73 + }
1.74 + free( testname );
1.75 + mypath = colon + 1;
1.76 + }
1.77 + free( path );
1.78 + if( ! fullname ) {
1.79 + fprintf( stderr, "tool wrapper: %s: command not found\n", argv[0] );
1.80 + exit( 1 );
1.81 + }
1.82 + }
1.83 +
1.84 + /* Duplicate my own name to add the 'dot' to tool name */
1.85 + realname = strdup( fullname );
1.86 + realname = (char*) realloc( realname, strlen( realname) + 2 * sizeof(char) );
1.87 + realname[ strlen( realname ) + 1 ] = '\0';
1.88 +
1.89 + /* Add the dot after the last '/' */
1.90 + lastslash = strrchr( realname, '/' );
1.91 + memmove( lastslash + 1, lastslash, strlen( lastslash ) );
1.92 + *( lastslash + 1 ) = '.';
1.93 +
1.94 + /* Compute the basedir of the tool */
1.95 + basedir = strdup( fullname );
1.96 + lastslash = strrchr( basedir, '/' );
1.97 + *lastslash = '\0';
1.98 + lastslash = strrchr( basedir, '/' );
1.99 + *lastslash = '\0';
1.100 +
1.101 + /* Append '/lib' */
1.102 + len = strlen( basedir );
1.103 + basedir = (char*) realloc( basedir, len + 5 );
1.104 + *( basedir + len ) = '\0';
1.105 + strcat( basedir, "/lib" );
1.106 +
1.107 + /* Now add the directory with our runtime libraries to the
1.108 + front of the library search path, LD_LIBRARY_PATH */
1.109 + ldlibpath = getenv( "LD_LIBRARY_PATH" );
1.110 + if( ldlibpath ) {
1.111 + basedir = (char*) realloc( basedir, strlen( basedir )
1.112 + + strlen( ldlibpath )
1.113 + + 2 * sizeof(char) );
1.114 + strcat( basedir, ":" );
1.115 + strcat( basedir, ldlibpath );
1.116 + }
1.117 +
1.118 + if( setenv( "LD_LIBRARY_PATH", basedir, 1 ) ) {
1.119 + errno = ENOMEM;
1.120 + perror( "tool wrapper" );
1.121 + exit( 1 );
1.122 + }
1.123 +
1.124 + /* Execute the real tool, now */
1.125 + execve_ret = execve( realname, argv, environ );
1.126 +
1.127 + /* In case something went wrong above, print a
1.128 + diagnostic message, and exit with error code 1 */
1.129 + perror( "tool wrapper" );
1.130 + return 1;
1.131 +}