]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
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 | ||
44 | namespace Security { | |
45 | namespace Debug { | |
46 | ||
47 | ||
48 | // | |
49 | // Debug scope names - short strings with value semantics. | |
50 | // We don't use STL strings because of overhead. | |
51 | // | |
52 | class Name { | |
53 | public: | |
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 | { | |
427c49bc | 61 | intptr_t length = end - start; if (length >= maxLength) length = maxLength - 1; |
b1ab9ed8 A |
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 | ||
73 | private: | |
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 | // | |
82 | class Target { | |
83 | public: | |
84 | Target(); | |
85 | virtual ~Target(); | |
86 | ||
87 | // get default (singleton) Target | |
88 | static Target &get(); | |
89 | ||
90 | void setFromEnvironment(); | |
91 | ||
92 | public: | |
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 | ||
113 | public: | |
866f8763 | 114 | void message(const char *scope, const char *format, va_list args) __attribute__((format(printf, 3, 0))); |
b1ab9ed8 | 115 | bool debugging(const char *scope); |
866f8763 A |
116 | void dump(const char *format, va_list args) __attribute__((format(printf,2,0))); |
117 | bool dumping(const char *scope); | |
b1ab9ed8 A |
118 | |
119 | protected: | |
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 | ||
133 | protected: | |
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 | ||
144 | protected: | |
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 | // | |
177 | class FileSink : public Target::Sink { | |
178 | public: | |
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 | ||
184 | private: | |
185 | FILE *file; | |
186 | }; | |
187 | ||
188 | class SyslogSink : public Target::Sink { | |
189 | public: | |
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 | ||
196 | private: | |
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 |