process_iterator_openbsd.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // Copyright (c) 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/process/process_iterator.h"
  5. #include <errno.h>
  6. #include <stddef.h>
  7. #include <sys/sysctl.h>
  8. #include "base/logging.h"
  9. #include "base/strings/string_split.h"
  10. #include "base/strings/string_util.h"
  11. namespace base {
  12. ProcessIterator::ProcessIterator(const ProcessFilter* filter)
  13. : index_of_kinfo_proc_(),
  14. filter_(filter) {
  15. int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_UID, getuid(),
  16. sizeof(struct kinfo_proc), 0 };
  17. bool done = false;
  18. int try_num = 1;
  19. const int max_tries = 10;
  20. do {
  21. size_t len = 0;
  22. if (sysctl(mib, std::size(mib), NULL, &len, NULL, 0) < 0) {
  23. DLOG(ERROR) << "failed to get the size needed for the process list";
  24. kinfo_procs_.resize(0);
  25. done = true;
  26. } else {
  27. size_t num_of_kinfo_proc = len / sizeof(struct kinfo_proc);
  28. // Leave some spare room for process table growth (more could show up
  29. // between when we check and now)
  30. num_of_kinfo_proc += 16;
  31. kinfo_procs_.resize(num_of_kinfo_proc);
  32. len = num_of_kinfo_proc * sizeof(struct kinfo_proc);
  33. if (sysctl(mib, std::size(mib), &kinfo_procs_[0], &len, NULL, 0) < 0) {
  34. // If we get a mem error, it just means we need a bigger buffer, so
  35. // loop around again. Anything else is a real error and give up.
  36. if (errno != ENOMEM) {
  37. DLOG(ERROR) << "failed to get the process list";
  38. kinfo_procs_.resize(0);
  39. done = true;
  40. }
  41. } else {
  42. // Got the list, just make sure we're sized exactly right
  43. size_t num_of_kinfo_proc = len / sizeof(struct kinfo_proc);
  44. kinfo_procs_.resize(num_of_kinfo_proc);
  45. done = true;
  46. }
  47. }
  48. } while (!done && (try_num++ < max_tries));
  49. if (!done) {
  50. DLOG(ERROR) << "failed to collect the process list in a few tries";
  51. kinfo_procs_.resize(0);
  52. }
  53. }
  54. ProcessIterator::~ProcessIterator() {
  55. }
  56. bool ProcessIterator::CheckForNextProcess() {
  57. std::string data;
  58. for (; index_of_kinfo_proc_ < kinfo_procs_.size(); ++index_of_kinfo_proc_) {
  59. kinfo_proc& kinfo = kinfo_procs_[index_of_kinfo_proc_];
  60. // Skip processes just awaiting collection
  61. if ((kinfo.p_pid > 0) && (kinfo.p_stat == SZOMB))
  62. continue;
  63. int mib[] = { CTL_KERN, KERN_PROC_ARGS, kinfo.p_pid };
  64. // Find out what size buffer we need.
  65. size_t data_len = 0;
  66. if (sysctl(mib, std::size(mib), NULL, &data_len, NULL, 0) < 0) {
  67. DVPLOG(1) << "failed to figure out the buffer size for a commandline";
  68. continue;
  69. }
  70. data.resize(data_len);
  71. if (sysctl(mib, std::size(mib), &data[0], &data_len, NULL, 0) < 0) {
  72. DVPLOG(1) << "failed to fetch a commandline";
  73. continue;
  74. }
  75. // |data| contains all the command line parameters of the process, separated
  76. // by blocks of one or more null characters. We tokenize |data| into a
  77. // vector of strings using '\0' as a delimiter and populate
  78. // |entry_.cmd_line_args_|.
  79. std::string delimiters;
  80. delimiters.push_back('\0');
  81. entry_.cmd_line_args_ = SplitString(data, delimiters, KEEP_WHITESPACE,
  82. SPLIT_WANT_NONEMPTY);
  83. // |data| starts with the full executable path followed by a null character.
  84. // We search for the first instance of '\0' and extract everything before it
  85. // to populate |entry_.exe_file_|.
  86. size_t exec_name_end = data.find('\0');
  87. if (exec_name_end == std::string::npos) {
  88. DLOG(ERROR) << "command line data didn't match expected format";
  89. continue;
  90. }
  91. entry_.pid_ = kinfo.p_pid;
  92. entry_.ppid_ = kinfo.p_ppid;
  93. entry_.gid_ = kinfo.p__pgid;
  94. size_t last_slash = data.rfind('/', exec_name_end);
  95. if (last_slash == std::string::npos)
  96. entry_.exe_file_.assign(data, 0, exec_name_end);
  97. else
  98. entry_.exe_file_.assign(data, last_slash + 1,
  99. exec_name_end - last_slash - 1);
  100. // Start w/ the next entry next time through
  101. ++index_of_kinfo_proc_;
  102. // Done
  103. return true;
  104. }
  105. return false;
  106. }
  107. bool NamedProcessIterator::IncludeEntry() {
  108. return (executable_name_ == entry().exe_file() &&
  109. ProcessIterator::IncludeEntry());
  110. }
  111. } // namespace base