yann@1492: #include yann@1492: #include yann@1492: #include yann@1492: #include yann@1492: #include yann@1492: #include yann@1492: #include yann@1492: #include yann@1492: yann@1492: yann@1492: /* Needed for execve */ yann@1492: extern char **environ; yann@1492: yann@1492: int main( int argc, yann@1492: char** argv ) yann@1492: { yann@1492: char *fullname; /* 'fullname' is used to store the absolute path to the yann@1492: tool being executed; it serves as a base to compute yann@1492: the realname of that tool, and the directory holding yann@1492: our runtime libraries */ yann@1492: char *realname; /* 'realname' is the real name of the tool, that is what yann@1492: the wrapper is currently impersonating */ yann@1492: char *basedir; /* 'libdir' contains our runtime libraries */ yann@1492: yann@1492: char *lastslash; /* Temporary variables now */ yann@1492: char *ldlibpath; yann@1492: size_t len; yann@1492: int execve_ret; yann@1492: yann@1492: /* In case we have a relative or absolute pathname (ie. contains a slash), yann@1492: * then realpath wll work. But if the tool was found in the PATH, realpath yann@1492: * won't work, and we'll have to search ourselves. yann@1492: * This if{}else{} block allocates memory for fullname. */ yann@1492: if( strchr( argv[0], '/' ) ) { yann@1492: fullname = (char*) malloc( PATH_MAX * sizeof(char) ); yann@1492: if( ! realpath( argv[0], fullname ) ) { yann@1492: perror( "tool wrapper" ); yann@1492: exit( 1 ); yann@1492: } yann@1492: } else { yann@1492: char *path; yann@1492: char *mypath; yann@1492: char *colon; yann@1492: char *testname; yann@1492: struct stat st; yann@1492: yann@1492: fullname = NULL; yann@1492: colon = mypath = path = strdup( getenv( "PATH" ) ); yann@1492: while( colon ) { yann@1492: colon = strchr( mypath, ':' ); yann@1492: if( colon ) { yann@1492: *colon = '\0'; yann@1492: } yann@1492: testname = strdup( mypath ); yann@1492: testname = (char*) realloc( testname, strlen( testname ) yann@1492: + strlen( argv[0] ) yann@1492: + 2 * sizeof(char) ); yann@1492: memset( testname + strlen( testname ), yann@1492: 0, yann@1492: strlen( argv[0] ) + 2 * sizeof(char) ); yann@1492: strcat( testname, "/" ); yann@1492: strcat( testname, argv[0] ); yann@1492: if( stat( testname, &st ) == 0 ) { yann@1492: /* OK, exists. Is it a regular file, or a yann@1492: * symlink, which the current user may execute? */ yann@1492: if( S_ISREG( st.st_mode ) && ! access( testname, X_OK || R_OK ) ) { yann@1492: fullname = strdup( testname ); yann@1492: break; yann@1492: } yann@1492: } yann@1492: free( testname ); yann@1492: mypath = colon + 1; yann@1492: } yann@1492: free( path ); yann@1492: if( ! fullname ) { yann@1492: fprintf( stderr, "tool wrapper: %s: command not found\n", argv[0] ); yann@1492: exit( 1 ); yann@1492: } yann@1492: } yann@1492: yann@1492: /* Duplicate my own name to add the 'dot' to tool name */ yann@1492: realname = strdup( fullname ); yann@1492: realname = (char*) realloc( realname, strlen( realname) + 2 * sizeof(char) ); yann@1492: realname[ strlen( realname ) + 1 ] = '\0'; yann@1492: yann@1492: /* Add the dot after the last '/' */ yann@1492: lastslash = strrchr( realname, '/' ); yann@1492: memmove( lastslash + 1, lastslash, strlen( lastslash ) ); yann@1492: *( lastslash + 1 ) = '.'; yann@1492: yann@1492: /* Compute the basedir of the tool */ yann@1492: basedir = strdup( fullname ); yann@1492: lastslash = strrchr( basedir, '/' ); yann@1492: *lastslash = '\0'; yann@1492: lastslash = strrchr( basedir, '/' ); yann@1492: *lastslash = '\0'; yann@1492: yann@1492: /* Append '/lib' */ yann@1492: len = strlen( basedir ); yann@1492: basedir = (char*) realloc( basedir, len + 5 ); yann@1492: *( basedir + len ) = '\0'; yann@1492: strcat( basedir, "/lib" ); yann@1492: yann@1492: /* Now add the directory with our runtime libraries to the yann@1492: front of the library search path, LD_LIBRARY_PATH */ yann@1492: ldlibpath = getenv( "LD_LIBRARY_PATH" ); yann@1492: if( ldlibpath ) { yann@1492: basedir = (char*) realloc( basedir, strlen( basedir ) yann@1492: + strlen( ldlibpath ) yann@1492: + 2 * sizeof(char) ); yann@1492: strcat( basedir, ":" ); yann@1492: strcat( basedir, ldlibpath ); yann@1492: } yann@1492: yann@1492: if( setenv( "LD_LIBRARY_PATH", basedir, 1 ) ) { yann@1492: errno = ENOMEM; yann@1492: perror( "tool wrapper" ); yann@1492: exit( 1 ); yann@1492: } yann@1492: yann@1492: /* Execute the real tool, now */ yann@1492: execve_ret = execve( realname, argv, environ ); yann@1492: yann@1492: /* In case something went wrong above, print a yann@1492: diagnostic message, and exit with error code 1 */ yann@1492: perror( "tool wrapper" ); yann@1492: return 1; yann@1492: }