7 #include <CoreFoundation/CoreFoundation.h>
10 CF2launch_data(CFTypeRef cfr
);
13 myCFDictionaryApplyFunction(const void *key
, const void *value
, void *context
)
15 launch_data_t ik
, iw
, where
= context
;
17 ik
= CF2launch_data(key
);
18 iw
= CF2launch_data(value
);
20 launch_data_dict_insert(where
, iw
, launch_data_get_string(ik
));
25 CF2launch_data(CFTypeRef cfr
)
28 CFTypeID cft
= CFGetTypeID(cfr
);
30 if (cft
== CFStringGetTypeID()) {
32 CFStringGetCString(cfr
, buf
, sizeof(buf
), kCFStringEncodingUTF8
);
33 r
= launch_data_alloc(LAUNCH_DATA_STRING
);
34 launch_data_set_string(r
, buf
);
35 } else if (cft
== CFBooleanGetTypeID()) {
36 r
= launch_data_alloc(LAUNCH_DATA_BOOL
);
37 launch_data_set_bool(r
, CFBooleanGetValue(cfr
));
38 } else if (cft
== CFArrayGetTypeID()) {
39 CFIndex i
, ac
= CFArrayGetCount(cfr
);
40 r
= launch_data_alloc(LAUNCH_DATA_ARRAY
);
41 for (i
= 0; i
< ac
; i
++) {
42 CFTypeRef v
= CFArrayGetValueAtIndex(cfr
, i
);
44 launch_data_t iv
= CF2launch_data(v
);
45 launch_data_array_set_index(r
, iv
, i
);
48 } else if (cft
== CFDictionaryGetTypeID()) {
49 r
= launch_data_alloc(LAUNCH_DATA_DICTIONARY
);
50 CFDictionaryApplyFunction(cfr
, myCFDictionaryApplyFunction
, r
);
51 } else if (cft
== CFDataGetTypeID()) {
52 r
= launch_data_alloc(LAUNCH_DATA_ARRAY
);
53 launch_data_set_opaque(r
, CFDataGetBytePtr(cfr
), CFDataGetLength(cfr
));
54 } else if (cft
== CFNumberGetTypeID()) {
57 CFNumberType cfnt
= CFNumberGetType(cfr
);
59 case kCFNumberSInt8Type
:
60 case kCFNumberSInt16Type
:
61 case kCFNumberSInt32Type
:
62 case kCFNumberSInt64Type
:
63 case kCFNumberCharType
:
64 case kCFNumberShortType
:
65 case kCFNumberIntType
:
66 case kCFNumberLongType
:
67 case kCFNumberLongLongType
:
68 CFNumberGetValue(cfr
, kCFNumberLongLongType
, &n
);
69 r
= launch_data_alloc(LAUNCH_DATA_INTEGER
);
70 launch_data_set_integer(r
, n
);
72 case kCFNumberFloat32Type
:
73 case kCFNumberFloat64Type
:
74 case kCFNumberFloatType
:
75 case kCFNumberDoubleType
:
76 CFNumberGetValue(cfr
, kCFNumberDoubleType
, &d
);
77 r
= launch_data_alloc(LAUNCH_DATA_REAL
);
78 launch_data_set_real(r
, d
);
91 CreateMyPropertyListFromFile(const char *posixfile
)
93 CFPropertyListRef propertyList
;
94 CFStringRef errorString
;
95 CFDataRef resourceData
;
99 fileURL
= CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault
, (const UInt8
*)posixfile
, strlen(posixfile
), false);
101 fprintf(stderr
, "%s: CFURLCreateFromFileSystemRepresentation(%s) failed\n", getprogname(), posixfile
);
103 if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault
, fileURL
, &resourceData
, NULL
, NULL
, &errorCode
)) {
104 fprintf(stderr
, "%s: CFURLCreateDataAndPropertiesFromResource(%s) failed: %d\n", getprogname(), posixfile
, (int)errorCode
);
106 propertyList
= CFPropertyListCreateFromXMLData(kCFAllocatorDefault
, resourceData
, kCFPropertyListMutableContainers
, &errorString
);
108 fprintf(stderr
, "%s: propertyList is NULL\n", getprogname());
114 #define _assert(test, format, args...) do { \
116 fprintf(stderr, format "\n", ##args); \
124 int main(int argc
, const char *argv
[]) {
125 _assert(argc
== 1, "usage: sbreload");
127 CFDictionaryRef plist
= CreateMyPropertyListFromFile("/System/Library/LaunchDaemons/com.apple.SpringBoard.plist");
128 _assert(plist
!= NULL
, "CreateMyPropertyListFromFile() == NULL");
130 launch_data_t job
= CF2launch_data(plist
);
131 _assert(job
!= NULL
, "CF2launch_data() == NULL");
133 launch_data_t data
, request
, response
;
135 data
= launch_data_dict_lookup(job
, LAUNCH_JOBKEY_LABEL
);
136 _assert(data
!= NULL
, "launch_data_dict_lookup(LABEL) == NULL");
137 const char *label
= launch_data_get_string(data
);
139 request
= launch_data_alloc(LAUNCH_DATA_DICTIONARY
);
140 launch_data_dict_insert(request
, launch_data_new_string(label
), LAUNCH_KEY_GETJOB
);
142 response
= launch_msg(request
);
143 _assert(response
!= NULL
, "launch_msg(GetJob) == NULL");
144 launch_data_free(request
);
148 if (launch_data_get_type(response
) == LAUNCH_DATA_ERRNO
) {
149 int error
= launch_data_get_errno(response
);
150 _assert(error
== ESRCH
, "GetJob(%s): %s", label
, strerror(error
));
152 } else if (launch_data_get_type(response
) == LAUNCH_DATA_DICTIONARY
) {
153 data
= launch_data_dict_lookup(response
, LAUNCH_JOBKEY_PID
);
154 _assert(data
!= NULL
, "launch_data_dict_lookup(PID) == NULL");
155 pid
= launch_data_get_integer(data
);
156 } else _assert(false, "launch_data_get_type() not in (DICTIONARY, ERRNO)");
158 launch_data_free(response
);
160 fprintf(stderr
, "notify_post(com.apple.mobile.springboard_teardown)\n");
161 notify_post("com.apple.mobile.springboard_teardown");
164 fprintf(stderr
, "waiting for kill(%u) != 0...\n", pid
);
165 while (kill(pid
, 0) == 0)
169 _assert(error
== ESRCH
, "kill(%u): %s", pid
, strerror(error
));
172 request
= launch_data_alloc(LAUNCH_DATA_DICTIONARY
);
173 launch_data_dict_insert(request
, job
, LAUNCH_KEY_SUBMITJOB
);
176 response
= launch_msg(request
);
177 _assert(response
!= NULL
, "launch_msg(SubmitJob) == NULL");
179 _assert(launch_data_get_type(response
) == LAUNCH_DATA_ERRNO
, "launch_data_get_type() != ERRNO");
180 int error
= launch_data_get_errno(response
);
181 launch_data_free(response
);
183 const char *string
= strerror(error
);
185 if (error
== EEXIST
) {
186 fprintf(stderr
, "SubmitJob(%s): %s, retrying...\n", label
, string
);
189 _assert(error
== 0, "SubmitJob(%s): %s", label
, string
);
194 launch_data_free(request
);