]> git.saurik.com Git - apple/xnu.git/blame_incremental - libsyscall/wrappers/libproc/libproc.c
xnu-2782.10.72.tar.gz
[apple/xnu.git] / libsyscall / wrappers / libproc / libproc.c
... / ...
CommitLineData
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#include <sys/resource.h>
32#include <sys/process_policy.h>
33#include <mach/message.h>
34
35#include "libproc_internal.h"
36
37int __proc_info(int callnum, int pid, int flavor, uint64_t arg, void * buffer, int buffersize);
38__private_extern__ int proc_setthreadname(void * buffer, int buffersize);
39int __process_policy(int scope, int action, int policy, int policy_subtype, proc_policy_attribute_t * attrp, pid_t target_pid, uint64_t target_threadid);
40int proc_rlimit_control(pid_t pid, int flavor, void *arg);
41
42int
43proc_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(PROC_INFO_CALL_LISTPIDS, 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
58int
59proc_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
70int
71proc_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
81int
82proc_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
93int
94proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize)
95{
96 int retval;
97
98 if ((retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, flavor, arg, buffer, buffersize)) == -1)
99 return(0);
100
101 return(retval);
102}
103
104
105int
106proc_pidoriginatorinfo(int flavor, void *buffer, int buffersize)
107{
108 int retval;
109
110 if ((retval = __proc_info(PROC_INFO_CALL_PIDORIGINATORINFO, getpid(), flavor, 0, buffer, buffersize)) == -1)
111 return(0);
112
113 return(retval);
114}
115
116int
117proc_pid_rusage(int pid, int flavor, rusage_info_t *buffer)
118{
119 return (__proc_info(PROC_INFO_CALL_PIDRUSAGE, pid, flavor, 0, buffer, 0));
120}
121
122int
123proc_setthread_cpupercent(uint8_t percentage, uint32_t ms_refill)
124{
125 uint32_t arg = 0;
126
127 /* Pack percentage and refill into a 32-bit number to match existing kernel implementation */
128 if ((percentage >= 100) || (ms_refill & ~0xffffffU)) {
129 errno = EINVAL;
130 return -1;
131 }
132
133 arg = ((ms_refill << 8) | percentage);
134
135 return (proc_rlimit_control(-1, RLIMIT_THREAD_CPULIMITS, (void *)(uintptr_t)arg));
136}
137
138int
139proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize)
140{
141 int retval;
142
143 if ((retval = __proc_info(PROC_INFO_CALL_PIDFDINFO, pid, flavor, (uint64_t)fd, buffer, buffersize)) == -1)
144 return(0);
145
146 return (retval);
147}
148
149
150int
151proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize)
152{
153 int retval;
154
155 if ((retval = __proc_info(PROC_INFO_CALL_PIDFILEPORTINFO, pid, flavor, (uint64_t)fileport, buffer, buffersize)) == -1)
156 return (0);
157 return (retval);
158}
159
160
161int
162proc_name(int pid, void * buffer, uint32_t buffersize)
163{
164 int retval = 0, len;
165 struct proc_bsdinfo pbsd;
166
167
168 if (buffersize < sizeof(pbsd.pbi_name)) {
169 errno = ENOMEM;
170 return(0);
171 }
172
173 retval = proc_pidinfo(pid, PROC_PIDTBSDINFO, (uint64_t)0, &pbsd, sizeof(struct proc_bsdinfo));
174 if (retval != 0) {
175 if (pbsd.pbi_name[0]) {
176 bcopy(&pbsd.pbi_name, buffer, sizeof(pbsd.pbi_name));
177 } else {
178 bcopy(&pbsd.pbi_comm, buffer, sizeof(pbsd.pbi_comm));
179 }
180 len = (int)strlen(buffer);
181 return(len);
182 }
183 return(0);
184}
185
186int
187proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize)
188{
189 int retval = 0, len;
190 struct proc_regionwithpathinfo reginfo;
191
192 if (buffersize < MAXPATHLEN) {
193 errno = ENOMEM;
194 return(0);
195 }
196
197 retval = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO, (uint64_t)address, &reginfo, sizeof(struct proc_regionwithpathinfo));
198 if (retval != -1) {
199 len = (int)strlen(&reginfo.prp_vip.vip_path[0]);
200 if (len != 0) {
201 if (len > MAXPATHLEN)
202 len = MAXPATHLEN;
203 bcopy(&reginfo.prp_vip.vip_path[0], buffer, len);
204 return(len);
205 }
206 return(0);
207 }
208 return(0);
209
210}
211
212int
213proc_kmsgbuf(void * buffer, uint32_t buffersize)
214{
215 int retval;
216
217 if ((retval = __proc_info(PROC_INFO_CALL_KERNMSGBUF, 0, 0, (uint64_t)0, buffer, buffersize)) == -1)
218 return(0);
219 return (retval);
220}
221
222int
223proc_pidpath(int pid, void * buffer, uint32_t buffersize)
224{
225 int retval, len;
226
227 if (buffersize < PROC_PIDPATHINFO_SIZE) {
228 errno = ENOMEM;
229 return(0);
230 }
231 if (buffersize > PROC_PIDPATHINFO_MAXSIZE) {
232 errno = EOVERFLOW;
233 return(0);
234 }
235
236 retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, PROC_PIDPATHINFO, (uint64_t)0, buffer, buffersize);
237 if (retval != -1) {
238 len = (int)strlen(buffer);
239 return(len);
240 }
241 return (0);
242}
243
244
245int
246proc_libversion(int *major, int * minor)
247{
248
249 if (major != NULL)
250 *major = 1;
251 if (minor != NULL)
252 *minor = 1;
253 return(0);
254}
255
256int
257proc_setpcontrol(const int control)
258{
259 int retval ;
260
261 if (control < PROC_SETPC_NONE || control > PROC_SETPC_TERMINATE)
262 return(EINVAL);
263
264 if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_PCONTROL, (uint64_t)control, NULL, 0)) == -1)
265 return(errno);
266
267 return(0);
268}
269
270
271__private_extern__ int
272proc_setthreadname(void * buffer, int buffersize)
273{
274 int retval;
275
276 retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_THREADNAME, (uint64_t)0, buffer, buffersize);
277
278 if (retval == -1)
279 return(errno);
280 else
281 return(0);
282}
283
284int
285proc_track_dirty(pid_t pid, uint32_t flags)
286{
287 if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_TRACK, flags, NULL, 0) == -1) {
288 return errno;
289 }
290
291 return 0;
292}
293
294int
295proc_set_dirty(pid_t pid, bool dirty)
296{
297 if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_SET, dirty, NULL, 0) == -1) {
298 return errno;
299 }
300
301 return 0;
302}
303
304int
305proc_get_dirty(pid_t pid, uint32_t *flags)
306{
307 int retval;
308
309 if (!flags) {
310 return EINVAL;
311 }
312
313 retval = __proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_GET, 0, NULL, 0);
314 if (retval == -1) {
315 return errno;
316 }
317
318 *flags = retval;
319
320 return 0;
321}
322
323int
324proc_clear_dirty(pid_t pid, uint32_t flags)
325{
326 if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_CLEAR, flags, NULL, 0) == -1) {
327 return errno;
328 }
329
330 return 0;
331}
332
333int
334proc_terminate(pid_t pid, int *sig)
335{
336 int retval;
337
338 if (!sig) {
339 return EINVAL;
340 }
341
342 retval = __proc_info(PROC_INFO_CALL_TERMINATE, pid, 0, 0, NULL, 0);
343 if (retval == -1) {
344 return errno;
345 }
346
347 *sig = retval;
348
349 return 0;
350}
351
352int
353proc_set_cpumon_params(pid_t pid, int percentage, int interval)
354{
355 proc_policy_cpuusage_attr_t attr;
356
357 attr.ppattr_cpu_attr = PROC_POLICY_RSRCACT_NOTIFY_EXC;
358 attr.ppattr_cpu_percentage = percentage;
359 attr.ppattr_cpu_attr_interval = (uint64_t)interval;
360 attr.ppattr_cpu_attr_deadline = 0;
361
362 return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE,
363 PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0));
364}
365
366int
367proc_get_cpumon_params(pid_t pid, int *percentage, int *interval)
368{
369 proc_policy_cpuusage_attr_t attr;
370 int ret;
371
372 ret = __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_GET, PROC_POLICY_RESOURCE_USAGE,
373 PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0);
374
375 if ((ret == 0) && (attr.ppattr_cpu_attr == PROC_POLICY_RSRCACT_NOTIFY_EXC)) {
376 *percentage = attr.ppattr_cpu_percentage;
377 *interval = (int)attr.ppattr_cpu_attr_interval;
378 } else {
379 *percentage = 0;
380 *interval = 0;
381 }
382
383 return (ret);
384}
385
386int
387proc_set_cpumon_defaults(pid_t pid)
388{
389 proc_policy_cpuusage_attr_t attr;
390
391 attr.ppattr_cpu_attr = PROC_POLICY_RSRCACT_NOTIFY_EXC;
392 attr.ppattr_cpu_percentage = PROC_POLICY_CPUMON_DEFAULTS;
393 attr.ppattr_cpu_attr_interval = 0;
394 attr.ppattr_cpu_attr_deadline = 0;
395
396 return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE,
397 PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0));
398}
399
400int
401proc_disable_cpumon(pid_t pid)
402{
403 proc_policy_cpuusage_attr_t attr;
404
405 attr.ppattr_cpu_attr = PROC_POLICY_RSRCACT_NOTIFY_EXC;
406 attr.ppattr_cpu_percentage = PROC_POLICY_CPUMON_DISABLE;
407 attr.ppattr_cpu_attr_interval = 0;
408 attr.ppattr_cpu_attr_deadline = 0;
409
410 return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE,
411 PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0));
412}
413
414
415/*
416 * Turn on the CPU usage monitor using the supplied parameters, and make
417 * violations of the monitor fatal.
418 *
419 * Returns: 0 on success;
420 * -1 on failure and sets errno
421 */
422int
423proc_set_cpumon_params_fatal(pid_t pid, int percentage, int interval)
424{
425 int current_percentage = 0;
426 int current_interval = 0; /* intervals are in seconds */
427 int ret = 0;
428
429 if ((percentage <= 0) || (interval <= 0)) {
430 errno = EINVAL;
431 return (-1);
432 }
433
434 /*
435 * Do a simple query to see if CPU monitoring is
436 * already active. If either the percentage or the
437 * interval is nonzero, then CPU monitoring is
438 * already in use for this process.
439 */
440 (void)proc_get_cpumon_params(pid, &current_percentage, &current_interval);
441 if (current_percentage || current_interval)
442 {
443 /*
444 * The CPU monitor appears to be active.
445 * We choose not to disturb those settings.
446 */
447 errno = EBUSY;
448 return (-1);
449 }
450
451 if ((ret = proc_set_cpumon_params(pid, percentage, interval)) != 0) {
452 /* Failed to activate the CPU monitor */
453 return (ret);
454 }
455
456 if ((ret = proc_rlimit_control(pid, RLIMIT_CPU_USAGE_MONITOR, CPUMON_MAKE_FATAL)) != 0) {
457 /* Failed to set termination, back out the CPU monitor settings. */
458 (void)proc_disable_cpumon(pid);
459 }
460
461 return (ret);
462}
463
464int
465proc_set_wakemon_params(pid_t pid, int rate_hz, int flags __unused)
466{
467 struct proc_rlimit_control_wakeupmon params;
468
469 params.wm_flags = WAKEMON_ENABLE;
470 params.wm_rate = rate_hz;
471
472 return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, &params));
473}
474
475#ifndef WAKEMON_GET_PARAMS
476#define WAKEMON_GET_PARAMS 0x4
477#define WAKEMON_SET_DEFAULTS 0x8
478#endif
479
480int
481proc_get_wakemon_params(pid_t pid, int *rate_hz, int *flags)
482{
483 struct proc_rlimit_control_wakeupmon params;
484 int error;
485
486 params.wm_flags = WAKEMON_GET_PARAMS;
487
488 if ((error = proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, &params)) != 0) {
489 return (error);
490 }
491
492 *rate_hz = params.wm_rate;
493 *flags = params.wm_flags;
494
495 return (0);
496}
497
498int
499proc_set_wakemon_defaults(pid_t pid)
500{
501 struct proc_rlimit_control_wakeupmon params;
502
503 params.wm_flags = WAKEMON_ENABLE | WAKEMON_SET_DEFAULTS;
504 params.wm_rate = -1;
505
506 return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, &params));
507}
508
509int
510proc_disable_wakemon(pid_t pid)
511{
512 struct proc_rlimit_control_wakeupmon params;
513
514 params.wm_flags = WAKEMON_DISABLE;
515 params.wm_rate = -1;
516
517 return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, &params));
518}
519
520
521
522
523/* Donate importance to adaptive processes from this process */
524int
525proc_donate_importance_boost()
526{
527 int rval;
528
529 rval = __process_policy(PROC_POLICY_SCOPE_PROCESS,
530 PROC_POLICY_ACTION_SET,
531 PROC_POLICY_BOOST,
532 PROC_POLICY_IMP_DONATION,
533 NULL, getpid(), 0);
534
535 if (rval == 0)
536 return (0);
537 else
538 return (errno);
539}
540
541static __attribute__((noinline)) void
542proc_importance_bad_assertion(char *reason) {
543 (void)reason;
544}
545
546/*
547 * Use the address of these variables as the token. This way, they can be
548 * printed in the debugger as useful names.
549 */
550uint64_t important_boost_assertion_token = 0xfafafafafafafafa;
551uint64_t normal_boost_assertion_token = 0xfbfbfbfbfbfbfbfb;
552uint64_t non_boost_assertion_token = 0xfcfcfcfcfcfcfcfc;
553uint64_t denap_boost_assertion_token = 0xfdfdfdfdfdfdfdfd;
554
555/*
556 * Accept the boost on a message, or request another boost assertion
557 * if we have already accepted the implicit boost for this message.
558 *
559 * Returns EOVERFLOW if an attempt is made to take an extra assertion when not boosted.
560 *
561 * Returns EIO if the message was not a boosting message.
562 * TODO: Return a 'non-boost' token instead.
563 */
564int
565proc_importance_assertion_begin_with_msg(mach_msg_header_t *msg,
566 __unused mach_msg_trailer_t *trailer,
567 uint64_t *assertion_token)
568{
569 int rval = 0;
570
571 if (assertion_token == NULL)
572 return (EINVAL);
573
574#define LEGACYBOOSTMASK (MACH_MSGH_BITS_VOUCHER_MASK | MACH_MSGH_BITS_RAISEIMP)
575#define LEGACYBOOSTED(m) (((m)->msgh_bits & LEGACYBOOSTMASK) == MACH_MSGH_BITS_RAISEIMP)
576
577 /* Is this a legacy boosted message? */
578 if (LEGACYBOOSTED(msg)) {
579
580 /*
581 * Have we accepted the implicit boost for this message yet?
582 * If we haven't accepted it yet, no need to call into kernel.
583 */
584 if ((msg->msgh_bits & MACH_MSGH_BITS_IMPHOLDASRT) == 0) {
585 msg->msgh_bits |= MACH_MSGH_BITS_IMPHOLDASRT;
586 *assertion_token = (uint64_t) &important_boost_assertion_token;
587 return (0);
588 }
589
590 /* Request an additional boost count */
591 rval = __process_policy(PROC_POLICY_SCOPE_PROCESS,
592 PROC_POLICY_ACTION_HOLD,
593 PROC_POLICY_BOOST,
594 PROC_POLICY_IMP_IMPORTANT,
595 NULL, getpid(), 0);
596 if (rval == 0) {
597 *assertion_token = (uint64_t) &important_boost_assertion_token;
598 return (0);
599 } else if (errno == EOVERFLOW) {
600 proc_importance_bad_assertion("Attempted to take assertion while not boosted");
601 return (errno);
602 } else {
603 return (errno);
604 }
605 }
606
607 return (EIO);
608}
609
610
611/*
612 * Drop a boost assertion.
613 * Returns EOVERFLOW on boost assertion underflow.
614 */
615int
616proc_importance_assertion_complete(uint64_t assertion_token)
617{
618 int rval = 0;
619
620 if (assertion_token == 0)
621 return (0);
622
623 if (assertion_token == (uint64_t) &important_boost_assertion_token) {
624 rval = __process_policy(PROC_POLICY_SCOPE_PROCESS,
625 PROC_POLICY_ACTION_DROP,
626 PROC_POLICY_BOOST,
627 PROC_POLICY_IMP_IMPORTANT,
628 NULL, getpid(), 0);
629 if (rval == 0) {
630 return (0);
631 } else if (errno == EOVERFLOW) {
632 proc_importance_bad_assertion("Attempted to drop too many assertions");
633 return (errno);
634 } else {
635 return (errno);
636 }
637 } else {
638 proc_importance_bad_assertion("Attempted to drop assertion with invalid token");
639 return (EIO);
640 }
641}
642
643/*
644 * Accept the De-Nap boost on a message, or request another boost assertion
645 * if we have already accepted the implicit boost for this message.
646 *
647 * Interface is deprecated before it really got started - just as synonym
648 * for proc_importance_assertion_begin_with_msg() now.
649 */
650int
651proc_denap_assertion_begin_with_msg(mach_msg_header_t *msg,
652 uint64_t *assertion_token)
653{
654#pragma clang diagnostic push
655#pragma clang diagnostic ignored "-Wdeprecated-declarations"
656 return proc_importance_assertion_begin_with_msg(msg, NULL, assertion_token);
657#pragma clang diagnostic pop
658}
659
660
661/*
662 * Drop a denap boost assertion.
663 *
664 * Interface is deprecated before it really got started - just a synonym
665 * for proc_importance_assertion_complete() now.
666 */
667int
668proc_denap_assertion_complete(uint64_t assertion_token)
669{
670 return proc_importance_assertion_complete(assertion_token);
671}
672
673
674int
675proc_clear_vmpressure(pid_t pid)
676{
677 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)
678 return(0);
679 else
680 return(errno);
681}
682
683/* set the current process as one who can resume suspended processes due to low virtual memory. Need to be root */
684int
685proc_set_owner_vmpressure(void)
686{
687 int retval;
688
689 if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_VMRSRCOWNER, (uint64_t)0, NULL, 0)) == -1)
690 return(errno);
691
692 return(0);
693}
694
695/* mark yourself to delay idle sleep on disk IO */
696int
697proc_set_delayidlesleep(void)
698{
699 int retval;
700
701 if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_DELAYIDLESLEEP, (uint64_t)1, NULL, 0)) == -1)
702 return(errno);
703
704 return(0);
705}
706
707/* Reset yourself to delay idle sleep on disk IO, if already set */
708int
709proc_clear_delayidlesleep(void)
710{
711 int retval;
712
713 if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_DELAYIDLESLEEP, (uint64_t)0, NULL, 0)) == -1)
714 return(errno);
715
716 return(0);
717}
718
719/* disable the launch time backgroudn policy and restore the process to default group */
720int
721proc_disable_apptype(pid_t pid, int apptype)
722{
723 switch (apptype) {
724 case PROC_POLICY_OSX_APPTYPE_TAL:
725 case PROC_POLICY_OSX_APPTYPE_DASHCLIENT:
726 break;
727 default:
728 return(EINVAL);
729 }
730
731 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_DISABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1)
732 return(0);
733 else
734 return(errno);
735
736}
737
738/* re-enable the launch time background policy if it had been disabled. */
739int
740proc_enable_apptype(pid_t pid, int apptype)
741{
742 switch (apptype) {
743 case PROC_POLICY_OSX_APPTYPE_TAL:
744 case PROC_POLICY_OSX_APPTYPE_DASHCLIENT:
745 break;
746 default:
747 return(EINVAL);
748
749 }
750
751 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_ENABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1)
752 return(0);
753 else
754 return(errno);
755
756}
757
758#if !TARGET_IPHONE_SIMULATOR
759
760int
761proc_suppress(__unused pid_t pid, __unused uint64_t *generation)
762{
763 return 0;
764}
765
766#endif /* !TARGET_IPHONE_SIMULATOR */
767
768
769
770