From 1b7c049ae18407e02a4dc099df5f499fe9557d1f Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 23 Feb 2017 08:45:22 -0500 Subject: Drop KWSys since we no longer use any components --- CMakeLists.txt | 6 - src/CMakeLists.txt | 1 - src/Options.h | 1 - src/Output.h | 2 - src/Utils.h | 1 - src/kwsys/.gitattributes | 16 - src/kwsys/CMakeLists.txt | 1292 --------------- src/kwsys/CONTRIBUTING.rst | 35 - src/kwsys/Configure.h.in | 131 -- src/kwsys/Copyright.txt | 31 - src/kwsys/Encoding.h.in | 79 - src/kwsys/EncodingC.c | 85 - src/kwsys/Process.h.in | 462 ------ src/kwsys/ProcessUNIX.c | 3058 ----------------------------------- src/kwsys/ProcessWin32.c | 3017 ---------------------------------- src/kwsys/README.txt | 12 - src/kwsys/System.c | 301 ---- src/kwsys/System.h.in | 69 - src/kwsys/kwsysPlatformTests.cmake | 219 --- src/kwsys/kwsysPlatformTestsC.c | 100 -- src/kwsys/kwsysPlatformTestsCXX.cxx | 699 -------- src/kwsys/kwsysPrivate.h | 41 - 22 files changed, 9658 deletions(-) delete mode 100644 src/kwsys/.gitattributes delete mode 100644 src/kwsys/CMakeLists.txt delete mode 100644 src/kwsys/CONTRIBUTING.rst delete mode 100644 src/kwsys/Configure.h.in delete mode 100644 src/kwsys/Copyright.txt delete mode 100644 src/kwsys/Encoding.h.in delete mode 100644 src/kwsys/EncodingC.c delete mode 100644 src/kwsys/Process.h.in delete mode 100644 src/kwsys/ProcessUNIX.c delete mode 100644 src/kwsys/ProcessWin32.c delete mode 100644 src/kwsys/README.txt delete mode 100644 src/kwsys/System.c delete mode 100644 src/kwsys/System.h.in delete mode 100644 src/kwsys/kwsysPlatformTests.cmake delete mode 100644 src/kwsys/kwsysPlatformTestsC.c delete mode 100644 src/kwsys/kwsysPlatformTestsCXX.cxx delete mode 100644 src/kwsys/kwsysPrivate.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ecf0c4b..4bf06b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,12 +55,6 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${std_cxx11}") endif() -set(KWSYS_NAMESPACE cxsys) -set(KWSYS_USE_Process 1) -set(KWSYS_HEADER_ROOT ${CastXML_BINARY_DIR}/src) -add_subdirectory(src/kwsys) -include_directories(${KWSYS_HEADER_ROOT}) - find_package(LLVM REQUIRED) if(DEFINED LLVM_BUILD_BINARY_DIR) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f3f80c4..b1acad3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -66,7 +66,6 @@ add_executable(castxml Utils.cxx Utils.h ) target_link_libraries(castxml - cxsys ${clang_libs} ${llvm_libs} ) diff --git a/src/Options.h b/src/Options.h index 0c7ffd9..d81c421 100644 --- a/src/Options.h +++ b/src/Options.h @@ -16,7 +16,6 @@ #ifndef CASTXML_OPTIONS_H #define CASTXML_OPTIONS_H -#include #include #include diff --git a/src/Output.h b/src/Output.h index db1982b..5c5ee11 100644 --- a/src/Output.h +++ b/src/Output.h @@ -16,8 +16,6 @@ #ifndef CASTXML_OUTPUT_H #define CASTXML_OUTPUT_H -#include - namespace llvm { class raw_ostream; } diff --git a/src/Utils.h b/src/Utils.h index a29e96f..e53c006 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -16,7 +16,6 @@ #ifndef CASTXML_UTILS_H #define CASTXML_UTILS_H -#include #include /// findResources - Call from main() to find resources diff --git a/src/kwsys/.gitattributes b/src/kwsys/.gitattributes deleted file mode 100644 index 248786e..0000000 --- a/src/kwsys/.gitattributes +++ /dev/null @@ -1,16 +0,0 @@ -.git* export-ignore -.gitattributes -export-ignore - -/GitSetup export-ignore -/SetupForDevelopment.sh export-ignore eol=lf - -/CONTRIBUTING.rst conflict-marker-size=78 - -*.c whitespace=tab-in-indent,no-lf-at-eof -*.h whitespace=tab-in-indent,no-lf-at-eof -*.h.in whitespace=tab-in-indent,no-lf-at-eof -*.cxx whitespace=tab-in-indent,no-lf-at-eof -*.hxx whitespace=tab-in-indent,no-lf-at-eof -*.hxx.in whitespace=tab-in-indent,no-lf-at-eof -*.txt whitespace=tab-in-indent,no-lf-at-eof -*.cmake whitespace=tab-in-indent,no-lf-at-eof diff --git a/src/kwsys/CMakeLists.txt b/src/kwsys/CMakeLists.txt deleted file mode 100644 index 9b26553..0000000 --- a/src/kwsys/CMakeLists.txt +++ /dev/null @@ -1,1292 +0,0 @@ -#============================================================================= -# KWSys - Kitware System Library -# Copyright 2000-2011 Kitware, Inc., Insight Software Consortium -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= - -# The Kitware System Library is intended to be included in other -# projects. It is completely configurable in that the library's -# namespace can be configured and the components that are included can -# be selected invididually. - -# Typical usage is to import the kwsys directory tree into a -# subdirectory under a parent project and enable the classes that will -# be used. All classes are disabled by default. The CMake listfile -# above this one configures the library as follows: -# -# SET(KWSYS_NAMESPACE foosys) -# SET(KWSYS_USE_Directory 1) # Enable Directory class. -# SUBDIRS(kwsys) -# -# Optional settings are as follows: -# -# KWSYS_HEADER_ROOT = The directory into which to generate the kwsys headers. -# A directory called "${KWSYS_NAMESPACE}" will be -# created under this root directory to hold the files. -# -# Example: -# -# SET(KWSYS_HEADER_ROOT ${PROJECT_BINARY_DIR}) -# INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR}) -# -# KWSYS_IOS_FORCE_OLD = Force use of old non-ANSI C++ streams even if -# new streams are available. This may be used -# by projects that cannot configure their -# streams library. -# Example: -# -# SET(KWSYS_IOS_FORCE_OLD 1) -# -# -# Optional settings to setup install rules are as follows: -# -# KWSYS_INSTALL_BIN_DIR = The installation target directories into -# KWSYS_INSTALL_LIB_DIR which the libraries and headers from -# KWSYS_INSTALL_INCLUDE_DIR kwsys should be installed by a "make install". -# The values should be specified relative to -# the installation prefix and NOT start with '/'. -# KWSYS_INSTALL_DOC_DIR = The installation target directory for documentation -# such as copyright information. -# -# KWSYS_INSTALL_COMPONENT_NAME_RUNTIME = Name of runtime and development -# KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT installation components. -# If not given the install rules -# will not be in any component. -# -# KWSYS_INSTALL_EXPORT_NAME = The EXPORT option value for install(TARGETS) calls. -# -# Example: -# -# SET(KWSYS_INSTALL_BIN_DIR bin) -# SET(KWSYS_INSTALL_LIB_DIR lib) -# SET(KWSYS_INSTALL_INCLUDE_DIR include) -# SET(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME Runtime) -# SET(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT Development) - -# Once configured, kwsys should be used as follows from C or C++ code: -# -# #include -# ... -# foosys::Directory directory; -# - -# NOTE: This library is intended for internal use by Kitware-driven -# projects. In order to keep it simple no attempt will be made to -# maintain backward compatibility when changes are made to KWSys. -# When an incompatible change is made Kitware's projects that use -# KWSys will be fixed, but no notification will necessarily be sent to -# any outside mailing list and no documentation of the change will be -# written. - -CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3 FATAL_ERROR) -IF(POLICY CMP0025) - CMAKE_POLICY(SET CMP0025 NEW) -ENDIF() -IF(POLICY CMP0056) - CMAKE_POLICY(SET CMP0056 NEW) -ENDIF() - -#----------------------------------------------------------------------------- -# If a namespace is not specified, use "kwsys" and enable testing. -# This should be the case only when kwsys is not included inside -# another project and is being tested. -IF(NOT KWSYS_NAMESPACE) - SET(KWSYS_NAMESPACE "kwsys") - SET(KWSYS_STANDALONE 1) -ENDIF() - -#----------------------------------------------------------------------------- -# The project name is that of the specified namespace. -PROJECT(${KWSYS_NAMESPACE}) - -# Tell CMake how to follow dependencies of sources in this directory. -SET_PROPERTY(DIRECTORY - PROPERTY IMPLICIT_DEPENDS_INCLUDE_TRANSFORM - "KWSYS_HEADER(%)=<${KWSYS_NAMESPACE}/%>" - ) - -# Select library components. -IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) - SET(KWSYS_ENABLE_C 1) - # Enable all components. - SET(KWSYS_USE_Base64 1) - SET(KWSYS_USE_Directory 1) - SET(KWSYS_USE_DynamicLoader 1) - SET(KWSYS_USE_Encoding 1) - SET(KWSYS_USE_Glob 1) - SET(KWSYS_USE_MD5 1) - SET(KWSYS_USE_Process 1) - SET(KWSYS_USE_RegularExpression 1) - SET(KWSYS_USE_System 1) - SET(KWSYS_USE_SystemTools 1) - SET(KWSYS_USE_CommandLineArguments 1) - SET(KWSYS_USE_FundamentalType 1) - SET(KWSYS_USE_Terminal 1) - SET(KWSYS_USE_IOStream 1) - SET(KWSYS_USE_FStream 1) - SET(KWSYS_USE_String 1) - SET(KWSYS_USE_SystemInformation 1) - SET(KWSYS_USE_CPU 1) -ENDIF() - -# Enforce component dependencies. -IF(KWSYS_USE_SystemTools) - SET(KWSYS_USE_Directory 1) - SET(KWSYS_USE_FStream 1) - SET(KWSYS_USE_Encoding 1) -ENDIF() -IF(KWSYS_USE_Glob) - SET(KWSYS_USE_Directory 1) - SET(KWSYS_USE_SystemTools 1) - SET(KWSYS_USE_RegularExpression 1) - SET(KWSYS_USE_FStream 1) - SET(KWSYS_USE_Encoding 1) -ENDIF() -IF(KWSYS_USE_Process) - SET(KWSYS_USE_System 1) - SET(KWSYS_USE_Encoding 1) -ENDIF() -IF(KWSYS_USE_SystemInformation) - SET(KWSYS_USE_Process 1) -ENDIF() -IF(KWSYS_USE_System) - SET(KWSYS_USE_Encoding 1) -ENDIF() -IF(KWSYS_USE_Directory) - SET(KWSYS_USE_Encoding 1) -ENDIF() -IF(KWSYS_USE_FStream) - SET(KWSYS_USE_Encoding 1) -ENDIF() - -# Setup the large file support default. -IF(KWSYS_LFS_DISABLE) - SET(KWSYS_LFS_REQUESTED 0) -ELSE() - SET(KWSYS_LFS_REQUESTED 1) -ENDIF() - -# Specify default 8 bit encoding for Windows -IF(NOT KWSYS_ENCODING_DEFAULT_CODEPAGE) - SET(KWSYS_ENCODING_DEFAULT_CODEPAGE CP_ACP) -ENDIF() - -# Enable testing if building standalone. -IF(KWSYS_STANDALONE) - INCLUDE(Dart) - MARK_AS_ADVANCED(BUILD_TESTING DART_ROOT TCL_TCLSH) - IF(BUILD_TESTING) - ENABLE_TESTING() - ENDIF() -ENDIF() - -# Include helper macros. -INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/kwsysPlatformTests.cmake) -INCLUDE(CheckTypeSize) - -# Do full dependency headers. -INCLUDE_REGULAR_EXPRESSION("^.*$") - -# Use new KWSYS_INSTALL_*_DIR variable names to control installation. -# Take defaults from the old names. Note that there was no old name -# for the bin dir, so we take the old lib dir name so DLLs will be -# installed in a compatible way for old code. -IF(NOT KWSYS_INSTALL_INCLUDE_DIR) - STRING(REGEX REPLACE "^/" "" KWSYS_INSTALL_INCLUDE_DIR - "${KWSYS_HEADER_INSTALL_DIR}") -ENDIF() -IF(NOT KWSYS_INSTALL_LIB_DIR) - STRING(REGEX REPLACE "^/" "" KWSYS_INSTALL_LIB_DIR - "${KWSYS_LIBRARY_INSTALL_DIR}") -ENDIF() -IF(NOT KWSYS_INSTALL_BIN_DIR) - STRING(REGEX REPLACE "^/" "" KWSYS_INSTALL_BIN_DIR - "${KWSYS_LIBRARY_INSTALL_DIR}") -ENDIF() - -# Setup header install rules. -SET(KWSYS_INSTALL_INCLUDE_OPTIONS) -IF(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT) - SET(KWSYS_INSTALL_INCLUDE_OPTIONS ${KWSYS_INSTALL_INCLUDE_OPTIONS} - COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT} - ) -ENDIF() - -# Setup library install rules. -SET(KWSYS_INSTALL_LIBRARY_RULE) -IF(KWSYS_INSTALL_LIB_DIR) - IF(KWSYS_INSTALL_EXPORT_NAME) - LIST(APPEND KWSYS_INSTALL_LIBRARY_RULE EXPORT ${KWSYS_INSTALL_EXPORT_NAME}) - ENDIF() - # Install the shared library to the lib directory. - SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} - LIBRARY DESTINATION ${KWSYS_INSTALL_LIB_DIR} - ) - # Assign the shared library to the runtime component. - IF(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME) - SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} - COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_RUNTIME} - ) - ENDIF() - - # Install the archive to the lib directory. - SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} - ARCHIVE DESTINATION ${KWSYS_INSTALL_LIB_DIR} - ) - # Assign the archive to the development component. - IF(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT) - SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} - COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT} - ) - ENDIF() -ENDIF() -IF(KWSYS_INSTALL_BIN_DIR) - # Install the runtime library to the bin directory. - SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} - RUNTIME DESTINATION ${KWSYS_INSTALL_BIN_DIR} - ) - # Assign the runtime library to the runtime component. - IF(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME) - SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE} - COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_RUNTIME} - ) - ENDIF() -ENDIF() - -# Do not support old KWSYS_*a_INSTALL_DIR variable names. -SET(KWSYS_HEADER_INSTALL_DIR) -SET(KWSYS_LIBRARY_INSTALL_DIR) - -# Generated source files will need this header. -STRING(COMPARE EQUAL "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}" - KWSYS_IN_SOURCE_BUILD) -IF(NOT KWSYS_IN_SOURCE_BUILD) - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsysPrivate.h - ${PROJECT_BINARY_DIR}/kwsysPrivate.h COPYONLY IMMEDIATE) -ENDIF() - -# Select plugin module file name convention. -IF(NOT KWSYS_DynamicLoader_PREFIX) - SET(KWSYS_DynamicLoader_PREFIX ${CMAKE_SHARED_MODULE_PREFIX}) -ENDIF() -IF(NOT KWSYS_DynamicLoader_SUFFIX) - SET(KWSYS_DynamicLoader_SUFFIX ${CMAKE_SHARED_MODULE_SUFFIX}) -ENDIF() - -#----------------------------------------------------------------------------- -# We require ANSI support from the C compiler. Add any needed flags. -IF(CMAKE_ANSI_CFLAGS) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_ANSI_CFLAGS}") -ENDIF() - -#----------------------------------------------------------------------------- -# Adjust compiler flags for some platforms. -IF(NOT CMAKE_COMPILER_IS_GNUCXX) - IF(CMAKE_SYSTEM MATCHES "OSF1-V.*") - STRING(REGEX MATCH "-timplicit_local" - KWSYS_CXX_FLAGS_HAVE_IMPLICIT_LOCAL "${CMAKE_CXX_FLAGS}") - STRING(REGEX MATCH "-no_implicit_include" - KWSYS_CXX_FLAGS_HAVE_NO_IMPLICIT_INCLUDE "${CMAKE_CXX_FLAGS}") - IF(NOT KWSYS_CXX_FLAGS_HAVE_IMPLICIT_LOCAL) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -timplicit_local") - ENDIF() - IF(NOT KWSYS_CXX_FLAGS_HAVE_NO_IMPLICIT_INCLUDE) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no_implicit_include") - ENDIF() - ENDIF() - IF(CMAKE_SYSTEM MATCHES "HP-UX") - SET(KWSYS_PLATFORM_CXX_TEST_EXTRA_FLAGS "+p") - IF(CMAKE_CXX_COMPILER_ID MATCHES "HP") - # it is known that version 3.85 fails and 6.25 works without these flags - IF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4) - # use new C++ library and improved template support - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -AA +hpxstd98") - ENDIF() - ENDIF() - ENDIF() -ENDIF() - -#----------------------------------------------------------------------------- -# Configure Large File Support. -KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_CSTDIO - "Checking whether header cstdio is available" DIRECT) -SET(KWSYS_LFS_AVAILABLE 0) -IF(KWSYS_LFS_REQUESTED) - # Large File Support is requested. - SET(KWSYS_LFS_REQUESTED 1) - - # Check for large file support. - SET(KWSYS_PLATFORM_CXX_TEST_DEFINES - -DKWSYS_CXX_HAS_CSTDIO=${KWSYS_CXX_HAS_CSTDIO}) - KWSYS_PLATFORM_CXX_TEST_RUN(KWSYS_LFS_WORKS - "Checking for Large File Support" DIRECT) - SET(KWSYS_PLATFORM_CXX_TEST_DEFINES) - - IF(KWSYS_LFS_WORKS) - SET(KWSYS_LFS_AVAILABLE 1) - ENDIF() -ELSE() - # Large File Support is not requested. - SET(KWSYS_LFS_REQUESTED 0) -ENDIF() - -#----------------------------------------------------------------------------- -# Configure the standard library header wrappers based on compiler's -# capabilities and parent project's request. Enforce 0/1 as only -# possible values for configuration into Configure.hxx. - -IF(0) # Not used by CastXML -KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAVE_STD - "Checking whether STL classes are in std namespace" DIRECT) - -IF(KWSYS_IOS_FORCE_OLD) - SET(KWSYS_IOS_USE_ANSI 0) -ELSE() - KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_USE_ANSI - "Checking whether ANSI stream headers are available" DIRECT) -ENDIF() - -IF(KWSYS_IOS_USE_ANSI) - KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAVE_STD - "Checking whether ANSI streams are in std namespace" DIRECT) - KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_USE_SSTREAM - "Checking whether ANSI string stream is available" DIRECT) -ELSE() - SET(KWSYS_IOS_HAVE_STD 0) - SET(KWSYS_IOS_USE_SSTREAM 0) -ENDIF() - -IF(KWSYS_IOS_USE_SSTREAM) - SET(KWSYS_IOS_USE_STRSTREAM_H 0) - SET(KWSYS_IOS_USE_STRSTREA_H 0) -ELSE() - KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_USE_STRSTREAM_H - "Checking whether strstream.h is available" DIRECT) - IF(KWSYS_IOS_USE_STRSTREAM_H) - SET(KWSYS_IOS_USE_STRSTREA_H 0) - ELSE() - KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_USE_STRSTREA_H - "Checking whether strstrea.h is available" DIRECT) - ENDIF() -ENDIF() - -KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_CSTDDEF - "Checking whether header cstddef is available" DIRECT) - -SET(KWSYS_PLATFORM_CXX_TEST_DEFINES - -DKWSYS_STL_HAVE_STD=${KWSYS_STL_HAVE_STD}) -KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_STRING_HAVE_NEQ_CHAR - "Checking whether stl string has operator!= for char*" DIRECT) -KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ITERATOR_TRAITS - "Checking whether stl has iterator_traits" DIRECT) -IF(KWSYS_STL_HAS_ITERATOR_TRAITS) - SET(KWSYS_STL_HAS_ITERATOR_CATEGORY 0) - SET(KWSYS_STL_HAS___ITERATOR_CATEGORY 0) -ELSE() - KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ITERATOR_CATEGORY - "Checking whether stl has old iterator_category" DIRECT) - IF(KWSYS_STL_HAS_ITERATOR_CATEGORY) - SET(KWSYS_STL_HAS___ITERATOR_CATEGORY 0) - ELSE() - KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS___ITERATOR_CATEGORY - "Checking whether stl has internal __iterator_category" DIRECT) - ENDIF() -ENDIF() -KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_TEMPLATE - "Checking whether stl has standard template allocator" DIRECT) -IF(KWSYS_STL_HAS_ALLOCATOR_TEMPLATE) - SET(KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE 0) - KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_REBIND - "Checking for rebind member of stl allocator" DIRECT) - KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT - "Checking for non-standard argument to stl allocator<>::max_size" DIRECT) -ELSE() - KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE - "Checking whether stl has old non-template allocator" DIRECT) - SET(KWSYS_STL_HAS_ALLOCATOR_REBIND 0) - SET(KWSYS_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT 0) -ENDIF() -KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_ALLOCATOR_OBJECTS - "Checking whether stl containers support allocator objects." DIRECT) -IF(KWSYS_IOS_USE_ANSI AND NOT WATCOM) - # ANSI streams always have string operators. - SET(KWSYS_STL_STRING_HAVE_OSTREAM 1) - SET(KWSYS_STL_STRING_HAVE_ISTREAM 1) -ELSE() - # There may not be string operators for old streams. - KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_STRING_HAVE_OSTREAM - "Checking whether stl string has ostream operator<<" DIRECT) - KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_STRING_HAVE_ISTREAM - "Checking whether stl string has istream operator>>" DIRECT) -ENDIF() -SET(KWSYS_PLATFORM_CXX_TEST_DEFINES - -DKWSYS_IOS_USE_ANSI=${KWSYS_IOS_USE_ANSI} - -DKWSYS_IOS_HAVE_STD=${KWSYS_IOS_HAVE_STD}) -KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAVE_BINARY - "Checking whether ios has binary openmode" DIRECT) -SET(KWSYS_PLATFORM_CXX_TEST_DEFINES) - -KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_NULL_TEMPLATE_ARGS - "Checking whether \"<>\" is needed for template friends" INVERT) -KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_MEMBER_TEMPLATES - "Checking for member template support" DIRECT) -KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_FULL_SPECIALIZATION - "Checking for standard template specialization syntax" DIRECT) -KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP - "Checking whether argument dependent lookup is supported" DIRECT) - -IF(UNIX) - KWSYS_PLATFORM_CXX_TEST(KWSYS_STAT_HAS_ST_MTIM - "Checking whether struct stat has st_mtim member" DIRECT) -ENDIF() - -# Check existence and uniqueness of long long and __int64. -KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_LONG_LONG - "Checking whether C++ compiler has 'long long'" DIRECT) -KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS___INT64 - "Checking whether C++ compiler has '__int64'" DIRECT) -IF(KWSYS_CXX_HAS___INT64) - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_SAME_LONG_AND___INT64 - "Checking whether long and __int64 are the same type" DIRECT) - IF(KWSYS_CXX_HAS_LONG_LONG) - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_SAME_LONG_LONG_AND___INT64 - "Checking whether long long and __int64 are the same type" DIRECT) - ENDIF() -ENDIF() - -# Enable the "long long" type if it is available. It is standard in -# C99 and C++03 but not in earlier standards. -IF(KWSYS_CXX_HAS_LONG_LONG) - SET(KWSYS_USE_LONG_LONG 1) -ELSE() - SET(KWSYS_USE_LONG_LONG 0) -ENDIF() - -# Enable the "__int64" type if it is available and unique. It is not -# standard. -SET(KWSYS_USE___INT64 0) -IF(KWSYS_CXX_HAS___INT64) - IF(NOT KWSYS_CXX_SAME_LONG_AND___INT64) - IF(NOT KWSYS_CXX_SAME_LONG_LONG_AND___INT64) - SET(KWSYS_USE___INT64 1) - ENDIF() - ENDIF() -ENDIF() -ENDIF() - -IF(KWSYS_USE_FundamentalType) - # Look for type size helper macros. - KWSYS_PLATFORM_INFO_TEST(C KWSYS_C_TYPE_MACROS - "Checking for C type size macros") - SET(macro_regex ".*INFO:macro\\[([^]]*)\\].*") - FOREACH(info ${KWSYS_C_TYPE_MACROS}) - IF("${info}" MATCHES "${macro_regex}") - STRING(REGEX REPLACE "${macro_regex}" "\\1" macro "${info}") - SET(KWSYS_C_HAS_MACRO_${macro} 1) - ENDIF() - ENDFOREACH() - - # Determine type sizes at preprocessing time if possible, and - # otherwise fall back to a try-compile. - SET(KWSYS_C_TYPE_NAME_CHAR "char") - SET(KWSYS_C_TYPE_NAME_SHORT "short") - SET(KWSYS_C_TYPE_NAME_INT "int") - SET(KWSYS_C_TYPE_NAME_LONG "long") - SET(KWSYS_C_TYPE_NAME_LONG_LONG "long long") - SET(KWSYS_C_TYPE_NAME___INT64 "__int64") - FOREACH(type CHAR SHORT INT LONG LONG_LONG __INT64) - IF(KWSYS_C_HAS_MACRO___SIZEOF_${type}__) - # Use __SIZEOF_${type}__ macro. - SET(KWSYS_SIZEOF_${type} TRUE) - SET(KWSYS_C_CODE_SIZEOF_${type} "#define ${KWSYS_NAMESPACE}_SIZEOF_${type} __SIZEOF_${type}__") - ELSEIF(KWSYS_C_HAS_MACRO___${type}_MAX__) - # Use __${type}_MAX__ macro. - SET(KWSYS_SIZEOF_${type} TRUE) - SET(KWSYS_C_CODE_SIZEOF_${type} "#if __${type}_MAX__ == 0x7f -# define ${KWSYS_NAMESPACE}_SIZEOF_${type} 1 -#elif __${type}_MAX__ == 0x7fff -# define ${KWSYS_NAMESPACE}_SIZEOF_${type} 2 -#elif __${type}_MAX__ == 0x7fffffff -# define ${KWSYS_NAMESPACE}_SIZEOF_${type} 4 -#elif __${type}_MAX__>>32 == 0x7fffffff -# define ${KWSYS_NAMESPACE}_SIZEOF_${type} 8 -#else -# error \"Cannot determine sizeof(${KWSYS_C_TYPE_NAME_${type}}).\" -#endif") - ELSE() - # Configure a hard-coded type size. - CHECK_TYPE_SIZE("${KWSYS_C_TYPE_NAME_${type}}" KWSYS_SIZEOF_${type}) - IF(NOT KWSYS_SIZEOF_${type}) - SET(KWSYS_SIZEOF_${type} 0) - ENDIF() - SET(KWSYS_C_CODE_SIZEOF_${type} - "#define ${KWSYS_NAMESPACE}_SIZEOF_${type} ${KWSYS_SIZEOF_${type}}") - ENDIF() - ENDFOREACH() - - IF(KWSYS_USE___INT64) - KWSYS_PLATFORM_CXX_TEST(KWSYS_CAN_CONVERT_UI64_TO_DOUBLE - "Checking whether unsigned __int64 can convert to double" DIRECT) - ELSE() - SET(KWSYS_CAN_CONVERT_UI64_TO_DOUBLE 1) - ENDIF() - - # Check signedness of "char" type. - KWSYS_PLATFORM_CXX_TEST_RUN(KWSYS_CHAR_IS_SIGNED - "Checking whether char is signed" DIRECT) -ENDIF() - -IF(0) # Not used by CastXML -IF(KWSYS_USE_Encoding) - # Look for type size helper macros. - KWSYS_PLATFORM_CXX_TEST(KWSYS_STL_HAS_WSTRING - "Checking whether wstring is available" DIRECT) -ENDIF() -ENDIF() - -IF(KWSYS_USE_IOStream) - # Determine whether iostreams support long long. - SET(KWSYS_PLATFORM_CXX_TEST_DEFINES - -DKWSYS_IOS_USE_ANSI=${KWSYS_IOS_USE_ANSI} - -DKWSYS_IOS_HAVE_STD=${KWSYS_IOS_HAVE_STD}) - IF(KWSYS_CXX_HAS_LONG_LONG) - KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_ISTREAM_LONG_LONG - "Checking if istream supports long long" DIRECT) - KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_OSTREAM_LONG_LONG - "Checking if ostream supports long long" DIRECT) - ELSE() - SET(KWSYS_IOS_HAS_ISTREAM_LONG_LONG 0) - SET(KWSYS_IOS_HAS_OSTREAM_LONG_LONG 0) - ENDIF() - IF(KWSYS_CXX_HAS___INT64) - KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_ISTREAM___INT64 - "Checking if istream supports __int64" DIRECT) - KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_OSTREAM___INT64 - "Checking if ostream supports __int64" DIRECT) - ELSE() - SET(KWSYS_IOS_HAS_ISTREAM___INT64 0) - SET(KWSYS_IOS_HAS_OSTREAM___INT64 0) - ENDIF() - SET(KWSYS_PLATFORM_CXX_TEST_DEFINES) -ENDIF() - -IF(KWSYS_NAMESPACE MATCHES "^kwsys$") - SET(KWSYS_NAME_IS_KWSYS 1) -ELSE() - SET(KWSYS_NAME_IS_KWSYS 0) -ENDIF() - -# Choose default shared/static build if not specified. -IF(KWSYS_BUILD_SHARED MATCHES "^KWSYS_BUILD_SHARED$") - SET(KWSYS_BUILD_SHARED ${BUILD_SHARED_LIBS}) -ENDIF() - -IF(KWSYS_BUILD_SHARED) - SET(KWSYS_BUILD_SHARED 1) - SET(KWSYS_LIBRARY_TYPE SHARED) -ELSE() - SET(KWSYS_BUILD_SHARED 0) - SET(KWSYS_LIBRARY_TYPE STATIC) -ENDIF() - -#----------------------------------------------------------------------------- -# Configure some implementation details. - -KWSYS_PLATFORM_C_TEST(KWSYS_C_HAS_PTRDIFF_T - "Checking whether C compiler has ptrdiff_t in stddef.h" DIRECT) -KWSYS_PLATFORM_C_TEST(KWSYS_C_HAS_SSIZE_T - "Checking whether C compiler has ssize_t in unistd.h" DIRECT) -SET_SOURCE_FILES_PROPERTIES(ProcessUNIX.c System.c PROPERTIES - COMPILE_FLAGS "-DKWSYS_C_HAS_PTRDIFF_T=${KWSYS_C_HAS_PTRDIFF_T} -DKWSYS_C_HAS_SSIZE_T=${KWSYS_C_HAS_SSIZE_T}" - ) - -IF(KWSYS_USE_SystemTools) - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_SETENV - "Checking whether CXX compiler has setenv" DIRECT) - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_UNSETENV - "Checking whether CXX compiler has unsetenv" DIRECT) - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H - "Checking whether CXX compiler has environ in stdlib.h" DIRECT) - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_UTIMES - "Checking whether CXX compiler has utimes" DIRECT) - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_UTIMENSAT - "Checking whether CXX compiler has utimensat" DIRECT) - SET_PROPERTY(SOURCE SystemTools.cxx APPEND PROPERTY COMPILE_DEFINITIONS - KWSYS_CXX_HAS_SETENV=${KWSYS_CXX_HAS_SETENV} - KWSYS_CXX_HAS_UNSETENV=${KWSYS_CXX_HAS_UNSETENV} - KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H=${KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H} - KWSYS_CXX_HAS_UTIMES=${KWSYS_CXX_HAS_UTIMES} - KWSYS_CXX_HAS_UTIMENSAT=${KWSYS_CXX_HAS_UTIMENSAT} - ) -ENDIF() - -IF(KWSYS_USE_SystemInformation) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS SIZEOF_VOID_P=${CMAKE_SIZEOF_VOID_P}) - IF(NOT CYGWIN) - INCLUDE(CheckIncludeFiles) - CHECK_INCLUDE_FILES("sys/types.h;ifaddrs.h" KWSYS_SYS_HAS_IFADDRS_H) - IF(KWSYS_SYS_HAS_IFADDRS_H) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_SYS_HAS_IFADDRS_H=1) - ENDIF() - ENDIF() - IF(WIN32) - INCLUDE(CheckSymbolExists) - SET(CMAKE_REQUIRED_LIBRARIES Psapi) - CHECK_SYMBOL_EXISTS(GetProcessMemoryInfo "windows.h;psapi.h" KWSYS_SYS_HAS_PSAPI) - UNSET(CMAKE_REQUIRED_LIBRARIES) - IF(KWSYS_SYS_HAS_PSAPI) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_SYS_HAS_PSAPI=1) - IF(MSVC70 OR MSVC71) - # Suppress LNK4089: all references to 'PSAPI.DLL' discarded by /OPT:REF - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /IGNORE:4089") - ENDIF() - ENDIF() - ENDIF() - IF(CMAKE_SYSTEM MATCHES "HP-UX") - CHECK_INCLUDE_FILES("sys/mpctl.h" KWSYS_SYS_HAS_MPCTL_H) - IF(KWSYS_SYS_HAS_MPCTL_H) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_SYS_HAS_MPCTL_H=1) - ENDIF() - ENDIF() - IF(CMAKE_SYSTEM MATCHES "BSD") - CHECK_INCLUDE_FILES("machine/cpu.h" KWSYS_SYS_HAS_MACHINE_CPU_H) - IF(KWSYS_SYS_HAS_MACHINE_CPU_H) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_SYS_HAS_MACHINE_CPU_H=1) - ENDIF() - ENDIF() - IF(KWSYS_LFS_AVAILABLE AND NOT KWSYS_LFS_DISABLE) - SET(KWSYS_PLATFORM_CXX_TEST_DEFINES -DKWSYS_HAS_LFS=1) - ENDIF() - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_RLIMIT64 - "Checking whether CXX compiler has rlimit64" DIRECT) - SET(KWSYS_PLATFORM_CXX_TEST_DEFINES) - IF(KWSYS_CXX_HAS_RLIMIT64) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_CXX_HAS_RLIMIT64=1) - ENDIF() - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ATOL - "Checking whether CXX compiler has atol" DIRECT) - IF(KWSYS_CXX_HAS_ATOL) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_CXX_HAS_ATOL=1) - ENDIF() - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ATOLL - "Checking whether CXX compiler has atoll" DIRECT) - IF(KWSYS_CXX_HAS_ATOLL) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_CXX_HAS_ATOLL=1) - ENDIF() - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS__ATOI64 - "Checking whether CXX compiler has _atoi64" DIRECT) - IF(KWSYS_CXX_HAS__ATOI64) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_CXX_HAS__ATOI64=1) - ENDIF() - IF(UNIX) - INCLUDE(CheckIncludeFileCXX) - # check for simple stack trace - # usually it's in libc but on FreeBSD - # it's in libexecinfo - FIND_LIBRARY(EXECINFO_LIB "execinfo") - MARK_AS_ADVANCED(EXECINFO_LIB) - IF (NOT EXECINFO_LIB) - SET(EXECINFO_LIB "") - ENDIF() - CHECK_INCLUDE_FILE_CXX("execinfo.h" KWSYS_CXX_HAS_EXECINFOH) - IF (KWSYS_CXX_HAS_EXECINFOH) - # we have the backtrace header check if it - # can be used with this compiler - SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${EXECINFO_LIB}) - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BACKTRACE - "Checking whether backtrace works with this C++ compiler" DIRECT) - SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES) - IF (KWSYS_CXX_HAS_BACKTRACE) - # backtrace is supported by this system and compiler. - # now check for the more advanced capabilities. - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE=1) - # check for symbol lookup using dladdr - CHECK_INCLUDE_FILE_CXX("dlfcn.h" KWSYS_CXX_HAS_DLFCNH) - IF (KWSYS_CXX_HAS_DLFCNH) - # we have symbol lookup libraries and headers - # check if they can be used with this compiler - SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${CMAKE_DL_LIBS}) - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_DLADDR - "Checking whether dladdr works with this C++ compiler" DIRECT) - SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES) - IF (KWSYS_CXX_HAS_DLADDR) - # symbol lookup is supported by this system - # and compiler. - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP=1) - ENDIF() - ENDIF() - # c++ demangling support - # check for cxxabi headers - CHECK_INCLUDE_FILE_CXX("cxxabi.h" KWSYS_CXX_HAS_CXXABIH) - IF (KWSYS_CXX_HAS_CXXABIH) - # check if cxxabi can be used with this - # system and compiler. - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_CXXABI - "Checking whether cxxabi works with this C++ compiler" DIRECT) - IF (KWSYS_CXX_HAS_CXXABI) - # c++ demangle using cxxabi is supported with - # this system and compiler - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE=1) - ENDIF() - ENDIF() - # basic backtrace works better with release build - # don't bother with advanced features for release - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS_DEBUG KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD=1) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS_RELWITHDEBINFO KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD=1) - ENDIF() - ENDIF() - ENDIF() - IF(BORLAND) - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM - "Checking whether Borland CXX compiler supports assembler instructions" DIRECT) - IF(KWSYS_CXX_HAS_BORLAND_ASM) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_CXX_HAS_BORLAND_ASM=1) - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM_CPUID - "Checking whether Borland CXX compiler supports CPUID assembler instruction" DIRECT) - IF(KWSYS_CXX_HAS_BORLAND_ASM_CPUID) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_CXX_HAS_BORLAND_ASM_CPUID=1) - ENDIF() - ENDIF() - ENDIF() - IF(KWSYS_USE___INT64) - SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_USE___INT64=1) - ENDIF() - IF(KWSYS_USE_LONG_LONG) - SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_USE_LONG_LONG=1) - ENDIF() - IF(KWSYS_IOS_HAS_OSTREAM_LONG_LONG) - SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_IOS_HAS_OSTREAM_LONG_LONG=1) - ENDIF() - IF(KWSYS_IOS_HAS_OSTREAM___INT64) - SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_IOS_HAS_OSTREAM___INT64=1) - ENDIF() - IF(KWSYS_BUILD_SHARED) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_BUILD_SHARED=1) - ENDIF() - - IF(UNIX AND NOT CYGWIN) - KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_GETLOADAVG - "Checking whether CXX compiler has getloadavg" DIRECT) - IF(KWSYS_CXX_HAS_GETLOADAVG) - SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY - COMPILE_DEFINITIONS KWSYS_CXX_HAS_GETLOADAVG=1) - ENDIF() - ENDIF() -ENDIF() - -#----------------------------------------------------------------------------- -# Choose a directory for the generated headers. -IF(NOT KWSYS_HEADER_ROOT) - SET(KWSYS_HEADER_ROOT "${PROJECT_BINARY_DIR}") -ENDIF() -SET(KWSYS_HEADER_DIR "${KWSYS_HEADER_ROOT}/${KWSYS_NAMESPACE}") -INCLUDE_DIRECTORIES(${KWSYS_HEADER_ROOT}) - -#----------------------------------------------------------------------------- -IF(KWSYS_INSTALL_DOC_DIR) - # Assign the license to the runtime component since it must be - # distributed with binary forms of this software. - IF(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME) - SET(KWSYS_INSTALL_LICENSE_OPTIONS ${KWSYS_INSTALL_LICENSE_OPTIONS} - COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_RUNTIME} - ) - ENDIF() - - # Install the license under the documentation directory. - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt - DESTINATION ${KWSYS_INSTALL_DOC_DIR}/${KWSYS_NAMESPACE} - ${KWSYS_INSTALL_LICENSE_OPTIONS}) -ENDIF() - -#----------------------------------------------------------------------------- -# Create STL header wrappers to block warnings in the STL headers and -# give standard names by which they may be included. -IF(0) # Not used by CastXML -SET(KWSYS_STL_HEADER_EXTRA_string 1) -FOREACH(header - algorithm - deque - exception - functional - iterator - list - map - memory - new - numeric - queue - set - stack - stdexcept - string - utility - vector - ) - # Configure the header wrapper. - SET(KWSYS_STL_HEADER "${header}") - IF(KWSYS_STL_HEADER_EXTRA_${header}) - SET(KWSYS_STL_HEADER_EXTRA - "#define ${KWSYS_NAMESPACE}_stl_${header}_including_hxx\n# include <${KWSYS_NAMESPACE}/stl/${header}.hxx>\n#undef ${KWSYS_NAMESPACE}_stl_${header}_including_hxx\n") - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsys_stl_${header}.hxx.in - ${KWSYS_HEADER_DIR}/stl/${header}.hxx - @ONLY IMMEDIATE) - IF(KWSYS_INSTALL_INCLUDE_DIR) - INSTALL(FILES ${KWSYS_HEADER_DIR}/stl/${header}.hxx - DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE}/stl - ${KWSYS_INSTALL_INCLUDE_OPTIONS}) - ENDIF() - ELSE() - SET(KWSYS_STL_HEADER_EXTRA "") - ENDIF() - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsys_stl.hxx.in - ${KWSYS_HEADER_DIR}/stl/${header} - @ONLY IMMEDIATE) - - # Create an install target for the header wrapper. - IF(KWSYS_INSTALL_INCLUDE_DIR) - INSTALL(FILES ${KWSYS_HEADER_DIR}/stl/${header} - DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE}/stl - ${KWSYS_INSTALL_INCLUDE_OPTIONS}) - ENDIF() -ENDFOREACH() - -# Provide cstddef header. -CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsys_cstddef.hxx.in - ${KWSYS_HEADER_DIR}/cstddef - @ONLY IMMEDIATE) -IF(KWSYS_INSTALL_INCLUDE_DIR) - INSTALL(FILES ${KWSYS_HEADER_DIR}/cstddef - DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE} - ${KWSYS_INSTALL_INCLUDE_OPTIONS}) -ENDIF() - -#----------------------------------------------------------------------------- -# Create streams header wrappers to give standard names by which they -# may be included. -FOREACH(header iostream fstream sstream iosfwd) - # Configure the header wrapper. - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/kwsys_ios_${header}.h.in - ${KWSYS_HEADER_DIR}/ios/${header} - @ONLY IMMEDIATE) - - # Create an install target for the header wrapper. - IF(KWSYS_INSTALL_INCLUDE_DIR) - INSTALL(FILES ${KWSYS_HEADER_DIR}/ios/${header} - DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE}/ios - ${KWSYS_INSTALL_INCLUDE_OPTIONS}) - ENDIF() -ENDFOREACH() -ENDIF() - -#----------------------------------------------------------------------------- -# Build a list of classes and headers we need to implement the -# selected components. Initialize with required components. -SET(KWSYS_CLASSES) -SET(KWSYS_H_FILES Configure) # CastXML needs only this. -IF(0) # Not used by CastXML -SET(KWSYS_H_FILES Configure SharedForward) -SET(KWSYS_HXX_FILES Configure String - hashtable hash_fun hash_map hash_set - auto_ptr - ) - -# Add selected C++ classes. -SET(cppclasses - Directory DynamicLoader Encoding Glob RegularExpression SystemTools - CommandLineArguments IOStream FStream SystemInformation - ) -FOREACH(cpp ${cppclasses}) - IF(KWSYS_USE_${cpp}) - # Use the corresponding class. - SET(KWSYS_CLASSES ${KWSYS_CLASSES} ${cpp}) - - # Load component-specific CMake code. - IF(EXISTS ${PROJECT_SOURCE_DIR}/kwsys${cpp}.cmake) - INCLUDE(${PROJECT_SOURCE_DIR}/kwsys${cpp}.cmake) - ENDIF() - ENDIF() -ENDFOREACH() -ENDIF() - -# Add selected C components. -FOREACH(c - Process Base64 Encoding FundamentalType MD5 Terminal System String CPU - ) - IF(KWSYS_USE_${c}) - # Use the corresponding header file. - SET(KWSYS_H_FILES ${KWSYS_H_FILES} ${c}) - - # Load component-specific CMake code. - IF(EXISTS ${PROJECT_SOURCE_DIR}/kwsys${c}.cmake) - INCLUDE(${PROJECT_SOURCE_DIR}/kwsys${c}.cmake) - ENDIF() - ENDIF() -ENDFOREACH() - -#----------------------------------------------------------------------------- -# Build a list of sources for the library based on components that are -# included. -SET(KWSYS_C_SRCS) -SET(KWSYS_CXX_SRCS) - -# Add the proper sources for this platform's Process implementation. -IF(KWSYS_USE_Process) - IF(NOT UNIX) - # Use the Windows implementation. - SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c) - ELSE() - # Use the UNIX implementation. - SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c) - ENDIF() -ENDIF() - -# Add selected C sources. -FOREACH(c Base64 Encoding MD5 Terminal System String) - IF(KWSYS_USE_${c}) - IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}C.c) - LIST(APPEND KWSYS_C_SRCS ${c}C.c) - ELSE() - LIST(APPEND KWSYS_C_SRCS ${c}.c) - ENDIF() - ENDIF() -ENDFOREACH() - -# Configure headers of C++ classes and construct the list of sources. -FOREACH(c ${KWSYS_CLASSES}) - # Add this source to the list of source files for the library. - IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}CXX.cxx) - LIST(APPEND KWSYS_CXX_SRCS ${c}CXX.cxx) - ELSEIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${c}.cxx) - LIST(APPEND KWSYS_CXX_SRCS ${c}.cxx) - ENDIF() - - # Configure the header for this class. - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${c}.hxx.in ${KWSYS_HEADER_DIR}/${c}.hxx - @ONLY IMMEDIATE) - SET(KWSYS_CXX_SRCS ${KWSYS_CXX_SRCS} ${KWSYS_HEADER_DIR}/${c}.hxx) - - # Create an install target for the header. - IF(KWSYS_INSTALL_INCLUDE_DIR) - INSTALL(FILES ${KWSYS_HEADER_DIR}/${c}.hxx - DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE} - ${KWSYS_INSTALL_INCLUDE_OPTIONS}) - ENDIF() -ENDFOREACH() - -# Configure C headers. -FOREACH(h ${KWSYS_H_FILES}) - # Configure the header into the given directory. - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${h}.h.in ${KWSYS_HEADER_DIR}/${h}.h - @ONLY IMMEDIATE) - SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ${KWSYS_HEADER_DIR}/${h}.h) - - # Create an install target for the header. - IF(KWSYS_INSTALL_INCLUDE_DIR) - INSTALL(FILES ${KWSYS_HEADER_DIR}/${h}.h - DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE} - ${KWSYS_INSTALL_INCLUDE_OPTIONS}) - ENDIF() -ENDFOREACH() - -# Configure other C++ headers. -FOREACH(h ${KWSYS_HXX_FILES}) - # Configure the header into the given directory. - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${h}.hxx.in ${KWSYS_HEADER_DIR}/${h}.hxx - @ONLY IMMEDIATE) - SET(KWSYS_CXX_SRCS ${KWSYS_CXX_SRCS} ${KWSYS_HEADER_DIR}/${h}.hxx) - - # Create an install target for the header. - IF(KWSYS_INSTALL_INCLUDE_DIR) - INSTALL(FILES ${KWSYS_HEADER_DIR}/${h}.hxx - DESTINATION ${KWSYS_INSTALL_INCLUDE_DIR}/${KWSYS_NAMESPACE} - ${KWSYS_INSTALL_INCLUDE_OPTIONS}) - ENDIF() -ENDFOREACH() - -#----------------------------------------------------------------------------- -# Add the library with the configured name and list of sources. -IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS) - ADD_LIBRARY(${KWSYS_NAMESPACE} ${KWSYS_LIBRARY_TYPE} - ${KWSYS_C_SRCS} ${KWSYS_CXX_SRCS}) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE} PROPERTY LABELS ${KWSYS_LABELS_LIB}) - IF(KWSYS_USE_DynamicLoader) - IF(UNIX) - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${CMAKE_DL_LIBS}) - ENDIF() - ENDIF() - - IF(KWSYS_USE_SystemInformation) - IF(WIN32) - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ws2_32) - IF(KWSYS_SYS_HAS_PSAPI) - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} Psapi) - ENDIF() - ELSEIF(UNIX) - IF (EXECINFO_LIB AND KWSYS_CXX_HAS_BACKTRACE) - # backtrace on FreeBSD is not in libc - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${EXECINFO_LIB}) - ENDIF() - IF (KWSYS_CXX_HAS_DLADDR) - # for symbol lookup using dladdr - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${CMAKE_DL_LIBS}) - ENDIF() - ENDIF() - ENDIF() - - # Apply user-defined target properties to the library. - IF(KWSYS_PROPERTIES_CXX) - SET_TARGET_PROPERTIES(${KWSYS_NAMESPACE} PROPERTIES - ${KWSYS_PROPERTIES_CXX} - ) - ENDIF() - - # Create an install target for the library. - IF(KWSYS_INSTALL_LIBRARY_RULE) - INSTALL(TARGETS ${KWSYS_NAMESPACE} ${KWSYS_INSTALL_LIBRARY_RULE}) - ENDIF() -ENDIF() - -# Add a C-only library if requested. -IF(KWSYS_ENABLE_C AND KWSYS_C_SRCS) - ADD_LIBRARY(${KWSYS_NAMESPACE}_c ${KWSYS_LIBRARY_TYPE} ${KWSYS_C_SRCS}) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}_c PROPERTY LABELS ${KWSYS_LABELS_LIB}) - - # Apply user-defined target properties to the library. - IF(KWSYS_PROPERTIES_C) - SET_TARGET_PROPERTIES(${KWSYS_NAMESPACE}_c PROPERTIES - ${KWSYS_PROPERTIES_C} - ) - ENDIF() - - # Create an install target for the library. - IF(KWSYS_INSTALL_LIBRARY_RULE) - INSTALL(TARGETS ${KWSYS_NAMESPACE}_c ${KWSYS_INSTALL_LIBRARY_RULE}) - ENDIF() -ENDIF() - -# For building kwsys itself, we use a macro defined on the command -# line to configure the namespace in the C and C++ source files. -ADD_DEFINITIONS("-DKWSYS_NAMESPACE=${KWSYS_NAMESPACE}") - -# Disable deprecation warnings for standard C functions. -IF(MSVC OR (WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "Intel")) - ADD_DEFINITIONS( - -D_CRT_NONSTDC_NO_DEPRECATE - -D_CRT_SECURE_NO_DEPRECATE - -D_CRT_SECURE_NO_WARNINGS - -D_SCL_SECURE_NO_DEPRECATE - ) -ENDIF() - -IF(WIN32) - # Help enforce the use of wide Windows apis. - ADD_DEFINITIONS(-DUNICODE -D_UNICODE) -ENDIF() - -IF(KWSYS_USE_String) - # Activate code in "String.c". See the comment in the source. - SET_SOURCE_FILES_PROPERTIES(String.c PROPERTIES - COMPILE_FLAGS "-DKWSYS_STRING_C") -ENDIF() - -IF(KWSYS_USE_Encoding) - # Set default 8 bit encoding in "EndcodingC.c". - SET_PROPERTY(SOURCE EncodingC.c APPEND PROPERTY COMPILE_DEFINITIONS - KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE}) -ENDIF() - -#----------------------------------------------------------------------------- -# Setup testing if not being built as part of another project. -IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) - IF(BUILD_TESTING) - # Compute the location of executables. - SET(EXEC_DIR "${CMAKE_CURRENT_BINARY_DIR}") - IF(EXECUTABLE_OUTPUT_PATH) - SET(EXEC_DIR "${EXECUTABLE_OUTPUT_PATH}") - ENDIF() - - # C tests - SET(KWSYS_C_TESTS - testEncode - testTerminal - ) - IF(KWSYS_STANDALONE) - SET(KWSYS_C_TESTS ${KWSYS_C_TESTS} testFail) - ENDIF() - CREATE_TEST_SOURCELIST( - KWSYS_C_TEST_SRCS ${KWSYS_NAMESPACE}TestsC.c - ${KWSYS_C_TESTS} - ) - ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestsC ${KWSYS_C_TEST_SRCS}) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsC PROPERTY LABELS ${KWSYS_LABELS_EXE}) - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestsC ${KWSYS_NAMESPACE}_c) - FOREACH(test ${KWSYS_C_TESTS}) - ADD_TEST(kwsys.${test} ${EXEC_DIR}/${KWSYS_NAMESPACE}TestsC ${test} ${KWSYS_TEST_ARGS_${test}}) - SET_PROPERTY(TEST kwsys.${test} PROPERTY LABELS ${KWSYS_LABELS_TEST}) - ENDFOREACH() - - # C++ tests - IF(NOT WATCOM) - SET(KWSYS_CXX_TESTS - testAutoPtr - testHashSTL - ) - ENDIF() - SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} - testIOS - testSystemTools - testCommandLineArguments - testCommandLineArguments1 - ) - IF(KWSYS_STL_HAS_WSTRING) - SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} - testEncoding - ) - ENDIF() - IF(KWSYS_USE_FStream) - SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} - testFStream - ) - ENDIF() - IF(KWSYS_USE_SystemInformation) - SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testSystemInformation) - ENDIF() - IF(KWSYS_USE_DynamicLoader) - SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testDynamicLoader) - # If kwsys contains the DynamicLoader, need extra library - ADD_LIBRARY(${KWSYS_NAMESPACE}TestDynload MODULE testDynload.c) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestDynload PROPERTY LABELS ${KWSYS_LABELS_LIB}) - ADD_DEPENDENCIES(${KWSYS_NAMESPACE}TestDynload ${KWSYS_NAMESPACE}) - ENDIF() - CREATE_TEST_SOURCELIST( - KWSYS_CXX_TEST_SRCS ${KWSYS_NAMESPACE}TestsCxx.cxx - ${KWSYS_CXX_TESTS} - ) - ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_CXX_TEST_SRCS}) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsCxx PROPERTY LABELS ${KWSYS_LABELS_EXE}) - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestsCxx ${KWSYS_NAMESPACE}) - - SET(TEST_SYSTEMTOOLS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") - SET(TEST_SYSTEMTOOLS_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") - CONFIGURE_FILE( - ${PROJECT_SOURCE_DIR}/testSystemTools.h.in - ${PROJECT_BINARY_DIR}/testSystemTools.h) - INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR}) - - IF(CTEST_TEST_KWSYS) - CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/ExtraTest.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/ExtraTest.cmake") - SET_DIRECTORY_PROPERTIES(PROPERTIES TEST_INCLUDE_FILE "${CMAKE_CURRENT_BINARY_DIR}/ExtraTest.cmake") - ENDIF() - - SET(KWSYS_TEST_ARGS_testCommandLineArguments - --another-bool-variable - --long3=opt - --set-bool-arg1 - -SSS ken brad bill andy - --some-bool-variable=true - --some-double-variable12.5 - --some-int-variable 14 - "--some-string-variable=test string with space" - --some-multi-argument 5 1 8 3 7 1 3 9 7 1 - -N 12.5 -SS=andy -N 1.31 -N 22 - -SS=bill -BBtrue -SS=brad - -BBtrue - -BBfalse - -SS=ken - -A - -C=test - --long2 hello - ) - SET(KWSYS_TEST_ARGS_testCommandLineArguments1 - --ignored - -n 24 - --second-ignored - "-m=test value" - third-ignored - -p - some junk at the end - ) - FOREACH(test ${KWSYS_CXX_TESTS}) - ADD_TEST(kwsys.${test} ${EXEC_DIR}/${KWSYS_NAMESPACE}TestsCxx ${test} ${KWSYS_TEST_ARGS_${test}}) - SET_PROPERTY(TEST kwsys.${test} PROPERTY LABELS ${KWSYS_LABELS_TEST}) - ENDFOREACH() - - # Process tests. - ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestProcess testProcess.c) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestProcess PROPERTY LABELS ${KWSYS_LABELS_EXE}) - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestProcess ${KWSYS_NAMESPACE}_c) - IF(NOT CYGWIN) - SET(KWSYS_TEST_PROCESS_7 7) - ENDIF() - FOREACH(n 1 2 3 4 5 6 ${KWSYS_TEST_PROCESS_7} 9 10) - ADD_TEST(kwsys.testProcess-${n} ${EXEC_DIR}/${KWSYS_NAMESPACE}TestProcess ${n}) - SET_PROPERTY(TEST kwsys.testProcess-${n} PROPERTY LABELS ${KWSYS_LABELS_TEST}) - SET_TESTS_PROPERTIES(kwsys.testProcess-${n} PROPERTIES TIMEOUT 120) - ENDFOREACH() - - # Some Apple compilers produce bad optimizations in this source. - IF(APPLE AND CMAKE_C_COMPILER_ID MATCHES "^(GNU|LLVM)$") - SET_SOURCE_FILES_PROPERTIES(testProcess.c PROPERTIES COMPILE_FLAGS -O0) - ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "XL") - # Tell IBM XL not to warn about our test infinite loop - SET_PROPERTY(SOURCE testProcess.c PROPERTY COMPILE_FLAGS -qsuppress=1500-010) - ENDIF() - - # Test SharedForward - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/testSharedForward.c.in - ${PROJECT_BINARY_DIR}/testSharedForward.c @ONLY IMMEDIATE) - ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestSharedForward - ${PROJECT_BINARY_DIR}/testSharedForward.c) - SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestSharedForward PROPERTY LABELS ${KWSYS_LABELS_EXE}) - ADD_DEPENDENCIES(${KWSYS_NAMESPACE}TestSharedForward ${KWSYS_NAMESPACE}_c) - ADD_TEST(kwsys.testSharedForward ${EXEC_DIR}/${KWSYS_NAMESPACE}TestSharedForward 1) - SET_PROPERTY(TEST kwsys.testSharedForward PROPERTY LABELS ${KWSYS_LABELS_TEST}) - - # Configure some test properties. - IF(KWSYS_STANDALONE) - # We expect test to fail - SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES WILL_FAIL ON) - GET_TEST_PROPERTY(kwsys.testFail WILL_FAIL wfv) - SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES MEASUREMENT "Some Key=Some Value") - MESSAGE(STATUS "GET_TEST_PROPERTY returned: ${wfv}") - ENDIF() - - # Set up ctest custom configuration file. - CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/CTestCustom.cmake.in - ${PROJECT_BINARY_DIR}/CTestCustom.cmake @ONLY) - - # Suppress known consistent failures on buggy systems. - IF(KWSYS_TEST_BOGUS_FAILURES) - SET_TESTS_PROPERTIES(${KWSYS_TEST_BOGUS_FAILURES} PROPERTIES WILL_FAIL ON) - ENDIF() - - ENDIF() -ENDIF() diff --git a/src/kwsys/CONTRIBUTING.rst b/src/kwsys/CONTRIBUTING.rst deleted file mode 100644 index 960eea4..0000000 --- a/src/kwsys/CONTRIBUTING.rst +++ /dev/null @@ -1,35 +0,0 @@ -Contributing to KWSys -********************* - -Overview -======== - -KWSys is kept in its own Git repository and shared by several projects -via copies in their source trees. Changes to KWSys should not be made -directly in a host project, except perhaps in maintenance branches. - -Please visit - - http://public.kitware.com/Wiki/KWSys/Git - -to contribute changes directly to KWSys upstream. Once changes are -reviewed, tested, and integrated there then the copies of KWSys within -dependent projects can be updated to get the changes. - -Issues -====== - -KWSys has no independent issue tracker. After encountering an issue -(bug) please try to submit a patch using the above instructions. -Otherwise please report the issue to the tracker for the project that -hosts the copy of KWSys in which the problem was found. - -License -======= - -We do not require any formal copyright assignment or contributor license -agreement. Any contributions intentionally sent upstream are presumed -to be offered under terms of the OSI-approved BSD 3-clause License. -See `Copyright.txt`_ for details. - -.. _`Copyright.txt`: Copyright.txt diff --git a/src/kwsys/Configure.h.in b/src/kwsys/Configure.h.in deleted file mode 100644 index 70cf844..0000000 --- a/src/kwsys/Configure.h.in +++ /dev/null @@ -1,131 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#ifndef @KWSYS_NAMESPACE@_Configure_h -#define @KWSYS_NAMESPACE@_Configure_h - -/* If we are building a kwsys .c or .cxx file, let it use the kwsys - namespace. When not building a kwsys source file these macros are - temporarily defined inside the headers that use them. */ -#if defined(KWSYS_NAMESPACE) -# define kwsys_ns(x) @KWSYS_NAMESPACE@##x -# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT -#endif - -/* Disable some warnings inside kwsys source files. */ -#if defined(KWSYS_NAMESPACE) -# if defined(__BORLANDC__) -# pragma warn -8027 /* function not inlined. */ -# endif -# if defined(__INTEL_COMPILER) -# pragma warning (disable: 1572) /* floating-point equality test */ -# endif -# if defined(__sgi) && !defined(__GNUC__) -# pragma set woff 3970 /* pointer to int conversion */ -# pragma set woff 3968 /* 64 bit conversion */ -# endif -#endif - -/* Whether kwsys namespace is "kwsys". */ -#define @KWSYS_NAMESPACE@_NAME_IS_KWSYS @KWSYS_NAME_IS_KWSYS@ - -/* Whether Large File Support is requested. */ -#define @KWSYS_NAMESPACE@_LFS_REQUESTED @KWSYS_LFS_REQUESTED@ - -/* Whether Large File Support is available. */ -#if @KWSYS_NAMESPACE@_LFS_REQUESTED -# define @KWSYS_NAMESPACE@_LFS_AVAILABLE @KWSYS_LFS_AVAILABLE@ -#endif - -/* Setup Large File Support if requested. */ -#if @KWSYS_NAMESPACE@_LFS_REQUESTED - /* Since LFS is requested this header must be included before system - headers whether or not LFS is available. */ -# if 0 && (defined(_SYS_TYPES_H) || defined(_SYS_TYPES_INCLUDED)) -# error "@KWSYS_NAMESPACE@/Configure.h must be included before sys/types.h" -# endif - /* Enable the large file API if it is available. */ -# if @KWSYS_NAMESPACE@_LFS_AVAILABLE && \ - !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINES) -# if !defined(_LARGEFILE_SOURCE) && \ - !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_LARGEFILE_SOURCE) -# define _LARGEFILE_SOURCE -# endif -# if !defined(_LARGEFILE64_SOURCE) && \ - !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_LARGEFILE64_SOURCE) -# define _LARGEFILE64_SOURCE -# endif -# if !defined(_LARGE_FILES) && \ - !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_LARGE_FILES) -# define _LARGE_FILES -# endif -# if !defined(_FILE_OFFSET_BITS) && \ - !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_FILE_OFFSET_BITS) -# define _FILE_OFFSET_BITS 64 -# endif -# if 0 && (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS < 64) -# error "_FILE_OFFSET_BITS must be defined to at least 64" -# endif -# endif -#endif - -/* Setup the export macro. */ -#if @KWSYS_BUILD_SHARED@ -# if defined(_WIN32) || defined(__CYGWIN__) -# if defined(@KWSYS_NAMESPACE@_EXPORTS) -# define @KWSYS_NAMESPACE@_EXPORT __declspec(dllexport) -# else -# define @KWSYS_NAMESPACE@_EXPORT __declspec(dllimport) -# endif -# elif __GNUC__ >= 4 -# define @KWSYS_NAMESPACE@_EXPORT __attribute__ ((visibility("default"))) -# else -# define @KWSYS_NAMESPACE@_EXPORT -# endif -#else -# define @KWSYS_NAMESPACE@_EXPORT -#endif - -/* Enable warnings that are off by default but are useful. */ -#if !defined(@KWSYS_NAMESPACE@_NO_WARNING_ENABLE) -# if defined(_MSC_VER) -# pragma warning ( default : 4263 ) /* no override, call convention differs */ -# endif -#endif - -/* Disable warnings that are on by default but occur in valid code. */ -#if !defined(@KWSYS_NAMESPACE@_NO_WARNING_DISABLE) -# if defined(_MSC_VER) -# pragma warning (disable: 4097) /* typedef is synonym for class */ -# pragma warning (disable: 4127) /* conditional expression is constant */ -# pragma warning (disable: 4244) /* possible loss in conversion */ -# pragma warning (disable: 4251) /* missing DLL-interface */ -# pragma warning (disable: 4305) /* truncation from type1 to type2 */ -# pragma warning (disable: 4309) /* truncation of constant value */ -# pragma warning (disable: 4514) /* unreferenced inline function */ -# pragma warning (disable: 4706) /* assignment in conditional expression */ -# pragma warning (disable: 4710) /* function not inlined */ -# pragma warning (disable: 4786) /* identifier truncated in debug info */ -# endif -#endif - -/* MSVC 6.0 in release mode will warn about code it produces with its - optimizer. Disable the warnings specifically for this - configuration. Real warnings will be revealed by a debug build or - by other compilers. */ -#if !defined(@KWSYS_NAMESPACE@_NO_WARNING_DISABLE_BOGUS) -# if defined(_MSC_VER) && (_MSC_VER < 1300) && defined(NDEBUG) -# pragma warning ( disable : 4701 ) /* Variable may be used uninitialized. */ -# pragma warning ( disable : 4702 ) /* Unreachable code. */ -# endif -#endif - -#endif diff --git a/src/kwsys/Copyright.txt b/src/kwsys/Copyright.txt deleted file mode 100644 index 1549a7d..0000000 --- a/src/kwsys/Copyright.txt +++ /dev/null @@ -1,31 +0,0 @@ -KWSys - Kitware System Library -Copyright 2000-2009 Kitware, Inc., Insight Software Consortium -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -* Neither the names of Kitware, Inc., the Insight Software Consortium, - nor the names of their contributors may be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/kwsys/Encoding.h.in b/src/kwsys/Encoding.h.in deleted file mode 100644 index 591c5a8..0000000 --- a/src/kwsys/Encoding.h.in +++ /dev/null @@ -1,79 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#ifndef @KWSYS_NAMESPACE@_Encoding_h -#define @KWSYS_NAMESPACE@_Encoding_h - -#include <@KWSYS_NAMESPACE@/Configure.h> -#include - -/* Redefine all public interface symbol names to be in the proper - namespace. These macros are used internally to kwsys only, and are - not visible to user code. Use kwsysHeaderDump.pl to reproduce - these macros after making changes to the interface. */ -#if !defined(KWSYS_NAMESPACE) -# define kwsys_ns(x) @KWSYS_NAMESPACE@##x -# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT -#endif -#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS -# define kwsysEncoding kwsys_ns(Encoding) -# define kwsysEncoding_mbstowcs kwsys_ns(Encoding_mbstowcs) -# define kwsysEncoding_DupToWide kwsys_ns(Encoding_DupToWide) -# define kwsysEncoding_wcstombs kwsys_ns(Encoding_wcstombs) -# define kwsysEncoding_DupToNarrow kwsys_ns(Encoding_DupToNarrow) -#endif - -#if defined(__cplusplus) -extern "C" -{ -#endif - - -/* Convert a narrow string to a wide string. - On Windows, UTF-8 is assumed, and on other platforms, - the current locale is assumed. - */ -kwsysEXPORT size_t kwsysEncoding_mbstowcs(wchar_t* dest, const char* src, size_t n); - -/* Convert a narrow string to a wide string. - This can return NULL if the conversion fails. */ -kwsysEXPORT wchar_t* kwsysEncoding_DupToWide(const char* src); - - -/* Convert a wide string to a narrow string. - On Windows, UTF-8 is assumed, and on other platforms, - the current locale is assumed. */ -kwsysEXPORT size_t kwsysEncoding_wcstombs(char* dest, const wchar_t* src, size_t n); - -/* Convert a wide string to a narrow string. - This can return NULL if the conversion fails. */ -kwsysEXPORT char* kwsysEncoding_DupToNarrow(const wchar_t* str); - - -#if defined(__cplusplus) -} /* extern "C" */ -#endif - -/* If we are building a kwsys .c or .cxx file, let it use these macros. - Otherwise, undefine them to keep the namespace clean. */ -#if !defined(KWSYS_NAMESPACE) -# undef kwsys_ns -# undef kwsysEXPORT -# if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS -# undef kwsysEncoding -# undef kwsysEncoding_mbstowcs -# undef kwsysEncoding_DupToWide -# undef kwsysEncoding_wcstombs -# undef kwsysEncoding_DupToNarrow -# endif -#endif - -#endif diff --git a/src/kwsys/EncodingC.c b/src/kwsys/EncodingC.c deleted file mode 100644 index 32b9bff..0000000 --- a/src/kwsys/EncodingC.c +++ /dev/null @@ -1,85 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#include "kwsysPrivate.h" -#include KWSYS_HEADER(Encoding.h) - -/* Work-around CMake dependency scanning limitation. This must - duplicate the above list of headers. */ -#if 0 -# include "Encoding.h.in" -#endif - -#include - -#ifdef _WIN32 -#include -#endif - -size_t kwsysEncoding_mbstowcs(wchar_t* dest, const char* str, size_t n) -{ - if(str == 0) - { - return (size_t)-1; - } -#ifdef _WIN32 - return MultiByteToWideChar(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, - str, -1, dest, (int)n) - 1; -#else - return mbstowcs(dest, str, n); -#endif -} - -wchar_t* kwsysEncoding_DupToWide(const char* str) -{ - wchar_t* ret = NULL; - size_t length = kwsysEncoding_mbstowcs(NULL, str, 0) + 1; - if(length > 0) - { - ret = (wchar_t*)malloc((length)*sizeof(wchar_t)); - if(ret) - { - ret[0] = 0; - kwsysEncoding_mbstowcs(ret, str, length); - } - } - return ret; -} - -size_t kwsysEncoding_wcstombs(char* dest, const wchar_t* str, size_t n) -{ - if(str == 0) - { - return (size_t)-1; - } -#ifdef _WIN32 - return WideCharToMultiByte(KWSYS_ENCODING_DEFAULT_CODEPAGE, 0, str, -1, - dest, (int)n, NULL, NULL) - 1; -#else - return wcstombs(dest, str, n); -#endif -} - -char* kwsysEncoding_DupToNarrow(const wchar_t* str) -{ - char* ret = NULL; - size_t length = kwsysEncoding_wcstombs(0, str, 0) + 1; - if(length > 0) - { - ret = (char*)malloc(length); - if(ret) - { - ret[0] = 0; - kwsysEncoding_wcstombs(ret, str, length); - } - } - return ret; -} diff --git a/src/kwsys/Process.h.in b/src/kwsys/Process.h.in deleted file mode 100644 index c5ebc97..0000000 --- a/src/kwsys/Process.h.in +++ /dev/null @@ -1,462 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#ifndef @KWSYS_NAMESPACE@_Process_h -#define @KWSYS_NAMESPACE@_Process_h - -#include <@KWSYS_NAMESPACE@/Configure.h> - -/* Redefine all public interface symbol names to be in the proper - namespace. These macros are used internally to kwsys only, and are - not visible to user code. Use kwsysHeaderDump.pl to reproduce - these macros after making changes to the interface. */ -#if !defined(KWSYS_NAMESPACE) -# define kwsys_ns(x) @KWSYS_NAMESPACE@##x -# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT -#endif -#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS -# define kwsysProcess kwsys_ns(Process) -# define kwsysProcess_s kwsys_ns(Process_s) -# define kwsysProcess_New kwsys_ns(Process_New) -# define kwsysProcess_Delete kwsys_ns(Process_Delete) -# define kwsysProcess_SetCommand kwsys_ns(Process_SetCommand) -# define kwsysProcess_AddCommand kwsys_ns(Process_AddCommand) -# define kwsysProcess_SetTimeout kwsys_ns(Process_SetTimeout) -# define kwsysProcess_SetWorkingDirectory kwsys_ns(Process_SetWorkingDirectory) -# define kwsysProcess_SetPipeFile kwsys_ns(Process_SetPipeFile) -# define kwsysProcess_SetPipeNative kwsys_ns(Process_SetPipeNative) -# define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared) -# define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach) -# define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow) -# define kwsysProcess_Option_MergeOutput kwsys_ns(Process_Option_MergeOutput) -# define kwsysProcess_Option_Verbatim kwsys_ns(Process_Option_Verbatim) -# define kwsysProcess_Option_CreateProcessGroup kwsys_ns(Process_Option_CreateProcessGroup) -# define kwsysProcess_GetOption kwsys_ns(Process_GetOption) -# define kwsysProcess_SetOption kwsys_ns(Process_SetOption) -# define kwsysProcess_Option_e kwsys_ns(Process_Option_e) -# define kwsysProcess_State_Starting kwsys_ns(Process_State_Starting) -# define kwsysProcess_State_Error kwsys_ns(Process_State_Error) -# define kwsysProcess_State_Exception kwsys_ns(Process_State_Exception) -# define kwsysProcess_State_Executing kwsys_ns(Process_State_Executing) -# define kwsysProcess_State_Exited kwsys_ns(Process_State_Exited) -# define kwsysProcess_State_Expired kwsys_ns(Process_State_Expired) -# define kwsysProcess_State_Killed kwsys_ns(Process_State_Killed) -# define kwsysProcess_State_Disowned kwsys_ns(Process_State_Disowned) -# define kwsysProcess_GetState kwsys_ns(Process_GetState) -# define kwsysProcess_State_e kwsys_ns(Process_State_e) -# define kwsysProcess_Exception_None kwsys_ns(Process_Exception_None) -# define kwsysProcess_Exception_Fault kwsys_ns(Process_Exception_Fault) -# define kwsysProcess_Exception_Illegal kwsys_ns(Process_Exception_Illegal) -# define kwsysProcess_Exception_Interrupt kwsys_ns(Process_Exception_Interrupt) -# define kwsysProcess_Exception_Numerical kwsys_ns(Process_Exception_Numerical) -# define kwsysProcess_Exception_Other kwsys_ns(Process_Exception_Other) -# define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException) -# define kwsysProcess_Exception_e kwsys_ns(Process_Exception_e) -# define kwsysProcess_GetExitCode kwsys_ns(Process_GetExitCode) -# define kwsysProcess_GetExitValue kwsys_ns(Process_GetExitValue) -# define kwsysProcess_GetErrorString kwsys_ns(Process_GetErrorString) -# define kwsysProcess_GetExceptionString kwsys_ns(Process_GetExceptionString) -# define kwsysProcess_Execute kwsys_ns(Process_Execute) -# define kwsysProcess_Disown kwsys_ns(Process_Disown) -# define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData) -# define kwsysProcess_Pipes_e kwsys_ns(Process_Pipes_e) -# define kwsysProcess_Pipe_None kwsys_ns(Process_Pipe_None) -# define kwsysProcess_Pipe_STDIN kwsys_ns(Process_Pipe_STDIN) -# define kwsysProcess_Pipe_STDOUT kwsys_ns(Process_Pipe_STDOUT) -# define kwsysProcess_Pipe_STDERR kwsys_ns(Process_Pipe_STDERR) -# define kwsysProcess_Pipe_Timeout kwsys_ns(Process_Pipe_Timeout) -# define kwsysProcess_Pipe_Handle kwsys_ns(Process_Pipe_Handle) -# define kwsysProcess_WaitForExit kwsys_ns(Process_WaitForExit) -# define kwsysProcess_Interrupt kwsys_ns(Process_Interrupt) -# define kwsysProcess_Kill kwsys_ns(Process_Kill) -#endif - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/** - * Process control data structure. - */ -typedef struct kwsysProcess_s kwsysProcess; - -/* Platform-specific pipe handle type. */ -#if defined(_WIN32) && !defined(__CYGWIN__) -typedef void* kwsysProcess_Pipe_Handle; -#else -typedef int kwsysProcess_Pipe_Handle; -#endif - -/** - * Create a new Process instance. - */ -kwsysEXPORT kwsysProcess* kwsysProcess_New(void); - -/** - * Delete an existing Process instance. If the instance is currently - * executing a process, this blocks until the process terminates. - */ -kwsysEXPORT void kwsysProcess_Delete(kwsysProcess* cp); - -/** - * Set the command line to be executed. Argument is an array of - * pointers to the command and each argument. The array must end with - * a NULL pointer. Any previous command lines are removed. Returns - * 1 for success and 0 otherwise. - */ -kwsysEXPORT int kwsysProcess_SetCommand(kwsysProcess* cp, - char const* const* command); - -/** - * Add a command line to be executed. Argument is an array of - * pointers to the command and each argument. The array must end with - * a NULL pointer. If this is not the first command added, its - * standard input will be connected to the standard output of the - * previous command. Returns 1 for success and 0 otherwise. - */ -kwsysEXPORT int kwsysProcess_AddCommand(kwsysProcess* cp, - char const* const* command); - -/** - * Set the timeout in seconds for the child process. The timeout - * period begins when the child is executed. If the child has not - * terminated when the timeout expires, it will be killed. A - * non-positive (<= 0) value will disable the timeout. - */ -kwsysEXPORT void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout); - -/** - * Set the working directory for the child process. The working - * directory can be absolute or relative to the current directory. - * Returns 1 for success and 0 for failure. - */ -kwsysEXPORT int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, - const char* dir); - -/** - * Set the name of a file to be attached to the given pipe. Returns 1 - * for success and 0 for failure. - */ -kwsysEXPORT int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, - const char* file); - -/** - * Set whether the given pipe in the child is shared with the parent - * process. The default is no for Pipe_STDOUT and Pipe_STDERR and yes - * for Pipe_STDIN. - */ -kwsysEXPORT void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, - int shared); - -/** - * Specify a platform-specific native pipe for use as one of the child - * interface pipes. The native pipe is specified by an array of two - * descriptors or handles. The first entry in the array (index 0) - * should be the read end of the pipe. The second entry in the array - * (index 1) should be the write end of the pipe. If a null pointer - * is given the option will be disabled. - * - * For Pipe_STDIN the native pipe is connected to the first child in - * the pipeline as its stdin. After the children are created the - * write end of the pipe will be closed in the child process and the - * read end will be closed in the parent process. - * - * For Pipe_STDOUT and Pipe_STDERR the pipe is connected to the last - * child as its stdout or stderr. After the children are created the - * write end of the pipe will be closed in the parent process and the - * read end will be closed in the child process. - */ -kwsysEXPORT void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, - kwsysProcess_Pipe_Handle p[2]); - -/** - * Get/Set a possibly platform-specific option. Possible options are: - * - * kwsysProcess_Option_Detach = Whether to detach the process. - * 0 = No (default) - * 1 = Yes - * - * kwsysProcess_Option_HideWindow = Whether to hide window on Windows. - * 0 = No (default) - * 1 = Yes - * - * kwsysProcess_Option_MergeOutput = Whether to merge stdout/stderr. - * No content will be returned as stderr. - * Any actual stderr will be on stdout. - * 0 = No (default) - * 1 = Yes - * - * kwsysProcess_Option_Verbatim = Whether SetCommand and AddCommand - * should treat the first argument - * as a verbatim command line - * and ignore the rest of the arguments. - * 0 = No (default) - * 1 = Yes - * - * kwsysProcess_Option_CreateProcessGroup = Whether to place the process in a - * new process group. This is - * useful if you want to send Ctrl+C - * to the process. On UNIX, also - * places the process in a new - * session. - * 0 = No (default) - * 1 = Yes - */ -kwsysEXPORT int kwsysProcess_GetOption(kwsysProcess* cp, int optionId); -kwsysEXPORT void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, - int value); -enum kwsysProcess_Option_e -{ - kwsysProcess_Option_HideWindow, - kwsysProcess_Option_Detach, - kwsysProcess_Option_MergeOutput, - kwsysProcess_Option_Verbatim, - kwsysProcess_Option_CreateProcessGroup -}; - -/** - * Get the current state of the Process instance. Possible states are: - * - * kwsysProcess_State_Starting = Execute has not yet been called. - * kwsysProcess_State_Error = Error administrating the child process. - * kwsysProcess_State_Exception = Child process exited abnormally. - * kwsysProcess_State_Executing = Child process is currently running. - * kwsysProcess_State_Exited = Child process exited normally. - * kwsysProcess_State_Expired = Child process's timeout expired. - * kwsysProcess_State_Killed = Child process terminated by Kill method. - * kwsysProcess_State_Disowned = Child is no longer managed by this object. - */ -kwsysEXPORT int kwsysProcess_GetState(kwsysProcess* cp); -enum kwsysProcess_State_e -{ - kwsysProcess_State_Starting, - kwsysProcess_State_Error, - kwsysProcess_State_Exception, - kwsysProcess_State_Executing, - kwsysProcess_State_Exited, - kwsysProcess_State_Expired, - kwsysProcess_State_Killed, - kwsysProcess_State_Disowned -}; - -/** - * When GetState returns "Exception", this method returns a - * platform-independent description of the exceptional behavior that - * caused the child to terminate abnormally. Possible exceptions are: - * - * kwsysProcess_Exception_None = No exceptional behavior occurred. - * kwsysProcess_Exception_Fault = Child crashed with a memory fault. - * kwsysProcess_Exception_Illegal = Child crashed with an illegal instruction. - * kwsysProcess_Exception_Interrupt = Child was interrupted by user (Cntl-C/Break). - * kwsysProcess_Exception_Numerical = Child crashed with a numerical exception. - * kwsysProcess_Exception_Other = Child terminated for another reason. - */ -kwsysEXPORT int kwsysProcess_GetExitException(kwsysProcess* cp); -enum kwsysProcess_Exception_e -{ - kwsysProcess_Exception_None, - kwsysProcess_Exception_Fault, - kwsysProcess_Exception_Illegal, - kwsysProcess_Exception_Interrupt, - kwsysProcess_Exception_Numerical, - kwsysProcess_Exception_Other -}; - -/** - * When GetState returns "Exited" or "Exception", this method returns - * the platform-specific raw exit code of the process. UNIX platforms - * should use WIFEXITED/WEXITSTATUS and WIFSIGNALED/WTERMSIG to access - * this value. Windows users should compare the value to the various - * EXCEPTION_* values. - * - * If GetState returns "Exited", use GetExitValue to get the - * platform-independent child return value. - */ -kwsysEXPORT int kwsysProcess_GetExitCode(kwsysProcess* cp); - -/** - * When GetState returns "Exited", this method returns the child's - * platform-independent exit code (such as the value returned by the - * child's main). - */ -kwsysEXPORT int kwsysProcess_GetExitValue(kwsysProcess* cp); - -/** - * When GetState returns "Error", this method returns a string - * describing the problem. Otherwise, it returns NULL. - */ -kwsysEXPORT const char* kwsysProcess_GetErrorString(kwsysProcess* cp); - -/** - * When GetState returns "Exception", this method returns a string - * describing the problem. Otherwise, it returns NULL. - */ -kwsysEXPORT const char* kwsysProcess_GetExceptionString(kwsysProcess* cp); - -/** - * Start executing the child process. - */ -kwsysEXPORT void kwsysProcess_Execute(kwsysProcess* cp); - -/** - * Stop management of a detached child process. This closes any pipes - * being read. If the child was not created with the - * kwsysProcess_Option_Detach option, this method does nothing. This - * is because disowning a non-detached process will cause the child - * exit signal to be left unhandled until this process exits. - */ -kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp); - -/** - * Block until data are available on a pipe, a timeout expires, or the - * child process terminates. Arguments are as follows: - * - * data = If data are read, the pointer to which this points is - * set to point to the data. - * length = If data are read, the integer to which this points is - * set to the length of the data read. - * timeout = Specifies the maximum time this call may block. Upon - * return after reading data, the time elapsed is subtracted - * from the timeout value. If this timeout expires, the - * value is set to 0. A NULL pointer passed for this argument - * indicates no timeout for the call. A negative or zero - * value passed for this argument may be used for polling - * and will always return immediately. - * - * Return value will be one of: - * - * Pipe_None = No more data will be available from the child process, - * ( == 0) or no process has been executed. WaitForExit should - * be called to wait for the process to terminate. - * Pipe_STDOUT = Data have been read from the child's stdout pipe. - * Pipe_STDERR = Data have been read from the child's stderr pipe. - * Pipe_Timeout = No data available within timeout specified for the - * call. Time elapsed has been subtracted from timeout - * argument. - */ -kwsysEXPORT int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, - int* length, double* timeout); -enum kwsysProcess_Pipes_e -{ - kwsysProcess_Pipe_None, - kwsysProcess_Pipe_STDIN, - kwsysProcess_Pipe_STDOUT, - kwsysProcess_Pipe_STDERR, - kwsysProcess_Pipe_Timeout=255 -}; - -/** - * Block until the child process terminates or the given timeout - * expires. If no process is running, returns immediatly. The - * argument is: - * - * timeout = Specifies the maximum time this call may block. Upon - * returning due to child termination, the elapsed time - * is subtracted from the given value. A NULL pointer - * passed for this argument indicates no timeout for the - * call. - * - * Return value will be one of: - * - * 0 = Child did not terminate within timeout specified for - * the call. Time elapsed has been subtracted from timeout - * argument. - * 1 = Child has terminated or was not running. - */ -kwsysEXPORT int kwsysProcess_WaitForExit(kwsysProcess* cp, double* timeout); - -/** - * Interrupt the process group for the child process that is currently - * running by sending it the appropriate operating-system specific signal. - * The caller should call WaitForExit after this returns to wait for the - * child to terminate. - * - * WARNING: If you didn't specify kwsysProcess_Option_CreateProcessGroup, - * you will interrupt your own process group. - */ -kwsysEXPORT void kwsysProcess_Interrupt(kwsysProcess* cp); - -/** - * Forcefully terminate the child process that is currently running. - * The caller should call WaitForExit after this returns to wait for - * the child to terminate. - */ -kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp); - -#if defined(__cplusplus) -} /* extern "C" */ -#endif - -/* If we are building a kwsys .c or .cxx file, let it use these macros. - Otherwise, undefine them to keep the namespace clean. */ -#if !defined(KWSYS_NAMESPACE) -# undef kwsys_ns -# undef kwsysEXPORT -# if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS -# undef kwsysProcess -# undef kwsysProcess_s -# undef kwsysProcess_New -# undef kwsysProcess_Delete -# undef kwsysProcess_SetCommand -# undef kwsysProcess_AddCommand -# undef kwsysProcess_SetTimeout -# undef kwsysProcess_SetWorkingDirectory -# undef kwsysProcess_SetPipeFile -# undef kwsysProcess_SetPipeNative -# undef kwsysProcess_SetPipeShared -# undef kwsysProcess_Option_Detach -# undef kwsysProcess_Option_HideWindow -# undef kwsysProcess_Option_MergeOutput -# undef kwsysProcess_Option_Verbatim -# undef kwsysProcess_Option_CreateProcessGroup -# undef kwsysProcess_GetOption -# undef kwsysProcess_SetOption -# undef kwsysProcess_Option_e -# undef kwsysProcess_State_Starting -# undef kwsysProcess_State_Error -# undef kwsysProcess_State_Exception -# undef kwsysProcess_State_Executing -# undef kwsysProcess_State_Exited -# undef kwsysProcess_State_Expired -# undef kwsysProcess_State_Killed -# undef kwsysProcess_State_Disowned -# undef kwsysProcess_GetState -# undef kwsysProcess_State_e -# undef kwsysProcess_Exception_None -# undef kwsysProcess_Exception_Fault -# undef kwsysProcess_Exception_Illegal -# undef kwsysProcess_Exception_Interrupt -# undef kwsysProcess_Exception_Numerical -# undef kwsysProcess_Exception_Other -# undef kwsysProcess_GetExitException -# undef kwsysProcess_Exception_e -# undef kwsysProcess_GetExitCode -# undef kwsysProcess_GetExitValue -# undef kwsysProcess_GetErrorString -# undef kwsysProcess_GetExceptionString -# undef kwsysProcess_Execute -# undef kwsysProcess_Disown -# undef kwsysProcess_WaitForData -# undef kwsysProcess_Pipes_e -# undef kwsysProcess_Pipe_None -# undef kwsysProcess_Pipe_STDIN -# undef kwsysProcess_Pipe_STDOUT -# undef kwsysProcess_Pipe_STDERR -# undef kwsysProcess_Pipe_Timeout -# undef kwsysProcess_Pipe_Handle -# undef kwsysProcess_WaitForExit -# undef kwsysProcess_Interrupt -# undef kwsysProcess_Kill -# endif -#endif - -#endif diff --git a/src/kwsys/ProcessUNIX.c b/src/kwsys/ProcessUNIX.c deleted file mode 100644 index 6d9b109..0000000 --- a/src/kwsys/ProcessUNIX.c +++ /dev/null @@ -1,3058 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#include "kwsysPrivate.h" -#include KWSYS_HEADER(Process.h) -#include KWSYS_HEADER(System.h) - -/* Work-around CMake dependency scanning limitation. This must - duplicate the above list of headers. */ -#if 0 -# include "Process.h.in" -# include "System.h.in" -#endif - -/* - -Implementation for UNIX - -On UNIX, a child process is forked to exec the program. Three output -pipes are read by the parent process using a select call to block -until data are ready. Two of the pipes are stdout and stderr for the -child. The third is a special pipe populated by a signal handler to -indicate that a child has terminated. This is used in conjunction -with the timeout on the select call to implement a timeout for program -even when it closes stdout and stderr and at the same time avoiding -races. - -*/ - - -/* - -TODO: - -We cannot create the pipeline of processes in suspended states. How -do we cleanup processes already started when one fails to load? Right -now we are just killing them, which is probably not the right thing to -do. - -*/ - -#if defined(__CYGWIN__) -/* Increase the file descriptor limit for select() before including - related system headers. (Default: 64) */ -# define FD_SETSIZE 16384 -#endif - -#include /* ptrdiff_t */ -#include /* snprintf */ -#include /* malloc, free */ -#include /* strdup, strerror, memset */ -#include /* struct timeval */ -#include /* pid_t, fd_set */ -#include /* waitpid */ -#include /* open mode */ -#include /* pipe, close, fork, execvp, select, _exit */ -#include /* fcntl */ -#include /* errno */ -#include /* gettimeofday */ -#include /* sigaction */ -#include /* DIR, dirent */ -#include /* isspace */ -#include /* assert */ - -#if defined(__VMS) -# define KWSYSPE_VMS_NONBLOCK , O_NONBLOCK -#else -# define KWSYSPE_VMS_NONBLOCK -#endif - -#if defined(KWSYS_C_HAS_PTRDIFF_T) && KWSYS_C_HAS_PTRDIFF_T -typedef ptrdiff_t kwsysProcess_ptrdiff_t; -#else -typedef int kwsysProcess_ptrdiff_t; -#endif - -#if defined(KWSYS_C_HAS_SSIZE_T) && KWSYS_C_HAS_SSIZE_T -typedef ssize_t kwsysProcess_ssize_t; -#else -typedef int kwsysProcess_ssize_t; -#endif - -#if defined(__BEOS__) && !defined(__ZETA__) -/* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */ -# include -static inline void kwsysProcess_usleep(unsigned int msec) -{ - snooze(msec); -} -#else -# define kwsysProcess_usleep usleep -#endif - -/* - * BeOS's select() works like WinSock: it's for networking only, and - * doesn't work with Unix file handles...socket and file handles are - * different namespaces (the same descriptor means different things in - * each context!) - * - * So on Unix-like systems where select() is flakey, we'll set the - * pipes' file handles to be non-blocking and just poll them directly - * without select(). - */ -#if !defined(__BEOS__) && !defined(__VMS) && !defined(__MINT__) -# define KWSYSPE_USE_SELECT 1 -#endif - -/* Some platforms do not have siginfo on their signal handlers. */ -#if defined(SA_SIGINFO) && !defined(__BEOS__) -# define KWSYSPE_USE_SIGINFO 1 -#endif - -/* The number of pipes for the child's output. The standard stdout - and stderr pipes are the first two. One more pipe is used to - detect when the child process has terminated. The third pipe is - not given to the child process, so it cannot close it until it - terminates. */ -#define KWSYSPE_PIPE_COUNT 3 -#define KWSYSPE_PIPE_STDOUT 0 -#define KWSYSPE_PIPE_STDERR 1 -#define KWSYSPE_PIPE_SIGNAL 2 - -/* The maximum amount to read from a pipe at a time. */ -#define KWSYSPE_PIPE_BUFFER_SIZE 1024 - -/* Keep track of times using a signed representation. Switch to the - native (possibly unsigned) representation only when calling native - functions. */ -typedef struct timeval kwsysProcessTimeNative; -typedef struct kwsysProcessTime_s kwsysProcessTime; -struct kwsysProcessTime_s -{ - long tv_sec; - long tv_usec; -}; - -typedef struct kwsysProcessCreateInformation_s -{ - int StdIn; - int StdOut; - int StdErr; - int ErrorPipe[2]; -} kwsysProcessCreateInformation; - -/*--------------------------------------------------------------------------*/ -static void kwsysProcessVolatileFree(volatile void* p); -static int kwsysProcessInitialize(kwsysProcess* cp); -static void kwsysProcessCleanup(kwsysProcess* cp, int error); -static void kwsysProcessCleanupDescriptor(int* pfd); -static void kwsysProcessClosePipes(kwsysProcess* cp); -static int kwsysProcessSetNonBlocking(int fd); -static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, - kwsysProcessCreateInformation* si); -static void kwsysProcessDestroy(kwsysProcess* cp); -static int kwsysProcessSetupOutputPipeFile(int* p, const char* name); -static int kwsysProcessSetupOutputPipeNative(int* p, int des[2]); -static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, - kwsysProcessTime* timeoutTime); -static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, - double* userTimeout, - kwsysProcessTimeNative* timeoutLength, - int zeroIsExpired); -static kwsysProcessTime kwsysProcessTimeGetCurrent(void); -static double kwsysProcessTimeToDouble(kwsysProcessTime t); -static kwsysProcessTime kwsysProcessTimeFromDouble(double d); -static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2); -static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2); -static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2); -static void kwsysProcessSetExitException(kwsysProcess* cp, int sig); -static void kwsysProcessChildErrorExit(int errorPipe); -static void kwsysProcessRestoreDefaultSignalHandlers(void); -static pid_t kwsysProcessFork(kwsysProcess* cp, - kwsysProcessCreateInformation* si); -static void kwsysProcessKill(pid_t process_id); -#if defined(__VMS) -static int kwsysProcessSetVMSFeature(const char* name, int value); -#endif -static int kwsysProcessesAdd(kwsysProcess* cp); -static void kwsysProcessesRemove(kwsysProcess* cp); -#if KWSYSPE_USE_SIGINFO -static void kwsysProcessesSignalHandler(int signum, siginfo_t* info, - void* ucontext); -#else -static void kwsysProcessesSignalHandler(int signum); -#endif - -/*--------------------------------------------------------------------------*/ -/* Structure containing data used to implement the child's execution. */ -struct kwsysProcess_s -{ - /* The command lines to execute. */ - char*** Commands; - volatile int NumberOfCommands; - - /* Descriptors for the read ends of the child's output pipes and - the signal pipe. */ - int PipeReadEnds[KWSYSPE_PIPE_COUNT]; - - /* Descriptors for the child's ends of the pipes. - Used temporarily during process creation. */ - int PipeChildStd[3]; - - /* Write descriptor for child termination signal pipe. */ - int SignalPipe; - - /* Buffer for pipe data. */ - char PipeBuffer[KWSYSPE_PIPE_BUFFER_SIZE]; - - /* Process IDs returned by the calls to fork. Everything is volatile - because the signal handler accesses them. You must be very careful - when reaping PIDs or modifying this array to avoid race conditions. */ - volatile pid_t* volatile ForkPIDs; - - /* Flag for whether the children were terminated by a faild select. */ - int SelectError; - - /* The timeout length. */ - double Timeout; - - /* The working directory for the process. */ - char* WorkingDirectory; - - /* Whether to create the child as a detached process. */ - int OptionDetach; - - /* Whether the child was created as a detached process. */ - int Detached; - - /* Whether to treat command lines as verbatim. */ - int Verbatim; - - /* Whether to merge stdout/stderr of the child. */ - int MergeOutput; - - /* Whether to create the process in a new process group. */ - volatile sig_atomic_t CreateProcessGroup; - - /* Time at which the child started. Negative for no timeout. */ - kwsysProcessTime StartTime; - - /* Time at which the child will timeout. Negative for no timeout. */ - kwsysProcessTime TimeoutTime; - - /* Flag for whether the timeout expired. */ - int TimeoutExpired; - - /* The number of pipes left open during execution. */ - int PipesLeft; - -#if KWSYSPE_USE_SELECT - /* File descriptor set for call to select. */ - fd_set PipeSet; -#endif - - /* The number of children still executing. */ - int CommandsLeft; - - /* The current status of the child process. Must be atomic because - the signal handler checks this to avoid a race. */ - volatile sig_atomic_t State; - - /* The exceptional behavior that terminated the child process, if - * any. */ - int ExitException; - - /* The exit code of the child process. */ - int ExitCode; - - /* The exit value of the child process, if any. */ - int ExitValue; - - /* Whether the process was killed. */ - volatile sig_atomic_t Killed; - - /* Buffer for error message in case of failure. */ - char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1]; - - /* Description for the ExitException. */ - char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE+1]; - - /* The exit codes of each child process in the pipeline. */ - int* CommandExitCodes; - - /* Name of files to which stdin and stdout pipes are attached. */ - char* PipeFileSTDIN; - char* PipeFileSTDOUT; - char* PipeFileSTDERR; - - /* Whether each pipe is shared with the parent process. */ - int PipeSharedSTDIN; - int PipeSharedSTDOUT; - int PipeSharedSTDERR; - - /* Native pipes provided by the user. */ - int PipeNativeSTDIN[2]; - int PipeNativeSTDOUT[2]; - int PipeNativeSTDERR[2]; - - /* The real working directory of this process. */ - int RealWorkingDirectoryLength; - char* RealWorkingDirectory; -}; - -/*--------------------------------------------------------------------------*/ -kwsysProcess* kwsysProcess_New(void) -{ - /* Allocate a process control structure. */ - kwsysProcess* cp = (kwsysProcess*)malloc(sizeof(kwsysProcess)); - if(!cp) - { - return 0; - } - memset(cp, 0, sizeof(kwsysProcess)); - - /* Share stdin with the parent process by default. */ - cp->PipeSharedSTDIN = 1; - - /* No native pipes by default. */ - cp->PipeNativeSTDIN[0] = -1; - cp->PipeNativeSTDIN[1] = -1; - cp->PipeNativeSTDOUT[0] = -1; - cp->PipeNativeSTDOUT[1] = -1; - cp->PipeNativeSTDERR[0] = -1; - cp->PipeNativeSTDERR[1] = -1; - - /* Set initial status. */ - cp->State = kwsysProcess_State_Starting; - - return cp; -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_Delete(kwsysProcess* cp) -{ - /* Make sure we have an instance. */ - if(!cp) - { - return; - } - - /* If the process is executing, wait for it to finish. */ - if(cp->State == kwsysProcess_State_Executing) - { - if(cp->Detached) - { - kwsysProcess_Disown(cp); - } - else - { - kwsysProcess_WaitForExit(cp, 0); - } - } - - /* Free memory. */ - kwsysProcess_SetCommand(cp, 0); - kwsysProcess_SetWorkingDirectory(cp, 0); - kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0); - kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0); - kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0); - if(cp->CommandExitCodes) - { - free(cp->CommandExitCodes); - } - free(cp); -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command) -{ - int i; - if(!cp) - { - return 0; - } - for(i=0; i < cp->NumberOfCommands; ++i) - { - char** c = cp->Commands[i]; - while(*c) - { - free(*c++); - } - free(cp->Commands[i]); - } - cp->NumberOfCommands = 0; - if(cp->Commands) - { - free(cp->Commands); - cp->Commands = 0; - } - if(command) - { - return kwsysProcess_AddCommand(cp, command); - } - return 1; -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) -{ - int newNumberOfCommands; - char*** newCommands; - - /* Make sure we have a command to add. */ - if(!cp || !command || !*command) - { - return 0; - } - - /* Allocate a new array for command pointers. */ - newNumberOfCommands = cp->NumberOfCommands + 1; - if(!(newCommands = - (char***)malloc(sizeof(char**) *(size_t)(newNumberOfCommands)))) - { - /* Out of memory. */ - return 0; - } - - /* Copy any existing commands into the new array. */ - { - int i; - for(i=0; i < cp->NumberOfCommands; ++i) - { - newCommands[i] = cp->Commands[i]; - } - } - - /* Add the new command. */ - if(cp->Verbatim) - { - /* In order to run the given command line verbatim we need to - parse it. */ - newCommands[cp->NumberOfCommands] = - kwsysSystem_Parse_CommandForUnix(*command, 0); - if(!newCommands[cp->NumberOfCommands] || - !newCommands[cp->NumberOfCommands][0]) - { - /* Out of memory or no command parsed. */ - free(newCommands); - return 0; - } - } - else - { - /* Copy each argument string individually. */ - char const* const* c = command; - kwsysProcess_ptrdiff_t n = 0; - kwsysProcess_ptrdiff_t i = 0; - while(*c++); - n = c - command - 1; - newCommands[cp->NumberOfCommands] = - (char**)malloc((size_t)(n+1)*sizeof(char*)); - if(!newCommands[cp->NumberOfCommands]) - { - /* Out of memory. */ - free(newCommands); - return 0; - } - for(i=0; i < n; ++i) - { - assert(command[i]); /* Quiet Clang scan-build. */ - newCommands[cp->NumberOfCommands][i] = strdup(command[i]); - if(!newCommands[cp->NumberOfCommands][i]) - { - break; - } - } - if(i < n) - { - /* Out of memory. */ - for(;i > 0; --i) - { - free(newCommands[cp->NumberOfCommands][i-1]); - } - free(newCommands); - return 0; - } - newCommands[cp->NumberOfCommands][n] = 0; - } - - /* Successfully allocated new command array. Free the old array. */ - free(cp->Commands); - cp->Commands = newCommands; - cp->NumberOfCommands = newNumberOfCommands; - - return 1; -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout) -{ - if(!cp) - { - return; - } - cp->Timeout = timeout; - if(cp->Timeout < 0) - { - cp->Timeout = 0; - } -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir) -{ - if(!cp) - { - return 0; - } - if(cp->WorkingDirectory == dir) - { - return 1; - } - if(cp->WorkingDirectory && dir && strcmp(cp->WorkingDirectory, dir) == 0) - { - return 1; - } - if(cp->WorkingDirectory) - { - free(cp->WorkingDirectory); - cp->WorkingDirectory = 0; - } - if(dir) - { - cp->WorkingDirectory = (char*)malloc(strlen(dir) + 1); - if(!cp->WorkingDirectory) - { - return 0; - } - strcpy(cp->WorkingDirectory, dir); - } - return 1; -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_SetPipeFile(kwsysProcess* cp, int prPipe, const char* file) -{ - char** pfile; - if(!cp) - { - return 0; - } - switch(prPipe) - { - case kwsysProcess_Pipe_STDIN: pfile = &cp->PipeFileSTDIN; break; - case kwsysProcess_Pipe_STDOUT: pfile = &cp->PipeFileSTDOUT; break; - case kwsysProcess_Pipe_STDERR: pfile = &cp->PipeFileSTDERR; break; - default: return 0; - } - if(*pfile) - { - free(*pfile); - *pfile = 0; - } - if(file) - { - *pfile = (char*)malloc(strlen(file)+1); - if(!*pfile) - { - return 0; - } - strcpy(*pfile, file); - } - - /* If we are redirecting the pipe, do not share it or use a native - pipe. */ - if(*pfile) - { - kwsysProcess_SetPipeNative(cp, prPipe, 0); - kwsysProcess_SetPipeShared(cp, prPipe, 0); - } - return 1; -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_SetPipeShared(kwsysProcess* cp, int prPipe, int shared) -{ - if(!cp) - { - return; - } - - switch(prPipe) - { - case kwsysProcess_Pipe_STDIN: cp->PipeSharedSTDIN = shared?1:0; break; - case kwsysProcess_Pipe_STDOUT: cp->PipeSharedSTDOUT = shared?1:0; break; - case kwsysProcess_Pipe_STDERR: cp->PipeSharedSTDERR = shared?1:0; break; - default: return; - } - - /* If we are sharing the pipe, do not redirect it to a file or use a - native pipe. */ - if(shared) - { - kwsysProcess_SetPipeFile(cp, prPipe, 0); - kwsysProcess_SetPipeNative(cp, prPipe, 0); - } -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_SetPipeNative(kwsysProcess* cp, int prPipe, int p[2]) -{ - int* pPipeNative = 0; - - if(!cp) - { - return; - } - - switch(prPipe) - { - case kwsysProcess_Pipe_STDIN: pPipeNative = cp->PipeNativeSTDIN; break; - case kwsysProcess_Pipe_STDOUT: pPipeNative = cp->PipeNativeSTDOUT; break; - case kwsysProcess_Pipe_STDERR: pPipeNative = cp->PipeNativeSTDERR; break; - default: return; - } - - /* Copy the native pipe descriptors provided. */ - if(p) - { - pPipeNative[0] = p[0]; - pPipeNative[1] = p[1]; - } - else - { - pPipeNative[0] = -1; - pPipeNative[1] = -1; - } - - /* If we are using a native pipe, do not share it or redirect it to - a file. */ - if(p) - { - kwsysProcess_SetPipeFile(cp, prPipe, 0); - kwsysProcess_SetPipeShared(cp, prPipe, 0); - } -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) -{ - if(!cp) - { - return 0; - } - - switch(optionId) - { - case kwsysProcess_Option_Detach: return cp->OptionDetach; - case kwsysProcess_Option_MergeOutput: return cp->MergeOutput; - case kwsysProcess_Option_Verbatim: return cp->Verbatim; - case kwsysProcess_Option_CreateProcessGroup: - return cp->CreateProcessGroup; - default: return 0; - } -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) -{ - if(!cp) - { - return; - } - - switch(optionId) - { - case kwsysProcess_Option_Detach: cp->OptionDetach = value; break; - case kwsysProcess_Option_MergeOutput: cp->MergeOutput = value; break; - case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break; - case kwsysProcess_Option_CreateProcessGroup: - cp->CreateProcessGroup = value; break; - default: break; - } -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_GetState(kwsysProcess* cp) -{ - return cp? cp->State : kwsysProcess_State_Error; -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_GetExitException(kwsysProcess* cp) -{ - return cp? cp->ExitException : kwsysProcess_Exception_Other; -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_GetExitCode(kwsysProcess* cp) -{ - return cp? cp->ExitCode : 0; -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_GetExitValue(kwsysProcess* cp) -{ - return cp? cp->ExitValue : -1; -} - -/*--------------------------------------------------------------------------*/ -const char* kwsysProcess_GetErrorString(kwsysProcess* cp) -{ - if(!cp) - { - return "Process management structure could not be allocated"; - } - else if(cp->State == kwsysProcess_State_Error) - { - return cp->ErrorMessage; - } - return "Success"; -} - -/*--------------------------------------------------------------------------*/ -const char* kwsysProcess_GetExceptionString(kwsysProcess* cp) -{ - if(!cp) - { - return "GetExceptionString called with NULL process management structure"; - } - else if(cp->State == kwsysProcess_State_Exception) - { - return cp->ExitExceptionString; - } - return "No exception"; -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_Execute(kwsysProcess* cp) -{ - int i; - - /* Do not execute a second copy simultaneously. */ - if(!cp || cp->State == kwsysProcess_State_Executing) - { - return; - } - - /* Make sure we have something to run. */ - if(cp->NumberOfCommands < 1) - { - strcpy(cp->ErrorMessage, "No command"); - cp->State = kwsysProcess_State_Error; - return; - } - - /* Initialize the control structure for a new process. */ - if(!kwsysProcessInitialize(cp)) - { - strcpy(cp->ErrorMessage, "Out of memory"); - cp->State = kwsysProcess_State_Error; - return; - } - -#if defined(__VMS) - /* Make sure pipes behave like streams on VMS. */ - if(!kwsysProcessSetVMSFeature("DECC$STREAM_PIPE", 1)) - { - kwsysProcessCleanup(cp, 1); - return; - } -#endif - - /* Save the real working directory of this process and change to - the working directory for the child processes. This is needed - to make pipe file paths evaluate correctly. */ - if(cp->WorkingDirectory) - { - int r; - if(!getcwd(cp->RealWorkingDirectory, - (size_t)(cp->RealWorkingDirectoryLength))) - { - kwsysProcessCleanup(cp, 1); - return; - } - - /* Some platforms specify that the chdir call may be - interrupted. Repeat the call until it finishes. */ - while(((r = chdir(cp->WorkingDirectory)) < 0) && (errno == EINTR)); - if(r < 0) - { - kwsysProcessCleanup(cp, 1); - return; - } - } - - /* If not running a detached child, add this object to the global - set of process objects that wish to be notified when a child - exits. */ - if(!cp->OptionDetach) - { - if(!kwsysProcessesAdd(cp)) - { - kwsysProcessCleanup(cp, 1); - return; - } - } - - /* Setup the stdin pipe for the first process. */ - if(cp->PipeFileSTDIN) - { - /* Open a file for the child's stdin to read. */ - cp->PipeChildStd[0] = open(cp->PipeFileSTDIN, O_RDONLY); - if(cp->PipeChildStd[0] < 0) - { - kwsysProcessCleanup(cp, 1); - return; - } - - /* Set close-on-exec flag on the pipe's end. */ - if(fcntl(cp->PipeChildStd[0], F_SETFD, FD_CLOEXEC) < 0) - { - kwsysProcessCleanup(cp, 1); - return; - } - } - else if(cp->PipeSharedSTDIN) - { - cp->PipeChildStd[0] = 0; - } - else if(cp->PipeNativeSTDIN[0] >= 0) - { - cp->PipeChildStd[0] = cp->PipeNativeSTDIN[0]; - - /* Set close-on-exec flag on the pipe's ends. The read end will - be dup2-ed into the stdin descriptor after the fork but before - the exec. */ - if((fcntl(cp->PipeNativeSTDIN[0], F_SETFD, FD_CLOEXEC) < 0) || - (fcntl(cp->PipeNativeSTDIN[1], F_SETFD, FD_CLOEXEC) < 0)) - { - kwsysProcessCleanup(cp, 1); - return; - } - } - else - { - cp->PipeChildStd[0] = -1; - } - - /* Create the output pipe for the last process. - We always create this so the pipe can be passed to select even if - it will report closed immediately. */ - { - /* Create the pipe. */ - int p[2]; - if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0) - { - kwsysProcessCleanup(cp, 1); - return; - } - - /* Store the pipe. */ - cp->PipeReadEnds[KWSYSPE_PIPE_STDOUT] = p[0]; - cp->PipeChildStd[1] = p[1]; - - /* Set close-on-exec flag on the pipe's ends. */ - if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || - (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) - { - kwsysProcessCleanup(cp, 1); - return; - } - - /* Set to non-blocking in case select lies, or for the polling - implementation. */ - if(!kwsysProcessSetNonBlocking(p[0])) - { - kwsysProcessCleanup(cp, 1); - return; - } - } - - if (cp->PipeFileSTDOUT) - { - /* Use a file for stdout. */ - if(!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[1], - cp->PipeFileSTDOUT)) - { - kwsysProcessCleanup(cp, 1); - return; - } - } - else if (cp->PipeSharedSTDOUT) - { - /* Use the parent stdout. */ - kwsysProcessCleanupDescriptor(&cp->PipeChildStd[1]); - cp->PipeChildStd[1] = 1; - } - else if (cp->PipeNativeSTDOUT[1] >= 0) - { - /* Use the given descriptor for stdout. */ - if(!kwsysProcessSetupOutputPipeNative(&cp->PipeChildStd[1], - cp->PipeNativeSTDOUT)) - { - kwsysProcessCleanup(cp, 1); - return; - } - } - - /* Create stderr pipe to be shared by all processes in the pipeline. - We always create this so the pipe can be passed to select even if - it will report closed immediately. */ - { - /* Create the pipe. */ - int p[2]; - if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0) - { - kwsysProcessCleanup(cp, 1); - return; - } - - /* Store the pipe. */ - cp->PipeReadEnds[KWSYSPE_PIPE_STDERR] = p[0]; - cp->PipeChildStd[2] = p[1]; - - /* Set close-on-exec flag on the pipe's ends. */ - if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || - (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) - { - kwsysProcessCleanup(cp, 1); - return; - } - - /* Set to non-blocking in case select lies, or for the polling - implementation. */ - if(!kwsysProcessSetNonBlocking(p[0])) - { - kwsysProcessCleanup(cp, 1); - return; - } - } - - if (cp->PipeFileSTDERR) - { - /* Use a file for stderr. */ - if(!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[2], - cp->PipeFileSTDERR)) - { - kwsysProcessCleanup(cp, 1); - return; - } - } - else if (cp->PipeSharedSTDERR) - { - /* Use the parent stderr. */ - kwsysProcessCleanupDescriptor(&cp->PipeChildStd[2]); - cp->PipeChildStd[2] = 2; - } - else if (cp->PipeNativeSTDERR[1] >= 0) - { - /* Use the given handle for stderr. */ - if(!kwsysProcessSetupOutputPipeNative(&cp->PipeChildStd[2], - cp->PipeNativeSTDERR)) - { - kwsysProcessCleanup(cp, 1); - return; - } - } - - /* The timeout period starts now. */ - cp->StartTime = kwsysProcessTimeGetCurrent(); - cp->TimeoutTime.tv_sec = -1; - cp->TimeoutTime.tv_usec = -1; - - /* Create the pipeline of processes. */ - { - kwsysProcessCreateInformation si = {-1, -1, -1, {-1, -1}}; - int nextStdIn = cp->PipeChildStd[0]; - for(i=0; i < cp->NumberOfCommands; ++i) - { - /* Setup the process's pipes. */ - si.StdIn = nextStdIn; - if (i == cp->NumberOfCommands-1) - { - nextStdIn = -1; - si.StdOut = cp->PipeChildStd[1]; - } - else - { - /* Create a pipe to sit between the children. */ - int p[2] = {-1,-1}; - if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0) - { - if (nextStdIn != cp->PipeChildStd[0]) - { - kwsysProcessCleanupDescriptor(&nextStdIn); - } - kwsysProcessCleanup(cp, 1); - return; - } - - /* Set close-on-exec flag on the pipe's ends. */ - if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || - (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) - { - close(p[0]); - close(p[1]); - if (nextStdIn != cp->PipeChildStd[0]) - { - kwsysProcessCleanupDescriptor(&nextStdIn); - } - kwsysProcessCleanup(cp, 1); - return; - } - nextStdIn = p[0]; - si.StdOut = p[1]; - } - si.StdErr = cp->MergeOutput? cp->PipeChildStd[1] : cp->PipeChildStd[2]; - - { - int res = kwsysProcessCreate(cp, i, &si); - - /* Close our copies of pipes used between children. */ - if (si.StdIn != cp->PipeChildStd[0]) - { - kwsysProcessCleanupDescriptor(&si.StdIn); - } - if (si.StdOut != cp->PipeChildStd[1]) - { - kwsysProcessCleanupDescriptor(&si.StdOut); - } - if (si.StdErr != cp->PipeChildStd[2] && !cp->MergeOutput) - { - kwsysProcessCleanupDescriptor(&si.StdErr); - } - - if(!res) - { - kwsysProcessCleanupDescriptor(&si.ErrorPipe[0]); - kwsysProcessCleanupDescriptor(&si.ErrorPipe[1]); - if (nextStdIn != cp->PipeChildStd[0]) - { - kwsysProcessCleanupDescriptor(&nextStdIn); - } - kwsysProcessCleanup(cp, 1); - return; - } - } - } - } - - /* The parent process does not need the child's pipe ends. */ - for (i=0; i < 3; ++i) - { - kwsysProcessCleanupDescriptor(&cp->PipeChildStd[i]); - } - - /* Restore the working directory. */ - if(cp->RealWorkingDirectory) - { - /* Some platforms specify that the chdir call may be - interrupted. Repeat the call until it finishes. */ - while((chdir(cp->RealWorkingDirectory) < 0) && (errno == EINTR)); - free(cp->RealWorkingDirectory); - cp->RealWorkingDirectory = 0; - } - - /* All the pipes are now open. */ - cp->PipesLeft = KWSYSPE_PIPE_COUNT; - - /* The process has now started. */ - cp->State = kwsysProcess_State_Executing; - cp->Detached = cp->OptionDetach; -} - -/*--------------------------------------------------------------------------*/ -kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp) -{ - /* Make sure a detached child process is running. */ - if(!cp || !cp->Detached || cp->State != kwsysProcess_State_Executing || - cp->TimeoutExpired || cp->Killed) - { - return; - } - - /* Close all the pipes safely. */ - kwsysProcessClosePipes(cp); - - /* We will not wait for exit, so cleanup now. */ - kwsysProcessCleanup(cp, 0); - - /* The process has been disowned. */ - cp->State = kwsysProcess_State_Disowned; -} - -/*--------------------------------------------------------------------------*/ -typedef struct kwsysProcessWaitData_s -{ - int Expired; - int PipeId; - int User; - double* UserTimeout; - kwsysProcessTime TimeoutTime; -} kwsysProcessWaitData; -static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length, - kwsysProcessWaitData* wd); - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length, - double* userTimeout) -{ - kwsysProcessTime userStartTime = {0, 0}; - kwsysProcessWaitData wd = - { - 0, - kwsysProcess_Pipe_None, - 0, - 0, - {0, 0} - }; - wd.UserTimeout = userTimeout; - /* Make sure we are executing a process. */ - if(!cp || cp->State != kwsysProcess_State_Executing || cp->Killed || - cp->TimeoutExpired) - { - return kwsysProcess_Pipe_None; - } - - /* Record the time at which user timeout period starts. */ - if(userTimeout) - { - userStartTime = kwsysProcessTimeGetCurrent(); - } - - /* Calculate the time at which a timeout will expire, and whether it - is the user or process timeout. */ - wd.User = kwsysProcessGetTimeoutTime(cp, userTimeout, - &wd.TimeoutTime); - - /* Data can only be available when pipes are open. If the process - is not running, cp->PipesLeft will be 0. */ - while(cp->PipesLeft > 0 && - !kwsysProcessWaitForPipe(cp, data, length, &wd)) {} - - /* Update the user timeout. */ - if(userTimeout) - { - kwsysProcessTime userEndTime = kwsysProcessTimeGetCurrent(); - kwsysProcessTime difference = kwsysProcessTimeSubtract(userEndTime, - userStartTime); - double d = kwsysProcessTimeToDouble(difference); - *userTimeout -= d; - if(*userTimeout < 0) - { - *userTimeout = 0; - } - } - - /* Check what happened. */ - if(wd.PipeId) - { - /* Data are ready on a pipe. */ - return wd.PipeId; - } - else if(wd.Expired) - { - /* A timeout has expired. */ - if(wd.User) - { - /* The user timeout has expired. It has no time left. */ - return kwsysProcess_Pipe_Timeout; - } - else - { - /* The process timeout has expired. Kill the children now. */ - kwsysProcess_Kill(cp); - cp->Killed = 0; - cp->TimeoutExpired = 1; - return kwsysProcess_Pipe_None; - } - } - else - { - /* No pipes are left open. */ - return kwsysProcess_Pipe_None; - } -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length, - kwsysProcessWaitData* wd) -{ - int i; - kwsysProcessTimeNative timeoutLength; - -#if KWSYSPE_USE_SELECT - int numReady = 0; - int max = -1; - kwsysProcessTimeNative* timeout = 0; - - /* Check for any open pipes with data reported ready by the last - call to select. According to "man select_tut" we must deal - with all descriptors reported by a call to select before - passing them to another select call. */ - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - if(cp->PipeReadEnds[i] >= 0 && - FD_ISSET(cp->PipeReadEnds[i], &cp->PipeSet)) - { - kwsysProcess_ssize_t n; - - /* We are handling this pipe now. Remove it from the set. */ - FD_CLR(cp->PipeReadEnds[i], &cp->PipeSet); - - /* The pipe is ready to read without blocking. Keep trying to - read until the operation is not interrupted. */ - while(((n = read(cp->PipeReadEnds[i], cp->PipeBuffer, - KWSYSPE_PIPE_BUFFER_SIZE)) < 0) && (errno == EINTR)); - if(n > 0) - { - /* We have data on this pipe. */ - if(i == KWSYSPE_PIPE_SIGNAL) - { - /* A child process has terminated. */ - kwsysProcessDestroy(cp); - } - else if(data && length) - { - /* Report this data. */ - *data = cp->PipeBuffer; - *length = (int)(n); - switch(i) - { - case KWSYSPE_PIPE_STDOUT: - wd->PipeId = kwsysProcess_Pipe_STDOUT; break; - case KWSYSPE_PIPE_STDERR: - wd->PipeId = kwsysProcess_Pipe_STDERR; break; - }; - return 1; - } - } - else if(n < 0 && errno == EAGAIN) - { - /* No data are really ready. The select call lied. See the - "man select" page on Linux for cases when this occurs. */ - } - else - { - /* We are done reading from this pipe. */ - kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); - --cp->PipesLeft; - } - } - } - - /* If we have data, break early. */ - if(wd->PipeId) - { - return 1; - } - - /* Make sure the set is empty (it should always be empty here - anyway). */ - FD_ZERO(&cp->PipeSet); - - /* Setup a timeout if required. */ - if(wd->TimeoutTime.tv_sec < 0) - { - timeout = 0; - } - else - { - timeout = &timeoutLength; - } - if(kwsysProcessGetTimeoutLeft(&wd->TimeoutTime, - wd->User?wd->UserTimeout:0, - &timeoutLength, 0)) - { - /* Timeout has already expired. */ - wd->Expired = 1; - return 1; - } - - /* Add the pipe reading ends that are still open. */ - max = -1; - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - if(cp->PipeReadEnds[i] >= 0) - { - FD_SET(cp->PipeReadEnds[i], &cp->PipeSet); - if(cp->PipeReadEnds[i] > max) - { - max = cp->PipeReadEnds[i]; - } - } - } - - /* Make sure we have a non-empty set. */ - if(max < 0) - { - /* All pipes have closed. Child has terminated. */ - return 1; - } - - /* Run select to block until data are available. Repeat call - until it is not interrupted. */ - while(((numReady = select(max+1, &cp->PipeSet, 0, 0, timeout)) < 0) && - (errno == EINTR)); - - /* Check result of select. */ - if(numReady == 0) - { - /* Select's timeout expired. */ - wd->Expired = 1; - return 1; - } - else if(numReady < 0) - { - /* Select returned an error. Leave the error description in the - pipe buffer. */ - strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE); - - /* Kill the children now. */ - kwsysProcess_Kill(cp); - cp->Killed = 0; - cp->SelectError = 1; - } - - return 0; -#else - /* Poll pipes for data since we do not have select. */ - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - if(cp->PipeReadEnds[i] >= 0) - { - const int fd = cp->PipeReadEnds[i]; - int n = read(fd, cp->PipeBuffer, KWSYSPE_PIPE_BUFFER_SIZE); - if(n > 0) - { - /* We have data on this pipe. */ - if(i == KWSYSPE_PIPE_SIGNAL) - { - /* A child process has terminated. */ - kwsysProcessDestroy(cp); - } - else if(data && length) - { - /* Report this data. */ - *data = cp->PipeBuffer; - *length = n; - switch(i) - { - case KWSYSPE_PIPE_STDOUT: - wd->PipeId = kwsysProcess_Pipe_STDOUT; break; - case KWSYSPE_PIPE_STDERR: - wd->PipeId = kwsysProcess_Pipe_STDERR; break; - }; - } - return 1; - } - else if (n == 0) /* EOF */ - { - /* We are done reading from this pipe. */ -#if defined(__VMS) - if(!cp->CommandsLeft) -#endif - { - kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); - --cp->PipesLeft; - } - } - else if (n < 0) /* error */ - { -#if defined(__VMS) - if(!cp->CommandsLeft) - { - kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); - --cp->PipesLeft; - } - else -#endif - if((errno != EINTR) && (errno != EAGAIN)) - { - strncpy(cp->ErrorMessage,strerror(errno), - KWSYSPE_PIPE_BUFFER_SIZE); - /* Kill the children now. */ - kwsysProcess_Kill(cp); - cp->Killed = 0; - cp->SelectError = 1; - return 1; - } - } - } - } - - /* If we have data, break early. */ - if(wd->PipeId) - { - return 1; - } - - if(kwsysProcessGetTimeoutLeft(&wd->TimeoutTime, wd->User?wd->UserTimeout:0, - &timeoutLength, 1)) - { - /* Timeout has already expired. */ - wd->Expired = 1; - return 1; - } - - /* Sleep a little, try again. */ - { - unsigned int msec = ((timeoutLength.tv_sec * 1000) + - (timeoutLength.tv_usec / 1000)); - if (msec > 100000) - { - msec = 100000; /* do not sleep more than 100 milliseconds at a time */ - } - kwsysProcess_usleep(msec); - } - return 0; -#endif -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) -{ - int status = 0; - int prPipe = 0; - - /* Make sure we are executing a process. */ - if(!cp || cp->State != kwsysProcess_State_Executing) - { - return 1; - } - - /* Wait for all the pipes to close. Ignore all data. */ - while((prPipe = kwsysProcess_WaitForData(cp, 0, 0, userTimeout)) > 0) - { - if(prPipe == kwsysProcess_Pipe_Timeout) - { - return 0; - } - } - - /* Check if there was an error in one of the waitpid calls. */ - if(cp->State == kwsysProcess_State_Error) - { - /* The error message is already in its buffer. Tell - kwsysProcessCleanup to not create it. */ - kwsysProcessCleanup(cp, 0); - return 1; - } - - /* Check whether the child reported an error invoking the process. */ - if(cp->SelectError) - { - /* The error message is already in its buffer. Tell - kwsysProcessCleanup to not create it. */ - kwsysProcessCleanup(cp, 0); - cp->State = kwsysProcess_State_Error; - return 1; - } - - /* Use the status of the last process in the pipeline. */ - status = cp->CommandExitCodes[cp->NumberOfCommands-1]; - - /* Determine the outcome. */ - if(cp->Killed) - { - /* We killed the child. */ - cp->State = kwsysProcess_State_Killed; - } - else if(cp->TimeoutExpired) - { - /* The timeout expired. */ - cp->State = kwsysProcess_State_Expired; - } - else if(WIFEXITED(status)) - { - /* The child exited normally. */ - cp->State = kwsysProcess_State_Exited; - cp->ExitException = kwsysProcess_Exception_None; - cp->ExitCode = status; - cp->ExitValue = (int)WEXITSTATUS(status); - } - else if(WIFSIGNALED(status)) - { - /* The child received an unhandled signal. */ - cp->State = kwsysProcess_State_Exception; - cp->ExitCode = status; - kwsysProcessSetExitException(cp, (int)WTERMSIG(status)); - } - else - { - /* Error getting the child return code. */ - strcpy(cp->ErrorMessage, "Error getting child return code."); - cp->State = kwsysProcess_State_Error; - } - - /* Normal cleanup. */ - kwsysProcessCleanup(cp, 0); - return 1; -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_Interrupt(kwsysProcess* cp) -{ - int i; - /* Make sure we are executing a process. */ - if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired || - cp->Killed) - { - return; - } - - /* Interrupt the children. */ - if (cp->CreateProcessGroup) - { - if(cp->ForkPIDs) - { - for(i=0; i < cp->NumberOfCommands; ++i) - { - /* Make sure the PID is still valid. */ - if(cp->ForkPIDs[i]) - { - /* The user created a process group for this process. The group ID - is the process ID for the original process in the group. */ - kill(-cp->ForkPIDs[i], SIGINT); - } - } - } - } - else - { - /* No process group was created. Kill our own process group. - NOTE: While one could argue that we could call kill(cp->ForkPIDs[i], - SIGINT) as a way to still interrupt the process even though it's not in - a special group, this is not an option on Windows. Therefore, we kill - the current process group for consistency with Windows. */ - kill(0, SIGINT); - } -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_Kill(kwsysProcess* cp) -{ - int i; - - /* Make sure we are executing a process. */ - if(!cp || cp->State != kwsysProcess_State_Executing) - { - return; - } - - /* First close the child exit report pipe write end to avoid causing a - SIGPIPE when the child terminates and our signal handler tries to - report it after we have already closed the read end. */ - kwsysProcessCleanupDescriptor(&cp->SignalPipe); - -#if !defined(__APPLE__) - /* Close all the pipe read ends. Do this before killing the - children because Cygwin has problems killing processes that are - blocking to wait for writing to their output pipes. */ - kwsysProcessClosePipes(cp); -#endif - - /* Kill the children. */ - cp->Killed = 1; - for(i=0; i < cp->NumberOfCommands; ++i) - { - int status; - if(cp->ForkPIDs[i]) - { - /* Kill the child. */ - kwsysProcessKill(cp->ForkPIDs[i]); - - /* Reap the child. Keep trying until the call is not - interrupted. */ - while((waitpid(cp->ForkPIDs[i], &status, 0) < 0) && (errno == EINTR)); - } - } - -#if defined(__APPLE__) - /* Close all the pipe read ends. Do this after killing the - children because OS X has problems closing pipe read ends whose - pipes are full and still have an open write end. */ - kwsysProcessClosePipes(cp); -#endif - - cp->CommandsLeft = 0; -} - -/*--------------------------------------------------------------------------*/ -/* Call the free() function with a pointer to volatile without causing - compiler warnings. */ -static void kwsysProcessVolatileFree(volatile void* p) -{ - /* clang has made it impossible to free memory that points to volatile - without first using special pragmas to disable a warning... */ -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wcast-qual" -#endif - free((void*)p); /* The cast will silence most compilers, but not clang. */ -#if defined(__clang__) -# pragma clang diagnostic pop -#endif -} - -/*--------------------------------------------------------------------------*/ -/* Initialize a process control structure for kwsysProcess_Execute. */ -static int kwsysProcessInitialize(kwsysProcess* cp) -{ - int i; - volatile pid_t* oldForkPIDs; - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - cp->PipeReadEnds[i] = -1; - } - for(i=0; i < 3; ++i) - { - cp->PipeChildStd[i] = -1; - } - cp->SignalPipe = -1; - cp->SelectError = 0; - cp->StartTime.tv_sec = -1; - cp->StartTime.tv_usec = -1; - cp->TimeoutTime.tv_sec = -1; - cp->TimeoutTime.tv_usec = -1; - cp->TimeoutExpired = 0; - cp->PipesLeft = 0; - cp->CommandsLeft = 0; -#if KWSYSPE_USE_SELECT - FD_ZERO(&cp->PipeSet); -#endif - cp->State = kwsysProcess_State_Starting; - cp->Killed = 0; - cp->ExitException = kwsysProcess_Exception_None; - cp->ExitCode = 1; - cp->ExitValue = 1; - cp->ErrorMessage[0] = 0; - strcpy(cp->ExitExceptionString, "No exception"); - - oldForkPIDs = cp->ForkPIDs; - cp->ForkPIDs = (volatile pid_t*)malloc( - sizeof(volatile pid_t)*(size_t)(cp->NumberOfCommands)); - if(oldForkPIDs) - { - kwsysProcessVolatileFree(oldForkPIDs); - } - if(!cp->ForkPIDs) - { - return 0; - } - for(i=0; i < cp->NumberOfCommands; ++i) - { - cp->ForkPIDs[i] = 0; /* can't use memset due to volatile */ - } - - if(cp->CommandExitCodes) - { - free(cp->CommandExitCodes); - } - cp->CommandExitCodes = (int*)malloc(sizeof(int)* - (size_t)(cp->NumberOfCommands)); - if(!cp->CommandExitCodes) - { - return 0; - } - memset(cp->CommandExitCodes, 0, sizeof(int)*(size_t)(cp->NumberOfCommands)); - - /* Allocate memory to save the real working directory. */ - if ( cp->WorkingDirectory ) - { -#if defined(MAXPATHLEN) - cp->RealWorkingDirectoryLength = MAXPATHLEN; -#elif defined(PATH_MAX) - cp->RealWorkingDirectoryLength = PATH_MAX; -#else - cp->RealWorkingDirectoryLength = 4096; -#endif - cp->RealWorkingDirectory = - (char*)malloc((size_t)(cp->RealWorkingDirectoryLength)); - if(!cp->RealWorkingDirectory) - { - return 0; - } - } - - return 1; -} - -/*--------------------------------------------------------------------------*/ -/* Free all resources used by the given kwsysProcess instance that were - allocated by kwsysProcess_Execute. */ -static void kwsysProcessCleanup(kwsysProcess* cp, int error) -{ - int i; - - if(error) - { - /* We are cleaning up due to an error. Report the error message - if one has not been provided already. */ - if(cp->ErrorMessage[0] == 0) - { - strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE); - } - - /* Set the error state. */ - cp->State = kwsysProcess_State_Error; - - /* Kill any children already started. */ - if(cp->ForkPIDs) - { - int status; - for(i=0; i < cp->NumberOfCommands; ++i) - { - if(cp->ForkPIDs[i]) - { - /* Kill the child. */ - kwsysProcessKill(cp->ForkPIDs[i]); - - /* Reap the child. Keep trying until the call is not - interrupted. */ - while((waitpid(cp->ForkPIDs[i], &status, 0) < 0) && - (errno == EINTR)); - } - } - } - - /* Restore the working directory. */ - if(cp->RealWorkingDirectory) - { - while((chdir(cp->RealWorkingDirectory) < 0) && (errno == EINTR)); - } - } - - /* If not creating a detached child, remove this object from the - global set of process objects that wish to be notified when a - child exits. */ - if(!cp->OptionDetach) - { - kwsysProcessesRemove(cp); - } - - /* Free memory. */ - if(cp->ForkPIDs) - { - kwsysProcessVolatileFree(cp->ForkPIDs); - cp->ForkPIDs = 0; - } - if(cp->RealWorkingDirectory) - { - free(cp->RealWorkingDirectory); - cp->RealWorkingDirectory = 0; - } - - /* Close pipe handles. */ - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); - } - for(i=0; i < 3; ++i) - { - kwsysProcessCleanupDescriptor(&cp->PipeChildStd[i]); - } -} - -/*--------------------------------------------------------------------------*/ -/* Close the given file descriptor if it is open. Reset its value to -1. */ -static void kwsysProcessCleanupDescriptor(int* pfd) -{ - if(pfd && *pfd > 2) - { - /* Keep trying to close until it is not interrupted by a - * signal. */ - while((close(*pfd) < 0) && (errno == EINTR)); - *pfd = -1; - } -} - -/*--------------------------------------------------------------------------*/ -static void kwsysProcessClosePipes(kwsysProcess* cp) -{ - int i; - - /* Close any pipes that are still open. */ - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - if(cp->PipeReadEnds[i] >= 0) - { -#if KWSYSPE_USE_SELECT - /* If the pipe was reported by the last call to select, we must - read from it. This is needed to satisfy the suggestions from - "man select_tut" and is not needed for the polling - implementation. Ignore the data. */ - if(FD_ISSET(cp->PipeReadEnds[i], &cp->PipeSet)) - { - /* We are handling this pipe now. Remove it from the set. */ - FD_CLR(cp->PipeReadEnds[i], &cp->PipeSet); - - /* The pipe is ready to read without blocking. Keep trying to - read until the operation is not interrupted. */ - while((read(cp->PipeReadEnds[i], cp->PipeBuffer, - KWSYSPE_PIPE_BUFFER_SIZE) < 0) && (errno == EINTR)); - } -#endif - - /* We are done reading from this pipe. */ - kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); - --cp->PipesLeft; - } - } -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcessSetNonBlocking(int fd) -{ - int flags = fcntl(fd, F_GETFL); - if(flags >= 0) - { - flags = fcntl(fd, F_SETFL, flags | O_NONBLOCK); - } - return flags >= 0; -} - -/*--------------------------------------------------------------------------*/ -#if defined(__VMS) -int decc$set_child_standard_streams(int fd1, int fd2, int fd3); -#endif - -/*--------------------------------------------------------------------------*/ -static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, - kwsysProcessCreateInformation* si) -{ - sigset_t mask, old_mask; - int pgidPipe[2]; - char tmp; - ssize_t readRes; - - /* Create the error reporting pipe. */ - if(pipe(si->ErrorPipe) < 0) - { - return 0; - } - - /* Create a pipe for detecting that the child process has created a process - group and session. */ - if(pipe(pgidPipe) < 0) - { - kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); - kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); - return 0; - } - - /* Set close-on-exec flag on the pipe's write end. */ - if(fcntl(si->ErrorPipe[1], F_SETFD, FD_CLOEXEC) < 0 || - fcntl(pgidPipe[1], F_SETFD, FD_CLOEXEC) < 0) - { - kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); - kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); - kwsysProcessCleanupDescriptor(&pgidPipe[0]); - kwsysProcessCleanupDescriptor(&pgidPipe[1]); - return 0; - } - - /* Block SIGINT / SIGTERM while we start. The purpose is so that our signal - handler doesn't get called from the child process after the fork and - before the exec, and subsequently start kill()'ing PIDs from ForkPIDs. */ - sigemptyset(&mask); - sigaddset(&mask, SIGINT); - sigaddset(&mask, SIGTERM); - if(sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) - { - kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); - kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); - kwsysProcessCleanupDescriptor(&pgidPipe[0]); - kwsysProcessCleanupDescriptor(&pgidPipe[1]); - return 0; - } - - /* Fork off a child process. */ -#if defined(__VMS) - /* VMS needs vfork and execvp to be in the same function because - they use setjmp/longjmp to run the child startup code in the - parent! TODO: OptionDetach. Also - TODO: CreateProcessGroup. */ - cp->ForkPIDs[prIndex] = vfork(); -#else - cp->ForkPIDs[prIndex] = kwsysProcessFork(cp, si); -#endif - if(cp->ForkPIDs[prIndex] < 0) - { - sigprocmask(SIG_SETMASK, &old_mask, 0); - kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); - kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); - kwsysProcessCleanupDescriptor(&pgidPipe[0]); - kwsysProcessCleanupDescriptor(&pgidPipe[1]); - return 0; - } - - if(cp->ForkPIDs[prIndex] == 0) - { -#if defined(__VMS) - /* Specify standard pipes for child process. */ - decc$set_child_standard_streams(si->StdIn, si->StdOut, si->StdErr); -#else - /* Close the read end of the error reporting / process group - setup pipe. */ - close(si->ErrorPipe[0]); - close(pgidPipe[0]); - - /* Setup the stdin, stdout, and stderr pipes. */ - if(si->StdIn > 0) - { - dup2(si->StdIn, 0); - } - else if(si->StdIn < 0) - { - close(0); - } - if(si->StdOut != 1) - { - dup2(si->StdOut, 1); - } - if(si->StdErr != 2) - { - dup2(si->StdErr, 2); - } - - /* Clear the close-on-exec flag for stdin, stdout, and stderr. - All other pipe handles will be closed when exec succeeds. */ - fcntl(0, F_SETFD, 0); - fcntl(1, F_SETFD, 0); - fcntl(2, F_SETFD, 0); - - /* Restore all default signal handlers. */ - kwsysProcessRestoreDefaultSignalHandlers(); - - /* Now that we have restored default signal handling and created the - process group, restore mask. */ - sigprocmask(SIG_SETMASK, &old_mask, 0); - - /* Create new process group. We use setsid instead of setpgid to avoid - the child getting hung up on signals like SIGTTOU. (In the real world, - this has been observed where "git svn" ends up calling the "resize" - program which opens /dev/tty. */ - if(cp->CreateProcessGroup && setsid() < 0) - { - kwsysProcessChildErrorExit(si->ErrorPipe[1]); - } -#endif - - /* Execute the real process. If successful, this does not return. */ - execvp(cp->Commands[prIndex][0], cp->Commands[prIndex]); - /* TODO: What does VMS do if the child fails to start? */ - /* TODO: On VMS, how do we put the process in a new group? */ - - /* Failure. Report error to parent and terminate. */ - kwsysProcessChildErrorExit(si->ErrorPipe[1]); - } - -#if defined(__VMS) - /* Restore the standard pipes of this process. */ - decc$set_child_standard_streams(0, 1, 2); -#endif - - /* We are done with the error reporting pipe and process group setup pipe - write end. */ - kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); - kwsysProcessCleanupDescriptor(&pgidPipe[1]); - - /* Make sure the child is in the process group before we proceed. This - avoids race conditions with calls to the kill function that we make for - signalling process groups. */ - while((readRes = read(pgidPipe[0], &tmp, 1)) > 0); - if(readRes < 0) - { - sigprocmask(SIG_SETMASK, &old_mask, 0); - kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); - kwsysProcessCleanupDescriptor(&pgidPipe[0]); - return 0; - } - kwsysProcessCleanupDescriptor(&pgidPipe[0]); - - /* Unmask signals. */ - if(sigprocmask(SIG_SETMASK, &old_mask, 0) < 0) - { - kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); - return 0; - } - - /* A child has been created. */ - ++cp->CommandsLeft; - - /* Block until the child's exec call succeeds and closes the error - pipe or writes data to the pipe to report an error. */ - { - kwsysProcess_ssize_t total = 0; - kwsysProcess_ssize_t n = 1; - /* Read the entire error message up to the length of our buffer. */ - while(total < KWSYSPE_PIPE_BUFFER_SIZE && n > 0) - { - /* Keep trying to read until the operation is not interrupted. */ - while(((n = read(si->ErrorPipe[0], cp->ErrorMessage+total, - (size_t)(KWSYSPE_PIPE_BUFFER_SIZE-total))) < 0) && - (errno == EINTR)); - if(n > 0) - { - total += n; - } - } - - /* We are done with the error reporting pipe read end. */ - kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); - - if(total > 0) - { - /* The child failed to execute the process. */ - return 0; - } - } - - return 1; -} - -/*--------------------------------------------------------------------------*/ -static void kwsysProcessDestroy(kwsysProcess* cp) -{ - /* A child process has terminated. Reap it if it is one handled by - this object. */ - int i; - /* Temporarily disable signals that access ForkPIDs. We don't want them to - read a reaped PID, and writes to ForkPIDs are not atomic. */ - sigset_t mask, old_mask; - sigemptyset(&mask); - sigaddset(&mask, SIGINT); - sigaddset(&mask, SIGTERM); - if(sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) - { - return; - } - - for(i=0; i < cp->NumberOfCommands; ++i) - { - if(cp->ForkPIDs[i]) - { - int result; - while(((result = waitpid(cp->ForkPIDs[i], - &cp->CommandExitCodes[i], WNOHANG)) < 0) && - (errno == EINTR)); - if(result > 0) - { - /* This child has termianted. */ - cp->ForkPIDs[i] = 0; - if(--cp->CommandsLeft == 0) - { - /* All children have terminated. Close the signal pipe - write end so that no more notifications are sent to this - object. */ - kwsysProcessCleanupDescriptor(&cp->SignalPipe); - - /* TODO: Once the children have terminated, switch - WaitForData to use a non-blocking read to get the - rest of the data from the pipe. This is needed when - grandchildren keep the output pipes open. */ - } - } - else if(result < 0 && cp->State != kwsysProcess_State_Error) - { - /* Unexpected error. Report the first time this happens. */ - strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE); - cp->State = kwsysProcess_State_Error; - } - } - } - - /* Re-enable signals. */ - sigprocmask(SIG_SETMASK, &old_mask, 0); -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcessSetupOutputPipeFile(int* p, const char* name) -{ - int fout; - if(!name) - { - return 1; - } - - /* Close the existing descriptor. */ - kwsysProcessCleanupDescriptor(p); - - /* Open a file for the pipe to write. */ - if((fout = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) - { - return 0; - } - - /* Set close-on-exec flag on the pipe's end. */ - if(fcntl(fout, F_SETFD, FD_CLOEXEC) < 0) - { - return 0; - } - - /* Assign the replacement descriptor. */ - *p = fout; - return 1; -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcessSetupOutputPipeNative(int* p, int des[2]) -{ - /* Close the existing descriptor. */ - kwsysProcessCleanupDescriptor(p); - - /* Set close-on-exec flag on the pipe's ends. The proper end will - be dup2-ed into the standard descriptor number after fork but - before exec. */ - if((fcntl(des[0], F_SETFD, FD_CLOEXEC) < 0) || - (fcntl(des[1], F_SETFD, FD_CLOEXEC) < 0)) - { - return 0; - } - - /* Assign the replacement descriptor. */ - *p = des[1]; - return 1; -} - -/*--------------------------------------------------------------------------*/ -/* Get the time at which either the process or user timeout will - expire. Returns 1 if the user timeout is first, and 0 otherwise. */ -static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, - kwsysProcessTime* timeoutTime) -{ - /* The first time this is called, we need to calculate the time at - which the child will timeout. */ - if(cp->Timeout > 0 && cp->TimeoutTime.tv_sec < 0) - { - kwsysProcessTime length = kwsysProcessTimeFromDouble(cp->Timeout); - cp->TimeoutTime = kwsysProcessTimeAdd(cp->StartTime, length); - } - - /* Start with process timeout. */ - *timeoutTime = cp->TimeoutTime; - - /* Check if the user timeout is earlier. */ - if(userTimeout) - { - kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent(); - kwsysProcessTime userTimeoutLength = kwsysProcessTimeFromDouble(*userTimeout); - kwsysProcessTime userTimeoutTime = kwsysProcessTimeAdd(currentTime, - userTimeoutLength); - if(timeoutTime->tv_sec < 0 || - kwsysProcessTimeLess(userTimeoutTime, *timeoutTime)) - { - *timeoutTime = userTimeoutTime; - return 1; - } - } - return 0; -} - -/*--------------------------------------------------------------------------*/ -/* Get the length of time before the given timeout time arrives. - Returns 1 if the time has already arrived, and 0 otherwise. */ -static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, - double* userTimeout, - kwsysProcessTimeNative* timeoutLength, - int zeroIsExpired) -{ - if(timeoutTime->tv_sec < 0) - { - /* No timeout time has been requested. */ - return 0; - } - else - { - /* Calculate the remaining time. */ - kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent(); - kwsysProcessTime timeLeft = kwsysProcessTimeSubtract(*timeoutTime, - currentTime); - if(timeLeft.tv_sec < 0 && userTimeout && *userTimeout <= 0) - { - /* Caller has explicitly requested a zero timeout. */ - timeLeft.tv_sec = 0; - timeLeft.tv_usec = 0; - } - - if(timeLeft.tv_sec < 0 || - (timeLeft.tv_sec == 0 && timeLeft.tv_usec == 0 && zeroIsExpired)) - { - /* Timeout has already expired. */ - return 1; - } - else - { - /* There is some time left. */ - timeoutLength->tv_sec = timeLeft.tv_sec; - timeoutLength->tv_usec = timeLeft.tv_usec; - return 0; - } - } -} - -/*--------------------------------------------------------------------------*/ -static kwsysProcessTime kwsysProcessTimeGetCurrent(void) -{ - kwsysProcessTime current; - kwsysProcessTimeNative current_native; - gettimeofday(¤t_native, 0); - current.tv_sec = (long)current_native.tv_sec; - current.tv_usec = (long)current_native.tv_usec; - return current; -} - -/*--------------------------------------------------------------------------*/ -static double kwsysProcessTimeToDouble(kwsysProcessTime t) -{ - return (double)t.tv_sec + (double)(t.tv_usec)*0.000001; -} - -/*--------------------------------------------------------------------------*/ -static kwsysProcessTime kwsysProcessTimeFromDouble(double d) -{ - kwsysProcessTime t; - t.tv_sec = (long)d; - t.tv_usec = (long)((d-(double)(t.tv_sec))*1000000); - return t; -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2) -{ - return ((in1.tv_sec < in2.tv_sec) || - ((in1.tv_sec == in2.tv_sec) && (in1.tv_usec < in2.tv_usec))); -} - -/*--------------------------------------------------------------------------*/ -static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2) -{ - kwsysProcessTime out; - out.tv_sec = in1.tv_sec + in2.tv_sec; - out.tv_usec = in1.tv_usec + in2.tv_usec; - if(out.tv_usec > 1000000) - { - out.tv_usec -= 1000000; - out.tv_sec += 1; - } - return out; -} - -/*--------------------------------------------------------------------------*/ -static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2) -{ - kwsysProcessTime out; - out.tv_sec = in1.tv_sec - in2.tv_sec; - out.tv_usec = in1.tv_usec - in2.tv_usec; - if(out.tv_usec < 0) - { - out.tv_usec += 1000000; - out.tv_sec -= 1; - } - return out; -} - -/*--------------------------------------------------------------------------*/ -#define KWSYSPE_CASE(type, str) \ - cp->ExitException = kwsysProcess_Exception_##type; \ - strcpy(cp->ExitExceptionString, str) -static void kwsysProcessSetExitException(kwsysProcess* cp, int sig) -{ - switch (sig) - { -#ifdef SIGSEGV - case SIGSEGV: KWSYSPE_CASE(Fault, "Segmentation fault"); break; -#endif -#ifdef SIGBUS -# if !defined(SIGSEGV) || SIGBUS != SIGSEGV - case SIGBUS: KWSYSPE_CASE(Fault, "Bus error"); break; -# endif -#endif -#ifdef SIGFPE - case SIGFPE: KWSYSPE_CASE(Numerical, "Floating-point exception"); break; -#endif -#ifdef SIGILL - case SIGILL: KWSYSPE_CASE(Illegal, "Illegal instruction"); break; -#endif -#ifdef SIGINT - case SIGINT: KWSYSPE_CASE(Interrupt, "User interrupt"); break; -#endif -#ifdef SIGABRT - case SIGABRT: KWSYSPE_CASE(Other, "Child aborted"); break; -#endif -#ifdef SIGKILL - case SIGKILL: KWSYSPE_CASE(Other, "Child killed"); break; -#endif -#ifdef SIGTERM - case SIGTERM: KWSYSPE_CASE(Other, "Child terminated"); break; -#endif -#ifdef SIGHUP - case SIGHUP: KWSYSPE_CASE(Other, "SIGHUP"); break; -#endif -#ifdef SIGQUIT - case SIGQUIT: KWSYSPE_CASE(Other, "SIGQUIT"); break; -#endif -#ifdef SIGTRAP - case SIGTRAP: KWSYSPE_CASE(Other, "SIGTRAP"); break; -#endif -#ifdef SIGIOT -# if !defined(SIGABRT) || SIGIOT != SIGABRT - case SIGIOT: KWSYSPE_CASE(Other, "SIGIOT"); break; -# endif -#endif -#ifdef SIGUSR1 - case SIGUSR1: KWSYSPE_CASE(Other, "SIGUSR1"); break; -#endif -#ifdef SIGUSR2 - case SIGUSR2: KWSYSPE_CASE(Other, "SIGUSR2"); break; -#endif -#ifdef SIGPIPE - case SIGPIPE: KWSYSPE_CASE(Other, "SIGPIPE"); break; -#endif -#ifdef SIGALRM - case SIGALRM: KWSYSPE_CASE(Other, "SIGALRM"); break; -#endif -#ifdef SIGSTKFLT - case SIGSTKFLT: KWSYSPE_CASE(Other, "SIGSTKFLT"); break; -#endif -#ifdef SIGCHLD - case SIGCHLD: KWSYSPE_CASE(Other, "SIGCHLD"); break; -#elif defined(SIGCLD) - case SIGCLD: KWSYSPE_CASE(Other, "SIGCLD"); break; -#endif -#ifdef SIGCONT - case SIGCONT: KWSYSPE_CASE(Other, "SIGCONT"); break; -#endif -#ifdef SIGSTOP - case SIGSTOP: KWSYSPE_CASE(Other, "SIGSTOP"); break; -#endif -#ifdef SIGTSTP - case SIGTSTP: KWSYSPE_CASE(Other, "SIGTSTP"); break; -#endif -#ifdef SIGTTIN - case SIGTTIN: KWSYSPE_CASE(Other, "SIGTTIN"); break; -#endif -#ifdef SIGTTOU - case SIGTTOU: KWSYSPE_CASE(Other, "SIGTTOU"); break; -#endif -#ifdef SIGURG - case SIGURG: KWSYSPE_CASE(Other, "SIGURG"); break; -#endif -#ifdef SIGXCPU - case SIGXCPU: KWSYSPE_CASE(Other, "SIGXCPU"); break; -#endif -#ifdef SIGXFSZ - case SIGXFSZ: KWSYSPE_CASE(Other, "SIGXFSZ"); break; -#endif -#ifdef SIGVTALRM - case SIGVTALRM: KWSYSPE_CASE(Other, "SIGVTALRM"); break; -#endif -#ifdef SIGPROF - case SIGPROF: KWSYSPE_CASE(Other, "SIGPROF"); break; -#endif -#ifdef SIGWINCH - case SIGWINCH: KWSYSPE_CASE(Other, "SIGWINCH"); break; -#endif -#ifdef SIGPOLL - case SIGPOLL: KWSYSPE_CASE(Other, "SIGPOLL"); break; -#endif -#ifdef SIGIO -# if !defined(SIGPOLL) || SIGIO != SIGPOLL - case SIGIO: KWSYSPE_CASE(Other, "SIGIO"); break; -# endif -#endif -#ifdef SIGPWR - case SIGPWR: KWSYSPE_CASE(Other, "SIGPWR"); break; -#endif -#ifdef SIGSYS - case SIGSYS: KWSYSPE_CASE(Other, "SIGSYS"); break; -#endif -#ifdef SIGUNUSED -# if !defined(SIGSYS) || SIGUNUSED != SIGSYS - case SIGUNUSED: KWSYSPE_CASE(Other, "SIGUNUSED"); break; -# endif -#endif - default: - cp->ExitException = kwsysProcess_Exception_Other; - sprintf(cp->ExitExceptionString, "Signal %d", sig); - break; - } -} -#undef KWSYSPE_CASE - -/*--------------------------------------------------------------------------*/ -/* When the child process encounters an error before its program is - invoked, this is called to report the error to the parent and - exit. */ -static void kwsysProcessChildErrorExit(int errorPipe) -{ - /* Construct the error message. */ - char buffer[KWSYSPE_PIPE_BUFFER_SIZE]; - kwsysProcess_ssize_t result; - strncpy(buffer, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE); - - /* Report the error to the parent through the special pipe. */ - result=write(errorPipe, buffer, strlen(buffer)); - (void)result; - - /* Terminate without cleanup. */ - _exit(1); -} - -/*--------------------------------------------------------------------------*/ -/* Restores all signal handlers to their default values. */ -static void kwsysProcessRestoreDefaultSignalHandlers(void) -{ - struct sigaction act; - memset(&act, 0, sizeof(struct sigaction)); - act.sa_handler = SIG_DFL; -#ifdef SIGHUP - sigaction(SIGHUP, &act, 0); -#endif -#ifdef SIGINT - sigaction(SIGINT, &act, 0); -#endif -#ifdef SIGQUIT - sigaction(SIGQUIT, &act, 0); -#endif -#ifdef SIGILL - sigaction(SIGILL, &act, 0); -#endif -#ifdef SIGTRAP - sigaction(SIGTRAP, &act, 0); -#endif -#ifdef SIGABRT - sigaction(SIGABRT, &act, 0); -#endif -#ifdef SIGIOT - sigaction(SIGIOT, &act, 0); -#endif -#ifdef SIGBUS - sigaction(SIGBUS, &act, 0); -#endif -#ifdef SIGFPE - sigaction(SIGFPE, &act, 0); -#endif -#ifdef SIGUSR1 - sigaction(SIGUSR1, &act, 0); -#endif -#ifdef SIGSEGV - sigaction(SIGSEGV, &act, 0); -#endif -#ifdef SIGUSR2 - sigaction(SIGUSR2, &act, 0); -#endif -#ifdef SIGPIPE - sigaction(SIGPIPE, &act, 0); -#endif -#ifdef SIGALRM - sigaction(SIGALRM, &act, 0); -#endif -#ifdef SIGTERM - sigaction(SIGTERM, &act, 0); -#endif -#ifdef SIGSTKFLT - sigaction(SIGSTKFLT, &act, 0); -#endif -#ifdef SIGCLD - sigaction(SIGCLD, &act, 0); -#endif -#ifdef SIGCHLD - sigaction(SIGCHLD, &act, 0); -#endif -#ifdef SIGCONT - sigaction(SIGCONT, &act, 0); -#endif -#ifdef SIGTSTP - sigaction(SIGTSTP, &act, 0); -#endif -#ifdef SIGTTIN - sigaction(SIGTTIN, &act, 0); -#endif -#ifdef SIGTTOU - sigaction(SIGTTOU, &act, 0); -#endif -#ifdef SIGURG - sigaction(SIGURG, &act, 0); -#endif -#ifdef SIGXCPU - sigaction(SIGXCPU, &act, 0); -#endif -#ifdef SIGXFSZ - sigaction(SIGXFSZ, &act, 0); -#endif -#ifdef SIGVTALRM - sigaction(SIGVTALRM, &act, 0); -#endif -#ifdef SIGPROF - sigaction(SIGPROF, &act, 0); -#endif -#ifdef SIGWINCH - sigaction(SIGWINCH, &act, 0); -#endif -#ifdef SIGPOLL - sigaction(SIGPOLL, &act, 0); -#endif -#ifdef SIGIO - sigaction(SIGIO, &act, 0); -#endif -#ifdef SIGPWR - sigaction(SIGPWR, &act, 0); -#endif -#ifdef SIGSYS - sigaction(SIGSYS, &act, 0); -#endif -#ifdef SIGUNUSED - sigaction(SIGUNUSED, &act, 0); -#endif -} - -/*--------------------------------------------------------------------------*/ -static void kwsysProcessExit(void) -{ - _exit(0); -} - -/*--------------------------------------------------------------------------*/ -#if !defined(__VMS) -static pid_t kwsysProcessFork(kwsysProcess* cp, - kwsysProcessCreateInformation* si) -{ - /* Create a detached process if requested. */ - if(cp->OptionDetach) - { - /* Create an intermediate process. */ - pid_t middle_pid = fork(); - if(middle_pid < 0) - { - /* Fork failed. Return as if we were not detaching. */ - return middle_pid; - } - else if(middle_pid == 0) - { - /* This is the intermediate process. Create the real child. */ - pid_t child_pid = fork(); - if(child_pid == 0) - { - /* This is the real child process. There is nothing to do here. */ - return 0; - } - else - { - /* Use the error pipe to report the pid to the real parent. */ - while((write(si->ErrorPipe[1], &child_pid, sizeof(child_pid)) < 0) && - (errno == EINTR)); - - /* Exit without cleanup. The parent holds all resources. */ - kwsysProcessExit(); - return 0; /* Never reached, but avoids SunCC warning. */ - } - } - else - { - /* This is the original parent process. The intermediate - process will use the error pipe to report the pid of the - detached child. */ - pid_t child_pid; - int status; - while((read(si->ErrorPipe[0], &child_pid, sizeof(child_pid)) < 0) && - (errno == EINTR)); - - /* Wait for the intermediate process to exit and clean it up. */ - while((waitpid(middle_pid, &status, 0) < 0) && (errno == EINTR)); - return child_pid; - } - } - else - { - /* Not creating a detached process. Use normal fork. */ - return fork(); - } -} -#endif - -/*--------------------------------------------------------------------------*/ -/* We try to obtain process information by invoking the ps command. - Here we define the command to call on each platform and the - corresponding parsing format string. The parsing format should - have two integers to store: the pid and then the ppid. */ -#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) \ - || defined(__OpenBSD__) || defined(__GLIBC__) || defined(__GNU__) -# define KWSYSPE_PS_COMMAND "ps axo pid,ppid" -# define KWSYSPE_PS_FORMAT "%d %d\n" -#elif defined(__sun) && (defined(__SVR4) || defined(__svr4__)) /* Solaris */ -# define KWSYSPE_PS_COMMAND "ps -e -o pid,ppid" -# define KWSYSPE_PS_FORMAT "%d %d\n" -#elif defined(__hpux) || defined(__sun__) || defined(__sgi) || defined(_AIX) \ - || defined(__sparc) -# define KWSYSPE_PS_COMMAND "ps -ef" -# define KWSYSPE_PS_FORMAT "%*s %d %d %*[^\n]\n" -#elif defined(__QNX__) -# define KWSYSPE_PS_COMMAND "ps -Af" -# define KWSYSPE_PS_FORMAT "%*d %d %d %*[^\n]\n" -#elif defined(__CYGWIN__) -# define KWSYSPE_PS_COMMAND "ps aux" -# define KWSYSPE_PS_FORMAT "%d %d %*[^\n]\n" -#endif - -/*--------------------------------------------------------------------------*/ -static void kwsysProcessKill(pid_t process_id) -{ -#if defined(__linux__) || defined(__CYGWIN__) - DIR* procdir; -#endif - - /* Suspend the process to be sure it will not create more children. */ - kill(process_id, SIGSTOP); - -#if defined(__CYGWIN__) - /* Some Cygwin versions seem to need help here. Give up our time slice - so that the child can process SIGSTOP before we send SIGKILL. */ - usleep(1); -#endif - - /* Kill all children if we can find them. */ -#if defined(__linux__) || defined(__CYGWIN__) - /* First try using the /proc filesystem. */ - if((procdir = opendir("/proc")) != NULL) - { -#if defined(MAXPATHLEN) - char fname[MAXPATHLEN]; -#elif defined(PATH_MAX) - char fname[PATH_MAX]; -#else - char fname[4096]; -#endif - char buffer[KWSYSPE_PIPE_BUFFER_SIZE+1]; - struct dirent* d; - - /* Each process has a directory in /proc whose name is the pid. - Within this directory is a file called stat that has the - following format: - - pid (command line) status ppid ... - - We want to get the ppid for all processes. Those that have - process_id as their parent should be recursively killed. */ - for(d = readdir(procdir); d; d = readdir(procdir)) - { - int pid; - if(sscanf(d->d_name, "%d", &pid) == 1 && pid != 0) - { - struct stat finfo; - sprintf(fname, "/proc/%d/stat", pid); - if(stat(fname, &finfo) == 0) - { - FILE* f = fopen(fname, "r"); - if(f) - { - size_t nread = fread(buffer, 1, KWSYSPE_PIPE_BUFFER_SIZE, f); - fclose(f); - buffer[nread] = '\0'; - if(nread > 0) - { - const char* rparen = strrchr(buffer, ')'); - int ppid; - if(rparen && (sscanf(rparen+1, "%*s %d", &ppid) == 1)) - { - if(ppid == process_id) - { - /* Recursively kill this child and its children. */ - kwsysProcessKill(pid); - } - } - } - } - } - } - } - closedir(procdir); - } - else -#endif - { -#if defined(KWSYSPE_PS_COMMAND) - /* Try running "ps" to get the process information. */ - FILE* ps = popen(KWSYSPE_PS_COMMAND, "r"); - - /* Make sure the process started and provided a valid header. */ - if(ps && fscanf(ps, "%*[^\n]\n") != EOF) - { - /* Look for processes whose parent is the process being killed. */ - int pid, ppid; - while(fscanf(ps, KWSYSPE_PS_FORMAT, &pid, &ppid) == 2) - { - if(ppid == process_id) - { - /* Recursively kill this child and its children. */ - kwsysProcessKill(pid); - } - } - } - - /* We are done with the ps process. */ - if(ps) - { - pclose(ps); - } -#endif - } - - /* Kill the process. */ - kill(process_id, SIGKILL); - -#if defined(__APPLE__) - /* On OS X 10.3 the above SIGSTOP occasionally prevents the SIGKILL - from working. Just in case, we resume the child and kill it - again. There is a small race condition in this obscure case. If - the child manages to fork again between these two signals, we - will not catch its children. */ - kill(process_id, SIGCONT); - kill(process_id, SIGKILL); -#endif -} - -/*--------------------------------------------------------------------------*/ -#if defined(__VMS) -int decc$feature_get_index(const char* name); -int decc$feature_set_value(int index, int mode, int value); -static int kwsysProcessSetVMSFeature(const char* name, int value) -{ - int i; - errno = 0; - i = decc$feature_get_index(name); - return i >= 0 && (decc$feature_set_value(i, 1, value) >= 0 || errno == 0); -} -#endif - -/*--------------------------------------------------------------------------*/ -/* Global set of executing processes for use by the signal handler. - This global instance will be zero-initialized by the compiler. */ -typedef struct kwsysProcessInstances_s -{ - int Count; - int Size; - kwsysProcess** Processes; -} kwsysProcessInstances; -static kwsysProcessInstances kwsysProcesses; - -/* The old SIGCHLD / SIGINT / SIGTERM handlers. */ -static struct sigaction kwsysProcessesOldSigChldAction; -static struct sigaction kwsysProcessesOldSigIntAction; -static struct sigaction kwsysProcessesOldSigTermAction; - -/*--------------------------------------------------------------------------*/ -static void kwsysProcessesUpdate(kwsysProcessInstances* newProcesses) -{ - /* Block signals while we update the set of pipes to check. - TODO: sigprocmask is undefined for threaded apps. See - pthread_sigmask. */ - sigset_t newset; - sigset_t oldset; - sigemptyset(&newset); - sigaddset(&newset, SIGCHLD); - sigaddset(&newset, SIGINT); - sigaddset(&newset, SIGTERM); - sigprocmask(SIG_BLOCK, &newset, &oldset); - - /* Store the new set in that seen by the signal handler. */ - kwsysProcesses = *newProcesses; - - /* Restore the signal mask to the previous setting. */ - sigprocmask(SIG_SETMASK, &oldset, 0); -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcessesAdd(kwsysProcess* cp) -{ - /* Create a pipe through which the signal handler can notify the - given process object that a child has exited. */ - { - /* Create the pipe. */ - int p[2]; - if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0) - { - return 0; - } - - /* Store the pipes now to be sure they are cleaned up later. */ - cp->PipeReadEnds[KWSYSPE_PIPE_SIGNAL] = p[0]; - cp->SignalPipe = p[1]; - - /* Switch the pipe to non-blocking mode so that reading a byte can - be an atomic test-and-set. */ - if(!kwsysProcessSetNonBlocking(p[0]) || - !kwsysProcessSetNonBlocking(p[1])) - { - return 0; - } - - /* The children do not need this pipe. Set close-on-exec flag on - the pipe's ends. */ - if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || - (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) - { - return 0; - } - } - - /* Attempt to add the given signal pipe to the signal handler set. */ - { - - /* Make sure there is enough space for the new signal pipe. */ - kwsysProcessInstances oldProcesses = kwsysProcesses; - kwsysProcessInstances newProcesses = oldProcesses; - if(oldProcesses.Count == oldProcesses.Size) - { - /* Start with enough space for a small number of process instances - and double the size each time more is needed. */ - newProcesses.Size = oldProcesses.Size? oldProcesses.Size*2 : 4; - - /* Try allocating the new block of memory. */ - if((newProcesses.Processes = ((kwsysProcess**) - malloc((size_t)(newProcesses.Size)* - sizeof(kwsysProcess*))))) - { - /* Copy the old pipe set to the new memory. */ - if(oldProcesses.Count > 0) - { - memcpy(newProcesses.Processes, oldProcesses.Processes, - ((size_t)(oldProcesses.Count) * sizeof(kwsysProcess*))); - } - } - else - { - /* Failed to allocate memory for the new signal pipe set. */ - return 0; - } - } - - /* Append the new signal pipe to the set. */ - newProcesses.Processes[newProcesses.Count++] = cp; - - /* Store the new set in that seen by the signal handler. */ - kwsysProcessesUpdate(&newProcesses); - - /* Free the original pipes if new ones were allocated. */ - if(newProcesses.Processes != oldProcesses.Processes) - { - free(oldProcesses.Processes); - } - - /* If this is the first process, enable the signal handler. */ - if(newProcesses.Count == 1) - { - /* Install our handler for SIGCHLD. Repeat call until it is not - interrupted. */ - struct sigaction newSigAction; - memset(&newSigAction, 0, sizeof(struct sigaction)); -#if KWSYSPE_USE_SIGINFO - newSigAction.sa_sigaction = kwsysProcessesSignalHandler; - newSigAction.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; -# ifdef SA_RESTART - newSigAction.sa_flags |= SA_RESTART; -# endif -#else - newSigAction.sa_handler = kwsysProcessesSignalHandler; - newSigAction.sa_flags = SA_NOCLDSTOP; -#endif - sigemptyset(&newSigAction.sa_mask); - while((sigaction(SIGCHLD, &newSigAction, - &kwsysProcessesOldSigChldAction) < 0) && - (errno == EINTR)); - - /* Install our handler for SIGINT / SIGTERM. Repeat call until - it is not interrupted. */ - sigemptyset(&newSigAction.sa_mask); - sigaddset(&newSigAction.sa_mask, SIGTERM); - while((sigaction(SIGINT, &newSigAction, - &kwsysProcessesOldSigIntAction) < 0) && - (errno == EINTR)); - - sigemptyset(&newSigAction.sa_mask); - sigaddset(&newSigAction.sa_mask, SIGINT); - while((sigaction(SIGTERM, &newSigAction, - &kwsysProcessesOldSigIntAction) < 0) && - (errno == EINTR)); - } - } - - return 1; -} - -/*--------------------------------------------------------------------------*/ -static void kwsysProcessesRemove(kwsysProcess* cp) -{ - /* Attempt to remove the given signal pipe from the signal handler set. */ - { - /* Find the given process in the set. */ - kwsysProcessInstances newProcesses = kwsysProcesses; - int i; - for(i=0; i < newProcesses.Count; ++i) - { - if(newProcesses.Processes[i] == cp) - { - break; - } - } - if(i < newProcesses.Count) - { - /* Remove the process from the set. */ - --newProcesses.Count; - for(; i < newProcesses.Count; ++i) - { - newProcesses.Processes[i] = newProcesses.Processes[i+1]; - } - - /* If this was the last process, disable the signal handler. */ - if(newProcesses.Count == 0) - { - /* Restore the signal handlers. Repeat call until it is not - interrupted. */ - while((sigaction(SIGCHLD, &kwsysProcessesOldSigChldAction, 0) < 0) && - (errno == EINTR)); - while((sigaction(SIGINT, &kwsysProcessesOldSigIntAction, 0) < 0) && - (errno == EINTR)); - while((sigaction(SIGTERM, &kwsysProcessesOldSigTermAction, 0) < 0) && - (errno == EINTR)); - - /* Free the table of process pointers since it is now empty. - This is safe because the signal handler has been removed. */ - newProcesses.Size = 0; - free(newProcesses.Processes); - newProcesses.Processes = 0; - } - - /* Store the new set in that seen by the signal handler. */ - kwsysProcessesUpdate(&newProcesses); - } - } - - /* Close the pipe through which the signal handler may have notified - the given process object that a child has exited. */ - kwsysProcessCleanupDescriptor(&cp->SignalPipe); -} - -/*--------------------------------------------------------------------------*/ -static void kwsysProcessesSignalHandler(int signum -#if KWSYSPE_USE_SIGINFO - , siginfo_t* info, void* ucontext -#endif - ) -{ - int i, j, procStatus, old_errno = errno; -#if KWSYSPE_USE_SIGINFO - (void)info; - (void)ucontext; -#endif - - /* Signal all process objects that a child has terminated. */ - switch(signum) - { - case SIGCHLD: - for(i=0; i < kwsysProcesses.Count; ++i) - { - /* Set the pipe in a signalled state. */ - char buf = 1; - kwsysProcess* cp = kwsysProcesses.Processes[i]; - kwsysProcess_ssize_t pipeStatus= - read(cp->PipeReadEnds[KWSYSPE_PIPE_SIGNAL], &buf, 1); - (void)pipeStatus; - pipeStatus=write(cp->SignalPipe, &buf, 1); - (void)pipeStatus; - } - break; - case SIGINT: - case SIGTERM: - /* Signal child processes that are running in new process groups. */ - for(i=0; i < kwsysProcesses.Count; ++i) - { - kwsysProcess* cp = kwsysProcesses.Processes[i]; - /* Check Killed to avoid data race condition when killing. - Check State to avoid data race condition in kwsysProcessCleanup - when there is an error (it leaves a reaped PID). */ - if(cp->CreateProcessGroup && !cp->Killed && - cp->State != kwsysProcess_State_Error && cp->ForkPIDs) - { - for(j=0; j < cp->NumberOfCommands; ++j) - { - /* Make sure the PID is still valid. */ - if(cp->ForkPIDs[j]) - { - /* The user created a process group for this process. The group ID - is the process ID for the original process in the group. */ - kill(-cp->ForkPIDs[j], SIGINT); - } - } - } - } - - /* Wait for all processes to terminate. */ - while(wait(&procStatus) >= 0 || errno != ECHILD) - { - } - - /* Terminate the process, which is now in an inconsistent state - because we reaped all the PIDs that it may have been reaping - or may have reaped in the future. Reraise the signal so that - the proper exit code is returned. */ - { - /* Install default signal handler. */ - struct sigaction defSigAction; - sigset_t unblockSet; - memset(&defSigAction, 0, sizeof(defSigAction)); - defSigAction.sa_handler = SIG_DFL; - sigemptyset(&defSigAction.sa_mask); - while((sigaction(signum, &defSigAction, 0) < 0) && - (errno == EINTR)); - /* Unmask the signal. */ - sigemptyset(&unblockSet); - sigaddset(&unblockSet, signum); - sigprocmask(SIG_UNBLOCK, &unblockSet, 0); - /* Raise the signal again. */ - raise(signum); - /* We shouldn't get here... but if we do... */ - _exit(1); - } - /* break omitted to silence unreachable code clang compiler warning. */ - } - -#if !KWSYSPE_USE_SIGINFO - /* Re-Install our handler. Repeat call until it is not interrupted. */ - { - struct sigaction newSigAction; - struct sigaction &oldSigAction; - memset(&newSigAction, 0, sizeof(struct sigaction)); - newSigChldAction.sa_handler = kwsysProcessesSignalHandler; - newSigChldAction.sa_flags = SA_NOCLDSTOP; - sigemptyset(&newSigAction.sa_mask); - switch(signum) - { - case SIGCHLD: oldSigAction = &kwsysProcessesOldSigChldAction; break; - case SIGINT: - sigaddset(&newSigAction.sa_mask, SIGTERM); - oldSigAction = &kwsysProcessesOldSigIntAction; break; - case SIGTERM: - sigaddset(&newSigAction.sa_mask, SIGINT); - oldSigAction = &kwsysProcessesOldSigTermAction; break; - default: return 0; - } - while((sigaction(signum, &newSigAction, - oldSigAction) < 0) && - (errno == EINTR)); - } -#endif - - errno = old_errno; -} diff --git a/src/kwsys/ProcessWin32.c b/src/kwsys/ProcessWin32.c deleted file mode 100644 index 1f8749f..0000000 --- a/src/kwsys/ProcessWin32.c +++ /dev/null @@ -1,3017 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#include "kwsysPrivate.h" -#include KWSYS_HEADER(Process.h) -#include KWSYS_HEADER(Encoding.h) - -/* Work-around CMake dependency scanning limitation. This must - duplicate the above list of headers. */ -#if 0 -# include "Process.h.in" -# include "Encoding_c.h.in" -#endif - -/* - -Implementation for Windows - -On windows, a thread is created to wait for data on each pipe. The -threads are synchronized with the main thread to simulate the use of -a UNIX-style select system call. - -*/ - -#ifdef _MSC_VER -#pragma warning (push, 1) -#endif -#include /* Windows API */ -#if defined(_MSC_VER) && _MSC_VER >= 1800 -# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx -#endif -#include /* strlen, strdup */ -#include /* sprintf */ -#include /* _unlink */ -#ifdef __WATCOMC__ -#define _unlink unlink -#endif - -#ifndef _MAX_FNAME -#define _MAX_FNAME 4096 -#endif -#ifndef _MAX_PATH -#define _MAX_PATH 4096 -#endif - -#ifdef _MSC_VER -#pragma warning (pop) -#pragma warning (disable: 4514) -#pragma warning (disable: 4706) -#endif - -#if defined(__BORLANDC__) -# pragma warn -8004 /* assigned a value that is never used */ -# pragma warn -8060 /* Assignment inside if() condition. */ -#endif - -/* There are pipes for the process pipeline's stdout and stderr. */ -#define KWSYSPE_PIPE_COUNT 2 -#define KWSYSPE_PIPE_STDOUT 0 -#define KWSYSPE_PIPE_STDERR 1 - -/* The maximum amount to read from a pipe at a time. */ -#define KWSYSPE_PIPE_BUFFER_SIZE 1024 - -/* Debug output macro. */ -#if 0 -# define KWSYSPE_DEBUG(x) \ -( \ - (void*)cp == (void*)0x00226DE0? \ - ( \ - fprintf(stderr, "%d/%p/%d ", (int)GetCurrentProcessId(), cp, __LINE__), \ - fprintf x, \ - fflush(stderr), \ - 1 \ - ) : (1) \ -) -#else -# define KWSYSPE_DEBUG(x) (void)1 -#endif - -typedef LARGE_INTEGER kwsysProcessTime; - -typedef struct kwsysProcessCreateInformation_s -{ - /* Windows child startup control data. */ - STARTUPINFOW StartupInfo; - - /* Original handles before making inherited duplicates. */ - HANDLE hStdInput; - HANDLE hStdOutput; - HANDLE hStdError; -} kwsysProcessCreateInformation; - - -/*--------------------------------------------------------------------------*/ -typedef struct kwsysProcessPipeData_s kwsysProcessPipeData; -static DWORD WINAPI kwsysProcessPipeThreadRead(LPVOID ptd); -static void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, - kwsysProcessPipeData* td); -static DWORD WINAPI kwsysProcessPipeThreadWake(LPVOID ptd); -static void kwsysProcessPipeThreadWakePipe(kwsysProcess* cp, - kwsysProcessPipeData* td); -static int kwsysProcessInitialize(kwsysProcess* cp); -static DWORD kwsysProcessCreate(kwsysProcess* cp, int index, - kwsysProcessCreateInformation* si); -static void kwsysProcessDestroy(kwsysProcess* cp, int event); -static DWORD kwsysProcessSetupOutputPipeFile(PHANDLE handle, - const char* name); -static void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle); -static void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle); -static void kwsysProcessCleanupHandle(PHANDLE h); -static void kwsysProcessCleanup(kwsysProcess* cp, DWORD error); -static void kwsysProcessCleanErrorMessage(kwsysProcess* cp); -static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, - kwsysProcessTime* timeoutTime); -static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, - double* userTimeout, - kwsysProcessTime* timeoutLength); -static kwsysProcessTime kwsysProcessTimeGetCurrent(void); -static DWORD kwsysProcessTimeToDWORD(kwsysProcessTime t); -static double kwsysProcessTimeToDouble(kwsysProcessTime t); -static kwsysProcessTime kwsysProcessTimeFromDouble(double d); -static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2); -static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2); -static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2); -static void kwsysProcessSetExitException(kwsysProcess* cp, int code); -static void kwsysProcessKillTree(int pid); -static void kwsysProcessDisablePipeThreads(kwsysProcess* cp); -static int kwsysProcessesInitialize(void); -static int kwsysTryEnterCreateProcessSection(void); -static void kwsysLeaveCreateProcessSection(void); -static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessId, - int newProcessGroup); -static void kwsysProcessesRemove(HANDLE hProcess); -static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType); - -/*--------------------------------------------------------------------------*/ -/* A structure containing synchronization data for each thread. */ -typedef struct kwsysProcessPipeSync_s kwsysProcessPipeSync; -struct kwsysProcessPipeSync_s -{ - /* Handle to the thread. */ - HANDLE Thread; - - /* Semaphore indicating to the thread that a process has started. */ - HANDLE Ready; - - /* Semaphore indicating to the thread that it should begin work. */ - HANDLE Go; - - /* Semaphore indicating thread has reset for another process. */ - HANDLE Reset; -}; - -/*--------------------------------------------------------------------------*/ -/* A structure containing data for each pipe's threads. */ -struct kwsysProcessPipeData_s -{ - /* ------------- Data managed per instance of kwsysProcess ------------- */ - - /* Synchronization data for reading thread. */ - kwsysProcessPipeSync Reader; - - /* Synchronization data for waking thread. */ - kwsysProcessPipeSync Waker; - - /* Index of this pipe. */ - int Index; - - /* The kwsysProcess instance owning this pipe. */ - kwsysProcess* Process; - - /* ------------- Data managed per call to Execute ------------- */ - - /* Buffer for data read in this pipe's thread. */ - char DataBuffer[KWSYSPE_PIPE_BUFFER_SIZE]; - - /* The length of the data stored in the buffer. */ - DWORD DataLength; - - /* Whether the pipe has been closed. */ - int Closed; - - /* Handle for the read end of this pipe. */ - HANDLE Read; - - /* Handle for the write end of this pipe. */ - HANDLE Write; -}; - -/*--------------------------------------------------------------------------*/ -/* Structure containing data used to implement the child's execution. */ -struct kwsysProcess_s -{ - /* ------------- Data managed per instance of kwsysProcess ------------- */ - - /* The status of the process structure. */ - int State; - - /* The command lines to execute. */ - wchar_t** Commands; - int NumberOfCommands; - - /* The exit code of each command. */ - DWORD* CommandExitCodes; - - /* The working directory for the child process. */ - wchar_t* WorkingDirectory; - - /* Whether to create the child as a detached process. */ - int OptionDetach; - - /* Whether the child was created as a detached process. */ - int Detached; - - /* Whether to hide the child process's window. */ - int HideWindow; - - /* Whether to treat command lines as verbatim. */ - int Verbatim; - - /* Whether to merge stdout/stderr of the child. */ - int MergeOutput; - - /* Whether to create the process in a new process group. */ - int CreateProcessGroup; - - /* Mutex to protect the shared index used by threads to report data. */ - HANDLE SharedIndexMutex; - - /* Semaphore used by threads to signal data ready. */ - HANDLE Full; - - /* Whether we are currently deleting this kwsysProcess instance. */ - int Deleting; - - /* Data specific to each pipe and its thread. */ - kwsysProcessPipeData Pipe[KWSYSPE_PIPE_COUNT]; - - /* Name of files to which stdin and stdout pipes are attached. */ - char* PipeFileSTDIN; - char* PipeFileSTDOUT; - char* PipeFileSTDERR; - - /* Whether each pipe is shared with the parent process. */ - int PipeSharedSTDIN; - int PipeSharedSTDOUT; - int PipeSharedSTDERR; - - /* Native pipes provided by the user. */ - HANDLE PipeNativeSTDIN[2]; - HANDLE PipeNativeSTDOUT[2]; - HANDLE PipeNativeSTDERR[2]; - - /* ------------- Data managed per call to Execute ------------- */ - - /* The exceptional behavior that terminated the process, if any. */ - int ExitException; - - /* The process exit code. */ - DWORD ExitCode; - - /* The process return code, if any. */ - int ExitValue; - - /* Index of last pipe to report data, if any. */ - int CurrentIndex; - - /* Index shared by threads to report data. */ - int SharedIndex; - - /* The timeout length. */ - double Timeout; - - /* Time at which the child started. */ - kwsysProcessTime StartTime; - - /* Time at which the child will timeout. Negative for no timeout. */ - kwsysProcessTime TimeoutTime; - - /* Flag for whether the process was killed. */ - int Killed; - - /* Flag for whether the timeout expired. */ - int TimeoutExpired; - - /* Flag for whether the process has terminated. */ - int Terminated; - - /* The number of pipes still open during execution and while waiting - for pipes to close after process termination. */ - int PipesLeft; - - /* Buffer for error messages. */ - char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1]; - - /* Description for the ExitException. */ - char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE+1]; - - /* Windows process information data. */ - PROCESS_INFORMATION* ProcessInformation; - - /* Data and process termination events for which to wait. */ - PHANDLE ProcessEvents; - int ProcessEventsLength; - - /* Real working directory of our own process. */ - DWORD RealWorkingDirectoryLength; - wchar_t* RealWorkingDirectory; - - /* Own handles for the child's ends of the pipes in the parent process. - Used temporarily during process creation. */ - HANDLE PipeChildStd[3]; -}; - -/*--------------------------------------------------------------------------*/ -kwsysProcess* kwsysProcess_New(void) -{ - int i; - - /* Process control structure. */ - kwsysProcess* cp; - - /* Windows version number data. */ - OSVERSIONINFO osv; - - /* Initialize list of processes before we get any farther. It's especially - important that the console Ctrl handler be added BEFORE starting the - first process. This prevents the risk of an orphaned process being - started by the main thread while the default Ctrl handler is in - progress. */ - if(!kwsysProcessesInitialize()) - { - return 0; - } - - /* Allocate a process control structure. */ - cp = (kwsysProcess*)malloc(sizeof(kwsysProcess)); - if(!cp) - { - /* Could not allocate memory for the control structure. */ - return 0; - } - ZeroMemory(cp, sizeof(*cp)); - - /* Share stdin with the parent process by default. */ - cp->PipeSharedSTDIN = 1; - - /* Set initial status. */ - cp->State = kwsysProcess_State_Starting; - - /* Choose a method of running the child based on version of - windows. */ - ZeroMemory(&osv, sizeof(osv)); - osv.dwOSVersionInfoSize = sizeof(osv); -#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx -# pragma warning (push) -# ifdef __INTEL_COMPILER -# pragma warning (disable:1478) -# else -# pragma warning (disable:4996) -# endif -#endif - GetVersionEx(&osv); -#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx -# pragma warning (pop) -#endif - if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) - { - /* Win9x no longer supported. */ - kwsysProcess_Delete(cp); - return 0; - } - - /* Initially no thread owns the mutex. Initialize semaphore to 1. */ - if(!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0))) - { - kwsysProcess_Delete(cp); - return 0; - } - - /* Initially no data are available. Initialize semaphore to 0. */ - if(!(cp->Full = CreateSemaphore(0, 0, 1, 0))) - { - kwsysProcess_Delete(cp); - return 0; - } - - /* Create the thread to read each pipe. */ - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - DWORD dummy=0; - - /* Assign the thread its index. */ - cp->Pipe[i].Index = i; - - /* Give the thread a pointer back to the kwsysProcess instance. */ - cp->Pipe[i].Process = cp; - - /* No process is yet running. Initialize semaphore to 0. */ - if(!(cp->Pipe[i].Reader.Ready = CreateSemaphore(0, 0, 1, 0))) - { - kwsysProcess_Delete(cp); - return 0; - } - - /* The pipe is not yet reset. Initialize semaphore to 0. */ - if(!(cp->Pipe[i].Reader.Reset = CreateSemaphore(0, 0, 1, 0))) - { - kwsysProcess_Delete(cp); - return 0; - } - - /* The thread's buffer is initially empty. Initialize semaphore to 1. */ - if(!(cp->Pipe[i].Reader.Go = CreateSemaphore(0, 1, 1, 0))) - { - kwsysProcess_Delete(cp); - return 0; - } - - /* Create the reading thread. It will block immediately. The - thread will not make deeply nested calls, so we need only a - small stack. */ - if(!(cp->Pipe[i].Reader.Thread = CreateThread(0, 1024, - kwsysProcessPipeThreadRead, - &cp->Pipe[i], 0, &dummy))) - { - kwsysProcess_Delete(cp); - return 0; - } - - /* No process is yet running. Initialize semaphore to 0. */ - if(!(cp->Pipe[i].Waker.Ready = CreateSemaphore(0, 0, 1, 0))) - { - kwsysProcess_Delete(cp); - return 0; - } - - /* The pipe is not yet reset. Initialize semaphore to 0. */ - if(!(cp->Pipe[i].Waker.Reset = CreateSemaphore(0, 0, 1, 0))) - { - kwsysProcess_Delete(cp); - return 0; - } - - /* The waker should not wake immediately. Initialize semaphore to 0. */ - if(!(cp->Pipe[i].Waker.Go = CreateSemaphore(0, 0, 1, 0))) - { - kwsysProcess_Delete(cp); - return 0; - } - - /* Create the waking thread. It will block immediately. The - thread will not make deeply nested calls, so we need only a - small stack. */ - if(!(cp->Pipe[i].Waker.Thread = CreateThread(0, 1024, - kwsysProcessPipeThreadWake, - &cp->Pipe[i], 0, &dummy))) - { - kwsysProcess_Delete(cp); - return 0; - } - } - for(i=0; i < 3; ++i) - { - cp->PipeChildStd[i] = INVALID_HANDLE_VALUE; - } - - return cp; -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_Delete(kwsysProcess* cp) -{ - int i; - - /* Make sure we have an instance. */ - if(!cp) - { - return; - } - - /* If the process is executing, wait for it to finish. */ - if(cp->State == kwsysProcess_State_Executing) - { - if(cp->Detached) - { - kwsysProcess_Disown(cp); - } - else - { - kwsysProcess_WaitForExit(cp, 0); - } - } - - /* We are deleting the kwsysProcess instance. */ - cp->Deleting = 1; - - /* Terminate each of the threads. */ - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - /* Terminate this reading thread. */ - if(cp->Pipe[i].Reader.Thread) - { - /* Signal the thread we are ready for it. It will terminate - immediately since Deleting is set. */ - ReleaseSemaphore(cp->Pipe[i].Reader.Ready, 1, 0); - - /* Wait for the thread to exit. */ - WaitForSingleObject(cp->Pipe[i].Reader.Thread, INFINITE); - - /* Close the handle to the thread. */ - kwsysProcessCleanupHandle(&cp->Pipe[i].Reader.Thread); - } - - /* Terminate this waking thread. */ - if(cp->Pipe[i].Waker.Thread) - { - /* Signal the thread we are ready for it. It will terminate - immediately since Deleting is set. */ - ReleaseSemaphore(cp->Pipe[i].Waker.Ready, 1, 0); - - /* Wait for the thread to exit. */ - WaitForSingleObject(cp->Pipe[i].Waker.Thread, INFINITE); - - /* Close the handle to the thread. */ - kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Thread); - } - - /* Cleanup the pipe's semaphores. */ - kwsysProcessCleanupHandle(&cp->Pipe[i].Reader.Ready); - kwsysProcessCleanupHandle(&cp->Pipe[i].Reader.Go); - kwsysProcessCleanupHandle(&cp->Pipe[i].Reader.Reset); - kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Ready); - kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Go); - kwsysProcessCleanupHandle(&cp->Pipe[i].Waker.Reset); - } - - /* Close the shared semaphores. */ - kwsysProcessCleanupHandle(&cp->SharedIndexMutex); - kwsysProcessCleanupHandle(&cp->Full); - - /* Free memory. */ - kwsysProcess_SetCommand(cp, 0); - kwsysProcess_SetWorkingDirectory(cp, 0); - kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0); - kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0); - kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0); - if(cp->CommandExitCodes) - { - free(cp->CommandExitCodes); - } - free(cp); -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command) -{ - int i; - if(!cp) - { - return 0; - } - for(i=0; i < cp->NumberOfCommands; ++i) - { - free(cp->Commands[i]); - } - cp->NumberOfCommands = 0; - if(cp->Commands) - { - free(cp->Commands); - cp->Commands = 0; - } - if(command) - { - return kwsysProcess_AddCommand(cp, command); - } - return 1; -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) -{ - int newNumberOfCommands; - wchar_t** newCommands; - - /* Make sure we have a command to add. */ - if(!cp || !command || !*command) - { - return 0; - } - - - /* Allocate a new array for command pointers. */ - newNumberOfCommands = cp->NumberOfCommands + 1; - if(!(newCommands = (wchar_t**)malloc(sizeof(wchar_t*) * newNumberOfCommands))) - { - /* Out of memory. */ - return 0; - } - - /* Copy any existing commands into the new array. */ - { - int i; - for(i=0; i < cp->NumberOfCommands; ++i) - { - newCommands[i] = cp->Commands[i]; - } - } - - if (cp->Verbatim) - { - /* Copy the verbatim command line into the buffer. */ - newCommands[cp->NumberOfCommands] = kwsysEncoding_DupToWide(*command); - } - else - { - /* Encode the arguments so CommandLineToArgvW can decode - them from the command line string in the child. */ - char buffer[32768]; /* CreateProcess max command-line length. */ - char* end = buffer + sizeof(buffer); - char* out = buffer; - char const* const* a; - for (a = command; *a; ++a) - { - int quote = !**a; /* Quote the empty string. */ - int slashes = 0; - char const* c; - if (a != command && out != end) { *out++ = ' '; } - for (c = *a; !quote && *c; ++c) - { quote = (*c == ' ' || *c == '\t'); } - if (quote && out != end) { *out++ = '"'; } - for (c = *a; *c; ++c) - { - if (*c == '\\') - { - ++slashes; - } - else - { - if (*c == '"') - { - // Add n+1 backslashes to total 2n+1 before internal '"'. - while(slashes-- >= 0 && out != end) { *out++ = '\\'; } - } - slashes = 0; - } - if (out != end) { *out++ = *c; } - } - if (quote) - { - // Add n backslashes to total 2n before ending '"'. - while (slashes-- > 0 && out != end) { *out++ = '\\'; } - if (out != end) { *out++ = '"'; } - } - } - if(out != end) - { - *out = '\0'; - newCommands[cp->NumberOfCommands] = kwsysEncoding_DupToWide(buffer); - } - else - { - newCommands[cp->NumberOfCommands] = 0; - } - } - if (!newCommands[cp->NumberOfCommands]) - { - /* Out of memory or command line too long. */ - free(newCommands); - return 0; - } - - /* Save the new array of commands. */ - free(cp->Commands); - cp->Commands = newCommands; - cp->NumberOfCommands = newNumberOfCommands; - return 1; -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout) -{ - if(!cp) - { - return; - } - cp->Timeout = timeout; - if(cp->Timeout < 0) - { - cp->Timeout = 0; - } -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir) -{ - if(!cp) - { - return 0; - } - if(cp->WorkingDirectory) - { - free(cp->WorkingDirectory); - cp->WorkingDirectory = 0; - } - if(dir && dir[0]) - { - wchar_t* wdir = kwsysEncoding_DupToWide(dir); - /* We must convert the working directory to a full path. */ - DWORD length = GetFullPathNameW(wdir, 0, 0, 0); - if(length > 0) - { - wchar_t* work_dir = malloc(length*sizeof(wchar_t)); - if(!work_dir) - { - free(wdir); - return 0; - } - if(!GetFullPathNameW(wdir, length, work_dir, 0)) - { - free(work_dir); - free(wdir); - return 0; - } - cp->WorkingDirectory = work_dir; - } - free(wdir); - } - return 1; -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file) -{ - char** pfile; - if(!cp) - { - return 0; - } - switch(pipe) - { - case kwsysProcess_Pipe_STDIN: pfile = &cp->PipeFileSTDIN; break; - case kwsysProcess_Pipe_STDOUT: pfile = &cp->PipeFileSTDOUT; break; - case kwsysProcess_Pipe_STDERR: pfile = &cp->PipeFileSTDERR; break; - default: return 0; - } - if(*pfile) - { - free(*pfile); - *pfile = 0; - } - if(file) - { - *pfile = (char*)malloc(strlen(file)+1); - if(!*pfile) - { - return 0; - } - strcpy(*pfile, file); - } - - /* If we are redirecting the pipe, do not share it or use a native - pipe. */ - if(*pfile) - { - kwsysProcess_SetPipeNative(cp, pipe, 0); - kwsysProcess_SetPipeShared(cp, pipe, 0); - } - - return 1; -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared) -{ - if(!cp) - { - return; - } - - switch(pipe) - { - case kwsysProcess_Pipe_STDIN: cp->PipeSharedSTDIN = shared?1:0; break; - case kwsysProcess_Pipe_STDOUT: cp->PipeSharedSTDOUT = shared?1:0; break; - case kwsysProcess_Pipe_STDERR: cp->PipeSharedSTDERR = shared?1:0; break; - default: return; - } - - /* If we are sharing the pipe, do not redirect it to a file or use a - native pipe. */ - if(shared) - { - kwsysProcess_SetPipeFile(cp, pipe, 0); - kwsysProcess_SetPipeNative(cp, pipe, 0); - } -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, HANDLE p[2]) -{ - HANDLE* pPipeNative = 0; - - if(!cp) - { - return; - } - - switch(pipe) - { - case kwsysProcess_Pipe_STDIN: pPipeNative = cp->PipeNativeSTDIN; break; - case kwsysProcess_Pipe_STDOUT: pPipeNative = cp->PipeNativeSTDOUT; break; - case kwsysProcess_Pipe_STDERR: pPipeNative = cp->PipeNativeSTDERR; break; - default: return; - } - - /* Copy the native pipe handles provided. */ - if(p) - { - pPipeNative[0] = p[0]; - pPipeNative[1] = p[1]; - } - else - { - pPipeNative[0] = 0; - pPipeNative[1] = 0; - } - - /* If we are using a native pipe, do not share it or redirect it to - a file. */ - if(p) - { - kwsysProcess_SetPipeFile(cp, pipe, 0); - kwsysProcess_SetPipeShared(cp, pipe, 0); - } -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) -{ - if(!cp) - { - return 0; - } - - switch(optionId) - { - case kwsysProcess_Option_Detach: return cp->OptionDetach; - case kwsysProcess_Option_HideWindow: return cp->HideWindow; - case kwsysProcess_Option_MergeOutput: return cp->MergeOutput; - case kwsysProcess_Option_Verbatim: return cp->Verbatim; - case kwsysProcess_Option_CreateProcessGroup: - return cp->CreateProcessGroup; - default: return 0; - } -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) -{ - if(!cp) - { - return; - } - - switch(optionId) - { - case kwsysProcess_Option_Detach: cp->OptionDetach = value; break; - case kwsysProcess_Option_HideWindow: cp->HideWindow = value; break; - case kwsysProcess_Option_MergeOutput: cp->MergeOutput = value; break; - case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break; - case kwsysProcess_Option_CreateProcessGroup: - cp->CreateProcessGroup = value; break; - default: break; - } -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_GetState(kwsysProcess* cp) -{ - return cp? cp->State : kwsysProcess_State_Error; -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_GetExitException(kwsysProcess* cp) -{ - return cp? cp->ExitException : kwsysProcess_Exception_Other; -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_GetExitValue(kwsysProcess* cp) -{ - return cp? cp->ExitValue : -1; -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_GetExitCode(kwsysProcess* cp) -{ - return cp? cp->ExitCode : 0; -} - -/*--------------------------------------------------------------------------*/ -const char* kwsysProcess_GetErrorString(kwsysProcess* cp) -{ - if(!cp) - { - return "Process management structure could not be allocated"; - } - else if(cp->State == kwsysProcess_State_Error) - { - return cp->ErrorMessage; - } - return "Success"; -} - -/*--------------------------------------------------------------------------*/ -const char* kwsysProcess_GetExceptionString(kwsysProcess* cp) -{ - if(!cp) - { - return "GetExceptionString called with NULL process management structure"; - } - else if(cp->State == kwsysProcess_State_Exception) - { - return cp->ExitExceptionString; - } - return "No exception"; -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_Execute(kwsysProcess* cp) -{ - int i; - - /* Do not execute a second time. */ - if(!cp || cp->State == kwsysProcess_State_Executing) - { - return; - } - - /* Make sure we have something to run. */ - if(cp->NumberOfCommands < 1) - { - strcpy(cp->ErrorMessage, "No command"); - cp->State = kwsysProcess_State_Error; - return; - } - - /* Initialize the control structure for a new process. */ - if(!kwsysProcessInitialize(cp)) - { - strcpy(cp->ErrorMessage, "Out of memory"); - cp->State = kwsysProcess_State_Error; - return; - } - - /* Save the real working directory of this process and change to - the working directory for the child processes. This is needed - to make pipe file paths evaluate correctly. */ - if(cp->WorkingDirectory) - { - if(!GetCurrentDirectoryW(cp->RealWorkingDirectoryLength, - cp->RealWorkingDirectory)) - { - kwsysProcessCleanup(cp, GetLastError()); - return; - } - SetCurrentDirectoryW(cp->WorkingDirectory); - } - - - /* Setup the stdin pipe for the first process. */ - if(cp->PipeFileSTDIN) - { - /* Create a handle to read a file for stdin. */ - wchar_t* wstdin = kwsysEncoding_DupToWide(cp->PipeFileSTDIN); - DWORD error; - cp->PipeChildStd[0] = - CreateFileW(wstdin, GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ|FILE_SHARE_WRITE, - 0, OPEN_EXISTING, 0, 0); - error = GetLastError(); /* Check now in case free changes this. */ - free(wstdin); - if(cp->PipeChildStd[0] == INVALID_HANDLE_VALUE) - { - kwsysProcessCleanup(cp, error); - return; - } - } - else if(cp->PipeSharedSTDIN) - { - /* Share this process's stdin with the child. */ - kwsysProcessSetupSharedPipe(STD_INPUT_HANDLE, &cp->PipeChildStd[0]); - } - else if(cp->PipeNativeSTDIN[0]) - { - /* Use the provided native pipe. */ - kwsysProcessSetupPipeNative(cp->PipeNativeSTDIN[0], &cp->PipeChildStd[0]); - } - else - { - /* Explicitly give the child no stdin. */ - cp->PipeChildStd[0] = INVALID_HANDLE_VALUE; - } - - /* Create the output pipe for the last process. - We always create this so the pipe thread can run even if we - do not end up giving the write end to the child below. */ - if(!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDOUT].Read, - &cp->Pipe[KWSYSPE_PIPE_STDOUT].Write, 0, 0)) - { - kwsysProcessCleanup(cp, GetLastError()); - return; - } - - if(cp->PipeFileSTDOUT) - { - /* Use a file for stdout. */ - DWORD error = kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[1], - cp->PipeFileSTDOUT); - if(error) - { - kwsysProcessCleanup(cp, error); - return; - } - } - else if(cp->PipeSharedSTDOUT) - { - /* Use the parent stdout. */ - kwsysProcessSetupSharedPipe(STD_OUTPUT_HANDLE, &cp->PipeChildStd[1]); - } - else if(cp->PipeNativeSTDOUT[1]) - { - /* Use the given handle for stdout. */ - kwsysProcessSetupPipeNative(cp->PipeNativeSTDOUT[1], &cp->PipeChildStd[1]); - } - else - { - /* Use our pipe for stdout. Duplicate the handle since our waker - thread will use the original. Do not make it inherited yet. */ - if(!DuplicateHandle(GetCurrentProcess(), - cp->Pipe[KWSYSPE_PIPE_STDOUT].Write, - GetCurrentProcess(), &cp->PipeChildStd[1], - 0, FALSE, DUPLICATE_SAME_ACCESS)) - { - kwsysProcessCleanup(cp, GetLastError()); - return; - } - } - - /* Create stderr pipe to be shared by all processes in the pipeline. - We always create this so the pipe thread can run even if we do not - end up giving the write end to the child below. */ - if(!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDERR].Read, - &cp->Pipe[KWSYSPE_PIPE_STDERR].Write, 0, 0)) - { - kwsysProcessCleanup(cp, GetLastError()); - return; - } - - if(cp->PipeFileSTDERR) - { - /* Use a file for stderr. */ - DWORD error = kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[2], - cp->PipeFileSTDERR); - if(error) - { - kwsysProcessCleanup(cp, error); - return; - } - } - else if(cp->PipeSharedSTDERR) - { - /* Use the parent stderr. */ - kwsysProcessSetupSharedPipe(STD_ERROR_HANDLE, &cp->PipeChildStd[2]); - } - else if(cp->PipeNativeSTDERR[1]) - { - /* Use the given handle for stderr. */ - kwsysProcessSetupPipeNative(cp->PipeNativeSTDERR[1], &cp->PipeChildStd[2]); - } - else - { - /* Use our pipe for stderr. Duplicate the handle since our waker - thread will use the original. Do not make it inherited yet. */ - if(!DuplicateHandle(GetCurrentProcess(), - cp->Pipe[KWSYSPE_PIPE_STDERR].Write, - GetCurrentProcess(), &cp->PipeChildStd[2], - 0, FALSE, DUPLICATE_SAME_ACCESS)) - { - kwsysProcessCleanup(cp, GetLastError()); - return; - } - } - - /* Create the pipeline of processes. */ - { - /* Child startup control data. */ - kwsysProcessCreateInformation si; - HANDLE nextStdInput = cp->PipeChildStd[0]; - - /* Initialize startup info data. */ - ZeroMemory(&si, sizeof(si)); - si.StartupInfo.cb = sizeof(si.StartupInfo); - - /* Decide whether a child window should be shown. */ - si.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW; - si.StartupInfo.wShowWindow = - (unsigned short)(cp->HideWindow?SW_HIDE:SW_SHOWDEFAULT); - - /* Connect the child's output pipes to the threads. */ - si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES; - - for(i=0; i < cp->NumberOfCommands; ++i) - { - /* Setup the process's pipes. */ - si.hStdInput = nextStdInput; - if (i == cp->NumberOfCommands-1) - { - /* The last child gets the overall stdout. */ - nextStdInput = INVALID_HANDLE_VALUE; - si.hStdOutput = cp->PipeChildStd[1]; - } - else - { - /* Create a pipe to sit between the children. */ - HANDLE p[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; - if (!CreatePipe(&p[0], &p[1], 0, 0)) - { - DWORD error = GetLastError(); - if (nextStdInput != cp->PipeChildStd[0]) - { - kwsysProcessCleanupHandle(&nextStdInput); - } - kwsysProcessCleanup(cp, error); - return; - } - nextStdInput = p[0]; - si.hStdOutput = p[1]; - } - si.hStdError = cp->MergeOutput? cp->PipeChildStd[1] : cp->PipeChildStd[2]; - - { - DWORD error = kwsysProcessCreate(cp, i, &si); - - /* Close our copies of pipes used between children. */ - if (si.hStdInput != cp->PipeChildStd[0]) - { - kwsysProcessCleanupHandle(&si.hStdInput); - } - if (si.hStdOutput != cp->PipeChildStd[1]) - { - kwsysProcessCleanupHandle(&si.hStdOutput); - } - if (si.hStdError != cp->PipeChildStd[2] && !cp->MergeOutput) - { - kwsysProcessCleanupHandle(&si.hStdError); - } - if (!error) - { - cp->ProcessEvents[i+1] = cp->ProcessInformation[i].hProcess; - } - else - { - if (nextStdInput != cp->PipeChildStd[0]) - { - kwsysProcessCleanupHandle(&nextStdInput); - } - kwsysProcessCleanup(cp, error); - return; - } - } - } - } - - /* The parent process does not need the child's pipe ends. */ - for (i=0; i < 3; ++i) - { - kwsysProcessCleanupHandle(&cp->PipeChildStd[i]); - } - - /* Restore the working directory. */ - if(cp->RealWorkingDirectory) - { - SetCurrentDirectoryW(cp->RealWorkingDirectory); - free(cp->RealWorkingDirectory); - cp->RealWorkingDirectory = 0; - } - - /* The timeout period starts now. */ - cp->StartTime = kwsysProcessTimeGetCurrent(); - cp->TimeoutTime = kwsysProcessTimeFromDouble(-1); - - /* All processes in the pipeline have been started in suspended - mode. Resume them all now. */ - for(i=0; i < cp->NumberOfCommands; ++i) - { - ResumeThread(cp->ProcessInformation[i].hThread); - } - - /* ---- It is no longer safe to call kwsysProcessCleanup. ----- */ - /* Tell the pipe threads that a process has started. */ - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - ReleaseSemaphore(cp->Pipe[i].Reader.Ready, 1, 0); - ReleaseSemaphore(cp->Pipe[i].Waker.Ready, 1, 0); - } - - /* We don't care about the children's main threads. */ - for(i=0; i < cp->NumberOfCommands; ++i) - { - kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread); - } - - /* No pipe has reported data. */ - cp->CurrentIndex = KWSYSPE_PIPE_COUNT; - cp->PipesLeft = KWSYSPE_PIPE_COUNT; - - /* The process has now started. */ - cp->State = kwsysProcess_State_Executing; - cp->Detached = cp->OptionDetach; -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_Disown(kwsysProcess* cp) -{ - int i; - - /* Make sure we are executing a detached process. */ - if(!cp || !cp->Detached || cp->State != kwsysProcess_State_Executing || - cp->TimeoutExpired || cp->Killed || cp->Terminated) - { - return; - } - - /* Disable the reading threads. */ - kwsysProcessDisablePipeThreads(cp); - - /* Wait for all pipe threads to reset. */ - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - WaitForSingleObject(cp->Pipe[i].Reader.Reset, INFINITE); - WaitForSingleObject(cp->Pipe[i].Waker.Reset, INFINITE); - } - - /* We will not wait for exit, so cleanup now. */ - kwsysProcessCleanup(cp, 0); - - /* The process has been disowned. */ - cp->State = kwsysProcess_State_Disowned; -} - -/*--------------------------------------------------------------------------*/ - -int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length, - double* userTimeout) -{ - kwsysProcessTime userStartTime; - kwsysProcessTime timeoutLength; - kwsysProcessTime timeoutTime; - DWORD timeout; - int user; - int done = 0; - int expired = 0; - int pipeId = kwsysProcess_Pipe_None; - DWORD w; - - /* Make sure we are executing a process. */ - if(!cp || cp->State != kwsysProcess_State_Executing || cp->Killed || - cp->TimeoutExpired) - { - return kwsysProcess_Pipe_None; - } - - /* Record the time at which user timeout period starts. */ - userStartTime = kwsysProcessTimeGetCurrent(); - - /* Calculate the time at which a timeout will expire, and whether it - is the user or process timeout. */ - user = kwsysProcessGetTimeoutTime(cp, userTimeout, &timeoutTime); - - /* Loop until we have a reason to return. */ - while(!done && cp->PipesLeft > 0) - { - /* If we previously got data from a thread, let it know we are - done with the data. */ - if(cp->CurrentIndex < KWSYSPE_PIPE_COUNT) - { - KWSYSPE_DEBUG((stderr, "releasing reader %d\n", cp->CurrentIndex)); - ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0); - cp->CurrentIndex = KWSYSPE_PIPE_COUNT; - } - - /* Setup a timeout if required. */ - if(kwsysProcessGetTimeoutLeft(&timeoutTime, user?userTimeout:0, - &timeoutLength)) - { - /* Timeout has already expired. */ - expired = 1; - break; - } - if(timeoutTime.QuadPart < 0) - { - timeout = INFINITE; - } - else - { - timeout = kwsysProcessTimeToDWORD(timeoutLength); - } - - /* Wait for a pipe's thread to signal or a process to terminate. */ - w = WaitForMultipleObjects(cp->ProcessEventsLength, cp->ProcessEvents, - 0, timeout); - if(w == WAIT_TIMEOUT) - { - /* Timeout has expired. */ - expired = 1; - done = 1; - } - else if(w == WAIT_OBJECT_0) - { - /* Save the index of the reporting thread and release the mutex. - The thread will block until we signal its Empty mutex. */ - cp->CurrentIndex = cp->SharedIndex; - ReleaseSemaphore(cp->SharedIndexMutex, 1, 0); - - /* Data are available or a pipe closed. */ - if(cp->Pipe[cp->CurrentIndex].Closed) - { - /* The pipe closed at the write end. Close the read end and - inform the wakeup thread it is done with this process. */ - kwsysProcessCleanupHandle(&cp->Pipe[cp->CurrentIndex].Read); - ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Waker.Go, 1, 0); - KWSYSPE_DEBUG((stderr, "wakeup %d\n", cp->CurrentIndex)); - --cp->PipesLeft; - } - else if(data && length) - { - /* Report this data. */ - *data = cp->Pipe[cp->CurrentIndex].DataBuffer; - *length = cp->Pipe[cp->CurrentIndex].DataLength; - switch(cp->CurrentIndex) - { - case KWSYSPE_PIPE_STDOUT: - pipeId = kwsysProcess_Pipe_STDOUT; break; - case KWSYSPE_PIPE_STDERR: - pipeId = kwsysProcess_Pipe_STDERR; break; - } - done = 1; - } - } - else - { - /* A process has terminated. */ - kwsysProcessDestroy(cp, w-WAIT_OBJECT_0); - } - } - - /* Update the user timeout. */ - if(userTimeout) - { - kwsysProcessTime userEndTime = kwsysProcessTimeGetCurrent(); - kwsysProcessTime difference = kwsysProcessTimeSubtract(userEndTime, - userStartTime); - double d = kwsysProcessTimeToDouble(difference); - *userTimeout -= d; - if(*userTimeout < 0) - { - *userTimeout = 0; - } - } - - /* Check what happened. */ - if(pipeId) - { - /* Data are ready on a pipe. */ - return pipeId; - } - else if(expired) - { - /* A timeout has expired. */ - if(user) - { - /* The user timeout has expired. It has no time left. */ - return kwsysProcess_Pipe_Timeout; - } - else - { - /* The process timeout has expired. Kill the child now. */ - KWSYSPE_DEBUG((stderr, "killing child because timeout expired\n")); - kwsysProcess_Kill(cp); - cp->TimeoutExpired = 1; - cp->Killed = 0; - return kwsysProcess_Pipe_None; - } - } - else - { - /* The children have terminated and no more data are available. */ - return kwsysProcess_Pipe_None; - } -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) -{ - int i; - int pipe; - - /* Make sure we are executing a process. */ - if(!cp || cp->State != kwsysProcess_State_Executing) - { - return 1; - } - - /* Wait for the process to terminate. Ignore all data. */ - while((pipe = kwsysProcess_WaitForData(cp, 0, 0, userTimeout)) > 0) - { - if(pipe == kwsysProcess_Pipe_Timeout) - { - /* The user timeout has expired. */ - return 0; - } - } - - KWSYSPE_DEBUG((stderr, "no more data\n")); - - /* When the last pipe closes in WaitForData, the loop terminates - without releasing the pipe's thread. Release it now. */ - if(cp->CurrentIndex < KWSYSPE_PIPE_COUNT) - { - KWSYSPE_DEBUG((stderr, "releasing reader %d\n", cp->CurrentIndex)); - ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0); - cp->CurrentIndex = KWSYSPE_PIPE_COUNT; - } - - /* Wait for all pipe threads to reset. */ - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - KWSYSPE_DEBUG((stderr, "waiting reader reset %d\n", i)); - WaitForSingleObject(cp->Pipe[i].Reader.Reset, INFINITE); - KWSYSPE_DEBUG((stderr, "waiting waker reset %d\n", i)); - WaitForSingleObject(cp->Pipe[i].Waker.Reset, INFINITE); - } - - /* ---- It is now safe again to call kwsysProcessCleanup. ----- */ - /* Close all the pipes. */ - kwsysProcessCleanup(cp, 0); - - /* Determine the outcome. */ - if(cp->Killed) - { - /* We killed the child. */ - cp->State = kwsysProcess_State_Killed; - } - else if(cp->TimeoutExpired) - { - /* The timeout expired. */ - cp->State = kwsysProcess_State_Expired; - } - else - { - /* The children exited. Report the outcome of the last process. */ - cp->ExitCode = cp->CommandExitCodes[cp->NumberOfCommands-1]; - if((cp->ExitCode & 0xF0000000) == 0xC0000000) - { - /* Child terminated due to exceptional behavior. */ - cp->State = kwsysProcess_State_Exception; - cp->ExitValue = 1; - kwsysProcessSetExitException(cp, cp->ExitCode); - } - else - { - /* Child exited without exception. */ - cp->State = kwsysProcess_State_Exited; - cp->ExitException = kwsysProcess_Exception_None; - cp->ExitValue = cp->ExitCode; - } - } - - return 1; -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_Interrupt(kwsysProcess* cp) -{ - int i; - /* Make sure we are executing a process. */ - if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired || - cp->Killed) - { - KWSYSPE_DEBUG((stderr, "interrupt: child not executing\n")); - return; - } - - /* Skip actually interrupting the child if it has already terminated. */ - if(cp->Terminated) - { - KWSYSPE_DEBUG((stderr, "interrupt: child already terminated\n")); - return; - } - - /* Interrupt the children. */ - if (cp->CreateProcessGroup) - { - if(cp->ProcessInformation) - { - for(i=0; i < cp->NumberOfCommands; ++i) - { - /* Make sure the process handle isn't closed (e.g. from disowning). */ - if(cp->ProcessInformation[i].hProcess) - { - /* The user created a process group for this process. The group ID - is the process ID for the original process in the group. Note - that we have to use Ctrl+Break: Ctrl+C is not allowed for process - groups. */ - GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, - cp->ProcessInformation[i].dwProcessId); - } - } - } - } - else - { - /* No process group was created. Kill our own process group... */ - GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0); - } -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcess_Kill(kwsysProcess* cp) -{ - int i; - /* Make sure we are executing a process. */ - if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired || - cp->Killed) - { - KWSYSPE_DEBUG((stderr, "kill: child not executing\n")); - return; - } - - /* Disable the reading threads. */ - KWSYSPE_DEBUG((stderr, "kill: disabling pipe threads\n")); - kwsysProcessDisablePipeThreads(cp); - - /* Skip actually killing the child if it has already terminated. */ - if(cp->Terminated) - { - KWSYSPE_DEBUG((stderr, "kill: child already terminated\n")); - return; - } - - /* Kill the children. */ - cp->Killed = 1; - for(i=0; i < cp->NumberOfCommands; ++i) - { - kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId); - /* Remove from global list of processes and close handles. */ - kwsysProcessesRemove(cp->ProcessInformation[i].hProcess); - kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread); - kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess); - } - - /* We are killing the children and ignoring all data. Do not wait - for them to exit. */ -} - -/*--------------------------------------------------------------------------*/ - -/* - Function executed for each pipe's thread. Argument is a pointer to - the kwsysProcessPipeData instance for this thread. -*/ -DWORD WINAPI kwsysProcessPipeThreadRead(LPVOID ptd) -{ - kwsysProcessPipeData* td = (kwsysProcessPipeData*)ptd; - kwsysProcess* cp = td->Process; - - /* Wait for a process to be ready. */ - while((WaitForSingleObject(td->Reader.Ready, INFINITE), !cp->Deleting)) - { - /* Read output from the process for this thread's pipe. */ - kwsysProcessPipeThreadReadPipe(cp, td); - - /* Signal the main thread we have reset for a new process. */ - ReleaseSemaphore(td->Reader.Reset, 1, 0); - } - return 0; -} - -/*--------------------------------------------------------------------------*/ - -/* - Function called in each pipe's thread to handle data for one - execution of a subprocess. -*/ -void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, kwsysProcessPipeData* td) -{ - /* Wait for space in the thread's buffer. */ - while((KWSYSPE_DEBUG((stderr, "wait for read %d\n", td->Index)), - WaitForSingleObject(td->Reader.Go, INFINITE), !td->Closed)) - { - KWSYSPE_DEBUG((stderr, "reading %d\n", td->Index)); - - /* Read data from the pipe. This may block until data are available. */ - if(!ReadFile(td->Read, td->DataBuffer, KWSYSPE_PIPE_BUFFER_SIZE, - &td->DataLength, 0)) - { - if(GetLastError() != ERROR_BROKEN_PIPE) - { - /* UNEXPECTED failure to read the pipe. */ - } - - /* The pipe closed. There are no more data to read. */ - td->Closed = 1; - KWSYSPE_DEBUG((stderr, "read closed %d\n", td->Index)); - } - - KWSYSPE_DEBUG((stderr, "read %d\n", td->Index)); - - /* Wait for our turn to be handled by the main thread. */ - WaitForSingleObject(cp->SharedIndexMutex, INFINITE); - - KWSYSPE_DEBUG((stderr, "reporting read %d\n", td->Index)); - - /* Tell the main thread we have something to report. */ - cp->SharedIndex = td->Index; - ReleaseSemaphore(cp->Full, 1, 0); - } - - /* We were signalled to exit with our buffer empty. Reset the - mutex for a new process. */ - KWSYSPE_DEBUG((stderr, "self releasing reader %d\n", td->Index)); - ReleaseSemaphore(td->Reader.Go, 1, 0); -} - -/*--------------------------------------------------------------------------*/ - -/* - Function executed for each pipe's thread. Argument is a pointer to - the kwsysProcessPipeData instance for this thread. -*/ -DWORD WINAPI kwsysProcessPipeThreadWake(LPVOID ptd) -{ - kwsysProcessPipeData* td = (kwsysProcessPipeData*)ptd; - kwsysProcess* cp = td->Process; - - /* Wait for a process to be ready. */ - while((WaitForSingleObject(td->Waker.Ready, INFINITE), !cp->Deleting)) - { - /* Wait for a possible wakeup. */ - kwsysProcessPipeThreadWakePipe(cp, td); - - /* Signal the main thread we have reset for a new process. */ - ReleaseSemaphore(td->Waker.Reset, 1, 0); - } - return 0; -} - -/*--------------------------------------------------------------------------*/ - -/* - Function called in each pipe's thread to handle reading thread - wakeup for one execution of a subprocess. -*/ -void kwsysProcessPipeThreadWakePipe(kwsysProcess* cp, kwsysProcessPipeData* td) -{ - (void)cp; - - /* Wait for a possible wake command. */ - KWSYSPE_DEBUG((stderr, "wait for wake %d\n", td->Index)); - WaitForSingleObject(td->Waker.Go, INFINITE); - KWSYSPE_DEBUG((stderr, "waking %d\n", td->Index)); - - /* If the pipe is not closed, we need to wake up the reading thread. */ - if(!td->Closed) - { - DWORD dummy; - KWSYSPE_DEBUG((stderr, "waker %d writing byte\n", td->Index)); - WriteFile(td->Write, "", 1, &dummy, 0); - KWSYSPE_DEBUG((stderr, "waker %d wrote byte\n", td->Index)); - } -} - -/*--------------------------------------------------------------------------*/ -/* Initialize a process control structure for kwsysProcess_Execute. */ -int kwsysProcessInitialize(kwsysProcess* cp) -{ - /* Reset internal status flags. */ - cp->TimeoutExpired = 0; - cp->Terminated = 0; - cp->Killed = 0; - cp->ExitException = kwsysProcess_Exception_None; - cp->ExitCode = 1; - cp->ExitValue = 1; - - /* Reset error data. */ - cp->ErrorMessage[0] = 0; - strcpy(cp->ExitExceptionString, "No exception"); - - /* Allocate process information for each process. */ - cp->ProcessInformation = - (PROCESS_INFORMATION*)malloc(sizeof(PROCESS_INFORMATION) * - cp->NumberOfCommands); - if(!cp->ProcessInformation) - { - return 0; - } - ZeroMemory(cp->ProcessInformation, - sizeof(PROCESS_INFORMATION) * cp->NumberOfCommands); - if(cp->CommandExitCodes) - { - free(cp->CommandExitCodes); - } - cp->CommandExitCodes = (DWORD*)malloc(sizeof(DWORD)*cp->NumberOfCommands); - if(!cp->CommandExitCodes) - { - return 0; - } - ZeroMemory(cp->CommandExitCodes, sizeof(DWORD)*cp->NumberOfCommands); - - /* Allocate event wait array. The first event is cp->Full, the rest - are the process termination events. */ - cp->ProcessEvents = (PHANDLE)malloc(sizeof(HANDLE)*(cp->NumberOfCommands+1)); - if(!cp->ProcessEvents) - { - return 0; - } - ZeroMemory(cp->ProcessEvents, sizeof(HANDLE) * (cp->NumberOfCommands+1)); - cp->ProcessEvents[0] = cp->Full; - cp->ProcessEventsLength = cp->NumberOfCommands+1; - - /* Allocate space to save the real working directory of this process. */ - if(cp->WorkingDirectory) - { - cp->RealWorkingDirectoryLength = GetCurrentDirectoryW(0, 0); - if(cp->RealWorkingDirectoryLength > 0) - { - cp->RealWorkingDirectory = malloc(cp->RealWorkingDirectoryLength * sizeof(wchar_t)); - if(!cp->RealWorkingDirectory) - { - return 0; - } - } - } - { - int i; - for (i=0; i < 3; ++i) - { - cp->PipeChildStd[i] = INVALID_HANDLE_VALUE; - } - } - - return 1; -} - -/*--------------------------------------------------------------------------*/ -static DWORD kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn) -{ - DWORD flags; - - /* Check whether the handle is valid for this process. */ - if (in != INVALID_HANDLE_VALUE && GetHandleInformation(in, &flags)) - { - /* Use the handle as-is if it is already inherited. */ - if (flags & HANDLE_FLAG_INHERIT) - { - *out = in; - return ERROR_SUCCESS; - } - - /* Create an inherited copy of this handle. */ - if (DuplicateHandle(GetCurrentProcess(), in, GetCurrentProcess(), out, - 0, TRUE, DUPLICATE_SAME_ACCESS)) - { - return ERROR_SUCCESS; - } - else - { - return GetLastError(); - } - } - else - { - /* The given handle is not valid for this process. Some child - processes may break if they do not have a valid standard handle, - so open NUL to give to the child. */ - SECURITY_ATTRIBUTES sa; - ZeroMemory(&sa, sizeof(sa)); - sa.nLength = (DWORD)sizeof(sa); - sa.bInheritHandle = 1; - *out = CreateFileW(L"NUL", - (isStdIn ? GENERIC_READ : - (GENERIC_WRITE | FILE_READ_ATTRIBUTES)), - FILE_SHARE_READ|FILE_SHARE_WRITE, - &sa, OPEN_EXISTING, 0, 0); - return (*out != INVALID_HANDLE_VALUE) ? ERROR_SUCCESS : GetLastError(); - } -} - -/*--------------------------------------------------------------------------*/ -DWORD kwsysProcessCreate(kwsysProcess* cp, int index, - kwsysProcessCreateInformation* si) -{ - DWORD creationFlags; - DWORD error = ERROR_SUCCESS; - - /* Check if we are currently exiting. */ - if (!kwsysTryEnterCreateProcessSection()) - { - /* The Ctrl handler is currently working on exiting our process. Rather - than return an error code, which could cause incorrect conclusions to be - reached by the caller, we simply hang. (For example, a CMake try_run - configure step might cause the project to configure wrong.) */ - Sleep(INFINITE); - } - - /* Create the child in a suspended state so we can wait until all - children have been created before running any one. */ - creationFlags = CREATE_SUSPENDED; - if (cp->CreateProcessGroup) - { - creationFlags |= CREATE_NEW_PROCESS_GROUP; - } - - /* Create inherited copies of the handles. */ - (error = kwsysProcessCreateChildHandle(&si->StartupInfo.hStdInput, - si->hStdInput, 1)) || - (error = kwsysProcessCreateChildHandle(&si->StartupInfo.hStdOutput, - si->hStdOutput, 0)) || - (error = kwsysProcessCreateChildHandle(&si->StartupInfo.hStdError, - si->hStdError, 0)) || - /* Create the process. */ - (!CreateProcessW(0, cp->Commands[index], 0, 0, TRUE, creationFlags, 0, - 0, &si->StartupInfo, &cp->ProcessInformation[index]) && - (error = GetLastError())); - - /* Close the inherited copies of the handles. */ - if (si->StartupInfo.hStdInput != si->hStdInput) - { - kwsysProcessCleanupHandle(&si->StartupInfo.hStdInput); - } - if (si->StartupInfo.hStdOutput != si->hStdOutput) - { - kwsysProcessCleanupHandle(&si->StartupInfo.hStdOutput); - } - if (si->StartupInfo.hStdError != si->hStdError) - { - kwsysProcessCleanupHandle(&si->StartupInfo.hStdError); - } - - /* Add the process to the global list of processes. */ - if (!error && - !kwsysProcessesAdd(cp->ProcessInformation[index].hProcess, - cp->ProcessInformation[index].dwProcessId, cp->CreateProcessGroup)) - { - /* This failed for some reason. Kill the suspended process. */ - TerminateProcess(cp->ProcessInformation[index].hProcess, 1); - /* And clean up... */ - kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess); - kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hThread); - strcpy(cp->ErrorMessage, "kwsysProcessesAdd function failed"); - error = ERROR_NOT_ENOUGH_MEMORY; /* Most likely reason. */ - } - - /* If the console Ctrl handler is waiting for us, this will release it... */ - kwsysLeaveCreateProcessSection(); - return error; -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcessDestroy(kwsysProcess* cp, int event) -{ - int i; - int index; - - /* Find the process index for the termination event. */ - for(index=0; index < cp->NumberOfCommands; ++index) - { - if(cp->ProcessInformation[index].hProcess == cp->ProcessEvents[event]) - { - break; - } - } - - /* Check the exit code of the process. */ - GetExitCodeProcess(cp->ProcessInformation[index].hProcess, - &cp->CommandExitCodes[index]); - - /* Remove from global list of processes. */ - kwsysProcessesRemove(cp->ProcessInformation[index].hProcess); - - /* Close the process handle for the terminated process. */ - kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess); - - /* Remove the process from the available events. */ - cp->ProcessEventsLength -= 1; - for(i=event; i < cp->ProcessEventsLength; ++i) - { - cp->ProcessEvents[i] = cp->ProcessEvents[i+1]; - } - - /* Check if all processes have terminated. */ - if(cp->ProcessEventsLength == 1) - { - cp->Terminated = 1; - - /* Close our copies of the pipe write handles so the pipe threads - can detect end-of-data. */ - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - /* TODO: If the child created its own child (our grandchild) - which inherited a copy of the pipe write-end then the pipe - may not close and we will still need the waker write pipe. - However we still want to be able to detect end-of-data in the - normal case. The reader thread will have to switch to using - PeekNamedPipe to read the last bit of data from the pipe - without blocking. This is equivalent to using a non-blocking - read on posix. */ - KWSYSPE_DEBUG((stderr, "closing wakeup write %d\n", i)); - kwsysProcessCleanupHandle(&cp->Pipe[i].Write); - } - } -} - -/*--------------------------------------------------------------------------*/ -DWORD kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name) -{ - HANDLE fout; - wchar_t* wname; - DWORD error; - if(!name) - { - return ERROR_INVALID_PARAMETER; - } - - /* Close the existing handle. */ - kwsysProcessCleanupHandle(phandle); - - /* Create a handle to write a file for the pipe. */ - wname = kwsysEncoding_DupToWide(name); - fout = CreateFileW(wname, GENERIC_WRITE, FILE_SHARE_READ, 0, - CREATE_ALWAYS, 0, 0); - error = GetLastError(); - free(wname); - if(fout == INVALID_HANDLE_VALUE) - { - return error; - } - - /* Assign the replacement handle. */ - *phandle = fout; - return ERROR_SUCCESS; -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle) -{ - /* Close the existing handle. */ - kwsysProcessCleanupHandle(handle); - /* Store the new standard handle. */ - *handle = GetStdHandle(nStdHandle); -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle) -{ - /* Close the existing handle. */ - kwsysProcessCleanupHandle(handle); - /* Store the new given handle. */ - *handle = native; -} - -/*--------------------------------------------------------------------------*/ - -/* Close the given handle if it is open. Reset its value to 0. */ -void kwsysProcessCleanupHandle(PHANDLE h) -{ - if(h && *h && *h != INVALID_HANDLE_VALUE && - *h != GetStdHandle(STD_INPUT_HANDLE) && - *h != GetStdHandle(STD_OUTPUT_HANDLE) && - *h != GetStdHandle(STD_ERROR_HANDLE)) - { - CloseHandle(*h); - *h = INVALID_HANDLE_VALUE; - } -} - -/*--------------------------------------------------------------------------*/ - -/* Close all handles created by kwsysProcess_Execute. */ -void kwsysProcessCleanup(kwsysProcess* cp, DWORD error) -{ - int i; - /* If this is an error case, report the error. */ - if(error) - { - /* Construct an error message if one has not been provided already. */ - if(cp->ErrorMessage[0] == 0) - { - /* Format the error message. */ - wchar_t err_msg[KWSYSPE_PIPE_BUFFER_SIZE]; - DWORD length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - err_msg, KWSYSPE_PIPE_BUFFER_SIZE, 0); - if(length < 1) - { - /* FormatMessage failed. Use a default message. */ - _snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, - "Process execution failed with error 0x%X. " - "FormatMessage failed with error 0x%X", - error, GetLastError()); - } - if(!WideCharToMultiByte(CP_UTF8, 0, err_msg, -1, cp->ErrorMessage, - KWSYSPE_PIPE_BUFFER_SIZE, NULL, NULL)) - { - /* WideCharToMultiByte failed. Use a default message. */ - _snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE, - "Process execution failed with error 0x%X. " - "WideCharToMultiByte failed with error 0x%X", - error, GetLastError()); - } - } - - /* Remove trailing period and newline, if any. */ - kwsysProcessCleanErrorMessage(cp); - - /* Set the error state. */ - cp->State = kwsysProcess_State_Error; - - /* Cleanup any processes already started in a suspended state. */ - if(cp->ProcessInformation) - { - for(i=0; i < cp->NumberOfCommands; ++i) - { - if(cp->ProcessInformation[i].hProcess) - { - TerminateProcess(cp->ProcessInformation[i].hProcess, 255); - WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE); - } - } - for(i=0; i < cp->NumberOfCommands; ++i) - { - /* Remove from global list of processes and close handles. */ - kwsysProcessesRemove(cp->ProcessInformation[i].hProcess); - kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread); - kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess); - } - } - - /* Restore the working directory. */ - if(cp->RealWorkingDirectory) - { - SetCurrentDirectoryW(cp->RealWorkingDirectory); - } - } - - /* Free memory. */ - if(cp->ProcessInformation) - { - free(cp->ProcessInformation); - cp->ProcessInformation = 0; - } - if(cp->ProcessEvents) - { - free(cp->ProcessEvents); - cp->ProcessEvents = 0; - } - if(cp->RealWorkingDirectory) - { - free(cp->RealWorkingDirectory); - cp->RealWorkingDirectory = 0; - } - - /* Close each pipe. */ - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - kwsysProcessCleanupHandle(&cp->Pipe[i].Write); - kwsysProcessCleanupHandle(&cp->Pipe[i].Read); - cp->Pipe[i].Closed = 0; - } - for(i=0; i < 3; ++i) - { - kwsysProcessCleanupHandle(&cp->PipeChildStd[i]); - } -} - -/*--------------------------------------------------------------------------*/ -void kwsysProcessCleanErrorMessage(kwsysProcess* cp) -{ - /* Remove trailing period and newline, if any. */ - size_t length = strlen(cp->ErrorMessage); - if(cp->ErrorMessage[length-1] == '\n') - { - cp->ErrorMessage[length-1] = 0; - --length; - if(length > 0 && cp->ErrorMessage[length-1] == '\r') - { - cp->ErrorMessage[length-1] = 0; - --length; - } - } - if(length > 0 && cp->ErrorMessage[length-1] == '.') - { - cp->ErrorMessage[length-1] = 0; - } -} - -/*--------------------------------------------------------------------------*/ -/* Get the time at which either the process or user timeout will - expire. Returns 1 if the user timeout is first, and 0 otherwise. */ -int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, - kwsysProcessTime* timeoutTime) -{ - /* The first time this is called, we need to calculate the time at - which the child will timeout. */ - if(cp->Timeout && cp->TimeoutTime.QuadPart < 0) - { - kwsysProcessTime length = kwsysProcessTimeFromDouble(cp->Timeout); - cp->TimeoutTime = kwsysProcessTimeAdd(cp->StartTime, length); - } - - /* Start with process timeout. */ - *timeoutTime = cp->TimeoutTime; - - /* Check if the user timeout is earlier. */ - if(userTimeout) - { - kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent(); - kwsysProcessTime userTimeoutLength = kwsysProcessTimeFromDouble(*userTimeout); - kwsysProcessTime userTimeoutTime = kwsysProcessTimeAdd(currentTime, - userTimeoutLength); - if(timeoutTime->QuadPart < 0 || - kwsysProcessTimeLess(userTimeoutTime, *timeoutTime)) - { - *timeoutTime = userTimeoutTime; - return 1; - } - } - return 0; -} - -/*--------------------------------------------------------------------------*/ -/* Get the length of time before the given timeout time arrives. - Returns 1 if the time has already arrived, and 0 otherwise. */ -int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, - double* userTimeout, - kwsysProcessTime* timeoutLength) -{ - if(timeoutTime->QuadPart < 0) - { - /* No timeout time has been requested. */ - return 0; - } - else - { - /* Calculate the remaining time. */ - kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent(); - *timeoutLength = kwsysProcessTimeSubtract(*timeoutTime, currentTime); - - if(timeoutLength->QuadPart < 0 && userTimeout && *userTimeout <= 0) - { - /* Caller has explicitly requested a zero timeout. */ - timeoutLength->QuadPart = 0; - } - - if(timeoutLength->QuadPart < 0) - { - /* Timeout has already expired. */ - return 1; - } - else - { - /* There is some time left. */ - return 0; - } - } -} - -/*--------------------------------------------------------------------------*/ -kwsysProcessTime kwsysProcessTimeGetCurrent() -{ - kwsysProcessTime current; - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - current.LowPart = ft.dwLowDateTime; - current.HighPart = ft.dwHighDateTime; - return current; -} - -/*--------------------------------------------------------------------------*/ -DWORD kwsysProcessTimeToDWORD(kwsysProcessTime t) -{ - return (DWORD)(t.QuadPart * 0.0001); -} - -/*--------------------------------------------------------------------------*/ -double kwsysProcessTimeToDouble(kwsysProcessTime t) -{ - return t.QuadPart * 0.0000001; -} - -/*--------------------------------------------------------------------------*/ -kwsysProcessTime kwsysProcessTimeFromDouble(double d) -{ - kwsysProcessTime t; - t.QuadPart = (LONGLONG)(d*10000000); - return t; -} - -/*--------------------------------------------------------------------------*/ -int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2) -{ - return in1.QuadPart < in2.QuadPart; -} - -/*--------------------------------------------------------------------------*/ -kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2) -{ - kwsysProcessTime out; - out.QuadPart = in1.QuadPart + in2.QuadPart; - return out; -} - -/*--------------------------------------------------------------------------*/ -kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2) -{ - kwsysProcessTime out; - out.QuadPart = in1.QuadPart - in2.QuadPart; - return out; -} - -/*--------------------------------------------------------------------------*/ -#define KWSYSPE_CASE(type, str) \ - cp->ExitException = kwsysProcess_Exception_##type; \ - strcpy(cp->ExitExceptionString, str) -static void kwsysProcessSetExitException(kwsysProcess* cp, int code) -{ - switch (code) - { - case STATUS_CONTROL_C_EXIT: - KWSYSPE_CASE(Interrupt, "User interrupt"); break; - - case STATUS_FLOAT_DENORMAL_OPERAND: - KWSYSPE_CASE(Numerical, "Floating-point exception (denormal operand)"); break; - case STATUS_FLOAT_DIVIDE_BY_ZERO: - KWSYSPE_CASE(Numerical, "Divide-by-zero"); break; - case STATUS_FLOAT_INEXACT_RESULT: - KWSYSPE_CASE(Numerical, "Floating-point exception (inexact result)"); break; - case STATUS_FLOAT_INVALID_OPERATION: - KWSYSPE_CASE(Numerical, "Invalid floating-point operation"); break; - case STATUS_FLOAT_OVERFLOW: - KWSYSPE_CASE(Numerical, "Floating-point overflow"); break; - case STATUS_FLOAT_STACK_CHECK: - KWSYSPE_CASE(Numerical, "Floating-point stack check failed"); break; - case STATUS_FLOAT_UNDERFLOW: - KWSYSPE_CASE(Numerical, "Floating-point underflow"); break; -#ifdef STATUS_FLOAT_MULTIPLE_FAULTS - case STATUS_FLOAT_MULTIPLE_FAULTS: - KWSYSPE_CASE(Numerical, "Floating-point exception (multiple faults)"); break; -#endif -#ifdef STATUS_FLOAT_MULTIPLE_TRAPS - case STATUS_FLOAT_MULTIPLE_TRAPS: - KWSYSPE_CASE(Numerical, "Floating-point exception (multiple traps)"); break; -#endif - case STATUS_INTEGER_DIVIDE_BY_ZERO: - KWSYSPE_CASE(Numerical, "Integer divide-by-zero"); break; - case STATUS_INTEGER_OVERFLOW: - KWSYSPE_CASE(Numerical, "Integer overflow"); break; - - case STATUS_DATATYPE_MISALIGNMENT: - KWSYSPE_CASE(Fault, "Datatype misalignment"); break; - case STATUS_ACCESS_VIOLATION: - KWSYSPE_CASE(Fault, "Access violation"); break; - case STATUS_IN_PAGE_ERROR: - KWSYSPE_CASE(Fault, "In-page error"); break; - case STATUS_INVALID_HANDLE: - KWSYSPE_CASE(Fault, "Invalid hanlde"); break; - case STATUS_NONCONTINUABLE_EXCEPTION: - KWSYSPE_CASE(Fault, "Noncontinuable exception"); break; - case STATUS_INVALID_DISPOSITION: - KWSYSPE_CASE(Fault, "Invalid disposition"); break; - case STATUS_ARRAY_BOUNDS_EXCEEDED: - KWSYSPE_CASE(Fault, "Array bounds exceeded"); break; - case STATUS_STACK_OVERFLOW: - KWSYSPE_CASE(Fault, "Stack overflow"); break; - - case STATUS_ILLEGAL_INSTRUCTION: - KWSYSPE_CASE(Illegal, "Illegal instruction"); break; - case STATUS_PRIVILEGED_INSTRUCTION: - KWSYSPE_CASE(Illegal, "Privileged instruction"); break; - - case STATUS_NO_MEMORY: - default: - cp->ExitException = kwsysProcess_Exception_Other; - _snprintf(cp->ExitExceptionString, KWSYSPE_PIPE_BUFFER_SIZE, "Exit code 0x%x\n", code); - break; - } -} -#undef KWSYSPE_CASE - -typedef struct kwsysProcess_List_s kwsysProcess_List; -static kwsysProcess_List* kwsysProcess_List_New(void); -static void kwsysProcess_List_Delete(kwsysProcess_List* self); -static int kwsysProcess_List_Update(kwsysProcess_List* self); -static int kwsysProcess_List_NextProcess(kwsysProcess_List* self); -static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List* self); -static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List* self); - -/*--------------------------------------------------------------------------*/ -/* Windows NT 4 API definitions. */ -#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) -typedef LONG NTSTATUS; -typedef LONG KPRIORITY; -typedef struct _UNICODE_STRING UNICODE_STRING; -struct _UNICODE_STRING -{ - USHORT Length; - USHORT MaximumLength; - PWSTR Buffer; -}; - -/* The process information structure. Declare only enough to get - process identifiers. The rest may be ignored because we use the - NextEntryDelta to move through an array of instances. */ -typedef struct _SYSTEM_PROCESS_INFORMATION SYSTEM_PROCESS_INFORMATION; -typedef SYSTEM_PROCESS_INFORMATION* PSYSTEM_PROCESS_INFORMATION; -struct _SYSTEM_PROCESS_INFORMATION -{ - ULONG NextEntryDelta; - ULONG ThreadCount; - ULONG Reserved1[6]; - LARGE_INTEGER CreateTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER KernelTime; - UNICODE_STRING ProcessName; - KPRIORITY BasePriority; - ULONG ProcessId; - ULONG InheritedFromProcessId; -}; - -/*--------------------------------------------------------------------------*/ -/* Toolhelp32 API definitions. */ -#define TH32CS_SNAPPROCESS 0x00000002 -#if defined(_WIN64) -typedef unsigned __int64 ProcessULONG_PTR; -#else -typedef unsigned long ProcessULONG_PTR; -#endif -typedef struct tagPROCESSENTRY32 PROCESSENTRY32; -typedef PROCESSENTRY32* LPPROCESSENTRY32; -struct tagPROCESSENTRY32 -{ - DWORD dwSize; - DWORD cntUsage; - DWORD th32ProcessID; - ProcessULONG_PTR th32DefaultHeapID; - DWORD th32ModuleID; - DWORD cntThreads; - DWORD th32ParentProcessID; - LONG pcPriClassBase; - DWORD dwFlags; - char szExeFile[MAX_PATH]; -}; - -/*--------------------------------------------------------------------------*/ -/* Windows API function types. */ -typedef HANDLE (WINAPI* CreateToolhelp32SnapshotType)(DWORD, DWORD); -typedef BOOL (WINAPI* Process32FirstType)(HANDLE, LPPROCESSENTRY32); -typedef BOOL (WINAPI* Process32NextType)(HANDLE, LPPROCESSENTRY32); -typedef NTSTATUS (WINAPI* ZwQuerySystemInformationType)(ULONG, PVOID, - ULONG, PULONG); - - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List__New_NT4(kwsysProcess_List* self); -static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self); -static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self); -static void kwsysProcess_List__Delete_Snapshot(kwsysProcess_List* self); -static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self); -static int kwsysProcess_List__Update_Snapshot(kwsysProcess_List* self); -static int kwsysProcess_List__Next_NT4(kwsysProcess_List* self); -static int kwsysProcess_List__Next_Snapshot(kwsysProcess_List* self); -static int kwsysProcess_List__GetProcessId_NT4(kwsysProcess_List* self); -static int kwsysProcess_List__GetProcessId_Snapshot(kwsysProcess_List* self); -static int kwsysProcess_List__GetParentId_NT4(kwsysProcess_List* self); -static int kwsysProcess_List__GetParentId_Snapshot(kwsysProcess_List* self); - -struct kwsysProcess_List_s -{ - /* Implementation switches at runtime based on version of Windows. */ - int NT4; - - /* Implementation functions and data for NT 4. */ - ZwQuerySystemInformationType P_ZwQuerySystemInformation; - char* Buffer; - int BufferSize; - PSYSTEM_PROCESS_INFORMATION CurrentInfo; - - /* Implementation functions and data for other Windows versions. */ - CreateToolhelp32SnapshotType P_CreateToolhelp32Snapshot; - Process32FirstType P_Process32First; - Process32NextType P_Process32Next; - HANDLE Snapshot; - PROCESSENTRY32 CurrentEntry; -}; - -/*--------------------------------------------------------------------------*/ -static kwsysProcess_List* kwsysProcess_List_New(void) -{ - OSVERSIONINFO osv; - kwsysProcess_List* self; - - /* Allocate and initialize the list object. */ - if(!(self = (kwsysProcess_List*)malloc(sizeof(kwsysProcess_List)))) - { - return 0; - } - memset(self, 0, sizeof(*self)); - - /* Select an implementation. */ - ZeroMemory(&osv, sizeof(osv)); - osv.dwOSVersionInfoSize = sizeof(osv); -#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx -# pragma warning (push) -# ifdef __INTEL_COMPILER -# pragma warning (disable:1478) -# else -# pragma warning (disable:4996) -# endif -#endif - GetVersionEx(&osv); -#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx -# pragma warning (pop) -#endif - self->NT4 = (osv.dwPlatformId == VER_PLATFORM_WIN32_NT && - osv.dwMajorVersion < 5)? 1:0; - - /* Initialize the selected implementation. */ - if(!(self->NT4? - kwsysProcess_List__New_NT4(self) : - kwsysProcess_List__New_Snapshot(self))) - { - kwsysProcess_List_Delete(self); - return 0; - } - - /* Update to the current set of processes. */ - if(!kwsysProcess_List_Update(self)) - { - kwsysProcess_List_Delete(self); - return 0; - } - return self; -} - -/*--------------------------------------------------------------------------*/ -static void kwsysProcess_List_Delete(kwsysProcess_List* self) -{ - if(self) - { - if(self->NT4) - { - kwsysProcess_List__Delete_NT4(self); - } - else - { - kwsysProcess_List__Delete_Snapshot(self); - } - free(self); - } -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List_Update(kwsysProcess_List* self) -{ - return self? (self->NT4? - kwsysProcess_List__Update_NT4(self) : - kwsysProcess_List__Update_Snapshot(self)) : 0; -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List_GetCurrentProcessId(kwsysProcess_List* self) -{ - return self? (self->NT4? - kwsysProcess_List__GetProcessId_NT4(self) : - kwsysProcess_List__GetProcessId_Snapshot(self)) : -1; - -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List_GetCurrentParentId(kwsysProcess_List* self) -{ - return self? (self->NT4? - kwsysProcess_List__GetParentId_NT4(self) : - kwsysProcess_List__GetParentId_Snapshot(self)) : -1; - -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List_NextProcess(kwsysProcess_List* self) -{ - return (self? (self->NT4? - kwsysProcess_List__Next_NT4(self) : - kwsysProcess_List__Next_Snapshot(self)) : 0); -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List__New_NT4(kwsysProcess_List* self) -{ - /* Get a handle to the NT runtime module that should already be - loaded in this program. This does not actually increment the - reference count to the module so we do not need to close the - handle. */ - HMODULE hNT = GetModuleHandleW(L"ntdll.dll"); - if(hNT) - { - /* Get pointers to the needed API functions. */ - self->P_ZwQuerySystemInformation = - ((ZwQuerySystemInformationType) - GetProcAddress(hNT, "ZwQuerySystemInformation")); - } - if(!self->P_ZwQuerySystemInformation) - { - return 0; - } - - /* Allocate an initial process information buffer. */ - self->BufferSize = 32768; - self->Buffer = (char*)malloc(self->BufferSize); - return self->Buffer? 1:0; -} - -/*--------------------------------------------------------------------------*/ -static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self) -{ - /* Free the process information buffer. */ - if(self->Buffer) - { - free(self->Buffer); - } -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self) -{ - self->CurrentInfo = 0; - for(;;) - { - /* Query number 5 is for system process list. */ - NTSTATUS status = - self->P_ZwQuerySystemInformation(5, self->Buffer, self->BufferSize, 0); - if(status == STATUS_INFO_LENGTH_MISMATCH) - { - /* The query requires a bigger buffer. */ - int newBufferSize = self->BufferSize * 2; - char* newBuffer = (char*)malloc(newBufferSize); - if(newBuffer) - { - free(self->Buffer); - self->Buffer = newBuffer; - self->BufferSize = newBufferSize; - } - else - { - return 0; - } - } - else if(status >= 0) - { - /* The query succeeded. Initialize traversal of the process list. */ - self->CurrentInfo = (PSYSTEM_PROCESS_INFORMATION)self->Buffer; - return 1; - } - else - { - /* The query failed. */ - return 0; - } - } -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List__Next_NT4(kwsysProcess_List* self) -{ - if(self->CurrentInfo) - { - if(self->CurrentInfo->NextEntryDelta > 0) - { - self->CurrentInfo = ((PSYSTEM_PROCESS_INFORMATION) - ((char*)self->CurrentInfo + - self->CurrentInfo->NextEntryDelta)); - return 1; - } - self->CurrentInfo = 0; - } - return 0; -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List__GetProcessId_NT4(kwsysProcess_List* self) -{ - return self->CurrentInfo? self->CurrentInfo->ProcessId : -1; -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List__GetParentId_NT4(kwsysProcess_List* self) -{ - return self->CurrentInfo? self->CurrentInfo->InheritedFromProcessId : -1; -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List__New_Snapshot(kwsysProcess_List* self) -{ - /* Get a handle to the Windows runtime module that should already be - loaded in this program. This does not actually increment the - reference count to the module so we do not need to close the - handle. */ - HMODULE hKernel = GetModuleHandleW(L"kernel32.dll"); - if(hKernel) - { - self->P_CreateToolhelp32Snapshot = - ((CreateToolhelp32SnapshotType) - GetProcAddress(hKernel, "CreateToolhelp32Snapshot")); - self->P_Process32First = - ((Process32FirstType) - GetProcAddress(hKernel, "Process32First")); - self->P_Process32Next = - ((Process32NextType) - GetProcAddress(hKernel, "Process32Next")); - } - return (self->P_CreateToolhelp32Snapshot && - self->P_Process32First && - self->P_Process32Next)? 1:0; -} - -/*--------------------------------------------------------------------------*/ -static void kwsysProcess_List__Delete_Snapshot(kwsysProcess_List* self) -{ - if(self->Snapshot) - { - CloseHandle(self->Snapshot); - } -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List__Update_Snapshot(kwsysProcess_List* self) -{ - if(self->Snapshot) - { - CloseHandle(self->Snapshot); - } - if(!(self->Snapshot = - self->P_CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0))) - { - return 0; - } - ZeroMemory(&self->CurrentEntry, sizeof(self->CurrentEntry)); - self->CurrentEntry.dwSize = sizeof(self->CurrentEntry); - if(!self->P_Process32First(self->Snapshot, &self->CurrentEntry)) - { - CloseHandle(self->Snapshot); - self->Snapshot = 0; - return 0; - } - return 1; -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List__Next_Snapshot(kwsysProcess_List* self) -{ - if(self->Snapshot) - { - if(self->P_Process32Next(self->Snapshot, &self->CurrentEntry)) - { - return 1; - } - CloseHandle(self->Snapshot); - self->Snapshot = 0; - } - return 0; -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List__GetProcessId_Snapshot(kwsysProcess_List* self) -{ - return self->Snapshot? self->CurrentEntry.th32ProcessID : -1; -} - -/*--------------------------------------------------------------------------*/ -static int kwsysProcess_List__GetParentId_Snapshot(kwsysProcess_List* self) -{ - return self->Snapshot? self->CurrentEntry.th32ParentProcessID : -1; -} - -/*--------------------------------------------------------------------------*/ -static void kwsysProcessKill(DWORD pid) -{ - HANDLE h = OpenProcess(PROCESS_TERMINATE, 0, pid); - if(h) - { - TerminateProcess(h, 255); - WaitForSingleObject(h, INFINITE); - CloseHandle(h); - } -} - -/*--------------------------------------------------------------------------*/ -static void kwsysProcessKillTree(int pid) -{ - kwsysProcess_List* plist = kwsysProcess_List_New(); - kwsysProcessKill(pid); - if(plist) - { - do - { - if(kwsysProcess_List_GetCurrentParentId(plist) == pid) - { - int ppid = kwsysProcess_List_GetCurrentProcessId(plist); - kwsysProcessKillTree(ppid); - } - } while(kwsysProcess_List_NextProcess(plist)); - kwsysProcess_List_Delete(plist); - } -} - -/*--------------------------------------------------------------------------*/ -static void kwsysProcessDisablePipeThreads(kwsysProcess* cp) -{ - int i; - - /* If data were just reported data, release the pipe's thread. */ - if(cp->CurrentIndex < KWSYSPE_PIPE_COUNT) - { - KWSYSPE_DEBUG((stderr, "releasing reader %d\n", cp->CurrentIndex)); - ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0); - cp->CurrentIndex = KWSYSPE_PIPE_COUNT; - } - - /* Wakeup all reading threads that are not on closed pipes. */ - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - /* The wakeup threads will write one byte to the pipe write ends. - If there are no data in the pipe then this is enough to wakeup - the reading threads. If there are already data in the pipe - this may block. We cannot use PeekNamedPipe to check whether - there are data because an outside process might still be - writing data if we are disowning it. Also, PeekNamedPipe will - block if checking a pipe on which the reading thread is - currently calling ReadPipe. Therefore we need a separate - thread to call WriteFile. If it blocks, that is okay because - it will unblock when we close the read end and break the pipe - below. */ - if(cp->Pipe[i].Read) - { - KWSYSPE_DEBUG((stderr, "releasing waker %d\n", i)); - ReleaseSemaphore(cp->Pipe[i].Waker.Go, 1, 0); - } - } - - /* Tell pipe threads to reset until we run another process. */ - while(cp->PipesLeft > 0) - { - /* The waking threads will cause all reading threads to report. - Wait for the next one and save its index. */ - KWSYSPE_DEBUG((stderr, "waiting for reader\n")); - WaitForSingleObject(cp->Full, INFINITE); - cp->CurrentIndex = cp->SharedIndex; - ReleaseSemaphore(cp->SharedIndexMutex, 1, 0); - KWSYSPE_DEBUG((stderr, "got reader %d\n", cp->CurrentIndex)); - - /* We are done reading this pipe. Close its read handle. */ - cp->Pipe[cp->CurrentIndex].Closed = 1; - kwsysProcessCleanupHandle(&cp->Pipe[cp->CurrentIndex].Read); - --cp->PipesLeft; - - /* Tell the reading thread we are done with the data. It will - reset immediately because the pipe is closed. */ - ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0); - } -} - -/*--------------------------------------------------------------------------*/ -/* Global set of executing processes for use by the Ctrl handler. - This global instance will be zero-initialized by the compiler. - - Note that the console Ctrl handler runs on a background thread and so - everything it does must be thread safe. Here, we track the hProcess - HANDLEs directly instead of kwsysProcess instances, so that we don't have - to make kwsysProcess thread safe. */ -typedef struct kwsysProcessInstance_s -{ - HANDLE hProcess; - DWORD dwProcessId; - int NewProcessGroup; /* Whether the process was created in a new group. */ -} kwsysProcessInstance; - -typedef struct kwsysProcessInstances_s -{ - /* Whether we have initialized key fields below, like critical sections. */ - int Initialized; - - /* Ctrl handler runs on a different thread, so we must sync access. */ - CRITICAL_SECTION Lock; - - int Exiting; - size_t Count; - size_t Size; - kwsysProcessInstance* Processes; -} kwsysProcessInstances; -static kwsysProcessInstances kwsysProcesses; - -/*--------------------------------------------------------------------------*/ -/* Initialize critial section and set up console Ctrl handler. You MUST call - this before using any other kwsysProcesses* functions below. */ -static int kwsysProcessesInitialize(void) -{ - /* Initialize everything if not done already. */ - if(!kwsysProcesses.Initialized) - { - InitializeCriticalSection(&kwsysProcesses.Lock); - - /* Set up console ctrl handler. */ - if(!SetConsoleCtrlHandler(kwsysCtrlHandler, TRUE)) - { - return 0; - } - - kwsysProcesses.Initialized = 1; - } - return 1; -} - -/*--------------------------------------------------------------------------*/ -/* The Ctrl handler waits on the global list of processes. To prevent an - orphaned process, do not create a new process if the Ctrl handler is - already running. Do so by using this function to check if it is ok to - create a process. */ -static int kwsysTryEnterCreateProcessSection(void) -{ - /* Enter main critical section; this means creating a process and the Ctrl - handler are mutually exclusive. */ - EnterCriticalSection(&kwsysProcesses.Lock); - /* Indicate to the caller if they can create a process. */ - if(kwsysProcesses.Exiting) - { - LeaveCriticalSection(&kwsysProcesses.Lock); - return 0; - } - else - { - return 1; - } -} - -/*--------------------------------------------------------------------------*/ -/* Matching function on successful kwsysTryEnterCreateProcessSection return. - Make sure you called kwsysProcessesAdd if applicable before calling this.*/ -static void kwsysLeaveCreateProcessSection(void) -{ - LeaveCriticalSection(&kwsysProcesses.Lock); -} - -/*--------------------------------------------------------------------------*/ -/* Add new process to global process list. The Ctrl handler will wait for - the process to exit before it returns. Do not close the process handle - until after calling kwsysProcessesRemove. The newProcessGroup parameter - must be set if the process was created with CREATE_NEW_PROCESS_GROUP. */ -static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessid, - int newProcessGroup) -{ - if(!kwsysProcessesInitialize() || !hProcess || - hProcess == INVALID_HANDLE_VALUE) - { - return 0; - } - - /* Enter the critical section. */ - EnterCriticalSection(&kwsysProcesses.Lock); - - /* Make sure there is enough space for the new process handle. */ - if(kwsysProcesses.Count == kwsysProcesses.Size) - { - size_t newSize; - kwsysProcessInstance *newArray; - /* Start with enough space for a small number of process handles - and double the size each time more is needed. */ - newSize = kwsysProcesses.Size? kwsysProcesses.Size*2 : 4; - - /* Try allocating the new block of memory. */ - if(newArray = (kwsysProcessInstance*)malloc( - newSize*sizeof(kwsysProcessInstance))) - { - /* Copy the old process handles to the new memory. */ - if(kwsysProcesses.Count > 0) - { - memcpy(newArray, kwsysProcesses.Processes, - kwsysProcesses.Count * sizeof(kwsysProcessInstance)); - } - } - else - { - /* Failed to allocate memory for the new process handle set. */ - LeaveCriticalSection(&kwsysProcesses.Lock); - return 0; - } - - /* Free original array. */ - free(kwsysProcesses.Processes); - - /* Update original structure with new allocation. */ - kwsysProcesses.Size = newSize; - kwsysProcesses.Processes = newArray; - } - - /* Append the new process information to the set. */ - kwsysProcesses.Processes[kwsysProcesses.Count].hProcess = hProcess; - kwsysProcesses.Processes[kwsysProcesses.Count].dwProcessId = dwProcessid; - kwsysProcesses.Processes[kwsysProcesses.Count++].NewProcessGroup = - newProcessGroup; - - /* Leave critical section and return success. */ - LeaveCriticalSection(&kwsysProcesses.Lock); - - return 1; -} - -/*--------------------------------------------------------------------------*/ -/* Removes process to global process list. */ -static void kwsysProcessesRemove(HANDLE hProcess) -{ - size_t i; - - if (!hProcess || hProcess == INVALID_HANDLE_VALUE) - { - return; - } - - EnterCriticalSection(&kwsysProcesses.Lock); - - /* Find the given process in the set. */ - for(i=0; i < kwsysProcesses.Count; ++i) - { - if(kwsysProcesses.Processes[i].hProcess == hProcess) - { - break; - } - } - if(i < kwsysProcesses.Count) - { - /* Found it! Remove the process from the set. */ - --kwsysProcesses.Count; - for(; i < kwsysProcesses.Count; ++i) - { - kwsysProcesses.Processes[i] = kwsysProcesses.Processes[i+1]; - } - - /* If this was the last process, free the array. */ - if(kwsysProcesses.Count == 0) - { - kwsysProcesses.Size = 0; - free(kwsysProcesses.Processes); - kwsysProcesses.Processes = 0; - } - } - - LeaveCriticalSection(&kwsysProcesses.Lock); -} - -/*--------------------------------------------------------------------------*/ -static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType) -{ - size_t i; - (void)dwCtrlType; - /* Enter critical section. */ - EnterCriticalSection(&kwsysProcesses.Lock); - - /* Set flag indicating that we are exiting. */ - kwsysProcesses.Exiting = 1; - - /* If some of our processes were created in a new process group, we must - manually interrupt them. They won't otherwise receive a Ctrl+C/Break. */ - for(i=0; i < kwsysProcesses.Count; ++i) - { - if(kwsysProcesses.Processes[i].NewProcessGroup) - { - DWORD groupId = kwsysProcesses.Processes[i].dwProcessId; - if(groupId) - { - GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, groupId); - } - } - } - - /* Wait for each child process to exit. This is the key step that prevents - us from leaving several orphaned children processes running in the - background when the user presses Ctrl+C. */ - for(i=0; i < kwsysProcesses.Count; ++i) - { - WaitForSingleObject(kwsysProcesses.Processes[i].hProcess, INFINITE); - } - - /* Leave critical section. */ - LeaveCriticalSection(&kwsysProcesses.Lock); - - /* Continue on to default Ctrl handler (which calls ExitProcess). */ - return FALSE; -} diff --git a/src/kwsys/README.txt b/src/kwsys/README.txt deleted file mode 100644 index b8191f7..0000000 --- a/src/kwsys/README.txt +++ /dev/null @@ -1,12 +0,0 @@ -KWSys provides a platform-independent API to many common system -features that are implemented differently on every platform. This -library is intended to be shared among many projects, so it has a -configurable namespace. Each project should configure KWSys to use a -namespace unique to itself. See comments in CMakeLists.txt for -details. - -You are probably reading this file in the source tree of a surrounding -project. In that case, see "../README.kwsys" for details of using -KWSys in your project. - -See CONTRIBUTING.rst for instructions to contribute KWSys changes. diff --git a/src/kwsys/System.c b/src/kwsys/System.c deleted file mode 100644 index ccc7e81..0000000 --- a/src/kwsys/System.c +++ /dev/null @@ -1,301 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#include "kwsysPrivate.h" -#include KWSYS_HEADER(System.h) - -/* Work-around CMake dependency scanning limitation. This must - duplicate the above list of headers. */ -#if 0 -# include "System.h.in" -#endif - -#include /* ptrdiff_t */ -#include /* malloc, free */ -#include /* memcpy */ -#include /* isspace */ - -#include - -#if defined(KWSYS_C_HAS_PTRDIFF_T) && KWSYS_C_HAS_PTRDIFF_T -typedef ptrdiff_t kwsysSystem_ptrdiff_t; -#else -typedef int kwsysSystem_ptrdiff_t; -#endif - -/*--------------------------------------------------------------------------*/ -static int kwsysSystem__AppendByte(char* local, - char** begin, char** end, - int* size, char c) -{ - /* Allocate space for the character. */ - if((*end - *begin) >= *size) - { - kwsysSystem_ptrdiff_t length = *end - *begin; - char* newBuffer = (char*)malloc((size_t)(*size*2)); - if(!newBuffer) - { - return 0; - } - memcpy(newBuffer, *begin, (size_t)(length)*sizeof(char)); - if(*begin != local) - { - free(*begin); - } - *begin = newBuffer; - *end = *begin + length; - *size *= 2; - } - - /* Store the character. */ - *(*end)++ = c; - return 1; -} - -/*--------------------------------------------------------------------------*/ -static int kwsysSystem__AppendArgument(char** local, - char*** begin, char*** end, - int* size, - char* arg_local, - char** arg_begin, char** arg_end, - int* arg_size) -{ - /* Append a null-terminator to the argument string. */ - if(!kwsysSystem__AppendByte(arg_local, arg_begin, arg_end, arg_size, '\0')) - { - return 0; - } - - /* Allocate space for the argument pointer. */ - if((*end - *begin) >= *size) - { - kwsysSystem_ptrdiff_t length = *end - *begin; - char** newPointers = (char**)malloc((size_t)(*size)*2*sizeof(char*)); - if(!newPointers) - { - return 0; - } - memcpy(newPointers, *begin, (size_t)(length)*sizeof(char*)); - if(*begin != local) - { - free(*begin); - } - *begin = newPointers; - *end = *begin + length; - *size *= 2; - } - - /* Allocate space for the argument string. */ - **end = (char*)malloc((size_t)(*arg_end - *arg_begin)); - if(!**end) - { - return 0; - } - - /* Store the argument in the command array. */ - memcpy(**end, *arg_begin,(size_t)(*arg_end - *arg_begin)); - ++(*end); - - /* Reset the argument to be empty. */ - *arg_end = *arg_begin; - - return 1; -} - -/*--------------------------------------------------------------------------*/ -#define KWSYSPE_LOCAL_BYTE_COUNT 1024 -#define KWSYSPE_LOCAL_ARGS_COUNT 32 -static char** kwsysSystem__ParseUnixCommand(const char* command, int flags) -{ - /* Create a buffer for argument pointers during parsing. */ - char* local_pointers[KWSYSPE_LOCAL_ARGS_COUNT]; - int pointers_size = KWSYSPE_LOCAL_ARGS_COUNT; - char** pointer_begin = local_pointers; - char** pointer_end = pointer_begin; - - /* Create a buffer for argument strings during parsing. */ - char local_buffer[KWSYSPE_LOCAL_BYTE_COUNT]; - int buffer_size = KWSYSPE_LOCAL_BYTE_COUNT; - char* buffer_begin = local_buffer; - char* buffer_end = buffer_begin; - - /* Parse the command string. Try to behave like a UNIX shell. */ - char** newCommand = 0; - const char* c = command; - int in_argument = 0; - int in_escape = 0; - int in_single = 0; - int in_double = 0; - int failed = 0; - for(;*c; ++c) - { - if(in_escape) - { - /* This character is escaped so do no special handling. */ - if(!in_argument) - { - in_argument = 1; - } - if(!kwsysSystem__AppendByte(local_buffer, &buffer_begin, - &buffer_end, &buffer_size, *c)) - { - failed = 1; - break; - } - in_escape = 0; - } - else if(*c == '\\') - { - /* The next character should be escaped. */ - in_escape = 1; - } - else if(*c == '\'' && !in_double) - { - /* Enter or exit single-quote state. */ - if(in_single) - { - in_single = 0; - } - else - { - in_single = 1; - if(!in_argument) - { - in_argument = 1; - } - } - } - else if(*c == '"' && !in_single) - { - /* Enter or exit double-quote state. */ - if(in_double) - { - in_double = 0; - } - else - { - in_double = 1; - if(!in_argument) - { - in_argument = 1; - } - } - } - else if(isspace((unsigned char) *c)) - { - if(in_argument) - { - if(in_single || in_double) - { - /* This space belongs to a quoted argument. */ - if(!kwsysSystem__AppendByte(local_buffer, &buffer_begin, - &buffer_end, &buffer_size, *c)) - { - failed = 1; - break; - } - } - else - { - /* This argument has been terminated by whitespace. */ - if(!kwsysSystem__AppendArgument(local_pointers, &pointer_begin, - &pointer_end, &pointers_size, - local_buffer, &buffer_begin, - &buffer_end, &buffer_size)) - { - failed = 1; - break; - } - in_argument = 0; - } - } - } - else - { - /* This character belong to an argument. */ - if(!in_argument) - { - in_argument = 1; - } - if(!kwsysSystem__AppendByte(local_buffer, &buffer_begin, - &buffer_end, &buffer_size, *c)) - { - failed = 1; - break; - } - } - } - - /* Finish the last argument. */ - if(in_argument) - { - if(!kwsysSystem__AppendArgument(local_pointers, &pointer_begin, - &pointer_end, &pointers_size, - local_buffer, &buffer_begin, - &buffer_end, &buffer_size)) - { - failed = 1; - } - } - - /* If we still have memory allocate space for the new command - buffer. */ - if(!failed) - { - kwsysSystem_ptrdiff_t n = pointer_end - pointer_begin; - newCommand = (char**)malloc((size_t)(n+1)*sizeof(char*)); - } - - if(newCommand) - { - /* Copy the arguments into the new command buffer. */ - kwsysSystem_ptrdiff_t n = pointer_end - pointer_begin; - memcpy(newCommand, pointer_begin, sizeof(char*)*(size_t)(n)); - newCommand[n] = 0; - } - else - { - /* Free arguments already allocated. */ - while(pointer_end != pointer_begin) - { - free(*(--pointer_end)); - } - } - - /* Free temporary buffers. */ - if(pointer_begin != local_pointers) - { - free(pointer_begin); - } - if(buffer_begin != local_buffer) - { - free(buffer_begin); - } - - /* The flags argument is currently unused. */ - (void)flags; - - /* Return the final command buffer. */ - return newCommand; -} - -/*--------------------------------------------------------------------------*/ -char** kwsysSystem_Parse_CommandForUnix(const char* command, int flags) -{ - /* Validate the flags. */ - if(flags != 0) - { - return 0; - } - - /* Forward to our internal implementation. */ - return kwsysSystem__ParseUnixCommand(command, flags); -} diff --git a/src/kwsys/System.h.in b/src/kwsys/System.h.in deleted file mode 100644 index 3f3d3f4..0000000 --- a/src/kwsys/System.h.in +++ /dev/null @@ -1,69 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#ifndef @KWSYS_NAMESPACE@_System_h -#define @KWSYS_NAMESPACE@_System_h - -#include <@KWSYS_NAMESPACE@/Configure.h> - -/* Redefine all public interface symbol names to be in the proper - namespace. These macros are used internally to kwsys only, and are - not visible to user code. Use kwsysHeaderDump.pl to reproduce - these macros after making changes to the interface. */ -#if !defined(KWSYS_NAMESPACE) -# define kwsys_ns(x) @KWSYS_NAMESPACE@##x -# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT -#endif -#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS -# define kwsysSystem_Parse_CommandForUnix kwsys_ns(System_Parse_CommandForUnix) -#endif - -#if defined(__cplusplus) -extern "C" -{ -#endif - -/** - * Parse a unix-style command line string into separate arguments. - * - * On success, returns a pointer to an array of pointers to individual - * argument strings. Each string is null-terminated and the last - * entry in the array is a NULL pointer (just like argv). It is the - * caller's responsibility to free() the strings and the array of - * pointers to them. - * - * On failure, returns NULL. Failure occurs only on invalid flags or - * when memory cannot be allocated; never due to content of the input - * string. Missing close-quotes are treated as if the necessary - * closing quote appears. - * - * By default single- and double-quoted arguments are supported, and - * any character may be escaped by a backslash. The flags argument is - * reserved for future use, and must be zero (or the call will fail). - */ -kwsysEXPORT char** kwsysSystem_Parse_CommandForUnix(const char* command, - int flags); - -#if defined(__cplusplus) -} /* extern "C" */ -#endif - -/* If we are building a kwsys .c or .cxx file, let it use these macros. - Otherwise, undefine them to keep the namespace clean. */ -#if !defined(KWSYS_NAMESPACE) -# undef kwsys_ns -# undef kwsysEXPORT -# if !defined(KWSYS_NAMESPACE) && !@KWSYS_NAMESPACE@_NAME_IS_KWSYS -# undef kwsysSystem_Parse_CommandForUnix -# endif -#endif - -#endif diff --git a/src/kwsys/kwsysPlatformTests.cmake b/src/kwsys/kwsysPlatformTests.cmake deleted file mode 100644 index 0da0f63..0000000 --- a/src/kwsys/kwsysPlatformTests.cmake +++ /dev/null @@ -1,219 +0,0 @@ -#============================================================================= -# KWSys - Kitware System Library -# Copyright 2000-2009 Kitware, Inc., Insight Software Consortium -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -SET(KWSYS_PLATFORM_TEST_FILE_C kwsysPlatformTestsC.c) -SET(KWSYS_PLATFORM_TEST_FILE_CXX kwsysPlatformTestsCXX.cxx) - -MACRO(KWSYS_PLATFORM_TEST lang var description invert) - IF(NOT DEFINED ${var}_COMPILED) - MESSAGE(STATUS "${description}") - TRY_COMPILE(${var}_COMPILED - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/${KWSYS_PLATFORM_TEST_FILE_${lang}} - COMPILE_DEFINITIONS -DTEST_${var} ${KWSYS_PLATFORM_TEST_DEFINES} ${KWSYS_PLATFORM_TEST_EXTRA_FLAGS} - CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=${KWSYS_PLATFORM_TEST_LINK_LIBRARIES}" - OUTPUT_VARIABLE OUTPUT) - IF(${var}_COMPILED) - FILE(APPEND - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "${description} compiled with the following output:\n${OUTPUT}\n\n") - ELSE() - FILE(APPEND - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "${description} failed to compile with the following output:\n${OUTPUT}\n\n") - ENDIF() - IF(${invert} MATCHES INVERT) - IF(${var}_COMPILED) - MESSAGE(STATUS "${description} - no") - ELSE() - MESSAGE(STATUS "${description} - yes") - ENDIF() - ELSE() - IF(${var}_COMPILED) - MESSAGE(STATUS "${description} - yes") - ELSE() - MESSAGE(STATUS "${description} - no") - ENDIF() - ENDIF() - ENDIF() - IF(${invert} MATCHES INVERT) - IF(${var}_COMPILED) - SET(${var} 0) - ELSE() - SET(${var} 1) - ENDIF() - ELSE() - IF(${var}_COMPILED) - SET(${var} 1) - ELSE() - SET(${var} 0) - ENDIF() - ENDIF() -ENDMACRO() - -MACRO(KWSYS_PLATFORM_TEST_RUN lang var description invert) - IF(NOT DEFINED ${var}) - MESSAGE(STATUS "${description}") - TRY_RUN(${var} ${var}_COMPILED - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/${KWSYS_PLATFORM_TEST_FILE_${lang}} - COMPILE_DEFINITIONS -DTEST_${var} ${KWSYS_PLATFORM_TEST_DEFINES} ${KWSYS_PLATFORM_TEST_EXTRA_FLAGS} - OUTPUT_VARIABLE OUTPUT) - - # Note that ${var} will be a 0 return value on success. - IF(${var}_COMPILED) - IF(${var}) - FILE(APPEND - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "${description} compiled but failed to run with the following output:\n${OUTPUT}\n\n") - ELSE() - FILE(APPEND - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "${description} compiled and ran with the following output:\n${OUTPUT}\n\n") - ENDIF() - ELSE() - FILE(APPEND - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "${description} failed to compile with the following output:\n${OUTPUT}\n\n") - SET(${var} -1 CACHE INTERNAL "${description} failed to compile.") - ENDIF() - - IF(${invert} MATCHES INVERT) - IF(${var}_COMPILED) - IF(${var}) - MESSAGE(STATUS "${description} - yes") - ELSE() - MESSAGE(STATUS "${description} - no") - ENDIF() - ELSE() - MESSAGE(STATUS "${description} - failed to compile") - ENDIF() - ELSE() - IF(${var}_COMPILED) - IF(${var}) - MESSAGE(STATUS "${description} - no") - ELSE() - MESSAGE(STATUS "${description} - yes") - ENDIF() - ELSE() - MESSAGE(STATUS "${description} - failed to compile") - ENDIF() - ENDIF() - ENDIF() - - IF(${invert} MATCHES INVERT) - IF(${var}_COMPILED) - IF(${var}) - SET(${var} 1) - ELSE() - SET(${var} 0) - ENDIF() - ELSE() - SET(${var} 1) - ENDIF() - ELSE() - IF(${var}_COMPILED) - IF(${var}) - SET(${var} 0) - ELSE() - SET(${var} 1) - ENDIF() - ELSE() - SET(${var} 0) - ENDIF() - ENDIF() -ENDMACRO() - -MACRO(KWSYS_PLATFORM_C_TEST var description invert) - SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_C_TEST_DEFINES}) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_C_TEST_EXTRA_FLAGS}) - KWSYS_PLATFORM_TEST(C "${var}" "${description}" "${invert}") - SET(KWSYS_PLATFORM_TEST_DEFINES) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS) -ENDMACRO() - -MACRO(KWSYS_PLATFORM_C_TEST_RUN var description invert) - SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_C_TEST_DEFINES}) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_C_TEST_EXTRA_FLAGS}) - KWSYS_PLATFORM_TEST_RUN(C "${var}" "${description}" "${invert}") - SET(KWSYS_PLATFORM_TEST_DEFINES) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS) -ENDMACRO() - -MACRO(KWSYS_PLATFORM_CXX_TEST var description invert) - SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_CXX_TEST_DEFINES}) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_CXX_TEST_EXTRA_FLAGS}) - SET(KWSYS_PLATFORM_TEST_LINK_LIBRARIES ${KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES}) - KWSYS_PLATFORM_TEST(CXX "${var}" "${description}" "${invert}") - SET(KWSYS_PLATFORM_TEST_DEFINES) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS) - SET(KWSYS_PLATFORM_TEST_LINK_LIBRARIES) -ENDMACRO() - -MACRO(KWSYS_PLATFORM_CXX_TEST_RUN var description invert) - SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_CXX_TEST_DEFINES}) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_CXX_TEST_EXTRA_FLAGS}) - KWSYS_PLATFORM_TEST_RUN(CXX "${var}" "${description}" "${invert}") - SET(KWSYS_PLATFORM_TEST_DEFINES) - SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS) -ENDMACRO() - -#----------------------------------------------------------------------------- -# KWSYS_PLATFORM_INFO_TEST(lang var description) -# -# Compile test named by ${var} and store INFO strings extracted from binary. -MACRO(KWSYS_PLATFORM_INFO_TEST lang var description) - # We can implement this macro on CMake 2.6 and above. - IF("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.6) - SET(${var} "") - ELSE() - # Choose a location for the result binary. - SET(KWSYS_PLATFORM_INFO_FILE - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/${var}.bin) - - # Compile the test binary. - IF(NOT EXISTS ${KWSYS_PLATFORM_INFO_FILE}) - MESSAGE(STATUS "${description}") - TRY_COMPILE(${var}_COMPILED - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/${KWSYS_PLATFORM_TEST_FILE_${lang}} - COMPILE_DEFINITIONS -DTEST_${var} - ${KWSYS_PLATFORM_${lang}_TEST_DEFINES} - ${KWSYS_PLATFORM_${lang}_TEST_EXTRA_FLAGS} - OUTPUT_VARIABLE OUTPUT - COPY_FILE ${KWSYS_PLATFORM_INFO_FILE} - ) - IF(${var}_COMPILED) - FILE(APPEND - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "${description} compiled with the following output:\n${OUTPUT}\n\n") - ELSE() - FILE(APPEND - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "${description} failed to compile with the following output:\n${OUTPUT}\n\n") - ENDIF() - IF(${var}_COMPILED) - MESSAGE(STATUS "${description} - compiled") - ELSE() - MESSAGE(STATUS "${description} - failed") - ENDIF() - ENDIF() - - # Parse info strings out of the compiled binary. - IF(${var}_COMPILED) - FILE(STRINGS ${KWSYS_PLATFORM_INFO_FILE} ${var} REGEX "INFO:[A-Za-z0-9]+\\[[^]]*\\]") - ELSE() - SET(${var} "") - ENDIF() - - SET(KWSYS_PLATFORM_INFO_FILE) - ENDIF() -ENDMACRO() diff --git a/src/kwsys/kwsysPlatformTestsC.c b/src/kwsys/kwsysPlatformTestsC.c deleted file mode 100644 index e602964..0000000 --- a/src/kwsys/kwsysPlatformTestsC.c +++ /dev/null @@ -1,100 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -/* - Macros to define main() in a cross-platform way. - - Usage: - - int KWSYS_PLATFORM_TEST_C_MAIN() - { - return 0; - } - - int KWSYS_PLATFORM_TEST_C_MAIN_ARGS(argc, argv) - { - (void)argc; (void)argv; - return 0; - } -*/ -#if defined(__CLASSIC_C__) -# define KWSYS_PLATFORM_TEST_C_MAIN() \ - main() -# define KWSYS_PLATFORM_TEST_C_MAIN_ARGS(argc, argv) \ - main(argc,argv) int argc; char* argv[]; -#else -# define KWSYS_PLATFORM_TEST_C_MAIN() \ - main(void) -# define KWSYS_PLATFORM_TEST_C_MAIN_ARGS(argc, argv) \ - main(int argc, char* argv[]) -#endif - -/*--------------------------------------------------------------------------*/ -#ifdef TEST_KWSYS_C_HAS_PTRDIFF_T -#include -int f(ptrdiff_t n) { return n > 0; } -int KWSYS_PLATFORM_TEST_C_MAIN() -{ - char* p = 0; - ptrdiff_t d = p - p; - (void)d; - return f(p - p); -} -#endif - -/*--------------------------------------------------------------------------*/ -#ifdef TEST_KWSYS_C_HAS_SSIZE_T -#include -int f(ssize_t n) { return (int)n; } -int KWSYS_PLATFORM_TEST_C_MAIN() -{ - ssize_t n = 0; - return f(n); -} -#endif - -/*--------------------------------------------------------------------------*/ -#ifdef TEST_KWSYS_C_TYPE_MACROS -char* info_macros = -#if defined(__SIZEOF_SHORT__) -"INFO:macro[__SIZEOF_SHORT__]\n" -#endif -#if defined(__SIZEOF_INT__) -"INFO:macro[__SIZEOF_INT__]\n" -#endif -#if defined(__SIZEOF_LONG__) -"INFO:macro[__SIZEOF_LONG__]\n" -#endif -#if defined(__SIZEOF_LONG_LONG__) -"INFO:macro[__SIZEOF_LONG_LONG__]\n" -#endif -#if defined(__SHORT_MAX__) -"INFO:macro[__SHORT_MAX__]\n" -#endif -#if defined(__INT_MAX__) -"INFO:macro[__INT_MAX__]\n" -#endif -#if defined(__LONG_MAX__) -"INFO:macro[__LONG_MAX__]\n" -#endif -#if defined(__LONG_LONG_MAX__) -"INFO:macro[__LONG_LONG_MAX__]\n" -#endif - ""; - -int KWSYS_PLATFORM_TEST_C_MAIN_ARGS(argc, argv) -{ - int require = 0; - require += info_macros[argc]; - (void)argv; - return require; -} -#endif diff --git a/src/kwsys/kwsysPlatformTestsCXX.cxx b/src/kwsys/kwsysPlatformTestsCXX.cxx deleted file mode 100644 index 1596fe4..0000000 --- a/src/kwsys/kwsysPlatformTestsCXX.cxx +++ /dev/null @@ -1,699 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -// Setup for tests that use result of stl namespace test. -#if defined(KWSYS_STL_HAVE_STD) -# if KWSYS_STL_HAVE_STD -# define kwsys_stl std -# else -# define kwsys_stl -# endif -#endif - -// Setup for tests that use iostreams. -#if defined(KWSYS_IOS_USE_ANSI) && defined(KWSYS_IOS_HAVE_STD) -# if defined(_MSC_VER) -# pragma warning (push,1) -# endif -# if KWSYS_IOS_USE_ANSI -# include -# else -# include -# endif -# if defined(_MSC_VER) -# pragma warning (pop) -# endif -# if KWSYS_IOS_HAVE_STD -# define kwsys_ios std -# else -# define kwsys_ios -# endif -#endif - -#ifdef TEST_KWSYS_STL_HAVE_STD -#include -void f(std ::list*) {} -int main() { return 0; } -#endif - -#ifdef TEST_KWSYS_IOS_USE_ANSI -#include -int main() { return 0; } -#endif - -#ifdef TEST_KWSYS_IOS_HAVE_STD -#include -void f(std ::ostream*) {} -int main() { return 0; } -#endif - -#ifdef TEST_KWSYS_IOS_USE_SSTREAM -#include -#if defined(__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ == 96 -# error "GCC 2.96 stringstream is buggy" -#endif -int main() -{ - std ::ostringstream ostr; - ostr << "hello"; - if(ostr.str().size() == 5) - { - return 0; - } - return -1; -} -#endif - -#ifdef TEST_KWSYS_IOS_USE_STRSTREAM_H -#include -int main() { return 0; } -#endif - -#ifdef TEST_KWSYS_IOS_USE_STRSTREA_H -#include -int main() { return 0; } -#endif - -#ifdef TEST_KWSYS_STL_STRING_HAVE_OSTREAM -# include -# include -void f(ostream& os, const kwsys_stl::string& s) { os << s; } -int main() { return 0; } -#endif - -#ifdef TEST_KWSYS_STL_STRING_HAVE_ISTREAM -# include -# include -void f(istream& is, kwsys_stl::string& s) { is >> s; } -int main() { return 0; } -#endif - -#ifdef TEST_KWSYS_STL_STRING_HAVE_NEQ_CHAR -# include -bool f(const kwsys_stl::string& s) { return s != ""; } -int main() { return 0; } -#endif - -#ifdef TEST_KWSYS_CXX_HAS_CSTDIO -#include -int main() { return 0; } -#endif - -#ifdef TEST_KWSYS_CXX_HAS_CSTDDEF -#include -void f(size_t) {} -int main() { return 0; } -#endif - -#ifdef TEST_KWSYS_CXX_HAS_LONG_LONG -long long f(long long n) { return n; } -int main() -{ - long long n = 0; - return static_cast(f(n)); -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS___INT64 -__int64 f(__int64 n) { return n; } -int main() -{ - __int64 n = 0; - return static_cast(f(n)); -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_NULL_TEMPLATE_ARGS -template class A; -template int f(A&); -template class A -{ -public: - // "friend int f<>(A&)" would conform - friend int f(A&); -private: - int x; -}; - -template int f(A& a) { return a.x = 0; } -template int f(A&); - -int main() -{ - A a; - return f(a); -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_MEMBER_TEMPLATES -template -class A -{ -public: - U u; - A(): u(0) {} - template V m(V* p) { return *p = u; } -}; - -int main() -{ - A a; - int s = 1; - return a.m(&s); -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_FULL_SPECIALIZATION -template struct A {}; -template <> struct A -{ - static int f() { return 0; } -}; -int main() { return A::f(); } -#endif - -#ifdef TEST_KWSYS_CXX_HAS_ARGUMENT_DEPENDENT_LOOKUP -namespace N -{ - class A {}; - int f(A*) { return 0; } -} -void f(void*); -int main() -{ - N::A* a = 0; - return f(a); -} -#endif - -#ifdef TEST_KWSYS_STL_HAS_ITERATOR_TRAITS -#include -#include -void f(kwsys_stl::iterator_traits::iterator>::iterator_category const&) {} -int main() { return 0; } -#endif - -#ifdef TEST_KWSYS_STL_HAS_ITERATOR_CATEGORY -#include -#include -void f(kwsys_stl::list::iterator x) { kwsys_stl::iterator_category(x); } -int main() { return 0; } -#endif - -#ifdef TEST_KWSYS_STL_HAS___ITERATOR_CATEGORY -#include -#include -void f(kwsys_stl::list::iterator x) { kwsys_stl::__iterator_category(x); } -int main() { return 0; } -#endif - -#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_TEMPLATE -#include -template -void f(const Alloc&) -{ - typedef typename Alloc::size_type alloc_size_type; -} -int main() -{ - f(kwsys_stl::allocator()); - return 0; -} -#endif - -#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_NONTEMPLATE -#include -void f(kwsys_stl::allocator::size_type const&) {} -int main() { return 0; } -#endif - -#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_REBIND -#include -template -void f(const T&, const Alloc&) -{ - typedef typename Alloc::template rebind::other alloc_type; -} -int main() -{ - f(0, kwsys_stl::allocator()); - return 0; -} -#endif - -#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_MAX_SIZE_ARGUMENT -#include -void f(kwsys_stl::allocator const& a) -{ - a.max_size(sizeof(int)); -} -int main() -{ - f(kwsys_stl::allocator()); - return 0; -} -#endif - -#ifdef TEST_KWSYS_STL_HAS_ALLOCATOR_OBJECTS -#include -void f(kwsys_stl::vector const& v1) -{ - kwsys_stl::vector(1, 1, v1.get_allocator()); -} -int main() -{ - f(kwsys_stl::vector()); - return 0; -} -#endif - -#ifdef TEST_KWSYS_STAT_HAS_ST_MTIM -#include -#include -#include -int main() -{ - struct stat stat1; - (void)stat1.st_mtim.tv_sec; - (void)stat1.st_mtim.tv_nsec; - return 0; -} -#endif - -#ifdef TEST_KWSYS_CXX_SAME_LONG_AND___INT64 -void function(long**) {} -int main() -{ - __int64** p = 0; - function(p); - return 0; -} -#endif - -#ifdef TEST_KWSYS_CXX_SAME_LONG_LONG_AND___INT64 -void function(long long**) {} -int main() -{ - __int64** p = 0; - function(p); - return 0; -} -#endif - -#ifdef TEST_KWSYS_CAN_CONVERT_UI64_TO_DOUBLE -void function(double& l, unsigned __int64 const& r) -{ - l = static_cast(r); -} - -int main() -{ - double tTo = 0.0; - unsigned __int64 tFrom = 0; - function(tTo, tFrom); - return 0; -} -#endif - -#ifdef TEST_KWSYS_IOS_HAVE_BINARY -int test_binary(int, ...) -{ - return 0; -} -int main() -{ - return test_binary(1, kwsys_ios::ios::binary); -} -#endif - -#ifdef TEST_KWSYS_IOS_HAS_ISTREAM_LONG_LONG -int test_istream(kwsys_ios::istream& is, long long& x) -{ - return (is >> x)? 1:0; -} -int main() -{ - long long x = 0; - return test_istream(kwsys_ios::cin, x); -} -#endif - -#ifdef TEST_KWSYS_IOS_HAS_OSTREAM_LONG_LONG -int test_ostream(kwsys_ios::ostream& os, long long x) -{ - return (os << x)? 1:0; -} -int main() -{ - long long x = 0; - return test_ostream(kwsys_ios::cout, x); -} -#endif - -#ifdef TEST_KWSYS_IOS_HAS_ISTREAM___INT64 -int test_istream(kwsys_ios::istream& is, __int64& x) -{ - return (is >> x)? 1:0; -} -int main() -{ - __int64 x = 0; - return test_istream(kwsys_ios::cin, x); -} -#endif - -#ifdef TEST_KWSYS_IOS_HAS_OSTREAM___INT64 -int test_ostream(kwsys_ios::ostream& os, __int64 x) -{ - return (os << x)? 1:0; -} -int main() -{ - __int64 x = 0; - return test_ostream(kwsys_ios::cout, x); -} -#endif - -#ifdef TEST_KWSYS_CHAR_IS_SIGNED -/* Return 0 for char signed and 1 for char unsigned. */ -int main() -{ - unsigned char uc = 255; - return (*reinterpret_cast(&uc) < 0)?0:1; -} -#endif - -#ifdef TEST_KWSYS_LFS_WORKS -/* Return 0 when LFS is available and 1 otherwise. */ -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE -#define _LARGE_FILES -#define _FILE_OFFSET_BITS 64 -#include -#include -#include -#if KWSYS_CXX_HAS_CSTDIO -# include -#endif -#include - -int main(int, char **argv) -{ - /* check that off_t can hold 2^63 - 1 and perform basic operations... */ -#define OFF_T_64 (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) - if (OFF_T_64 % 2147483647 != 1) - return 1; - - // stat breaks on SCO OpenServer - struct stat buf; - stat( argv[0], &buf ); - if (!S_ISREG(buf.st_mode)) - return 2; - - FILE *file = fopen( argv[0], "r" ); - off_t offset = ftello( file ); - fseek( file, offset, SEEK_CUR ); - fclose( file ); - return 0; -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_SETENV -#include -int main() -{ - return setenv("A", "B", 1); -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_UNSETENV -#include -int main() -{ - unsetenv("A"); - return 0; -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H -#include -int main() -{ - char* e = environ[0]; - return e? 0:1; -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_GETLOADAVG -// Match feature definitions from SystemInformation.cxx -#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) -# define _GNU_SOURCE -#endif -#include -int main() -{ - double loadavg[3] = { 0.0, 0.0, 0.0 }; - return getloadavg(loadavg, 3); -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_RLIMIT64 -# if defined(KWSYS_HAS_LFS) -# define _LARGEFILE_SOURCE -# define _LARGEFILE64_SOURCE -# define _LARGE_FILES -# define _FILE_OFFSET_BITS 64 -# endif -# include -int main() -{ - struct rlimit64 rlim; - return getrlimit64(0,&rlim); -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_ATOLL -#include -int main() -{ - const char *str="1024"; - return static_cast(atoll(str)); -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_ATOL -#include -int main() -{ - const char *str="1024"; - return static_cast(atol(str)); -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS__ATOI64 -#include -int main() -{ - const char *str="1024"; - return static_cast(_atoi64(str)); -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_UTIMES -#include -int main() -{ - struct timeval* current_time = 0; - return utimes("/example", current_time); -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_UTIMENSAT -#include -#include -int main() -{ - struct timespec times[2] = {{0,UTIME_OMIT},{0,UTIME_NOW}}; - return utimensat(AT_FDCWD, "/example", times, AT_SYMLINK_NOFOLLOW); -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_BACKTRACE -#if defined(__PATHSCALE__) || defined(__PATHCC__) \ - || (defined(__LSB_VERSION__) && (__LSB_VERSION__ < 41)) -backtrace doesnt work with this compiler or os -#endif -#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) -# define _GNU_SOURCE -#endif -#include -int main() -{ - void *stackSymbols[256]; - backtrace(stackSymbols,256); - backtrace_symbols(&stackSymbols[0],1); - return 0; -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_DLADDR -#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) -# define _GNU_SOURCE -#endif -#include -int main() -{ - Dl_info info; - int ierr=dladdr((void*)main,&info); - return 0; -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_CXXABI -#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) -# define _GNU_SOURCE -#endif -#if defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5130 \ - && __linux && __SUNPRO_CC_COMPAT == 'G' -# include -#endif -#include -int main() -{ - int status = 0; - size_t bufferLen = 512; - char buffer[512] = {'\0'}; - const char *function="_ZN5kwsys17SystemInformation15GetProgramStackEii"; - char *demangledFunction = - abi::__cxa_demangle(function, buffer, &bufferLen, &status); - return status; -} -#endif - -#ifdef TEST_KWSYS_CXX_TYPE_INFO -/* Collect fundamental type information and save it to a CMake script. */ - -/* Include limits.h to get macros indicating long long and __int64. - Note that certain compilers need special macros to define these - macros in limits.h. */ -#if defined(_MSC_VER) && !defined(_MSC_EXTENSIONS) -# define _MSC_EXTENSIONS -#endif -#if defined(__GNUC__) && __GNUC__ < 3 -# define _GNU_SOURCE -#endif -#include - -#include -#include - -/* Due to shell differences and limitations of ADD_DEFINITIONS the - KWSYS_CXX_TYPE_INFO_FILE macro will sometimes have double quotes - and sometimes not. This macro will make sure the value is treated - as a double-quoted string. */ -#define TO_STRING(x) TO_STRING0(x) -#define TO_STRING0(x) TO_STRING1(x) -#define TO_STRING1(x) #x - -void f() {} - -int main() -{ - /* Construct the output file name. Some preprocessors will add an - extra level of double quotes, so strip them. */ - char fbuf[] = TO_STRING(KWSYS_CXX_TYPE_INFO_FILE); - char* fname = fbuf; - if(fname[0] == '"') - { - ++fname; - int len = static_cast(strlen(fname)); - if(len > 0 && fname[len-1] == '"') - { - fname[len-1] = 0; - } - } - - /* Try to open the output file. */ - if(FILE* fout = fopen(fname, "w")) - { - /* Set the size of standard types. */ - fprintf(fout, "SET(KWSYS_SIZEOF_CHAR %d)\n", static_cast(sizeof(char))); - fprintf(fout, "SET(KWSYS_SIZEOF_SHORT %d)\n", static_cast(sizeof(short))); - fprintf(fout, "SET(KWSYS_SIZEOF_INT %d)\n", static_cast(sizeof(int))); - fprintf(fout, "SET(KWSYS_SIZEOF_LONG %d)\n", static_cast(sizeof(long))); - - /* Set the size of some non-standard but common types. */ - /* Check for a limits.h macro for long long to see if the type exists. */ -#if defined(LLONG_MAX) || defined(LONG_LONG_MAX) || defined(LONGLONG_MAX) - fprintf(fout, "SET(KWSYS_SIZEOF_LONG_LONG %d)\n", static_cast(sizeof(long long))); -#else - fprintf(fout, "SET(KWSYS_SIZEOF_LONG_LONG 0) # No long long available.\n"); -#endif - /* Check for a limits.h macro for __int64 to see if the type exists. */ -#if defined(_I64_MIN) - fprintf(fout, "SET(KWSYS_SIZEOF___INT64 %d)\n", static_cast(sizeof(__int64))); -#else - fprintf(fout, "SET(KWSYS_SIZEOF___INT64 0) # No __int64 available.\n"); -#endif - - /* Set the size of some pointer types. */ - fprintf(fout, "SET(KWSYS_SIZEOF_PDATA %d)\n", static_cast(sizeof(void*))); - fprintf(fout, "SET(KWSYS_SIZEOF_PFUNC %d)\n", static_cast(sizeof(&f))); - - /* Set whether the native type "char" is signed or unsigned. */ - unsigned char uc = 255; - fprintf(fout, "SET(KWSYS_CHAR_IS_SIGNED %d)\n", - (*reinterpret_cast(&uc) < 0)?1:0); - - fclose(fout); - return 0; - } - else - { - fprintf(stderr, "Failed to write fundamental type info to \"%s\".\n", - fname); - return 1; - } -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_BORLAND_ASM -int main() -{ - int a = 1; - __asm { - xor EBX, EBX; - mov a, EBX; - } - - return a; -} -#endif - -#ifdef TEST_KWSYS_CXX_HAS_BORLAND_ASM_CPUID -int main() -{ - int a = 0; - __asm { - xor EAX, EAX; - cpuid; - mov a, EAX; - } - - return a; -} -#endif - -#ifdef TEST_KWSYS_STL_HAS_WSTRING -#include -void f(std ::wstring*) {} -int main() { return 0; } -#endif diff --git a/src/kwsys/kwsysPrivate.h b/src/kwsys/kwsysPrivate.h deleted file mode 100644 index 3a26c26..0000000 --- a/src/kwsys/kwsysPrivate.h +++ /dev/null @@ -1,41 +0,0 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2009 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ -#ifndef KWSYS_NAMESPACE -# error "Do not include kwsysPrivate.h outside of kwsys c and cxx files." -#endif - -#ifndef _kwsysPrivate_h -#define _kwsysPrivate_h - -/* - Define KWSYS_HEADER macro to help the c and cxx files include kwsys - headers from the configured namespace directory. The macro can be - used like this: - - #include KWSYS_HEADER(Directory.hxx) - #include KWSYS_HEADER(std/vector) -*/ -#define KWSYS_HEADER(x) KWSYS_HEADER0(KWSYS_NAMESPACE/x) -#define KWSYS_HEADER0(x) KWSYS_HEADER1(x) -#define KWSYS_HEADER1(x) - -/* - Define KWSYS_NAMESPACE_STRING to be a string constant containing the - name configured for this instance of the kwsys library. -*/ -#define KWSYS_NAMESPACE_STRING KWSYS_NAMESPACE_STRING0(KWSYS_NAMESPACE) -#define KWSYS_NAMESPACE_STRING0(x) KWSYS_NAMESPACE_STRING1(x) -#define KWSYS_NAMESPACE_STRING1(x) #x - -#else -# error "kwsysPrivate.h included multiple times." -#endif -- cgit v0.12