File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libiconv / srclib / relocwrapper.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:57:48 2012 UTC (12 years, 4 months ago) by misho
Branches: libiconv, MAIN
CVS tags: v1_13_1, HEAD
libiconv

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

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