root/src/stratcond.c

Revision 379bcaf4955fc4c5eacc375218033eb41602a152, 9.9 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 4 years ago)

rework stratcon's startup sequence to look like noit's, refs #319

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007-2010, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials provided
14  *       with the distribution.
15  *     * Neither the name OmniTI Computer Consulting, Inc. nor the names
16  *       of its contributors may be used to endorse or promote products
17  *       derived from this software without specific prior written
18  *       permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "noit_defines.h"
34
35 #include <assert.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <limits.h>
42
43 #include "eventer/eventer.h"
44 #include "utils/noit_log.h"
45 #include "utils/noit_hash.h"
46 #include "utils/noit_security.h"
47 #include "utils/noit_watchdog.h"
48 #include "utils/noit_lockfile.h"
49 #include "noit_listener.h"
50 #include "noit_console.h"
51 #include "noit_module.h"
52 #include "noit_conf.h"
53 #include "noit_rest.h"
54 #include "noit_capabilities_listener.h"
55 #include "stratcon_jlog_streamer.h"
56 #include "stratcon_datastore.h"
57 #include "stratcon_iep.h"
58 #include "stratcon_realtime_http.h"
59
60 #define APPNAME "stratcon"
61 static char *config_file = ETC_DIR "/" APPNAME ".conf";
62 static const char *droptouser = NULL;
63 static const char *droptogroup = NULL;
64 static const char *chrootpath = NULL;
65 static int foreground = 0;
66 static int debug = 0;
67 static int strict_module_load = 0;
68 static char **enable_logs;
69 static int enable_logs_cnt = 0;
70 static char **disable_logs;
71 static int disable_logs_cnt = 0;
72 static char *glider = NULL;
73
74 #include "man/stratcond.usage.h"
75 static void usage(const char *progname) {
76   printf("Usage for %s:\n", progname);
77 #ifdef STRATCOND_USAGE
78   assert(write(STDOUT_FILENO,
79               STRATCOND_USAGE,
80               sizeof(STRATCOND_USAGE)-1) == sizeof(STRATCOND_USAGE)-1);
81 #else
82   printf("\nError in usage, build problem.\n");
83 #endif
84   return;
85 }
86
87 void cli_log_switches() {
88   int i;
89   noit_log_stream_t ls;
90   for(i=0; i<enable_logs_cnt; i++) {
91     ls = noit_log_stream_find(enable_logs[i]);
92     if(!ls) noitL(noit_error, "No such log: '%s'\n", enable_logs[i]);
93     if(ls && !ls->enabled) {
94       noitL(noit_error, "Enabling %s\n", enable_logs[i]);
95       ls->enabled = 1;
96     }
97   }
98   for(i=0; i<disable_logs_cnt; i++) {
99     ls = noit_log_stream_find(disable_logs[i]);
100     if(!ls) noitL(noit_error, "No such log: '%s'\n", enable_logs[i]);
101     if(ls && ls->enabled) {
102       noitL(noit_error, "Disabling %s\n", disable_logs[i]);
103       ls->enabled = 0;
104     }
105   }
106 }
107 void parse_clargs(int argc, char **argv) {
108   int c;
109   enable_logs = calloc(argc, sizeof(*enable_logs));
110   disable_logs = calloc(argc, sizeof(*disable_logs));
111   while((c = getopt(argc, argv, "Mrshc:dDu:g:t:l:L:G:")) != EOF) {
112     switch(c) {
113       case 'M':
114         strict_module_load = 1;
115         break;
116       case 'G':
117         glider = strdup(optarg);
118         break;
119       case 'l':
120         enable_logs[enable_logs_cnt++] = strdup(optarg);
121         break;
122       case 'L':
123         disable_logs[disable_logs_cnt++] = strdup(optarg);
124         break;
125       case 'r':
126         stratcon_iep_set_enabled(0);
127         break;
128       case 's':
129         stratcon_datastore_set_enabled(0);
130         break;
131       case 'h':
132         usage(argv[0]);
133         exit(1);
134         break;
135       case 'u':
136         droptouser = strdup(optarg);
137         break;
138       case 'g':
139         droptogroup = strdup(optarg);
140         break;
141       case 't':
142         chrootpath = strdup(optarg);
143         break;
144       case 'c':
145         config_file = strdup(optarg);
146         break;
147       case 'd':
148         debug++;
149         break;
150       case 'D':
151         foreground = 1;
152         break;
153       default:
154         break;
155     }
156   }
157 }
158
159 static
160 int configure_eventer() {
161   int rv = 0;
162   noit_hash_table *table;
163   table = noit_conf_get_hash(NULL, "/" APPNAME "/eventer/config");
164   if(table) {
165     noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
166     const char *key, *value;
167     int klen;
168     while(noit_hash_next_str(table, &iter, &key, &klen, &value)) {
169       int subrv;
170       if((subrv = eventer_propset(key, value)) != 0)
171         rv = subrv;
172     }
173     noit_hash_destroy(table, free, free);
174     free(table);
175   }
176   return rv;
177 }
178
179 static int child_main() {
180   char conf_str[1024];
181
182   /* Next (re)load the configs */
183   if(noit_conf_load(config_file) == -1) {
184     fprintf(stderr, "Cannot load config: '%s'\n", config_file);
185     exit(2);
186   }
187
188   noit_log_reopen_all();
189
190   /* Lastly, run through all other system inits */
191   if(!noit_conf_get_stringbuf(NULL, "/" APPNAME "/eventer/@implementation",
192                               conf_str, sizeof(conf_str))) {
193     noitL(noit_stderr, "Cannot find '%s' in configuration\n",
194           "/" APPNAME "/eventer/@implementation");
195     exit(2);
196   }
197   if(eventer_choose(conf_str) == -1) {
198     noitL(noit_stderr, "Cannot choose eventer %s\n", conf_str);
199     exit(2);
200   }
201   if(configure_eventer() != 0) {
202     noitL(noit_stderr, "Cannot configure eventer\n");
203     exit(2);
204   }
205   if(eventer_init() == -1) {
206     noitL(noit_stderr, "Cannot init eventer %s\n", conf_str);
207     exit(2);
208   }
209   /* rotation init requires, eventer_init() */
210   noit_conf_log_init_rotate(APPNAME, noit_false);
211
212   noit_watchdog_child_eventer_heartbeat();
213
214   noit_console_init(APPNAME);
215   noit_console_conf_init();
216   noit_http_rest_init();
217   stratcon_realtime_http_init(APPNAME);
218   noit_capabilities_listener_init();
219   noit_listener_init(APPNAME);
220
221   noit_module_init();
222   if(strict_module_load && noit_module_load_failures() > 0) {
223     noitL(noit_stderr, "Failed to load some modules and -M given.\n");
224     exit(2);
225   }
226
227   if(stratcon_datastore_get_enabled())
228     stratcon_datastore_init();
229
230   /* Drop privileges */
231   if(chrootpath && noit_security_chroot(chrootpath)) {
232     noitL(noit_stderr, "Failed to chroot(), exiting.\n");
233     exit(-1);
234   }
235   if(noit_security_usergroup(droptouser, droptogroup, noit_false)) {
236     noitL(noit_stderr, "Failed to drop privileges, exiting.\n");
237     exit(-1);
238   }
239
240   stratcon_jlog_streamer_init(APPNAME);
241
242   if(stratcon_iep_get_enabled())
243     stratcon_iep_init();
244   if(stratcon_datastore_get_enabled()) {
245     /* Write our log out, and setup a watchdog to write it out on change. */
246     stratcon_datastore_saveconfig(NULL);
247     noit_conf_coalesce_changes(10); /* 10 seconds of no changes before we write */
248   }
249   else
250     noit_conf_coalesce_changes(INT_MAX);
251
252   noit_conf_watch_and_journal_watchdog(stratcon_datastore_saveconfig, NULL);
253
254   eventer_loop();
255   return 0;
256 }
257
258 int main(int argc, char **argv) {
259   int fd, lockfd = -1;
260   char lockfile[PATH_MAX];
261   char user[32], group[32];
262   char *trace_dir = NULL;
263   parse_clargs(argc, argv);
264
265   noit_log_init();
266   noit_log_stream_add_stream(noit_debug, noit_stderr);
267   noit_log_stream_add_stream(noit_error, noit_stderr);
268
269   /* Next load the configs */
270   noit_conf_init(APPNAME);
271   if(noit_conf_load(config_file) == -1) {
272     fprintf(stderr, "Cannot load config: '%s'\n", config_file);
273     exit(-1);
274   }
275
276   /* Reinitialize the logging system now that we have a config */
277   snprintf(user, sizeof(user), "%d", getuid());
278   snprintf(group, sizeof(group), "%d", getgid());
279   if(noit_security_usergroup(droptouser, droptogroup, noit_true)) {
280     noitL(noit_stderr, "Failed to drop privileges, exiting.\n");
281     exit(-1);
282   }
283   noit_conf_log_init(APPNAME);
284   cli_log_switches();
285   if(noit_security_usergroup(user, group, noit_true)) {
286     noitL(noit_stderr, "Failed to regain privileges, exiting.\n");
287     exit(-1);
288   }
289   if(debug)
290     noit_debug->enabled = 1;
291
292   if(!glider) noit_conf_get_string(NULL, "/" APPNAME "/watchdog/@glider", &glider);
293   noit_watchdog_glider(glider);
294   noit_conf_get_string(NULL, "/" APPNAME "/watchdog/@tracedir", &trace_dir);
295   if(trace_dir) noit_watchdog_glider_trace_dir(trace_dir);
296
297   if(chdir("/") != 0) {
298     fprintf(stderr, "cannot chdir(\"/\"): %s\n", strerror(errno));
299     exit(2);
300   }
301
302   noit_watchdog_prefork_init();
303
304   /* Acquire the lock so that we can throw an error if it doesn't work.
305    * If we've started -D, we'll have the lock.
306    * If not we will daemon and must reacquire the lock.
307    */
308   lockfd = -1;
309   lockfile[0] = '\0';
310   if(noit_conf_get_stringbuf(NULL, "/" APPNAME "/@lockfile",
311                              lockfile, sizeof(lockfile))) {
312     if((lockfd = noit_lockfile_acquire(lockfile)) < 0) {
313       noitL(noit_stderr, "Failed to acquire lock: %s\n", lockfile);
314       exit(-1);
315     }
316   }
317
318   if(foreground) exit(child_main());
319
320   /* This isn't inherited across forks... */
321   if(lockfd >= 0) noit_lockfile_release(lockfd);
322
323   fd = open("/dev/null", O_RDWR);
324   dup2(fd, STDIN_FILENO);
325   dup2(fd, STDOUT_FILENO);
326   dup2(fd, STDERR_FILENO);
327   if(fork()) exit(0);
328   setsid();
329   if(fork()) exit(0);
330
331   /* Reacquire the lock */
332   if(*lockfile) {
333     if(noit_lockfile_acquire(lockfile) < 0) {
334       noitL(noit_stderr, "Failed to acquire lock: %s\n", lockfile);
335       exit(-1);
336     }
337   }
338
339   return noit_watchdog_start_child("stratcond", child_main, 0);
340 }
Note: See TracBrowser for help on using the browser.