Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:10

0001 // Copyright (c) 2022 Klemens D. Morgenstern
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 //linux stores this as a blob with an EOF at the end
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) // done!
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             // environ         -  nullptr       - strlen  + null terminators
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 //BOOST_PROCESS_V2_EXT_IMPL_ENV_IPP