1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file. 4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/process/process_iterator.h" 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <sys/sysctl.h> 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace base { 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ProcessIterator::ProcessIterator(const ProcessFilter* filter) 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : index_of_kinfo_proc_(), 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) filter_(filter) { 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_UID, getuid() }; 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool done = false; 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int try_num = 1; 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const int max_tries = 10; 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) do { 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t len = 0; 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (sysctl(mib, arraysize(mib), NULL, &len, NULL, 0) < 0) { 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(ERROR) << "failed to get the size needed for the process list"; 28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kinfo_procs_.resize(0); 29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) done = true; 30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t num_of_kinfo_proc = len / sizeof(struct kinfo_proc); 32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Leave some spare room for process table growth (more could show up 33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // between when we check and now) 34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_of_kinfo_proc += 16; 35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kinfo_procs_.resize(num_of_kinfo_proc); 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) len = num_of_kinfo_proc * sizeof(struct kinfo_proc); 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (sysctl(mib, arraysize(mib), &kinfo_procs_[0], &len, NULL, 0) <0) { 38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // If we get a mem error, it just means we need a bigger buffer, so 39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // loop around again. Anything else is a real error and give up. 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (errno != ENOMEM) { 41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(ERROR) << "failed to get the process list"; 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kinfo_procs_.resize(0); 43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) done = true; 44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Got the list, just make sure we're sized exactly right 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t num_of_kinfo_proc = len / sizeof(struct kinfo_proc); 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kinfo_procs_.resize(num_of_kinfo_proc); 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) done = true; 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } while (!done && (try_num++ < max_tries)); 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!done) { 55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(ERROR) << "failed to collect the process list in a few tries"; 56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kinfo_procs_.resize(0); 57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ProcessIterator::~ProcessIterator() { 61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool ProcessIterator::CheckForNextProcess() { 64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string data; 65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (; index_of_kinfo_proc_ < kinfo_procs_.size(); ++index_of_kinfo_proc_) { 67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t length; 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) struct kinfo_proc kinfo = kinfo_procs_[index_of_kinfo_proc_]; 69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int mib[] = { CTL_KERN, KERN_PROC_ARGS, kinfo.ki_pid }; 70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if ((kinfo.ki_pid > 0) && (kinfo.ki_stat == SZOMB)) 72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) continue; 73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) length = 0; 75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (sysctl(mib, arraysize(mib), NULL, &length, NULL, 0) < 0) { 76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(ERROR) << "failed to figure out the buffer size for a command line"; 77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) continue; 78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) data.resize(length); 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (sysctl(mib, arraysize(mib), &data[0], &length, NULL, 0) < 0) { 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(ERROR) << "failed to fetch a commandline"; 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) continue; 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::string delimiters; 88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) delimiters.push_back('\0'); 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Tokenize(data, delimiters, &entry_.cmd_line_args_); 90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t exec_name_end = data.find('\0'); 92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (exec_name_end == std::string::npos) { 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(ERROR) << "command line data didn't match expected format"; 94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) continue; 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry_.pid_ = kinfo.ki_pid; 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry_.ppid_ = kinfo.ki_ppid; 99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry_.gid_ = kinfo.ki_pgid; 100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t last_slash = data.rfind('/', exec_name_end); 102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (last_slash == std::string::npos) { 103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry_.exe_file_.assign(data, 0, exec_name_end); 104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry_.exe_file_.assign(data, last_slash + 1, 106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) exec_name_end - last_slash - 1); 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Start w/ the next entry next time through 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ++index_of_kinfo_proc_; 111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return true; 113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool NamedProcessIterator::IncludeEntry() { 118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (executable_name_ != entry().exe_file()) 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return ProcessIterator::IncludeEntry(); 122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace base 125