2 * Copyright (c) 2000-2008, 2010-2016 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>
41 #include <os/log_private.h>
43 #include "SCDynamicStoreInternal.h"
45 #include "config.h" /* MiG generated file */
48 #define INSTALL_FACILITY "install"
49 #define INSTALL_ENVIRONMENT "__OSINSTALL_ENVIRONMENT"
52 extern asl_object_t
_asl_server_control_query(void);
54 /* framework variables */
55 int _sc_debug
= FALSE
; /* non-zero if debugging enabled */
56 int _sc_verbose
= FALSE
; /* non-zero if verbose logging enabled */
57 int _sc_log
= TRUE
; /* 0 if SC messages should be written to stdout/stderr,
58 1 if SC messages should be logged w/asl(3),
59 2 if SC messages should be written to stdout/stderr AND logged */
63 #pragma mark Thread specific data
66 static pthread_once_t tsKeyInitialized
= PTHREAD_ONCE_INIT
;
67 static pthread_key_t tsDataKey
;
71 __SCThreadSpecificDataFinalize(void *arg
)
73 __SCThreadSpecificDataRef tsd
= (__SCThreadSpecificDataRef
)arg
;
76 if (tsd
->_asl
!= NULL
) asl_release(tsd
->_asl
);
77 if (tsd
->_sc_store
!= NULL
) CFRelease(tsd
->_sc_store
);
78 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, tsd
);
85 __SCThreadSpecificKeyInitialize()
87 pthread_key_create(&tsDataKey
, __SCThreadSpecificDataFinalize
);
93 __SCThreadSpecificDataRef
94 __SCGetThreadSpecificData()
96 __SCThreadSpecificDataRef tsd
;
97 pthread_once(&tsKeyInitialized
, __SCThreadSpecificKeyInitialize
);
99 tsd
= pthread_getspecific(tsDataKey
);
101 tsd
= CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(__SCThreadSpecificData
), 0);
103 tsd
->_sc_error
= kSCStatusOK
;
104 tsd
->_sc_store
= NULL
;
105 pthread_setspecific(tsDataKey
, tsd
);
116 #define kASLModule "ASLModule"
117 #define kASLOption "ASLOption"
118 #define kLoggerID "LoggerID"
120 #define ENABLE_SC_FORMATTING
121 #ifdef ENABLE_SC_FORMATTING
122 // from <CoreFoundation/ForFoundationOnly.h>
123 extern CFStringRef
_CFStringCreateWithFormatAndArgumentsAux(CFAllocatorRef alloc
, CFStringRef (*copyDescFunc
)(CFTypeRef
, CFDictionaryRef
), CFDictionaryRef formatOptions
, CFStringRef format
, va_list arguments
);
124 #endif /* ENABLE_SC_FORMATTING */
128 _SCCopyDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
)
130 #ifdef ENABLE_SC_FORMATTING
131 CFMutableDictionaryRef nFormatOptions
;
134 CFTypeID type
= CFGetTypeID(cf
);
136 if (!formatOptions
||
137 !CFDictionaryGetValueIfPresent(formatOptions
, CFSTR("PREFIX1"), (const void **)&prefix1
)) {
141 if (type
== CFStringGetTypeID()) {
142 return CFStringCreateWithFormat(NULL
,
149 if (type
== CFBooleanGetTypeID()) {
150 return CFStringCreateWithFormat(NULL
,
154 CFBooleanGetValue(cf
) ? "TRUE" : "FALSE");
157 if (type
== CFDataGetTypeID()) {
161 CFMutableStringRef str
;
163 str
= CFStringCreateMutable(NULL
, 0);
164 CFStringAppendFormat(str
, formatOptions
, CFSTR("%@<data> 0x"), prefix1
);
166 data
= CFDataGetBytePtr(cf
);
167 dataLen
= CFDataGetLength(cf
);
168 for (i
= 0; i
< dataLen
; i
++) {
169 CFStringAppendFormat(str
, NULL
, CFSTR("%02x"), data
[i
]);
175 if (type
== CFNumberGetTypeID()) {
176 return CFStringCreateWithFormat(NULL
,
183 if (type
== CFDateGetTypeID()) {
184 CFCalendarRef calendar
;
187 int MM
, DD
, YYYY
, hh
, mm
, ss
;
189 calendar
= CFCalendarCreateWithIdentifier(NULL
, kCFGregorianCalendar
);
190 tz
= CFTimeZoneCopySystem();
191 CFCalendarSetTimeZone(calendar
, tz
);
193 CFCalendarDecomposeAbsoluteTime(calendar
,
194 CFDateGetAbsoluteTime(cf
),
196 &MM
, &DD
, &YYYY
, &hh
, &mm
, &ss
);
199 str
= CFStringCreateWithFormat(NULL
,
201 CFSTR("%@%02d/%02d/%04d %02d:%02d:%02d"),
203 MM
, DD
, YYYY
, hh
, mm
, ss
);
207 if ((formatOptions
== NULL
) ||
208 !CFDictionaryGetValueIfPresent(formatOptions
, CFSTR("PREFIX2"), (const void **)&prefix2
)) {
212 if (formatOptions
!= NULL
) {
213 nFormatOptions
= CFDictionaryCreateMutableCopy(NULL
, 0, formatOptions
);
215 nFormatOptions
= CFDictionaryCreateMutable(NULL
,
217 &kCFTypeDictionaryKeyCallBacks
,
218 &kCFTypeDictionaryValueCallBacks
);
220 assert(nFormatOptions
!= NULL
);
224 if (type
== CFArrayGetTypeID()) {
225 const void * elements_q
[N_QUICK
];
226 const void ** elements
= elements_q
;
229 CFMutableStringRef str
;
231 str
= CFStringCreateMutable(NULL
, 0);
232 CFStringAppendFormat(str
, formatOptions
, CFSTR("%@<array> {"), prefix1
);
234 nElements
= CFArrayGetCount(cf
);
236 if (nElements
> (CFIndex
)(sizeof(elements_q
)/sizeof(CFTypeRef
)))
237 elements
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
238 CFArrayGetValues(cf
, CFRangeMake(0, nElements
), elements
);
239 for (i
= 0; i
< nElements
; i
++) {
240 CFMutableStringRef nPrefix1
;
241 CFMutableStringRef nPrefix2
;
245 nStr
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%ld"), i
);
247 nPrefix1
= CFStringCreateMutable(NULL
, 0);
248 CFStringAppendFormat(nPrefix1
,
253 nPrefix2
= CFStringCreateMutable(NULL
, 0);
254 CFStringAppendFormat(nPrefix2
,
259 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX1"), nPrefix1
);
260 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX2"), nPrefix2
);
265 vStr
= _SCCopyDescription((CFTypeRef
)elements
[i
], nFormatOptions
);
266 CFStringAppendFormat(str
,
272 if (elements
!= elements_q
) CFAllocatorDeallocate(NULL
, elements
);
274 CFStringAppendFormat(str
, formatOptions
, CFSTR("\n%@}"), prefix2
);
276 CFRelease(nFormatOptions
);
280 if (type
== CFDictionaryGetTypeID()) {
281 const void * keys_q
[N_QUICK
];
282 const void ** keys
= keys_q
;
285 CFMutableStringRef nPrefix1
;
286 CFMutableStringRef nPrefix2
;
287 CFMutableStringRef str
;
289 str
= CFStringCreateMutable(NULL
, 0);
290 CFStringAppendFormat(str
, formatOptions
, CFSTR("%@<dictionary> {"), prefix1
);
292 nElements
= CFDictionaryGetCount(cf
);
294 CFComparatorFunction compFunc
= NULL
;
295 CFMutableArrayRef sortedKeys
;
297 if (nElements
> (CFIndex
)(sizeof(keys_q
) / sizeof(CFTypeRef
))) {
298 keys
= CFAllocatorAllocate(NULL
, nElements
* sizeof(CFTypeRef
), 0);
300 CFDictionaryGetKeysAndValues(cf
, keys
, NULL
);
302 sortedKeys
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
303 for (i
= 0; i
< nElements
; i
++) {
304 CFArrayAppendValue(sortedKeys
, (CFStringRef
)keys
[i
]);
307 if (isA_CFString(keys
[0])) {
308 compFunc
= (CFComparatorFunction
)CFStringCompare
;
310 else if (isA_CFNumber(keys
[0])) {
311 compFunc
= (CFComparatorFunction
)CFNumberCompare
;
313 else if (isA_CFDate(keys
[0])) {
314 compFunc
= (CFComparatorFunction
)CFDateCompare
;
317 if (compFunc
!= NULL
) {
318 CFArraySortValues(sortedKeys
,
319 CFRangeMake(0, nElements
),
324 for (i
= 0; i
< nElements
; i
++) {
330 key
= CFArrayGetValueAtIndex(sortedKeys
, i
);
331 kStr
= _SCCopyDescription((CFTypeRef
)key
, NULL
);
333 nPrefix1
= CFStringCreateMutable(NULL
, 0);
334 CFStringAppendFormat(nPrefix1
,
339 nPrefix2
= CFStringCreateMutable(NULL
, 0);
340 CFStringAppendFormat(nPrefix2
,
345 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX1"), nPrefix1
);
346 CFDictionarySetValue(nFormatOptions
, CFSTR("PREFIX2"), nPrefix2
);
351 val
= CFDictionaryGetValue(cf
, key
);
352 vStr
= _SCCopyDescription((CFTypeRef
)val
, nFormatOptions
);
353 CFStringAppendFormat(str
,
360 CFRelease(sortedKeys
);
362 if (keys
!= keys_q
) {
363 CFAllocatorDeallocate(NULL
, keys
);
366 CFStringAppendFormat(str
, formatOptions
, CFSTR("\n%@}"), prefix2
);
368 CFRelease(nFormatOptions
);
372 CFRelease(nFormatOptions
);
373 #endif /* ENABLE_SC_FORMATTING */
375 return CFStringCreateWithFormat(NULL
,
383 static pthread_mutex_t lock
= PTHREAD_MUTEX_INITIALIZER
;
386 _SC_isInstallEnvironment() {
387 static dispatch_once_t once
;
388 static Boolean is_install
;
390 dispatch_once(&once
, ^{
391 is_install
= (getenv(INSTALL_ENVIRONMENT
) != NULL
);
401 static os_log_t log
= NULL
;
404 log
= os_log_create("com.apple.SystemConfiguration", "");
412 _SC_syslog_os_log_mapping(int level
)
422 return OS_LOG_TYPE_ERROR
;
427 return OS_LOG_TYPE_DEFAULT
;
430 return OS_LOG_TYPE_INFO
;
433 return OS_LOG_TYPE_DEBUG
;
436 return OS_LOG_TYPE_DEFAULT
;
440 __SCLog(asl_object_t asl
, asl_object_t msg
, int level
, void *ret_addr
, CFStringRef formatString
, va_list formatArguments
)
446 if ((asl
== NULL
) && (level
>= 0)) {
447 const char *__format
;
449 __format
= CFStringGetCStringPtr(formatString
, kCFStringEncodingUTF8
);
450 if (__format
!= NULL
) {
451 os_log_type_t __type
;
453 __type
= _SC_syslog_os_log_mapping(level
);
454 os_log_with_args(_SC_LOG_DEFAULT(),
464 __SCThreadSpecificDataRef tsd
;
466 tsd
= __SCGetThreadSpecificData();
467 if (tsd
->_asl
== NULL
) {
468 tsd
->_asl
= asl_open(NULL
, (_SC_isInstallEnvironment() ? INSTALL_FACILITY
: NULL
), 0);
469 asl_set_filter(tsd
->_asl
, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG
));
474 #ifdef ENABLE_SC_FORMATTING
475 str
= _CFStringCreateWithFormatAndArgumentsAux(NULL
,
480 #else /* ENABLE_SC_FORMATTING */
481 str
= CFStringCreateWithFormatAndArguments (NULL
,
485 #endif /* !ENABLE_SC_FORMATTING */
488 lines
= CFStringCreateArrayBySeparatingStrings(NULL
, str
, CFSTR("\n"));
491 CFIndex n
= CFArrayGetCount(lines
);
493 for (i
= 0; i
< n
; i
++) {
494 line
=_SC_cfstring_to_cstring_ext(CFArrayGetValueAtIndex(lines
, i
),
497 kCFStringEncodingUTF8
,
500 asl_log(asl
, msg
, level
, "%s", line
);
501 CFAllocatorDeallocate(NULL
, line
);
506 line
=_SC_cfstring_to_cstring_ext(str
,
509 kCFStringEncodingUTF8
,
512 asl_log(asl
, msg
, ~level
, "%s", line
);
513 CFAllocatorDeallocate(NULL
, line
);
521 __SCPrint(FILE *stream
, CFStringRef formatString
, va_list formatArguments
, Boolean trace
, Boolean addNL
)
527 #ifdef ENABLE_SC_FORMATTING
528 str
= _CFStringCreateWithFormatAndArgumentsAux(NULL
,
533 #else /* ENABLE_SC_FORMATTING */
534 str
= CFStringCreateWithFormatAndArguments (NULL
,
538 #endif /* !ENABLE_SC_FORMATTING */
540 line
=_SC_cfstring_to_cstring_ext(str
,
543 kCFStringEncodingUTF8
,
551 pthread_mutex_lock(&lock
);
554 struct timeval tv_now
;
556 (void)gettimeofday(&tv_now
, NULL
);
557 (void)localtime_r(&tv_now
.tv_sec
, &tm_now
);
558 (void)fprintf(stream
, "%2d:%02d:%02d.%03d ",
559 tm_now
.tm_hour
, tm_now
.tm_min
, tm_now
.tm_sec
, tv_now
.tv_usec
/ 1000);
561 (void)fwrite((const void *)line
, usedBufLen
, 1, stream
);
563 (void)fputc('\n', stream
);
566 pthread_mutex_unlock(&lock
);
567 CFAllocatorDeallocate(NULL
, line
);
574 SCLog(Boolean condition
, int level
, CFStringRef formatString
, ...)
576 va_list formatArguments
;
577 va_list formatArguments_print
;
579 Boolean print
= FALSE
;
586 * Note: The following are the expected values for _sc_log
588 * 0 if SC messages should be written to stdout/stderr
589 * 1 if SC messages should be logged w/asl(3)
590 * 2 if SC messages should be written to stdout/stderr AND logged
594 log
= TRUE
; // log requested
595 va_start(formatArguments
, formatString
);
598 print
= TRUE
; // log AND print requested
599 va_copy(formatArguments_print
, formatArguments
);
602 print
= TRUE
; // print requested
603 va_start(formatArguments_print
, formatString
);
607 __SCLog(NULL
, NULL
, level
, __builtin_return_address(0), formatString
, formatArguments
);
608 va_end(formatArguments
);
612 __SCPrint((LOG_PRI(level
) > LOG_NOTICE
) ? stderr
: stdout
,
614 formatArguments_print
,
615 (_sc_log
> 0), // trace
616 TRUE
); // add newline
617 va_end(formatArguments_print
);
625 __SC_Log(int level
, CFStringRef format_CF
, os_log_t log
, os_log_type_t type
, const char *format
, ...)
627 Boolean do_log
= FALSE
;
628 Boolean do_print
= FALSE
;
633 * Note: The following are the expected values for _sc_log
635 * 0 if SC messages should be written to stdout/stderr
636 * 1 if SC messages should be logged w/asl(3)
637 * 2 if SC messages should be written to stdout/stderr AND logged
641 log
= TRUE
; // log requested
642 va_start(args_log
, format
);
645 do_print
= TRUE
; // log AND print requested
646 va_copy(args_print
, args_log
);
649 do_print
= TRUE
; // print requested
650 va_start(args_print
, format
);
655 os_log_with_args(log
,
659 __builtin_return_address(0));
661 // if we need to break apart a multi-line message
665 __builtin_return_address(0),
676 (_sc_log
> 0), // trace
677 TRUE
); // add newline
687 SCLOG(asl_object_t asl
, asl_object_t msg
, int level
, CFStringRef formatString
, ...)
689 va_list formatArguments
;
690 va_list formatArguments_print
;
692 Boolean print
= FALSE
;
695 * Note: The following are the expected values for _sc_log
697 * 0 if SC messages should be written to stdout/stderr
698 * 1 if SC messages should be logged w/asl(3)
699 * 2 if SC messages should be written to stdout/stderr AND logged
703 log
= TRUE
; // log requested
704 va_start(formatArguments
, formatString
);
707 print
= TRUE
; // log AND print requested
708 va_copy(formatArguments_print
, formatArguments
);
711 print
= TRUE
; // print requested
712 va_start(formatArguments_print
, formatString
);
716 __SCLog(asl
, msg
, level
, __builtin_return_address(0), formatString
, formatArguments
);
717 va_end(formatArguments
);
724 __SCPrint((level
> ASL_LEVEL_NOTICE
) ? stderr
: stdout
,
726 formatArguments_print
,
727 (_sc_log
> 0), // trace
728 TRUE
); // add newline
729 va_end(formatArguments_print
);
737 SCPrint(Boolean condition
, FILE *stream
, CFStringRef formatString
, ...)
739 va_list formatArguments
;
745 va_start(formatArguments
, formatString
);
746 __SCPrint(stream
, formatString
, formatArguments
, FALSE
, FALSE
);
747 va_end(formatArguments
);
754 #pragma mark ASL Functions
757 static CFTypeID __kSCLoggerTypeID
= _kCFRuntimeNotATypeID
;
760 kModuleStatusEnabled
,
761 kModuleStatusDisabled
,
762 kModuleStatusDoesNotExist
767 CFRuntimeBase cf_base
;
769 char * loggerID
; // LoggerID
773 ModuleStatus module_status
;
774 pthread_mutex_t lock
;
778 static void __SCLoggerDeallocate(CFTypeRef cf
);
779 static const CFRuntimeClass __SCLoggerClass
= {
781 "SCLogger", /* className */
784 __SCLoggerDeallocate
, /* deallocate */
787 NULL
, /* copyFormattingDesc */
788 NULL
/* copyDebugDesc */
792 #define DATETIMEBUFFERSIZE 32
795 static pthread_once_t registerLoggerOnce
= PTHREAD_ONCE_INIT
;
796 static pthread_once_t defaultLoggerOnce
= PTHREAD_ONCE_INIT
;
799 kLoggerASLControlEnableModule
,
800 kLoggerASLControlDisableModule
,
801 kLoggerASLControlLogFileCheckpoint
804 static SCLoggerRef defaultLogger
= NULL
;
805 static SCLoggerRef
__SCLoggerCreate(void);
806 static void __SCLoggerDefaultLoggerInit();
807 static SCLoggerRef
SCLoggerGetDefaultLogger();
808 static void SCLoggerSetLoggerID(SCLoggerRef logger
, CFStringRef loggerID
);
809 static void SCLoggerSendMessageToModuleOnly(SCLoggerRef logger
, Boolean isPrivate
);
810 static void SCLoggerSendASLControl(SCLoggerRef logger
, LoggerASLControl control
);
811 static ModuleStatus
GetModuleStatus(const char * loggerID
);
814 __SCLoggerRegisterClass(void)
816 if (__kSCLoggerTypeID
== _kCFRuntimeNotATypeID
) {
817 __kSCLoggerTypeID
= _CFRuntimeRegisterClass(&__SCLoggerClass
);
823 __SCLoggerAllocate(CFAllocatorRef allocator
)
828 pthread_once(®isterLoggerOnce
, __SCLoggerRegisterClass
);
830 size
= sizeof(*state
) - sizeof(CFRuntimeBase
);
831 state
= (SCLoggerRef
) _CFRuntimeCreateInstance(allocator
,
839 __SCLoggerDeallocate(CFTypeRef cf
)
841 SCLoggerRef logger
= (SCLoggerRef
)cf
;
843 if (logger
!= NULL
) {
844 // Rotate on close behavior
845 if (logger
->module_status
!= kModuleStatusDoesNotExist
) {
846 SCLoggerSendASLControl(logger
,
847 kLoggerASLControlLogFileCheckpoint
);
849 if (logger
->loggerID
!= NULL
) {
850 CFAllocatorDeallocate(NULL
, logger
->loggerID
);
851 logger
->loggerID
= NULL
;
853 if (logger
->aslm
!= NULL
) {
854 asl_release(logger
->aslm
);
857 if (logger
->aslc
!= NULL
) {
858 asl_release(logger
->aslc
);
865 __SCLoggerCreate(void)
867 SCLoggerRef tempLogger
= NULL
;
869 tempLogger
= __SCLoggerAllocate(kCFAllocatorDefault
);
870 tempLogger
->loggerID
= NULL
;
871 tempLogger
->flags
= kSCLoggerFlagsDefault
;
872 tempLogger
->aslc
= asl_open(NULL
, (_SC_isInstallEnvironment() ? INSTALL_FACILITY
: NULL
), ASL_OPT_NO_DELAY
);
873 tempLogger
->aslm
= asl_new(ASL_TYPE_MSG
);
874 pthread_mutex_init(&(tempLogger
->lock
), NULL
);
875 tempLogger
->module_status
= kModuleStatusDoesNotExist
;
881 SCLoggerGetFlags(SCLoggerRef logger
)
883 return logger
->flags
;
887 SCLoggerSetFlags(SCLoggerRef logger
, SCLoggerFlags flags
)
889 if (logger
== defaultLogger
) {
892 pthread_mutex_lock(&(logger
->lock
));
893 if (flags
!= kSCLoggerFlagsNone
) {
894 logger
->module_status
= GetModuleStatus(logger
->loggerID
);
895 if (logger
->module_status
== kModuleStatusDoesNotExist
) {
898 if ((flags
& kSCLoggerFlagsFile
) != 0) {
899 if ((logger
->flags
& kSCLoggerFlagsFile
) == 0) {
900 // Enable the module if disabled
901 if (logger
->module_status
== kModuleStatusDisabled
) {
902 SCLoggerSendASLControl(logger
, kLoggerASLControlEnableModule
);
904 // Setting ASL Filter level to debug
905 asl_set_filter(logger
->aslc
, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG
));
906 if (logger
->loggerID
!= NULL
) {
907 asl_set(logger
->aslm
, kLoggerID
,
912 else if ((logger
->flags
& kSCLoggerFlagsFile
) != 0) {
913 asl_unset(logger
->aslm
, kLoggerID
);
914 asl_set_filter(logger
->aslc
, ASL_FILTER_MASK_UPTO(ASL_LEVEL_NOTICE
));
915 SCLoggerSendMessageToModuleOnly(logger
, false);
917 if ((flags
& kSCLoggerFlagsDefault
) != 0) {
918 if ((logger
->flags
& kSCLoggerFlagsDefault
) == 0) {
919 SCLoggerSendMessageToModuleOnly(logger
, false);
922 else if ((logger
->flags
& kSCLoggerFlagsDefault
) != 0) {
923 SCLoggerSendMessageToModuleOnly(logger
, true);
926 logger
->flags
= flags
;
928 pthread_mutex_unlock(&(logger
->lock
));
933 SCLoggerSetLoggerID(SCLoggerRef logger
, CFStringRef loggerID
)
936 = _SC_cfstring_to_cstring(loggerID
, NULL
, 0,
937 kCFStringEncodingUTF8
);
938 // Enable the module if disabled
939 logger
->module_status
= GetModuleStatus(logger
->loggerID
);
940 if (logger
->module_status
== kModuleStatusDisabled
) {
941 SCLoggerSendASLControl(logger
, kLoggerASLControlEnableModule
);
946 GetModuleStatus(const char * loggerID
)
948 ModuleStatus moduleStatus
= kModuleStatusDoesNotExist
;
949 asl_object_t response
= NULL
;
950 const char* value
= NULL
;
952 if (loggerID
!= NULL
) {
953 response
= _asl_server_control_query();
954 if (response
== NULL
) {
957 value
= asl_get(response
, loggerID
);
959 moduleStatus
= kModuleStatusDoesNotExist
;
963 if (strcmp(value
, "enabled") == 0) {
964 moduleStatus
= kModuleStatusEnabled
;
967 moduleStatus
= kModuleStatusDisabled
;
971 asl_release(response
);
977 SCLoggerSendMessageToModuleOnly(SCLoggerRef logger
, Boolean isPrivate
)
980 asl_set(logger
->aslm
, kASLModule
, logger
->loggerID
);
983 if (asl_get(logger
->aslm
, kASLModule
) != NULL
) {
984 asl_unset(logger
->aslm
, kASLModule
);
990 SCLoggerSendASLControl(SCLoggerRef logger
, LoggerASLControl control
)
992 SCLoggerRef defLogger
= SCLoggerGetDefaultLogger();
993 pthread_mutex_lock(&(defLogger
->lock
));
995 // this next line turns the asl_log()'s that follow into control messages
996 asl_set(defLogger
->aslm
, kASLOption
, "control");
999 case kLoggerASLControlEnableModule
:
1000 asl_log(defLogger
->aslc
, defLogger
->aslm
,
1001 ASL_LEVEL_NOTICE
, "@ %s enable 1",
1004 case kLoggerASLControlDisableModule
:
1005 asl_log(defLogger
->aslc
, defLogger
->aslm
,
1006 ASL_LEVEL_NOTICE
, "@ %s enable 0",
1009 case kLoggerASLControlLogFileCheckpoint
:
1010 asl_log(defLogger
->aslc
, defLogger
->aslm
,
1011 ASL_LEVEL_NOTICE
, "@ %s checkpoint",
1018 // turn off control mode
1019 asl_unset(defLogger
->aslm
, kASLOption
);
1020 pthread_mutex_unlock(&defLogger
->lock
);
1025 SCLoggerCreate(CFStringRef loggerID
)
1027 SCLoggerRef logger
= NULL
;
1029 logger
= __SCLoggerCreate();
1030 if (loggerID
!= NULL
) {
1031 SCLoggerSetLoggerID(logger
, loggerID
);
1033 SCLoggerSetFlags(logger
, kSCLoggerFlagsDefault
);
1038 __SCLoggerDefaultLoggerInit()
1040 if (defaultLogger
== NULL
) {
1041 defaultLogger
= __SCLoggerCreate();
1042 defaultLogger
->flags
= kSCLoggerFlagsDefault
;
1047 SCLoggerGetDefaultLogger()
1049 pthread_once(&defaultLoggerOnce
, __SCLoggerDefaultLoggerInit
);
1050 return defaultLogger
;
1054 SCLoggerVLogInternal(SCLoggerRef logger
, int loglevel
, void *ret_addr
,
1055 CFStringRef formatString
, va_list args
)
1061 || logger
->module_status
== kModuleStatusDoesNotExist
) {
1062 logger
= SCLoggerGetDefaultLogger();
1064 pthread_mutex_lock(&(logger
->lock
));
1065 if (logger
->flags
== kSCLoggerFlagsNone
) {
1066 pthread_mutex_unlock(&(logger
->lock
));
1069 aslc
= logger
->aslc
;
1070 aslm
= logger
->aslm
;
1071 __SCLog(aslc
, aslm
, loglevel
, ret_addr
, formatString
, args
);
1072 pthread_mutex_unlock(&(logger
->lock
));
1077 SCLoggerLog(SCLoggerRef logger
, int loglevel
, CFStringRef formatString
, ...)
1081 va_start(args
, formatString
);
1082 SCLoggerVLogInternal(logger
, loglevel
, __builtin_return_address(0), formatString
, args
);
1089 SCLoggerVLog(SCLoggerRef logger
, int loglevel
, CFStringRef formatString
, va_list args
)
1091 SCLoggerVLogInternal(logger
, loglevel
, __builtin_return_address(0), formatString
, args
);
1097 #pragma mark SC error handling / logging
1100 const CFStringRef kCFErrorDomainSystemConfiguration
= CFSTR("com.apple.SystemConfiguration");
1103 static const struct sc_errmsg
{
1107 { kSCStatusAccessError
, "Permission denied" },
1108 { kSCStatusConnectionIgnore
, "Network connection information not available at this time" },
1109 { kSCStatusConnectionNoService
, "Network service for connection not available" },
1110 { kSCStatusFailed
, "Failed!" },
1111 { kSCStatusInvalidArgument
, "Invalid argument" },
1112 { kSCStatusKeyExists
, "Key already defined" },
1113 { kSCStatusLocked
, "Lock already held" },
1114 { kSCStatusMaxLink
, "Maximum link count exceeded" },
1115 { kSCStatusNeedLock
, "Lock required for this operation" },
1116 { kSCStatusNoStoreServer
, "Configuration daemon not (no longer) available" },
1117 { kSCStatusNoStoreSession
, "Configuration daemon session not active" },
1118 { kSCStatusNoConfigFile
, "Configuration file not found" },
1119 { kSCStatusNoKey
, "No such key" },
1120 { kSCStatusNoLink
, "No such link" },
1121 { kSCStatusNoPrefsSession
, "Preference session not active" },
1122 { kSCStatusNotifierActive
, "Notifier is currently active" },
1123 { kSCStatusOK
, "Success!" },
1124 { kSCStatusPrefsBusy
, "Preferences update currently in progress" },
1125 { kSCStatusReachabilityUnknown
, "Network reachability cannot be determined" },
1126 { kSCStatusStale
, "Write attempted on stale version of object" },
1128 #define nSC_ERRMSGS (sizeof(sc_errmsgs)/sizeof(struct sc_errmsg))
1131 _SCErrorSet(int error
)
1133 __SCThreadSpecificDataRef tsd
;
1135 tsd
= __SCGetThreadSpecificData();
1136 tsd
->_sc_error
= error
;
1142 SCCopyLastError(void)
1148 __SCThreadSpecificDataRef tsd
;
1149 CFMutableDictionaryRef userInfo
= NULL
;
1151 tsd
= __SCGetThreadSpecificData();
1152 code
=tsd
->_sc_error
;
1154 for (i
= 0; i
< (int)nSC_ERRMSGS
; i
++) {
1155 if (sc_errmsgs
[i
].status
== code
) {
1158 domain
= kCFErrorDomainSystemConfiguration
;
1159 userInfo
= CFDictionaryCreateMutable(NULL
,
1161 &kCFCopyStringDictionaryKeyCallBacks
,
1162 &kCFTypeDictionaryValueCallBacks
);
1163 str
= CFStringCreateWithCString(NULL
,
1164 sc_errmsgs
[i
].message
,
1165 kCFStringEncodingASCII
);
1166 CFDictionarySetValue(userInfo
, kCFErrorDescriptionKey
, str
);
1172 if ((code
> 0) && (code
<= ELAST
)) {
1173 domain
= kCFErrorDomainPOSIX
;
1177 domain
= kCFErrorDomainMach
;
1181 error
= CFErrorCreate(NULL
, domain
, code
, userInfo
);
1182 if (userInfo
!= NULL
) CFRelease(userInfo
);
1190 __SCThreadSpecificDataRef tsd
;
1192 tsd
= __SCGetThreadSpecificData();
1193 return tsd
->_sc_error
;
1198 SCErrorString(int status
)
1202 for (i
= 0; i
< (int)nSC_ERRMSGS
; i
++) {
1203 if (sc_errmsgs
[i
].status
== status
) {
1204 return sc_errmsgs
[i
].message
;
1208 if ((status
> 0) && (status
<= ELAST
)) {
1209 return strerror(status
);
1212 if ((status
>= BOOTSTRAP_SUCCESS
) && (status
<= BOOTSTRAP_NO_MEMORY
)) {
1213 return bootstrap_strerror(status
);
1216 return mach_error_string(status
);