exe.ipp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // Copyright (c) 2022 Klemens D. Morgenstern
  2. // Copyright (c) 2022 Samuel Venable
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_PROCESS_V2_IMPL_EXE_IPP
  7. #define BOOST_PROCESS_V2_IMPL_EXE_IPP
  8. #include <boost/process/v2/detail/config.hpp>
  9. #include <boost/process/v2/detail/last_error.hpp>
  10. #include <boost/process/v2/detail/throw_error.hpp>
  11. #include <boost/process/v2/ext/detail/proc_info.hpp>
  12. #include <boost/process/v2/ext/exe.hpp>
  13. #include <string>
  14. #include <vector>
  15. #if defined(BOOST_PROCESS_V2_WINDOWS)
  16. #include <windows.h>
  17. #else
  18. #include <climits>
  19. #endif
  20. #if (defined(__APPLE__) && defined(__MACH__))
  21. #include <sys/proc_info.h>
  22. #include <libproc.h>
  23. #endif
  24. #if (defined(BOOST_PROCESS_V2_WINDOWS) || defined(__linux__) || defined(__ANDROID__) || defined(__sun))
  25. #include <cstdlib>
  26. #endif
  27. #if (defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__))
  28. #include <sys/types.h>
  29. #include <sys/sysctl.h>
  30. #if !defined(__FreeBSD__)
  31. #include <alloca.h>
  32. #endif
  33. #endif
  34. #if defined(__OpenBSD__)
  35. #include <boost/process/v2/ext/cwd.hpp>
  36. #include <boost/process/v2/ext/cmd.hpp>
  37. #include <boost/process/v2/ext/env.hpp>
  38. #include <boost/algorithm/string.hpp>
  39. #include <boost/algorithm/string/split.hpp>
  40. #include <boost/algorithm/string/classification.hpp>
  41. #include <sys/types.h>
  42. #include <sys/param.h>
  43. #include <sys/sysctl.h>
  44. #include <kvm.h>
  45. #endif
  46. BOOST_PROCESS_V2_BEGIN_NAMESPACE
  47. namespace ext {
  48. #if defined(BOOST_PROCESS_V2_WINDOWS)
  49. filesystem::path exe(HANDLE process_handle)
  50. {
  51. boost::system::error_code ec;
  52. auto res = exe(process_handle, ec);
  53. if (ec)
  54. detail::throw_error(ec, "exe");
  55. return res;
  56. }
  57. filesystem::path exe(HANDLE proc, boost::system::error_code & ec)
  58. {
  59. wchar_t buffer[MAX_PATH];
  60. // On input, specifies the size of the lpExeName buffer, in characters.
  61. DWORD size = MAX_PATH;
  62. if (QueryFullProcessImageNameW(proc, 0, buffer, &size))
  63. {
  64. return filesystem::canonical(buffer, ec);
  65. }
  66. else
  67. BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
  68. return "";
  69. }
  70. filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec)
  71. {
  72. if (pid == GetCurrentProcessId())
  73. {
  74. wchar_t buffer[MAX_PATH];
  75. if (GetModuleFileNameW(nullptr, buffer, sizeof(buffer)))
  76. {
  77. return filesystem::canonical(buffer, ec);
  78. }
  79. }
  80. else
  81. {
  82. struct del
  83. {
  84. void operator()(HANDLE h)
  85. {
  86. ::CloseHandle(h);
  87. };
  88. };
  89. std::unique_ptr<void, del> proc{detail::ext::open_process_with_debug_privilege(pid, ec)};
  90. if (proc == nullptr)
  91. BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
  92. else
  93. return exe(proc.get(), ec);
  94. }
  95. return "";
  96. }
  97. #elif (defined(__APPLE__) && defined(__MACH__))
  98. filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec)
  99. {
  100. char buffer[PROC_PIDPATHINFO_MAXSIZE];
  101. if (proc_pidpath(pid, buffer, sizeof(buffer)) > 0)
  102. {
  103. return filesystem::canonical(buffer, ec);
  104. }
  105. BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
  106. return "";
  107. }
  108. #elif (defined(__linux__) || defined(__ANDROID__) || defined(__sun))
  109. filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec)
  110. {
  111. #if (defined(__linux__) || defined(__ANDROID__))
  112. return filesystem::canonical(
  113. filesystem::path("/proc") / std::to_string(pid) / "exe", ec
  114. );
  115. #elif defined(__sun)
  116. return fileystem::canonical(
  117. filesystem::path("/proc") / std::to_string(pid) / "path/a.out", ec
  118. );
  119. #endif
  120. }
  121. #elif (defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__))
  122. filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec)
  123. {
  124. #if (defined(__FreeBSD__) || defined(__DragonFly__))
  125. int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, pid};
  126. #elif defined(__NetBSD__)
  127. int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_PATHNAME};
  128. #endif
  129. std::size_t len = 0;
  130. if (sysctl(mib, 4, nullptr, &len, nullptr, 0) == 0)
  131. {
  132. std::string strbuff;
  133. strbuff.resize(len);
  134. if (sysctl(mib, 4, &strbuff[0], &len, nullptr, 0) == 0)
  135. {
  136. strbuff.resize(len - 1);
  137. return filesystem::canonical(strbuff, ec);
  138. }
  139. }
  140. BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
  141. return "";
  142. }
  143. #elif defined(__OpenBSD__)
  144. filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec)
  145. {
  146. BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOTSUP, boost::system::system_category())
  147. return "";
  148. }
  149. #else
  150. #error "Platform not supported"
  151. #endif
  152. filesystem::path exe(boost::process::v2::pid_type pid)
  153. {
  154. boost::system::error_code ec;
  155. auto res = exe(pid, ec);
  156. if (ec)
  157. detail::throw_error(ec, "exe");
  158. return res;
  159. }
  160. } // namespace ext
  161. BOOST_PROCESS_V2_END_NAMESPACE
  162. #endif // BOOST_PROCESS_V2_IMPL_EXE_IPP