root/src/stratcond.c

Revision 35d80a0f98b37605f57c21fbd5751fce4958910f, 8.4 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 4 years ago)

fixes #244

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007-2009, 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 "noit_listener.h"
49 #include "noit_console.h"
50 #include "noit_module.h"
51 #include "noit_conf.h"
52 #include "noit_rest.h"
53 #include "noit_capabilities_listener.h"
54 #include "stratcon_jlog_streamer.h"
55 #include "stratcon_datastore.h"
56 #include "stratcon_iep.h"
57 #include "stratcon_realtime_http.h"
58
59 #define APPNAME "stratcon"
60 static char *config_file = ETC_DIR "/" APPNAME ".conf";
61 static const char *droptouser = NULL;
62 static const char *droptogroup = NULL;
63 static const char *chrootpath = NULL;
64 static int foreground = 0;
65 static int debug = 0;
66 static int strict_module_load = 0;
67 static char **enable_logs;
68 static int enable_logs_cnt = 0;
69 static char **disable_logs;
70 static int disable_logs_cnt = 0;
71
72 #include "man/stratcond.usage.h"
73 static void usage(const char *progname) {
74   printf("Usage for %s:\n", progname);
75 #ifdef STRATCOND_USAGE
76   assert(write(STDOUT_FILENO,
77               STRATCOND_USAGE,
78               sizeof(STRATCOND_USAGE)-1) == sizeof(STRATCOND_USAGE)-1);
79 #else
80   printf("\nError in usage, build problem.\n");
81 #endif
82   return;
83 }
84
85 void cli_log_switches() {
86   int i;
87   noit_log_stream_t ls;
88   for(i=0; i<enable_logs_cnt; i++) {
89     ls = noit_log_stream_find(enable_logs[i]);
90     if(!ls) noitL(noit_error, "No such log: '%s'\n", enable_logs[i]);
91     if(ls && !ls->enabled) {
92       noitL(noit_error, "Enabling %s\n", enable_logs[i]);
93       ls->enabled = 1;
94     }
95   }
96   for(i=0; i<disable_logs_cnt; i++) {
97     ls = noit_log_stream_find(disable_logs[i]);
98     if(!ls) noitL(noit_error, "No such log: '%s'\n", enable_logs[i]);
99     if(ls && ls->enabled) {
100       noitL(noit_error, "Disabling %s\n", disable_logs[i]);
101       ls->enabled = 0;
102     }
103   }
104 }
105 void parse_clargs(int argc, char **argv) {
106   int c;
107   enable_logs = calloc(argc, sizeof(*enable_logs));
108   disable_logs = calloc(argc, sizeof(*disable_logs));
109   while((c = getopt(argc, argv, "Mrshc:dDu:g:t:l:L:")) != EOF) {
110     switch(c) {
111       case 'M':
112         strict_module_load = 1;
113         break;
114       case 'l':
115         enable_logs[enable_logs_cnt++] = strdup(optarg);
116         break;
117       case 'L':
118         disable_logs[disable_logs_cnt++] = strdup(optarg);
119         break;
120       case 'r':
121         stratcon_iep_set_enabled(0);
122         break;
123       case 's':
124         stratcon_datastore_set_enabled(0);
125         break;
126       case 'h':
127         usage(argv[0]);
128         exit(1);
129         break;
130       case 'u':
131         droptouser = strdup(optarg);
132         break;
133       case 'g':
134         droptogroup = strdup(optarg);
135         break;
136       case 't':
137         chrootpath = strdup(optarg);
138         break;
139       case 'c':
140         config_file = strdup(optarg);
141         break;
142       case 'd':
143         debug++;
144         break;
145       case 'D':
146         foreground = 1;
147         break;
148       default:
149         break;
150     }
151   }
152 }
153
154 static
155 int configure_eventer() {
156   int rv = 0;
157   noit_hash_table *table;
158   table = noit_conf_get_hash(NULL, "/" APPNAME "/eventer/config");
159   if(table) {
160     noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
161     const char *key, *value;
162     int klen;
163     while(noit_hash_next_str(table, &iter, &key, &klen, &value)) {
164       int subrv;
165       if((subrv = eventer_propset(key, value)) != 0)
166         rv = subrv;
167     }
168     noit_hash_destroy(table, free, free);
169     free(table);
170   }
171   return rv;
172 }
173
174 static int child_main() {
175   char conf_str[1024];
176   char user[32], group[32];
177
178   /* First initialize logging, so we can log errors */
179   noit_log_init();
180   noit_log_stream_add_stream(noit_debug, noit_stderr);
181   noit_log_stream_add_stream(noit_error, noit_stderr);
182
183   /* Next load the configs */
184   noit_conf_init(APPNAME);
185   if(noit_conf_load(config_file) == -1) {
186     fprintf(stderr, "Cannot load config: '%s'\n", config_file);
187     exit(2);
188   }
189
190   /* Reinitialize the logging system now that we have a config */
191   snprintf(user, sizeof(user), "%d", getuid());
192   snprintf(group, sizeof(group), "%d", getgid());
193   if(noit_security_usergroup(droptouser, droptogroup, noit_true)) {
194     noitL(noit_stderr, "Failed to drop privileges, exiting.\n");
195     exit(2);
196   }
197   noit_conf_log_init(APPNAME);
198   cli_log_switches();
199   if(noit_security_usergroup(user, group, noit_true)) {
200     noitL(noit_stderr, "Failed to regain privileges, exiting.\n");
201     exit(2);
202   }
203   if(debug)
204     noit_debug->enabled = 1;
205
206   /* Lastly, run through all other system inits */
207   if(!noit_conf_get_stringbuf(NULL, "/" APPNAME "/eventer/@implementation",
208                               conf_str, sizeof(conf_str))) {
209     noitL(noit_stderr, "Cannot find '%s' in configuration\n",
210           "/" APPNAME "/eventer/@implementation");
211     exit(2);
212   }
213   if(eventer_choose(conf_str) == -1) {
214     noitL(noit_stderr, "Cannot choose eventer %s\n", conf_str);
215     exit(2);
216   }
217   if(configure_eventer() != 0) {
218     noitL(noit_stderr, "Cannot configure eventer\n");
219     exit(2);
220   }
221   if(eventer_init() == -1) {
222     noitL(noit_stderr, "Cannot init eventer %s\n", conf_str);
223     exit(2);
224   }
225
226   noit_watchdog_child_eventer_heartbeat();
227
228   noit_console_init(APPNAME);
229   noit_console_conf_init();
230   noit_http_rest_init();
231   stratcon_realtime_http_init(APPNAME);
232   noit_capabilities_listener_init();
233   noit_listener_init(APPNAME);
234
235   noit_module_init();
236   if(strict_module_load && noit_module_load_failures() > 0) {
237     noitL(noit_stderr, "Failed to load some modules and -M given.\n");
238     exit(2);
239   }
240
241   if(stratcon_datastore_get_enabled())
242     stratcon_datastore_init();
243
244   /* Drop privileges */
245   if(chrootpath && noit_security_chroot(chrootpath)) {
246     noitL(noit_stderr, "Failed to chroot(), exiting.\n");
247     exit(-1);
248   }
249   if(noit_security_usergroup(droptouser, droptogroup, noit_false)) {
250     noitL(noit_stderr, "Failed to drop privileges, exiting.\n");
251     exit(-1);
252   }
253
254   if(stratcon_iep_get_enabled())
255     stratcon_iep_init();
256   if(stratcon_datastore_get_enabled()) {
257     stratcon_jlog_streamer_init(APPNAME);
258     /* Write our log out, and setup a watchdog to write it out on change. */
259     stratcon_datastore_saveconfig(NULL);
260     noit_conf_coalesce_changes(10); /* 10 seconds of no changes before we write */
261   }
262   else
263     noit_conf_coalesce_changes(INT_MAX);
264
265   noit_conf_watch_and_journal_watchdog(stratcon_datastore_saveconfig, NULL);
266
267   eventer_loop();
268   return 0;
269 }
270
271 int main(int argc, char **argv) {
272   parse_clargs(argc, argv);
273
274   if(chdir("/") != 0) {
275     fprintf(stderr, "cannot chdir(\"/\"): %s\n", strerror(errno));
276     exit(2);
277   }
278
279   noit_watchdog_prefork_init();
280
281   if(foreground) exit(child_main());
282
283   close(STDIN_FILENO);
284   close(STDOUT_FILENO);
285   close(STDERR_FILENO);
286   if(fork()) exit(0);
287   setsid();
288   if(fork()) exit(0);
289
290   return noit_watchdog_start_child("stratcond", child_main, 0);
291 }
Note: See TracBrowser for help on using the browser.