version 1.1.1.2, 2012/05/29 09:29:43
|
version 1.1.1.3, 2021/03/17 13:38:46
|
Line 1
|
Line 1
|
/* Provide relocatable programs. |
/* Provide relocatable programs. |
Copyright (C) 2003-2011 Free Software Foundation, Inc. | Copyright (C) 2003-2019 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 13
|
Line 13
|
GNU General Public License for more details. |
GNU General Public License for more details. |
|
|
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
along with this program. If not, see <http://www.gnu.org/licenses/>. */ | along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
|
|
|
|
#define _GL_USE_STDLIB_ALLOC 1 |
#define _GL_USE_STDLIB_ALLOC 1 |
Line 22
|
Line 22
|
/* Specification. */ |
/* Specification. */ |
#include "progname.h" |
#include "progname.h" |
|
|
|
#include <errno.h> |
#include <stdbool.h> |
#include <stdbool.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
Line 30
|
Line 31
|
#include <unistd.h> |
#include <unistd.h> |
#include <sys/stat.h> |
#include <sys/stat.h> |
|
|
/* Get declaration of _NSGetExecutablePath on MacOS X 10.2 or newer. */ | /* Get declaration of _NSGetExecutablePath on Mac OS X 10.2 or newer. */ |
#if HAVE_MACH_O_DYLD_H |
#if HAVE_MACH_O_DYLD_H |
# include <mach-o/dyld.h> |
# include <mach-o/dyld.h> |
#endif |
#endif |
|
|
#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ | #if defined _WIN32 && !defined __CYGWIN__ |
# define WIN32_NATIVE | # define WINDOWS_NATIVE |
#endif |
#endif |
|
|
#ifdef WIN32_NATIVE | #ifdef WINDOWS_NATIVE |
# define WIN32_LEAN_AND_MEAN |
# define WIN32_LEAN_AND_MEAN |
# include <windows.h> |
# include <windows.h> |
#endif |
#endif |
|
|
|
#ifdef __EMX__ |
|
# define INCL_DOS |
|
# include <os2.h> |
|
#endif |
|
|
#include "relocatable.h" |
#include "relocatable.h" |
|
|
#ifdef NO_XMALLOC |
#ifdef NO_XMALLOC |
Line 73 extern char * canonicalize_file_name (const char *name
|
Line 79 extern char * canonicalize_file_name (const char *name
|
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 __CYGWIN__) || defined __EMX__ || defined __DJGPP__ |
/* Win32, OS/2, DOS */ | /* Native Windows, 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 89 extern char * canonicalize_file_name (const char *name
|
Line 95 extern char * canonicalize_file_name (const char *name
|
# define FILE_SYSTEM_PREFIX_LEN(P) 0 |
# define FILE_SYSTEM_PREFIX_LEN(P) 0 |
#endif |
#endif |
|
|
/* The results of open() in this file are not used with fchdir, |
|
therefore save some unnecessary work in fchdir.c. */ |
|
#undef open |
|
#undef close |
|
|
|
/* Use the system functions, not the gnulib overrides in this file. */ |
/* Use the system functions, not the gnulib overrides in this file. */ |
#undef sprintf |
#undef sprintf |
|
|
Line 102 extern char * canonicalize_file_name (const char *name
|
Line 103 extern char * canonicalize_file_name (const char *name
|
|
|
#if ENABLE_RELOCATABLE |
#if ENABLE_RELOCATABLE |
|
|
|
#ifdef __sun |
|
|
|
/* Helper function, from gnulib module 'safe-read'. */ |
|
static size_t |
|
safe_read (int fd, void *buf, size_t count) |
|
{ |
|
for (;;) |
|
{ |
|
ssize_t result = read (fd, buf, count); |
|
|
|
if (0 <= result || errno != EINTR) |
|
return result; |
|
} |
|
} |
|
|
|
/* Helper function, from gnulib module 'full-read'. */ |
|
static size_t |
|
full_read (int fd, void *buf, size_t count) |
|
{ |
|
size_t total = 0; |
|
const char *ptr = (const char *) buf; |
|
|
|
while (count > 0) |
|
{ |
|
size_t n = safe_read (fd, ptr, count); |
|
if (n == (size_t) -1) |
|
break; |
|
if (n == 0) |
|
{ |
|
errno = 0; |
|
break; |
|
} |
|
total += n; |
|
ptr += n; |
|
count -= n; |
|
} |
|
|
|
return total; |
|
} |
|
|
|
#endif |
|
|
#if defined __linux__ || defined __CYGWIN__ |
#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.) */ |
Line 112 static int executable_fd = -1;
|
Line 155 static int executable_fd = -1;
|
static bool |
static bool |
maybe_executable (const char *filename) |
maybe_executable (const char *filename) |
{ |
{ |
/* Woe32 lacks the access() function. */ | /* The native Windows API lacks the access() function. */ |
#if !defined WIN32_NATIVE | #if !defined WINDOWS_NATIVE |
if (access (filename, X_OK) < 0) |
if (access (filename, X_OK) < 0) |
return false; |
return false; |
#endif |
#endif |
Line 143 maybe_executable (const char *filename)
|
Line 186 maybe_executable (const char *filename)
|
|
|
/* Determine the full pathname of the current executable, freshly allocated. |
/* Determine the full pathname of the current executable, freshly allocated. |
Return NULL if unknown. |
Return NULL if unknown. |
Guaranteed to work on Linux and Woe32. Likely to work on the other | Guaranteed to work on Linux and native Windows. Likely to work on the |
Unixes (maybe except BeOS), under most conditions. */ | other Unixes (maybe except BeOS), under most conditions. */ |
static char * |
static char * |
find_executable (const char *argv0) |
find_executable (const char *argv0) |
{ |
{ |
#if defined WIN32_NATIVE | #if defined WINDOWS_NATIVE |
/* Native Win32 only. | /* Native Windows only. |
On Cygwin, it is better to use the Cygwin provided /proc interface, than |
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 | to use native Windows API and cygwin_conv_to_posix_path, because it |
longer file names | supports longer file names |
(see <http://cygwin.com/ml/cygwin/2011-01/msg00410.html>). */ | (see <https://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 162 find_executable (const char *argv0)
|
Line 205 find_executable (const char *argv0)
|
/* Shouldn't happen. */ |
/* Shouldn't happen. */ |
return NULL; |
return NULL; |
return xstrdup (location); |
return xstrdup (location); |
|
#elif defined __EMX__ |
|
PPIB ppib; |
|
char location[CCHMAXPATH]; |
|
|
|
/* See http://cyberkinetica.homeunix.net/os2tk45/cp1/619_L2H_DosGetInfoBlocksSynt.html |
|
for specification of DosGetInfoBlocks(). */ |
|
if (DosGetInfoBlocks (NULL, &ppib)) |
|
return NULL; |
|
|
|
/* See http://cyberkinetica.homeunix.net/os2tk45/cp1/1247_L2H_DosQueryModuleNameSy.html |
|
for specification of DosQueryModuleName(). */ |
|
if (DosQueryModuleName (ppib->pib_hmte, sizeof (location), location)) |
|
return NULL; |
|
|
|
_fnslashify (location); |
|
|
|
return xstrdup (location); |
#else /* Unix */ |
#else /* Unix */ |
# ifdef __linux__ | # if defined __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 188 find_executable (const char *argv0)
|
Line 248 find_executable (const char *argv0)
|
} |
} |
} |
} |
# endif |
# endif |
# ifdef __CYGWIN__ | # if defined __ANDROID__ || defined __FreeBSD_kernel__ |
| /* On Android and GNU/kFreeBSD, the executable is accessible as |
| /proc/<pid>/exe and /proc/self/exe. */ |
| { |
| char *link; |
| |
| link = xreadlink ("/proc/self/exe"); |
| if (link != NULL) |
| return link; |
| } |
| # endif |
| # if defined __FreeBSD__ || defined __DragonFly__ |
| /* In FreeBSD >= 5.0, the executable is accessible as /proc/<pid>/file and |
| /proc/curproc/file. */ |
| { |
| char *link; |
| |
| link = xreadlink ("/proc/curproc/file"); |
| if (link != NULL) |
| { |
| if (strcmp (link, "unknown") != 0) |
| return link; |
| free (link); |
| } |
| } |
| # endif |
| # if defined __NetBSD__ |
| /* In NetBSD >= 4.0, the executable is accessible as /proc/<pid>/exe and |
| /proc/curproc/exe. */ |
| { |
| char *link; |
| |
| link = xreadlink ("/proc/curproc/exe"); |
| if (link != NULL) |
| return link; |
| } |
| # endif |
| # if defined __sun |
| /* On Solaris >= 11.4, /proc/<pid>/execname and /proc/self/execname contains |
| the name of the executable, either as an absolute file name or relative to |
| the current directory. */ |
| { |
| char namebuf[4096]; |
| int fd = open ("/proc/self/execname", O_RDONLY, 0); |
| if (fd >= 0) |
| { |
| size_t len = full_read (fd, namebuf, sizeof (namebuf)); |
| close (fd); |
| if (len > 0 && len < sizeof (namebuf)) |
| { |
| namebuf[len] = '\0'; |
| return canonicalize_file_name (namebuf); |
| } |
| } |
| } |
| # endif |
| # if defined __CYGWIN__ |
/* The executable is accessible as /proc/<pid>/exe, at least in |
/* The executable is accessible as /proc/<pid>/exe, at least in |
Cygwin >= 1.5. */ |
Cygwin >= 1.5. */ |
{ |
{ |
Line 202 find_executable (const char *argv0)
|
Line 318 find_executable (const char *argv0)
|
} |
} |
# endif |
# endif |
# if HAVE_MACH_O_DYLD_H && HAVE__NSGETEXECUTABLEPATH |
# if HAVE_MACH_O_DYLD_H && HAVE__NSGETEXECUTABLEPATH |
/* On MacOS X 10.2 or newer, the function | /* On Mac OS 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. */ |
char location[4096]; |
char location[4096]; |