RSC  0.17.1
MacProcessInfo.cpp
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is part of the RSC project
4  *
5  * Copyright (C) 2014 Johannes Wienke <jwienke at techfak dot uni-bielefeld dot de>
6  *
7  * This file may be licensed under the terms of the
8  * GNU Lesser General Public License Version 3 (the ``LGPL''),
9  * or (at your option) any later version.
10  *
11  * Software distributed under the License is distributed
12  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13  * express or implied. See the LGPL for the specific language
14  * governing rights and limitations.
15  *
16  * You should have received a copy of the LGPL along with this
17  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
18  * or write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * The development of this software was supported by:
22  * CoR-Lab, Research Institute for Cognition and Robotics
23  * Bielefeld University
24  *
25  * ============================================================ */
26 
27 #include "ProcessInfo.h"
28 
29 #include <sys/sysctl.h>
30 #include <sys/types.h> // for getpwuid(3)
31 #include <pwd.h> // likewise
32 #include <unistd.h> // for getuid(2)
33 #include <stdlib.h>
34 #include <string.h>
35 #include <libproc.h>
36 
37 #include <boost/shared_array.hpp>
38 
39 #include <boost/format.hpp>
40 
41 #include <boost/date_time/posix_time/posix_time.hpp>
42 
43 #include "HostInfo.h"
44 
45 namespace rsc {
46 namespace os{
47 
49  return getpid(); // cannot fail according to getpid(2)
50 }
51 
52 // taken from https://gist.github.com/nonowarn/770696
53 std::vector<std::string> getCommandlineComponents(PID pid) {
54 
55  int mib[3];
56  mib[0] = CTL_KERN;
57  mib[1] = KERN_ARGMAX;
58  int argmax;
59  size_t size = sizeof(argmax);
60  if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) {
61  throw std::runtime_error(boost::str(boost::format("Could not determine"
62  " command line:"
63  " %1%")
64  % strerror(errno)));
65  }
66 
67  /*
68  * Make a sysctl() call to get the raw argument space of the process.
69  * The layout is documented in start.s, which is part of the Csu
70  * project. In summary, it looks like:
71  *
72  * /---------------\ 0x00000000
73  * : :
74  * : :
75  * |---------------|
76  * | argc |
77  * |---------------|
78  * | arg[0] |
79  * |---------------|
80  * : :
81  * : :
82  * |---------------|
83  * | arg[argc - 1] |
84  * |---------------|
85  * | 0 |
86  * |---------------|
87  * | env[0] |
88  * |---------------|
89  * : :
90  * : :
91  * |---------------|
92  * | env[n] |
93  * |---------------|
94  * | 0 |
95  * |---------------| <-- Beginning of data returned by sysctl() is here.
96  * | argc |
97  * |---------------|
98  * | exec_path |
99  * |:::::::::::::::|
100  * | |
101  * | String area. |
102  * | |
103  * |---------------| <-- Top of stack.
104  * : :
105  * : :
106  * \---------------/ 0xffffffff
107  */
108  mib[0] = CTL_KERN;
109  mib[1] = KERN_PROCARGS2;
110  mib[2] = pid;
111  size = (size_t)argmax;
112  boost::shared_array<char> procargs(new char[argmax]);
113  if (sysctl(mib, 3, procargs.get(), &size, NULL, 0) == -1) {
114  throw std::runtime_error(boost::str(boost::format("Could not determine"
115  " command line:"
116  " %1%")
117  % strerror(errno)));
118  }
119 
120  // get the number of arguments from the first memory segment
121  int nargs;
122  memcpy(&nargs, procargs.get(), sizeof(nargs));
123 
124  // increment pointer to the memory by the size of argc to point to the first argument
125  char* cp;
126  cp = procargs.get() + sizeof(nargs);
127 
128  // Skip the saved exec_path
129  for (; cp < &procargs[size]; cp++) {
130  if (*cp == '\0') {
131  // End of exec_path reached
132  break;
133  }
134  }
135  if (cp == &procargs[size]) {
136  throw new std::runtime_error("Could not determine command line:"
137  " End of info memory reached without"
138  " finding the string area.");
139  }
140 
141  // Skip trailing '\0' characters
142  for (; cp < &procargs[size]; cp++) {
143  if (*cp != '\0') {
144  // Beginning of first argument reached
145  break;
146  }
147  }
148  if (cp == &procargs[size]) {
149  throw new std::runtime_error("Could not determine command line:"
150  " End of info memory reached without"
151  " finding the string area.");
152  }
153  // cp has reached the beginning of argv[0]
154 
155  // scan through the memory starting at the begining of argv[0] and
156  // grab as many null-terminated arguments as possible.
157  std::vector<std::string> commandLine;
158  for (int i = 0; i < nargs && cp < &procargs[size]; ++i) {
159  std::string argument(cp);
160  commandLine.push_back(argument);
161  cp += commandLine.back().size() + 1;
162  }
163 
164  return commandLine;
165 }
166 
167 std::string getProgramName(PID pid) {
168  std::vector<std::string> components;
169  try {
170  components = getCommandlineComponents(pid);
171  } catch (const std::exception& e) {
172  throw std::runtime_error(boost::str(boost::format("Could not determine"
173  " program name: %1%")
174  % e.what()));
175  }
176  if (components.empty()) {
177  throw std::runtime_error("Could not determine program name: empty"
178  " commandline entry");
179  }
180  return components[0];
181 }
182 
183 std::string currentProgramName() {
185 }
186 
187 std::string getExecutablePath(PID pid) {
188  char pathBuffer[PROC_PIDPATHINFO_MAXSIZE];
189  if (proc_pidpath(pid, pathBuffer, sizeof(pathBuffer)) <= 0) {
190  throw std::runtime_error(boost::str(boost::format("Could not determine"
191  " program name:"
192  " %1%")
193  % strerror(errno)));
194 
195  }
196  return std::string(pathBuffer);
197 }
198 
199 std::string currentExecutablePath() {
201 }
202 
203 std::vector<std::string> getCommandlineArguments(PID pid) {
204  std::vector<std::string> result;
205  try {
206  result = getCommandlineComponents(pid);
207  } catch (const std::exception& e) {
208  throw std::runtime_error(boost::str(boost::format("Could not determine"
209  " commandline arguments:"
210  " %1%")
211  % e.what()));
212  }
213  if (result.empty()) {
214  throw std::runtime_error("Could not determine commandline arguments:"
215  " empty commandline entry");
216  }
217 
218  result.erase(result.begin());
219  return result;
220 }
221 
222 std::vector<std::string> currentCommandlineArguments() {
224 }
225 
226 // taken from http://compgroups.net/comp.unix.programmer/how-to-get-process-start-time-in-mac-osx/2994303
227 boost::posix_time::ptime getProcessStartTime(PID pid) {
228  int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
229  struct kinfo_proc kp;
230  size_t len = (size_t) sizeof(kp);
231  if (sysctl(mib, 4, &kp, &len, NULL, 0) != 0) {
232  throw std::runtime_error(boost::str(boost::format("Could not determine"
233  " process start time:"
234  " %1%")
235  % strerror(errno)));
236  }
237  if (len == 0) {
238  throw std::runtime_error("Could not determine process start time:"
239  " No such PID.");
240  }
241 
242  return boost::posix_time::from_time_t(kp.kp_proc.p_starttime.tv_sec) +
243  boost::posix_time::microseconds(kp.kp_proc.p_starttime.tv_usec);
244 }
245 
246 boost::posix_time::ptime currentProcessStartTime() {
248 }
249 
250 std::string getExecutingUser(PID /*pid*/) {
251  throw std::runtime_error("Could not determine executing user:"
252  " not supported");
253 }
254 
255 std::string currentExecutingUser() {
256  passwd* entry = getpwuid(getuid());
257  return entry->pw_name;
258 }
259 
260 }
261 }
std::vector< std::string > getCommandlineComponents(PID pid)
std::vector< std::string > getCommandlineArguments(PID pid)
Return the list of commandline arguments of the process designated by pid.
boost::posix_time::ptime getProcessStartTime(PID pid)
Return the start time of the process designated by pid.
PID currentProcessId()
Return the id the current process.
boost::posix_time::ptime currentProcessStartTime()
Return the start time of the current process.
std::string getExecutablePath(PID pid)
Return the absolute path of the executable file that is executed in the process designated by pid...
std::vector< std::string > currentCommandlineArguments()
Return the list of commandline arguments of the current process.
std::string getExecutingUser(PID pid)
Return login- or account-name of the user executing pid.
std::string currentExecutingUser()
Return the login- or account-name of the user executing the current process.
std::string getProgramName(PID pid)
Return the name of the program executed in the process designated by pid.
unsigned int PID
Definition: ProcessInfo.h:47
std::string currentProgramName()
Return the name of the program executed in the current process.
std::string currentExecutablePath()
Return the absolute path of the executable file that is executed in the current process.