]> git.saurik.com Git - apple/libc.git/blob - darwin/libproc.c
0b6eb47ee852d590653305bfca629b748c4fe5ab
[apple/libc.git] / darwin / libproc.c
1 /*
2 * Copyright (c) 2006, 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <sys/cdefs.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <strings.h>
29 #include <sys/errno.h>
30 #include <sys/msgbuf.h>
31 #define CONFIG_EMBEDDED 1
32 #include <sys/process_policy.h>
33
34 #include "libproc_internal.h"
35
36 int __proc_info(int callnum, int pid, int flavor, uint64_t arg, void * buffer, int buffersize);
37 __private_extern__ int proc_setthreadname(void * buffer, int buffersize);
38 int __process_policy(int scope, int action, int policy, int policy_subtype, proc_policy_attribute_t * attrp, pid_t target_pid, uint64_t target_threadid);
39
40
41
42 int
43 proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize)
44 {
45 int retval;
46
47 if ((type >= PROC_ALL_PIDS) || (type <= PROC_PPID_ONLY)) {
48 if ((retval = __proc_info(1, type, typeinfo,(uint64_t)0, buffer, buffersize)) == -1)
49 return(0);
50 } else {
51 errno = EINVAL;
52 retval = 0;
53 }
54 return(retval);
55 }
56
57
58 int
59 proc_listallpids(void * buffer, int buffersize)
60 {
61 int numpids;
62 numpids = proc_listpids(PROC_ALL_PIDS, (uint32_t)0, buffer, buffersize);
63
64 if (numpids == -1)
65 return(-1);
66 else
67 return(numpids/sizeof(int));
68 }
69
70 int
71 proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize)
72 {
73 int numpids;
74 numpids = proc_listpids(PROC_PGRP_ONLY, (uint32_t)pgrpid, buffer, buffersize);
75 if (numpids == -1)
76 return(-1);
77 else
78 return(numpids/sizeof(int));
79 }
80
81 int
82 proc_listchildpids(pid_t ppid, void * buffer, int buffersize)
83 {
84 int numpids;
85 numpids = proc_listpids(PROC_PPID_ONLY, (uint32_t)ppid, buffer, buffersize);
86 if (numpids == -1)
87 return(-1);
88 else
89 return(numpids/sizeof(int));
90 }
91
92
93 int
94 proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize)
95 {
96 int retval;
97
98 if ((retval = __proc_info(2, pid, flavor, arg, buffer, buffersize)) == -1)
99 return(0);
100
101 return(retval);
102 }
103
104
105 int
106 proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize)
107 {
108 int retval;
109
110 if ((retval = __proc_info(3, pid, flavor, (uint64_t)fd, buffer, buffersize)) == -1)
111 return(0);
112
113 return (retval);
114 }
115
116
117 int
118 proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize)
119 {
120 int retval;
121
122 if ((retval = __proc_info(6, pid, flavor, (uint64_t)fileport, buffer, buffersize)) == -1)
123 return (0);
124 return (retval);
125 }
126
127
128 int
129 proc_name(int pid, void * buffer, uint32_t buffersize)
130 {
131 int retval = 0, len;
132 struct proc_bsdinfo pbsd;
133
134
135 if (buffersize < sizeof(pbsd.pbi_name)) {
136 errno = ENOMEM;
137 return(0);
138 }
139
140 retval = proc_pidinfo(pid, PROC_PIDTBSDINFO, (uint64_t)0, &pbsd, sizeof(struct proc_bsdinfo));
141 if (retval != 0) {
142 if (pbsd.pbi_name[0]) {
143 bcopy(&pbsd.pbi_name, buffer, sizeof(pbsd.pbi_name));
144 } else {
145 bcopy(&pbsd.pbi_comm, buffer, sizeof(pbsd.pbi_comm));
146 }
147 len = strlen(buffer);
148 return(len);
149 }
150 return(0);
151 }
152
153 int
154 proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize)
155 {
156 int retval = 0, len;
157 struct proc_regionwithpathinfo reginfo;
158
159 if (buffersize < MAXPATHLEN) {
160 errno = ENOMEM;
161 return(0);
162 }
163
164 retval = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO, (uint64_t)address, &reginfo, sizeof(struct proc_regionwithpathinfo));
165 if (retval != -1) {
166 len = strlen(&reginfo.prp_vip.vip_path[0]);
167 if (len != 0) {
168 if (len > MAXPATHLEN)
169 len = MAXPATHLEN;
170 bcopy(&reginfo.prp_vip.vip_path[0], buffer, len);
171 return(len);
172 }
173 return(0);
174 }
175 return(0);
176
177 }
178
179 int
180 proc_kmsgbuf(void * buffer, uint32_t buffersize)
181 {
182 int retval;
183
184 if ((retval = __proc_info(4, 0, 0, (uint64_t)0, buffer, buffersize)) == -1)
185 return(0);
186 return (retval);
187 }
188
189 int
190 proc_pidpath(int pid, void * buffer, uint32_t buffersize)
191 {
192 int retval, len;
193
194 if (buffersize < PROC_PIDPATHINFO_SIZE) {
195 errno = ENOMEM;
196 return(0);
197 }
198 if (buffersize > PROC_PIDPATHINFO_MAXSIZE) {
199 errno = EOVERFLOW;
200 return(0);
201 }
202
203 retval = __proc_info(2, pid, PROC_PIDPATHINFO, (uint64_t)0, buffer, buffersize);
204 if (retval != -1) {
205 len = strlen(buffer);
206 return(len);
207 }
208 return (0);
209 }
210
211
212 int
213 proc_libversion(int *major, int * minor)
214 {
215
216 if (major != NULL)
217 *major = 1;
218 if (minor != NULL)
219 *minor = 1;
220 return(0);
221 }
222
223 int
224 proc_setpcontrol(const int control)
225 {
226 int retval ;
227
228 if (control < PROC_SETPC_NONE || control > PROC_SETPC_TERMINATE)
229 return(EINVAL);
230
231 if ((retval = __proc_info(5, getpid(), PROC_SELFSET_PCONTROL, (uint64_t)control, NULL, 0)) == -1)
232 return(errno);
233
234 return(0);
235 }
236
237
238 __private_extern__ int
239 proc_setthreadname(void * buffer, int buffersize)
240 {
241 int retval;
242
243 retval = __proc_info(5, getpid(), PROC_SELFSET_THREADNAME, (uint64_t)0, buffer, buffersize);
244
245 if (retval == -1)
246 return(errno);
247 else
248 return(0);
249 }
250
251 #if TARGET_OS_EMBEDDED
252
253 int
254 proc_setcpu_percentage(pid_t pid, int action, int percentage)
255 {
256 proc_policy_cpuusage_attr_t attr;
257
258 bzero(&attr, sizeof(proc_policy_cpuusage_attr_t));
259 attr.ppattr_cpu_attr = action;
260 attr.ppattr_cpu_percentage = percentage;
261 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, &attr, pid, (uint64_t)0) != -1)
262 return(0);
263 else
264 return(errno);
265 }
266
267 int
268 proc_setcpu_deadline(pid_t pid, int action, uint64_t deadline)
269 {
270 proc_policy_cpuusage_attr_t attr;
271
272 bzero(&attr, sizeof(proc_policy_cpuusage_attr_t));
273 attr.ppattr_cpu_attr = action;
274 attr.ppattr_cpu_attr_deadline = deadline;
275 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, &attr, pid, (uint64_t)0) != -1)
276 return(0);
277 else
278 return(errno);
279
280 }
281
282
283 int
284 proc_setcpu_percentage_withdeadline(pid_t pid, int action, int percentage, uint64_t deadline)
285 {
286 proc_policy_cpuusage_attr_t attr;
287
288 bzero(&attr, sizeof(proc_policy_cpuusage_attr_t));
289 attr.ppattr_cpu_attr = action;
290 attr.ppattr_cpu_percentage = percentage;
291 attr.ppattr_cpu_attr_deadline = deadline;
292 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, &attr, pid, (uint64_t)0) != -1)
293 return(0);
294 else
295 return(errno);
296 }
297
298 int
299 proc_clear_cpulimits(pid_t pid)
300 {
301 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_RESTORE, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, NULL, pid, (uint64_t)0) != -1)
302 return(0);
303 else
304 return(errno);
305
306
307 }
308
309 int
310 proc_appstate(int pid, int * appstatep)
311 {
312 int state;
313
314 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_GET, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_STATE, (int *)&state, pid, (uint64_t)0) != -1) {
315 if (appstatep != NULL)
316 *appstatep = state;
317 return(0);
318 } else
319 return(errno);
320
321 }
322
323
324 int
325 proc_setappstate(int pid, int appstate)
326 {
327 int state = appstate;
328
329 switch (state) {
330 case PROC_APPSTATE_NONE:
331 case PROC_APPSTATE_ACTIVE:
332 case PROC_APPSTATE_INACTIVE:
333 case PROC_APPSTATE_BACKGROUND:
334 case PROC_APPSTATE_NONUI:
335 break;
336 default:
337 return(EINVAL);
338 }
339 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_STATE, (int *)&state, pid, (uint64_t)0) != -1)
340 return(0);
341 else
342 return(errno);
343 }
344
345 int
346 proc_devstatusnotify(int devicestatus)
347 {
348 int state = devicestatus;
349
350 switch (devicestatus) {
351 case PROC_DEVSTATUS_SHORTTERM:
352 case PROC_DEVSTATUS_LONGTERM:
353 break;
354 default:
355 return(EINVAL);
356 }
357
358 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_DEVSTATUS, (int *)&state, getpid(), (uint64_t)0) != -1) {
359 return(0);
360 } else
361 return(errno);
362
363 }
364
365 int
366 proc_pidbind(int pid, uint64_t threadid, int bind)
367 {
368 int state = bind;
369 pid_t passpid = pid;
370
371 switch (bind) {
372 case PROC_PIDBIND_CLEAR:
373 passpid = getpid(); /* ignore pid on clear */
374 break;
375 case PROC_PIDBIND_SET:
376 break;
377 default:
378 return(EINVAL);
379 }
380 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_PIDBIND, (int *)&state, passpid, threadid) != -1)
381 return(0);
382 else
383 return(errno);
384 }
385
386 #else /* TARGET_OS_EMBEDDED */
387
388 int
389 proc_clear_vmpressure(pid_t pid)
390 {
391 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_RESTORE, PROC_POLICY_RESOURCE_STARVATION, PROC_POLICY_RS_VIRTUALMEM, NULL, pid, (uint64_t)0) != -1)
392 return(0);
393 else
394 return(errno);
395 }
396
397 /* set the current process as one who can resume suspended processes due to low virtual memory. Need to be root */
398 int
399 proc_set_owner_vmpressure(void)
400 {
401 int retval;
402
403 if ((retval = __proc_info(5, getpid(), PROC_SELFSET_VMRSRCOWNER, (uint64_t)0, NULL, 0)) == -1)
404 return(errno);
405
406 return(0);
407 }
408
409 /* disable the launch time backgroudn policy and restore the process to default group */
410 int
411 proc_disable_apptype(pid_t pid, int apptype)
412 {
413 switch (apptype) {
414 case PROC_POLICY_OSX_APPTYPE_TAL:
415 case PROC_POLICY_OSX_APPTYPE_DASHCLIENT:
416 break;
417 default:
418 return(EINVAL);
419
420 }
421
422 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_DISABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1)
423 return(0);
424 else
425 return(errno);
426
427 }
428
429 /* re-enable the launch time background policy if it had been disabled. */
430 int
431 proc_enable_apptype(pid_t pid, int apptype)
432 {
433 switch (apptype) {
434 case PROC_POLICY_OSX_APPTYPE_TAL:
435 case PROC_POLICY_OSX_APPTYPE_DASHCLIENT:
436 break;
437 default:
438 return(EINVAL);
439
440 }
441
442 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_ENABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1)
443 return(0);
444 else
445 return(errno);
446
447 }
448
449 #endif /* TARGET_OS_EMBEDDED */
450