File indexing completed on 2025-01-18 09:50:10
0001
0002
0003
0004
0005 #ifndef BOOST_PROCESS_V2_EXT_IMPL_ENV_IPP
0006 #define BOOST_PROCESS_V2_EXT_IMPL_ENV_IPP
0007
0008 #include <boost/process/v2/detail/config.hpp>
0009 #include <boost/process/v2/detail/last_error.hpp>
0010 #include <boost/process/v2/detail/throw_error.hpp>
0011 #include <boost/process/v2/ext/detail/proc_info.hpp>
0012 #include <boost/process/v2/ext/env.hpp>
0013
0014 #if defined(BOOST_PROCESS_V2_WINDOWS)
0015 #include <shellapi.h>
0016 #else
0017 #include <cstdlib>
0018 #endif
0019
0020 #if (defined(__linux__) || defined(__ANDROID__))
0021 #include <cstdio>
0022 #endif
0023
0024 BOOST_PROCESS_V2_BEGIN_NAMESPACE
0025
0026 namespace detail {
0027 namespace ext {
0028
0029 #if defined(BOOST_PROCESS_V2_WINDOWS)
0030
0031 void native_env_handle_deleter::operator()(native_env_handle_type h) const
0032 {
0033 delete [] h;
0034 }
0035
0036 native_env_iterator next(native_env_iterator nh)
0037 {
0038 while (*nh != L'\0')
0039 nh ++;
0040 return ++nh ;
0041 }
0042 native_env_iterator find_end(native_env_iterator nh)
0043 {
0044 while (*nh - 1 != L'\0' && *nh != L'\0')
0045 nh ++;
0046 return nh ;
0047 }
0048
0049 const environment::char_type * dereference(native_env_iterator iterator)
0050 {
0051 return iterator;
0052 }
0053
0054 #elif (defined(__linux__) || defined(__ANDROID__))
0055
0056
0057 void native_env_handle_deleter::operator()(native_env_handle_type h) const
0058 {
0059 delete [] h;
0060 }
0061
0062 native_env_iterator next(native_env_iterator nh)
0063 {
0064 while (*nh != '\0')
0065 nh ++;
0066 return ++nh ;
0067 }
0068 native_env_iterator find_end(native_env_iterator nh)
0069 {
0070 while (*nh != EOF)
0071 nh ++;
0072 return nh ;
0073 }
0074
0075 const environment::char_type * dereference(native_env_iterator iterator)
0076 {
0077 return iterator;
0078 }
0079
0080 #elif (defined(__APPLE___) || defined(__MACH__))
0081
0082 void native_env_handle_deleter::operator()(native_env_handle_type h) const
0083 {
0084 delete [] h;
0085 }
0086
0087 native_env_iterator next(native_env_iterator nh)
0088 {
0089 while (*nh != '\0')
0090 nh ++;
0091 return ++nh ;
0092 }
0093 native_env_iterator find_end(native_env_iterator nh)
0094 {
0095 while (*nh - 1 != '\0' && *nh != '\0')
0096 nh ++;
0097 return nh ;
0098 }
0099
0100 const environment::char_type * dereference(native_env_iterator iterator)
0101 {
0102 return iterator;
0103 }
0104
0105
0106 #elif defined(__FreeBSD__)
0107
0108 void native_env_handle_deleter::operator()(native_env_handle_type h) const
0109 {
0110 delete [] h;
0111 }
0112
0113 native_env_iterator next(native_env_iterator nh)
0114 {
0115 return ++nh ;
0116 }
0117 native_env_iterator find_end(native_env_iterator nh)
0118 {
0119 while (*nh != nullptr)
0120 nh++;
0121
0122 return nh ;
0123 }
0124
0125 const environment::char_type * dereference(native_env_iterator iterator)
0126 {
0127 return *iterator;
0128 }
0129
0130 #endif
0131
0132 }
0133 }
0134
0135 namespace ext
0136 {
0137
0138 #if defined(BOOST_PROCESS_V2_WINDOWS)
0139
0140 env_view env(HANDLE proc, boost::system::error_code & ec)
0141 {
0142 wchar_t *buffer = nullptr;
0143 PEB peb;
0144 SIZE_T nRead = 0;
0145 ULONG len = 0;
0146 PROCESS_BASIC_INFORMATION pbi;
0147 detail::ext::RTL_USER_PROCESS_PARAMETERS_EXTENDED upp;
0148
0149 NTSTATUS status = 0;
0150 PVOID buf = nullptr;
0151 status = NtQueryInformationProcess(proc, ProcessBasicInformation, &pbi, sizeof(pbi), &len);
0152 ULONG error = RtlNtStatusToDosError(status);
0153
0154 if (error)
0155 {
0156 BOOST_PROCESS_V2_ASSIGN_EC(ec, error, boost::system::system_category())
0157 return {};
0158 }
0159
0160 if (!ReadProcessMemory(proc, pbi.PebBaseAddress, &peb, sizeof(peb), &nRead))
0161 {
0162 BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0163 return {};
0164 }
0165
0166 if (!ReadProcessMemory(proc, peb.ProcessParameters, &upp, sizeof(upp), &nRead))
0167 {
0168 BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0169 return {};
0170 }
0171
0172 env_view ev;
0173 buf = upp.Environment;
0174 len = (ULONG)upp.EnvironmentSize;
0175 ev.handle_.reset(new wchar_t[len / 2 + 1]());
0176
0177 if (!ReadProcessMemory(proc, buf, ev.handle_.get(), len, &nRead))
0178 {
0179 BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0180 return {};
0181 }
0182
0183 ev.handle_.get()[len / 2] = L'\0';
0184 return ev;
0185 }
0186
0187 env_view env(HANDLE handle)
0188 {
0189 boost::system::error_code ec;
0190 auto res = env(handle, ec);
0191 if (ec)
0192 detail::throw_error(ec, "env");
0193 return res;
0194 }
0195
0196 env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
0197 {
0198 struct del
0199 {
0200 void operator()(HANDLE h)
0201 {
0202 ::CloseHandle(h);
0203 };
0204 };
0205 std::unique_ptr<void, del> proc{detail::ext::open_process_with_debug_privilege(pid, ec)};
0206 if (proc == nullptr)
0207 BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0208 else
0209 return env(proc.get(), ec);
0210
0211 return {};
0212 }
0213
0214 #elif (defined(__APPLE___) || defined(__MACH__))
0215
0216 env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
0217 {
0218 int mib[3] = {CTL_KERN, KERN_ARGMAX, 0};
0219 int argmax = 0;
0220 auto size = sizeof(argmax);
0221 if (sysctl(mib, 2, &argmax, &size, nullptr, 0) == -1)
0222 {
0223 BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0224 return {};
0225 }
0226
0227 std::string procargs;
0228 procargs.resize(argmax - 1);
0229 mib[1] = KERN_PROCARGS2;
0230 mib[2] = pid;
0231
0232 size = argmax;
0233
0234 if (sysctl(mib, 3, &*procargs.begin(), &size, nullptr, 0) != 0)
0235 {
0236 BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0237 return {};
0238 }
0239 std::uint32_t nargs;
0240 memcpy(&nargs, &*procargs.begin(), sizeof(nargs));
0241 char *cp = &*procargs.begin() + sizeof(nargs);
0242
0243 for (; cp < &*procargs.end(); cp++)
0244 if (*cp == '\0')
0245 break;
0246
0247
0248 if (cp == &procargs[size])
0249 return {};
0250
0251
0252 for (; cp < &*procargs.end(); cp++)
0253 if (*cp != '\0') break;
0254
0255
0256 if (cp == &*procargs.end())
0257 return {};
0258
0259
0260 int i = 0;
0261 char *sp = cp;
0262 std::vector<char> vec;
0263
0264 while ((*sp != '\0' || i < nargs) && sp < &*procargs.end()) {
0265 if (i >= nargs)
0266 vec.push_back(*sp);
0267
0268 sp += 1;
0269 }
0270
0271 env_view ev;
0272 ev.handle_.reset(new char[vec.size()]());
0273 std::copy(vec.begin(), vec.end(), ev.handle_.get());
0274 return ev;
0275 }
0276
0277 #elif (defined(__linux__) || defined(__ANDROID__))
0278
0279 env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
0280 {
0281 std::size_t size = 0;
0282 std::unique_ptr<char, detail::ext::native_env_handle_deleter> procargs{};
0283
0284 int f = ::open(("/proc/" + std::to_string(pid) + "/environ").c_str(), O_RDONLY);
0285
0286 while (!procargs || procargs.get()[size - 1] != EOF)
0287 {
0288 std::unique_ptr<char, detail::ext::native_env_handle_deleter> buf{new char[size + 4096]};
0289 if (size > 0)
0290 std::memmove(buf.get(), procargs.get(), size);
0291 auto r = ::read(f, buf.get() + size, 4096);
0292 if (r < 0)
0293 {
0294 BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0295 ::close(f);
0296 return {};
0297 }
0298 procargs = std::move(buf);
0299 size += r;
0300 if (r < 4096)
0301 {
0302 procargs.get()[size] = EOF;
0303 break;
0304 }
0305 }
0306 ::close(f);
0307
0308 env_view ev;
0309 ev.handle_ = std::move(procargs);
0310 return ev;
0311 }
0312
0313 #elif defined(__FreeBSD__)
0314 env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec)
0315 {
0316 env_view ev;
0317
0318 unsigned cntp = 0;
0319 procstat *proc_stat = procstat_open_sysctl();
0320 if (proc_stat != nullptr)
0321 {
0322 kinfo_proc *proc_info = procstat_getprocs(proc_stat, KERN_PROC_PID, pid, &cntp);
0323 if (proc_info != nullptr)
0324 {
0325 char **env = procstat_getenvv(proc_stat, proc_info, 0);
0326 if (env != nullptr)
0327 {
0328 auto e = env;
0329 std::size_t n = 0u, len = 0u;
0330 while (e && *e != nullptr)
0331 {
0332 n ++;
0333 len += std::strlen(*e);
0334 e++;
0335 }
0336 std::size_t mem_needed =
0337
0338 (n * sizeof(char*)) + sizeof(char*) + len + n;
0339
0340 char * out = new (std::nothrow) char[mem_needed];
0341 if (out != nullptr)
0342 {
0343 auto eno = reinterpret_cast<char**>(out);
0344 auto eeo = eno;
0345 auto str = out + (n * sizeof(char*)) + sizeof(char*);
0346 e = env;
0347 while (*e != nullptr)
0348 {
0349 auto len = std::strlen(*e) + 1u;
0350 std::memcpy(str, *e, len);
0351 *eno = str;
0352 str += len;
0353 eno ++;
0354 e++;
0355 }
0356 *eno = nullptr;
0357
0358 ev.handle_.reset(eeo);
0359 }
0360 else
0361 BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0362
0363 }
0364 procstat_freeprocs(proc_stat, proc_info);
0365
0366 }
0367 else
0368 BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0369 procstat_close(proc_stat);
0370 }
0371 else
0372 BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0373 return ev;
0374 }
0375
0376 #endif
0377
0378 env_view env(boost::process::v2::pid_type pid)
0379 {
0380 boost::system::error_code ec;
0381 auto res = env(pid, ec);
0382 if (ec)
0383 detail::throw_error(ec, "env");
0384 return res;
0385 }
0386 }
0387 BOOST_PROCESS_V2_END_NAMESPACE
0388
0389 #endif