2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
24 * Modification History
26 * June 1, 2001 Allan Nathanson <ajn@apple.com>
27 * - public API conversion
29 * 24 March 2000 Allan Nathanson (ajn@apple.com)
39 #include <sys/types.h>
41 #include <objc/objc-runtime.h>
44 #include "configd_server.h"
45 #include "plugin_support.h"
47 Boolean _configd_fork = TRUE; /* TRUE if process should be run in the background */
48 Boolean _configd_verbose = FALSE; /* TRUE if verbose logging enabled */
49 CFMutableSetRef _plugins_exclude = NULL; /* bundle identifiers to exclude from loading */
50 CFMutableSetRef _plugins_verbose = NULL; /* bundle identifiers to enable verbose logging */
52 static const char *signames[] = {
53 "" , "HUP" , "INT" , "QUIT", "ILL" , "TRAP", "ABRT", "EMT" ,
54 "FPE" , "KILL", "BUS" , "SEGV", "SYS" , "PIPE", "ALRM", "TERM",
55 "URG" , "STOP", "TSTP" , "CONT", "CHLD" , "TTIN", "TTOU", "IO" ,
56 "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "INFO", "USR1", "USR2"
61 usage(const char *prog)
63 SCPrint(TRUE, stderr, CFSTR("%s: [-d] [-v] [-V bundleID] [-b] [-B bundleID] [-t plugin-path]\n"), prog);
64 SCPrint(TRUE, stderr, CFSTR("options:\n"));
65 SCPrint(TRUE, stderr, CFSTR("\t-d\tdisable daemon/run in foreground\n"));
66 SCPrint(TRUE, stderr, CFSTR("\t-v\tenable verbose logging\n"));
67 SCPrint(TRUE, stderr, CFSTR("\t-V\tenable verbose logging for the specified plug-in\n"));
68 SCPrint(TRUE, stderr, CFSTR("\t-b\tdisable loading of ALL plug-ins\n"));
69 SCPrint(TRUE, stderr, CFSTR("\t-B\tdisable loading of the specified plug-in\n"));
70 SCPrint(TRUE, stderr, CFSTR("\t-t\tload/test the specified plug-in\n"));
71 SCPrint(TRUE, stderr, CFSTR("\t\t (Note: only the plug-in will be started)\n"), prog);
82 * Note: we can't use SCLog() since the signal may be received while the
83 * logging thread lock is held.
85 if (_configd_verbose) {
86 syslog (LOG_INFO, "caught SIG%s" , signames[signum]);
88 fprintf(stderr, "caught SIG%s\n", signames[signum]);
107 signal(SIGTERM, parent_exit);
114 /* child: becomes the daemon (see below) */
115 signal(SIGTERM, SIG_DFL);
119 /* parent: wait for signal, then exit */
122 (void) wait4(child_pid, (int *)&status, 0, 0);
123 if (WIFEXITED(status)) {
125 "*** configd (daemon) failed to start, exit status=%d",
126 WEXITSTATUS(status));
129 "*** configd (daemon) failed to start, received signal=%d",
142 if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
143 (void) dup2(fd, STDIN_FILENO);
144 (void) dup2(fd, STDOUT_FILENO);
145 (void) dup2(fd, STDERR_FILENO);
154 main(int argc, const char *argv[])
156 Boolean loadBundles = TRUE;
157 struct sigaction nact;
160 const char *prog = argv[0];
162 const char *testBundle = NULL;
164 _plugins_exclude = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
165 _plugins_verbose = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
167 /* process any arguments */
169 while ((opt = getopt(argc, argv, "bB:dt:vV:")) != -1) {
175 str = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingMacRoman);
176 CFSetSetValue(_plugins_exclude, str);
180 _configd_fork = FALSE;
186 _configd_verbose = TRUE;
189 if (strcmp(optarg, "com.apple.SystemConfiguration") == 0) {
192 str = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingMacRoman);
193 CFSetSetValue(_plugins_verbose, str);
206 * display an error if configd is already running and we are
207 * not executing/testing a bundle.
209 if ((testBundle == NULL) && (server_active() == TRUE)) {
210 exit (EX_UNAVAILABLE);
213 /* check credentials */
215 fprintf(stderr, "%s: permission denied.\n", prog);
220 if (fork_child() == -1) {
221 fprintf(stderr, "configd: fork() failed, %s\n", strerror(errno));
224 /* now the child process, parent waits in fork_child */
227 /* open syslog() facility */
229 int logopt = LOG_NDELAY|LOG_PID;
231 if (_configd_verbose)
233 openlog("configd", logopt, LOG_DAEMON);
235 _sc_log = FALSE; /* redirect SCLog() to stdout/stderr */
238 /* add signal handler to catch a SIGHUP */
240 nact.sa_handler = catcher;
241 sigemptyset(&nact.sa_mask);
242 nact.sa_flags = SA_RESTART;
244 if (sigaction(SIGHUP, &nact, NULL) == -1) {
245 SCLog(_configd_verbose, LOG_ERR,
246 CFSTR("sigaction(SIGHUP, ...) failed: %s"),
250 /* add signal handler to catch a SIGPIPE */
252 if (sigaction(SIGPIPE, &nact, NULL) == -1) {
253 SCLog(_configd_verbose, LOG_ERR,
254 CFSTR("sigaction(SIGPIPE, ...) failed: %s"),
260 objc_setMultithreaded(YES);
262 if (testBundle == NULL) {
263 /* initialize primary (store management) thread */
266 /* load/initialize/start bundles into the secondary thread */
271 /* synchronize with parent process */
272 kill(getppid(), SIGTERM);
279 if (testBundle == NULL) {
280 /* start primary (store management) thread */
283 /* load/initialize/start specified plug-in */
284 plugin_exec((void *)testBundle);
287 exit (EX_OK); // insure the process exit status is 0
288 return 0; // ...and make main fit the ANSI spec.