root/maint/gnulib/lib/relocwrapper.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. add_dotbin
  2. relocate_libdirs
  3. activate_libdirs
  4. main

   1 /* Relocating wrapper program.
   2    Copyright (C) 2003, 2005-2007, 2009-2021 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 3 of the License, or
   8    (at your option) 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, see <https://www.gnu.org/licenses/>.  */
  17 
  18 /* Dependencies:
  19    relocwrapper
  20     -> progname
  21     -> progreloc
  22        -> stat
  23           -> filename
  24           -> pathmax
  25           -> verify
  26        -> areadlink
  27           -> careadlinkat
  28              -> allocator
  29           -> readlink
  30              -> stat
  31        -> canonicalize-lgpl
  32           -> libc-config
  33           -> errno
  34           -> fcntl-h
  35           -> stdbool
  36           -> sys_stat
  37           -> unistd
  38           -> eloop-threshold
  39           -> filename
  40           -> idx
  41           -> intprops
  42           -> scratch_buffer
  43              -> malloc-posix
  44              -> realloc-posix
  45              -> free-posix
  46           -> pathmax
  47           -> mempcpy
  48           -> rawmemchr
  49           -> readlink
  50           -> stat
  51           -> double-slash-root
  52     -> relocatable
  53     -> setenv
  54        -> malloca
  55     -> fprintf-posix [ignore, cut dependency tree here]
  56     -> strerror [ignore, cut dependency tree here]
  57     -> c-ctype
  58 
  59    Macros that need to be set while compiling this file:
  60      - ENABLE_RELOCATABLE 1
  61      - INSTALLPREFIX the base installation directory
  62      - INSTALLDIR the directory into which this program is installed
  63      - LIBPATHVAR the platform dependent runtime library path variable
  64      - LIBDIRS a comma-terminated list of strings representing the list of
  65        directories that contain the libraries at installation time
  66 
  67    We don't want to internationalize this wrapper because then it would
  68    depend on libintl and therefore need relocation itself.  So use only
  69    libc functions, no gettext(), no error(), no xmalloc(), no xsetenv().
  70  */
  71 
  72 #define _GL_USE_STDLIB_ALLOC 1
  73 #include <config.h>
  74 
  75 #include <stdio.h>
  76 #include <stdlib.h>
  77 #include <string.h>
  78 #include <unistd.h>
  79 #include <errno.h>
  80 
  81 #include "progname.h"
  82 #include "relocatable.h"
  83 #include "c-ctype.h"
  84 #include "verify.h"
  85 
  86 /* Use the system functions, not the gnulib overrides in this file.  */
  87 #undef fprintf
  88 #undef strerror
  89 
  90 /* Return a copy of the filename, with an extra ".bin" at the end.
  91    More generally, it replaces "${EXEEXT}" at the end with ".bin${EXEEXT}".  */
  92 static char *
  93 add_dotbin (const char *filename)
     /* [previous][next][first][last][top][bottom][index][help] */
  94 {
  95   size_t filename_len = strlen (filename);
  96   char *result = (char *) malloc (filename_len + 4 + 1);
  97 
  98   if (result != NULL)
  99     {
 100       if (sizeof (EXEEXT) > sizeof (""))
 101         {
 102           /* EXEEXT handling.  */
 103           const size_t exeext_len = sizeof (EXEEXT) - sizeof ("");
 104           static const char exeext[] = EXEEXT;
 105           if (filename_len > exeext_len)
 106             {
 107               /* Compare using an inlined copy of c_strncasecmp(), because
 108                  the filenames may have undergone a case conversion since
 109                  they were packaged.  In other words, EXEEXT may be ".exe"
 110                  on one system and ".EXE" on another.  */
 111               const char *s1 = filename + filename_len - exeext_len;
 112               const char *s2 = exeext;
 113               for (; *s1 != '\0'; s1++, s2++)
 114                 {
 115                   unsigned char c1 = *s1;
 116                   unsigned char c2 = *s2;
 117                   if (c_tolower (c1) != c_tolower (c2))
 118                     goto simple_append;
 119                 }
 120               /* Insert ".bin" before EXEEXT or its equivalent.  */
 121               memcpy (result, filename, filename_len - exeext_len);
 122               memcpy (result + filename_len - exeext_len, ".bin", 4);
 123               memcpy (result + filename_len - exeext_len + 4,
 124                       filename + filename_len - exeext_len,
 125                       exeext_len + 1);
 126               return result;
 127             }
 128         }
 129      simple_append:
 130       /* Simply append ".bin".  */
 131       memcpy (result, filename, filename_len);
 132       memcpy (result + filename_len, ".bin", 4 + 1);
 133       return result;
 134     }
 135   else
 136     {
 137       fprintf (stderr, "%s: %s\n", program_name, "memory exhausted");
 138       exit (1);
 139     }
 140 }
 141 
 142 /* List of directories that contain the libraries.  */
 143 static const char *libdirs[] = { LIBDIRS NULL };
 144 /* Verify that at least one directory is given.  */
 145 verify (sizeof (libdirs) / sizeof (libdirs[0]) > 1);
 146 
 147 /* Relocate the list of directories that contain the libraries.  */
 148 static void
 149 relocate_libdirs ()
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151   size_t i;
 152 
 153   for (i = 0; i < sizeof (libdirs) / sizeof (libdirs[0]) - 1; i++)
 154     libdirs[i] = relocate (libdirs[i]);
 155 }
 156 
 157 /* Activate the list of directories in the LIBPATHVAR.  */
 158 static void
 159 activate_libdirs ()
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161   const char *old_value;
 162   size_t total;
 163   size_t i;
 164   char *value;
 165   char *p;
 166 
 167   old_value = getenv (LIBPATHVAR);
 168   if (old_value == NULL)
 169     old_value = "";
 170 
 171   total = 0;
 172   for (i = 0; i < sizeof (libdirs) / sizeof (libdirs[0]) - 1; i++)
 173     total += strlen (libdirs[i]) + 1;
 174   total += strlen (old_value) + 1;
 175 
 176   value = (char *) malloc (total);
 177   if (value == NULL)
 178     {
 179       fprintf (stderr, "%s: %s\n", program_name, "memory exhausted");
 180       exit (1);
 181     }
 182   p = value;
 183   for (i = 0; i < sizeof (libdirs) / sizeof (libdirs[0]) - 1; i++)
 184     {
 185       size_t len = strlen (libdirs[i]);
 186       memcpy (p, libdirs[i], len);
 187       p += len;
 188       *p++ = ':';
 189     }
 190   if (old_value[0] != '\0')
 191     strcpy (p, old_value);
 192   else
 193     p[-1] = '\0';
 194 
 195   if (setenv (LIBPATHVAR, value, 1) < 0)
 196     {
 197       fprintf (stderr, "%s: %s\n", program_name, "memory exhausted");
 198       exit (1);
 199     }
 200 }
 201 
 202 int
 203 main (int argc, char *argv[])
     /* [previous][next][first][last][top][bottom][index][help] */
 204 {
 205   char *full_program_name;
 206 
 207   /* Set the program name and perform preparations for
 208      get_full_program_name() and relocate().  */
 209   set_program_name_and_installdir (argv[0], INSTALLPREFIX, INSTALLDIR);
 210 
 211   /* Get the full program path.  (Important if accessed through a symlink.)  */
 212   full_program_name = get_full_program_name ();
 213   if (full_program_name == NULL)
 214     full_program_name = argv[0];
 215 
 216   /* Invoke the real program, with suffix ".bin".  */
 217   argv[0] = add_dotbin (full_program_name);
 218   relocate_libdirs ();
 219   activate_libdirs ();
 220   execv (argv[0], argv);
 221   fprintf (stderr, "%s: could not execute %s: %s\n",
 222            program_name, argv[0], strerror (errno));
 223   exit (127);
 224 }

/* [previous][next][first][last][top][bottom][index][help] */