123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762 |
- // Copyright (c) 2022 Klemens D. Morgenstern
- // Copyright (c) 2022 Samuel Venable
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_PROCESS_V2_IMPL_PID_IPP
- #define BOOST_PROCESS_V2_IMPL_PID_IPP
- #include <boost/process/v2/detail/config.hpp>
- #include <boost/process/v2/detail/last_error.hpp>
- #include <boost/process/v2/detail/throw_error.hpp>
- #include <boost/process/v2/pid.hpp>
- #if defined(BOOST_PROCESS_V2_WINDOWS)
- #include <windows.h>
- #include <tlhelp32.h>
- #else
- #include <unistd.h>
- #endif
- #if (defined(__APPLE__) && defined(__MACH__))
- #include <sys/proc_info.h>
- #include <libproc.h>
- #endif
- #if (defined(__linux__) || defined(__ANDROID__))
- #include <dirent.h>
- #endif
- #if defined(__FreeBSD__)
- #include <sys/types.h>
- #include <sys/user.h>
- #include <libutil.h>
- #include <cstdlib>
- #endif
- #if (defined(__DragonFly__) || defined(__OpenBSD__))
- #include <sys/types.h>
- #include <sys/param.h>
- #include <sys/sysctl.h>
- #include <sys/user.h>
- #include <kvm.h>
- #endif
- #if defined(__NetBSD__)
- #include <sys/types.h>
- #include <kvm.h>
- #include <sys/param.h>
- #include <sys/sysctl.h>
- #endif
- #if defined(__sun)
- #include <sys/types.h>
- #include <kvm.h>
- #include <sys/param.h>
- #include <sys/time.h>
- #include <sys/proc.h>
- #endif
- BOOST_PROCESS_V2_BEGIN_NAMESPACE
- #if defined(BOOST_PROCESS_V2_WINDOWS)
- pid_type current_pid() {return ::GetCurrentProcessId();}
- #else
- pid_type current_pid() {return ::getpid();}
- #endif
- #if defined(BOOST_PROCESS_V2_WINDOWS)
- std::vector<pid_type> all_pids(boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
- if (!hp)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- PROCESSENTRY32 pe;
- pe.dwSize = sizeof(PROCESSENTRY32);
- if (Process32First(hp, &pe))
- {
- do
- {
- vec.push_back(pe.th32ProcessID);
- } while (Process32Next(hp, &pe));
- }
- CloseHandle(hp);
- return vec;
- }
- pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
- {
- pid_type ppid = static_cast<pid_type>(-1);
- HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
- if (!hp)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return ppid;
- }
- PROCESSENTRY32 pe;
- pe.dwSize = sizeof(PROCESSENTRY32);
- if (Process32First(hp, &pe))
- {
- do
- {
- if (pe.th32ProcessID == pid)
- {
- ppid = pe.th32ParentProcessID;
- break;
- }
- }
- while (Process32Next(hp, &pe));
- }
- CloseHandle(hp);
- return ppid;
- }
- std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
- if (!hp)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- PROCESSENTRY32 pe;
- pe.dwSize = sizeof(PROCESSENTRY32);
- if (Process32First(hp, &pe))
- {
- do
- {
- if (pe.th32ParentProcessID == pid)
- {
- vec.push_back(pe.th32ProcessID);
- }
- }
- while (Process32Next(hp, &pe));
- }
- CloseHandle(hp);
- return vec;
- }
- #elif (defined(__APPLE__) && defined(__MACH__))
- std::vector<pid_type> all_pids(boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- vec.resize(proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0) / sizeof(pid_type));
- const auto sz = proc_listpids(PROC_ALL_PIDS, 0, &vec[0], sizeof(pid_type) * vec.size());
- if (sz < 0)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return {};
- }
- vec.resize(sz);
- return vec;
- }
- pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
- {
- pid_type ppid = static_cast<pid_type>(-1);
- proc_bsdinfo proc_info;
- if (proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &proc_info, sizeof(proc_info)) <= 0)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return ppid;
- }
- else
- ppid = proc_info.pbi_ppid;
- return ppid;
- }
- std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- vec.resize(proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, nullptr, 0) / sizeof(pid_type));
- const auto sz = proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, &vec[0], sizeof(pid_type) * vec.size());
- if (sz < 0)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return {};
- }
- vec.resize(sz);
- return vec;
- }
- #elif (defined(__linux__) || defined(__ANDROID__))
- std::vector<pid_type> all_pids(boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- DIR *proc = opendir("/proc");
- if (!proc)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- struct dirent *ent = nullptr;
- while ((ent = readdir(proc)))
- {
- if (!isdigit(*ent->d_name))
- continue;
- vec.push_back(atoi(ent->d_name));
- }
- closedir(proc);
- return vec;
- }
- pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
- {
- pid_type ppid = static_cast<pid_type>(-1);
- char buffer[BUFSIZ];
- sprintf(buffer, "/proc/%d/stat", pid);
- FILE *stat = fopen(buffer, "r");
- if (!stat)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return ppid;
- }
- else
- {
- std::size_t size = fread(buffer, sizeof(char), sizeof(buffer), stat);
- if (size > 0)
- {
- char *token = nullptr;
- if ((token = strtok(buffer, " ")))
- {
- if ((token = strtok(nullptr, " ")))
- {
- if ((token = strtok(nullptr, " ")))
- {
- if ((token = strtok(nullptr, " ")))
- {
- ppid = (pid_type)strtoul(token, nullptr, 10);
- }
- }
- }
- }
- if (!token)
- {
- fclose(stat);
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return ppid;
- }
- }
- fclose(stat);
- }
- return ppid;
- }
- std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- std::vector<pid_type> pids = all_pids(ec);
- if (!pids.empty())
- vec.reserve(pids.size());
- for (std::size_t i = 0; i < pids.size(); i++)
- {
- pid_type ppid = parent_pid(pids[i], ec);
- if (ppid != -1 && ppid == pid)
- {
- vec.push_back(pids[i]);
- }
- }
- return vec;
- }
- #elif defined(__FreeBSD__)
- std::vector<pid_type> all_pids(boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- int cntp = 0;
- kinfo_proc *proc_info = kinfo_getallproc(&cntp);
- if (proc_info)
- {
- vec.reserve(cntp);
- for (int i = 0; i < cntp; i++)
- vec.push_back(proc_info[i].ki_pid);
- free(proc_info);
- }
- else
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
- {
- pid_type ppid = static_cast<pid_type>(-1);
- kinfo_proc *proc_info = kinfo_getproc(pid);
- if (proc_info)
- {
- ppid = proc_info->ki_ppid;
- free(proc_info);
- }
- else
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return ppid;
- }
- std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- int cntp = 0;
- kinfo_proc *proc_info = kinfo_getallproc(&cntp);
- if (proc_info)
- {
- vec.reserve(cntp);
- for (int i = 0; i < cntp; i++)
- {
- if (proc_info[i].ki_ppid == pid)
- {
- vec.push_back(proc_info[i].ki_pid);
- }
- }
- free(proc_info);
- }
- else
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- #elif defined(__DragonFly__)
- std::vector<pid_type> all_pids(boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- int cntp = 0;
- kinfo_proc *proc_info = nullptr;
- const char *nlistf, *memf;
- nlistf = memf = "/dev/null";
- struct closer
- {
- void operator()(kvm_t * kd)
- {
- kvm_close(kd);
- }
- };
- std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)};
- if (!kd)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, &cntp)))
- {
- vec.reserve(cntp);
- for (int i = 0; i < cntp; i++)
- if (proc_info[i].kp_pid >= 0)
- vec.push_back(proc_info[i].kp_pid);
- }
- else
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
- {
- pid_type ppid = static_cast<pid_type>(-1);
- int cntp = 0;
- kinfo_proc *proc_info = nullptr;
- const char *nlistf, *memf;
- nlistf = memf = "/dev/null";
- struct closer
- {
- void operator()(kvm_t * kd)
- {
- kvm_close(kd);
- }
- };
- std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)};
- if (!kd)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return ppid;
- }
- if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, &cntp)))
- {
- if (proc_info->kp_ppid >= 0)
- {
- ppid = proc_info->kp_ppid;
- }
- }
- else
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return ppid;
- }
- std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- int cntp = 0;
- kinfo_proc *proc_info = nullptr;
- const char *nlistf, *memf;
- nlistf = memf = "/dev/null";
- struct closer
- {
- void operator()(kvm_t * kd)
- {
- kvm_close(kd);
- }
- };
- std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)};
- if (!kd)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, &cntp)))
- {
- vec.reserve(cntp);
- for (int i = 0; i < cntp; i++)
- {
- if (proc_info[i].kp_pid >= 0 && proc_info[i].kp_ppid >= 0 && proc_info[i].kp_ppid == pid)
- {
- vec.push_back(proc_info[i].kp_pid);
- }
- }
- }
- else
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- #elif defined(__NetBSD__)
- std::vector<pid_type> all_pids(boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- int cntp = 0;
- kinfo_proc2 *proc_info = nullptr;
- struct closer
- {
- void operator()(kvm_t * kd)
- {
- kvm_close(kd);
- }
- };
- std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
- if (!kd)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &cntp)))
- {
- vec.reserve(cntp);
- for (int i = cntp - 1; i >= 0; i--)
- {
- vec.push_back(proc_info[i].p_pid);
- }
- }
- else
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
- {
- pid_type ppid = static_cast<pid_type>(-1);
- int cntp = 0;
- kinfo_proc2 *proc_info = nullptr;
- struct closer
- {
- void operator()(kvm_t * kd)
- {
- kvm_close(kd);
- }
- };
- std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
- if (!kd)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return ppid;
- }
- if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc2), &cntp)))
- {
- ppid = proc_info->p_ppid;
- }
- else
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return ppid;
- }
- std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- int cntp = 0;
- kinfo_proc2 *proc_info = nullptr;
- struct closer
- {
- void operator()(kvm_t * kd)
- {
- kvm_close(kd);
- }
- };
- std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
- if (!kd)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &cntp)))
- {
- vec.reserve(cntp);
- for (int i = cntp - 1; i >= 0; i--)
- {
- if (proc_info[i].p_ppid == pid)
- {
- vec.push_back(proc_info[i].p_pid);
- }
- }
- }
- else
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- #elif defined(__OpenBSD__)
- std::vector<pid_type> all_pids(boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- int cntp = 0;
- kinfo_proc *proc_info = nullptr;
- struct closer
- {
- void operator()(kvm_t * kd)
- {
- kvm_close(kd);
- }
- };
- std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
- if (!kd)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cntp)))
- {
- vec.reserve(cntp);
- for (int i = cntp - 1; i >= 0; i--)
- {
- if (proc_info[i].kp_pid >= 0)
- {
- vec.push_back(proc_info[i].kp_pid);
- }
- }
- }
- else
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
- {
- pid_type ppid = static_cast<pid_type>(-1);
- int cntp = 0;
- kinfo_proc *proc_info = nullptr;
- struct closer
- {
- void operator()(kvm_t * kd)
- {
- kvm_close(kd);
- }
- };
- std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
- if (!kd)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return ppid;
- }
- if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &cntp)))
- {
- ppid = proc_info->p_ppid;
- }
- else
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return ppid;
- }
- std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- int cntp = 0;
- kinfo_proc *proc_info = nullptr;
- struct closer
- {
- void operator()(kvm_t * kd)
- {
- kvm_close(kd);
- }
- };
- std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
- if (!kd)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cntp)))
- {
- vec.reserve(cntp);
- for (int i = cntp - 1; i >= 0; i--)
- {
- if (proc_info[i].p_ppid == pid)
- {
- vec.push_back(proc_info[i].p_pid);
- }
- }
- }
- else
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- #elif defined(__sun)
- std::vector<pid_type> all_pids(boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- struct pid cur_pid;
- proc *proc_info = nullptr;
- struct closer
- {
- void operator()(kvm_t * kd)
- {
- kvm_close(kd);
- }
- };
- std::unique_ptr<kvm_t, closer> kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr)};
- if (!kd)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- while ((proc_info = kvm_nextproc(kd)))
- {
- if (kvm_kread(kd, (std::uintptr_t)proc_info->p_pidp, &cur_pid, sizeof(cur_pid)) != -1)
- {
- vec.insert(vec.begin(), cur_pid.pid_id);
- }
- else
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- break;
- }
- }
- return vec;
- }
- pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
- {
- pid_type ppid = static_cast<pid_type>(-1);
- proc *proc_info = nullptr;
- struct closer
- {
- void operator()(kvm_t * kd)
- {
- kvm_close(kd);
- }
- };
- std::unique_ptr<kvm_t, closer> kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr)};
- if (!kd)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return ppid;
- }
- if ((proc_info = kvm_getproc(kd, pid)))
- {
- ppid = proc_info->p_ppid;
- }
- else
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return ppid;
- }
- std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
- {
- std::vector<pid_type> vec;
- struct pid cur_pid;
- proc *proc_info = nullptr;
- struct closer
- {
- void operator()(kvm_t * kd)
- {
- kvm_close(kd);
- }
- };
- std::unique_ptr<kvm_t, closer> kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr);
- if (!kd)
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- return vec;
- }
- while ((proc_info = kvm_nextproc(kd)))
- {
- if (proc_info->p_ppid == pid)
- {
- if (kvm_kread(kd, (std::uintptr_t)proc_info->p_pidp, &cur_pid, sizeof(cur_pid)) != -1)
- {
- vec.insert(vec.begin(), cur_pid.pid_id);
- }
- else
- {
- BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
- break;
- }
- }
- }
- return vec;
- }
- #else
- #error "Platform not supported"
- #endif
- std::vector<pid_type> all_pids()
- {
- boost::system::error_code ec;
- auto res = all_pids(ec);
- if (ec)
- detail::throw_error(ec, "all_pids");
- return res;
- }
- pid_type parent_pid(pid_type pid)
- {
- boost::system::error_code ec;
- auto res = parent_pid(pid, ec);
- if (ec)
- detail::throw_error(ec, "parent_pid");
- return res;
- }
- std::vector<pid_type> child_pids(pid_type pid)
- {
- boost::system::error_code ec;
- auto res = child_pids(pid, ec);
- if (ec)
- detail::throw_error(ec, "child_pids");
- return res;
- }
- BOOST_PROCESS_V2_END_NAMESPACE
- #endif // BOOST_PROCESS_V2_IMPL_PID_IPP
|