atoll: Assume that the compiler supports 'long long'.
[gnulib.git] / lib / progreloc.c
blob9d81efa14b6c3eb4127d7e7d1e0b342d5ce317b7
1 /* Provide relocatable programs.
2 Copyright (C) 2003-2019 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2003.
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.
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.
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/>. */
19 #define _GL_USE_STDLIB_ALLOC 1
20 #include <config.h>
22 /* Specification. */
23 #include "progname.h"
25 #include <errno.h>
26 #include <stdbool.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <sys/stat.h>
34 /* Get declaration of _NSGetExecutablePath on Mac OS X 10.2 or newer. */
35 #if HAVE_MACH_O_DYLD_H
36 # include <mach-o/dyld.h>
37 #endif
39 #if defined _WIN32 && !defined __CYGWIN__
40 # define WINDOWS_NATIVE
41 #endif
43 #ifdef WINDOWS_NATIVE
44 # define WIN32_LEAN_AND_MEAN
45 # include <windows.h>
46 #endif
48 #ifdef __EMX__
49 # define INCL_DOS
50 # include <os2.h>
51 #endif
53 #include "relocatable.h"
55 #ifdef NO_XMALLOC
56 # include "areadlink.h"
57 # define xreadlink areadlink
58 #else
59 # include "xreadlink.h"
60 #endif
62 #ifdef NO_XMALLOC
63 # define xmalloc malloc
64 # define xstrdup strdup
65 #else
66 # include "xalloc.h"
67 #endif
69 #ifndef O_EXEC
70 # define O_EXEC O_RDONLY /* This is often close enough in older systems. */
71 #endif
73 /* Declare canonicalize_file_name.
74 The <stdlib.h> included above may be the system's one, not the gnulib
75 one. */
76 extern char * canonicalize_file_name (const char *name);
78 /* Pathname support.
79 ISSLASH(C) tests whether C is a directory separator character.
80 IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
82 #if (defined _WIN32 && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__
83 /* Native Windows, OS/2, DOS */
84 # define ISSLASH(C) ((C) == '/' || (C) == '\\')
85 # define HAS_DEVICE(P) \
86 ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
87 && (P)[1] == ':')
88 # define IS_PATH_WITH_DIR(P) \
89 (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
90 # define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
91 #else
92 /* Unix */
93 # define ISSLASH(C) ((C) == '/')
94 # define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
95 # define FILE_SYSTEM_PREFIX_LEN(P) 0
96 #endif
98 /* Use the system functions, not the gnulib overrides in this file. */
99 #undef sprintf
101 #undef set_program_name
104 #if ENABLE_RELOCATABLE
106 #ifdef __sun
108 /* Helper function, from gnulib module 'safe-read'. */
109 static size_t
110 safe_read (int fd, void *buf, size_t count)
112 for (;;)
114 ssize_t result = read (fd, buf, count);
116 if (0 <= result || errno != EINTR)
117 return result;
121 /* Helper function, from gnulib module 'full-read'. */
122 static size_t
123 full_read (int fd, void *buf, size_t count)
125 size_t total = 0;
126 const char *ptr = (const char *) buf;
128 while (count > 0)
130 size_t n = safe_read (fd, ptr, count);
131 if (n == (size_t) -1)
132 break;
133 if (n == 0)
135 errno = 0;
136 break;
138 total += n;
139 ptr += n;
140 count -= n;
143 return total;
146 #endif
148 #if defined __linux__ || defined __CYGWIN__
149 /* File descriptor of the executable.
150 (Only used to verify that we find the correct executable.) */
151 static int executable_fd = -1;
152 #endif
154 /* Define this function only when it's needed. */
155 #if !(defined WINDOWS_NATIVE || defined __EMX__)
157 /* Tests whether a given pathname may belong to the executable. */
158 static bool
159 maybe_executable (const char *filename)
161 /* The native Windows API lacks the access() function. */
162 # if !defined WINDOWS_NATIVE
163 if (access (filename, X_OK) < 0)
164 return false;
165 # endif
167 # if defined __linux__ || defined __CYGWIN__
168 if (executable_fd >= 0)
170 /* If we already have an executable_fd, check that filename points to
171 the same inode. */
172 struct stat statexe;
173 struct stat statfile;
175 if (fstat (executable_fd, &statexe) >= 0)
177 if (stat (filename, &statfile) < 0)
178 return false;
179 if (!(statfile.st_dev
180 && statfile.st_dev == statexe.st_dev
181 && statfile.st_ino == statexe.st_ino))
182 return false;
185 # endif
187 return true;
190 #endif
192 /* Determine the full pathname of the current executable, freshly allocated.
193 Return NULL if unknown.
194 Guaranteed to work on Linux and native Windows. Likely to work on the
195 other Unixes (maybe except BeOS), under most conditions. */
196 static char *
197 find_executable (const char *argv0)
199 #if defined WINDOWS_NATIVE
200 /* Native Windows only.
201 On Cygwin, it is better to use the Cygwin provided /proc interface, than
202 to use native Windows API and cygwin_conv_to_posix_path, because it
203 supports longer file names
204 (see <https://cygwin.com/ml/cygwin/2011-01/msg00410.html>). */
205 char location[MAX_PATH];
206 int length = GetModuleFileName (NULL, location, sizeof (location));
207 if (length < 0)
208 return NULL;
209 if (!IS_PATH_WITH_DIR (location))
210 /* Shouldn't happen. */
211 return NULL;
212 return xstrdup (location);
213 #elif defined __EMX__
214 PPIB ppib;
215 char location[CCHMAXPATH];
217 /* See http://cyberkinetica.homeunix.net/os2tk45/cp1/619_L2H_DosGetInfoBlocksSynt.html
218 for specification of DosGetInfoBlocks(). */
219 if (DosGetInfoBlocks (NULL, &ppib))
220 return NULL;
222 /* See http://cyberkinetica.homeunix.net/os2tk45/cp1/1247_L2H_DosQueryModuleNameSy.html
223 for specification of DosQueryModuleName(). */
224 if (DosQueryModuleName (ppib->pib_hmte, sizeof (location), location))
225 return NULL;
227 _fnslashify (location);
229 return xstrdup (location);
230 #else /* Unix */
231 # if defined __linux__
232 /* The executable is accessible as /proc/<pid>/exe. In newer Linux
233 versions, also as /proc/self/exe. Linux >= 2.1 provides a symlink
234 to the true pathname; older Linux versions give only device and ino,
235 enclosed in brackets, which we cannot use here. */
237 char *link;
239 link = xreadlink ("/proc/self/exe");
240 if (link != NULL && link[0] != '[')
241 return link;
242 if (executable_fd < 0)
243 executable_fd = open ("/proc/self/exe", O_EXEC, 0);
246 char buf[6+10+5];
247 sprintf (buf, "/proc/%d/exe", getpid ());
248 link = xreadlink (buf);
249 if (link != NULL && link[0] != '[')
250 return link;
251 if (executable_fd < 0)
252 executable_fd = open (buf, O_EXEC, 0);
255 # endif
256 # if defined __ANDROID__ || defined __FreeBSD_kernel__
257 /* On Android and GNU/kFreeBSD, the executable is accessible as
258 /proc/<pid>/exe and /proc/self/exe. */
260 char *link;
262 link = xreadlink ("/proc/self/exe");
263 if (link != NULL)
264 return link;
266 # endif
267 # if defined __FreeBSD__ || defined __DragonFly__
268 /* In FreeBSD >= 5.0, the executable is accessible as /proc/<pid>/file and
269 /proc/curproc/file. */
271 char *link;
273 link = xreadlink ("/proc/curproc/file");
274 if (link != NULL)
276 if (strcmp (link, "unknown") != 0)
277 return link;
278 free (link);
281 # endif
282 # if defined __NetBSD__
283 /* In NetBSD >= 4.0, the executable is accessible as /proc/<pid>/exe and
284 /proc/curproc/exe. */
286 char *link;
288 link = xreadlink ("/proc/curproc/exe");
289 if (link != NULL)
290 return link;
292 # endif
293 # if defined __sun
294 /* On Solaris >= 11.4, /proc/<pid>/execname and /proc/self/execname contains
295 the name of the executable, either as an absolute file name or relative to
296 the current directory. */
298 char namebuf[4096];
299 int fd = open ("/proc/self/execname", O_RDONLY, 0);
300 if (fd >= 0)
302 size_t len = full_read (fd, namebuf, sizeof (namebuf));
303 close (fd);
304 if (len > 0 && len < sizeof (namebuf))
306 namebuf[len] = '\0';
307 return canonicalize_file_name (namebuf);
311 # endif
312 # if defined __CYGWIN__
313 /* The executable is accessible as /proc/<pid>/exe, at least in
314 Cygwin >= 1.5. */
316 char *link;
318 link = xreadlink ("/proc/self/exe");
319 if (link != NULL)
320 return link;
321 if (executable_fd < 0)
322 executable_fd = open ("/proc/self/exe", O_EXEC, 0);
324 # endif
325 # if HAVE_MACH_O_DYLD_H && HAVE__NSGETEXECUTABLEPATH
326 /* On Mac OS X 10.2 or newer, the function
327 int _NSGetExecutablePath (char *buf, uint32_t *bufsize);
328 can be used to retrieve the executable's full path. */
329 char location[4096];
330 unsigned int length = sizeof (location);
331 if (_NSGetExecutablePath (location, &length) == 0
332 && location[0] == '/')
333 return canonicalize_file_name (location);
334 # endif
335 /* Guess the executable's full path. We assume the executable has been
336 called via execlp() or execvp() with properly set up argv[0]. The
337 login(1) convention to add a '-' prefix to argv[0] is not supported. */
339 bool has_slash = false;
341 const char *p;
342 for (p = argv0; *p; p++)
343 if (*p == '/')
345 has_slash = true;
346 break;
349 if (!has_slash)
351 /* exec searches paths without slashes in the directory list given
352 by $PATH. */
353 const char *path = getenv ("PATH");
355 if (path != NULL)
357 const char *p;
358 const char *p_next;
360 for (p = path; *p; p = p_next)
362 const char *q;
363 size_t p_len;
364 char *concat_name;
366 for (q = p; *q; q++)
367 if (*q == ':')
368 break;
369 p_len = q - p;
370 p_next = (*q == '\0' ? q : q + 1);
372 /* We have a path item at p, of length p_len.
373 Now concatenate the path item and argv0. */
374 concat_name = (char *) xmalloc (p_len + strlen (argv0) + 2);
375 # ifdef NO_XMALLOC
376 if (concat_name == NULL)
377 return NULL;
378 # endif
379 if (p_len == 0)
380 /* An empty PATH element designates the current directory. */
381 strcpy (concat_name, argv0);
382 else
384 memcpy (concat_name, p, p_len);
385 concat_name[p_len] = '/';
386 strcpy (concat_name + p_len + 1, argv0);
388 if (maybe_executable (concat_name))
389 return canonicalize_file_name (concat_name);
390 free (concat_name);
393 /* Not found in the PATH, assume the current directory. */
395 /* exec treats paths containing slashes as relative to the current
396 directory. */
397 if (maybe_executable (argv0))
398 return canonicalize_file_name (argv0);
400 /* No way to find the executable. */
401 return NULL;
402 #endif
405 /* Full pathname of executable, or NULL. */
406 static char *executable_fullname;
408 static void
409 prepare_relocate (const char *orig_installprefix, const char *orig_installdir,
410 const char *argv0)
412 char *curr_prefix;
414 /* Determine the full pathname of the current executable. */
415 executable_fullname = find_executable (argv0);
417 /* Determine the current installation prefix from it. */
418 curr_prefix = compute_curr_prefix (orig_installprefix, orig_installdir,
419 executable_fullname);
420 if (curr_prefix != NULL)
422 /* Now pass this prefix to all copies of the relocate.c source file. */
423 set_relocation_prefix (orig_installprefix, curr_prefix);
425 free (curr_prefix);
429 /* Set program_name, based on argv[0], and original installation prefix and
430 directory, for relocatability. */
431 void
432 set_program_name_and_installdir (const char *argv0,
433 const char *orig_installprefix,
434 const char *orig_installdir)
436 const char *argv0_stripped = argv0;
438 /* Relocatable programs are renamed to .bin by install-reloc. Or, more
439 generally, their suffix is changed from $exeext to .bin$exeext.
440 Remove the ".bin" here. */
442 size_t argv0_len = strlen (argv0);
443 const size_t exeext_len = sizeof (EXEEXT) - sizeof ("");
444 if (argv0_len > 4 + exeext_len)
445 if (memcmp (argv0 + argv0_len - exeext_len - 4, ".bin", 4) == 0)
447 if (sizeof (EXEEXT) > sizeof (""))
449 /* Compare using an inlined copy of c_strncasecmp(), because
450 the filenames may have undergone a case conversion since
451 they were packaged. In other words, EXEEXT may be ".exe"
452 on one system and ".EXE" on another. */
453 static const char exeext[] = EXEEXT;
454 const char *s1 = argv0 + argv0_len - exeext_len;
455 const char *s2 = exeext;
456 for (; *s1 != '\0'; s1++, s2++)
458 unsigned char c1 = *s1;
459 unsigned char c2 = *s2;
460 if ((c1 >= 'A' && c1 <= 'Z' ? c1 - 'A' + 'a' : c1)
461 != (c2 >= 'A' && c2 <= 'Z' ? c2 - 'A' + 'a' : c2))
462 goto done_stripping;
465 /* Remove ".bin" before EXEEXT or its equivalent. */
467 char *shorter = (char *) xmalloc (argv0_len - 4 + 1);
468 #ifdef NO_XMALLOC
469 if (shorter != NULL)
470 #endif
472 memcpy (shorter, argv0, argv0_len - exeext_len - 4);
473 if (sizeof (EXEEXT) > sizeof (""))
474 memcpy (shorter + argv0_len - exeext_len - 4,
475 argv0 + argv0_len - exeext_len - 4,
476 exeext_len);
477 shorter[argv0_len - 4] = '\0';
478 argv0_stripped = shorter;
481 done_stripping: ;
485 set_program_name (argv0_stripped);
487 prepare_relocate (orig_installprefix, orig_installdir, argv0);
490 /* Return the full pathname of the current executable, based on the earlier
491 call to set_program_name_and_installdir. Return NULL if unknown. */
492 char *
493 get_full_program_name (void)
495 return executable_fullname;
498 #endif