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
24 #if defined(CMAKE_INTDIR)
25 # define CONFIG_DIR_PRE CMAKE_INTDIR "/"
26 # define CONFIG_DIR_POST "/" CMAKE_INTDIR
28 # define CONFIG_DIR_PRE ""
29 # define CONFIG_DIR_POST ""
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
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"
77 #if !defined(KWSYS_SHARED_FORWARD_DIR_BUILD)
78 # define KWSYS_SHARED_FORWARD_DIR_BUILD @KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD
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"
85 #if !defined(KWSYS_SHARED_FORWARD_PATH_BUILD)
86 # define KWSYS_SHARED_FORWARD_PATH_BUILD @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_BUILD
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"
93 #if !defined(KWSYS_SHARED_FORWARD_PATH_INSTALL)
94 # define KWSYS_SHARED_FORWARD_PATH_INSTALL @KWSYS_NAMESPACE@_SHARED_FORWARD_PATH_INSTALL
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"
101 #if !defined(KWSYS_SHARED_FORWARD_EXE_BUILD)
102 # define KWSYS_SHARED_FORWARD_EXE_BUILD @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_BUILD
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"
109 #if !defined(KWSYS_SHARED_FORWARD_EXE_INSTALL)
110 # define KWSYS_SHARED_FORWARD_EXE_INSTALL @KWSYS_NAMESPACE@_SHARED_FORWARD_EXE_INSTALL
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
117 # undef KWSYS_SHARED_FORWARD_CONFIG_NAME
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
126 # undef KWSYS_SHARED_FORWARD_OPTION_COMMAND
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
135 # undef KWSYS_SHARED_FORWARD_OPTION_PRINT
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
144 # undef KWSYS_SHARED_FORWARD_OPTION_LDD
147 /*--------------------------------------------------------------------------*/
148 /* Include needed system headers. */
156 #if defined(_WIN32) && !defined(__CYGWIN__)
158 # include <windows.h>
159 # include <process.h>
160 # define KWSYS_SHARED_FORWARD_ESCAPE_ARGV /* re-escape argv for execvp */
163 # include <sys/stat.h>
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 '\\'
174 # define KWSYS_SHARED_FORWARD_PATH_SEP ':'
175 # define KWSYS_SHARED_FORWARD_PATH_SLASH '/'
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
186 # define KWSYS_SHARED_FORWARD_MAXPATH 16384
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. */
195 # define KWSYS_SHARED_FORWARD_LDD "ldd"
196 # define KWSYS_SHARED_FORWARD_LDD_N 1
197 # define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
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"
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"
216 # define KWSYS_SHARED_FORWARD_LDD "dump", "-H"
217 # define KWSYS_SHARED_FORWARD_LDD_N 2
218 # define KWSYS_SHARED_FORWARD_LDPATH "LIBPATH"
223 # define KWSYS_SHARED_FORWARD_LDD "ldd"
224 # define KWSYS_SHARED_FORWARD_LDD_N 1
225 # include <sys/isa_defs.h>
227 # define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
228 # elif defined(_LP64)
229 # define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH_64"
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"
240 # define KWSYS_SHARED_FORWARD_LDPATH "SHLIB_PATH"
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"
259 # if defined(__CYGWIN__)
260 # define KWSYS_SHARED_FORWARD_LDD "cygcheck"
261 # define KWSYS_SHARED_FORWARD_LDD_N 1
263 # define KWSYS_SHARED_FORWARD_LDPATH "PATH"
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"
273 #ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
274 /*--------------------------------------------------------------------------*/
275 typedef struct kwsys_sf_arg_info_s
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. */
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. */
297 info
.size
= (int)strlen(in
) + 1;
300 /* Scan the string for characters that require escaping or quoting. */
303 /* Check whether this character needs quotes. */
304 if(strchr(" \t?'#&<>|^", *c
))
309 /* On Windows only backslashes and double-quotes need escaping. */
312 /* Found a backslash. It may need to be escaped later. */
313 ++windows_backslashes
;
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;
324 /* Found another character. This eliminates the possibility
325 that any immediately preceding backslashes will be
327 windows_backslashes
= 0;
331 /* Check whether the argument needs surrounding quotes. */
334 /* Surrounding quotes are needed. Allocate space for them. */
337 /* We must escape all ending backslashes when quoting on windows. */
338 info
.size
+= windows_backslashes
;
344 /*--------------------------------------------------------------------------*/
345 static char* kwsys_sf_get_arg(kwsys_sf_arg_info info
, char* out
)
347 /* String iterator. */
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. */
356 /* Add the opening quote for this argument. */
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. */
366 /* Found a backslash. It may need to be escaped later. */
367 ++windows_backslashes
;
371 /* Found a double-quote. Escape all immediately preceding
373 while(windows_backslashes
> 0)
375 --windows_backslashes
;
379 /* Add the backslash to escape the double-quote. */
384 /* We encountered a normal character. This eliminates any
385 escaping needed for preceding backslashes. */
386 windows_backslashes
= 0;
389 /* Store this character. */
395 /* Add enough backslashes to escape any trailing ones. */
396 while(windows_backslashes
> 0)
398 --windows_backslashes
;
402 /* Add the closing quote for this argument. */
406 /* Store a terminating null without incrementing. */
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
,
421 return n
> 0 && n
<= KWSYS_SHARED_FORWARD_MAXPATH
;
423 /* Implementation for UNIX. */
424 return realpath(in_path
, out_path
) != 0;
428 /*--------------------------------------------------------------------------*/
429 static int kwsys_shared_forward_samepath(const char* file1
, const char* file2
)
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
);
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
);
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());
478 /* Implementation for UNIX. */
479 strcpy(message
, strerror(errno
));
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. */
492 for(argvc
= argv
; *argvc
; ++argvc
,++argc
) {}
495 /* Create the escaped arguments. */
497 char** nargv
= (char**)malloc((argc
+1) * sizeof(char*));
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
]);
507 /* Replace the command line to be used. */
512 /* Invoke the child process. */
513 #if defined(_MSC_VER)
515 #elif defined(__MINGW32__)
516 /* Avoid incompatible pointer warning with a cast. */
517 execvp(cmd
, (char const* const*)argv
);
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)
544 else if(last_slash_index
== 0)
546 /* Only one leading slash. */
547 strcpy(result
, kwsys_shared_forward_path_slash
);
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;
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
573 # define KWSYS_SHARED_FORWARD_ACCESS access
576 # define KWSYS_SHARED_FORWARD_ACCESS_OK X_OK
578 # define KWSYS_SHARED_FORWARD_ACCESS_OK 04
580 if(KWSYS_SHARED_FORWARD_ACCESS(f
, KWSYS_SHARED_FORWARD_ACCESS_OK
) == 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. */
596 const char* p
= argv0
;
597 for(;*p
&& !has_slash
; ++p
)
599 if(*p
== '/' || *p
== '\\')
607 /* There is a slash. Use the dirname of the given location. */
608 kwsys_shared_forward_dirname(argv0
, result
);
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
;
620 /* Store the end of this path entry. */
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. */
632 /* Determine the length without trailing slash. */
633 int length
= (int)(last
-first
);
634 if(*(last
-1) == '/' || *(last
-1) == '\\')
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
))
653 /* Move to the next directory in the path. */
658 /* We could not find the executable. */
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
,
670 /* Check the specified path type. */
671 if(in_path
[0] == '/')
673 /* Already a full path. */
674 strcpy(result
, in_path
);
677 else if(in_path
[0] && in_path
[1] == ':')
679 /* Already a full path. */
680 strcpy(result
, in_path
);
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
))
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
);
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};
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
];
724 char build_path
[] = KWSYS_SHARED_FORWARD_DIR_BUILD
;
725 const char* self_path_logical
= self_path
;
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",
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
;
745 exe_path
= KWSYS_SHARED_FORWARD_EXE_BUILD
".exe";
747 exe_path
= KWSYS_SHARED_FORWARD_EXE_BUILD
;
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
);
757 /* Running in install tree. Use the install path and exe. */
758 search_path
= search_path_install
;
760 exe_path
= KWSYS_SHARED_FORWARD_EXE_INSTALL
".exe";
762 exe_path
= KWSYS_SHARED_FORWARD_EXE_INSTALL
;
765 #if defined(KWSYS_SHARED_FORWARD_CONFIG_NAME)
766 /* Use the original self path directory. */
767 strcpy(self_path_logical
, self_path
);
771 /* Construct the runtime search path. */
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"))
792 /* Construct the executable location. */
793 if(!kwsys_shared_forward_fullpath(self_path_logical
, exe_path
, exe
,
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
];
807 kwsys_shared_forward_strerror(msg
);
808 fprintf(stderr
, "Error running");
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
);
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)
849 /* Use the command line given. */
850 strcpy(exe
, argv
[2]);
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");
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
);
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
);
888 /* We have no ldd-like executable available on this platform. */
889 fprintf(stderr
, "No ldd-like tool is known to this executable.\n");
895 /* Replace this process with the real executable. */
897 kwsys_shared_forward_execvp(argv
[0], argv
);
899 /* Report why execution failed. */
900 kwsys_shared_forward_print_failure(argv
);
904 /* Could not convert self path to the library directory. */
909 /* Could not find this executable. */
910 fprintf(stderr
, "Error locating executable \"%s\".\n", argv
[0]);
913 /* Avoid unused argument warning. */
916 /* Exit with failure. */
921 # error "@KWSYS_NAMESPACE@/SharedForward.h should be included only once."