2 * Copyright (c) 2000-2011 Apple 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@
25 * Modification History
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
30 * November 9, 2000 Allan Nathanson <ajn@apple.com>
34 //#define DO_NOT_CRASH
35 //#define DO_NOT_INFORM
37 #include <SystemConfiguration/SystemConfiguration.h>
38 #include <SystemConfiguration/SCValidation.h>
39 #include <SystemConfiguration/SCPrivate.h>
41 #include <sys/param.h>
42 #include <sys/types.h>
43 #include <sys/socket.h>
45 #include <net/if_dl.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
49 #include <mach/mach.h>
50 #include <mach/notify.h>
51 #include <mach/mach_error.h>
60 #if TARGET_OS_EMBEDDED && !TARGET_OS_EMBEDDED_OTHER && !defined(DO_NOT_INFORM)
61 #include <CoreFoundation/CFUserNotification.h>
62 #endif // TARGET_OS_EMBEDDED && !TARGET_OS_EMBEDDED_OTHER && !defined(DO_NOT_INFORM)
68 #pragma mark Miscellaneous
72 _SC_cfstring_to_cstring(CFStringRef cfstr
, char *buf
, CFIndex bufLen
, CFStringEncoding encoding
)
81 len
= CFStringGetLength(cfstr
);
83 /* how much buffer space will we really need? */
84 converted
= CFStringGetBytes(cfstr
,
92 if (converted
< len
) {
93 /* if full string could not be converted */
101 if (bufLen
< (last
+ 1)) {
102 /* if the size of the provided buffer is too small */
107 /* allocate a buffer */
109 buf
= CFAllocatorAllocate(NULL
, bufLen
, 0);
115 (void)CFStringGetBytes(cfstr
,
130 _SC_sockaddr_to_string(const struct sockaddr
*address
, char *buf
, size_t bufLen
)
133 switch (address
->sa_family
) {
135 (void)inet_ntop(((struct sockaddr_in
*)address
)->sin_family
,
136 &((struct sockaddr_in
*)address
)->sin_addr
,
141 (void)inet_ntop(((struct sockaddr_in6
*)address
)->sin6_family
,
142 &((struct sockaddr_in6
*)address
)->sin6_addr
,
145 if (((struct sockaddr_in6
*)address
)->sin6_scope_id
!= 0) {
149 if ((n
+IF_NAMESIZE
+1) <= (int)bufLen
) {
151 if_indextoname(((struct sockaddr_in6
*)address
)->sin6_scope_id
, &buf
[n
]);
157 if (((struct sockaddr_dl
*)address
)->sdl_len
< bufLen
) {
158 bufLen
= ((struct sockaddr_dl
*)address
)->sdl_len
;
163 bcopy(((struct sockaddr_dl
*)address
)->sdl_data
, buf
, bufLen
);
166 snprintf(buf
, bufLen
, "unexpected address family %d", address
->sa_family
);
175 _SC_sendMachMessage(mach_port_t port
, mach_msg_id_t msg_id
)
177 mach_msg_empty_send_t msg
;
178 mach_msg_option_t options
;
179 kern_return_t status
;
181 msg
.header
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0);
182 msg
.header
.msgh_size
= sizeof(msg
);
183 msg
.header
.msgh_remote_port
= port
;
184 msg
.header
.msgh_local_port
= MACH_PORT_NULL
;
185 msg
.header
.msgh_id
= msg_id
;
186 options
= MACH_SEND_TIMEOUT
;
187 status
= mach_msg(&msg
.header
, /* msg */
188 MACH_SEND_MSG
|options
, /* options */
189 msg
.header
.msgh_size
, /* send_size */
191 MACH_PORT_NULL
, /* rcv_name */
193 MACH_PORT_NULL
); /* notify */
194 if (status
!= MACH_MSG_SUCCESS
) {
195 mach_msg_destroy(&msg
.header
);
203 _SC_trimDomain(CFStringRef domain
)
207 if (!isA_CFString(domain
)) {
211 // remove any leading/trailing dots
212 length
= CFStringGetLength(domain
);
214 (CFStringFindWithOptions(domain
,
219 CFStringFindWithOptions(domain
,
221 CFRangeMake(0, length
),
222 kCFCompareAnchored
|kCFCompareBackwards
,
224 CFMutableStringRef trimmed
;
226 trimmed
= CFStringCreateMutableCopy(NULL
, 0, domain
);
227 CFStringTrim(trimmed
, CFSTR("."));
228 domain
= (CFStringRef
)trimmed
;
229 length
= CFStringGetLength(domain
);
244 #pragma mark Serialization
248 _SCSerialize(CFPropertyListRef obj
, CFDataRef
*xml
, void **dataRef
, CFIndex
*dataLen
)
252 if ((xml
== NULL
) && ((dataRef
== NULL
) || (dataLen
== NULL
))) {
253 /* if not keeping track of allocated space */
257 myXml
= CFPropertyListCreateData(NULL
,
259 kCFPropertyListBinaryFormat_v1_0
,
263 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCSerialize() failed"));
267 if ((dataRef
!= NULL
) && (dataLen
!= NULL
)) {
276 if ((dataRef
!= NULL
) && (dataLen
!= NULL
)) {
277 *dataRef
= (void *)CFDataGetBytePtr(myXml
);
278 *dataLen
= CFDataGetLength(myXml
);
281 mach_msg_type_number_t len
;
282 kern_return_t status
;
284 status
= vm_read(mach_task_self(),
285 (vm_address_t
)CFDataGetBytePtr(myXml
), // address
286 (vm_size_t
) CFDataGetLength(myXml
), // size
289 if (status
!= KERN_SUCCESS
) {
290 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCSerialize(): %s"), mach_error_string(status
));
306 _SCUnserialize(CFPropertyListRef
*obj
, CFDataRef xml
, void *dataRef
, CFIndex dataLen
)
311 kern_return_t status
;
313 xml
= CFDataCreateWithBytesNoCopy(NULL
, (void *)dataRef
, dataLen
, kCFAllocatorNull
);
314 *obj
= CFPropertyListCreateWithData(NULL
, xml
, kCFPropertyListImmutable
, NULL
, &error
);
317 status
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
);
318 if (status
!= KERN_SUCCESS
) {
319 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCUnserialize(): %s"), mach_error_string(status
));
320 /* non-fatal???, proceed */
323 *obj
= CFPropertyListCreateWithData(NULL
, xml
, kCFPropertyListImmutable
, NULL
, &error
);
328 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCUnserialize(): %@"), error
);
331 _SCErrorSet(kSCStatusFailed
);
340 _SCSerializeString(CFStringRef str
, CFDataRef
*data
, void **dataRef
, CFIndex
*dataLen
)
344 if (!isA_CFString(str
)) {
345 /* if not a CFString */
349 if ((data
== NULL
) && ((dataRef
== NULL
) || (dataLen
== NULL
))) {
350 /* if not keeping track of allocated space */
354 myData
= CFStringCreateExternalRepresentation(NULL
, str
, kCFStringEncodingUTF8
, 0);
355 if (myData
== NULL
) {
356 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCSerializeString() failed"));
360 if ((dataRef
!= NULL
) && (dataLen
!= NULL
)) {
369 if ((dataRef
!= NULL
) && (dataLen
!= NULL
)) {
370 *dataRef
= (void *)CFDataGetBytePtr(myData
);
371 *dataLen
= CFDataGetLength(myData
);
374 mach_msg_type_number_t len
;
375 kern_return_t status
;
377 *dataLen
= CFDataGetLength(myData
);
378 status
= vm_read(mach_task_self(),
379 (vm_address_t
)CFDataGetBytePtr(myData
), // address
383 if (status
!= KERN_SUCCESS
) {
384 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCSerializeString(): %s"), mach_error_string(status
));
400 _SCUnserializeString(CFStringRef
*str
, CFDataRef utf8
, void *dataRef
, CFIndex dataLen
)
403 kern_return_t status
;
405 utf8
= CFDataCreateWithBytesNoCopy(NULL
, dataRef
, dataLen
, kCFAllocatorNull
);
406 *str
= CFStringCreateFromExternalRepresentation(NULL
, utf8
, kCFStringEncodingUTF8
);
409 status
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
);
410 if (status
!= KERN_SUCCESS
) {
411 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCUnserializeString(): %s"), mach_error_string(status
));
412 /* non-fatal???, proceed */
415 *str
= CFStringCreateFromExternalRepresentation(NULL
, utf8
, kCFStringEncodingUTF8
);
419 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCUnserializeString() failed"));
428 _SCSerializeData(CFDataRef data
, void **dataRef
, CFIndex
*dataLen
)
430 mach_msg_type_number_t len
;
431 kern_return_t status
;
433 if (!isA_CFData(data
)) {
434 /* if not a CFData */
438 *dataLen
= CFDataGetLength(data
);
439 status
= vm_read(mach_task_self(),
440 (vm_address_t
)CFDataGetBytePtr(data
), // address
444 if (status
!= KERN_SUCCESS
) {
445 SCLog(TRUE
, LOG_ERR
, CFSTR("_SCSerializeData(): %s"), mach_error_string(status
));
458 _SCUnserializeData(CFDataRef
*data
, void *dataRef
, CFIndex dataLen
)
460 kern_return_t status
;
462 *data
= CFDataCreate(NULL
, dataRef
, dataLen
);
463 status
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
);
464 if (status
!= KERN_SUCCESS
) {
465 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("_SCUnserializeData(): %s"), mach_error_string(status
));
466 _SCErrorSet(kSCStatusFailed
);
475 _SCSerializeMultiple(CFDictionaryRef dict
)
477 const void * keys_q
[N_QUICK
];
478 const void ** keys
= keys_q
;
480 CFDictionaryRef newDict
= NULL
;
481 const void * pLists_q
[N_QUICK
];
482 const void ** pLists
= pLists_q
;
483 const void * values_q
[N_QUICK
];
484 const void ** values
= values_q
;
486 nElements
= CFDictionaryGetCount(dict
);
490 if (nElements
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
491 keys
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
492 values
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
493 pLists
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
495 bzero(pLists
, nElements
* sizeof(CFTypeRef
));
497 CFDictionaryGetKeysAndValues(dict
, keys
, values
);
498 for (i
= 0; i
< nElements
; i
++) {
499 if (!_SCSerialize((CFPropertyListRef
)values
[i
], (CFDataRef
*)&pLists
[i
], NULL
, NULL
)) {
505 newDict
= CFDictionaryCreate(NULL
,
509 &kCFTypeDictionaryKeyCallBacks
,
510 &kCFTypeDictionaryValueCallBacks
);
517 for (i
= 0; i
< nElements
; i
++) {
518 if (pLists
[i
]) CFRelease(pLists
[i
]);
521 if (keys
!= keys_q
) {
522 CFAllocatorDeallocate(NULL
, keys
);
523 CFAllocatorDeallocate(NULL
, values
);
524 CFAllocatorDeallocate(NULL
, pLists
);
533 _SCUnserializeMultiple(CFDictionaryRef dict
)
535 const void * keys_q
[N_QUICK
];
536 const void ** keys
= keys_q
;
538 CFDictionaryRef newDict
= NULL
;
539 const void * pLists_q
[N_QUICK
];
540 const void ** pLists
= pLists_q
;
541 const void * values_q
[N_QUICK
];
542 const void ** values
= values_q
;
544 nElements
= CFDictionaryGetCount(dict
);
548 if (nElements
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
549 keys
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
550 values
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
551 pLists
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
553 bzero(pLists
, nElements
* sizeof(CFTypeRef
));
555 CFDictionaryGetKeysAndValues(dict
, keys
, values
);
556 for (i
= 0; i
< nElements
; i
++) {
557 if (!_SCUnserialize((CFPropertyListRef
*)&pLists
[i
], values
[i
], NULL
, 0)) {
563 newDict
= CFDictionaryCreate(NULL
,
567 &kCFTypeDictionaryKeyCallBacks
,
568 &kCFTypeDictionaryValueCallBacks
);
575 for (i
= 0; i
< nElements
; i
++) {
576 if (pLists
[i
]) CFRelease(pLists
[i
]);
579 if (keys
!= keys_q
) {
580 CFAllocatorDeallocate(NULL
, keys
);
581 CFAllocatorDeallocate(NULL
, values
);
582 CFAllocatorDeallocate(NULL
, pLists
);
591 #pragma mark CFRunLoop scheduling
594 __private_extern__
void
595 _SC_signalRunLoop(CFTypeRef obj
, CFRunLoopSourceRef rls
, CFArrayRef rlList
)
597 CFRunLoopRef rl
= NULL
;
598 CFRunLoopRef rl1
= NULL
;
600 CFIndex n
= CFArrayGetCount(rlList
);
606 /* get first runLoop for this object */
607 for (i
= 0; i
< n
; i
+= 3) {
608 if (!CFEqual(obj
, CFArrayGetValueAtIndex(rlList
, i
))) {
612 rl1
= (CFRunLoopRef
)CFArrayGetValueAtIndex(rlList
, i
+1);
617 /* if not scheduled */
621 /* check if we have another runLoop for this object */
623 for (i
= i
+3; i
< n
; i
+= 3) {
626 if (!CFEqual(obj
, CFArrayGetValueAtIndex(rlList
, i
))) {
630 rl2
= (CFRunLoopRef
)CFArrayGetValueAtIndex(rlList
, i
+1);
631 if (!CFEqual(rl1
, rl2
)) {
632 /* we've got more than one runLoop */
639 /* if we only have one runLoop */
644 /* more than one different runLoop, so we must pick one */
645 for (i
= 0; i
< n
; i
+=3) {
648 if (!CFEqual(obj
, CFArrayGetValueAtIndex(rlList
, i
))) {
652 rl
= (CFRunLoopRef
)CFArrayGetValueAtIndex(rlList
, i
+1);
653 rlMode
= CFRunLoopCopyCurrentMode(rl
);
654 if (rlMode
!= NULL
) {
657 waiting
= (CFRunLoopIsWaiting(rl
) && CFRunLoopContainsSource(rl
, rls
, rlMode
));
660 /* we've found a runLoop that's "ready" */
667 /* didn't choose one above, so choose first */
668 CFRunLoopWakeUp(rl1
);
673 __private_extern__ Boolean
674 _SC_isScheduled(CFTypeRef obj
, CFRunLoopRef runLoop
, CFStringRef runLoopMode
, CFMutableArrayRef rlList
)
677 CFIndex n
= CFArrayGetCount(rlList
);
679 for (i
= 0; i
< n
; i
+= 3) {
680 if ((obj
!= NULL
) && !CFEqual(obj
, CFArrayGetValueAtIndex(rlList
, i
))) {
683 if ((runLoop
!= NULL
) && !CFEqual(runLoop
, CFArrayGetValueAtIndex(rlList
, i
+1))) {
686 if ((runLoopMode
!= NULL
) && !CFEqual(runLoopMode
, CFArrayGetValueAtIndex(rlList
, i
+2))) {
696 __private_extern__
void
697 _SC_schedule(CFTypeRef obj
, CFRunLoopRef runLoop
, CFStringRef runLoopMode
, CFMutableArrayRef rlList
)
699 CFArrayAppendValue(rlList
, obj
);
700 CFArrayAppendValue(rlList
, runLoop
);
701 CFArrayAppendValue(rlList
, runLoopMode
);
707 __private_extern__ Boolean
708 _SC_unschedule(CFTypeRef obj
, CFRunLoopRef runLoop
, CFStringRef runLoopMode
, CFMutableArrayRef rlList
, Boolean all
)
711 Boolean found
= FALSE
;
712 CFIndex n
= CFArrayGetCount(rlList
);
715 if ((obj
!= NULL
) && !CFEqual(obj
, CFArrayGetValueAtIndex(rlList
, i
))) {
719 if ((runLoop
!= NULL
) && !CFEqual(runLoop
, CFArrayGetValueAtIndex(rlList
, i
+1))) {
723 if ((runLoopMode
!= NULL
) && !CFEqual(runLoopMode
, CFArrayGetValueAtIndex(rlList
, i
+2))) {
730 CFArrayRemoveValueAtIndex(rlList
, i
+ 2);
731 CFArrayRemoveValueAtIndex(rlList
, i
+ 1);
732 CFArrayRemoveValueAtIndex(rlList
, i
);
749 #define SYSTEMCONFIGURATION_BUNDLE_ID CFSTR("com.apple.SystemConfiguration")
750 #define SYSTEMCONFIGURATION_FRAMEWORK_PATH "/System/Library/Frameworks/SystemConfiguration.framework"
751 #define SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN (sizeof(SYSTEMCONFIGURATION_FRAMEWORK_PATH) - 1)
753 #define SUFFIX_SYM "~sym"
754 #define SUFFIX_SYM_LEN (sizeof(SUFFIX_SYM) - 1)
756 #define SUFFIX_DST "~dst"
760 _SC_CFBundleGet(void)
762 static CFBundleRef bundle
= NULL
;
766 if (bundle
!= NULL
) {
770 bundle
= CFBundleGetBundleWithIdentifier(SYSTEMCONFIGURATION_BUNDLE_ID
);
771 if (bundle
!= NULL
) {
772 CFRetain(bundle
); // we want to hold a reference to the bundle
776 // if appropriate (e.g. when debugging), try a bit harder
778 env
= getenv("DYLD_FRAMEWORK_PATH");
779 len
= (env
!= NULL
) ? strlen(env
) : 0;
781 // trim any trailing slashes
783 if (env
[len
- 1] != '/') {
789 // if DYLD_FRAMEWORK_PATH is ".../xxx~sym" than try ".../xxx~dst"
790 if ((len
> SUFFIX_SYM_LEN
) &&
791 (strncmp(&env
[len
- SUFFIX_SYM_LEN
], SUFFIX_SYM
, SUFFIX_SYM_LEN
) == 0) &&
792 ((len
+ SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN
) < MAXPATHLEN
)) {
793 char path
[MAXPATHLEN
];
796 strlcpy(path
, env
, sizeof(path
));
797 strlcpy(&path
[len
- SUFFIX_SYM_LEN
], SUFFIX_DST
, sizeof(path
) - (len
- SUFFIX_SYM_LEN
));
798 strlcat(&path
[len
], SYSTEMCONFIGURATION_FRAMEWORK_PATH
, sizeof(path
) - len
);
800 url
= CFURLCreateFromFileSystemRepresentation(NULL
,
802 len
+ SYSTEMCONFIGURATION_FRAMEWORK_PATH_LEN
,
804 bundle
= CFBundleCreate(NULL
, url
);
808 if (bundle
== NULL
) {
809 static Boolean warned
= FALSE
;
811 SCLog(!warned
, LOG_WARNING
,
812 CFSTR("_SC_CFBundleGet(), could not get CFBundle for \"%@\""),
813 SYSTEMCONFIGURATION_BUNDLE_ID
);
822 _SC_CFBundleCopyNonLocalizedString(CFBundleRef bundle
, CFStringRef key
, CFStringRef value
, CFStringRef tableName
)
824 CFStringRef str
= NULL
;
827 if ((tableName
== NULL
) || CFEqual(tableName
, CFSTR(""))) tableName
= CFSTR("Localizable");
829 url
= CFBundleCopyResourceURLForLocalization(bundle
,
835 CFDataRef data
= NULL
;
838 if (CFURLCreateDataAndPropertiesFromResource(NULL
,
844 CFDictionaryRef table
;
846 table
= CFPropertyListCreateWithData(NULL
,
848 kCFPropertyListImmutable
,
852 if (isA_CFDictionary(table
)) {
853 str
= CFDictionaryGetValue(table
, key
);
869 str
= CFRetain(value
);
877 #pragma mark Mach port / CFMachPort management
881 _SC_CFMachPortCreateWithPort(const char *portDescription
,
883 CFMachPortCallBack callout
,
884 CFMachPortContext
*context
)
887 Boolean shouldFree
= FALSE
;
889 port
= CFMachPortCreateWithPort(NULL
, portNum
, callout
, context
, &shouldFree
);
890 if ((port
== NULL
) || shouldFree
) {
892 char *crash_info
= NULL
;
896 CFSTR("%s: CFMachPortCreateWithPort() failed , port = %p"),
900 err
= CFStringCreateWithFormat(NULL
, NULL
,
901 CFSTR("%s: CFMachPortCreateWithPort recycled, [old] port = %@"),
902 portDescription
, port
);
904 err
= CFStringCreateWithFormat(NULL
, NULL
,
905 CFSTR("%s: CFMachPortCreateWithPort returned NULL"),
908 crash_info
= _SC_cfstring_to_cstring(err
, NULL
, 0, kCFStringEncodingASCII
);
911 (void) proc_name(getpid(), name
, sizeof(name
));
912 err
= CFStringCreateWithFormat(NULL
,
914 CFSTR("A recycled mach_port has been detected by \"%s\"."),
916 _SC_crash(crash_info
, CFSTR("CFMachPort error"), err
);
917 CFAllocatorDeallocate(NULL
, crash_info
);
926 #pragma mark DOS encoding/codepage
929 #if !TARGET_OS_IPHONE
931 _SC_dos_encoding_and_codepage(CFStringEncoding macEncoding
,
933 CFStringEncoding
*dosEncoding
,
936 switch (macEncoding
) {
937 case kCFStringEncodingMacRoman
:
938 if (macRegion
!= 0) /* anything non-zero is not US */
939 *dosEncoding
= kCFStringEncodingDOSLatin1
;
941 *dosEncoding
= kCFStringEncodingDOSLatinUS
;
944 case kCFStringEncodingMacJapanese
:
945 *dosEncoding
= kCFStringEncodingDOSJapanese
;
948 case kCFStringEncodingMacChineseTrad
:
949 *dosEncoding
= kCFStringEncodingDOSChineseTrad
;
952 case kCFStringEncodingMacKorean
:
953 *dosEncoding
= kCFStringEncodingDOSKorean
;
956 case kCFStringEncodingMacArabic
:
957 *dosEncoding
= kCFStringEncodingDOSArabic
;
960 case kCFStringEncodingMacHebrew
:
961 *dosEncoding
= kCFStringEncodingDOSHebrew
;
964 case kCFStringEncodingMacGreek
:
965 *dosEncoding
= kCFStringEncodingDOSGreek
;
968 case kCFStringEncodingMacCyrillic
:
969 *dosEncoding
= kCFStringEncodingDOSCyrillic
;
972 case kCFStringEncodingMacThai
:
973 *dosEncoding
= kCFStringEncodingDOSThai
;
976 case kCFStringEncodingMacChineseSimp
:
977 *dosEncoding
= kCFStringEncodingDOSChineseSimplif
;
980 case kCFStringEncodingMacCentralEurRoman
:
981 *dosEncoding
= kCFStringEncodingDOSLatin2
;
984 case kCFStringEncodingMacTurkish
:
985 *dosEncoding
= kCFStringEncodingDOSTurkish
;
988 case kCFStringEncodingMacCroatian
:
989 *dosEncoding
= kCFStringEncodingDOSLatin2
;
992 case kCFStringEncodingMacIcelandic
:
993 *dosEncoding
= kCFStringEncodingDOSIcelandic
;
996 case kCFStringEncodingMacRomanian
:
997 *dosEncoding
= kCFStringEncodingDOSLatin2
;
1000 case kCFStringEncodingMacFarsi
:
1001 *dosEncoding
= kCFStringEncodingDOSArabic
;
1004 case kCFStringEncodingMacUkrainian
:
1005 *dosEncoding
= kCFStringEncodingDOSCyrillic
;
1009 *dosEncoding
= kCFStringEncodingDOSLatin1
;
1013 *dosCodepage
= CFStringConvertEncodingToWindowsCodepage(*dosEncoding
);
1016 #endif // !TARGET_OS_IPHONE
1020 #pragma mark Debugging
1024 * print status of in-use mach ports
1027 _SC_logMachPortStatus(void)
1029 kern_return_t status
;
1030 mach_port_name_array_t ports
;
1031 mach_port_type_array_t types
;
1032 mach_msg_type_number_t pi
, pn
, tn
;
1033 CFMutableStringRef str
;
1035 SCLog(TRUE
, LOG_NOTICE
, CFSTR("----------"));
1037 /* report on ALL mach ports associated with this task */
1038 status
= mach_port_names(mach_task_self(), &ports
, &pn
, &types
, &tn
);
1039 if (status
== MACH_MSG_SUCCESS
) {
1040 str
= CFStringCreateMutable(NULL
, 0);
1041 for (pi
= 0; pi
< pn
; pi
++) {
1042 char rights
[16], *rp
= &rights
[0];
1044 if (types
[pi
] != MACH_PORT_TYPE_NONE
) {
1047 if (types
[pi
] & MACH_PORT_TYPE_SEND
)
1049 if (types
[pi
] & MACH_PORT_TYPE_RECEIVE
)
1051 if (types
[pi
] & MACH_PORT_TYPE_SEND_ONCE
)
1053 if (types
[pi
] & MACH_PORT_TYPE_PORT_SET
)
1055 if (types
[pi
] & MACH_PORT_TYPE_DEAD_NAME
)
1060 CFStringAppendFormat(str
, NULL
, CFSTR(" %d%s"), ports
[pi
], rights
);
1062 SCLog(TRUE
, LOG_NOTICE
, CFSTR("Task ports (n=%d):%@"), pn
, str
);
1071 _SC_logMachPortReferences(const char *str
, mach_port_t port
)
1073 const char *blanks
= " ";
1075 mach_port_type_t pt
;
1076 mach_port_status_t recv_status
= { 0 };
1077 mach_port_urefs_t refs_send
= 0;
1078 mach_port_urefs_t refs_recv
= 0;
1079 mach_port_urefs_t refs_once
= 0;
1080 mach_port_urefs_t refs_pset
= 0;
1081 mach_port_urefs_t refs_dead
= 0;
1082 kern_return_t status
;
1086 static int is_configd
= -1;
1088 if (is_configd
== -1) {
1091 (void) proc_name(getpid(), name
, sizeof(name
));
1092 is_configd
= (strncmp(name
, "configd", sizeof(name
)) == 0);
1094 if (is_configd
== 1) {
1095 // if "configd", add indication if this is the M[ain] or [P]lugin thread
1097 (CFRunLoopGetMain() == CFRunLoopGetCurrent()) ? "M " : "P ",
1101 // add provided string
1102 strlcat(buf
, str
, sizeof(buf
));
1105 strlcat(buf
, blanks
, sizeof(buf
));
1106 if (strcmp(&buf
[sizeof(buf
) - 3], " ") == 0) {
1107 buf
[sizeof(buf
) - 3] = ':';
1111 status
= mach_port_type(mach_task_self(), port
, &pt
);
1112 if (status
!= KERN_SUCCESS
) {
1113 SCLog(TRUE
, LOG_NOTICE
,
1114 CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_SEND): %s"),
1117 mach_error_string(status
));
1120 if ((pt
& MACH_PORT_TYPE_SEND
) != 0) {
1121 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_SEND
, &refs_send
);
1122 if (status
!= KERN_SUCCESS
) {
1123 SCLog(TRUE
, LOG_NOTICE
,
1124 CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_SEND): %s"),
1127 mach_error_string(status
));
1131 if ((pt
& MACH_PORT_TYPE_RECEIVE
) != 0) {
1132 mach_msg_type_number_t count
;
1134 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_RECEIVE
, &refs_recv
);
1135 if (status
!= KERN_SUCCESS
) {
1136 SCLog(TRUE
, LOG_NOTICE
,
1137 CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_RECEIVE): %s"),
1140 mach_error_string(status
));
1143 count
= MACH_PORT_RECEIVE_STATUS_COUNT
;
1144 status
= mach_port_get_attributes(mach_task_self(),
1146 MACH_PORT_RECEIVE_STATUS
,
1147 (mach_port_info_t
)&recv_status
,
1149 if (status
!= KERN_SUCCESS
) {
1150 SCLog(TRUE
, LOG_NOTICE
,
1151 CFSTR("%mach_port_get_attributes(..., %d, MACH_PORT_RECEIVE_STATUS): %s"),
1154 mach_error_string(status
));
1158 if ((pt
& MACH_PORT_TYPE_SEND_ONCE
) != 0) {
1159 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_SEND_ONCE
, &refs_once
);
1160 if (status
!= KERN_SUCCESS
) {
1161 SCLog(TRUE
, LOG_NOTICE
,
1162 CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_SEND_ONCE): %s"),
1165 mach_error_string(status
));
1169 if ((pt
& MACH_PORT_TYPE_PORT_SET
) != 0) {
1170 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_PORT_SET
, &refs_pset
);
1171 if (status
!= KERN_SUCCESS
) {
1172 SCLog(TRUE
, LOG_NOTICE
,
1173 CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_PORT_SET): %s"),
1176 mach_error_string(status
));
1180 if ((pt
& MACH_PORT_TYPE_DEAD_NAME
) != 0) {
1181 status
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_DEAD_NAME
, &refs_dead
);
1182 if (status
!= KERN_SUCCESS
) {
1183 SCLog(TRUE
, LOG_NOTICE
,
1184 CFSTR("%smach_port_get_refs(..., %d, MACH_PORT_RIGHT_DEAD_NAME): %s"),
1187 mach_error_string(status
));
1191 SCLog(TRUE
, LOG_NOTICE
,
1192 CFSTR("%smach port 0x%x (%d): send=%d, receive=%d, send once=%d, port set=%d, dead name=%d%s%s"),
1201 recv_status
.mps_nsrequest
? ", no more senders" : "",
1202 ((pt
& MACH_PORT_TYPE_DEAD_NAME
) != 0) ? ", dead name request" : "");
1214 CFMutableStringRef trace
;
1216 n
= backtrace(stack
, sizeof(stack
)/sizeof(stack
[0]));
1218 SCLog(TRUE
, LOG_ERR
, CFSTR("backtrace() failed: %s"), strerror(errno
));
1222 trace
= CFStringCreateMutable(NULL
, 0);
1224 symbols
= backtrace_symbols(stack
, n
);
1225 if (symbols
!= NULL
) {
1228 for (i
= 0; i
< n
; i
++) {
1229 CFStringAppendFormat(trace
, NULL
, CFSTR("%s\n"), symbols
[i
]);
1239 /* CrashReporter info */
1240 const char *__crashreporter_info__
= NULL
;
1241 asm(".desc ___crashreporter_info__, 0x10");
1245 _SC_SimulateCrash(const char *crash_info
, CFStringRef notifyHeader
, CFStringRef notifyMessage
)
1247 static bool (*dyfunc_SimulateCrash
)(pid_t
, mach_exception_data_type_t
, CFStringRef
) = NULL
;
1248 static void *image
= NULL
;
1251 if ((dyfunc_SimulateCrash
== NULL
) && (image
== NULL
)) {
1252 const char *framework
= "/System/Library/PrivateFrameworks/CrashReporterSupport.framework/"
1253 #if !TARGET_OS_EMBEDDED
1255 #endif // !TARGET_OS_EMBEDDED
1256 "CrashReporterSupport";
1257 struct stat statbuf
;
1258 const char *suffix
= getenv("DYLD_IMAGE_SUFFIX");
1259 char path
[MAXPATHLEN
];
1261 strlcpy(path
, framework
, sizeof(path
));
1262 if (suffix
) strlcat(path
, suffix
, sizeof(path
));
1263 if (0 <= stat(path
, &statbuf
)) {
1264 image
= dlopen(path
, RTLD_LAZY
| RTLD_LOCAL
);
1266 image
= dlopen(framework
, RTLD_LAZY
| RTLD_LOCAL
);
1269 if (image
!= NULL
) {
1270 dyfunc_SimulateCrash
= dlsym(image
, "SimulateCrash");
1272 image
= (void *)0x1; // to ensure that we only dlopen() once
1276 if (dyfunc_SimulateCrash
!= NULL
) {
1279 str
= CFStringCreateWithCString(NULL
, crash_info
, kCFStringEncodingUTF8
);
1280 ok
= dyfunc_SimulateCrash(getpid(), 0xbad0005cull
, str
);
1284 #if TARGET_OS_EMBEDDED && !TARGET_OS_EMBEDDED_OTHER && !defined(DO_NOT_INFORM)
1286 static Boolean warned
= FALSE
;
1289 notifyMessage
= CFStringCreateWithFormat(NULL
,
1291 CFSTR("%@\n\nPlease collect the crash report and file a Radar."),
1293 CFUserNotificationDisplayNotice(0,
1294 kCFUserNotificationStopAlertLevel
,
1301 CFRelease(notifyMessage
);
1305 #endif // TARGET_OS_EMBEDDED && !TARGET_OS_EMBEDDED_OTHER && !defined(DO_NOT_INFORM)
1312 _SC_crash(const char *crash_info
, CFStringRef notifyHeader
, CFStringRef notifyMessage
)
1316 if (crash_info
!= NULL
) {
1317 __crashreporter_info__
= crash_info
;
1319 SCLog(TRUE
, LOG_ERR
, CFSTR("%s"), crash_info
);
1322 if (_SC_isAppleInternal()) {
1323 // simulate a crash report
1324 ok
= _SC_SimulateCrash(crash_info
, notifyHeader
, notifyMessage
);
1325 #ifndef DO_NOT_CRASH
1327 // if we could not simulate a crash report, crash for real
1330 #endif // DO_NOT_CRASH
1333 __crashreporter_info__
= NULL
;