2 * Copyright (c) 2000-2008, 2010-2015 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 <SystemConfiguration/SystemConfiguration.h>
42 #include <SystemConfiguration/SCPrivate.h>
44 #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
);
398 __SCLog(asl_object_t asl
, asl_object_t msg
, int level
, CFStringRef formatString
, va_list formatArguments
)
405 __SCThreadSpecificDataRef tsd
;
407 tsd
= __SCGetThreadSpecificData();
408 if (tsd
->_asl
== NULL
) {
409 tsd
->_asl
= asl_open(NULL
, (_SC_isInstallEnvironment() ? INSTALL_FACILITY
: NULL
), 0);
410 asl_set_filter(tsd
->_asl
, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG
));
415 #ifdef ENABLE_SC_FORMATTING
416 str
= _CFStringCreateWithFormatAndArgumentsAux(NULL
,
421 #else /* ENABLE_SC_FORMATTING */
422 str
= CFStringCreateWithFormatAndArguments (NULL
,
426 #endif /* !ENABLE_SC_FORMATTING */
429 lines
= CFStringCreateArrayBySeparatingStrings(NULL
, str
, CFSTR("\n"));
432 CFIndex n
= CFArrayGetCount(lines
);
434 for (i
= 0; i
< n
; i
++) {
435 line
= CFStringCreateExternalRepresentation(NULL
,
436 CFArrayGetValueAtIndex(lines
, i
),
437 kCFStringEncodingUTF8
,
440 asl_log(asl
, msg
, level
, "%.*s", (int)CFDataGetLength(line
), CFDataGetBytePtr(line
));
447 line
= CFStringCreateExternalRepresentation(NULL
,
449 kCFStringEncodingUTF8
,
452 asl_log(asl
, msg
, ~level
, "%.*s", (int)CFDataGetLength(line
), CFDataGetBytePtr(line
));
462 __SCPrint(FILE *stream
, CFStringRef formatString
, va_list formatArguments
, Boolean trace
, Boolean addNL
)
467 #ifdef ENABLE_SC_FORMATTING
468 str
= _CFStringCreateWithFormatAndArgumentsAux(NULL
,
473 #else /* ENABLE_SC_FORMATTING */
474 str
= CFStringCreateWithFormatAndArguments (NULL
,
478 #endif /* !ENABLE_SC_FORMATTING */
480 line
= CFStringCreateExternalRepresentation(NULL
,
482 kCFStringEncodingUTF8
,
489 pthread_mutex_lock(&lock
);
492 struct timeval tv_now
;
494 (void)gettimeofday(&tv_now
, NULL
);
495 (void)localtime_r(&tv_now
.tv_sec
, &tm_now
);
496 (void)fprintf(stream
, "%2d:%02d:%02d.%03d ",
497 tm_now
.tm_hour
, tm_now
.tm_min
, tm_now
.tm_sec
, tv_now
.tv_usec
/ 1000);
499 (void)fwrite((const void *)CFDataGetBytePtr(line
), (size_t)CFDataGetLength(line
), 1, stream
);
501 (void)fputc('\n', stream
);
504 pthread_mutex_unlock(&lock
);
512 SCLog(Boolean condition
, int level
, CFStringRef formatString
, ...)
514 va_list formatArguments
;
515 va_list formatArguments_print
;
517 Boolean print
= FALSE
;
524 * Note: The following are the expected values for _sc_log
526 * 0 if SC messages should be written to stdout/stderr
527 * 1 if SC messages should be logged w/asl(3)
528 * 2 if SC messages should be written to stdout/stderr AND logged
532 log
= TRUE
; // log requested
533 va_start(formatArguments
, formatString
);
536 print
= TRUE
; // log AND print requested
537 va_copy(formatArguments_print
, formatArguments
);
540 print
= TRUE
; // print requested
541 va_start(formatArguments_print
, formatString
);
545 __SCLog(NULL
, NULL
, level
, formatString
, formatArguments
);
546 va_end(formatArguments
);
550 __SCPrint((LOG_PRI(level
) > LOG_NOTICE
) ? stderr
: stdout
,
552 formatArguments_print
,
553 (_sc_log
> 0), // trace
554 TRUE
); // add newline
555 va_end(formatArguments_print
);
563 SCLOG(asl_object_t asl
, asl_object_t msg
, int level
, CFStringRef formatString
, ...)
565 va_list formatArguments
;
566 va_list formatArguments_print
;
568 Boolean print
= FALSE
;
571 * Note: The following are the expected values for _sc_log
573 * 0 if SC messages should be written to stdout/stderr
574 * 1 if SC messages should be logged w/asl(3)
575 * 2 if SC messages should be written to stdout/stderr AND logged
579 log
= TRUE
; // log requested
580 va_start(formatArguments
, formatString
);
583 print
= TRUE
; // log AND print requested
584 va_copy(formatArguments_print
, formatArguments
);
587 print
= TRUE
; // print requested
588 va_start(formatArguments_print
, formatString
);
592 __SCLog(asl
, msg
, level
, formatString
, formatArguments
);
593 va_end(formatArguments
);
600 __SCPrint((level
> ASL_LEVEL_NOTICE
) ? stderr
: stdout
,
602 formatArguments_print
,
603 (_sc_log
> 0), // trace
604 TRUE
); // add newline
605 va_end(formatArguments_print
);
613 SCPrint(Boolean condition
, FILE *stream
, CFStringRef formatString
, ...)
615 va_list formatArguments
;
621 va_start(formatArguments
, formatString
);
622 __SCPrint(stream
, formatString
, formatArguments
, FALSE
, FALSE
);
623 va_end(formatArguments
);
630 SCTrace(FILE *stream
, CFStringRef formatString
, ...)
632 va_list formatArguments
;
634 va_start(formatArguments
, formatString
);
635 if (stream
!= NULL
) {
636 __SCPrint(stream
, formatString
, formatArguments
, TRUE
, FALSE
);
638 va_end(formatArguments
);
645 #pragma mark ASL Functions
648 static CFTypeID __kSCLoggerTypeID
= _kCFRuntimeNotATypeID
;
651 kModuleStatusEnabled
,
652 kModuleStatusDisabled
,
653 kModuleStatusDoesNotExist
658 CFRuntimeBase cf_base
;
660 char * loggerID
; // LoggerID
664 ModuleStatus module_status
;
665 pthread_mutex_t lock
;
669 static void __SCLoggerDeallocate(CFTypeRef cf
);
670 static const CFRuntimeClass __SCLoggerClass
= {
672 "SCLogger", /* className */
675 __SCLoggerDeallocate
, /* deallocate */
678 NULL
, /* copyFormattingDesc */
679 NULL
/* copyDebugDesc */
683 #define DATETIMEBUFFERSIZE 32
686 static pthread_once_t registerLoggerOnce
= PTHREAD_ONCE_INIT
;
687 static pthread_once_t defaultLoggerOnce
= PTHREAD_ONCE_INIT
;
690 kLoggerASLControlEnableModule
,
691 kLoggerASLControlDisableModule
,
692 kLoggerASLControlLogFileCheckpoint
695 static SCLoggerRef defaultLogger
= NULL
;
696 static SCLoggerRef
__SCLoggerCreate(void);
697 static void __SCLoggerDefaultLoggerInit();
698 static SCLoggerRef
SCLoggerGetDefaultLogger();
699 static void SCLoggerSetLoggerID(SCLoggerRef logger
, CFStringRef loggerID
);
700 static void SCLoggerSendMessageToModuleOnly(SCLoggerRef logger
, Boolean isPrivate
);
701 static void SCLoggerSendASLControl(SCLoggerRef logger
, LoggerASLControl control
);
702 static ModuleStatus
GetModuleStatus(const char * loggerID
);
705 __SCLoggerRegisterClass(void)
707 if (__kSCLoggerTypeID
== _kCFRuntimeNotATypeID
) {
708 __kSCLoggerTypeID
= _CFRuntimeRegisterClass(&__SCLoggerClass
);
714 __SCLoggerAllocate(CFAllocatorRef allocator
)
719 pthread_once(®isterLoggerOnce
, __SCLoggerRegisterClass
);
721 size
= sizeof(*state
) - sizeof(CFRuntimeBase
);
722 state
= (SCLoggerRef
) _CFRuntimeCreateInstance(allocator
,
726 bzero((void*)state
+ sizeof(CFRuntimeBase
), size
);
731 __SCLoggerDeallocate(CFTypeRef cf
)
733 SCLoggerRef logger
= (SCLoggerRef
)cf
;
735 if (logger
!= NULL
) {
736 // Rotate on close behavior
737 if (logger
->module_status
!= kModuleStatusDoesNotExist
) {
738 SCLoggerSendASLControl(logger
,
739 kLoggerASLControlLogFileCheckpoint
);
741 if (logger
->loggerID
!= NULL
) {
742 CFAllocatorDeallocate(NULL
, logger
->loggerID
);
743 logger
->loggerID
= NULL
;
745 if (logger
->aslm
!= NULL
) {
746 asl_release(logger
->aslm
);
749 if (logger
->aslc
!= NULL
) {
750 asl_release(logger
->aslc
);
757 __SCLoggerCreate(void)
759 SCLoggerRef tempLogger
= NULL
;
761 tempLogger
= __SCLoggerAllocate(kCFAllocatorDefault
);
762 tempLogger
->loggerID
= NULL
;
763 tempLogger
->flags
= kSCLoggerFlagsDefault
;
764 tempLogger
->aslc
= asl_open(NULL
, (_SC_isInstallEnvironment() ? INSTALL_FACILITY
: NULL
), ASL_OPT_NO_DELAY
);
765 tempLogger
->aslm
= asl_new(ASL_TYPE_MSG
);
766 pthread_mutex_init(&(tempLogger
->lock
), NULL
);
767 tempLogger
->module_status
= kModuleStatusDoesNotExist
;
773 SCLoggerGetFlags(SCLoggerRef logger
)
775 return logger
->flags
;
779 SCLoggerSetFlags(SCLoggerRef logger
, SCLoggerFlags flags
)
781 if (logger
== defaultLogger
) {
784 pthread_mutex_lock(&(logger
->lock
));
785 if (flags
!= kSCLoggerFlagsNone
) {
786 logger
->module_status
= GetModuleStatus(logger
->loggerID
);
787 if (logger
->module_status
== kModuleStatusDoesNotExist
) {
790 if ((flags
& kSCLoggerFlagsFile
) != 0) {
791 if ((logger
->flags
& kSCLoggerFlagsFile
) == 0) {
792 // Enable the module if disabled
793 if (logger
->module_status
== kModuleStatusDisabled
) {
794 SCLoggerSendASLControl(logger
, kLoggerASLControlEnableModule
);
796 // Setting ASL Filter level to debug
797 asl_set_filter(logger
->aslc
, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG
));
798 if (logger
->loggerID
!= NULL
) {
799 asl_set(logger
->aslm
, kLoggerID
,
804 else if ((logger
->flags
& kSCLoggerFlagsFile
) != 0) {
805 asl_unset(logger
->aslm
, kLoggerID
);
806 asl_set_filter(logger
->aslc
, ASL_FILTER_MASK_UPTO(ASL_LEVEL_NOTICE
));
807 SCLoggerSendMessageToModuleOnly(logger
, false);
809 if ((flags
& kSCLoggerFlagsDefault
) != 0) {
810 if ((logger
->flags
& kSCLoggerFlagsDefault
) == 0) {
811 SCLoggerSendMessageToModuleOnly(logger
, false);
814 else if ((logger
->flags
& kSCLoggerFlagsDefault
) != 0) {
815 SCLoggerSendMessageToModuleOnly(logger
, true);
818 logger
->flags
= flags
;
820 pthread_mutex_unlock(&(logger
->lock
));
825 SCLoggerSetLoggerID(SCLoggerRef logger
, CFStringRef loggerID
)
828 = _SC_cfstring_to_cstring(loggerID
, NULL
, 0,
829 kCFStringEncodingUTF8
);
830 // Enable the module if disabled
831 logger
->module_status
= GetModuleStatus(logger
->loggerID
);
832 if (logger
->module_status
== kModuleStatusDisabled
) {
833 SCLoggerSendASLControl(logger
, kLoggerASLControlEnableModule
);
838 GetModuleStatus(const char * loggerID
)
840 ModuleStatus moduleStatus
= kModuleStatusDoesNotExist
;
841 asl_object_t response
= NULL
;
842 const char* value
= NULL
;
844 if (loggerID
!= NULL
) {
845 response
= _asl_server_control_query();
846 if (response
== NULL
) {
849 value
= asl_get(response
, loggerID
);
851 moduleStatus
= kModuleStatusDoesNotExist
;
855 if (strcmp(value
, "enabled") == 0) {
856 moduleStatus
= kModuleStatusEnabled
;
859 moduleStatus
= kModuleStatusDisabled
;
863 asl_release(response
);
869 SCLoggerSendMessageToModuleOnly(SCLoggerRef logger
, Boolean isPrivate
)
872 asl_set(logger
->aslm
, kASLModule
, logger
->loggerID
);
875 if (asl_get(logger
->aslm
, kASLModule
) != NULL
) {
876 asl_unset(logger
->aslm
, kASLModule
);
882 SCLoggerSendASLControl(SCLoggerRef logger
, LoggerASLControl control
)
884 SCLoggerRef defLogger
= SCLoggerGetDefaultLogger();
885 pthread_mutex_lock(&(defLogger
->lock
));
887 // this next line turns the asl_log()'s that follow into control messages
888 asl_set(defLogger
->aslm
, kASLOption
, "control");
891 case kLoggerASLControlEnableModule
:
892 asl_log(defLogger
->aslc
, defLogger
->aslm
,
893 ASL_LEVEL_NOTICE
, "@ %s enable 1",
896 case kLoggerASLControlDisableModule
:
897 asl_log(defLogger
->aslc
, defLogger
->aslm
,
898 ASL_LEVEL_NOTICE
, "@ %s enable 0",
901 case kLoggerASLControlLogFileCheckpoint
:
902 asl_log(defLogger
->aslc
, defLogger
->aslm
,
903 ASL_LEVEL_NOTICE
, "@ %s checkpoint",
910 // turn off control mode
911 asl_unset(defLogger
->aslm
, kASLOption
);
912 pthread_mutex_unlock(&defLogger
->lock
);
917 SCLoggerCreate(CFStringRef loggerID
)
919 SCLoggerRef logger
= NULL
;
921 logger
= __SCLoggerCreate();
922 if (loggerID
!= NULL
) {
923 SCLoggerSetLoggerID(logger
, loggerID
);
925 SCLoggerSetFlags(logger
, kSCLoggerFlagsDefault
);
930 __SCLoggerDefaultLoggerInit()
932 if (defaultLogger
== NULL
) {
933 defaultLogger
= __SCLoggerCreate();
934 defaultLogger
->flags
= kSCLoggerFlagsDefault
;
939 SCLoggerGetDefaultLogger()
941 pthread_once(&defaultLoggerOnce
, __SCLoggerDefaultLoggerInit
);
942 return defaultLogger
;
946 SCLoggerVLog(SCLoggerRef logger
, int loglevel
, CFStringRef formatString
,
953 || logger
->module_status
== kModuleStatusDoesNotExist
) {
954 logger
= SCLoggerGetDefaultLogger();
956 pthread_mutex_lock(&(logger
->lock
));
957 if (logger
->flags
== kSCLoggerFlagsNone
) {
958 pthread_mutex_unlock(&(logger
->lock
));
963 __SCLog(aslc
, aslm
, loglevel
, formatString
, args
);
964 pthread_mutex_unlock(&(logger
->lock
));
969 SCLoggerLog(SCLoggerRef logger
, int loglevel
, CFStringRef formatString
, ...)
973 va_start(args
, formatString
);
974 SCLoggerVLog(logger
, loglevel
, formatString
, args
);
982 #pragma mark SC error handling / logging
985 const CFStringRef kCFErrorDomainSystemConfiguration
= CFSTR("com.apple.SystemConfiguration");
988 static const struct sc_errmsg
{
992 { kSCStatusAccessError
, "Permission denied" },
993 { kSCStatusConnectionIgnore
, "Network connection information not available at this time" },
994 { kSCStatusConnectionNoService
, "Network service for connection not available" },
995 { kSCStatusFailed
, "Failed!" },
996 { kSCStatusInvalidArgument
, "Invalid argument" },
997 { kSCStatusKeyExists
, "Key already defined" },
998 { kSCStatusLocked
, "Lock already held" },
999 { kSCStatusMaxLink
, "Maximum link count exceeded" },
1000 { kSCStatusNeedLock
, "Lock required for this operation" },
1001 { kSCStatusNoStoreServer
, "Configuration daemon not (no longer) available" },
1002 { kSCStatusNoStoreSession
, "Configuration daemon session not active" },
1003 { kSCStatusNoConfigFile
, "Configuration file not found" },
1004 { kSCStatusNoKey
, "No such key" },
1005 { kSCStatusNoLink
, "No such link" },
1006 { kSCStatusNoPrefsSession
, "Preference session not active" },
1007 { kSCStatusNotifierActive
, "Notifier is currently active" },
1008 { kSCStatusOK
, "Success!" },
1009 { kSCStatusPrefsBusy
, "Preferences update currently in progress" },
1010 { kSCStatusReachabilityUnknown
, "Network reachability cannot be determined" },
1011 { kSCStatusStale
, "Write attempted on stale version of object" },
1013 #define nSC_ERRMSGS (sizeof(sc_errmsgs)/sizeof(struct sc_errmsg))
1016 _SCErrorSet(int error
)
1018 __SCThreadSpecificDataRef tsd
;
1020 tsd
= __SCGetThreadSpecificData();
1021 tsd
->_sc_error
= error
;
1027 SCCopyLastError(void)
1033 __SCThreadSpecificDataRef tsd
;
1034 CFMutableDictionaryRef userInfo
= NULL
;
1036 tsd
= __SCGetThreadSpecificData();
1037 code
=tsd
->_sc_error
;
1039 for (i
= 0; i
< (int)nSC_ERRMSGS
; i
++) {
1040 if (sc_errmsgs
[i
].status
== code
) {
1043 domain
= kCFErrorDomainSystemConfiguration
;
1044 userInfo
= CFDictionaryCreateMutable(NULL
,
1046 &kCFCopyStringDictionaryKeyCallBacks
,
1047 &kCFTypeDictionaryValueCallBacks
);
1048 str
= CFStringCreateWithCString(NULL
,
1049 sc_errmsgs
[i
].message
,
1050 kCFStringEncodingASCII
);
1051 CFDictionarySetValue(userInfo
, kCFErrorDescriptionKey
, str
);
1057 if ((code
> 0) && (code
<= ELAST
)) {
1058 domain
= kCFErrorDomainPOSIX
;
1062 domain
= kCFErrorDomainMach
;
1066 error
= CFErrorCreate(NULL
, domain
, code
, userInfo
);
1067 if (userInfo
!= NULL
) CFRelease(userInfo
);
1075 __SCThreadSpecificDataRef tsd
;
1077 tsd
= __SCGetThreadSpecificData();
1078 return tsd
->_sc_error
;
1083 SCErrorString(int status
)
1087 for (i
= 0; i
< (int)nSC_ERRMSGS
; i
++) {
1088 if (sc_errmsgs
[i
].status
== status
) {
1089 return sc_errmsgs
[i
].message
;
1093 if ((status
> 0) && (status
<= ELAST
)) {
1094 return strerror(status
);
1097 if ((status
>= BOOTSTRAP_SUCCESS
) && (status
<= BOOTSTRAP_NO_MEMORY
)) {
1098 return bootstrap_strerror(status
);
1101 return mach_error_string(status
);