2 * Copyright (c) 2000-2008, 2010-2013 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 * March 24, 2000 Allan Nathanson <ajn@apple.com>
34 #include <mach/mach.h>
35 #include <mach/mach_error.h>
36 #include <servers/bootstrap.h>
42 #include <SystemConfiguration/SystemConfiguration.h>
43 #include <SystemConfiguration/SCPrivate.h>
45 #include "SCDynamicStoreInternal.h"
46 #include "config.h" /* MiG generated file */
49 /* framework variables */
50 int _sc_debug
= FALSE
; /* non-zero if debugging enabled */
51 int _sc_verbose
= FALSE
; /* non-zero if verbose logging enabled */
52 int _sc_log
= TRUE
; /* 0 if SC messages should be written to stdout/stderr,
53 1 if SC messages should be logged w/asl(3),
54 2 if SC messages should be written to stdout/stderr AND logged */
58 #pragma mark Thread specific data
61 static pthread_once_t tsKeyInitialized
= PTHREAD_ONCE_INIT
;
62 static pthread_key_t tsDataKey
;
66 __SCThreadSpecificDataFinalize(void *arg
)
68 __SCThreadSpecificDataRef tsd
= (__SCThreadSpecificDataRef
)arg
;
71 if (tsd
->_asl
!= NULL
) asl_close(tsd
->_asl
);
72 if (tsd
->_sc_store
!= NULL
) CFRelease(tsd
->_sc_store
);
73 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, tsd
);
80 __SCThreadSpecificKeyInitialize()
82 pthread_key_create(&tsDataKey
, __SCThreadSpecificDataFinalize
);
88 __SCThreadSpecificDataRef
89 __SCGetThreadSpecificData()
91 __SCThreadSpecificDataRef tsd
;
92 pthread_once(&tsKeyInitialized
, __SCThreadSpecificKeyInitialize
);
94 tsd
= pthread_getspecific(tsDataKey
);
96 tsd
= CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(__SCThreadSpecificData
), 0);
98 tsd
->_sc_error
= kSCStatusOK
;
99 tsd
->_sc_store
= NULL
;
100 pthread_setspecific(tsDataKey
, tsd
);
111 #define kASLModule "ASLModule"
112 #define kASLOption "ASLOption"
113 #define kLoggerID "LoggerID"
115 #define ENABLE_SC_FORMATTING
116 #ifdef ENABLE_SC_FORMATTING
117 // from <CoreFoundation/ForFoundationOnly.h>
118 extern CFStringRef
_CFStringCreateWithFormatAndArgumentsAux(CFAllocatorRef alloc
, CFStringRef (*copyDescFunc
)(CFTypeRef
, CFDictionaryRef
), CFDictionaryRef formatOptions
, CFStringRef format
, va_list arguments
);
119 #endif /* ENABLE_SC_FORMATTING */
123 _SCCopyDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
)
125 #ifdef ENABLE_SC_FORMATTING
126 CFMutableDictionaryRef nFormatOptions
;
129 CFTypeID type
= CFGetTypeID(cf
);
131 if (!formatOptions
||
132 !CFDictionaryGetValueIfPresent(formatOptions
, CFSTR("PREFIX1"), (const void **)&prefix1
)) {
136 if (type
== CFStringGetTypeID()) {
137 return CFStringCreateWithFormat(NULL
,
144 if (type
== CFBooleanGetTypeID()) {
145 return CFStringCreateWithFormat(NULL
,
149 CFBooleanGetValue(cf
) ? "TRUE" : "FALSE");
152 if (type
== CFDataGetTypeID()) {
156 CFMutableStringRef str
;
158 str
= CFStringCreateMutable(NULL
, 0);
159 CFStringAppendFormat(str
, formatOptions
, CFSTR("%@<data> 0x"), prefix1
);
161 data
= CFDataGetBytePtr(cf
);
162 dataLen
= CFDataGetLength(cf
);
163 for (i
= 0; i
< dataLen
; i
++) {
164 CFStringAppendFormat(str
, NULL
, CFSTR("%02x"), data
[i
]);
170 if (type
== CFNumberGetTypeID()) {
171 return CFStringCreateWithFormat(NULL
,
178 if (type
== CFDateGetTypeID()) {
179 CFGregorianDate gDate
;
183 tZone
= CFTimeZoneCopySystem();
184 gDate
= CFAbsoluteTimeGetGregorianDate(CFDateGetAbsoluteTime(cf
), tZone
);
185 str
= CFStringCreateWithFormat(NULL
,
187 CFSTR("%@%02d/%02d/%04d %02d:%02d:%02.0f %@"),
195 CFTimeZoneGetName(tZone
));
200 if ((formatOptions
== NULL
) ||
201 !CFDictionaryGetValueIfPresent(formatOptions
, CFSTR("PREFIX2"), (const void **)&prefix2
)) {
205 if (formatOptions
!= NULL
) {
206 nFormatOptions
= CFDictionaryCreateMutableCopy(NULL
, 0, formatOptions
);
208 nFormatOptions
= CFDictionaryCreateMutable(NULL
,
210 &kCFTypeDictionaryKeyCallBacks
,
211 &kCFTypeDictionaryValueCallBacks
);
213 assert(nFormatOptions
!= NULL
);
217 if (type
== CFArrayGetTypeID()) {
218 const void * elements_q
[N_QUICK
];
219 const void ** elements
= elements_q
;
222 CFMutableStringRef str
;
224 str
= CFStringCreateMutable(NULL
, 0);
225 CFStringAppendFormat(str
, formatOptions
, CFSTR("%@<array> {"), prefix1
);
227 nElements
= CFArrayGetCount(cf
);
229 if (nElements
> (CFIndex
)(sizeof(elements_q
)/sizeof(CFTypeRef
)))
230 elements
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
231 CFArrayGetValues(cf
, CFRangeMake(0, nElements
), elements
);
232 for (i
= 0; i
< nElements
; i
++) {
233 CFMutableStringRef nPrefix1
;
234 CFMutableStringRef nPrefix2
;
238 nStr
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%ld"), i
);
240 nPrefix1
= CFStringCreateMutable(NULL
, 0);
241 CFStringAppendFormat(nPrefix1
,
246 nPrefix2
= CFStringCreateMutable(NULL
, 0);
247 CFStringAppendFormat(nPrefix2
,
252 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX1"), nPrefix1
);
253 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX2"), nPrefix2
);
258 vStr
= _SCCopyDescription((CFTypeRef
)elements
[i
], nFormatOptions
);
259 CFStringAppendFormat(str
,
265 if (elements
!= elements_q
) CFAllocatorDeallocate(NULL
, elements
);
267 CFStringAppendFormat(str
, formatOptions
, CFSTR("\n%@}"), prefix2
);
269 CFRelease(nFormatOptions
);
273 if (type
== CFDictionaryGetTypeID()) {
274 const void * keys_q
[N_QUICK
];
275 const void ** keys
= keys_q
;
278 CFMutableStringRef nPrefix1
;
279 CFMutableStringRef nPrefix2
;
280 CFMutableStringRef str
;
282 str
= CFStringCreateMutable(NULL
, 0);
283 CFStringAppendFormat(str
, formatOptions
, CFSTR("%@<dictionary> {"), prefix1
);
285 nElements
= CFDictionaryGetCount(cf
);
287 CFMutableArrayRef sortedKeys
;
289 if (nElements
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
290 keys
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
292 CFDictionaryGetKeysAndValues(cf
, keys
, NULL
);
294 sortedKeys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
295 for (i
= 0; i
< nElements
; i
++) {
296 CFArrayAppendValue(sortedKeys
, (CFStringRef
)keys
[i
]);
298 CFArraySortValues(sortedKeys
,
299 CFRangeMake(0, nElements
),
300 (CFComparatorFunction
)CFStringCompare
,
303 for (i
= 0; i
< nElements
; i
++) {
309 key
= CFArrayGetValueAtIndex(sortedKeys
, i
);
310 kStr
= _SCCopyDescription((CFTypeRef
)key
, NULL
);
312 nPrefix1
= CFStringCreateMutable(NULL
, 0);
313 CFStringAppendFormat(nPrefix1
,
318 nPrefix2
= CFStringCreateMutable(NULL
, 0);
319 CFStringAppendFormat(nPrefix2
,
324 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX1"), nPrefix1
);
325 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX2"), nPrefix2
);
330 val
= CFDictionaryGetValue(cf
, key
);
331 vStr
= _SCCopyDescription((CFTypeRef
)val
, nFormatOptions
);
332 CFStringAppendFormat(str
,
339 CFRelease(sortedKeys
);
341 if (keys
!= keys_q
) {
342 CFAllocatorDeallocate(NULL
, keys
);
345 CFStringAppendFormat(str
, formatOptions
, CFSTR("\n%@}"), prefix2
);
347 CFRelease(nFormatOptions
);
351 CFRelease(nFormatOptions
);
352 #endif /* ENABLE_SC_FORMATTING */
354 return CFStringCreateWithFormat(NULL
,
362 static pthread_mutex_t lock
= PTHREAD_MUTEX_INITIALIZER
;
365 __SCLog(aslclient asl
, aslmsg msg
, int level
, CFStringRef formatString
, va_list formatArguments
)
372 __SCThreadSpecificDataRef tsd
;
374 tsd
= __SCGetThreadSpecificData();
375 if (tsd
->_asl
== NULL
) {
376 tsd
->_asl
= asl_open(NULL
, NULL
, 0);
377 asl_set_filter(tsd
->_asl
, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG
));
382 #ifdef ENABLE_SC_FORMATTING
383 str
= _CFStringCreateWithFormatAndArgumentsAux(NULL
,
388 #else /* ENABLE_SC_FORMATTING */
389 str
= CFStringCreateWithFormatAndArguments (NULL
,
393 #endif /* !ENABLE_SC_FORMATTING */
396 lines
= CFStringCreateArrayBySeparatingStrings(NULL
, str
, CFSTR("\n"));
399 int n
= CFArrayGetCount(lines
);
401 for (i
= 0; i
< n
; i
++) {
402 line
= CFStringCreateExternalRepresentation(NULL
,
403 CFArrayGetValueAtIndex(lines
, i
),
404 kCFStringEncodingUTF8
,
407 asl_log(asl
, msg
, level
, "%.*s", (int)CFDataGetLength(line
), CFDataGetBytePtr(line
));
414 line
= CFStringCreateExternalRepresentation(NULL
,
416 kCFStringEncodingUTF8
,
419 asl_log(asl
, msg
, ~level
, "%.*s", (int)CFDataGetLength(line
), CFDataGetBytePtr(line
));
430 __SCPrint(FILE *stream
, CFStringRef formatString
, va_list formatArguments
, Boolean trace
, Boolean addNL
)
435 #ifdef ENABLE_SC_FORMATTING
436 str
= _CFStringCreateWithFormatAndArgumentsAux(NULL
,
441 #else /* ENABLE_SC_FORMATTING */
442 str
= CFStringCreateWithFormatAndArguments (NULL
,
446 #endif /* !ENABLE_SC_FORMATTING */
448 line
= CFStringCreateExternalRepresentation(NULL
,
450 kCFStringEncodingUTF8
,
457 pthread_mutex_lock(&lock
);
460 struct timeval tv_now
;
462 (void)gettimeofday(&tv_now
, NULL
);
463 (void)localtime_r(&tv_now
.tv_sec
, &tm_now
);
464 (void)fprintf(stream
, "%2d:%02d:%02d.%03d ",
465 tm_now
.tm_hour
, tm_now
.tm_min
, tm_now
.tm_sec
, tv_now
.tv_usec
/ 1000);
467 (void)fwrite((const void *)CFDataGetBytePtr(line
), (size_t)CFDataGetLength(line
), 1, stream
);
469 (void)fputc('\n', stream
);
472 pthread_mutex_unlock(&lock
);
480 SCLog(Boolean condition
, int level
, CFStringRef formatString
, ...)
482 va_list formatArguments
;
483 va_list formatArguments_print
;
485 Boolean print
= FALSE
;
492 * Note: The following are the expected values for _sc_log
494 * 0 if SC messages should be written to stdout/stderr
495 * 1 if SC messages should be logged w/asl(3)
496 * 2 if SC messages should be written to stdout/stderr AND logged
500 log
= TRUE
; // log requested
501 va_start(formatArguments
, formatString
);
504 print
= TRUE
; // log AND print requested
505 va_copy(formatArguments_print
, formatArguments
);
508 print
= TRUE
; // print requested
509 va_start(formatArguments_print
, formatString
);
513 __SCLog(NULL
, NULL
, level
, formatString
, formatArguments
);
514 va_end(formatArguments
);
518 __SCPrint((LOG_PRI(level
) > LOG_NOTICE
) ? stderr
: stdout
,
520 formatArguments_print
,
521 (_sc_log
> 0), // trace
522 TRUE
); // add newline
523 va_end(formatArguments_print
);
531 SCLOG(aslclient asl
, aslmsg msg
, int level
, CFStringRef formatString
, ...)
533 va_list formatArguments
;
534 va_list formatArguments_print
;
536 Boolean print
= FALSE
;
539 * Note: The following are the expected values for _sc_log
541 * 0 if SC messages should be written to stdout/stderr
542 * 1 if SC messages should be logged w/asl(3)
543 * 2 if SC messages should be written to stdout/stderr AND logged
547 log
= TRUE
; // log requested
548 va_start(formatArguments
, formatString
);
551 print
= TRUE
; // log AND print requested
552 va_copy(formatArguments_print
, formatArguments
);
555 print
= TRUE
; // print requested
556 va_start(formatArguments_print
, formatString
);
560 __SCLog(asl
, msg
, level
, formatString
, formatArguments
);
561 va_end(formatArguments
);
568 __SCPrint((level
> ASL_LEVEL_NOTICE
) ? stderr
: stdout
,
570 formatArguments_print
,
571 (_sc_log
> 0), // trace
572 TRUE
); // add newline
573 va_end(formatArguments_print
);
581 SCPrint(Boolean condition
, FILE *stream
, CFStringRef formatString
, ...)
583 va_list formatArguments
;
589 va_start(formatArguments
, formatString
);
590 __SCPrint(stream
, formatString
, formatArguments
, FALSE
, FALSE
);
591 va_end(formatArguments
);
598 SCTrace(Boolean condition
, FILE *stream
, CFStringRef formatString
, ...)
600 va_list formatArguments
;
606 va_start(formatArguments
, formatString
);
607 __SCPrint(stream
, formatString
, formatArguments
, TRUE
, FALSE
);
608 va_end(formatArguments
);
615 #pragma mark ASL Functions
618 #if ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
621 extern kern_return_t
_asl_server_query(mach_port_t server
,
623 mach_msg_type_number_t requestCnt
,
628 mach_msg_type_number_t
*replyCnt
,
631 security_token_t
*token
);
633 #define ASL_SERVICE_NAME "com.apple.system.logger"
637 _asl_control_query(aslmsg a
)
639 asl_search_result_t
*out
;
640 char *qstr
, *str
, *res
;
641 uint32_t len
, reslen
, status
;
643 kern_return_t kstatus
;
645 mach_port_t server_port
;
646 security_token_t sec
;
648 bootstrap_look_up(bootstrap_port
, ASL_SERVICE_NAME
, &server_port
);
649 if (server_port
== MACH_PORT_NULL
) return NULL
;
652 qstr
= asl_msg_to_string((asl_msg_t
*)a
, &len
);
657 asprintf(&str
, "1\nQ [= ASLOption control]\n");
662 asprintf(&str
, "1\n%s [= ASLOption control]\n", qstr
);
667 if (str
== NULL
) return NULL
;
677 status
= ASL_STATUS_OK
;
679 kstatus
= vm_allocate(mach_task_self(), (vm_address_t
*)&vmstr
, len
, TRUE
);
680 if (kstatus
!= KERN_SUCCESS
) return NULL
;
682 memmove(vmstr
, str
, len
);
686 kstatus
= _asl_server_query(server_port
, vmstr
, len
, qmin
, 1, 0, (caddr_t
*)&res
, &reslen
, &cmax
, (int *)&status
, &sec
);
687 if (kstatus
!= KERN_SUCCESS
) return NULL
;
689 if (res
== NULL
) return NULL
;
691 out
= asl_list_from_string(res
);
692 vm_deallocate(mach_task_self(), (vm_address_t
)res
, reslen
);
698 static CFTypeID __kSCLoggerTypeID
= _kCFRuntimeNotATypeID
;
701 kModuleStatusEnabled
,
702 kModuleStatusDisabled
,
703 kModuleStatusDoesNotExist
708 CFRuntimeBase cf_base
;
710 char * loggerID
; // LoggerID
714 ModuleStatus module_status
;
715 pthread_mutex_t lock
;
719 static void __SCLoggerDeallocate(CFTypeRef cf
);
720 static const CFRuntimeClass __SCLoggerClass
= {
722 "SCLogger", /* className */
725 __SCLoggerDeallocate
, /* deallocate */
728 NULL
, /* copyFormattingDesc */
729 NULL
/* copyDebugDesc */
733 #define DATETIMEBUFFERSIZE 32
736 static pthread_once_t registerLoggerOnce
= PTHREAD_ONCE_INIT
;
737 static pthread_once_t defaultLoggerOnce
= PTHREAD_ONCE_INIT
;
740 kLoggerASLControlEnableModule
,
741 kLoggerASLControlDisableModule
,
742 kLoggerASLControlLogFileCheckpoint
745 static SCLoggerRef defaultLogger
= NULL
;
746 static SCLoggerRef
__SCLoggerCreate(void);
747 static void __SCLoggerDefaultLoggerInit();
748 static SCLoggerRef
SCLoggerGetDefaultLogger();
749 static void SCLoggerSetLoggerID(SCLoggerRef logger
, CFStringRef loggerID
);
750 static void SCLoggerSendMessageToModuleOnly(SCLoggerRef logger
, Boolean isPrivate
);
751 static void SCLoggerSendASLControl(SCLoggerRef logger
, LoggerASLControl control
);
752 static ModuleStatus
GetModuleStatus(const char * loggerID
);
755 __SCLoggerRegisterClass(void)
757 if (__kSCLoggerTypeID
== _kCFRuntimeNotATypeID
) {
758 __kSCLoggerTypeID
= _CFRuntimeRegisterClass(&__SCLoggerClass
);
764 __SCLoggerAllocate(CFAllocatorRef allocator
)
769 pthread_once(®isterLoggerOnce
, __SCLoggerRegisterClass
);
771 size
= sizeof(*state
) - sizeof(CFRuntimeBase
);
772 state
= (SCLoggerRef
) _CFRuntimeCreateInstance(allocator
,
776 bzero((void*)state
+ sizeof(CFRuntimeBase
), size
);
781 __SCLoggerDeallocate(CFTypeRef cf
)
783 SCLoggerRef logger
= (SCLoggerRef
)cf
;
785 if (logger
!= NULL
) {
786 // Rotate on close behavior
787 if (logger
->module_status
!= kModuleStatusDoesNotExist
) {
788 SCLoggerSendASLControl(logger
,
789 kLoggerASLControlLogFileCheckpoint
);
791 if (logger
->loggerID
!= NULL
) {
792 CFAllocatorDeallocate(NULL
, logger
->loggerID
);
793 logger
->loggerID
= NULL
;
795 if (logger
->aslm
!= NULL
) {
796 asl_free(logger
->aslm
);
799 if (logger
->aslc
!= NULL
) {
800 asl_close(logger
->aslc
);
807 __SCLoggerCreate(void)
809 SCLoggerRef tempLogger
= NULL
;
811 tempLogger
= __SCLoggerAllocate(kCFAllocatorDefault
);
812 tempLogger
->loggerID
= NULL
;
813 tempLogger
->flags
= kSCLoggerFlagsDefault
;
814 tempLogger
->aslc
= asl_open(NULL
, NULL
, ASL_OPT_NO_DELAY
);
815 tempLogger
->aslm
= asl_new(ASL_TYPE_MSG
);
816 pthread_mutex_init(&(tempLogger
->lock
), NULL
);
817 tempLogger
->module_status
= kModuleStatusDoesNotExist
;
823 SCLoggerGetFlags(SCLoggerRef logger
)
825 return logger
->flags
;
829 SCLoggerSetFlags(SCLoggerRef logger
, SCLoggerFlags flags
)
831 if (logger
== defaultLogger
) {
834 pthread_mutex_lock(&(logger
->lock
));
835 if (flags
!= kSCLoggerFlagsNone
) {
836 logger
->module_status
= GetModuleStatus(logger
->loggerID
);
837 if (logger
->module_status
== kModuleStatusDoesNotExist
) {
840 if ((flags
& kSCLoggerFlagsFile
) != 0) {
841 if ((logger
->flags
& kSCLoggerFlagsFile
) == 0) {
842 // Enable the module if disabled
843 if (logger
->module_status
== kModuleStatusDisabled
) {
844 SCLoggerSendASLControl(logger
, kLoggerASLControlEnableModule
);
846 // Setting ASL Filter level to debug
847 asl_set_filter(logger
->aslc
, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG
));
848 if (logger
->loggerID
!= NULL
) {
849 asl_set(logger
->aslm
, kLoggerID
,
854 else if ((logger
->flags
& kSCLoggerFlagsFile
) != 0) {
855 asl_unset(logger
->aslm
, kLoggerID
);
856 asl_set_filter(logger
->aslc
, ASL_FILTER_MASK_UPTO(ASL_LEVEL_NOTICE
));
857 SCLoggerSendMessageToModuleOnly(logger
, false);
859 if ((flags
& kSCLoggerFlagsDefault
) != 0) {
860 if ((logger
->flags
& kSCLoggerFlagsDefault
) == 0) {
861 SCLoggerSendMessageToModuleOnly(logger
, false);
864 else if ((logger
->flags
& kSCLoggerFlagsDefault
) != 0) {
865 SCLoggerSendMessageToModuleOnly(logger
, true);
868 logger
->flags
= flags
;
870 pthread_mutex_unlock(&(logger
->lock
));
875 SCLoggerSetLoggerID(SCLoggerRef logger
, CFStringRef loggerID
)
878 = _SC_cfstring_to_cstring(loggerID
, NULL
, 0,
879 kCFStringEncodingUTF8
);
880 // Enable the module if disabled
881 logger
->module_status
= GetModuleStatus(logger
->loggerID
);
882 if (logger
->module_status
== kModuleStatusDisabled
) {
883 SCLoggerSendASLControl(logger
, kLoggerASLControlEnableModule
);
888 GetModuleStatus(const char * loggerID
)
890 aslresponse response
= NULL
;
891 aslmsg responseMessage
= NULL
;
892 ModuleStatus moduleStatus
= kModuleStatusDoesNotExist
;
893 const char* value
= NULL
;
895 if (loggerID
!= NULL
) {
896 response
= _asl_control_query(NULL
);
897 if (response
== NULL
) {
900 responseMessage
= aslresponse_next(response
);
901 if (responseMessage
== NULL
) {
904 value
= asl_get(responseMessage
, loggerID
);
906 moduleStatus
= kModuleStatusDoesNotExist
;
910 if (strcmp(value
, "enabled") == 0) {
911 moduleStatus
= kModuleStatusEnabled
;
914 moduleStatus
= kModuleStatusDisabled
;
918 if (response
!= NULL
) {
919 aslresponse_free(response
);
926 SCLoggerSendMessageToModuleOnly(SCLoggerRef logger
, Boolean isPrivate
)
929 asl_set(logger
->aslm
, kASLModule
, logger
->loggerID
);
932 if (asl_get(logger
->aslm
, kASLModule
) != NULL
) {
933 asl_unset(logger
->aslm
, kASLModule
);
939 SCLoggerSendASLControl(SCLoggerRef logger
, LoggerASLControl control
)
941 SCLoggerRef defLogger
= SCLoggerGetDefaultLogger();
942 pthread_mutex_lock(&(defLogger
->lock
));
944 // this next line turns the asl_log()'s that follow into control messages
945 asl_set(defLogger
->aslm
, kASLOption
, "control");
948 case kLoggerASLControlEnableModule
:
949 asl_log(defLogger
->aslc
, defLogger
->aslm
,
950 ASL_LEVEL_NOTICE
, "@ %s enable 1",
953 case kLoggerASLControlDisableModule
:
954 asl_log(defLogger
->aslc
, defLogger
->aslm
,
955 ASL_LEVEL_NOTICE
, "@ %s enable 0",
958 case kLoggerASLControlLogFileCheckpoint
:
959 asl_log(defLogger
->aslc
, defLogger
->aslm
,
960 ASL_LEVEL_NOTICE
, "@ %s checkpoint",
967 // turn off control mode
968 asl_unset(defLogger
->aslm
, kASLOption
);
969 pthread_mutex_unlock(&defLogger
->lock
);
974 SCLoggerCreate(CFStringRef loggerID
)
976 SCLoggerRef logger
= NULL
;
978 logger
= __SCLoggerCreate();
979 if (loggerID
!= NULL
) {
980 SCLoggerSetLoggerID(logger
, loggerID
);
982 SCLoggerSetFlags(logger
, kSCLoggerFlagsDefault
);
987 __SCLoggerDefaultLoggerInit()
989 if (defaultLogger
== NULL
) {
990 defaultLogger
= __SCLoggerCreate();
991 defaultLogger
->flags
= kSCLoggerFlagsDefault
;
996 SCLoggerGetDefaultLogger()
998 pthread_once(&defaultLoggerOnce
, __SCLoggerDefaultLoggerInit
);
999 return defaultLogger
;
1003 SCLoggerVLog(SCLoggerRef logger
, int loglevel
, CFStringRef formatString
,
1010 || logger
->module_status
== kModuleStatusDoesNotExist
) {
1011 logger
= SCLoggerGetDefaultLogger();
1013 pthread_mutex_lock(&(logger
->lock
));
1014 if (logger
->flags
== kSCLoggerFlagsNone
) {
1015 pthread_mutex_unlock(&(logger
->lock
));
1018 aslc
= logger
->aslc
;
1019 aslm
= logger
->aslm
;
1020 __SCLog(aslc
, aslm
, loglevel
, formatString
, args
);
1021 pthread_mutex_unlock(&(logger
->lock
));
1026 SCLoggerLog(SCLoggerRef logger
, int loglevel
, CFStringRef formatString
, ...)
1030 va_start(args
, formatString
);
1031 SCLoggerVLog(logger
, loglevel
, formatString
, args
);
1037 #endif // ((__MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) || (__IPHONE_OS_VERSION_MIN_REQUIRED >= 60000))
1041 #pragma mark SC error handling / logging
1044 const CFStringRef kCFErrorDomainSystemConfiguration
= CFSTR("com.apple.SystemConfiguration");
1047 static const struct sc_errmsg
{
1051 { kSCStatusAccessError
, "Permission denied" },
1052 { kSCStatusConnectionIgnore
, "Network connection information not available at this time" },
1053 { kSCStatusConnectionNoService
, "Network service for connection not available" },
1054 { kSCStatusFailed
, "Failed!" },
1055 { kSCStatusInvalidArgument
, "Invalid argument" },
1056 { kSCStatusKeyExists
, "Key already defined" },
1057 { kSCStatusLocked
, "Lock already held" },
1058 { kSCStatusMaxLink
, "Maximum link count exceeded" },
1059 { kSCStatusNeedLock
, "Lock required for this operation" },
1060 { kSCStatusNoStoreServer
, "Configuration daemon not (no longer) available" },
1061 { kSCStatusNoStoreSession
, "Configuration daemon session not active" },
1062 { kSCStatusNoConfigFile
, "Configuration file not found" },
1063 { kSCStatusNoKey
, "No such key" },
1064 { kSCStatusNoLink
, "No such link" },
1065 { kSCStatusNoPrefsSession
, "Preference session not active" },
1066 { kSCStatusNotifierActive
, "Notifier is currently active" },
1067 { kSCStatusOK
, "Success!" },
1068 { kSCStatusPrefsBusy
, "Preferences update currently in progress" },
1069 { kSCStatusReachabilityUnknown
, "Network reachability cannot be determined" },
1070 { kSCStatusStale
, "Write attempted on stale version of object" },
1072 #define nSC_ERRMSGS (sizeof(sc_errmsgs)/sizeof(struct sc_errmsg))
1075 _SCErrorSet(int error
)
1077 __SCThreadSpecificDataRef tsd
;
1079 tsd
= __SCGetThreadSpecificData();
1080 tsd
->_sc_error
= error
;
1086 SCCopyLastError(void)
1092 __SCThreadSpecificDataRef tsd
;
1093 CFMutableDictionaryRef userInfo
= NULL
;
1095 tsd
= __SCGetThreadSpecificData();
1096 code
=tsd
->_sc_error
;
1098 for (i
= 0; i
< (int)nSC_ERRMSGS
; i
++) {
1099 if (sc_errmsgs
[i
].status
== code
) {
1102 domain
= kCFErrorDomainSystemConfiguration
;
1103 userInfo
= CFDictionaryCreateMutable(NULL
,
1105 &kCFCopyStringDictionaryKeyCallBacks
,
1106 &kCFTypeDictionaryValueCallBacks
);
1107 str
= CFStringCreateWithCString(NULL
,
1108 sc_errmsgs
[i
].message
,
1109 kCFStringEncodingASCII
);
1110 CFDictionarySetValue(userInfo
, kCFErrorDescriptionKey
, str
);
1116 if ((code
> 0) && (code
<= ELAST
)) {
1117 domain
= kCFErrorDomainPOSIX
;
1121 domain
= kCFErrorDomainMach
;
1125 error
= CFErrorCreate(NULL
, domain
, code
, userInfo
);
1126 if (userInfo
!= NULL
) CFRelease(userInfo
);
1134 __SCThreadSpecificDataRef tsd
;
1136 tsd
= __SCGetThreadSpecificData();
1137 return tsd
->_sc_error
;
1142 SCErrorString(int status
)
1146 for (i
= 0; i
< (int)nSC_ERRMSGS
; i
++) {
1147 if (sc_errmsgs
[i
].status
== status
) {
1148 return sc_errmsgs
[i
].message
;
1152 if ((status
> 0) && (status
<= ELAST
)) {
1153 return strerror(status
);
1156 if ((status
>= BOOTSTRAP_SUCCESS
) && (status
<= BOOTSTRAP_NO_MEMORY
)) {
1157 return bootstrap_strerror(status
);
1160 return mach_error_string(status
);