ENH: Added support for Windows.

This commit is contained in:
Brad King 2005-08-18 09:23:15 -04:00
parent 861719c054
commit 207c39a7ad

View File

@ -38,11 +38,6 @@
paths relative to the forwarding executable location or as full paths relative to the forwarding executable location or as full
paths. Include no trailing slash. */ 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 /* Full path to the directory in which this executable is built. Do
not include a trailing slash. */ not include a trailing slash. */
#if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD) #if !defined(@KWSYS_NAMESPACE@_SHARED_FORWARD_DIR_BUILD)
@ -108,16 +103,30 @@
#include <limits.h> #include <limits.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <errno.h> #include <errno.h>
#include <stdio.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. */ /* Configuration for this platform. */
/* The path separator 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_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. */ /* The maximum length of a file name. */
#if defined(PATH_MAX) #if defined(PATH_MAX)
@ -196,6 +205,12 @@ static const char kwsys_shared_forward_path_sep[2] = {KWSYS_SHARED_FORWARD_PATH_
# endif # endif
#endif #endif
/* Windows */
#if defined(_WIN32)
# undef KWSYS_SHARED_FORWARD_OPTION_LDD
# define KWSYS_SHARED_FORWARD_LDPATH "PATH"
#endif
/* Guess on this unknown system. */ /* Guess on this unknown system. */
#if !defined(KWSYS_SHARED_FORWARD_LDPATH) #if !defined(KWSYS_SHARED_FORWARD_LDPATH)
# define KWSYS_SHARED_FORWARD_LDD "ldd" # define KWSYS_SHARED_FORWARD_LDD "ldd"
@ -203,6 +218,66 @@ static const char kwsys_shared_forward_path_sep[2] = {KWSYS_SHARED_FORWARD_PATH_
# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH" # define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
#endif #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. */ /* Function to get the directory containing the given file or directory. */
static void kwsys_shared_forward_dirname(const char* begin, char* result) 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); const char* end = begin + strlen(begin);
for(;begin <= end && last_slash_index < 0; --end) for(;begin <= end && last_slash_index < 0; --end)
{ {
if(*end == '/') if(*end == '/' || *end == '\\')
{ {
last_slash_index = end-begin; last_slash_index = end-begin;
} }
@ -224,11 +299,21 @@ static void kwsys_shared_forward_dirname(const char* begin, char* result)
/* No slashes. */ /* No slashes. */
strcpy(result, "."); 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. */ /* 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 else
{ {
/* A non-leading slash. */ /* A non-leading slash. */
@ -237,6 +322,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. */ /* Function to locate the executable currently running. */
static int kwsys_shared_forward_self_path(const char* argv0, char* result) 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; const char* p = argv0;
for(;*p && !has_slash; ++p) for(;*p && !has_slash; ++p)
{ {
if(*p == '/') if(*p == '/' || *p == '\\')
{ {
has_slash = 1; 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. */ /* Determine the length without trailing slash. */
int length = last-first; int length = last-first;
if(*(last-1) == '/') if(*(last-1) == '/' || *(last-1) == '\\')
{ {
--length; --length;
} }
/* Construct the name of the executable in this location. */ /* Construct the name of the executable in this location. */
strncpy(result, first, length); strncpy(result, first, length);
result[length] = '/'; result[length] = KWSYS_SHARED_FORWARD_PATH_SLASH;
strcpy(result+(length)+1, argv0); strcpy(result+(length)+1, argv0);
/* Check if it exists. */ /* Check if it exists and is executable. */
if(access(result, X_OK) == 0) if(kwsys_shared_forward_is_executable(result))
{ {
/* Found it. */ /* Found it. */
result[length] = 0; result[length] = 0;
@ -323,19 +432,28 @@ static int kwsys_shared_forward_fullpath(const char* self_path,
/* Already a full path. */ /* Already a full path. */
strcpy(result, in_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 else
{ {
/* Relative to self path. */ /* Relative to self path. */
char temp_path[KWSYS_SHARED_FORWARD_MAXPATH]; char temp_path[KWSYS_SHARED_FORWARD_MAXPATH];
strcpy(temp_path, self_path); strcpy(temp_path, self_path);
strcat(temp_path, "/"); strcat(temp_path, kwsys_shared_forward_path_slash);
strcat(temp_path, in_path); strcat(temp_path, in_path);
if(!realpath(temp_path, result)) if(!kwsys_shared_forward_realpath(temp_path, result))
{ {
if(desc) if(desc)
{ {
char msgbuf[KWSYS_SHARED_FORWARD_MAXPATH];
kwsys_shared_forward_strerror(msgbuf);
fprintf(stderr, "Error converting %s \"%s\" to real path: %s\n", fprintf(stderr, "Error converting %s \"%s\" to real path: %s\n",
desc, temp_path, strerror(errno)); desc, temp_path, msgbuf);
} }
return 0; return 0;
} }
@ -358,28 +476,55 @@ static int kwsys_shared_forward_get_settings(const char* self_path,
const char* exe_path; const char* exe_path;
/* Get the real name of the build and self paths. */ /* 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]; 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", fprintf(stderr, "Error converting self path \"%s\" to real path: %s\n",
self_path, strerror(errno)); self_path, msgbuf);
return 0; return 0;
} }
/* Check whether we are running in the build tree or an install tree. */ /* Check whether we are running in the build tree or an install tree. */
if(realpath(KWSYS_SHARED_FORWARD_DIR_BUILD, build_path) && if(kwsys_shared_forward_realpath(build_path, build_path_real) &&
strcmp(self_path_real, build_path) == 0) strcmp(self_path_real, build_path_real) == 0)
{ {
/* Running in build tree. Use the build path and exe. */ /* Running in build tree. Use the build path and exe. */
search_path = search_path_build; search_path = search_path_build;
#if defined(_WIN32)
exe_path = KWSYS_SHARED_FORWARD_EXE_BUILD ".exe";
#else
exe_path = KWSYS_SHARED_FORWARD_EXE_BUILD; 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 else
{ {
/* Running in install tree. Use the install path and exe. */ /* Running in install tree. Use the install path and exe. */
search_path = search_path_install; search_path = search_path_install;
#if defined(_WIN32)
exe_path = KWSYS_SHARED_FORWARD_EXE_INSTALL ".exe";
#else
exe_path = KWSYS_SHARED_FORWARD_EXE_INSTALL; 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. */ /* Construct the runtime search path. */
@ -394,7 +539,7 @@ static int kwsys_shared_forward_get_settings(const char* self_path,
} }
/* Add this path component. */ /* Add this path component. */
if(!kwsys_shared_forward_fullpath(self_path, *dir, if(!kwsys_shared_forward_fullpath(self_path_logical, *dir,
ldpath+strlen(ldpath), ldpath+strlen(ldpath),
"runtime path entry")) "runtime path entry"))
{ {
@ -404,7 +549,7 @@ static int kwsys_shared_forward_get_settings(const char* self_path,
} }
/* Construct the executable location. */ /* 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")) "executable file"))
{ {
return 0; 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. */ /* 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; char** arg = argv;
kwsys_shared_forward_strerror(msg);
fprintf(stderr, "Error running"); fprintf(stderr, "Error running");
for(; *arg; ++arg) 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}; char* ldd_argv[] = {KWSYS_SHARED_FORWARD_LDD, 0, 0};
ldd_argv[KWSYS_SHARED_FORWARD_LDD_N] = exe; 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. */ /* Report why execution failed. */
kwsys_shared_forward_print_failure(ldd_argv, strerror(errno)); kwsys_shared_forward_print_failure(ldd_argv);
return 1; return 1;
} }
#endif #endif
/* Replace this process with the real executable. */ /* Replace this process with the real executable. */
argv[0] = exe; argv[0] = exe;
execv(argv[0], argv); kwsys_shared_forward_execv(argv[0], argv);
/* Report why execution failed. */ /* Report why execution failed. */
kwsys_shared_forward_print_failure(argv, strerror(errno)); kwsys_shared_forward_print_failure(argv);
} }
else else
{ {
@ -491,7 +638,7 @@ static int @KWSYS_NAMESPACE@_shared_forward_to_real(int argc, char** argv)
else else
{ {
/* Could not find this executable. */ /* 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. */ /* Avoid unused argument warning. */