Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / libiconv / srclib / progreloc.c
blob4a3fa48be48e25f7891745617369e223af03ac8e
1 /* Provide relocatable programs.
2 Copyright (C) 2003-2011 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 <http://www.gnu.org/licenses/>. */
19 #define _GL_USE_STDLIB_ALLOC 1
20 #include <config.h>
22 /* Specification. */
23 #include "progname.h"
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <sys/stat.h>
33 /* Get declaration of _NSGetExecutablePath on MacOS X 10.2 or newer. */
34 #if HAVE_MACH_O_DYLD_H
35 # include <mach-o/dyld.h>
36 #endif
38 #if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
39 # define WIN32_NATIVE
40 #endif
42 #ifdef WIN32_NATIVE
43 # define WIN32_LEAN_AND_MEAN
44 # include <windows.h>
45 #endif
47 #include "relocatable.h"
49 #ifdef NO_XMALLOC
50 # include "areadlink.h"
51 # define xreadlink areadlink
52 #else
53 # include "xreadlink.h"
54 #endif
56 #ifdef NO_XMALLOC
57 # define xmalloc malloc
58 # define xstrdup strdup
59 #else
60 # include "xalloc.h"
61 #endif
63 #ifndef O_EXEC
64 # define O_EXEC O_RDONLY /* This is often close enough in older systems. */
65 #endif
67 /* Declare canonicalize_file_name.
68 The <stdlib.h> included above may be the system's one, not the gnulib
69 one. */
70 extern char * canonicalize_file_name (const char *name);
72 /* Pathname support.
73 ISSLASH(C) tests whether C is a directory separator character.
74 IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
76 #if ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__
77 /* Win32, OS/2, DOS */
78 # define ISSLASH(C) ((C) == '/' || (C) == '\\')
79 # define HAS_DEVICE(P) \
80 ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
81 && (P)[1] == ':')
82 # define IS_PATH_WITH_DIR(P) \
83 (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
84 # define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
85 #else
86 /* Unix */
87 # define ISSLASH(C) ((C) == '/')
88 # define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
89 # define FILE_SYSTEM_PREFIX_LEN(P) 0
90 #endif
92 /* The results of open() in this file are not used with fchdir,
93 therefore save some unnecessary work in fchdir.c. */
94 #undef open
95 #undef close
97 /* Use the system functions, not the gnulib overrides in this file. */
98 #undef sprintf
100 #undef set_program_name
103 #if ENABLE_RELOCATABLE
105 #if defined __linux__ || defined __CYGWIN__
106 /* File descriptor of the executable.
107 (Only used to verify that we find the correct executable.) */
108 static int executable_fd = -1;
109 #endif
111 /* Tests whether a given pathname may belong to the executable. */
112 static bool
113 maybe_executable (const char *filename)
115 /* Woe32 lacks the access() function. */
116 #if !defined WIN32_NATIVE
117 if (access (filename, X_OK) < 0)
118 return false;
119 #endif
121 #if defined __linux__ || defined __CYGWIN__
122 if (executable_fd >= 0)
124 /* If we already have an executable_fd, check that filename points to
125 the same inode. */
126 struct stat statexe;
127 struct stat statfile;
129 if (fstat (executable_fd, &statexe) >= 0)
131 if (stat (filename, &statfile) < 0)
132 return false;
133 if (!(statfile.st_dev
134 && statfile.st_dev == statexe.st_dev
135 && statfile.st_ino == statexe.st_ino))
136 return false;
139 #endif
141 return true;
144 /* Determine the full pathname of the current executable, freshly allocated.
145 Return NULL if unknown.
146 Guaranteed to work on Linux and Woe32. Likely to work on the other
147 Unixes (maybe except BeOS), under most conditions. */
148 static char *
149 find_executable (const char *argv0)
151 #if defined WIN32_NATIVE
152 /* Native Win32 only.
153 On Cygwin, it is better to use the Cygwin provided /proc interface, than
154 to use native Win32 API and cygwin_conv_to_posix_path, because it supports
155 longer file names
156 (see <http://cygwin.com/ml/cygwin/2011-01/msg00410.html>). */
157 char location[MAX_PATH];
158 int length = GetModuleFileName (NULL, location, sizeof (location));
159 if (length < 0)
160 return NULL;
161 if (!IS_PATH_WITH_DIR (location))
162 /* Shouldn't happen. */
163 return NULL;
164 return xstrdup (location);
165 #else /* Unix */
166 # ifdef __linux__
167 /* The executable is accessible as /proc/<pid>/exe. In newer Linux
168 versions, also as /proc/self/exe. Linux >= 2.1 provides a symlink
169 to the true pathname; older Linux versions give only device and ino,
170 enclosed in brackets, which we cannot use here. */
172 char *link;
174 link = xreadlink ("/proc/self/exe");
175 if (link != NULL && link[0] != '[')
176 return link;
177 if (executable_fd < 0)
178 executable_fd = open ("/proc/self/exe", O_EXEC, 0);
181 char buf[6+10+5];
182 sprintf (buf, "/proc/%d/exe", getpid ());
183 link = xreadlink (buf);
184 if (link != NULL && link[0] != '[')
185 return link;
186 if (executable_fd < 0)
187 executable_fd = open (buf, O_EXEC, 0);
190 # endif
191 # ifdef __CYGWIN__
192 /* The executable is accessible as /proc/<pid>/exe, at least in
193 Cygwin >= 1.5. */
195 char *link;
197 link = xreadlink ("/proc/self/exe");
198 if (link != NULL)
199 return link;
200 if (executable_fd < 0)
201 executable_fd = open ("/proc/self/exe", O_EXEC, 0);
203 # endif
204 # if HAVE_MACH_O_DYLD_H && HAVE__NSGETEXECUTABLEPATH
205 /* On MacOS X 10.2 or newer, the function
206 int _NSGetExecutablePath (char *buf, uint32_t *bufsize);
207 can be used to retrieve the executable's full path. */
208 char location[4096];
209 unsigned int length = sizeof (location);
210 if (_NSGetExecutablePath (location, &length) == 0
211 && location[0] == '/')
212 return canonicalize_file_name (location);
213 # endif
214 /* Guess the executable's full path. We assume the executable has been
215 called via execlp() or execvp() with properly set up argv[0]. The
216 login(1) convention to add a '-' prefix to argv[0] is not supported. */
218 bool has_slash = false;
220 const char *p;
221 for (p = argv0; *p; p++)
222 if (*p == '/')
224 has_slash = true;
225 break;
228 if (!has_slash)
230 /* exec searches paths without slashes in the directory list given
231 by $PATH. */
232 const char *path = getenv ("PATH");
234 if (path != NULL)
236 const char *p;
237 const char *p_next;
239 for (p = path; *p; p = p_next)
241 const char *q;
242 size_t p_len;
243 char *concat_name;
245 for (q = p; *q; q++)
246 if (*q == ':')
247 break;
248 p_len = q - p;
249 p_next = (*q == '\0' ? q : q + 1);
251 /* We have a path item at p, of length p_len.
252 Now concatenate the path item and argv0. */
253 concat_name = (char *) xmalloc (p_len + strlen (argv0) + 2);
254 # ifdef NO_XMALLOC
255 if (concat_name == NULL)
256 return NULL;
257 # endif
258 if (p_len == 0)
259 /* An empty PATH element designates the current directory. */
260 strcpy (concat_name, argv0);
261 else
263 memcpy (concat_name, p, p_len);
264 concat_name[p_len] = '/';
265 strcpy (concat_name + p_len + 1, argv0);
267 if (maybe_executable (concat_name))
268 return canonicalize_file_name (concat_name);
269 free (concat_name);
272 /* Not found in the PATH, assume the current directory. */
274 /* exec treats paths containing slashes as relative to the current
275 directory. */
276 if (maybe_executable (argv0))
277 return canonicalize_file_name (argv0);
279 /* No way to find the executable. */
280 return NULL;
281 #endif
284 /* Full pathname of executable, or NULL. */
285 static char *executable_fullname;
287 static void
288 prepare_relocate (const char *orig_installprefix, const char *orig_installdir,
289 const char *argv0)
291 char *curr_prefix;
293 /* Determine the full pathname of the current executable. */
294 executable_fullname = find_executable (argv0);
296 /* Determine the current installation prefix from it. */
297 curr_prefix = compute_curr_prefix (orig_installprefix, orig_installdir,
298 executable_fullname);
299 if (curr_prefix != NULL)
301 /* Now pass this prefix to all copies of the relocate.c source file. */
302 set_relocation_prefix (orig_installprefix, curr_prefix);
304 free (curr_prefix);
308 /* Set program_name, based on argv[0], and original installation prefix and
309 directory, for relocatability. */
310 void
311 set_program_name_and_installdir (const char *argv0,
312 const char *orig_installprefix,
313 const char *orig_installdir)
315 const char *argv0_stripped = argv0;
317 /* Relocatable programs are renamed to .bin by install-reloc. Or, more
318 generally, their suffix is changed from $exeext to .bin$exeext.
319 Remove the ".bin" here. */
321 size_t argv0_len = strlen (argv0);
322 const size_t exeext_len = sizeof (EXEEXT) - sizeof ("");
323 if (argv0_len > 4 + exeext_len)
324 if (memcmp (argv0 + argv0_len - exeext_len - 4, ".bin", 4) == 0)
326 if (sizeof (EXEEXT) > sizeof (""))
328 /* Compare using an inlined copy of c_strncasecmp(), because
329 the filenames may have undergone a case conversion since
330 they were packaged. In other words, EXEEXT may be ".exe"
331 on one system and ".EXE" on another. */
332 static const char exeext[] = EXEEXT;
333 const char *s1 = argv0 + argv0_len - exeext_len;
334 const char *s2 = exeext;
335 for (; *s1 != '\0'; s1++, s2++)
337 unsigned char c1 = *s1;
338 unsigned char c2 = *s2;
339 if ((c1 >= 'A' && c1 <= 'Z' ? c1 - 'A' + 'a' : c1)
340 != (c2 >= 'A' && c2 <= 'Z' ? c2 - 'A' + 'a' : c2))
341 goto done_stripping;
344 /* Remove ".bin" before EXEEXT or its equivalent. */
346 char *shorter = (char *) xmalloc (argv0_len - 4 + 1);
347 #ifdef NO_XMALLOC
348 if (shorter != NULL)
349 #endif
351 memcpy (shorter, argv0, argv0_len - exeext_len - 4);
352 if (sizeof (EXEEXT) > sizeof (""))
353 memcpy (shorter + argv0_len - exeext_len - 4,
354 argv0 + argv0_len - exeext_len - 4,
355 exeext_len);
356 shorter[argv0_len - 4] = '\0';
357 argv0_stripped = shorter;
360 done_stripping: ;
364 set_program_name (argv0_stripped);
366 prepare_relocate (orig_installprefix, orig_installdir, argv0);
369 /* Return the full pathname of the current executable, based on the earlier
370 call to set_program_name_and_installdir. Return NULL if unknown. */
371 char *
372 get_full_program_name (void)
374 return executable_fullname;
377 #endif