]> git.saurik.com Git - apple/configd.git/blob - SystemConfiguration.fproj/SCD.c
configd-42.tar.gz
[apple/configd.git] / SystemConfiguration.fproj / SCD.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 /*
24 * Modification History
25 *
26 * June 1, 2001 Allan Nathanson <ajn@apple.com>
27 * - public API conversion
28 *
29 * March 24, 2000 Allan Nathanson <ajn@apple.com>
30 * - initial revision
31 */
32
33 #include <mach/mach.h>
34 #include <mach/mach_error.h>
35 #include <pthread.h>
36
37 #include <SystemConfiguration/SystemConfiguration.h>
38 #include <SystemConfiguration/SCPrivate.h>
39 #include "SCDynamicStoreInternal.h"
40 #include "config.h" /* MiG generated file */
41
42 /* framework variables */
43 Boolean _sc_debug = FALSE; /* TRUE if debugging enabled */
44 Boolean _sc_verbose = FALSE; /* TRUE if verbose logging enabled */
45 Boolean _sc_log = TRUE; /* TRUE if SCLog() output goes to syslog */
46
47 static const struct sc_errmsg {
48 int status;
49 char *message;
50 } sc_errmsgs[] = {
51 { kSCStatusAccessError, "Permission denied" },
52 { kSCStatusFailed, "Failed!" },
53 { kSCStatusInvalidArgument, "Invalid argument" },
54 { kSCStatusKeyExists, "Key already defined" },
55 { kSCStatusLocked, "Lock already held" },
56 { kSCStatusNeedLock, "Lock required for this operation" },
57 { kSCStatusNoStoreServer, "Configuration daemon not (no longer) available" },
58 { kSCStatusNoStoreSession, "Configuration daemon session not active" },
59 { kSCStatusNoConfigFile, "Configuration file not found" },
60 { kSCStatusNoKey, "No such key" },
61 { kSCStatusNoLink, "No such link" },
62 { kSCStatusNoPrefsSession, "Preference session not active" },
63 { kSCStatusNotifierActive, "Notifier is currently active" },
64 { kSCStatusOK, "Success!" },
65 { kSCStatusPrefsBusy, "Configuration daemon busy" },
66 { kSCStatusReachabilityUnknown, "Network reachability cannot be determined" },
67 { kSCStatusStale, "Write attempted on stale version of object" },
68 };
69 #define nSC_ERRMSGS (sizeof(sc_errmsgs)/sizeof(struct sc_errmsg))
70
71
72 #define USE_SCCOPYDESCRIPTION
73 #ifdef USE_SCCOPYDESCRIPTION
74
75 // from <CoreFoundation/CFVeryPrivate.h>
76 extern CFStringRef _CFStringCreateWithFormatAndArgumentsAux(CFAllocatorRef alloc, CFStringRef (*copyDescFunc)(void *, CFDictionaryRef), CFDictionaryRef formatOptions, CFStringRef format, va_list arguments);
77
78 static CFStringRef
79 _SCCopyDescription(void *info, CFDictionaryRef formatOptions)
80 {
81 CFMutableDictionaryRef nFormatOptions;
82 CFStringRef prefix1;
83 CFStringRef prefix2;
84 CFTypeID type = CFGetTypeID(info);
85
86 if (!formatOptions ||
87 !CFDictionaryGetValueIfPresent(formatOptions, CFSTR("PREFIX1"), (void **)&prefix1)) {
88 prefix1 = CFSTR("");
89 }
90
91 if (type == CFStringGetTypeID()) {
92 return CFStringCreateWithFormat(NULL,
93 formatOptions,
94 CFSTR("%@%@"),
95 prefix1,
96 info);
97 }
98
99 if (type == CFBooleanGetTypeID()) {
100 return CFStringCreateWithFormat(NULL,
101 formatOptions,
102 CFSTR("%@%s"),
103 prefix1,
104 CFBooleanGetValue(info) ? "TRUE" : "FALSE");
105 }
106
107 if (type == CFDataGetTypeID()) {
108 const u_int8_t *data;
109 CFIndex dataLen;
110 CFIndex i;
111 CFMutableStringRef str;
112
113 str = CFStringCreateMutable(NULL, 0);
114 CFStringAppendFormat(str, formatOptions, CFSTR("%@<data> 0x"), prefix1);
115
116 data = CFDataGetBytePtr(info);
117 dataLen = CFDataGetLength(info);
118 for (i = 0; i < dataLen; i++) {
119 CFStringAppendFormat(str, NULL, CFSTR("%02x"), data[i]);
120 }
121
122 return str;
123 }
124
125 if (type == CFNumberGetTypeID()) {
126 return CFStringCreateWithFormat(NULL,
127 formatOptions,
128 CFSTR("%@%@"),
129 prefix1,
130 info);
131 }
132
133 if (type == CFDateGetTypeID()) {
134 CFGregorianDate gDate;
135 CFStringRef str;
136 CFTimeZoneRef tZone;
137
138 tZone = CFTimeZoneCopySystem();
139 gDate = CFAbsoluteTimeGetGregorianDate(CFDateGetAbsoluteTime(info), tZone);
140 str = CFStringCreateWithFormat(NULL,
141 formatOptions,
142 CFSTR("%@%02d/%02d/%04d %02d:%02d:%02.0f %@"),
143 prefix1,
144 gDate.month,
145 gDate.day,
146 gDate.year,
147 gDate.hour,
148 gDate.minute,
149 gDate.second,
150 CFTimeZoneGetName(tZone));
151 CFRelease(tZone);
152 return str;
153 }
154
155 if (!formatOptions ||
156 !CFDictionaryGetValueIfPresent(formatOptions, CFSTR("PREFIX2"), (void **)&prefix2)) {
157 prefix2 = CFStringCreateCopy(NULL, prefix1);
158 }
159
160 if (formatOptions) {
161 nFormatOptions = CFDictionaryCreateMutableCopy(NULL, 0, formatOptions);
162 } else {
163 nFormatOptions = CFDictionaryCreateMutable(NULL,
164 0,
165 &kCFTypeDictionaryKeyCallBacks,
166 &kCFTypeDictionaryValueCallBacks);
167 }
168
169 if (type == CFArrayGetTypeID()) {
170 void **elements;
171 CFIndex i;
172 CFIndex nElements;
173 CFMutableStringRef str;
174
175 str = CFStringCreateMutable(NULL, 0);
176 CFStringAppendFormat(str, formatOptions, CFSTR("%@<array> {"), prefix1);
177
178 nElements = CFArrayGetCount(info);
179 elements = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0);
180 CFArrayGetValues(info, CFRangeMake(0, nElements), elements);
181 for (i=0; i<nElements; i++) {
182 CFMutableStringRef nPrefix1;
183 CFMutableStringRef nPrefix2;
184 CFStringRef nStr;
185 CFStringRef vStr;
186
187 nStr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%u"), i);
188
189 nPrefix1 = CFStringCreateMutable(NULL, 0);
190 CFStringAppendFormat(nPrefix1,
191 formatOptions,
192 CFSTR("%@ %@ : "),
193 prefix2,
194 nStr);
195 nPrefix2 = CFStringCreateMutable(NULL, 0);
196 CFStringAppendFormat(nPrefix2,
197 formatOptions,
198 CFSTR("%@ "),
199 prefix2);
200
201 CFDictionarySetValue(nFormatOptions, CFSTR("PREFIX1"), nPrefix1);
202 CFDictionarySetValue(nFormatOptions, CFSTR("PREFIX2"), nPrefix2);
203 CFRelease(nPrefix1);
204 CFRelease(nPrefix2);
205 CFRelease(nStr);
206
207 vStr = _SCCopyDescription(elements[i], nFormatOptions);
208 CFStringAppendFormat(str,
209 formatOptions,
210 CFSTR("\n%@"),
211 vStr);
212 CFRelease(vStr);
213 }
214 CFAllocatorDeallocate(NULL, elements);
215 CFStringAppendFormat(str, formatOptions, CFSTR("\n%@}"), prefix2);
216
217 CFRelease(nFormatOptions);
218 return str;
219 }
220
221 if (type == CFDictionaryGetTypeID()) {
222 void **keys;
223 CFIndex i;
224 CFIndex nElements;
225 CFMutableStringRef nPrefix1;
226 CFMutableStringRef nPrefix2;
227 CFMutableStringRef str;
228 void **values;
229
230 str = CFStringCreateMutable(NULL, 0);
231 CFStringAppendFormat(str, formatOptions, CFSTR("%@<dictionary> {"), prefix1);
232
233 nElements = CFDictionaryGetCount(info);
234 keys = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0);
235 values = CFAllocatorAllocate(NULL, nElements * sizeof(CFTypeRef), 0);
236 CFDictionaryGetKeysAndValues(info, keys, values);
237 for (i=0; i<nElements; i++) {
238 CFStringRef kStr;
239 CFStringRef vStr;
240
241 kStr = _SCCopyDescription(keys[i], NULL);
242
243 nPrefix1 = CFStringCreateMutable(NULL, 0);
244 CFStringAppendFormat(nPrefix1,
245 formatOptions,
246 CFSTR("%@ %@ : "),
247 prefix2,
248 kStr);
249 nPrefix2 = CFStringCreateMutable(NULL, 0);
250 CFStringAppendFormat(nPrefix2,
251 formatOptions,
252 CFSTR("%@ "),
253 prefix2);
254
255 CFDictionarySetValue(nFormatOptions, CFSTR("PREFIX1"), nPrefix1);
256 CFDictionarySetValue(nFormatOptions, CFSTR("PREFIX2"), nPrefix2);
257 CFRelease(nPrefix1);
258 CFRelease(nPrefix2);
259 CFRelease(kStr);
260
261 vStr = _SCCopyDescription(values[i], nFormatOptions);
262 CFStringAppendFormat(str,
263 formatOptions,
264 CFSTR("\n%@"),
265 vStr);
266 CFRelease(vStr);
267 }
268 CFAllocatorDeallocate(NULL, keys);
269 CFAllocatorDeallocate(NULL, values);
270 CFStringAppendFormat(str, formatOptions, CFSTR("\n%@}"), prefix2);
271
272 CFRelease(nFormatOptions);
273 return str;
274 }
275
276 {
277 CFStringRef cfStr;
278 CFStringRef str;
279
280 cfStr = CFCopyDescription(info);
281 str = CFStringCreateWithFormat(NULL,
282 formatOptions,
283 CFSTR("%@%@"),
284 prefix1,
285 cfStr);
286 CFRelease(cfStr);
287 return str;
288 }
289 }
290
291 #endif /* USE_SCCOPYDESCRIPTION */
292
293
294 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
295
296
297 __private_extern__ void
298 __SCLog(int level, CFStringRef str)
299 {
300 CFArrayRef lines;
301
302 lines = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR("\n"));
303 if (lines) {
304 int i;
305
306 pthread_mutex_lock(&lock);
307 for (i=0; i<CFArrayGetCount(lines); i++) {
308 CFDataRef line;
309
310 line = CFStringCreateExternalRepresentation(NULL,
311 CFArrayGetValueAtIndex(lines, i),
312 kCFStringEncodingMacRoman,
313 '?');
314 if (line) {
315 syslog (level, "%.*s", (int)CFDataGetLength(line), CFDataGetBytePtr(line));
316 CFRelease(line);
317 }
318 }
319 pthread_mutex_unlock(&lock);
320 CFRelease(lines);
321 }
322
323 return;
324 }
325
326
327 __private_extern__ void
328 __SCPrint(FILE *stream, CFStringRef str)
329 {
330 CFDataRef line;
331
332 line = CFStringCreateExternalRepresentation(NULL,
333 str,
334 kCFStringEncodingMacRoman,
335 '?');
336 if (line) {
337 pthread_mutex_lock(&lock);
338 fprintf(stream, "%.*s", (int)CFDataGetLength(line), CFDataGetBytePtr(line));
339 fflush (stream);
340 pthread_mutex_unlock(&lock);
341 CFRelease(line);
342 }
343
344 return;
345 }
346
347
348 void
349 SCLog(Boolean condition, int level, CFStringRef formatString, ...)
350 {
351 va_list argList;
352 CFStringRef resultString;
353
354 if (!condition) {
355 return;
356 }
357
358 va_start(argList, formatString);
359 #ifdef USE_SCCOPYDESCRIPTION
360 resultString = _CFStringCreateWithFormatAndArgumentsAux(NULL,
361 _SCCopyDescription,
362 NULL,
363 formatString,
364 argList);
365 #else /* USE_SCCOPYDESCRIPTION */
366 resultString = CFStringCreateWithFormatAndArguments(NULL, NULL, formatString, argList);
367 #endif /* !USE_SCCOPYDESCRIPTION */
368 va_end(argList);
369
370 if (_sc_log) {
371 __SCLog(level, resultString);
372 } else {
373 FILE *f = (LOG_PRI(level) > LOG_NOTICE) ? stderr : stdout;
374 CFStringRef newString;
375
376 /* add a new-line */
377 newString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@\n"), resultString);
378 __SCPrint(f, newString);
379 CFRelease(newString);
380 }
381 CFRelease(resultString);
382 return;
383 }
384
385
386 void
387 SCPrint(Boolean condition, FILE *stream, CFStringRef formatString, ...)
388 {
389 va_list argList;
390 CFStringRef resultString;
391
392 if (!condition) {
393 return;
394 }
395
396 va_start(argList, formatString);
397 #ifdef USE_SCCOPYDESCRIPTION
398 resultString = _CFStringCreateWithFormatAndArgumentsAux(NULL,
399 _SCCopyDescription,
400 NULL,
401 formatString,
402 argList);
403 #else /* USE_SCCOPYDESCRIPTION */
404 resultString = CFStringCreateWithFormatAndArguments(NULL, NULL, formatString, argList);
405 #endif /* !USE_SCCOPYDESCRIPTION */
406 va_end(argList);
407
408 __SCPrint(stream, resultString);
409 CFRelease(resultString);
410 return;
411 }
412
413
414 typedef struct {
415 int _sc_error;
416 } __SCThreadSpecificData, *__SCThreadSpecificDataRef;
417
418
419 static pthread_once_t tsKeyInitialized = PTHREAD_ONCE_INIT;
420 static pthread_key_t tsDataKey = NULL;
421
422
423 static void
424 __SCThreadSpecificDataFinalize(void *arg)
425 {
426 __SCThreadSpecificDataRef tsd = (__SCThreadSpecificDataRef)arg;
427
428 if (!tsd) return;
429
430 CFAllocatorDeallocate(kCFAllocatorSystemDefault, tsd);
431 return;
432 }
433
434
435 static void
436 __SCThreadSpecificKeyInitialize()
437 {
438 pthread_key_create(&tsDataKey, __SCThreadSpecificDataFinalize);
439 return;
440 }
441
442
443 void
444 _SCErrorSet(int error)
445 {
446 __SCThreadSpecificDataRef tsd;
447
448 pthread_once(&tsKeyInitialized, __SCThreadSpecificKeyInitialize);
449
450 tsd = pthread_getspecific(tsDataKey);
451 if (!tsd) {
452 tsd = CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(__SCThreadSpecificData), 0);
453 bzero(tsd, sizeof(__SCThreadSpecificData));
454 pthread_setspecific(tsDataKey, tsd);
455 }
456
457 tsd->_sc_error = error;
458 return;
459 }
460
461
462 int
463 SCError()
464 {
465 __SCThreadSpecificDataRef tsd;
466
467 pthread_once(&tsKeyInitialized, __SCThreadSpecificKeyInitialize);
468
469 tsd = pthread_getspecific(tsDataKey);
470 return tsd ? tsd->_sc_error : kSCStatusOK;
471 }
472
473
474 const char *
475 SCErrorString(int status)
476 {
477 int i;
478
479 for (i = 0; i < nSC_ERRMSGS; i++) {
480 if (sc_errmsgs[i].status == status) {
481 return sc_errmsgs[i].message;
482 }
483 }
484
485 if ((status > 0) && (status <= ELAST)) {
486 return strerror(status);
487 }
488
489 return mach_error_string(status);
490 }