Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / kwsys / SharedForward.h.in
blob3f864faa49f08b041753e753375087a39b9adf3a
1 /*=========================================================================
3 Program: KWSys - Kitware System Library
4 Module: $RCSfile: SharedForward.h.in,v $
6 Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
7 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the above copyright notices for more information.
13 =========================================================================*/
14 #ifndef @KWSYS_NAMESPACE@_SharedForward_h
15 #define @KWSYS_NAMESPACE@_SharedForward_h
18 This header is used to create a forwarding executable sets up the
19 shared library search path and replaces itself with a real
20 executable. This is useful when creating installations on UNIX with
21 shared libraries that will run from any install directory. Typical
22 usage:
24 #if defined(CMAKE_INTDIR)
25 # define CONFIG_DIR_PRE CMAKE_INTDIR "/"
26 # define CONFIG_DIR_POST "/" CMAKE_INTDIR
27 #else
28 # define CONFIG_DIR_PRE ""
29 # define CONFIG_DIR_POST ""
30 #endif
31 #define @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD "/path/to/foo-build/bin"
32 #define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD "." CONFIG_DIR_POST
33 #define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL "../lib/foo-1.2"
34 #define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD CONFIG_DIR_PRE "foo-real"
35 #define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL "../lib/foo-1.2/foo-real"
36 #define @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_COMMAND "--command"
37 #define @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT "--print"
38 #define @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD "--ldd"
39 #if defined(CMAKE_INTDIR)
40 # define @KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME CMAKE_INTDIR
41 #endif
42 #include <@KWSYS_NAMESPACE@/SharedForward.h>
43 int main(int argc, char** argv)
45 return @KWSYS_NAMESPACE@_shared_forward_to_real(argc, argv);
48 Specify search and executable paths relative to the forwarding
49 executable location or as full paths. Include no trailing slash.
50 In the case of a multi-configuration build, when CMAKE_INTDIR is
51 defined, the DIR_BUILD setting should point at the directory above
52 the executable (the one containing the per-configuration
53 subdirectory specified by CMAKE_INTDIR). Then PATH_BUILD entries
54 and EXE_BUILD should be specified relative to this location and use
55 CMAKE_INTDIR as necessary. In the above example imagine appending
56 the PATH_BUILD or EXE_BUILD setting to the DIR_BUILD setting. The
57 result should form a valid path with per-configuration subdirectory.
59 Additional paths may be specified in the PATH_BUILD and PATH_INSTALL
60 variables by using comma-separated strings. For example:
62 #define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD \
63 "." CONFIG_DIR_POST, "/path/to/bar-build" CONFIG_DIR_POST
64 #define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL \
65 "../lib/foo-1.2", "../lib/bar-4.5"
67 See the comments below for specific explanations of each macro.
70 /*--------------------------------------------------------------------------*/
72 /* Full path to the directory in which this executable is built. Do
73 not include a trailing slash. */
74 #if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD)
75 # error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD"
76 #endif
77 #if !defined(KWSYS_SHARED_FORWARD_DIR_BUILD)
78 # define KWSYS_SHARED_FORWARD_DIR_BUILD @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD
79 #endif
81 /* Library search path for build tree. */
82 #if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD)
83 # error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD"
84 #endif
85 #if !defined(KWSYS_SHARED_FORWARD_PATH_BUILD)
86 # define KWSYS_SHARED_FORWARD_PATH_BUILD @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD
87 #endif
89 /* Library search path for install tree. */
90 #if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL)
91 # error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL"
92 #endif
93 #if !defined(KWSYS_SHARED_FORWARD_PATH_INSTALL)
94 # define KWSYS_SHARED_FORWARD_PATH_INSTALL @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL
95 #endif
97 /* The real executable to which to forward in the build tree. */
98 #if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD)
99 # error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD"
100 #endif
101 #if !defined(KWSYS_SHARED_FORWARD_EXE_BUILD)
102 # define KWSYS_SHARED_FORWARD_EXE_BUILD @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD
103 #endif
105 /* The real executable to which to forward in the install tree. */
106 #if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL)
107 # error "Must define @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL"
108 #endif
109 #if !defined(KWSYS_SHARED_FORWARD_EXE_INSTALL)
110 # define KWSYS_SHARED_FORWARD_EXE_INSTALL @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL
111 #endif
113 /* The configuration name with which this executable was built (Debug/Release). */
114 #if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME)
115 # define KWSYS_SHARED_FORWARD_CONFIG_NAME @KWSYS_NAMESPACE@_SHARED_FORWARD_CONFIG_NAME
116 #else
117 # undef KWSYS_SHARED_FORWARD_CONFIG_NAME
118 #endif
120 /* Create command line option to replace executable. */
121 #if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_COMMAND)
122 # if !defined(KWSYS_SHARED_FORWARD_OPTION_COMMAND)
123 # define KWSYS_SHARED_FORWARD_OPTION_COMMAND @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_COMMAND
124 # endif
125 #else
126 # undef KWSYS_SHARED_FORWARD_OPTION_COMMAND
127 #endif
129 /* Create command line option to print environment setting and exit. */
130 #if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT)
131 # if !defined(KWSYS_SHARED_FORWARD_OPTION_PRINT)
132 # define KWSYS_SHARED_FORWARD_OPTION_PRINT @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_PRINT
133 # endif
134 #else
135 # undef KWSYS_SHARED_FORWARD_OPTION_PRINT
136 #endif
138 /* Create command line option to run ldd or equivalent. */
139 #if defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD)
140 # if !defined(KWSYS_SHARED_FORWARD_OPTION_LDD)
141 # define KWSYS_SHARED_FORWARD_OPTION_LDD @KWSYS_NAMESPACE@_SHARED_FORWARD_OPTION_LDD
142 # endif
143 #else
144 # undef KWSYS_SHARED_FORWARD_OPTION_LDD
145 #endif
147 /*--------------------------------------------------------------------------*/
148 /* Include needed system headers. */
150 #include <limits.h>
151 #include <stdlib.h>
152 #include <string.h>
153 #include <errno.h>
154 #include <stdio.h>
156 #if defined(_WIN32) && !defined(__CYGWIN__)
157 # include <io.h>
158 # include <windows.h>
159 # include <process.h>
160 # define KWSYS_SHARED_FORWARD_ESCAPE_ARGV /* re-escape argv for execvp */
161 #else
162 # include <unistd.h>
163 # include <sys/stat.h>
164 #endif
166 /*--------------------------------------------------------------------------*/
167 /* Configuration for this platform. */
169 /* The path separator for this platform. */
170 #if defined(_WIN32) && !defined(__CYGWIN__)
171 # define KWSYS_SHARED_FORWARD_PATH_SEP ';'
172 # define KWSYS_SHARED_FORWARD_PATH_SLASH '\\'
173 #else
174 # define KWSYS_SHARED_FORWARD_PATH_SEP ':'
175 # define KWSYS_SHARED_FORWARD_PATH_SLASH '/'
176 #endif
177 static const char kwsys_shared_forward_path_sep[2] = {KWSYS_SHARED_FORWARD_PATH_SEP, 0};
178 static const char kwsys_shared_forward_path_slash[2] = {KWSYS_SHARED_FORWARD_PATH_SLASH, 0};
180 /* The maximum length of a file name. */
181 #if defined(PATH_MAX)
182 # define KWSYS_SHARED_FORWARD_MAXPATH PATH_MAX
183 #elif defined(MAXPATHLEN)
184 # define KWSYS_SHARED_FORWARD_MAXPATH MAXPATHLEN
185 #else
186 # define KWSYS_SHARED_FORWARD_MAXPATH 16384
187 #endif
189 /* Select the environment variable holding the shared library runtime
190 search path for this platform and build configuration. Also select
191 ldd command equivalent. */
193 /* Linux */
194 #if defined(__linux)
195 # define KWSYS_SHARED_FORWARD_LDD "ldd"
196 # define KWSYS_SHARED_FORWARD_LDD_N 1
197 # define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
198 #endif
200 /* FreeBSD */
201 #if defined(__FreeBSD__)
202 # define KWSYS_SHARED_FORWARD_LDD "ldd"
203 # define KWSYS_SHARED_FORWARD_LDD_N 1
204 # define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
205 #endif
207 /* OSX */
208 #if defined(__APPLE__)
209 # define KWSYS_SHARED_FORWARD_LDD "otool", "-L"
210 # define KWSYS_SHARED_FORWARD_LDD_N 2
211 # define KWSYS_SHARED_FORWARD_LDPATH "DYLD_LIBRARY_PATH"
212 #endif
214 /* AIX */
215 #if defined(_AIX)
216 # define KWSYS_SHARED_FORWARD_LDD "dump", "-H"
217 # define KWSYS_SHARED_FORWARD_LDD_N 2
218 # define KWSYS_SHARED_FORWARD_LDPATH "LIBPATH"
219 #endif
221 /* SUN */
222 #if defined(__sparc)
223 # define KWSYS_SHARED_FORWARD_LDD "ldd"
224 # define KWSYS_SHARED_FORWARD_LDD_N 1
225 # include <sys/isa_defs.h>
226 # if defined(_ILP32)
227 # define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
228 # elif defined(_LP64)
229 # define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH_64"
230 # endif
231 #endif
233 /* HP-UX */
234 #if defined(__hpux)
235 # define KWSYS_SHARED_FORWARD_LDD "chatr"
236 # define KWSYS_SHARED_FORWARD_LDD_N 1
237 # if defined(__LP64__)
238 # define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
239 # else
240 # define KWSYS_SHARED_FORWARD_LDPATH "SHLIB_PATH"
241 # endif
242 #endif
244 /* SGI MIPS */
245 #if defined(__sgi) && defined(_MIPS_SIM)
246 # define KWSYS_SHARED_FORWARD_LDD "ldd"
247 # define KWSYS_SHARED_FORWARD_LDD_N 1
248 # if _MIPS_SIM == _ABIO32
249 # define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
250 # elif _MIPS_SIM == _ABIN32
251 # define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARYN32_PATH"
252 # elif _MIPS_SIM == _ABI64
253 # define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY64_PATH"
254 # endif
255 #endif
257 /* Windows */
258 #if defined(_WIN32)
259 # if defined(__CYGWIN__)
260 # define KWSYS_SHARED_FORWARD_LDD "cygcheck"
261 # define KWSYS_SHARED_FORWARD_LDD_N 1
262 # endif
263 # define KWSYS_SHARED_FORWARD_LDPATH "PATH"
264 #endif
266 /* Guess on this unknown system. */
267 #if !defined(KWSYS_SHARED_FORWARD_LDPATH)
268 # define KWSYS_SHARED_FORWARD_LDD "ldd"
269 # define KWSYS_SHARED_FORWARD_LDD_N 1
270 # define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
271 #endif
273 #ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
274 /*--------------------------------------------------------------------------*/
275 typedef struct kwsys_sf_arg_info_s
277 const char* arg;
278 int size;
279 int quote;
280 } kwsys_sf_arg_info;
282 /*--------------------------------------------------------------------------*/
283 static kwsys_sf_arg_info kwsys_sf_get_arg_info(const char* in)
285 /* Initialize information. */
286 kwsys_sf_arg_info info;
288 /* String iterator. */
289 const char* c;
291 /* Keep track of how many backslashes have been encountered in a row. */
292 int windows_backslashes = 0;
294 /* Start with the length of the original argument, plus one for
295 either a terminating null or a separating space. */
296 info.arg = in;
297 info.size = (int)strlen(in) + 1;
298 info.quote = 0;
300 /* Scan the string for characters that require escaping or quoting. */
301 for(c=in; *c; ++c)
303 /* Check whether this character needs quotes. */
304 if(strchr(" \t?'#&<>|^", *c))
306 info.quote = 1;
309 /* On Windows only backslashes and double-quotes need escaping. */
310 if(*c == '\\')
312 /* Found a backslash. It may need to be escaped later. */
313 ++windows_backslashes;
315 else if(*c == '"')
317 /* Found a double-quote. We need to escape it and all
318 immediately preceding backslashes. */
319 info.size += windows_backslashes + 1;
320 windows_backslashes = 0;
322 else
324 /* Found another character. This eliminates the possibility
325 that any immediately preceding backslashes will be
326 escaped. */
327 windows_backslashes = 0;
331 /* Check whether the argument needs surrounding quotes. */
332 if(info.quote)
334 /* Surrounding quotes are needed. Allocate space for them. */
335 info.size += 2;
337 /* We must escape all ending backslashes when quoting on windows. */
338 info.size += windows_backslashes;
341 return info;
344 /*--------------------------------------------------------------------------*/
345 static char* kwsys_sf_get_arg(kwsys_sf_arg_info info, char* out)
347 /* String iterator. */
348 const char* c;
350 /* Keep track of how many backslashes have been encountered in a row. */
351 int windows_backslashes = 0;
353 /* Whether the argument must be quoted. */
354 if(info.quote)
356 /* Add the opening quote for this argument. */
357 *out++ = '"';
360 /* Scan the string for characters that require escaping or quoting. */
361 for(c=info.arg; *c; ++c)
363 /* On Windows only backslashes and double-quotes need escaping. */
364 if(*c == '\\')
366 /* Found a backslash. It may need to be escaped later. */
367 ++windows_backslashes;
369 else if(*c == '"')
371 /* Found a double-quote. Escape all immediately preceding
372 backslashes. */
373 while(windows_backslashes > 0)
375 --windows_backslashes;
376 *out++ = '\\';
379 /* Add the backslash to escape the double-quote. */
380 *out++ = '\\';
382 else
384 /* We encountered a normal character. This eliminates any
385 escaping needed for preceding backslashes. */
386 windows_backslashes = 0;
389 /* Store this character. */
390 *out++ = *c;
393 if(info.quote)
395 /* Add enough backslashes to escape any trailing ones. */
396 while(windows_backslashes > 0)
398 --windows_backslashes;
399 *out++ = '\\';
402 /* Add the closing quote for this argument. */
403 *out++ = '"';
406 /* Store a terminating null without incrementing. */
407 *out = 0;
409 return out;
411 #endif
413 /*--------------------------------------------------------------------------*/
414 /* Function to convert a logical or relative path to a physical full path. */
415 static int kwsys_shared_forward_realpath(const char* in_path, char* out_path)
417 #if defined(_WIN32) && !defined(__CYGWIN__)
418 /* Implementation for Windows. */
419 DWORD n = GetFullPathName(in_path, KWSYS_SHARED_FORWARD_MAXPATH,
420 out_path, 0);
421 return n > 0 && n <= KWSYS_SHARED_FORWARD_MAXPATH;
422 #else
423 /* Implementation for UNIX. */
424 return realpath(in_path, out_path) != 0;
425 #endif
428 /*--------------------------------------------------------------------------*/
429 static int kwsys_shared_forward_samepath(const char* file1, const char* file2)
431 #if defined(_WIN32)
432 int result = 0;
433 HANDLE h1 = CreateFile(file1, GENERIC_READ, FILE_SHARE_READ, NULL,
434 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
435 HANDLE h2 = CreateFile(file2, GENERIC_READ, FILE_SHARE_READ, NULL,
436 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
437 if(h1 != INVALID_HANDLE_VALUE && h2 != INVALID_HANDLE_VALUE)
439 BY_HANDLE_FILE_INFORMATION fi1;
440 BY_HANDLE_FILE_INFORMATION fi2;
441 GetFileInformationByHandle(h1, &fi1);
442 GetFileInformationByHandle(h2, &fi2);
443 result = (fi1.dwVolumeSerialNumber == fi2.dwVolumeSerialNumber &&
444 fi1.nFileIndexHigh == fi2.nFileIndexHigh &&
445 fi1.nFileIndexLow == fi2.nFileIndexLow);
447 CloseHandle(h1);
448 CloseHandle(h2);
449 return result;
450 #else
451 struct stat fs1, fs2;
452 return (stat(file1, &fs1) == 0 && stat(file2, &fs2) == 0 &&
453 memcmp(&fs2.st_dev, &fs1.st_dev, sizeof(fs1.st_dev)) == 0 &&
454 memcmp(&fs2.st_ino, &fs1.st_ino, sizeof(fs1.st_ino)) == 0 &&
455 fs2.st_size == fs1.st_size);
456 #endif
459 /*--------------------------------------------------------------------------*/
460 /* Function to report a system error message. */
461 static void kwsys_shared_forward_strerror(char* message)
463 #if defined(_WIN32) && !defined(__CYGWIN__)
464 /* Implementation for Windows. */
465 DWORD original = GetLastError();
466 DWORD length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
467 FORMAT_MESSAGE_IGNORE_INSERTS, 0, original,
468 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
469 message, KWSYS_SHARED_FORWARD_MAXPATH, 0);
470 if(length < 1 || length > KWSYS_SHARED_FORWARD_MAXPATH)
472 /* FormatMessage failed. Use a default message. */
473 _snprintf(message, KWSYS_SHARED_FORWARD_MAXPATH,
474 "Error 0x%X (FormatMessage failed with error 0x%X)",
475 original, GetLastError());
477 #else
478 /* Implementation for UNIX. */
479 strcpy(message, strerror(errno));
480 #endif
483 /*--------------------------------------------------------------------------*/
484 /* Functions to execute a child process. */
485 static void kwsys_shared_forward_execvp(const char* cmd, char* const* argv)
487 #ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
488 /* Count the number of arguments. */
489 int argc = 0;
491 char* const* argvc;
492 for(argvc = argv; *argvc; ++argvc,++argc) {}
495 /* Create the escaped arguments. */
497 char** nargv = (char**)malloc((argc+1) * sizeof(char*));
498 int i;
499 for(i=0; i < argc; ++i)
501 kwsys_sf_arg_info info = kwsys_sf_get_arg_info(argv[i]);
502 nargv[i] = (char*)malloc(info.size);
503 kwsys_sf_get_arg(info, nargv[i]);
505 nargv[argc] = 0;
507 /* Replace the command line to be used. */
508 argv = nargv;
510 #endif
512 /* Invoke the child process. */
513 #if defined(_MSC_VER)
514 _execvp(cmd, argv);
515 #elif defined(__MINGW32__)
516 /* Avoid incompatible pointer warning with a cast. */
517 execvp(cmd, (char const* const*)argv);
518 #else
519 execvp(cmd, argv);
520 #endif
523 /*--------------------------------------------------------------------------*/
524 /* Function to get the directory containing the given file or directory. */
525 static void kwsys_shared_forward_dirname(const char* begin, char* result)
527 /* Find the location of the last slash. */
528 int last_slash_index = -1;
529 const char* end = begin + strlen(begin);
530 for(;begin <= end && last_slash_index < 0; --end)
532 if(*end == '/' || *end == '\\')
534 last_slash_index = (int)(end-begin);
538 /* Handle each case of the index of the last slash. */
539 if(last_slash_index < 0)
541 /* No slashes. */
542 strcpy(result, ".");
544 else if(last_slash_index == 0)
546 /* Only one leading slash. */
547 strcpy(result, kwsys_shared_forward_path_slash);
549 #if defined(_WIN32)
550 else if(last_slash_index == 2 && begin[1] == ':')
552 /* Only one leading drive letter and slash. */
553 strncpy(result, begin, last_slash_index);
554 result[last_slash_index] = KWSYS_SHARED_FORWARD_PATH_SLASH;
555 result[last_slash_index+1] = 0;
557 #endif
558 else
560 /* A non-leading slash. */
561 strncpy(result, begin, last_slash_index);
562 result[last_slash_index] = 0;
566 /*--------------------------------------------------------------------------*/
567 /* Function to check if a file exists and is executable. */
568 static int kwsys_shared_forward_is_executable(const char* f)
570 #if defined(_MSC_VER)
571 # define KWSYS_SHARED_FORWARD_ACCESS _access
572 #else
573 # define KWSYS_SHARED_FORWARD_ACCESS access
574 #endif
575 #if defined(X_OK)
576 # define KWSYS_SHARED_FORWARD_ACCESS_OK X_OK
577 #else
578 # define KWSYS_SHARED_FORWARD_ACCESS_OK 04
579 #endif
580 if(KWSYS_SHARED_FORWARD_ACCESS(f, KWSYS_SHARED_FORWARD_ACCESS_OK) == 0)
582 return 1;
584 else
586 return 0;
590 /*--------------------------------------------------------------------------*/
591 /* Function to locate the executable currently running. */
592 static int kwsys_shared_forward_self_path(const char* argv0, char* result)
594 /* Check whether argv0 has a slash. */
595 int has_slash = 0;
596 const char* p = argv0;
597 for(;*p && !has_slash; ++p)
599 if(*p == '/' || *p == '\\')
601 has_slash = 1;
605 if(has_slash)
607 /* There is a slash. Use the dirname of the given location. */
608 kwsys_shared_forward_dirname(argv0, result);
609 return 1;
611 else
613 /* There is no slash. Search the PATH for the executable. */
614 const char* path = getenv("PATH");
615 const char* begin = path;
616 const char* end = begin + (begin?strlen(begin):0);
617 const char* first = begin;
618 while(first != end)
620 /* Store the end of this path entry. */
621 const char* last;
623 /* Skip all path separators. */
624 for(;*first && *first == KWSYS_SHARED_FORWARD_PATH_SEP; ++first);
626 /* Find the next separator. */
627 for(last = first;*last && *last != KWSYS_SHARED_FORWARD_PATH_SEP; ++last);
629 /* If we got a non-empty directory, look for the executable there. */
630 if(first < last)
632 /* Determine the length without trailing slash. */
633 int length = (int)(last-first);
634 if(*(last-1) == '/' || *(last-1) == '\\')
636 --length;
639 /* Construct the name of the executable in this location. */
640 strncpy(result, first, length);
641 result[length] = KWSYS_SHARED_FORWARD_PATH_SLASH;
642 strcpy(result+(length)+1, argv0);
644 /* Check if it exists and is executable. */
645 if(kwsys_shared_forward_is_executable(result))
647 /* Found it. */
648 result[length] = 0;
649 return 1;
653 /* Move to the next directory in the path. */
654 first = last;
658 /* We could not find the executable. */
659 return 0;
662 /*--------------------------------------------------------------------------*/
663 /* Function to convert a specified path to a full path. If it is not
664 already full, it is taken relative to the self path. */
665 static int kwsys_shared_forward_fullpath(const char* self_path,
666 const char* in_path,
667 char* result,
668 const char* desc)
670 /* Check the specified path type. */
671 if(in_path[0] == '/')
673 /* Already a full path. */
674 strcpy(result, in_path);
676 #if defined(_WIN32)
677 else if(in_path[0] && in_path[1] == ':')
679 /* Already a full path. */
680 strcpy(result, in_path);
682 #endif
683 else
685 /* Relative to self path. */
686 char temp_path[KWSYS_SHARED_FORWARD_MAXPATH];
687 strcpy(temp_path, self_path);
688 strcat(temp_path, kwsys_shared_forward_path_slash);
689 strcat(temp_path, in_path);
690 if(!kwsys_shared_forward_realpath(temp_path, result))
692 if(desc)
694 char msgbuf[KWSYS_SHARED_FORWARD_MAXPATH];
695 kwsys_shared_forward_strerror(msgbuf);
696 fprintf(stderr, "Error converting %s \"%s\" to real path: %s\n",
697 desc, temp_path, msgbuf);
699 return 0;
702 return 1;
705 /*--------------------------------------------------------------------------*/
706 /* Function to compute the library search path and executable name
707 based on the self path. */
708 static int kwsys_shared_forward_get_settings(const char* self_path,
709 char* ldpath, char* exe)
711 /* Possible search paths. */
712 static const char* search_path_build[] = {KWSYS_SHARED_FORWARD_PATH_BUILD, 0};
713 static const char* search_path_install[] = {KWSYS_SHARED_FORWARD_PATH_INSTALL, 0};
715 /* Chosen paths. */
716 const char** search_path;
717 const char* exe_path;
719 /* Get the real name of the build and self paths. */
720 #if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
721 char build_path[] = KWSYS_SHARED_FORWARD_DIR_BUILD "/" KWSYS_SHARED_FORWARD_CONFIG_NAME;
722 char self_path_logical[KWSYS_SHARED_FORWARD_MAXPATH];
723 #else
724 char build_path[] = KWSYS_SHARED_FORWARD_DIR_BUILD;
725 const char* self_path_logical = self_path;
726 #endif
727 char build_path_real[KWSYS_SHARED_FORWARD_MAXPATH];
728 char self_path_real[KWSYS_SHARED_FORWARD_MAXPATH];
729 if(!kwsys_shared_forward_realpath(self_path, self_path_real))
731 char msgbuf[KWSYS_SHARED_FORWARD_MAXPATH];
732 kwsys_shared_forward_strerror(msgbuf);
733 fprintf(stderr, "Error converting self path \"%s\" to real path: %s\n",
734 self_path, msgbuf);
735 return 0;
738 /* Check whether we are running in the build tree or an install tree. */
739 if(kwsys_shared_forward_realpath(build_path, build_path_real) &&
740 kwsys_shared_forward_samepath(self_path_real, build_path_real))
742 /* Running in build tree. Use the build path and exe. */
743 search_path = search_path_build;
744 #if defined(_WIN32)
745 exe_path = KWSYS_SHARED_FORWARD_EXE_BUILD ".exe";
746 #else
747 exe_path = KWSYS_SHARED_FORWARD_EXE_BUILD;
748 #endif
750 #if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
751 /* Remove the configuration directory from self_path. */
752 kwsys_shared_forward_dirname(self_path, self_path_logical);
753 #endif
755 else
757 /* Running in install tree. Use the install path and exe. */
758 search_path = search_path_install;
759 #if defined(_WIN32)
760 exe_path = KWSYS_SHARED_FORWARD_EXE_INSTALL ".exe";
761 #else
762 exe_path = KWSYS_SHARED_FORWARD_EXE_INSTALL;
763 #endif
765 #if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
766 /* Use the original self path directory. */
767 strcpy(self_path_logical, self_path);
768 #endif
771 /* Construct the runtime search path. */
773 const char** dir;
774 for(dir = search_path; *dir; ++dir)
776 /* Add seperator between path components. */
777 if(dir != search_path)
779 strcat(ldpath, kwsys_shared_forward_path_sep);
782 /* Add this path component. */
783 if(!kwsys_shared_forward_fullpath(self_path_logical, *dir,
784 ldpath+strlen(ldpath),
785 "runtime path entry"))
787 return 0;
792 /* Construct the executable location. */
793 if(!kwsys_shared_forward_fullpath(self_path_logical, exe_path, exe,
794 "executable file"))
796 return 0;
798 return 1;
801 /*--------------------------------------------------------------------------*/
802 /* Function to print why execution of a command line failed. */
803 static void kwsys_shared_forward_print_failure(char** argv)
805 char msg[KWSYS_SHARED_FORWARD_MAXPATH];
806 char** arg = argv;
807 kwsys_shared_forward_strerror(msg);
808 fprintf(stderr, "Error running");
809 for(; *arg; ++arg)
811 fprintf(stderr, " \"%s\"", *arg);
813 fprintf(stderr, ": %s\n", msg);
816 /* Static storage space to store the updated environment variable. */
817 static char kwsys_shared_forward_ldpath[KWSYS_SHARED_FORWARD_MAXPATH*16] = KWSYS_SHARED_FORWARD_LDPATH "=";
819 /*--------------------------------------------------------------------------*/
820 /* Main driver function to be called from main. */
821 static int @KWSYS_NAMESPACE@_shared_forward_to_real(int argc, char** argv)
823 /* Get the directory containing this executable. */
824 char self_path[KWSYS_SHARED_FORWARD_MAXPATH];
825 if(kwsys_shared_forward_self_path(argv[0], self_path))
827 /* Found this executable. Use it to get the library directory. */
828 char exe[KWSYS_SHARED_FORWARD_MAXPATH];
829 if(kwsys_shared_forward_get_settings(self_path,
830 kwsys_shared_forward_ldpath, exe))
832 /* Append the old runtime search path. */
833 const char* old_ldpath = getenv(KWSYS_SHARED_FORWARD_LDPATH);
834 if(old_ldpath)
836 strcat(kwsys_shared_forward_ldpath, kwsys_shared_forward_path_sep);
837 strcat(kwsys_shared_forward_ldpath, old_ldpath);
840 /* Store the environment variable. */
841 putenv(kwsys_shared_forward_ldpath);
843 #if defined(KWSYS_SHARED_FORWARD_OPTION_COMMAND)
844 /* Look for the command line replacement option. */
845 if(argc > 1 && strcmp(argv[1], KWSYS_SHARED_FORWARD_OPTION_COMMAND) == 0)
847 if(argc > 2)
849 /* Use the command line given. */
850 strcpy(exe, argv[2]);
851 argv += 2;
852 argc -= 2;
854 else
856 /* The option was not given an executable. */
857 fprintf(stderr, "Option " KWSYS_SHARED_FORWARD_OPTION_COMMAND
858 " must be followed by a command line.\n");
859 return 1;
862 #endif
864 #if defined(KWSYS_SHARED_FORWARD_OPTION_PRINT)
865 /* Look for the print command line option. */
866 if(argc > 1 && strcmp(argv[1], KWSYS_SHARED_FORWARD_OPTION_PRINT) == 0)
868 fprintf(stdout, "%s\n", kwsys_shared_forward_ldpath);
869 fprintf(stdout, "%s\n", exe);
870 return 0;
872 #endif
874 #if defined(KWSYS_SHARED_FORWARD_OPTION_LDD)
875 /* Look for the ldd command line option. */
876 if(argc > 1 && strcmp(argv[1], KWSYS_SHARED_FORWARD_OPTION_LDD) == 0)
878 # if defined(KWSYS_SHARED_FORWARD_LDD)
879 /* Use the named ldd-like executable and arguments. */
880 char* ldd_argv[] = {KWSYS_SHARED_FORWARD_LDD, 0, 0};
881 ldd_argv[KWSYS_SHARED_FORWARD_LDD_N] = exe;
882 kwsys_shared_forward_execvp(ldd_argv[0], ldd_argv);
884 /* Report why execution failed. */
885 kwsys_shared_forward_print_failure(ldd_argv);
886 return 1;
887 # else
888 /* We have no ldd-like executable available on this platform. */
889 fprintf(stderr, "No ldd-like tool is known to this executable.\n");
890 return 1;
891 # endif
893 #endif
895 /* Replace this process with the real executable. */
896 argv[0] = exe;
897 kwsys_shared_forward_execvp(argv[0], argv);
899 /* Report why execution failed. */
900 kwsys_shared_forward_print_failure(argv);
902 else
904 /* Could not convert self path to the library directory. */
907 else
909 /* Could not find this executable. */
910 fprintf(stderr, "Error locating executable \"%s\".\n", argv[0]);
913 /* Avoid unused argument warning. */
914 (void)argc;
916 /* Exit with failure. */
917 return 1;
920 #else
921 # error "@KWSYS_NAMESPACE@/SharedForward.h should be included only once."
922 #endif