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