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