Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // Copyright (c) 2022 Klemens D. Morgenstern
0002 // Copyright (c) 2022 Samuel Venable
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 #ifndef BOOST_PROCESS_V2_IMPL_PID_IPP
0007 #define BOOST_PROCESS_V2_IMPL_PID_IPP
0008 
0009 #include <boost/process/v2/detail/config.hpp>
0010 #include <boost/process/v2/detail/last_error.hpp>
0011 #include <boost/process/v2/detail/throw_error.hpp>
0012 #include <boost/process/v2/pid.hpp>
0013 
0014 #if defined(BOOST_PROCESS_V2_WINDOWS)
0015 #include <windows.h>
0016 #include <tlhelp32.h>
0017 #else
0018 #include <unistd.h>
0019 #endif
0020 
0021 #if (defined(__APPLE__) && defined(__MACH__))
0022 #include <sys/proc_info.h>
0023 #include <libproc.h>
0024 #endif
0025 
0026 #if (defined(__linux__) || defined(__ANDROID__))
0027 #include <dirent.h>
0028 #endif
0029 
0030 #if defined(__FreeBSD__)
0031 #include <sys/types.h>
0032 #include <sys/user.h>
0033 #include <libutil.h>
0034 #include <cstdlib>
0035 #endif
0036 
0037 #if (defined(__DragonFly__) ||  defined(__OpenBSD__))
0038 #include <sys/types.h>
0039 #include <sys/param.h>
0040 #include <sys/sysctl.h>
0041 #include <sys/user.h>
0042 #include <kvm.h>
0043 #endif
0044 
0045 #if defined(__NetBSD__)
0046 #include <sys/types.h>
0047 #include <kvm.h>
0048 #include <sys/param.h>
0049 #include <sys/sysctl.h>
0050 #endif
0051 
0052 #if defined(__sun)
0053 #include <sys/types.h>
0054 #include <kvm.h>
0055 #include <sys/param.h>
0056 #include <sys/time.h>
0057 #include <sys/proc.h>
0058 #endif
0059 
0060 BOOST_PROCESS_V2_BEGIN_NAMESPACE
0061 
0062 #if defined(BOOST_PROCESS_V2_WINDOWS)
0063 pid_type current_pid() {return ::GetCurrentProcessId();}
0064 #else
0065 pid_type current_pid() {return ::getpid();}
0066 #endif
0067 
0068 #if defined(BOOST_PROCESS_V2_WINDOWS)
0069 
0070 std::vector<pid_type> all_pids(boost::system::error_code & ec)
0071 {
0072     std::vector<pid_type> vec;
0073     HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
0074     if (!hp)
0075     {
0076         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0077         return vec;
0078     }
0079     PROCESSENTRY32 pe;
0080     pe.dwSize = sizeof(PROCESSENTRY32);
0081     if (Process32First(hp, &pe)) 
0082     {
0083         do 
0084         {
0085             vec.push_back(pe.th32ProcessID);
0086         } while (Process32Next(hp, &pe));
0087     }
0088     CloseHandle(hp);
0089     return vec;
0090 }
0091 
0092 pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
0093 {
0094     pid_type ppid = static_cast<pid_type>(-1);
0095     HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
0096     if (!hp)
0097     {
0098         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0099         return ppid;
0100     }
0101     PROCESSENTRY32 pe;
0102     pe.dwSize = sizeof(PROCESSENTRY32);
0103     if (Process32First(hp, &pe))
0104     {
0105         do
0106         {
0107             if (pe.th32ProcessID == pid)
0108             {
0109                 ppid = pe.th32ParentProcessID;
0110                 break;
0111             }
0112         }
0113         while (Process32Next(hp, &pe));
0114     }
0115     CloseHandle(hp);
0116     return ppid;
0117 }
0118 
0119 std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
0120 {
0121     std::vector<pid_type> vec;
0122     HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
0123     if (!hp)
0124     {
0125         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0126         return vec;
0127     }
0128     PROCESSENTRY32 pe;
0129     pe.dwSize = sizeof(PROCESSENTRY32);
0130     if (Process32First(hp, &pe))
0131     {
0132         do
0133         {
0134             if (pe.th32ParentProcessID == pid)
0135             {
0136                 vec.push_back(pe.th32ProcessID);
0137             }
0138         } 
0139         while (Process32Next(hp, &pe));
0140     }
0141     CloseHandle(hp);
0142     return vec;
0143 }
0144 
0145 #elif (defined(__APPLE__) && defined(__MACH__))
0146 
0147 std::vector<pid_type> all_pids(boost::system::error_code & ec)
0148 {
0149     std::vector<pid_type> vec;
0150     vec.resize(proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0) / sizeof(pid_type));
0151     const auto sz = proc_listpids(PROC_ALL_PIDS, 0, &vec[0], sizeof(pid_type) * vec.size());
0152     if (sz < 0)
0153     {
0154         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0155         return {};
0156     }
0157     vec.resize(sz);
0158     return vec;
0159 }
0160 
0161 pid_type parent_pid(pid_type pid, boost::system::error_code & ec) 
0162 {
0163     pid_type ppid = static_cast<pid_type>(-1);
0164     proc_bsdinfo proc_info;
0165     if (proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &proc_info, sizeof(proc_info)) <= 0)
0166     {
0167         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0168         return ppid;
0169     }
0170     else
0171         ppid = proc_info.pbi_ppid;
0172     return ppid;
0173 }
0174 
0175 std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec) 
0176 {
0177     std::vector<pid_type> vec;
0178     vec.resize(proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, nullptr, 0) / sizeof(pid_type));
0179     const auto sz = proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, &vec[0], sizeof(pid_type) * vec.size());
0180     if (sz < 0)
0181     {
0182         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0183         return {};
0184     }
0185     vec.resize(sz);
0186     return vec;
0187 }
0188 
0189 #elif (defined(__linux__) || defined(__ANDROID__))
0190 
0191 std::vector<pid_type> all_pids(boost::system::error_code & ec)
0192 {
0193     std::vector<pid_type> vec;
0194     DIR *proc = opendir("/proc");
0195     if (!proc)
0196     {
0197         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0198         return vec;
0199     } 
0200     struct dirent *ent = nullptr;
0201     while ((ent = readdir(proc))) 
0202     {
0203         if (!isdigit(*ent->d_name))
0204             continue;
0205         vec.push_back(atoi(ent->d_name));
0206     }
0207     closedir(proc);
0208     return vec;
0209 }
0210 
0211 pid_type parent_pid(pid_type pid, boost::system::error_code & ec) 
0212 {
0213     pid_type ppid = static_cast<pid_type>(-1);
0214     char buffer[BUFSIZ];
0215     sprintf(buffer, "/proc/%d/stat", pid);
0216     FILE *stat = fopen(buffer, "r");
0217     if (!stat)
0218     {
0219         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0220         return ppid;
0221     } 
0222     else
0223     {
0224         std::size_t size = fread(buffer, sizeof(char), sizeof(buffer), stat);
0225         if (size > 0) 
0226         {
0227             char *token = nullptr;
0228             if ((token = strtok(buffer, " "))) 
0229             {
0230                 if ((token = strtok(nullptr, " "))) 
0231                 {
0232                     if ((token = strtok(nullptr, " "))) 
0233                     {
0234                         if ((token = strtok(nullptr, " "))) 
0235                         {
0236                             ppid = (pid_type)strtoul(token, nullptr, 10);
0237                         }
0238                     }
0239                 }
0240             }
0241             if (!token)
0242             {
0243                 fclose(stat);
0244                 BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0245                 return ppid;
0246             }
0247         }
0248         fclose(stat);
0249     }
0250     return ppid;
0251 }
0252 
0253 std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec) 
0254 {
0255     std::vector<pid_type> vec;
0256     std::vector<pid_type> pids = all_pids(ec);
0257     if (!pids.empty()) 
0258         vec.reserve(pids.size());
0259     for (std::size_t i = 0; i < pids.size(); i++)
0260     {
0261         pid_type ppid = parent_pid(pids[i], ec);
0262         if (ppid != -1 && ppid == pid)
0263         {
0264             vec.push_back(pids[i]);
0265         }
0266     }
0267     return vec;
0268 }
0269 
0270 #elif defined(__FreeBSD__)
0271 
0272 std::vector<pid_type> all_pids(boost::system::error_code & ec)
0273 {
0274     std::vector<pid_type> vec;
0275     int cntp = 0;
0276     kinfo_proc *proc_info = kinfo_getallproc(&cntp);
0277     if (proc_info) 
0278     {
0279         vec.reserve(cntp);
0280         for (int i = 0; i < cntp; i++)
0281             vec.push_back(proc_info[i].ki_pid);
0282         free(proc_info);
0283     }
0284     else
0285         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0286     return vec;
0287 }
0288 
0289 pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
0290 {
0291     pid_type ppid = static_cast<pid_type>(-1);
0292     kinfo_proc *proc_info = kinfo_getproc(pid);
0293     if (proc_info)
0294     {
0295         ppid = proc_info->ki_ppid;
0296         free(proc_info);
0297     }
0298     else
0299         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0300     return ppid;
0301 }
0302 
0303 std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec) 
0304 {
0305     std::vector<pid_type> vec;
0306     int cntp = 0; 
0307     kinfo_proc *proc_info = kinfo_getallproc(&cntp);
0308     if (proc_info)
0309     {
0310         vec.reserve(cntp);
0311         for (int i = 0; i < cntp; i++)
0312         {
0313             if (proc_info[i].ki_ppid == pid)
0314             {
0315                 vec.push_back(proc_info[i].ki_pid);
0316             }
0317         }
0318         free(proc_info);
0319     }
0320     else
0321         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0322     return vec;
0323 }
0324 
0325 #elif defined(__DragonFly__)
0326 
0327 std::vector<pid_type> all_pids(boost::system::error_code & ec)
0328 {
0329     std::vector<pid_type> vec;
0330     int cntp = 0;
0331     kinfo_proc *proc_info = nullptr;
0332     const char *nlistf, *memf;
0333     nlistf = memf = "/dev/null";
0334     struct closer
0335     {
0336         void operator()(kvm_t * kd)
0337         {
0338             kvm_close(kd);
0339         }
0340     };
0341 
0342     std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)};
0343     if (!kd) 
0344     {
0345         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0346         return vec;
0347     }
0348     if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, &cntp))) 
0349     {
0350         vec.reserve(cntp);
0351         for (int i = 0; i < cntp; i++) 
0352             if (proc_info[i].kp_pid >= 0) 
0353                 vec.push_back(proc_info[i].kp_pid);
0354     }
0355     else
0356         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0357     return vec;
0358 }
0359 
0360 pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
0361 {
0362     pid_type ppid = static_cast<pid_type>(-1);
0363     int cntp = 0;
0364     kinfo_proc *proc_info = nullptr;
0365     const char *nlistf, *memf;
0366     nlistf = memf = "/dev/null";
0367     struct closer
0368     {
0369         void operator()(kvm_t * kd)
0370         {
0371             kvm_close(kd);
0372         }
0373     };
0374 
0375     std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)}; 
0376     if (!kd) 
0377     {
0378         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0379         return ppid;
0380     }
0381     if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, &cntp)))
0382     {
0383         if (proc_info->kp_ppid >= 0)
0384         {
0385             ppid = proc_info->kp_ppid;
0386         }
0387     }
0388     else
0389         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0390     return ppid;
0391 }
0392 
0393 std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec) 
0394 {
0395     std::vector<pid_type> vec;
0396     int cntp = 0;
0397     kinfo_proc *proc_info = nullptr;
0398     const char *nlistf, *memf;
0399     nlistf = memf = "/dev/null";
0400     struct closer
0401     {
0402         void operator()(kvm_t * kd)
0403         {
0404             kvm_close(kd);
0405         }
0406     };
0407 
0408     std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)};
0409     if (!kd) 
0410     {
0411         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0412         return vec;
0413     }
0414     if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, &cntp)))
0415     {
0416         vec.reserve(cntp);
0417         for (int i = 0; i < cntp; i++)
0418         {
0419             if (proc_info[i].kp_pid >= 0 && proc_info[i].kp_ppid >= 0 && proc_info[i].kp_ppid == pid)
0420             {
0421                 vec.push_back(proc_info[i].kp_pid);
0422             }
0423         }
0424     }
0425     else
0426         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0427     return vec;
0428 }
0429 
0430 #elif defined(__NetBSD__)
0431 
0432 std::vector<pid_type> all_pids(boost::system::error_code & ec)
0433 {
0434     std::vector<pid_type> vec;
0435     int cntp = 0;
0436     kinfo_proc2  *proc_info = nullptr;
0437     struct closer
0438     {
0439         void operator()(kvm_t * kd)
0440         {
0441             kvm_close(kd);
0442         }
0443     };
0444 
0445     std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
0446     if (!kd)
0447     {
0448         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0449         return vec;
0450     } 
0451     if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &cntp)))
0452     {
0453         vec.reserve(cntp);
0454         for (int i = cntp - 1; i >= 0; i--) 
0455         {
0456             vec.push_back(proc_info[i].p_pid);
0457         }
0458     }
0459     else
0460         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0461     return vec;
0462 }
0463 
0464 pid_type parent_pid(pid_type pid, boost::system::error_code & ec) 
0465 {
0466     pid_type ppid = static_cast<pid_type>(-1);
0467     int cntp = 0;
0468     kinfo_proc2 *proc_info = nullptr;
0469     struct closer
0470     {
0471         void operator()(kvm_t * kd)
0472         {
0473             kvm_close(kd);
0474         }
0475     };
0476 
0477     std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
0478     if (!kd) 
0479     {
0480         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0481         return ppid;
0482     }
0483     if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc2), &cntp)))
0484     {
0485         ppid = proc_info->p_ppid;
0486     }
0487     else
0488         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0489     return ppid;
0490 }
0491 
0492 std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec) 
0493 {
0494     std::vector<pid_type> vec;
0495     int cntp = 0;
0496     kinfo_proc2 *proc_info = nullptr;
0497     struct closer
0498     {
0499         void operator()(kvm_t * kd)
0500         {
0501             kvm_close(kd);
0502         }
0503     };
0504 
0505     std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
0506     if (!kd) 
0507     {
0508         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0509         return vec;
0510     }
0511     if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &cntp)))
0512     {
0513         vec.reserve(cntp);
0514         for (int i = cntp - 1; i >= 0; i--)
0515         {
0516             if (proc_info[i].p_ppid == pid)
0517             {
0518                 vec.push_back(proc_info[i].p_pid);
0519             }
0520         }
0521     }
0522     else
0523         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0524     return vec;
0525 }
0526 
0527 #elif defined(__OpenBSD__)
0528 
0529 std::vector<pid_type> all_pids(boost::system::error_code & ec)
0530 {
0531     std::vector<pid_type> vec;
0532     int cntp = 0;
0533     kinfo_proc *proc_info = nullptr;
0534     struct closer
0535     {
0536         void operator()(kvm_t * kd)
0537         {
0538             kvm_close(kd);
0539         }
0540     };
0541 
0542     std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
0543     if (!kd)
0544     {
0545         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0546         return vec;
0547     } 
0548     if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cntp)))
0549     {
0550         vec.reserve(cntp);
0551         for (int i = cntp - 1; i >= 0; i--)
0552         {
0553             if (proc_info[i].kp_pid >= 0) 
0554             {
0555                 vec.push_back(proc_info[i].kp_pid);
0556             }
0557         }
0558     }
0559     else
0560         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0561     return vec;
0562 }
0563 
0564 pid_type parent_pid(pid_type pid, boost::system::error_code & ec) 
0565 {
0566     pid_type ppid = static_cast<pid_type>(-1);
0567     int cntp = 0;
0568     kinfo_proc *proc_info = nullptr;
0569     struct closer
0570     {
0571         void operator()(kvm_t * kd)
0572         {
0573             kvm_close(kd);
0574         }
0575     };
0576 
0577     std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)};
0578     if (!kd)
0579     {
0580         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0581         return ppid;
0582     }
0583     if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &cntp)))
0584     {
0585         ppid = proc_info->p_ppid;
0586     }
0587     else
0588         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0589     return ppid;
0590 }
0591 
0592 std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec) 
0593 {
0594     std::vector<pid_type> vec;
0595     int cntp = 0;
0596     kinfo_proc *proc_info = nullptr;
0597     struct closer
0598     {
0599         void operator()(kvm_t * kd)
0600         {
0601             kvm_close(kd);
0602         }
0603     };
0604 
0605     std::unique_ptr<kvm_t, closer> kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; 
0606     if (!kd) 
0607     {
0608         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0609         return vec;
0610     }
0611     if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cntp)))
0612     {
0613         vec.reserve(cntp);
0614         for (int i = cntp - 1; i >= 0; i--)
0615         {
0616             if (proc_info[i].p_ppid == pid)
0617             {
0618                 vec.push_back(proc_info[i].p_pid);
0619             }
0620         }
0621     }
0622     else
0623         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0624     return vec;
0625 }
0626 
0627 
0628 #elif defined(__sun)
0629 
0630 std::vector<pid_type> all_pids(boost::system::error_code & ec)
0631 {
0632     std::vector<pid_type> vec;
0633     struct pid cur_pid;
0634     proc *proc_info = nullptr;
0635     struct closer
0636     {
0637         void operator()(kvm_t * kd)
0638         {
0639             kvm_close(kd);
0640         }
0641     };
0642 
0643     std::unique_ptr<kvm_t, closer> kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr)};
0644     if (!kd)
0645     {
0646         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0647         return vec;
0648     } 
0649     while ((proc_info = kvm_nextproc(kd)))
0650     {
0651         if (kvm_kread(kd, (std::uintptr_t)proc_info->p_pidp, &cur_pid, sizeof(cur_pid)) != -1)
0652         {
0653             vec.insert(vec.begin(), cur_pid.pid_id);
0654         }
0655         else
0656         {
0657             BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0658             break;
0659         }
0660     }
0661     return vec;
0662 }
0663 
0664 pid_type parent_pid(pid_type pid, boost::system::error_code & ec) 
0665 {
0666     pid_type ppid = static_cast<pid_type>(-1);
0667     proc *proc_info = nullptr;
0668     struct closer
0669     {
0670         void operator()(kvm_t * kd)
0671         {
0672             kvm_close(kd);
0673         }
0674     };
0675 
0676     std::unique_ptr<kvm_t, closer> kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr)};
0677     if (!kd)
0678     {
0679         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0680         return ppid;
0681     }
0682     if ((proc_info = kvm_getproc(kd, pid)))
0683     {
0684         ppid = proc_info->p_ppid;
0685     }
0686     else
0687         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0688     return ppid;
0689 }
0690 
0691 std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
0692 {
0693     std::vector<pid_type> vec;
0694     struct pid cur_pid;
0695     proc *proc_info = nullptr;
0696     struct closer
0697     {
0698         void operator()(kvm_t * kd)
0699         {
0700             kvm_close(kd);
0701         }
0702     };
0703 
0704     std::unique_ptr<kvm_t, closer> kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr);
0705     if (!kd)
0706     {
0707         BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0708         return vec;
0709     }
0710     while ((proc_info = kvm_nextproc(kd)))
0711     {
0712         if (proc_info->p_ppid == pid)
0713         {
0714             if (kvm_kread(kd, (std::uintptr_t)proc_info->p_pidp, &cur_pid, sizeof(cur_pid)) != -1)
0715             {
0716                 vec.insert(vec.begin(), cur_pid.pid_id);
0717             }
0718             else
0719             {
0720                 BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
0721                 break;
0722             }
0723         }
0724     }
0725     return vec;
0726 }
0727 
0728 #else
0729 #error "Platform not supported"
0730 #endif
0731 
0732 std::vector<pid_type> all_pids()
0733 {
0734     boost::system::error_code ec;
0735     auto res = all_pids(ec);
0736     if (ec)
0737         detail::throw_error(ec, "all_pids");
0738     return res;
0739 }
0740 
0741 pid_type parent_pid(pid_type pid)
0742 {
0743     boost::system::error_code ec;
0744     auto res = parent_pid(pid, ec);
0745     if (ec)
0746         detail::throw_error(ec, "parent_pid");
0747     return res;
0748 }
0749 
0750 std::vector<pid_type> child_pids(pid_type pid)
0751 {
0752     boost::system::error_code ec;
0753     auto res = child_pids(pid, ec);
0754     if (ec)
0755         detail::throw_error(ec, "child_pids");
0756     return res;
0757 }
0758 
0759 BOOST_PROCESS_V2_END_NAMESPACE
0760 
0761 #endif // BOOST_PROCESS_V2_IMPL_PID_IPP
0762