/* * Copyright (c) 2006-2010 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * debugging.c - non-trivial debug support */ #include #include #include #include #include #include #include #include #include #define MAX_SCOPE_LENGTH 12 #if !defined(NDEBUG) static CFStringRef copyScopeName(const char *scope, CFIndex scopeLen) { if (scopeLen > MAX_SCOPE_LENGTH) scopeLen = MAX_SCOPE_LENGTH - 1; return CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)scope, scopeLen, kCFStringEncodingUTF8, false); } pthread_once_t __security_debug_once = PTHREAD_ONCE_INIT; static const char *gDebugScope; static CFMutableSetRef scopeSet; static bool negate = false; static void __security_debug_init(void) { const char *cur_scope = gDebugScope = getenv("DEBUGSCOPE"); if (cur_scope) { if (!strcmp(cur_scope, "all")) { scopeSet = NULL; negate = true; } else if (!strcmp(cur_scope, "none")) { scopeSet = NULL; negate = false; } else { scopeSet = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); if (cur_scope[0] == '-') { negate = true; cur_scope++; } else { negate = false; } const char *sep; while ((sep = strchr(cur_scope, ','))) { CFStringRef scopeName = copyScopeName(cur_scope, sep - cur_scope); CFSetAddValue(scopeSet, scopeName); CFRelease(scopeName); cur_scope = sep + 1; } CFStringRef scopeName = copyScopeName(cur_scope, strlen(cur_scope)); CFSetAddValue(scopeSet, scopeName); CFRelease(scopeName); } } else { scopeSet = NULL; negate = false; } } #endif void __security_debug(CFStringRef scope, const char *function, const char *file, int line, CFStringRef format, ...) { #if !defined(NDEBUG) pthread_once(&__security_debug_once, __security_debug_init); /* Scope NULL is always enabled. */ if (scope) { /* Check if the scope is enabled. */ if (scopeSet) { if (negate == CFSetContainsValue(scopeSet, scope)) { return; } } else if (!negate) { return; } } #endif va_list args; va_start(args, format); CFStringRef message = CFStringCreateWithFormatAndArguments( kCFAllocatorDefault, NULL, format, args); va_end(args); time_t now = time(NULL); char *date = ctime(&now); date[19] = '\0'; CFStringRef logStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s %@ %s %@\n"), date + 4, scope ? scope : CFSTR(""), function, message); CFShow(logStr); char logMsg[4096]; if (CFStringGetCString(logStr, logMsg, sizeof(logMsg), kCFStringEncodingUTF8)) { char scopeStr[MAX_SCOPE_LENGTH + 1]; aslmsg msg = asl_new(ASL_TYPE_MSG); if (scope) { if (CFStringGetCString(scope, scopeStr, sizeof(scopeStr), kCFStringEncodingUTF8)) { asl_set(msg, ASL_KEY_FACILITY, scopeStr); } asl_set(msg, ASL_KEY_LEVEL, ASL_STRING_INFO); } else { asl_set(msg, ASL_KEY_LEVEL, ASL_STRING_ERR); } asl_set(msg, ASL_KEY_MSG, logMsg); asl_send(NULL, msg); asl_free(msg); } CFRelease(logStr); CFRelease(message); }