1/* Relocating wrapper program. 2 Copyright (C) 2003 Free Software Foundation, Inc. 3 Written by Bruno Haible <bruno@clisp.org>, 2003. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2, or (at your option) 8 any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software Foundation, 17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 18 19/* Dependencies: 20 relocwrapper 21 -> progname 22 -> progreloc 23 -> xreadlink 24 -> readlink 25 -> canonicalize 26 -> allocsa 27 -> relocatable 28 -> setenv 29 -> allocsa 30 -> strerror 31 32 Macros that need to be set while compiling this file: 33 - ENABLE_RELOCATABLE 1 34 - INSTALLPREFIX the base installation directory 35 - INSTALLDIR the directory into which this program is installed 36 - LIBPATHVAR the platform dependent runtime library path variable 37 - LIBDIRS a comma-terminated list of strings representing the list of 38 directories that contain the libraries at installation time 39 40 We don't want to internationalize this wrapper because then it would 41 depend on libintl and therefore need relocation itself. So use only 42 libc functions, no gettext(), no error(), no xmalloc(), no xsetenv(). 43 */ 44 45#ifdef HAVE_CONFIG_H 46# include <config.h> 47#endif 48 49#include <stdio.h> 50#include <stdlib.h> 51#include <string.h> 52#if HAVE_UNISTD_H 53# include <unistd.h> 54#endif 55#include <errno.h> 56 57#include "progname.h" 58#include "relocatable.h" 59#include "setenv.h" 60 61/* Return a copy of the filename, with an extra ".bin" at the end. */ 62static char * 63add_dotbin (const char *filename) 64{ 65 size_t filename_len = strlen (filename); 66 char *result = (char *) malloc (filename_len + 4 + 1); 67 68 if (result != NULL) 69 { 70 memcpy (result, filename, filename_len); 71 memcpy (result + filename_len, ".bin", 4 + 1); 72 return result; 73 } 74 else 75 { 76 fprintf (stderr, "%s: %s\n", program_name, "memory exhausted"); 77 exit (1); 78 } 79} 80 81/* List of directories that contain the libraries. */ 82static const char *libdirs[] = { LIBDIRS NULL }; 83/* Verify that at least one directory is given. */ 84typedef int verify1[2 * (sizeof (libdirs) / sizeof (libdirs[0]) > 1) - 1]; 85 86/* Relocate the list of directories that contain the libraries. */ 87static void 88relocate_libdirs () 89{ 90 size_t i; 91 92 for (i = 0; i < sizeof (libdirs) / sizeof (libdirs[0]) - 1; i++) 93 libdirs[i] = relocate (libdirs[i]); 94} 95 96/* Activate the list of directories in the LIBPATHVAR. */ 97static void 98activate_libdirs () 99{ 100 const char *old_value; 101 size_t total; 102 size_t i; 103 char *value; 104 char *p; 105 106 old_value = getenv (LIBPATHVAR); 107 if (old_value == NULL) 108 old_value = ""; 109 110 total = 0; 111 for (i = 0; i < sizeof (libdirs) / sizeof (libdirs[0]) - 1; i++) 112 total += strlen (libdirs[i]) + 1; 113 total += strlen (old_value) + 1; 114 115 value = (char *) malloc (total); 116 if (value == NULL) 117 { 118 fprintf (stderr, "%s: %s\n", program_name, "memory exhausted"); 119 exit (1); 120 } 121 p = value; 122 for (i = 0; i < sizeof (libdirs) / sizeof (libdirs[0]) - 1; i++) 123 { 124 size_t len = strlen (libdirs[i]); 125 memcpy (p, libdirs[i], len); 126 p += len; 127 *p++ = ':'; 128 } 129 if (old_value[0] != '\0') 130 strcpy (p, old_value); 131 else 132 p[-1] = '\0'; 133 134 if (setenv (LIBPATHVAR, value, 1) < 0) 135 { 136 fprintf (stderr, "%s: %s\n", program_name, "memory exhausted"); 137 exit (1); 138 } 139} 140 141int 142main (int argc, char *argv[]) 143{ 144 char *full_program_name; 145 146 /* Set the program name and perform preparations for 147 get_full_program_name() and relocate(). */ 148 set_program_name_and_installdir (argv[0], INSTALLPREFIX, INSTALLDIR); 149 150 /* Get the full program path. (Important if accessed through a symlink.) */ 151 full_program_name = get_full_program_name (); 152 if (full_program_name == NULL) 153 full_program_name = argv[0]; 154 155 /* Invoke the real program, with suffix ".bin". */ 156 argv[0] = add_dotbin (full_program_name); 157 relocate_libdirs (); 158 activate_libdirs (); 159 execv (argv[0], argv); 160 fprintf (stderr, "%s: could not execute %s: %s\n", 161 program_name, argv[0], strerror (errno)); 162 exit (127); 163} 164