1/* 2 * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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 11 * file. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25// 26// debugsupport - support interface for making and managing debugger objects. 27// 28// This header is not needed for logging debug messages. 29// 30#ifndef _H_DEBUGSUPPORT 31#define _H_DEBUGSUPPORT 32 33// 34// Generate stub-code support if NDEBUG (but not CLEAN_NDEBUG) is set, to support 35// client code that may have been generated with debug enabled. You don't actually 36// get *real* debug logging, of course, just cheap dummy stubs to keep the linker happy. 37// 38#include <security_utilities/debugging.h> 39#include <security_utilities/threading.h> 40#include <security_utilities/globalizer.h> 41#include <cstdarg> 42#include <set> 43 44namespace Security { 45namespace Debug { 46 47 48// 49// Debug scope names - short strings with value semantics. 50// We don't use STL strings because of overhead. 51// 52class Name { 53public: 54 static const int maxLength = 12; 55 56 Name(const char *s) 57 { strncpy(mName, s, maxLength-1); mName[maxLength-1] = '\0'; } 58 59 Name(const char *start, const char *end) 60 { 61 intptr_t length = end - start; if (length >= maxLength) length = maxLength - 1; 62 memcpy(mName, start, length); memset(mName + length, 0, maxLength - length); 63 } 64 65 operator const char *() const { return mName; } 66 67 bool operator < (const Name &other) const 68 { return memcmp(mName, other.mName, maxLength) < 0; } 69 70 bool operator == (const Name &other) const 71 { return memcmp(mName, other.mName, maxLength) == 0; } 72 73private: 74 char mName[maxLength]; // null terminated for easy printing 75}; 76 77 78// 79// A debugging Target. This is an object that receives debugging requests. 80// You can have many, but one default one is always provided. 81// 82class Target { 83public: 84 Target(); 85 virtual ~Target(); 86 87 // get default (singleton) Target 88 static Target &get(); 89 90 void setFromEnvironment(); 91 92public: 93 class Sink { 94 public: 95 virtual ~Sink(); 96 virtual void put(const char *buffer, unsigned int length) = 0; 97 virtual void dump(const char *buffer); 98 virtual void configure(const char *argument); 99 const bool needsDate; 100 101 protected: 102 Sink(bool nd = true) : needsDate(nd) { } 103 }; 104 105 void to(Sink *sink); 106 void to(const char *filename); 107 void to(int syslogPriority); 108 void to(FILE *openFile); 109 110 void configure(); // from DEBUGOPTIONS 111 void configure(const char *options); // from explicit string 112 113public: 114 void message(const char *scope, const char *format, va_list args); 115 bool debugging(const char *scope); 116 void dump(const char *format, va_list args); 117 bool dump(const char *scope); 118 119protected: 120 class Selector { 121 public: 122 Selector(); 123 void operator = (const char *config); 124 125 bool operator () (const char *name) const; 126 127 private: 128 bool useSet; // use contents of enableSet 129 bool negate; // negate meaning of enableSet 130 set<Name> enableSet; // set of names 131 }; 132 133protected: 134 class PerThread { 135 public: 136 PerThread() { id = ++lastUsed; } 137 unsigned int id; // arbitrary (sequential) ID number 138 139 private: 140 static unsigned int lastUsed; // last id used 141 }; 142 ThreadNexus<PerThread> perThread; 143 144protected: 145 static const size_t messageConstructionSize = 512; // size of construction buffer 146 147 Selector logSelector; // selector for logging 148 Selector dumpSelector; // selector for dumping 149 150 // output option state (from last configure call) 151 bool showScope; // include scope in output lines 152 bool showScopeRight; // scope after proc/thread, not before 153 bool showThread; // include thread and pid in output lines 154 bool showProc; // include "nice" process/thread id in output lines 155 bool showDate; // include date in output lines 156 size_t dumpLimit; // max. # of bytes dumped by dumpData & friends 157 158 // misc. global state 159 static const size_t maxProgNameLength = 20; // max. program name remembered 160 static const size_t procLength = 14; // characters for proc/thread column 161 static char progName[]; // (short truncated form of) program name 162 163 // current output support 164 Sink *sink; 165 166 static terminate_handler previousTerminator; // for chaining 167 static void terminator(); 168 169 // the default Target 170 static Target *singleton; 171}; 172 173 174// 175// Standard Target::Sinks 176// 177class FileSink : public Target::Sink { 178public: 179 FileSink(FILE *f) : Sink(true), file(f) { } 180 void put(const char *, unsigned int); 181 void dump(const char *text); 182 void configure(const char *); 183 184private: 185 FILE *file; 186}; 187 188class SyslogSink : public Target::Sink { 189public: 190 SyslogSink(int pri) 191 : Sink(false), priority(pri), dumpBase(dumpBuffer), dumpPtr(dumpBuffer) { } 192 void put(const char *, unsigned int); 193 void dump(const char *text); 194 void configure(const char *); 195 196private: 197 int priority; 198 199 // a sliding buffer to hold partial line output 200 static const size_t dumpBufferSize = 1024; // make this about 2 * maximum line length of dumps 201 char dumpBuffer[dumpBufferSize]; 202 char *dumpBase, *dumpPtr; 203}; 204 205 206} // end namespace Debug 207} // end namespace Security 208 209 210#endif //_H_DEBUGSUPPORT 211