]>
git.saurik.com Git - apple/launchd.git/blob - launchd/src/liblaunch.c
2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
23 #include <libkern/OSByteOrder.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <sys/fcntl.h>
39 #include "launch_priv.h"
41 /* __OSBogusByteSwap__() must not really exist in the symbol namespace
42 * in order for the following to generate an error at build time.
44 extern void __OSBogusByteSwap__(void);
47 ({ typeof (x) _X, _x = (x); \
48 switch (sizeof(_x)) { \
50 _X = OSSwapHostToBigInt64(_x); \
53 _X = OSSwapHostToBigInt32(_x); \
56 _X = OSSwapHostToBigInt16(_x); \
62 __OSBogusByteSwap__(); \
70 ({ typeof (x) _X, _x = (x); \
71 switch (sizeof(_x)) { \
73 _X = OSSwapBigToHostInt64(_x); \
76 _X = OSSwapBigToHostInt32(_x); \
79 _X = OSSwapBigToHostInt16(_x); \
85 __OSBogusByteSwap__(); \
92 struct launch_msg_header
{
98 #define LAUNCH_MSG_HEADER_MAGIC 0xD2FEA02366B39A41ull
100 struct _launch_data
{
104 launch_data_t
*_array
;
135 static void make_msg_and_cmsg(launch_data_t
, void **, size_t *, int **, size_t *);
136 static launch_data_t
make_data(launch_t
, size_t *, size_t *);
137 static int _fd(int fd
);
139 static pthread_once_t _lc_once
= PTHREAD_ONCE_INIT
;
141 void (*__log_liblaunch_bug
)(const char *path
, unsigned int line
, const char *test
) = NULL
;
144 _log_liblaunch_bug(const char *path
, unsigned int line
, const char *test
)
146 if (__log_liblaunch_bug
)
147 __log_liblaunch_bug(path
, line
, test
);
151 (__builtin_expect(!(e), 0) ? _log_liblaunch_bug(__FILE__, __LINE__, #e), false : true)
153 static struct _launch_client
{
156 launch_data_t async_resp
;
159 static void launch_client_init(void)
161 struct sockaddr_un sun
;
162 char *where
= getenv(LAUNCHD_SOCKET_ENV
);
163 char *_launchd_fd
= getenv(LAUNCHD_TRUSTED_FD_ENV
);
164 int r
, dfd
, lfd
= -1, tries
;
166 _lc
= calloc(1, sizeof(struct _launch_client
));
171 pthread_mutex_init(&_lc
->mtx
, NULL
);
174 lfd
= strtol(_launchd_fd
, NULL
, 10);
175 if ((dfd
= dup(lfd
)) >= 0) {
176 assumes(close(dfd
) != -1);
181 unsetenv(LAUNCHD_TRUSTED_FD_ENV
);
184 memset(&sun
, 0, sizeof(sun
));
185 sun
.sun_family
= AF_UNIX
;
188 strncpy(sun
.sun_path
, where
, sizeof(sun
.sun_path
));
190 snprintf(sun
.sun_path
, sizeof(sun
.sun_path
), "%s/%u/sock", LAUNCHD_SOCK_PREFIX
, getuid());
192 if (!assumes((lfd
= _fd(socket(AF_UNIX
, SOCK_STREAM
, 0))) != -1))
195 for (tries
= 0; tries
< 10; tries
++) {
196 r
= connect(lfd
, (struct sockaddr
*)&sun
, sizeof(sun
));
198 if (getuid() != 0 && fork() == 0)
199 execl("/sbin/launchd", "/sbin/launchd", NULL
);
206 assumes(close(lfd
) != -1);
210 if (!(_lc
->l
= launchd_fdopen(lfd
))) {
214 if (!(_lc
->async_resp
= launch_data_alloc(LAUNCH_DATA_ARRAY
)))
220 launchd_close(_lc
->l
);
226 launch_data_t
launch_data_alloc(launch_data_type_t t
)
228 launch_data_t d
= calloc(1, sizeof(struct _launch
));
233 case LAUNCH_DATA_DICTIONARY
:
234 case LAUNCH_DATA_ARRAY
:
235 d
->_array
= malloc(0);
245 launch_data_type_t
launch_data_get_type(launch_data_t d
)
250 void launch_data_free(launch_data_t d
)
255 case LAUNCH_DATA_DICTIONARY
:
256 case LAUNCH_DATA_ARRAY
:
257 for (i
= 0; i
< d
->_array_cnt
; i
++)
258 launch_data_free(d
->_array
[i
]);
261 case LAUNCH_DATA_STRING
:
265 case LAUNCH_DATA_OPAQUE
:
275 size_t launch_data_dict_get_count(launch_data_t dict
)
277 if (!assumes(dict
->type
== LAUNCH_DATA_DICTIONARY
))
280 return dict
->_array_cnt
/ 2;
284 bool launch_data_dict_insert(launch_data_t dict
, launch_data_t what
, const char *key
)
286 launch_data_t thekey
;
289 if (!assumes(dict
->type
== LAUNCH_DATA_DICTIONARY
))
292 thekey
= launch_data_new_string(key
);
294 for (i
= 0; i
< dict
->_array_cnt
; i
+= 2) {
295 if (!strcasecmp(key
, dict
->_array
[i
]->string
)) {
296 dict
->type
= LAUNCH_DATA_ARRAY
;
297 launch_data_array_set_index(dict
, thekey
, i
);
298 launch_data_array_set_index(dict
, what
, i
+ 1);
299 dict
->type
= LAUNCH_DATA_DICTIONARY
;
303 dict
->type
= LAUNCH_DATA_ARRAY
;
304 launch_data_array_set_index(dict
, thekey
, i
);
305 launch_data_array_set_index(dict
, what
, i
+ 1);
306 dict
->type
= LAUNCH_DATA_DICTIONARY
;
310 launch_data_t
launch_data_dict_lookup(launch_data_t dict
, const char *key
)
314 if (!assumes(dict
->type
== LAUNCH_DATA_DICTIONARY
))
317 for (i
= 0; i
< dict
->_array_cnt
; i
+= 2) {
318 if (!strcasecmp(key
, dict
->_array
[i
]->string
))
319 return dict
->_array
[i
+ 1];
325 bool launch_data_dict_remove(launch_data_t dict
, const char *key
)
329 if (!assumes(dict
->type
== LAUNCH_DATA_DICTIONARY
))
332 for (i
= 0; i
< dict
->_array_cnt
; i
+= 2) {
333 if (!strcasecmp(key
, dict
->_array
[i
]->string
))
336 if (i
== dict
->_array_cnt
)
338 launch_data_free(dict
->_array
[i
]);
339 launch_data_free(dict
->_array
[i
+ 1]);
340 memmove(dict
->_array
+ i
, dict
->_array
+ i
+ 2, (dict
->_array_cnt
- (i
+ 2)) * sizeof(launch_data_t
));
341 dict
->_array_cnt
-= 2;
345 void launch_data_dict_iterate(launch_data_t dict
, void (*cb
)(launch_data_t
, const char *, void *), void *context
)
349 if (!assumes(dict
->type
== LAUNCH_DATA_DICTIONARY
))
352 for (i
= 0; i
< dict
->_array_cnt
; i
+= 2)
353 cb(dict
->_array
[i
+ 1], dict
->_array
[i
]->string
, context
);
356 bool launch_data_array_set_index(launch_data_t where
, launch_data_t what
, size_t ind
)
358 if (!assumes(where
->type
== LAUNCH_DATA_ARRAY
))
361 if ((ind
+ 1) >= where
->_array_cnt
) {
362 where
->_array
= realloc(where
->_array
, (ind
+ 1) * sizeof(launch_data_t
));
363 memset(where
->_array
+ where
->_array_cnt
, 0, (ind
+ 1 - where
->_array_cnt
) * sizeof(launch_data_t
));
364 where
->_array_cnt
= ind
+ 1;
367 if (where
->_array
[ind
])
368 launch_data_free(where
->_array
[ind
]);
369 where
->_array
[ind
] = what
;
373 launch_data_t
launch_data_array_get_index(launch_data_t where
, size_t ind
)
375 if (!assumes(where
->type
== LAUNCH_DATA_ARRAY
))
378 if (ind
< where
->_array_cnt
)
379 return where
->_array
[ind
];
383 launch_data_t
launch_data_array_pop_first(launch_data_t where
)
385 launch_data_t r
= NULL
;
387 if (!assumes(where
->type
== LAUNCH_DATA_ARRAY
))
390 if (where
->_array_cnt
> 0) {
391 r
= where
->_array
[0];
392 memmove(where
->_array
, where
->_array
+ 1, (where
->_array_cnt
- 1) * sizeof(launch_data_t
));
398 size_t launch_data_array_get_count(launch_data_t where
)
400 if (!assumes(where
->type
== LAUNCH_DATA_ARRAY
))
402 return where
->_array_cnt
;
405 bool launch_data_set_errno(launch_data_t d
, int e
)
407 if (!assumes(d
->type
== LAUNCH_DATA_ERRNO
))
413 bool launch_data_set_fd(launch_data_t d
, int fd
)
415 if (!assumes(d
->type
== LAUNCH_DATA_FD
))
421 bool launch_data_set_integer(launch_data_t d
, long long n
)
423 if (!assumes(d
->type
== LAUNCH_DATA_INTEGER
))
429 bool launch_data_set_bool(launch_data_t d
, bool b
)
431 if (!assumes(d
->type
== LAUNCH_DATA_BOOL
))
437 bool launch_data_set_real(launch_data_t d
, double n
)
439 if (!assumes(d
->type
== LAUNCH_DATA_REAL
))
445 bool launch_data_set_string(launch_data_t d
, const char *s
)
447 if (!assumes(d
->type
== LAUNCH_DATA_STRING
))
451 d
->string
= strdup(s
);
453 d
->string_len
= strlen(d
->string
);
459 bool launch_data_set_opaque(launch_data_t d
, const void *o
, size_t os
)
461 if (!assumes(d
->type
== LAUNCH_DATA_OPAQUE
))
466 d
->opaque
= malloc(os
);
468 memcpy(d
->opaque
, o
, os
);
474 int launch_data_get_errno(launch_data_t d
)
476 if (!assumes(d
->type
== LAUNCH_DATA_ERRNO
))
481 int launch_data_get_fd(launch_data_t d
)
483 if (!assumes(d
->type
== LAUNCH_DATA_FD
))
488 long long launch_data_get_integer(launch_data_t d
)
490 if (!assumes(d
->type
== LAUNCH_DATA_INTEGER
))
495 bool launch_data_get_bool(launch_data_t d
)
497 if (!assumes(d
->type
== LAUNCH_DATA_BOOL
))
502 double launch_data_get_real(launch_data_t d
)
504 if (!assumes(d
->type
== LAUNCH_DATA_REAL
))
509 const char *launch_data_get_string(launch_data_t d
)
511 if (!assumes(d
->type
== LAUNCH_DATA_STRING
))
516 void *launch_data_get_opaque(launch_data_t d
)
518 if (!assumes(d
->type
== LAUNCH_DATA_OPAQUE
))
523 size_t launch_data_get_opaque_size(launch_data_t d
)
525 if (!assumes(d
->type
== LAUNCH_DATA_OPAQUE
))
527 return d
->opaque_size
;
530 int launchd_getfd(launch_t l
)
535 launch_t
launchd_fdopen(int fd
)
539 c
= calloc(1, sizeof(struct _launch
));
545 assumes(fcntl(fd
, F_SETFL
, O_NONBLOCK
) != -1);
547 if ((c
->sendbuf
= malloc(0)) == NULL
)
549 if ((c
->sendfds
= malloc(0)) == NULL
)
551 if ((c
->recvbuf
= malloc(0)) == NULL
)
553 if ((c
->recvfds
= malloc(0)) == NULL
)
571 void launchd_close(launch_t lh
)
581 assumes(close(lh
->fd
) != -1);
585 static void make_msg_and_cmsg(launch_data_t d
, void **where
, size_t *len
, int **fd_where
, size_t *fdcnt
)
587 launch_data_t o_in_w
;
590 *where
= realloc(*where
, *len
+ sizeof(struct _launch_data
));
592 o_in_w
= *where
+ *len
;
593 memset(o_in_w
, 0, sizeof(struct _launch_data
));
594 *len
+= sizeof(struct _launch_data
);
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
);
614 *fd_where
= realloc(*fd_where
, (*fdcnt
+ 1) * sizeof(int));
615 (*fd_where
)[*fdcnt
] = d
->fd
;
619 case LAUNCH_DATA_STRING
:
620 o_in_w
->string_len
= host2big(d
->string_len
);
621 *where
= realloc(*where
, *len
+ strlen(d
->string
) + 1);
622 memcpy(*where
+ *len
, d
->string
, strlen(d
->string
) + 1);
623 *len
+= strlen(d
->string
) + 1;
625 case LAUNCH_DATA_OPAQUE
:
626 o_in_w
->opaque_size
= host2big(d
->opaque_size
);
627 *where
= realloc(*where
, *len
+ d
->opaque_size
);
628 memcpy(*where
+ *len
, d
->opaque
, d
->opaque_size
);
629 *len
+= d
->opaque_size
;
631 case LAUNCH_DATA_DICTIONARY
:
632 case LAUNCH_DATA_ARRAY
:
633 o_in_w
->_array_cnt
= host2big(d
->_array_cnt
);
634 *where
= realloc(*where
, *len
+ (d
->_array_cnt
* sizeof(launch_data_t
)));
635 memcpy(*where
+ *len
, d
->_array
, d
->_array_cnt
* sizeof(launch_data_t
));
636 *len
+= d
->_array_cnt
* sizeof(launch_data_t
);
638 for (i
= 0; i
< d
->_array_cnt
; i
++)
639 make_msg_and_cmsg(d
->_array
[i
], where
, len
, fd_where
, fdcnt
);
646 static launch_data_t
make_data(launch_t conn
, size_t *data_offset
, size_t *fdoffset
)
648 launch_data_t r
= conn
->recvbuf
+ *data_offset
;
651 if ((conn
->recvlen
- *data_offset
) < sizeof(struct _launch_data
))
653 *data_offset
+= sizeof(struct _launch_data
);
655 switch (big2host(r
->type
)) {
656 case LAUNCH_DATA_DICTIONARY
:
657 case LAUNCH_DATA_ARRAY
:
658 tmpcnt
= big2host(r
->_array_cnt
);
659 if ((conn
->recvlen
- *data_offset
) < (tmpcnt
* sizeof(launch_data_t
))) {
663 r
->_array
= conn
->recvbuf
+ *data_offset
;
664 *data_offset
+= tmpcnt
* sizeof(launch_data_t
);
665 for (i
= 0; i
< tmpcnt
; i
++) {
666 r
->_array
[i
] = make_data(conn
, data_offset
, fdoffset
);
667 if (r
->_array
[i
] == NULL
)
670 r
->_array_cnt
= tmpcnt
;
672 case LAUNCH_DATA_STRING
:
673 tmpcnt
= big2host(r
->string_len
);
674 if ((conn
->recvlen
- *data_offset
) < (tmpcnt
+ 1)) {
678 r
->string
= conn
->recvbuf
+ *data_offset
;
679 r
->string_len
= tmpcnt
;
680 *data_offset
+= tmpcnt
+ 1;
682 case LAUNCH_DATA_OPAQUE
:
683 tmpcnt
= big2host(r
->opaque_size
);
684 if ((conn
->recvlen
- *data_offset
) < tmpcnt
) {
688 r
->opaque
= conn
->recvbuf
+ *data_offset
;
689 r
->opaque_size
= tmpcnt
;
690 *data_offset
+= tmpcnt
;
694 r
->fd
= _fd(conn
->recvfds
[*fdoffset
]);
698 case LAUNCH_DATA_INTEGER
:
699 r
->number
= big2host(r
->number
);
701 case LAUNCH_DATA_REAL
:
702 r
->float_num
= big2host(r
->float_num
);
704 case LAUNCH_DATA_BOOL
:
705 r
->boolean
= big2host(r
->boolean
);
707 case LAUNCH_DATA_ERRNO
:
708 r
->err
= big2host(r
->err
);
716 r
->type
= big2host(r
->type
);
721 int launchd_msg_send(launch_t lh
, launch_data_t d
)
723 struct launch_msg_header lmh
;
724 struct cmsghdr
*cm
= NULL
;
727 size_t sentctrllen
= 0;
730 memset(&mh
, 0, sizeof(mh
));
733 uint64_t msglen
= lh
->sendlen
;
735 make_msg_and_cmsg(d
, &lh
->sendbuf
, &lh
->sendlen
, &lh
->sendfds
, &lh
->sendfdcnt
);
737 msglen
= (lh
->sendlen
- msglen
) + sizeof(struct launch_msg_header
);
738 lmh
.len
= host2big(msglen
);
740 lmh
.magic
= host2big(LAUNCH_MSG_HEADER_MAGIC
);
742 iov
[0].iov_base
= &lmh
;
743 iov
[0].iov_len
= sizeof(lmh
);
747 mh
.msg_iov
= iov
+ 1;
751 iov
[1].iov_base
= lh
->sendbuf
;
752 iov
[1].iov_len
= lh
->sendlen
;
755 if (lh
->sendfdcnt
> 0) {
756 lmh
.fdcnt
= host2big((uint64_t)lh
->sendfdcnt
);
757 sentctrllen
= mh
.msg_controllen
= CMSG_SPACE(lh
->sendfdcnt
* sizeof(int));
758 cm
= alloca(mh
.msg_controllen
);
761 memset(cm
, 0, mh
.msg_controllen
);
763 cm
->cmsg_len
= CMSG_LEN(lh
->sendfdcnt
* sizeof(int));
764 cm
->cmsg_level
= SOL_SOCKET
;
765 cm
->cmsg_type
= SCM_RIGHTS
;
767 memcpy(CMSG_DATA(cm
), lh
->sendfds
, lh
->sendfdcnt
* sizeof(int));
771 if (!assumes((r
= sendmsg(lh
->fd
, &mh
, 0)) != -1)) {
776 } else if (sentctrllen
!= mh
.msg_controllen
) {
782 r
-= sizeof(struct launch_msg_header
);
786 if (lh
->sendlen
> 0) {
787 memmove(lh
->sendbuf
, lh
->sendbuf
+ r
, lh
->sendlen
);
790 lh
->sendbuf
= malloc(0);
795 lh
->sendfds
= malloc(0);
797 if (lh
->sendlen
> 0) {
806 int launch_get_fd(void)
808 pthread_once(&_lc_once
, launch_client_init
);
818 static void launch_msg_getmsgs(launch_data_t m
, void *context
)
820 launch_data_t async_resp
, *sync_resp
= context
;
822 if ((LAUNCH_DATA_DICTIONARY
== launch_data_get_type(m
)) && (async_resp
= launch_data_dict_lookup(m
, LAUNCHD_ASYNC_MSG_KEY
))) {
823 launch_data_array_set_index(_lc
->async_resp
, launch_data_copy(async_resp
), launch_data_array_get_count(_lc
->async_resp
));
825 *sync_resp
= launch_data_copy(m
);
829 launch_data_t
launch_msg(launch_data_t d
)
831 launch_data_t resp
= NULL
;
833 pthread_once(&_lc_once
, launch_client_init
);
840 pthread_mutex_lock(&_lc
->mtx
);
842 if (d
&& launchd_msg_send(_lc
->l
, d
) == -1) {
844 if (!assumes(errno
== EAGAIN
))
846 } while (launchd_msg_send(_lc
->l
, NULL
) == -1);
849 while (resp
== NULL
) {
850 if (d
== NULL
&& launch_data_array_get_count(_lc
->async_resp
) > 0) {
851 resp
= launch_data_array_pop_first(_lc
->async_resp
);
854 if (launchd_msg_recv(_lc
->l
, launch_msg_getmsgs
, &resp
) == -1) {
855 if (!assumes(errno
== EAGAIN
)) {
857 } else if (d
== NULL
) {
864 FD_SET(_lc
->l
->fd
, &rfds
);
866 assumes(select(_lc
->l
->fd
+ 1, &rfds
, NULL
, NULL
, NULL
) == 1);
872 pthread_mutex_unlock(&_lc
->mtx
);
877 int launchd_msg_recv(launch_t lh
, void (*cb
)(launch_data_t
, void *), void *context
)
879 struct cmsghdr
*cm
= alloca(4096);
880 launch_data_t rmsg
= NULL
;
881 size_t data_offset
, fd_offset
;
886 memset(&mh
, 0, sizeof(mh
));
890 lh
->recvbuf
= realloc(lh
->recvbuf
, lh
->recvlen
+ 8*1024);
892 iov
.iov_base
= lh
->recvbuf
+ lh
->recvlen
;
893 iov
.iov_len
= 8*1024;
895 mh
.msg_controllen
= 4096;
897 if (!assumes((r
= recvmsg(lh
->fd
, &mh
, 0)) != -1))
903 if (!assumes(!(mh
.msg_flags
& MSG_CTRUNC
))) {
904 errno
= ECONNABORTED
;
908 if (mh
.msg_controllen
> 0) {
909 if (!assumes(cm
->cmsg_len
== mh
.msg_controllen
)) {
913 lh
->recvfds
= realloc(lh
->recvfds
, lh
->recvfdcnt
* sizeof(int) + mh
.msg_controllen
- sizeof(struct cmsghdr
));
914 memcpy(lh
->recvfds
+ lh
->recvfdcnt
, CMSG_DATA(cm
), mh
.msg_controllen
- sizeof(struct cmsghdr
));
915 lh
->recvfdcnt
+= (mh
.msg_controllen
- sizeof(struct cmsghdr
)) / sizeof(int);
920 while (lh
->recvlen
> 0) {
921 struct launch_msg_header
*lmhp
= lh
->recvbuf
;
923 data_offset
= sizeof(struct launch_msg_header
);
926 if (lh
->recvlen
< sizeof(struct launch_msg_header
))
929 tmplen
= big2host(lmhp
->len
);
931 if (!assumes(big2host(lmhp
->magic
) == LAUNCH_MSG_HEADER_MAGIC
) ||
932 !assumes(tmplen
> sizeof(struct launch_msg_header
))) {
937 if (!assumes(big2host(lmhp
->fdcnt
) == lh
->recvfdcnt
)) {
942 if (lh
->recvlen
< tmplen
) {
946 if ((rmsg
= make_data(lh
, &data_offset
, &fd_offset
)) == NULL
) {
953 lh
->recvlen
-= data_offset
;
954 if (lh
->recvlen
> 0) {
955 memmove(lh
->recvbuf
, lh
->recvbuf
+ data_offset
, lh
->recvlen
);
958 lh
->recvbuf
= malloc(0);
961 lh
->recvfdcnt
-= fd_offset
;
962 if (lh
->recvfdcnt
> 0) {
963 memmove(lh
->recvfds
, lh
->recvfds
+ fd_offset
, lh
->recvfdcnt
* sizeof(int));
966 lh
->recvfds
= malloc(0);
969 if (lh
->recvlen
== 0)
970 assumes(lh
->recvfdcnt
== 0);
981 launch_data_t
launch_data_copy(launch_data_t o
)
983 launch_data_t r
= launch_data_alloc(o
->type
);
987 memcpy(r
, o
, sizeof(struct _launch_data
));
990 case LAUNCH_DATA_DICTIONARY
:
991 case LAUNCH_DATA_ARRAY
:
992 r
->_array
= calloc(1, o
->_array_cnt
* sizeof(launch_data_t
));
993 for (i
= 0; i
< o
->_array_cnt
; i
++) {
995 r
->_array
[i
] = launch_data_copy(o
->_array
[i
]);
998 case LAUNCH_DATA_STRING
:
999 r
->string
= strdup(o
->string
);
1001 case LAUNCH_DATA_OPAQUE
:
1002 r
->opaque
= malloc(o
->opaque_size
);
1003 memcpy(r
->opaque
, o
->opaque
, o
->opaque_size
);
1012 void launchd_batch_enable(bool val
)
1014 launch_data_t resp
, tmp
, msg
;
1016 tmp
= launch_data_alloc(LAUNCH_DATA_BOOL
);
1017 launch_data_set_bool(tmp
, val
);
1019 msg
= launch_data_alloc(LAUNCH_DATA_DICTIONARY
);
1020 launch_data_dict_insert(msg
, tmp
, LAUNCH_KEY_BATCHCONTROL
);
1022 resp
= launch_msg(msg
);
1024 launch_data_free(msg
);
1027 launch_data_free(resp
);
1030 bool launchd_batch_query(void)
1032 launch_data_t resp
, msg
= launch_data_alloc(LAUNCH_DATA_STRING
);
1035 launch_data_set_string(msg
, LAUNCH_KEY_BATCHQUERY
);
1037 resp
= launch_msg(msg
);
1039 launch_data_free(msg
);
1042 if (launch_data_get_type(resp
) == LAUNCH_DATA_BOOL
)
1043 rval
= launch_data_get_bool(resp
);
1044 launch_data_free(resp
);
1049 static int _fd(int fd
)
1052 assumes(fcntl(fd
, F_SETFD
, 1) != -1);
1056 launch_data_t
launch_data_new_errno(int e
)
1058 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_ERRNO
);
1061 launch_data_set_errno(r
, e
);
1066 launch_data_t
launch_data_new_fd(int fd
)
1068 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_FD
);
1071 launch_data_set_fd(r
, fd
);
1076 launch_data_t
launch_data_new_integer(long long n
)
1078 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_INTEGER
);
1081 launch_data_set_integer(r
, n
);
1086 launch_data_t
launch_data_new_bool(bool b
)
1088 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_BOOL
);
1091 launch_data_set_bool(r
, b
);
1096 launch_data_t
launch_data_new_real(double d
)
1098 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_REAL
);
1101 launch_data_set_real(r
, d
);
1106 launch_data_t
launch_data_new_string(const char *s
)
1108 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_STRING
);
1113 if (!launch_data_set_string(r
, s
)) {
1114 launch_data_free(r
);
1121 launch_data_t
launch_data_new_opaque(const void *o
, size_t os
)
1123 launch_data_t r
= launch_data_alloc(LAUNCH_DATA_OPAQUE
);
1128 if (!launch_data_set_opaque(r
, o
, os
)) {
1129 launch_data_free(r
);