]> git.saurik.com Git - apple/configd.git/blame - configd.tproj/configd.m
configd-24.tar.gz
[apple/configd.git] / configd.tproj / configd.m
CommitLineData
5958d7c0
A
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 * 24 March 2000 Allan Nathanson (ajn@apple.com)
26 * - created
27 */
28
29#include <stdio.h>
30#include <sysexits.h>
31#include <syslog.h>
32#include <unistd.h>
33#include <paths.h>
34#include <fcntl.h>
35#include <sys/types.h>
36#include <sys/wait.h>
37#include <objc/objc-runtime.h>
38
39#include "configd.h"
40#include "configd_server.h"
41#include "plugin_support.h"
42
43
44const char *signames[] = {
45 "" , "HUP" , "INT" , "QUIT", "ILL" , "TRAP", "ABRT", "EMT" ,
46 "FPE" , "KILL", "BUS" , "SEGV", "SYS" , "PIPE", "ALRM", "TERM",
47 "URG" , "STOP", "TSTP" , "CONT", "CHLD" , "TTIN", "TTOU", "IO" ,
48 "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "INFO", "USR1", "USR2"
49};
50
51
52void
53usage(const char *prog)
54{
55 SCDLog(LOG_INFO, CFSTR("%s: [-d] [-v] [-b] [-t plugin-bundle-path]"), prog);
56 SCDLog(LOG_INFO, CFSTR("options:"));
57 SCDLog(LOG_INFO, CFSTR("\t-d\tenable debugging"));
58 SCDLog(LOG_INFO, CFSTR("\t-v\tenable verbose logging"));
59 SCDLog(LOG_INFO, CFSTR("\t-b\tdisable loading of ALL plug-ins"));
60 SCDLog(LOG_INFO, CFSTR("\t-t\tload/test the specified plug-in"));
61 SCDLog(LOG_INFO, CFSTR("\t\t (Note: only the plug-in will be started)"), prog);
62 exit (EX_USAGE);
63}
64
65
66void
67catcher(int signum)
68{
69 /*
70 * log the signal
71 *
72 * Note: we can't use SCDLog() since the signal may be received while the
73 * logging thread lock is held.
74 */
75 if (SCDOptionGet(NULL, kSCDOptionUseSyslog)) {
76 syslog (LOG_INFO, "caught SIG%s" , signames[signum]);
77 } else {
78 fprintf(stderr, "caught SIG%s\n", signames[signum]);
79 fflush (stderr);
80 }
81
82 return;
83}
84
85static void
86parent_exit(int i)
87{
88 _exit (0);
89}
90
91static int
92fork_child()
93{
94 int child_pid;
95 int fd;
96
97 signal(SIGTERM, parent_exit);
98 child_pid = fork();
99 switch (child_pid) {
100 case -1: {
101 return -1;
102 }
103 case 0: {
104 /* child: becomes the daemon (see below) */
105 signal(SIGTERM, SIG_DFL);
106 break;
107 }
108 default: {
109 /* parent: wait for signal, then exit */
110 int status;
111
112 (void) wait4(child_pid, (int *)&status, 0, 0);
113 if (WIFEXITED(status)) {
114 fprintf(stderr,
115 "*** configd (daemon) failed to start, exit status=%d",
116 WEXITSTATUS(status));
117 } else {
118 fprintf(stderr,
119 "*** configd (daemon) failed to start, received signal=%d",
120 WTERMSIG(status));
121 }
122 fflush (stderr);
123 exit (EX_SOFTWARE);
124 }
125 }
126
127 if (setsid() == -1)
128 return -1;
129
130 (void)chdir("/");
131
132 if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
133 (void)dup2(fd, STDIN_FILENO);
134 (void)dup2(fd, STDOUT_FILENO);
135 (void)dup2(fd, STDERR_FILENO);
136 if (fd > 2)
137 (void)close(fd);
138 }
139
140 return 0;
141}
142
143int
144main (int argc, const char *argv[])
145{
146 extern int optind;
147 int opt;
148 const char *prog = argv[0];
149 boolean_t loadBundles = TRUE;
150 const char *testBundle = NULL;
151 struct sigaction nact;
152
153 /* process any arguments */
154
155 while ((opt = getopt(argc, argv, "bdt:v")) != -1) {
156 switch(opt) {
157 case 'b':
158 loadBundles = FALSE;
159 break;
160 case 'd':
161 SCDOptionSet(NULL, kSCDOptionDebug, TRUE);
162 break;
163 case 't':
164 testBundle = optarg;
165 break;
166 case 'v':
167 SCDOptionSet(NULL, kSCDOptionVerbose, TRUE);
168 break;
169 case '?':
170 default :
171 usage(prog);
172 }
173 }
174 argc -= optind;
175 argv += optind;
176
177 /*
178 * display an error if configd is already running and we are
179 * not executing/testing a bundle.
180 */
181 if ((testBundle == NULL) && (server_active() == TRUE)) {
182 exit (EX_UNAVAILABLE);
183 }
184
185 /* get ready */
186
187 SCDOptionSet(NULL, kSCDOptionIsServer, TRUE); /* Use the config API's "server" code */
188 SCDOptionSet(NULL, kSCDOptionUseCFRunLoop, TRUE); /* Use the CFRunLoop */
189
190 /* check credentials */
191 if (getuid() != 0) {
192#ifdef DEBUG
193 if (!SCDOptionGet(NULL, kSCDOptionDebug)) {
194#endif /* DEBUG */
195 fprintf(stderr, "%s: permission denied.\n", prog);
196 exit (EX_NOPERM);
197#ifdef DEBUG
198 }
199#endif /* DEBUG */
200 }
201
202 if ((testBundle == NULL) && !SCDOptionGet(NULL, kSCDOptionDebug)) {
203 if (fork_child() == -1) {
204 fprintf(stderr, "configd: fork() failed, %s\n", strerror(errno));
205 exit (1);
206 }
207 /* now the child process, parent waits in fork_child */
208
209 /* log via syslog() facility */
210 openlog("configd", (LOG_NDELAY | LOG_PID), LOG_DAEMON);
211 SCDOptionSet(NULL, kSCDOptionUseSyslog, TRUE);
212 }
213
214 /* add signal handler to catch a SIGPIPE */
215
216 nact.sa_handler = catcher;
217 sigemptyset(&nact.sa_mask);
218 nact.sa_flags = SA_RESTART;
219
220 if (sigaction(SIGPIPE, &nact, NULL) == -1) {
221 SCDLog(LOG_ERR,
222 CFSTR("sigaction(SIGPIPE, ...) failed: %s"),
223 strerror(errno));
224 }
225
226 /* get set */
227
228 objc_setMultithreaded(YES);
229
230 if (testBundle == NULL) {
231 /* initialize primary (cache management) thread */
232 server_init();
233
234 /* load/initialize/start bundles into the secondary thread */
235 if (loadBundles) {
236 plugin_init();
237 } else {
238 if (!SCDOptionGet(NULL, kSCDOptionDebug)) {
239 /* synchronize with parent process */
240 kill(getppid(), SIGTERM);
241 }
242 }
243 }
244
245 /* go */
246
247 if (testBundle == NULL) {
248 /* start primary (cache management) thread */
249 server_loop();
250 } else {
251 /* load/initialize/start specified plug-in */
252 plugin_exec((void *)testBundle);
253 }
254
255 exit (EX_OK); // insure the process exit status is 0
256 return 0; // ...and make main fit the ANSI spec.
257}