diff options
Diffstat (limited to 'Source/kwsys')
-rw-r--r-- | Source/kwsys/SharedForward.h.in | 209 |
1 files changed, 178 insertions, 31 deletions
diff --git a/Source/kwsys/SharedForward.h.in b/Source/kwsys/SharedForward.h.in index 99592b6..e5e4a9f 100644 --- a/Source/kwsys/SharedForward.h.in +++ b/Source/kwsys/SharedForward.h.in @@ -38,11 +38,6 @@ paths relative to the forwarding executable location or as full paths. Include no trailing slash. */ -/* This is not useful on Windows. */ -#if defined(_WIN32) -# error "@KWSYS_NAMESPACE@/SharedForward.h is useless on Windows." -#endif - /* Full path to the directory in which this executable is built. Do not include a trailing slash. */ #if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD) @@ -108,16 +103,30 @@ #include <limits.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> #include <errno.h> #include <stdio.h> +#if defined(_WIN32) && !defined(__CYGWIN__) +# include <io.h> +# include <windows.h> +# include <process.h> +#else +# include <unistd.h> +#endif + /*--------------------------------------------------------------------------*/ /* Configuration for this platform. */ /* The path separator for this platform. */ -#define KWSYS_SHARED_FORWARD_PATH_SEP ':' +#if defined(_WIN32) && !defined(__CYGWIN__) +# define KWSYS_SHARED_FORWARD_PATH_SEP ';' +# define KWSYS_SHARED_FORWARD_PATH_SLASH '\\' +#else +# define KWSYS_SHARED_FORWARD_PATH_SEP ':' +# define KWSYS_SHARED_FORWARD_PATH_SLASH '/' +#endif static const char kwsys_shared_forward_path_sep[2] = {KWSYS_SHARED_FORWARD_PATH_SEP, 0}; +static const char kwsys_shared_forward_path_slash[2] = {KWSYS_SHARED_FORWARD_PATH_SLASH, 0}; /* The maximum length of a file name. */ #if defined(PATH_MAX) @@ -196,6 +205,12 @@ static const char kwsys_shared_forward_path_sep[2] = {KWSYS_SHARED_FORWARD_PATH_ # endif #endif +/* Windows */ +#if defined(_WIN32) +# undef KWSYS_SHARED_FORWARD_OPTION_LDD +# define KWSYS_SHARED_FORWARD_LDPATH "PATH" +#endif + /* Guess on this unknown system. */ #if !defined(KWSYS_SHARED_FORWARD_LDPATH) # define KWSYS_SHARED_FORWARD_LDD "ldd" @@ -204,6 +219,66 @@ static const char kwsys_shared_forward_path_sep[2] = {KWSYS_SHARED_FORWARD_PATH_ #endif /*--------------------------------------------------------------------------*/ +/* Function to convert a logical or relative path to a physical full path. */ +static int kwsys_shared_forward_realpath(const char* in_path, char* out_path) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Implementation for Windows. */ + DWORD n = GetFullPathName(in_path, KWSYS_SHARED_FORWARD_MAXPATH, + out_path, 0); + return n > 0 && n <= KWSYS_SHARED_FORWARD_MAXPATH; +#else + /* Implementation for UNIX. */ + return realpath(in_path, out_path) != 0; +#endif +} + +/*--------------------------------------------------------------------------*/ +/* Function to report a system error message. */ +static void kwsys_shared_forward_strerror(char* message) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Implementation for Windows. */ + DWORD original = GetLastError(); + DWORD length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, 0, original, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + message, KWSYS_SHARED_FORWARD_MAXPATH, 0); + if(length < 1 || length > KWSYS_SHARED_FORWARD_MAXPATH) + { + /* FormatMessage failed. Use a default message. */ + _snprintf(message, KWSYS_SHARED_FORWARD_MAXPATH, + "Error 0x%X (FormatMessage failed with error 0x%X)", + original, GetLastError()); + } +#else + /* Implementation for UNIX. */ + strcpy(message, strerror(errno)); +#endif +} + +/*--------------------------------------------------------------------------*/ +/* Functions to execute a child process. */ +static void kwsys_shared_forward_execv(const char* cmd, + char* const argv[]) +{ +#if defined(_MSC_VER) + _execv(cmd, argv); +#else + execv(cmd, argv); +#endif +} +static void kwsys_shared_forward_execvp(const char* cmd, + char* const argv[]) +{ +#if defined(_MSC_VER) + _execvp(cmd, argv); +#else + execvp(cmd, argv); +#endif +} + +/*--------------------------------------------------------------------------*/ /* Function to get the directory containing the given file or directory. */ static void kwsys_shared_forward_dirname(const char* begin, char* result) { @@ -212,7 +287,7 @@ static void kwsys_shared_forward_dirname(const char* begin, char* result) const char* end = begin + strlen(begin); for(;begin <= end && last_slash_index < 0; --end) { - if(*end == '/') + if(*end == '/' || *end == '\\') { last_slash_index = end-begin; } @@ -224,11 +299,21 @@ static void kwsys_shared_forward_dirname(const char* begin, char* result) /* No slashes. */ strcpy(result, "."); } - else if(last_slash_index == 0) + else if(last_slash_index == 0 || + (end-begin > 2 && begin[1] == ':' && + last_slash_index == 2)) { /* Only one leading slash. */ - strcpy(result, "/"); + strcpy(result, kwsys_shared_forward_path_slash); } +#if defined(_WIN32) + else if(last_slash_index == 2 && begin[1] == ':') + { + /* Only one leading drive letter and slash. */ + strncpy(result, begin, last_slash_index); + result[last_slash_index] = 0; + } +#endif else { /* A non-leading slash. */ @@ -238,6 +323,30 @@ static void kwsys_shared_forward_dirname(const char* begin, char* result) } /*--------------------------------------------------------------------------*/ +/* Function to check if a file exists and is executable. */ +static int kwsys_shared_forward_is_executable(const char* f) +{ +#if defined(_MSC_VER) +# define KWSYS_SHARED_FORWARD_ACCESS _access +#else +# define KWSYS_SHARED_FORWARD_ACCESS access +#endif +#if defined(X_OK) +# define KWSYS_SHARED_FORWARD_ACCESS_OK X_OK +#else +# define KWSYS_SHARED_FORWARD_ACCESS_OK 04 +#endif + if(KWSYS_SHARED_FORWARD_ACCESS(f, KWSYS_SHARED_FORWARD_ACCESS_OK) == 0) + { + return 1; + } + else + { + return 0; + } +} + +/*--------------------------------------------------------------------------*/ /* Function to locate the executable currently running. */ static int kwsys_shared_forward_self_path(const char* argv0, char* result) { @@ -246,7 +355,7 @@ static int kwsys_shared_forward_self_path(const char* argv0, char* result) const char* p = argv0; for(;*p && !has_slash; ++p) { - if(*p == '/') + if(*p == '/' || *p == '\\') { has_slash = 1; } @@ -281,18 +390,18 @@ static int kwsys_shared_forward_self_path(const char* argv0, char* result) { /* Determine the length without trailing slash. */ int length = last-first; - if(*(last-1) == '/') + if(*(last-1) == '/' || *(last-1) == '\\') { --length; } /* Construct the name of the executable in this location. */ strncpy(result, first, length); - result[length] = '/'; + result[length] = KWSYS_SHARED_FORWARD_PATH_SLASH; strcpy(result+(length)+1, argv0); - /* Check if it exists. */ - if(access(result, X_OK) == 0) + /* Check if it exists and is executable. */ + if(kwsys_shared_forward_is_executable(result)) { /* Found it. */ result[length] = 0; @@ -323,19 +432,28 @@ static int kwsys_shared_forward_fullpath(const char* self_path, /* Already a full path. */ strcpy(result, in_path); } +#if defined(_WIN32) + else if(in_path[0] && in_path[1] == ':') + { + /* Already a full path. */ + strcpy(result, in_path); + } +#endif else { /* Relative to self path. */ char temp_path[KWSYS_SHARED_FORWARD_MAXPATH]; strcpy(temp_path, self_path); - strcat(temp_path, "/"); + strcat(temp_path, kwsys_shared_forward_path_slash); strcat(temp_path, in_path); - if(!realpath(temp_path, result)) + if(!kwsys_shared_forward_realpath(temp_path, result)) { if(desc) { + char msgbuf[KWSYS_SHARED_FORWARD_MAXPATH]; + kwsys_shared_forward_strerror(msgbuf); fprintf(stderr, "Error converting %s \"%s\" to real path: %s\n", - desc, temp_path, strerror(errno)); + desc, temp_path, msgbuf); } return 0; } @@ -358,28 +476,55 @@ static int kwsys_shared_forward_get_settings(const char* self_path, const char* exe_path; /* Get the real name of the build and self paths. */ - char build_path[KWSYS_SHARED_FORWARD_MAXPATH]; +#if defined(CMAKE_INTDIR) + char build_path[] = KWSYS_SHARED_FORWARD_DIR_BUILD "/" CMAKE_INTDIR; + char self_path_logical[KWSYS_SHARED_FORWARD_MAXPATH]; +#else + char build_path[] = KWSYS_SHARED_FORWARD_DIR_BUILD; + const char* self_path_logical = self_path; +#endif + char build_path_real[KWSYS_SHARED_FORWARD_MAXPATH]; char self_path_real[KWSYS_SHARED_FORWARD_MAXPATH]; - if(!realpath(self_path, self_path_real)) + if(!kwsys_shared_forward_realpath(self_path, self_path_real)) { + char msgbuf[KWSYS_SHARED_FORWARD_MAXPATH]; + kwsys_shared_forward_strerror(msgbuf); fprintf(stderr, "Error converting self path \"%s\" to real path: %s\n", - self_path, strerror(errno)); + self_path, msgbuf); return 0; } /* Check whether we are running in the build tree or an install tree. */ - if(realpath(KWSYS_SHARED_FORWARD_DIR_BUILD, build_path) && - strcmp(self_path_real, build_path) == 0) + if(kwsys_shared_forward_realpath(build_path, build_path_real) && + strcmp(self_path_real, build_path_real) == 0) { /* Running in build tree. Use the build path and exe. */ search_path = search_path_build; +#if defined(_WIN32) + exe_path = KWSYS_SHARED_FORWARD_EXE_BUILD ".exe"; +#else exe_path = KWSYS_SHARED_FORWARD_EXE_BUILD; +#endif + +#if defined(CMAKE_INTDIR) + /* Remove the configuration directory from self_path. */ + kwsys_shared_forward_dirname(self_path, self_path_logical); +#endif } else { /* Running in install tree. Use the install path and exe. */ search_path = search_path_install; +#if defined(_WIN32) + exe_path = KWSYS_SHARED_FORWARD_EXE_INSTALL ".exe"; +#else exe_path = KWSYS_SHARED_FORWARD_EXE_INSTALL; +#endif + +#if defined(CMAKE_INTDIR) + /* Use the original self path directory. */ + strcpy(self_path_logical, self_path); +#endif } /* Construct the runtime search path. */ @@ -394,7 +539,7 @@ static int kwsys_shared_forward_get_settings(const char* self_path, } /* Add this path component. */ - if(!kwsys_shared_forward_fullpath(self_path, *dir, + if(!kwsys_shared_forward_fullpath(self_path_logical, *dir, ldpath+strlen(ldpath), "runtime path entry")) { @@ -404,7 +549,7 @@ static int kwsys_shared_forward_get_settings(const char* self_path, } /* Construct the executable location. */ - if(!kwsys_shared_forward_fullpath(self_path, exe_path, exe, + if(!kwsys_shared_forward_fullpath(self_path_logical, exe_path, exe, "executable file")) { return 0; @@ -414,9 +559,11 @@ static int kwsys_shared_forward_get_settings(const char* self_path, /*--------------------------------------------------------------------------*/ /* Function to print why execution of a command line failed. */ -static void kwsys_shared_forward_print_failure(char** argv, const char* msg) +static void kwsys_shared_forward_print_failure(char** argv) { + char msg[KWSYS_SHARED_FORWARD_MAXPATH]; char** arg = argv; + kwsys_shared_forward_strerror(msg); fprintf(stderr, "Error running"); for(; *arg; ++arg) { @@ -468,20 +615,20 @@ static int @KWSYS_NAMESPACE@_shared_forward_to_real(int argc, char** argv) { char* ldd_argv[] = {KWSYS_SHARED_FORWARD_LDD, 0, 0}; ldd_argv[KWSYS_SHARED_FORWARD_LDD_N] = exe; - execvp(ldd_argv[0], ldd_argv); + kwsys_shared_forward_execvp(ldd_argv[0], ldd_argv); /* Report why execution failed. */ - kwsys_shared_forward_print_failure(ldd_argv, strerror(errno)); + kwsys_shared_forward_print_failure(ldd_argv); return 1; } #endif /* Replace this process with the real executable. */ argv[0] = exe; - execv(argv[0], argv); + kwsys_shared_forward_execv(argv[0], argv); /* Report why execution failed. */ - kwsys_shared_forward_print_failure(argv, strerror(errno)); + kwsys_shared_forward_print_failure(argv); } else { @@ -491,7 +638,7 @@ static int @KWSYS_NAMESPACE@_shared_forward_to_real(int argc, char** argv) else { /* Could not find this executable. */ - fprintf(stderr, "Error locating executable \"%s\".", argv[0]); + fprintf(stderr, "Error locating executable \"%s\".\n", argv[0]); } /* Avoid unused argument warning. */ |