root/src/noitd.c

Revision 670f01e50c4bf8c2e20f6be14acc73b631d91163, 8.0 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 4 years ago)

fixes logfile ownership if -u/-g is specified, refs #205

  • 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 #include "noit_defines.h"
33
34 #include <assert.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <sys/mman.h>
41 #include <signal.h>
42 #ifdef HAVE_SYS_WAIT_H
43 #include <sys/wait.h>
44 #endif
45
46 #include "eventer/eventer.h"
47 #include "utils/noit_log.h"
48 #include "utils/noit_hash.h"
49 #include "utils/noit_security.h"
50 #include "utils/noit_watchdog.h"
51 #include "noit_listener.h"
52 #include "noit_console.h"
53 #include "noit_jlog_listener.h"
54 #include "noit_rest.h"
55 #include "noit_check_rest.h"
56 #include "noit_livestream_listener.h"
57 #include "noit_capabilities_listener.h"
58 #include "noit_module.h"
59 #include "noit_conf.h"
60 #include "noit_conf_checks.h"
61 #include "noit_filters.h"
62
63 #define APPNAME "noit"
64 #define CHILD_WATCHDOG_TIMEOUT 5 /*seconds*/
65
66 static char *config_file = ETC_DIR "/" APPNAME ".conf";
67 static const char *droptouser = NULL;
68 static const char *droptogroup = NULL;
69 static const char *chrootpath = NULL;
70 static int foreground = 0;
71 static int debug = 0;
72
73 #include "man/noitd.usage.h"
74 static void usage(const char *progname) {
75   printf("Usage for %s:\n", progname);
76 #ifdef NOITD_USAGE
77   assert(write(STDOUT_FILENO,
78                NOITD_USAGE,
79                sizeof(NOITD_USAGE)-1) == sizeof(NOITD_USAGE)-1);
80 #else
81   printf("\nError in usage, build problem.\n");
82 #endif
83   return;
84 }
85 void parse_clargs(int argc, char **argv) {
86   int c;
87   while((c = getopt(argc, argv, "hc:dDu:g:t:")) != EOF) {
88     switch(c) {
89       case 'h':
90         usage(argv[0]);
91         exit(1);
92         break;
93       case 'u':
94         droptouser = strdup(optarg);
95         break;
96       case 'g':
97         droptogroup = strdup(optarg);
98         break;
99       case 't':
100         chrootpath = strdup(optarg);
101         break;
102       case 'c':
103         config_file = strdup(optarg);
104         break;
105       case 'D':
106         foreground = 1;
107         break;
108       case 'd':
109         debug++;
110         break;
111       default:
112         break;
113     }
114   }
115 }
116
117 static
118 int configure_eventer() {
119   int rv = 0;
120   noit_hash_table *table;
121   table = noit_conf_get_hash(NULL, "/" APPNAME "/eventer/config");
122   if(table) {
123     noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
124     const char *key, *value;
125     int klen;
126     while(noit_hash_next_str(table, &iter, &key, &klen, &value)) {
127       int subrv;
128       if((subrv = eventer_propset(key, value)) != 0)
129         rv = subrv;
130     }
131     noit_hash_destroy(table, free, free);
132     free(table);
133   }
134   return rv;
135 }
136
137 static int __reload_needed = 0;
138 static void request_conf_reload(int sig) {
139   if(sig == SIGHUP) {
140     __reload_needed = 1;
141   }
142 }
143 static int noitice_hup(eventer_t e, int mask, void *unused, struct timeval *now) {
144   if(__reload_needed) {
145     noitL(noit_error, "SIGHUP received, performing reload\n");
146     if(noit_conf_load(config_file) == -1) {
147       noitL(noit_error, "Cannot load config: '%s'\n", config_file);
148       exit(-1);
149     }
150     noit_poller_reload(NULL);
151     __reload_needed = 0;
152   }
153   return 0;
154 }
155 static int child_main() {
156   eventer_t e;
157
158   /* Load our config...
159    * to ensure it is current w.r.t. to this child starting */
160   if(noit_conf_load(config_file) == -1) {
161     noitL(noit_error, "Cannot load config: '%s'\n", config_file);
162     exit(-1);
163   }
164
165   signal(SIGHUP, request_conf_reload);
166
167   /* initialize the eventer */
168   if(eventer_init() == -1) {
169     noitL(noit_stderr, "Cannot initialize eventer\n");
170     exit(-1);
171   }
172
173   /* Setup our heartbeat */
174   noit_watchdog_child_eventer_heartbeat();
175
176   e = eventer_alloc();
177   e->mask = EVENTER_RECURRENT;
178   e->callback = noitice_hup;
179   eventer_add_recurrent(e);
180
181   /* Initialize all of our listeners */
182   noit_console_init(APPNAME);
183   noit_console_conf_init();
184   noit_console_conf_checks_init();
185   noit_capabilities_listener_init();
186   noit_jlog_listener_init();
187   noit_http_rest_init();
188   noit_check_rest_init();
189   noit_filters_rest_init();
190   noit_livestream_listener_init();
191
192   noit_module_init();
193
194   /* Drop privileges */
195   if(chrootpath && noit_security_chroot(chrootpath)) {
196     noitL(noit_stderr, "Failed to chroot(), exiting.\n");
197     exit(2);
198   }
199   if(noit_security_usergroup(droptouser, droptogroup, noit_false)) {
200     noitL(noit_stderr, "Failed to drop privileges, exiting.\n");
201     exit(2);
202   }
203
204   /* Prepare for launch... */
205   noit_filters_init();
206   noit_poller_init();
207   noit_listener_init(APPNAME);
208
209   /* Write our log out, and setup a watchdog to write it out on change. */
210   noit_conf_write_log(NULL);
211   noit_conf_coalesce_changes(10); /* 10 seconds of no changes before we write */
212   noit_conf_watch_and_journal_watchdog(noit_conf_write_log, NULL);
213
214   eventer_loop();
215   return 0;
216 }
217
218 int main(int argc, char **argv) {
219   char conf_str[1024];
220   char user[32], group[32];
221
222   parse_clargs(argc, argv);
223
224   /* First initialize logging, so we can log errors */
225   noit_log_init();
226   noit_log_stream_add_stream(noit_debug, noit_stderr);
227   noit_log_stream_add_stream(noit_error, noit_stderr);
228
229   /* Next load the configs */
230   noit_conf_init(APPNAME);
231   if(noit_conf_load(config_file) == -1) {
232     fprintf(stderr, "Cannot load config: '%s'\n", config_file);
233   }
234
235   /* Reinitialize the logging system now that we have a config */
236   snprintf(user, sizeof(user), "%d", getuid());
237   snprintf(group, sizeof(group), "%d", getgid());
238   if(noit_security_usergroup(droptouser, droptogroup, noit_true)) {
239     noitL(noit_stderr, "Failed to drop privileges, exiting.\n");
240     exit(-1);
241   }
242   noit_conf_log_init(APPNAME);
243   if(noit_security_usergroup(user, group, noit_true)) {
244     noitL(noit_stderr, "Failed to regain privileges, exiting.\n");
245     exit(-1);
246   }
247   if(debug)
248     noit_debug->enabled = 1;
249
250   /* Lastly, run through all other system inits */
251   if(!noit_conf_get_stringbuf(NULL, "/" APPNAME "/eventer/@implementation",
252                               conf_str, sizeof(conf_str))) {
253     noitL(noit_stderr, "Cannot find '%s' in configuration\n",
254           "/" APPNAME "/eventer/@implementation");
255     exit(-1);
256   }
257   if(eventer_choose(conf_str) == -1) {
258     noitL(noit_stderr, "Cannot choose eventer %s\n", conf_str);
259     exit(-1);
260   }
261   if(configure_eventer() != 0) {
262     noitL(noit_stderr, "Cannot configure eventer\n");
263     exit(-1);
264   }
265
266   noit_watchdog_prefork_init();
267
268   if(chdir("/") != 0) {
269     noitL(noit_stderr, "Failed chdir(\"/\"): %s\n", strerror(errno));
270     exit(-1);
271   }
272   if(foreground) return child_main();
273
274   close(STDIN_FILENO);
275   close(STDOUT_FILENO);
276   close(STDERR_FILENO);
277   if(fork()) exit(0);
278   setsid();
279   if(fork()) exit(0);
280
281   signal(SIGHUP, SIG_IGN);
282   return noit_watchdog_start_child("noitd", child_main, 0);
283 }
Note: See TracBrowser for help on using the browser.