File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libiconv / srclib / relocwrapper.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 13:38:46 2021 UTC (3 years, 3 months ago) by misho
Branches: libiconv, MAIN
CVS tags: v1_16p0, HEAD
libiconv 1.16

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>