timespec_get: New module.
[gnulib.git] / lib / progreloc.c
blob1aa74aef1e16233d12e05dc117be253630951ada
1 /* Provide relocatable programs.
2 Copyright (C) 2003-2021 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 #if defined IN_RELOCWRAPPER && (!defined O_CLOEXEC || GNULIB_defined_O_CLOEXEC)
74 # undef O_CLOEXEC
75 # define O_CLOEXEC 0
76 #endif
78 /* Declare canonicalize_file_name.
79 The <stdlib.h> included above may be the system's one, not the gnulib
80 one. */
81 extern char * canonicalize_file_name (const char *name);
83 #if defined WINDOWS_NATIVE
84 /* Don't assume that UNICODE is not defined. */
85 # undef GetModuleFileName
86 # define GetModuleFileName GetModuleFileNameA
87 #endif
89 /* Pathname support.
90 ISSLASH(C) tests whether C is a directory separator character.
91 IS_FILE_NAME_WITH_DIR(P) tests whether P contains a directory specification.
93 #if (defined _WIN32 && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__
94 /* Native Windows, OS/2, DOS */
95 # define ISSLASH(C) ((C) == '/' || (C) == '\\')
96 # define HAS_DEVICE(P) \
97 ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
98 && (P)[1] == ':')
99 # define IS_FILE_NAME_WITH_DIR(P) \
100 (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
101 # define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
102 #else
103 /* Unix */
104 # define ISSLASH(C) ((C) == '/')
105 # define IS_FILE_NAME_WITH_DIR(P) (strchr (P, '/') != NULL)
106 # define FILE_SYSTEM_PREFIX_LEN(P) 0
107 #endif
109 /* Use the system functions, not the gnulib overrides in this file. */
110 #undef sprintf
112 #undef set_program_name
115 #if ENABLE_RELOCATABLE
117 #ifdef __sun
119 /* Helper function, from gnulib module 'safe-read'. */
120 static size_t
121 safe_read (int fd, void *buf, size_t count)
123 for (;;)
125 ssize_t result = read (fd, buf, count);
127 if (0 <= result || errno != EINTR)
128 return result;
132 /* Helper function, from gnulib module 'full-read'. */
133 static size_t
134 full_read (int fd, void *buf, size_t count)
136 size_t total = 0;
137 const char *ptr = (const char *) buf;
139 while (count > 0)
141 size_t n = safe_read (fd, ptr, count);
142 if (n == (size_t) -1)
143 break;
144 if (n == 0)
146 errno = 0;
147 break;
149 total += n;
150 ptr += n;
151 count -= n;
154 return total;
157 #endif
159 #if defined __linux__ || defined __CYGWIN__
160 /* File descriptor of the executable.
161 (Only used to verify that we find the correct executable.) */
162 static int executable_fd = -1;
163 #endif
165 /* Define this function only when it's needed. */
166 #if !(defined WINDOWS_NATIVE || defined __EMX__)
168 /* Tests whether a given filename may belong to the executable. */
169 static bool
170 maybe_executable (const char *filename)
172 /* The native Windows API lacks the access() function. */
173 # if !defined WINDOWS_NATIVE
174 if (access (filename, X_OK) < 0)
175 return false;
176 # endif
178 # if defined __linux__ || defined __CYGWIN__
179 if (executable_fd >= 0)
181 /* If we already have an executable_fd, check that filename points to
182 the same inode. */
183 struct stat statexe;
184 struct stat statfile;
186 if (fstat (executable_fd, &statexe) >= 0)
187 return (stat (filename, &statfile) >= 0
188 && statfile.st_dev
189 && statfile.st_dev == statexe.st_dev
190 && statfile.st_ino == statexe.st_ino);
192 # endif
194 /* Check that the filename does not point to a directory. */
196 struct stat statfile;
198 return (stat (filename, &statfile) >= 0
199 && ! S_ISDIR (statfile.st_mode));
203 #endif
205 /* Determine the full pathname of the current executable, freshly allocated.
206 Return NULL if unknown.
207 Guaranteed to work on Linux and native Windows. Likely to work on the
208 other Unixes (maybe except BeOS), under most conditions. */
209 static char *
210 find_executable (const char *argv0)
212 #if defined WINDOWS_NATIVE
213 /* Native Windows only.
214 On Cygwin, it is better to use the Cygwin provided /proc interface, than
215 to use native Windows API and cygwin_conv_to_posix_path, because it
216 supports longer file names
217 (see <https://cygwin.com/ml/cygwin/2011-01/msg00410.html>). */
218 char location[MAX_PATH];
219 int length = GetModuleFileName (NULL, location, sizeof (location));
220 if (length < 0)
221 return NULL;
222 if (!IS_FILE_NAME_WITH_DIR (location))
223 /* Shouldn't happen. */
224 return NULL;
225 return xstrdup (location);
226 #elif defined __EMX__
227 PPIB ppib;
228 char location[CCHMAXPATH];
230 /* See http://cyberkinetica.homeunix.net/os2tk45/cp1/619_L2H_DosGetInfoBlocksSynt.html
231 for specification of DosGetInfoBlocks(). */
232 if (DosGetInfoBlocks (NULL, &ppib))
233 return NULL;
235 /* See http://cyberkinetica.homeunix.net/os2tk45/cp1/1247_L2H_DosQueryModuleNameSy.html
236 for specification of DosQueryModuleName(). */
237 if (DosQueryModuleName (ppib->pib_hmte, sizeof (location), location))
238 return NULL;
240 _fnslashify (location);
242 return xstrdup (location);
243 #else /* Unix */
244 # if defined __linux__
245 /* The executable is accessible as /proc/<pid>/exe. In newer Linux
246 versions, also as /proc/self/exe. Linux >= 2.1 provides a symlink
247 to the true pathname; older Linux versions give only device and ino,
248 enclosed in brackets, which we cannot use here. */
250 char *link;
252 link = xreadlink ("/proc/self/exe");
253 if (link != NULL && link[0] != '[')
254 return link;
255 if (executable_fd < 0)
256 executable_fd = open ("/proc/self/exe", O_EXEC | O_CLOEXEC, 0);
259 char buf[6+10+5];
260 sprintf (buf, "/proc/%d/exe", getpid ());
261 link = xreadlink (buf);
262 if (link != NULL && link[0] != '[')
263 return link;
264 if (executable_fd < 0)
265 executable_fd = open (buf, O_EXEC | O_CLOEXEC, 0);
268 # endif
269 # if defined __ANDROID__ || defined __FreeBSD_kernel__
270 /* On Android and GNU/kFreeBSD, the executable is accessible as
271 /proc/<pid>/exe and /proc/self/exe. */
273 char *link;
275 link = xreadlink ("/proc/self/exe");
276 if (link != NULL)
277 return link;
279 # endif
280 # if defined __FreeBSD__ || defined __DragonFly__
281 /* In FreeBSD >= 5.0, the executable is accessible as /proc/<pid>/file and
282 /proc/curproc/file. */
284 char *link;
286 link = xreadlink ("/proc/curproc/file");
287 if (link != NULL)
289 if (strcmp (link, "unknown") != 0)
290 return link;
291 free (link);
294 # endif
295 # if defined __NetBSD__
296 /* In NetBSD >= 4.0, the executable is accessible as /proc/<pid>/exe and
297 /proc/curproc/exe. */
299 char *link;
301 link = xreadlink ("/proc/curproc/exe");
302 if (link != NULL)
303 return link;
305 # endif
306 # if defined __sun
307 /* On Solaris >= 11.4, /proc/<pid>/execname and /proc/self/execname contains
308 the name of the executable, either as an absolute file name or relative to
309 the current directory. */
311 char namebuf[4096];
312 int fd = open ("/proc/self/execname", O_RDONLY | O_CLOEXEC, 0);
313 if (fd >= 0)
315 size_t len = full_read (fd, namebuf, sizeof (namebuf));
316 close (fd);
317 if (len > 0 && len < sizeof (namebuf))
319 namebuf[len] = '\0';
320 return canonicalize_file_name (namebuf);
324 # endif
325 # if defined __CYGWIN__
326 /* The executable is accessible as /proc/<pid>/exe, at least in
327 Cygwin >= 1.5. */
329 char *link;
331 link = xreadlink ("/proc/self/exe");
332 if (link != NULL)
333 return link;
334 if (executable_fd < 0)
335 executable_fd = open ("/proc/self/exe", O_EXEC | O_CLOEXEC, 0);
337 # endif
338 # if HAVE_MACH_O_DYLD_H && HAVE__NSGETEXECUTABLEPATH
339 /* On Mac OS X 10.2 or newer, the function
340 int _NSGetExecutablePath (char *buf, uint32_t *bufsize);
341 can be used to retrieve the executable's full path. */
342 char location[4096];
343 unsigned int length = sizeof (location);
344 if (_NSGetExecutablePath (location, &length) == 0
345 && location[0] == '/')
346 return canonicalize_file_name (location);
347 # endif
348 /* Guess the executable's full path. We assume the executable has been
349 called via execlp() or execvp() with properly set up argv[0]. The
350 login(1) convention to add a '-' prefix to argv[0] is not supported. */
352 bool has_slash = false;
354 const char *p;
355 for (p = argv0; *p; p++)
356 if (*p == '/')
358 has_slash = true;
359 break;
362 if (!has_slash)
364 /* exec searches paths without slashes in the directory list given
365 by $PATH. */
366 const char *path = getenv ("PATH");
368 if (path != NULL)
370 const char *p;
371 const char *p_next;
373 for (p = path; *p; p = p_next)
375 const char *q;
376 size_t p_len;
377 char *concat_name;
379 for (q = p; *q; q++)
380 if (*q == ':')
381 break;
382 p_len = q - p;
383 p_next = (*q == '\0' ? q : q + 1);
385 /* We have a path item at p, of length p_len.
386 Now concatenate the path item and argv0. */
387 concat_name = (char *) xmalloc (p_len + strlen (argv0) + 2);
388 # ifdef NO_XMALLOC
389 if (concat_name == NULL)
390 return NULL;
391 # endif
392 if (p_len == 0)
393 /* An empty PATH element designates the current directory. */
394 strcpy (concat_name, argv0);
395 else
397 memcpy (concat_name, p, p_len);
398 concat_name[p_len] = '/';
399 strcpy (concat_name + p_len + 1, argv0);
401 if (maybe_executable (concat_name))
402 return canonicalize_file_name (concat_name);
403 free (concat_name);
406 /* Not found in the PATH, assume the current directory. */
408 /* exec treats paths containing slashes as relative to the current
409 directory. */
410 if (maybe_executable (argv0))
411 return canonicalize_file_name (argv0);
413 /* No way to find the executable. */
414 return NULL;
415 #endif
418 /* Full pathname of executable, or NULL. */
419 static char *executable_fullname;
421 static void
422 prepare_relocate (const char *orig_installprefix, const char *orig_installdir,
423 const char *argv0)
425 char *curr_prefix;
427 /* Determine the full pathname of the current executable. */
428 executable_fullname = find_executable (argv0);
430 /* Determine the current installation prefix from it. */
431 curr_prefix = compute_curr_prefix (orig_installprefix, orig_installdir,
432 executable_fullname);
433 if (curr_prefix != NULL)
435 /* Now pass this prefix to all copies of the relocate.c source file. */
436 set_relocation_prefix (orig_installprefix, curr_prefix);
438 free (curr_prefix);
442 /* Set program_name, based on argv[0], and original installation prefix and
443 directory, for relocatability. */
444 void
445 set_program_name_and_installdir (const char *argv0,
446 const char *orig_installprefix,
447 const char *orig_installdir)
449 const char *argv0_stripped = argv0;
451 /* Relocatable programs are renamed to .bin by install-reloc. Or, more
452 generally, their suffix is changed from $exeext to .bin$exeext.
453 Remove the ".bin" here. */
455 size_t argv0_len = strlen (argv0);
456 const size_t exeext_len = sizeof (EXEEXT) - sizeof ("");
457 if (argv0_len > 4 + exeext_len)
458 if (memcmp (argv0 + argv0_len - exeext_len - 4, ".bin", 4) == 0)
460 if (sizeof (EXEEXT) > sizeof (""))
462 /* Compare using an inlined copy of c_strncasecmp(), because
463 the filenames may have undergone a case conversion since
464 they were packaged. In other words, EXEEXT may be ".exe"
465 on one system and ".EXE" on another. */
466 static const char exeext[] = EXEEXT;
467 const char *s1 = argv0 + argv0_len - exeext_len;
468 const char *s2 = exeext;
469 for (; *s1 != '\0'; s1++, s2++)
471 unsigned char c1 = *s1;
472 unsigned char c2 = *s2;
473 if ((c1 >= 'A' && c1 <= 'Z' ? c1 - 'A' + 'a' : c1)
474 != (c2 >= 'A' && c2 <= 'Z' ? c2 - 'A' + 'a' : c2))
475 goto done_stripping;
478 /* Remove ".bin" before EXEEXT or its equivalent. */
480 char *shorter = (char *) xmalloc (argv0_len - 4 + 1);
481 #ifdef NO_XMALLOC
482 if (shorter != NULL)
483 #endif
485 memcpy (shorter, argv0, argv0_len - exeext_len - 4);
486 if (sizeof (EXEEXT) > sizeof (""))
487 memcpy (shorter + argv0_len - exeext_len - 4,
488 argv0 + argv0_len - exeext_len - 4,
489 exeext_len);
490 shorter[argv0_len - 4] = '\0';
491 argv0_stripped = shorter;
494 done_stripping: ;
498 set_program_name (argv0_stripped);
500 prepare_relocate (orig_installprefix, orig_installdir, argv0);
503 /* Return the full pathname of the current executable, based on the earlier
504 call to set_program_name_and_installdir. Return NULL if unknown. */
505 char *
506 get_full_program_name (void)
508 return executable_fullname;
511 #endif