2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
22 #include "liblaunch_public.h"
23 #include "liblaunch_private.h"
24 #include "liblaunch_internal.h"
26 #include <mach/mach.h>
27 #include <libkern/OSByteOrder.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <sys/fcntl.h>
43 #include "libbootstrap_public.h"
44 #include "libvproc_public.h"
45 #include "libvproc_private.h"
46 #include "libvproc_internal.h"
48 /* __OSBogusByteSwap__() must not really exist in the symbol namespace
49 * in order for the following to generate an error at build time.
51 extern void __OSBogusByteSwap__(void);
54 ({ typeof (x) _X, _x = (x); \
55 switch (sizeof(_x)) { \
57 _X = OSSwapHostToBigInt64(_x); \
60 _X = OSSwapHostToBigInt32(_x); \
63 _X = OSSwapHostToBigInt16(_x); \
69 __OSBogusByteSwap__(); \
77 ({ typeof (x) _X, _x = (x); \
78 switch (sizeof(_x)) { \
80 _X = OSSwapBigToHostInt64(_x); \
83 _X = OSSwapBigToHostInt32(_x); \
86 _X = OSSwapBigToHostInt16(_x); \
92 __OSBogusByteSwap__(); \
99 struct launch_msg_header
{
104 #define LAUNCH_MSG_HEADER_MAGIC 0xD2FEA02366B39A41ull
106 struct _launch_data
{
111 launch_data_t
*_array
;
119 uint64_t opaque_size
;
126 uint32_t boolean
; /* We'd use 'bool' but this struct needs to be used under Rosetta, and sizeof(bool) is different between PowerPC and Intel */
143 static launch_data_t
launch_data_array_pop_first(launch_data_t where
);
144 static int _fd(int fd
);
145 static void launch_client_init(void);
146 static void launch_msg_getmsgs(launch_data_t m
, void *context
);
147 static launch_data_t
launch_msg_internal(launch_data_t d
);
148 static void launch_mach_checkin_service(launch_data_t obj
, const char *key
, void *context
);
150 static launch_t in_flight_msg_recv_client
;
151 static pthread_once_t _lc_once
= PTHREAD_ONCE_INIT
;
153 static struct _launch_client
{
156 launch_data_t async_resp
;
160 launch_client_init(void)
162 struct sockaddr_un sun
;
163 char *where
= getenv(LAUNCHD_SOCKET_ENV
);
164 char *_launchd_fd
= getenv(LAUNCHD_TRUSTED_FD_ENV
);
168 _lc
= calloc(1, sizeof(struct _launch_client
));
173 pthread_mutex_init(&_lc
->mtx
, NULL
);
176 lfd
= strtol(_launchd_fd
, NULL
, 10);
177 if ((dfd
= dup(lfd
)) >= 0) {
183 unsetenv(LAUNCHD_TRUSTED_FD_ENV
);
186 memset(&sun
, 0, sizeof(sun
));
187 sun
.sun_family
= AF_UNIX
;
189 if (where
&& where
[0] != '\0') {
190 strncpy(sun
.sun_path
, where
, sizeof(sun
.sun_path
));
191 } else if (!getenv("SUDO_COMMAND") && _vprocmgr_getsocket(spath
) == 0) {
194 min_len
= sizeof(sun
.sun_path
) < sizeof(spath
) ? sizeof(sun
.sun_path
) : sizeof(spath
);
196 strncpy(sun
.sun_path
, spath
, min_len
);
198 strncpy(sun
.sun_path
, LAUNCHD_SOCK_PREFIX
"/sock", sizeof(sun
.sun_path
));
201 if ((lfd
= _fd(socket(AF_UNIX
, SOCK_STREAM
, 0))) == -1)
203 if (-1 == connect(lfd
, (struct sockaddr
*)&sun
, sizeof(sun
)))
206 if (!(_lc
->l
= launchd_fdopen(lfd
)))
208 if (!(_lc
->async_resp
= launch_data_alloc(LAUNCH_DATA_ARRAY
)))
214 launchd_close(_lc
->l
, close
);
223 launch_data_alloc(launch_data_type_t t
)
225 launch_data_t d
= calloc(1, sizeof(struct _launch
));
230 case LAUNCH_DATA_DICTIONARY
:
231 case LAUNCH_DATA_ARRAY
:
232 d
->_array
= malloc(0);
243 launch_data_get_type(launch_data_t d
)
249 launch_data_free(launch_data_t d
)
254 case LAUNCH_DATA_DICTIONARY
:
255 case LAUNCH_DATA_ARRAY
:
256 for (i
= 0; i
< d
->_array_cnt
; i
++)
257 launch_data_free(d
->_array
[i
]);
260 case LAUNCH_DATA_STRING
:
264 case LAUNCH_DATA_OPAQUE
:
275 launch_data_dict_get_count(launch_data_t dict
)
277 return dict
->_array_cnt
/ 2;
282 launch_data_dict_insert(launch_data_t dict
, launch_data_t what
, const char *key
)
285 launch_data_t thekey
= launch_data_alloc(LAUNCH_DATA_STRING
);
287 launch_data_set_string(thekey
, key
);
289 for (i
= 0; i
< dict
->_array_cnt
; i
+= 2) {
290 if (!strcasecmp(key
, dict
->_array
[i
]->string
)) {
291 launch_data_array_set_index(dict
, thekey
, i
);
292 launch_data_array_set_index(dict
, what
, i
+ 1);
296 launch_data_array_set_index(dict
, thekey
, i
);
297 launch_data_array_set_index(dict
, what
, i
+ 1);
302 launch_data_dict_lookup(launch_data_t dict
, const char *key
)
306 if (LAUNCH_DATA_DICTIONARY
!= dict
->type
)
309 for (i
= 0; i
< dict
->_array_cnt
; i
+= 2) {
310 if (!strcasecmp(key
, dict
->_array
[i
]->string
))
311 return dict
->_array
[i
+ 1];
318 launch_data_dict_remove(launch_data_t dict
, const char *key
)
322 for (i
= 0; i
< dict
->_array_cnt
; i
+= 2) {
323 if (!strcasecmp(key
, dict
->_array
[i
]->string
))
326 if (i
== dict
->_array_cnt
)
328 launch_data_free(dict
->_array
[i
]);
329 launch_data_free(dict
->_array
[i
+ 1]);
330 memmove(dict
->_array
+ i
, dict
->_array
+ i
+ 2, (dict
->_array_cnt
- (i
+ 2)) * sizeof(launch_data_t
));
331 dict
->_array_cnt
-= 2;
336 launch_data_dict_iterate(launch_data_t dict
, void (*cb
)(launch_data_t
, const char *, void *), void *context
)
340 if (LAUNCH_DATA_DICTIONARY
!= dict
->type
)
343 for (i
= 0; i
< dict
->_array_cnt
; i
+= 2)
344 cb(dict
->_array
[i
+ 1], dict
->_array
[i
]->string
, context
);
348 launch_data_array_set_index(launch_data_t where
, launch_data_t what
, size_t ind
)
350 if ((ind
+ 1) >= where
->_array_cnt
) {
351 where
->_array
= reallocf(where
->_array
, (ind
+ 1) * sizeof(launch_data_t
));
352 memset(where
->_array
+ where
->_array_cnt
, 0, (ind
+ 1 - where
->_array_cnt
) * sizeof(launch_data_t
));
353 where
->_array_cnt
= ind
+ 1;
356 if (where
->_array
[ind
])
357 launch_data_free(where
->_array
[ind
]);
358 where
->_array
[ind
] = what
;
363 launch_data_array_get_index(launch_data_t where
, size_t ind
)
365 if (LAUNCH_DATA_ARRAY
!= where
->type
)
367 if (ind
< where
->_array_cnt
)
368 return where
->_array
[ind
];
373 launch_data_array_pop_first(launch_data_t where
)
375 launch_data_t r
= NULL
;
377 if (where
->_array_cnt
> 0) {
378 r
= where
->_array
[0];
379 memmove(where
->_array
, where
->_array
+ 1, (where
->_array_cnt
- 1) * sizeof(launch_data_t
));
386 launch_data_array_get_count(launch_data_t where
)
388 if (LAUNCH_DATA_ARRAY
!= where
->type
)
390 return where
->_array_cnt
;
394 launch_data_set_errno(launch_data_t d
, int e
)
401 launch_data_set_fd(launch_data_t d
, int fd
)
408 launch_data_set_machport(launch_data_t d
, mach_port_t p
)
415 launch_data_set_integer(launch_data_t d
, long long n
)
422 launch_data_set_bool(launch_data_t d
, bool b
)
429 launch_data_set_real(launch_data_t d
, double n
)
436 launch_data_set_string(launch_data_t d
, const char *s
)
440 d
->string
= strdup(s
);
442 d
->string_len
= strlen(d
->string
);
449 launch_data_set_opaque(launch_data_t d
, const void *o
, size_t os
)
454 d
->opaque
= malloc(os
);
456 memcpy(d
->opaque
, o
, os
);
463 launch_data_get_errno(launch_data_t d
)
469 launch_data_get_fd(launch_data_t d
)
475 launch_data_get_machport(launch_data_t d
)
481 launch_data_get_integer(launch_data_t d
)
487 launch_data_get_bool(launch_data_t d
)
493 launch_data_get_real(launch_data_t d
)
499 launch_data_get_string(launch_data_t d
)
501 if (LAUNCH_DATA_STRING
!= d
->type
)
507 launch_data_get_opaque(launch_data_t d
)
509 if (LAUNCH_DATA_OPAQUE
!= d
->type
)
515 launch_data_get_opaque_size(launch_data_t d
)
517 return d
->opaque_size
;
521 launchd_getfd(launch_t l
)
527 launchd_fdopen(int fd
)
531 c
= calloc(1, sizeof(struct _launch
));
537 fcntl(fd
, F_SETFL
, O_NONBLOCK
);
539 if ((c
->sendbuf
= malloc(0)) == NULL
)
541 if ((c
->sendfds
= malloc(0)) == NULL
)
543 if ((c
->recvbuf
= malloc(0)) == NULL
)
545 if ((c
->recvfds
= malloc(0)) == NULL
)
564 launchd_close(launch_t lh
, typeof(close
) closefunc
)
566 if (in_flight_msg_recv_client
== lh
) {
567 in_flight_msg_recv_client
= NULL
;
582 #define ROUND_TO_64BIT_WORD_SIZE(x) ((x + 7) & ~7)
585 launch_data_pack(launch_data_t d
, void *where
, size_t len
, int *fd_where
, size_t *fd_cnt
)
587 launch_data_t o_in_w
= where
;
588 size_t i
, rsz
, total_data_len
= sizeof(struct _launch_data
);
590 if (total_data_len
> len
) {
594 where
+= total_data_len
;
596 o_in_w
->type
= host2big(d
->type
);
599 case LAUNCH_DATA_INTEGER
:
600 o_in_w
->number
= host2big(d
->number
);
602 case LAUNCH_DATA_REAL
:
603 o_in_w
->float_num
= host2big(d
->float_num
);
605 case LAUNCH_DATA_BOOL
:
606 o_in_w
->boolean
= host2big(d
->boolean
);
608 case LAUNCH_DATA_ERRNO
:
609 o_in_w
->err
= host2big(d
->err
);
612 o_in_w
->fd
= host2big(d
->fd
);
613 if (fd_where
&& d
->fd
!= -1) {
614 fd_where
[*fd_cnt
] = d
->fd
;
618 case LAUNCH_DATA_STRING
:
619 o_in_w
->string_len
= host2big(d
->string_len
);
620 total_data_len
+= ROUND_TO_64BIT_WORD_SIZE(strlen(d
->string
) + 1);
621 if (total_data_len
> len
) {
624 memcpy(where
, d
->string
, strlen(d
->string
) + 1);
626 case LAUNCH_DATA_OPAQUE
:
627 o_in_w
->opaque_size
= host2big(d
->opaque_size
);
628 total_data_len
+= ROUND_TO_64BIT_WORD_SIZE(d
->opaque_size
);
629 if (total_data_len
> len
) {
632 memcpy(where
, d
->opaque
, d
->opaque_size
);
634 case LAUNCH_DATA_DICTIONARY
:
635 case LAUNCH_DATA_ARRAY
:
636 o_in_w
->_array_cnt
= host2big(d
->_array_cnt
);
637 total_data_len
+= d
->_array_cnt
* sizeof(uint64_t);
638 if (total_data_len
> len
) {
642 where
+= d
->_array_cnt
* sizeof(uint64_t);
644 for (i
= 0; i
< d
->_array_cnt
; i
++) {
645 rsz
= launch_data_pack(d
->_array
[i
], where
, len
- total_data_len
, fd_where
, fd_cnt
);
650 total_data_len
+= rsz
;
657 return total_data_len
;
661 launch_data_unpack(void *data
, size_t data_size
, int *fds
, size_t fd_cnt
, size_t *data_offset
, size_t *fdoffset
)
663 launch_data_t r
= data
+ *data_offset
;
666 if ((data_size
- *data_offset
) < sizeof(struct _launch_data
))
668 *data_offset
+= sizeof(struct _launch_data
);
670 switch (big2host(r
->type
)) {
671 case LAUNCH_DATA_DICTIONARY
:
672 case LAUNCH_DATA_ARRAY
:
673 tmpcnt
= big2host(r
->_array_cnt
);
674 if ((data_size
- *data_offset
) < (tmpcnt
* sizeof(uint64_t))) {
678 r
->_array
= data
+ *data_offset
;
679 *data_offset
+= tmpcnt
* sizeof(uint64_t);
680 for (i
= 0; i
< tmpcnt
; i
++) {
681 r
->_array
[i
] = launch_data_unpack(data
, data_size
, fds
, fd_cnt
, data_offset
, fdoffset
);
682 if (r
->_array
[i
] == NULL
)
685 r
->_array_cnt
= tmpcnt
;
687 case LAUNCH_DATA_STRING
:
688 tmpcnt
= big2host(r
->string_len
);
689 if ((data_size
- *data_offset
) < (tmpcnt
+ 1)) {
693 r
->string
= data
+ *data_offset
;
694 r
->string_len
= tmpcnt
;
695 *data_offset
+= ROUND_TO_64BIT_WORD_SIZE(tmpcnt
+ 1);
697 case LAUNCH_DATA_OPAQUE
:
698 tmpcnt
= big2host(r
->opaque_size
);
699 if ((data_size
- *data_offset
) < tmpcnt
) {
703 r
->opaque
= data
+ *data_offset
;
704 r
->opaque_size
= tmpcnt
;
705 *data_offset
+= ROUND_TO_64BIT_WORD_SIZE(tmpcnt
);
708 if (r
->fd
!= -1 && fd_cnt
> *fdoffset
) {
709 r
->fd
= _fd(fds
[*fdoffset
]);
713 case LAUNCH_DATA_INTEGER
:
714 r
->number
= big2host(r
->number
);
716 case LAUNCH_DATA_REAL
:
717 r
->float_num
= big2host(r
->float_num
);
719 case LAUNCH_DATA_BOOL
:
720 r
->boolean
= big2host(r
->boolean
);
722 case LAUNCH_DATA_ERRNO
:
723 r
->err
= big2host(r
->err
);
724 case LAUNCH_DATA_MACHPORT
:
732 r
->type
= big2host(r
->type
);
737 int launchd_msg_send(launch_t lh
, launch_data_t d
)
739 struct launch_msg_header lmh
;
740 struct cmsghdr
*cm
= NULL
;
743 size_t sentctrllen
= 0;
746 memset(&mh
, 0, sizeof(mh
));
748 /* confirm that the next hack works */
749 assert((d
&& lh
->sendlen
== 0) || (!d
&& lh
->sendlen
));
752 size_t fd_slots_used
= 0;
753 size_t good_enough_size
= 10 * 1024 * 1024;
756 /* hack, see the above assert to verify "correctness" */
758 lh
->sendbuf
= malloc(good_enough_size
);
760 lh
->sendfds
= malloc(4 * 1024);
762 lh
->sendlen
= launch_data_pack(d
, lh
->sendbuf
, good_enough_size
, lh
->sendfds
, &fd_slots_used
);
764 if (lh
->sendlen
== 0) {
769 lh
->sendfdcnt
= fd_slots_used
;
771 msglen
= lh
->sendlen
+ sizeof(struct launch_msg_header
); /* type promotion to make the host2big() macro work right */
772 lmh
.len
= host2big(msglen
);
773 lmh
.magic
= host2big(LAUNCH_MSG_HEADER_MAGIC
);
775 iov
[0].iov_base
= &lmh
;
776 iov
[0].iov_len
= sizeof(lmh
);
780 mh
.msg_iov
= iov
+ 1;
784 iov
[1].iov_base
= lh
->sendbuf
;
785 iov
[1].iov_len
= lh
->sendlen
;
788 if (lh
->sendfdcnt
> 0) {
789 sentctrllen
= mh
.msg_controllen
= CMSG_SPACE(lh
->sendfdcnt
* sizeof(int));
790 cm
= alloca(mh
.msg_controllen
);
793 memset(cm
, 0, mh
.msg_controllen
);
795 cm
->cmsg_len
= CMSG_LEN(lh
->sendfdcnt
* sizeof(int));
796 cm
->cmsg_level
= SOL_SOCKET
;
797 cm
->cmsg_type
= SCM_RIGHTS
;
799 memcpy(CMSG_DATA(cm
), lh
->sendfds
, lh
->sendfdcnt
* sizeof(int));
802 if ((r
= sendmsg(lh
->fd
, &mh
, 0)) == -1) {
807 } else if (sentctrllen
!= mh
.msg_controllen
) {
813 r
-= sizeof(struct launch_msg_header
);
817 if (lh
->sendlen
> 0) {
818 memmove(lh
->sendbuf
, lh
->sendbuf
+ r
, lh
->sendlen
);
821 lh
->sendbuf
= malloc(0);
826 lh
->sendfds
= malloc(0);
828 if (lh
->sendlen
> 0) {
840 pthread_once(&_lc_once
, launch_client_init
);
851 launch_msg_getmsgs(launch_data_t m
, void *context
)
853 launch_data_t async_resp
, *sync_resp
= context
;
855 if ((LAUNCH_DATA_DICTIONARY
== launch_data_get_type(m
)) && (async_resp
= launch_data_dict_lookup(m
, LAUNCHD_ASYNC_MSG_KEY
))) {
856 launch_data_array_set_index(_lc
->async_resp
, launch_data_copy(async_resp
), launch_data_array_get_count(_lc
->async_resp
));
858 *sync_resp
= launch_data_copy(m
);
863 launch_mach_checkin_service(launch_data_t obj
, const char *key
, void *context
__attribute__((unused
)))
865 kern_return_t result
;
869 strlcpy(srvnm
, key
, sizeof(srvnm
));
871 result
= bootstrap_check_in(bootstrap_port
, srvnm
, &p
);
873 if (result
== BOOTSTRAP_SUCCESS
)
874 launch_data_set_machport(obj
, p
);
878 launch_msg(launch_data_t d
)
880 launch_data_t mps
, r
= launch_msg_internal(d
);
882 if (launch_data_get_type(d
) == LAUNCH_DATA_STRING
) {
883 if (strcmp(launch_data_get_string(d
), LAUNCH_KEY_CHECKIN
) != 0)
887 if (launch_data_get_type(r
) != LAUNCH_DATA_DICTIONARY
)
889 mps
= launch_data_dict_lookup(r
, LAUNCH_JOBKEY_MACHSERVICES
);
892 launch_data_dict_iterate(mps
, launch_mach_checkin_service
, NULL
);
899 launch_msg_internal(launch_data_t d
)
901 launch_data_t resp
= NULL
;
903 if (d
&& (launch_data_get_type(d
) == LAUNCH_DATA_STRING
)
904 && (strcmp(launch_data_get_string(d
), LAUNCH_KEY_GETJOBS
) == 0)
905 && vproc_swap_complex(NULL
, VPROC_GSK_ALLJOBS
, NULL
, &resp
) == NULL
) {
909 pthread_once(&_lc_once
, launch_client_init
);
916 pthread_mutex_lock(&_lc
->mtx
);
918 if (d
&& launchd_msg_send(_lc
->l
, d
) == -1) {
922 } while (launchd_msg_send(_lc
->l
, NULL
) == -1);
925 while (resp
== NULL
) {
926 if (d
== NULL
&& launch_data_array_get_count(_lc
->async_resp
) > 0) {
927 resp
= launch_data_array_pop_first(_lc
->async_resp
);
930 if (launchd_msg_recv(_lc
->l
, launch_msg_getmsgs
, &resp
) == -1) {
931 if (errno
!= EAGAIN
) {
933 } else if (d
== NULL
) {
940 FD_SET(_lc
->l
->fd
, &rfds
);
942 select(_lc
->l
->fd
+ 1, &rfds
, NULL
, NULL
, NULL
);
948 pthread_mutex_unlock(&_lc
->mtx
);
953 int launchd_msg_recv(launch_t lh
, void (*cb
)(launch_data_t
, void *), void *context
)
955 struct cmsghdr
*cm
= alloca(4096);
956 launch_data_t rmsg
= NULL
;
957 size_t data_offset
, fd_offset
;
962 memset(&mh
, 0, sizeof(mh
));
966 lh
->recvbuf
= reallocf(lh
->recvbuf
, lh
->recvlen
+ 8*1024);
968 iov
.iov_base
= lh
->recvbuf
+ lh
->recvlen
;
969 iov
.iov_len
= 8*1024;
971 mh
.msg_controllen
= 4096;
973 if ((r
= recvmsg(lh
->fd
, &mh
, 0)) == -1)
979 if (mh
.msg_flags
& MSG_CTRUNC
) {
980 errno
= ECONNABORTED
;
984 if (mh
.msg_controllen
> 0) {
985 lh
->recvfds
= reallocf(lh
->recvfds
, lh
->recvfdcnt
* sizeof(int) + mh
.msg_controllen
- sizeof(struct cmsghdr
));
986 memcpy(lh
->recvfds
+ lh
->recvfdcnt
, CMSG_DATA(cm
), mh
.msg_controllen
- sizeof(struct cmsghdr
));
987 lh
->recvfdcnt
+= (mh
.msg_controllen
- sizeof(struct cmsghdr
)) / sizeof(int);
992 while (lh
->recvlen
> 0) {
993 struct launch_msg_header
*lmhp
= lh
->recvbuf
;
995 data_offset
= sizeof(struct launch_msg_header
);
998 if (lh
->recvlen
< sizeof(struct launch_msg_header
))
1001 tmplen
= big2host(lmhp
->len
);
1003 if (big2host(lmhp
->magic
) != LAUNCH_MSG_HEADER_MAGIC
|| tmplen
<= sizeof(struct launch_msg_header
)) {
1008 if (lh
->recvlen
< tmplen
) {
1009 goto need_more_data
;
1012 if ((rmsg
= launch_data_unpack(lh
->recvbuf
, lh
->recvlen
, lh
->recvfds
, lh
->recvfdcnt
, &data_offset
, &fd_offset
)) == NULL
) {
1017 in_flight_msg_recv_client
= lh
;
1021 /* launchd and only launchd can call launchd_close() as a part of the callback */
1022 if (in_flight_msg_recv_client
== NULL
) {
1027 lh
->recvlen
-= data_offset
;
1028 if (lh
->recvlen
> 0) {
1029 memmove(lh
->recvbuf
, lh
->recvbuf
+ data_offset
, lh
->recvlen
);
1032 lh
->recvbuf
= malloc(0);
1035 lh
->recvfdcnt
-= fd_offset
;
1036 if (lh
->recvfdcnt
> 0) {
1037 memmove(lh
->recvfds
, lh
->recvfds
+ fd_offset
, lh
->recvfdcnt
* sizeof(int));
1040 lh
->recvfds
= malloc(0);
1052 launch_data_t
launch_data_copy(launch_data_t o
)
1054 launch_data_t r
= launch_data_alloc(o
->type
);
1058 memcpy(r
, o
, sizeof(struct _launch_data
));
1061 case LAUNCH_DATA_DICTIONARY
:
1062 case LAUNCH_DATA_ARRAY
:
1063 r
->_array
= calloc(1, o
->_array_cnt
* sizeof(launch_data_t
));
1064 for (i
= 0; i
< o
->_array_cnt
; i
++) {
1066 r
->_array
[i
] = launch_data_copy(o
->_array
[i
]);
1069 case LAUNCH_DATA_STRING
:
1070 r
->string
= strdup(o
->string
);
1072 case LAUNCH_DATA_OPAQUE
:
1073 r
->opaque
= malloc(o
->opaque_size
);
1074 memcpy(r
->opaque
, o
->opaque
, o
->opaque_size
);
1084 launchd_batch_enable(bool b
)
1088 vproc_swap_integer(NULL
, VPROC_GSK_GLOBAL_ON_DEMAND
, &val
, NULL
);
1092 launchd_batch_query(void)
1096 if (vproc_swap_integer(NULL
, VPROC_GSK_GLOBAL_ON_DEMAND
, NULL
, &val
) == NULL
) {
1103 static int _fd(int fd
)
1106 fcntl(fd
, F_SETFD
, 1);
1110 launch_data_t
launch_data_new_errno(int e
)
1112 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_ERRNO
);
1115 launch_data_set_errno(r
, e
);
1120 launch_data_t
launch_data_new_fd(int fd
)
1122 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_FD
);
1125 launch_data_set_fd(r
, fd
);
1130 launch_data_t
launch_data_new_machport(mach_port_t p
)
1132 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_MACHPORT
);
1135 launch_data_set_machport(r
, p
);
1140 launch_data_t
launch_data_new_integer(long long n
)
1142 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_INTEGER
);
1145 launch_data_set_integer(r
, n
);
1150 launch_data_t
launch_data_new_bool(bool b
)
1152 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_BOOL
);
1155 launch_data_set_bool(r
, b
);
1160 launch_data_t
launch_data_new_real(double d
)
1162 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_REAL
);
1165 launch_data_set_real(r
, d
);
1170 launch_data_t
launch_data_new_string(const char *s
)
1172 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_STRING
);
1177 if (!launch_data_set_string(r
, s
)) {
1178 launch_data_free(r
);
1185 launch_data_t
launch_data_new_opaque(const void *o
, size_t os
)
1187 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_OPAQUE
);
1192 if (!launch_data_set_opaque(r
, o
, os
)) {
1193 launch_data_free(r
);
1201 load_launchd_jobs_at_loginwindow_prompt(int flags
__attribute__((unused
)), ...)
1203 _vprocmgr_init("LoginWindow");
1207 create_and_switch_to_per_session_launchd(const char *login
__attribute__((unused
)), int flags
__attribute__((unused
)), ...)
1209 mach_port_t bezel_ui_server
;
1211 uid_t target_user
= geteuid() ? geteuid() : getuid();
1213 if (_vprocmgr_move_subset_to_user(target_user
, "Aqua")) {
1217 #define BEZEL_UI_PATH "/System/Library/LoginPlugins/BezelServices.loginPlugin/Contents/Resources/BezelUI/BezelUIServer"
1218 #define BEZEL_UI_PLIST "/System/Library/LaunchAgents/com.apple.BezelUIServer.plist"
1219 #define BEZEL_UI_SERVICE "BezelUI"
1221 if (!(stat(BEZEL_UI_PLIST
, &sb
) == 0 && S_ISREG(sb
.st_mode
))) {
1222 if (bootstrap_create_server(bootstrap_port
, BEZEL_UI_PATH
, target_user
, true, &bezel_ui_server
) == BOOTSTRAP_SUCCESS
) {
1225 if (bootstrap_create_service(bezel_ui_server
, BEZEL_UI_SERVICE
, &srv
) == BOOTSTRAP_SUCCESS
) {
1226 mach_port_deallocate(mach_task_self(), srv
);
1229 mach_port_deallocate(mach_task_self(), bezel_ui_server
);