| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file Copyright.txt or https://cmake.org/licensing for details. */ | |
| #include <cstddef> | |
| #include <iostream> | |
| #include <string> | |
| #include <vector> | |
| #include <cm/memory> | |
| #include <CoreFoundation/CoreFoundation.h> | |
| #include "cmsys/FStream.hxx" | |
| #include "cmsys/Process.h" | |
| #include "cmsys/SystemTools.hxx" | |
| // For the PATH_MAX constant | |
| #include <sys/syslimits.h> | |
| #define DebugError(x) \ | |
| ofs << x << std::endl; \ | |
| std::cout << x << std::endl | |
| int main(int argc, char* argv[]) | |
| { | |
| // if ( cmsys::SystemTools::FileExists( | |
| cmsys::ofstream ofs("/tmp/output.txt"); | |
| CFStringRef fileName; | |
| CFBundleRef appBundle; | |
| CFURLRef scriptFileURL; | |
| // get CF URL for script | |
| if (!(appBundle = CFBundleGetMainBundle())) { | |
| DebugError("Cannot get main bundle"); | |
| return 1; | |
| } | |
| fileName = CFSTR("RuntimeScript"); | |
| if (!(scriptFileURL = | |
| CFBundleCopyResourceURL(appBundle, fileName, nullptr, nullptr))) { | |
| DebugError("CFBundleCopyResourceURL failed"); | |
| return 1; | |
| } | |
| // create path string | |
| auto path = cm::make_unique<UInt8[]>(PATH_MAX); | |
| if (!path) { | |
| return 1; | |
| } | |
| // get the file system path of the url as a cstring | |
| // in an encoding suitable for posix apis | |
| if (!CFURLGetFileSystemRepresentation(scriptFileURL, true, path.get(), | |
| PATH_MAX)) { | |
| DebugError("CFURLGetFileSystemRepresentation failed"); | |
| return 1; | |
| } | |
| // dispose of the CF variable | |
| CFRelease(scriptFileURL); | |
| std::string fullScriptPath = reinterpret_cast<char*>(path.get()); | |
| path.reset(); | |
| if (!cmsys::SystemTools::FileExists(fullScriptPath)) { | |
| return 1; | |
| } | |
| std::string scriptDirectory = | |
| cmsys::SystemTools::GetFilenamePath(fullScriptPath); | |
| ofs << fullScriptPath << std::endl; | |
| std::vector<const char*> args; | |
| args.push_back(fullScriptPath.c_str()); | |
| int cc; | |
| for (cc = 1; cc < argc; ++cc) { | |
| args.push_back(argv[cc]); | |
| } | |
| args.push_back(nullptr); | |
| cmsysProcess* cp = cmsysProcess_New(); | |
| cmsysProcess_SetCommand(cp, args.data()); | |
| cmsysProcess_SetWorkingDirectory(cp, scriptDirectory.c_str()); | |
| cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); | |
| cmsysProcess_SetTimeout(cp, 0); | |
| cmsysProcess_Execute(cp); | |
| char* data; | |
| int length; | |
| while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) { | |
| // Translate NULL characters in the output into valid text. | |
| for (int i = 0; i < length; ++i) { | |
| if (data[i] == '\0') { | |
| data[i] = ' '; | |
| } | |
| } | |
| std::cout.write(data, length); | |
| } | |
| cmsysProcess_WaitForExit(cp, nullptr); | |
| bool result = true; | |
| if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) { | |
| if (cmsysProcess_GetExitValue(cp) != 0) { | |
| result = false; | |
| } | |
| } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exception) { | |
| const char* exception_str = cmsysProcess_GetExceptionString(cp); | |
| std::cerr << exception_str << std::endl; | |
| result = false; | |
| } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Error) { | |
| const char* error_str = cmsysProcess_GetErrorString(cp); | |
| std::cerr << error_str << std::endl; | |
| result = false; | |
| } else if (cmsysProcess_GetState(cp) == cmsysProcess_State_Expired) { | |
| const char* error_str = "Process terminated due to timeout\n"; | |
| std::cerr << error_str << std::endl; | |
| result = false; | |
| } | |
| cmsysProcess_Delete(cp); | |
| return 0; | |
| } |