Diff for /embedaddon/libiconv/srclib/progreloc.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 22:57:48 version 1.1.1.2, 2012/05/29 09:29:43
Line 1 Line 1
 /* Provide relocatable programs.  /* Provide relocatable programs.
   Copyright (C) 2003-2009 Free Software Foundation, Inc.   Copyright (C) 2003-2011 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2003.     Written by Bruno Haible <bruno@clisp.org>, 2003.
   
    This program is free software: you can redistribute it and/or modify     This program is free software: you can redistribute it and/or modify
Line 16 Line 16
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */     along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   
   
   #define _GL_USE_STDLIB_ALLOC 1
 #include <config.h>  #include <config.h>
   
 /* Specification.  */  /* Specification.  */
Line 34 Line 35
 # include <mach-o/dyld.h>  # include <mach-o/dyld.h>
 #endif  #endif
   
#if defined _WIN32 || defined __WIN32__#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
 # define WIN32_NATIVE  # define WIN32_NATIVE
 #endif  #endif
   
#if defined WIN32_NATIVE || defined __CYGWIN__#ifdef WIN32_NATIVE
 # define WIN32_LEAN_AND_MEAN  # define WIN32_LEAN_AND_MEAN
 # include <windows.h>  # include <windows.h>
 #endif  #endif
   
 #include "canonicalize.h"  
 #include "relocatable.h"  #include "relocatable.h"
   
 #ifdef NO_XMALLOC  #ifdef NO_XMALLOC
Line 60 Line 60
 # include "xalloc.h"  # include "xalloc.h"
 #endif  #endif
   
   #ifndef O_EXEC
   # define O_EXEC O_RDONLY /* This is often close enough in older systems.  */
   #endif
   
   /* Declare canonicalize_file_name.
      The <stdlib.h> included above may be the system's one, not the gnulib
      one.  */
   extern char * canonicalize_file_name (const char *name);
   
 /* Pathname support.  /* Pathname support.
    ISSLASH(C)           tests whether C is a directory separator character.     ISSLASH(C)           tests whether C is a directory separator character.
    IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.     IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
  */   */
#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__#if ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__
  /* Win32, Cygwin, OS/2, DOS */  /* Win32, OS/2, DOS */
 # define ISSLASH(C) ((C) == '/' || (C) == '\\')  # define ISSLASH(C) ((C) == '/' || (C) == '\\')
 # define HAS_DEVICE(P) \  # define HAS_DEVICE(P) \
     ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \      ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
Line 85 Line 94
 #undef open  #undef open
 #undef close  #undef close
   
   /* Use the system functions, not the gnulib overrides in this file.  */
   #undef sprintf
   
 #undef set_program_name  #undef set_program_name
   
   
 #if ENABLE_RELOCATABLE  #if ENABLE_RELOCATABLE
   
#ifdef __linux__#if defined __linux__ || defined __CYGWIN__
 /* File descriptor of the executable.  /* File descriptor of the executable.
    (Only used to verify that we find the correct executable.)  */     (Only used to verify that we find the correct executable.)  */
 static int executable_fd = -1;  static int executable_fd = -1;
Line 100  static int executable_fd = -1; Line 112  static int executable_fd = -1;
 static bool  static bool
 maybe_executable (const char *filename)  maybe_executable (const char *filename)
 {  {
  /* Woe32 lacks the access() function, but Cygwin doesn't.  */  /* Woe32 lacks the access() function.  */
#if !(defined WIN32_NATIVE && !defined __CYGWIN__)#if !defined WIN32_NATIVE
   if (access (filename, X_OK) < 0)    if (access (filename, X_OK) < 0)
     return false;      return false;
   #endif
   
#ifdef __linux__#if defined __linux__ || defined __CYGWIN__
   if (executable_fd >= 0)    if (executable_fd >= 0)
     {      {
       /* If we already have an executable_fd, check that filename points to        /* If we already have an executable_fd, check that filename points to
         the same inode.  */         the same inode.  */
       struct stat statexe;        struct stat statexe;
       struct stat statfile;        struct stat statfile;
   
       if (fstat (executable_fd, &statexe) >= 0)        if (fstat (executable_fd, &statexe) >= 0)
        {        {
          if (stat (filename, &statfile) < 0)          if (stat (filename, &statfile) < 0)
            return false;            return false;
          if (!(statfile.st_dev          if (!(statfile.st_dev
                && statfile.st_dev == statexe.st_dev                && statfile.st_dev == statexe.st_dev
                && statfile.st_ino == statexe.st_ino))                && statfile.st_ino == statexe.st_ino))
            return false;            return false;
        }        }
     }      }
 #endif  #endif
 #endif  
   
   return true;    return true;
 }  }
Line 136  maybe_executable (const char *filename) Line 148  maybe_executable (const char *filename)
 static char *  static char *
 find_executable (const char *argv0)  find_executable (const char *argv0)
 {  {
#if defined WIN32_NATIVE || defined __CYGWIN__#if defined WIN32_NATIVE
   /* Native Win32 only.
      On Cygwin, it is better to use the Cygwin provided /proc interface, than
      to use native Win32 API and cygwin_conv_to_posix_path, because it supports
      longer file names
      (see <http://cygwin.com/ml/cygwin/2011-01/msg00410.html>).  */
   char location[MAX_PATH];    char location[MAX_PATH];
   int length = GetModuleFileName (NULL, location, sizeof (location));    int length = GetModuleFileName (NULL, location, sizeof (location));
   if (length < 0)    if (length < 0)
Line 144  find_executable (const char *argv0) Line 161  find_executable (const char *argv0)
   if (!IS_PATH_WITH_DIR (location))    if (!IS_PATH_WITH_DIR (location))
     /* Shouldn't happen.  */      /* Shouldn't happen.  */
     return NULL;      return NULL;
  {  return xstrdup (location);
#if defined __CYGWIN__#else /* Unix */
    /* cygwin-1.5.13 (2005-03-01) or newer would also allow a Linux-like# ifdef __linux__
       implementation: readlink of "/proc/self/exe".  But using the 
       result of the Win32 system call is simpler and is consistent with the 
       code in relocatable.c.  */ 
    /* On Cygwin, we need to convert paths coming from Win32 system calls 
       to the Unix-like slashified notation.  */ 
    static char location_as_posix_path[2 * MAX_PATH]; 
    /* There's no error return defined for cygwin_conv_to_posix_path. 
       See cygwin-api/func-cygwin-conv-to-posix-path.html. 
       Does it overflow the buffer of expected size MAX_PATH or does it 
       truncate the path?  I don't know.  Let's catch both.  */ 
    cygwin_conv_to_posix_path (location, location_as_posix_path); 
    location_as_posix_path[MAX_PATH - 1] = '\0'; 
    if (strlen (location_as_posix_path) >= MAX_PATH - 1) 
      /* A sign of buffer overflow or path truncation.  */ 
      return NULL; 
    /* Call canonicalize_file_name, because Cygwin supports symbolic links.  */ 
    return canonicalize_file_name (location_as_posix_path); 
#else 
    return xstrdup (location); 
#endif 
  } 
#else /* Unix && !Cygwin */ 
#ifdef __linux__ 
   /* The executable is accessible as /proc/<pid>/exe.  In newer Linux    /* The executable is accessible as /proc/<pid>/exe.  In newer Linux
      versions, also as /proc/self/exe.  Linux >= 2.1 provides a symlink       versions, also as /proc/self/exe.  Linux >= 2.1 provides a symlink
      to the true pathname; older Linux versions give only device and ino,       to the true pathname; older Linux versions give only device and ino,
Line 181  find_executable (const char *argv0) Line 175  find_executable (const char *argv0)
     if (link != NULL && link[0] != '[')      if (link != NULL && link[0] != '[')
       return link;        return link;
     if (executable_fd < 0)      if (executable_fd < 0)
      executable_fd = open ("/proc/self/exe", O_RDONLY, 0);      executable_fd = open ("/proc/self/exe", O_EXEC, 0);
   
     {      {
       char buf[6+10+5];        char buf[6+10+5];
       sprintf (buf, "/proc/%d/exe", getpid ());        sprintf (buf, "/proc/%d/exe", getpid ());
       link = xreadlink (buf);        link = xreadlink (buf);
       if (link != NULL && link[0] != '[')        if (link != NULL && link[0] != '[')
        return link;        return link;
       if (executable_fd < 0)        if (executable_fd < 0)
        executable_fd = open (buf, O_RDONLY, 0);        executable_fd = open (buf, O_EXEC, 0);
     }      }
   }    }
#endif# endif
#if HAVE_MACH_O_DYLD_H && HAVE__NSGETEXECUTABLEPATHifdef __CYGWIN__
   /* The executable is accessible as /proc/<pid>/exe, at least in
      Cygwin >= 1.5.  */
   {
     char *link;
 
     link = xreadlink ("/proc/self/exe");
     if (link != NULL)
       return link;
     if (executable_fd < 0)
       executable_fd = open ("/proc/self/exe", O_EXEC, 0);
   }
 # endif
 # if HAVE_MACH_O_DYLD_H && HAVE__NSGETEXECUTABLEPATH
   /* On MacOS X 10.2 or newer, the function    /* On MacOS X 10.2 or newer, the function
        int _NSGetExecutablePath (char *buf, uint32_t *bufsize);         int _NSGetExecutablePath (char *buf, uint32_t *bufsize);
      can be used to retrieve the executable's full path.  */       can be used to retrieve the executable's full path.  */
Line 203  find_executable (const char *argv0) Line 210  find_executable (const char *argv0)
   if (_NSGetExecutablePath (location, &length) == 0    if (_NSGetExecutablePath (location, &length) == 0
       && location[0] == '/')        && location[0] == '/')
     return canonicalize_file_name (location);      return canonicalize_file_name (location);
#endif# endif
   /* Guess the executable's full path.  We assume the executable has been    /* Guess the executable's full path.  We assume the executable has been
      called via execlp() or execvp() with properly set up argv[0].  The       called via execlp() or execvp() with properly set up argv[0].  The
      login(1) convention to add a '-' prefix to argv[0] is not supported.  */       login(1) convention to add a '-' prefix to argv[0] is not supported.  */
Line 212  find_executable (const char *argv0) Line 219  find_executable (const char *argv0)
     {      {
       const char *p;        const char *p;
       for (p = argv0; *p; p++)        for (p = argv0; *p; p++)
        if (*p == '/')        if (*p == '/')
          {          {
            has_slash = true;            has_slash = true;
            break;            break;
          }          }
     }      }
     if (!has_slash)      if (!has_slash)
       {        {
        /* exec searches paths without slashes in the directory list given        /* exec searches paths without slashes in the directory list given
           by $PATH.  */           by $PATH.  */
        const char *path = getenv ("PATH");        const char *path = getenv ("PATH");
   
        if (path != NULL)        if (path != NULL)
          {          {
            const char *p;            const char *p;
            const char *p_next;            const char *p_next;
   
            for (p = path; *p; p = p_next)            for (p = path; *p; p = p_next)
              {              {
                const char *q;                const char *q;
                size_t p_len;                size_t p_len;
                char *concat_name;                char *concat_name;
   
                for (q = p; *q; q++)                for (q = p; *q; q++)
                  if (*q == ':')                  if (*q == ':')
                    break;                    break;
                p_len = q - p;                p_len = q - p;
                p_next = (*q == '\0' ? q : q + 1);                p_next = (*q == '\0' ? q : q + 1);
   
                /* We have a path item at p, of length p_len.                /* We have a path item at p, of length p_len.
                   Now concatenate the path item and argv0.  */                   Now concatenate the path item and argv0.  */
                concat_name = (char *) xmalloc (p_len + strlen (argv0) + 2);                concat_name = (char *) xmalloc (p_len + strlen (argv0) + 2);
#ifdef NO_XMALLOCifdef NO_XMALLOC
                if (concat_name == NULL)                if (concat_name == NULL)
                  return NULL;                  return NULL;
#endifendif
                if (p_len == 0)                if (p_len == 0)
                  /* An empty PATH element designates the current directory.  */                  /* An empty PATH element designates the current directory.  */
                  strcpy (concat_name, argv0);                  strcpy (concat_name, argv0);
                else                else
                  {                  {
                    memcpy (concat_name, p, p_len);                    memcpy (concat_name, p, p_len);
                    concat_name[p_len] = '/';                    concat_name[p_len] = '/';
                    strcpy (concat_name + p_len + 1, argv0);                    strcpy (concat_name + p_len + 1, argv0);
                  }                  }
                if (maybe_executable (concat_name))                if (maybe_executable (concat_name))
                  return canonicalize_file_name (concat_name);                  return canonicalize_file_name (concat_name);
                free (concat_name);                free (concat_name);
              }              }
          }          }
        /* Not found in the PATH, assume the current directory.  */        /* Not found in the PATH, assume the current directory.  */
       }        }
     /* exec treats paths containing slashes as relative to the current      /* exec treats paths containing slashes as relative to the current
        directory.  */         directory.  */
Line 279  static char *executable_fullname; Line 286  static char *executable_fullname;
   
 static void  static void
 prepare_relocate (const char *orig_installprefix, const char *orig_installdir,  prepare_relocate (const char *orig_installprefix, const char *orig_installdir,
                  const char *argv0)                  const char *argv0)
 {  {
   char *curr_prefix;    char *curr_prefix;
   
Line 288  prepare_relocate (const char *orig_installprefix, cons Line 295  prepare_relocate (const char *orig_installprefix, cons
   
   /* Determine the current installation prefix from it.  */    /* Determine the current installation prefix from it.  */
   curr_prefix = compute_curr_prefix (orig_installprefix, orig_installdir,    curr_prefix = compute_curr_prefix (orig_installprefix, orig_installdir,
                                     executable_fullname);                                     executable_fullname);
   if (curr_prefix != NULL)    if (curr_prefix != NULL)
     {      {
       /* Now pass this prefix to all copies of the relocate.c source file.  */        /* Now pass this prefix to all copies of the relocate.c source file.  */
Line 302  prepare_relocate (const char *orig_installprefix, cons Line 309  prepare_relocate (const char *orig_installprefix, cons
    directory, for relocatability.  */     directory, for relocatability.  */
 void  void
 set_program_name_and_installdir (const char *argv0,  set_program_name_and_installdir (const char *argv0,
                                 const char *orig_installprefix,                                 const char *orig_installprefix,
                                 const char *orig_installdir)                                 const char *orig_installdir)
 {  {
   const char *argv0_stripped = argv0;    const char *argv0_stripped = argv0;
   
Line 315  set_program_name_and_installdir (const char *argv0, Line 322  set_program_name_and_installdir (const char *argv0,
     const size_t exeext_len = sizeof (EXEEXT) - sizeof ("");      const size_t exeext_len = sizeof (EXEEXT) - sizeof ("");
     if (argv0_len > 4 + exeext_len)      if (argv0_len > 4 + exeext_len)
       if (memcmp (argv0 + argv0_len - exeext_len - 4, ".bin", 4) == 0)        if (memcmp (argv0 + argv0_len - exeext_len - 4, ".bin", 4) == 0)
        {        {
          if (sizeof (EXEEXT) > sizeof (""))          if (sizeof (EXEEXT) > sizeof (""))
            {            {
              /* Compare using an inlined copy of c_strncasecmp(), because              /* Compare using an inlined copy of c_strncasecmp(), because
                 the filenames may have undergone a case conversion since                 the filenames may have undergone a case conversion since
                 they were packaged.  In other words, EXEEXT may be ".exe"                 they were packaged.  In other words, EXEEXT may be ".exe"
                 on one system and ".EXE" on another.  */                 on one system and ".EXE" on another.  */
              static const char exeext[] = EXEEXT;              static const char exeext[] = EXEEXT;
              const char *s1 = argv0 + argv0_len - exeext_len;              const char *s1 = argv0 + argv0_len - exeext_len;
              const char *s2 = exeext;              const char *s2 = exeext;
              for (; *s1 != '\0'; s1++, s2++)              for (; *s1 != '\0'; s1++, s2++)
                {                {
                  unsigned char c1 = *s1;                  unsigned char c1 = *s1;
                  unsigned char c2 = *s2;                  unsigned char c2 = *s2;
                  if ((c1 >= 'A' && c1 <= 'Z' ? c1 - 'A' + 'a' : c1)                  if ((c1 >= 'A' && c1 <= 'Z' ? c1 - 'A' + 'a' : c1)
                      != (c2 >= 'A' && c2 <= 'Z' ? c2 - 'A' + 'a' : c2))                      != (c2 >= 'A' && c2 <= 'Z' ? c2 - 'A' + 'a' : c2))
                    goto done_stripping;                    goto done_stripping;
                }                }
            }            }
          /* Remove ".bin" before EXEEXT or its equivalent.  */          /* Remove ".bin" before EXEEXT or its equivalent.  */
          {          {
            char *shorter = (char *) xmalloc (argv0_len - 4 + 1);            char *shorter = (char *) xmalloc (argv0_len - 4 + 1);
 #ifdef NO_XMALLOC  #ifdef NO_XMALLOC
            if (shorter != NULL)            if (shorter != NULL)
 #endif  #endif
              {              {
                memcpy (shorter, argv0, argv0_len - exeext_len - 4);                memcpy (shorter, argv0, argv0_len - exeext_len - 4);
                if (sizeof (EXEEXT) > sizeof (""))                if (sizeof (EXEEXT) > sizeof (""))
                  memcpy (shorter + argv0_len - exeext_len - 4,                  memcpy (shorter + argv0_len - exeext_len - 4,
                          argv0 + argv0_len - exeext_len - 4,                          argv0 + argv0_len - exeext_len - 4,
                          exeext_len);                          exeext_len);
                shorter[argv0_len - 4] = '\0';                shorter[argv0_len - 4] = '\0';
                argv0_stripped = shorter;                argv0_stripped = shorter;
              }              }
          }          }
         done_stripping: ;         done_stripping: ;
       }        }
   }    }
   

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


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