ENH: Added support for Windows.

This commit is contained in:
Brad King 2005-08-18 09:23:15 -04:00
parent 861719c054
commit 207c39a7ad
1 changed files with 178 additions and 31 deletions

View File

@ -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"
@ -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"
#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. */
@ -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. */
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. */