root/src/noit_main.c

Revision 9267e43ddfd7b4b47ee778995e83ee06f228731a, 7.0 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 3 years ago)

refactor this into something reusable

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2011, 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 "utils/noit_log.h"
47 #include "noit_conf.h"
48 #include "utils/noit_security.h"
49 #include "utils/noit_watchdog.h"
50 #include "utils/noit_lockfile.h"
51 #include "eventer/eventer.h"
52
53 static char **enable_logs;
54 static int enable_logs_cnt = 0;
55 static char **disable_logs;
56 static int disable_logs_cnt = 0;
57
58 void
59 noit_main_enable_log(const char *name) {
60   enable_logs[enable_logs_cnt++] = strdup(name);
61 }
62 void
63 noit_main_disable_log(const char *name) {
64   disable_logs[disable_logs_cnt++] = strdup(name);
65 }
66 static int
67 configure_eventer(const char *appname) {
68   int rv = 0;
69   noit_hash_table *table;
70   char appscratch[1024];
71
72   snprintf(appscratch, sizeof(appscratch), "/%s/eventer/config", appname);
73   table = noit_conf_get_hash(NULL, appscratch);
74   if(table) {
75     noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
76     const char *key, *value;
77     int klen;
78     while(noit_hash_next_str(table, &iter, &key, &klen, &value)) {
79       int subrv;
80       if((subrv = eventer_propset(key, value)) != 0)
81         rv = subrv;
82     }
83     noit_hash_destroy(table, free, free);
84     free(table);
85   }
86   return rv;
87 }
88
89 void cli_log_switches() {
90   int i;
91   noit_log_stream_t ls;
92   for(i=0; i<enable_logs_cnt; i++) {
93     ls = noit_log_stream_find(enable_logs[i]);
94     if(!ls) noitL(noit_error, "No such log: '%s'\n", enable_logs[i]);
95     if(ls && !ls->enabled) {
96       noitL(noit_error, "Enabling %s\n", enable_logs[i]);
97       ls->enabled = 1;
98     }
99   }
100   for(i=0; i<disable_logs_cnt; i++) {
101     ls = noit_log_stream_find(disable_logs[i]);
102     if(!ls) noitL(noit_error, "No such log: '%s'\n", enable_logs[i]);
103     if(ls && ls->enabled) {
104       noitL(noit_error, "Disabling %s\n", disable_logs[i]);
105       ls->enabled = 0;
106     }
107   }
108 }
109
110 int
111 noit_main(const char *appname,
112           const char *config_filename, int debug, int foreground,
113           const char *_glider,
114           const char *drop_to_user, const char *drop_to_group,
115           int (*passed_child_main)(void)) {
116   int fd, lockfd;
117   char conf_str[1024];
118   char lockfile[PATH_MAX];
119   char user[32], group[32];
120   char *trace_dir = NULL;
121   char appscratch[1024];
122   char *glider = (char *)_glider;
123    
124   /* First initialize logging, so we can log errors */
125   noit_log_init();
126   noit_log_stream_add_stream(noit_debug, noit_stderr);
127   noit_log_stream_add_stream(noit_error, noit_stderr);
128
129   /* Next load the configs */
130   noit_conf_init(appname);
131   if(noit_conf_load(config_filename) == -1) {
132     fprintf(stderr, "Cannot load config: '%s'\n", config_filename);
133     exit(-1);
134   }
135
136   /* Reinitialize the logging system now that we have a config */
137   snprintf(user, sizeof(user), "%d", getuid());
138   snprintf(group, sizeof(group), "%d", getgid());
139   if(noit_security_usergroup(drop_to_user, drop_to_group, noit_true)) {
140     noitL(noit_stderr, "Failed to drop privileges, exiting.\n");
141     exit(-1);
142   }
143   noit_conf_log_init(appname);
144   cli_log_switches();
145   if(noit_security_usergroup(user, group, noit_true)) {
146     noitL(noit_stderr, "Failed to regain privileges, exiting.\n");
147     exit(-1);
148   }
149   if(debug)
150     noit_debug->enabled = 1;
151
152   snprintf(appscratch, sizeof(appscratch), "/%s/watchdog/@glider", appname);
153   if(!glider) noit_conf_get_string(NULL, appscratch, &glider);
154   noit_watchdog_glider(glider);
155   snprintf(appscratch, sizeof(appscratch), "/%s/watchdog/@tracedir", appname);
156   noit_conf_get_string(NULL, appscratch, &trace_dir);
157   if(trace_dir) noit_watchdog_glider_trace_dir(trace_dir);
158
159   /* Lastly, run through all other system inits */
160   snprintf(appscratch, sizeof(appscratch), "/%s/eventer/@implementation", appname);
161   if(!noit_conf_get_stringbuf(NULL, appscratch, conf_str, sizeof(conf_str))) {
162     noitL(noit_stderr, "Cannot find '%s' in configuration\n", appscratch);
163     exit(-1);
164   }
165   if(eventer_choose(conf_str) == -1) {
166     noitL(noit_stderr, "Cannot choose eventer %s\n", conf_str);
167     exit(-1);
168   }
169   if(configure_eventer(appname) != 0) {
170     noitL(noit_stderr, "Cannot configure eventer\n");
171     exit(-1);
172   }
173
174   noit_watchdog_prefork_init();
175
176   if(chdir("/") != 0) {
177     noitL(noit_stderr, "Failed chdir(\"/\"): %s\n", strerror(errno));
178     exit(-1);
179   }
180
181   /* Acquire the lock so that we can throw an error if it doesn't work.
182    * If we've started -D, we'll have the lock.
183    * If not we will daemon and must reacquire the lock.
184    */
185   lockfd = -1;
186   lockfile[0] = '\0';
187   snprintf(appscratch, sizeof(appscratch), "/%s/@lockfile", appname);
188   if(noit_conf_get_stringbuf(NULL, appscratch,
189                              lockfile, sizeof(lockfile))) {
190     if((lockfd = noit_lockfile_acquire(lockfile)) < 0) {
191       noitL(noit_stderr, "Failed to acquire lock: %s\n", lockfile);
192       exit(-1);
193     }
194   }
195
196   if(foreground) return passed_child_main();
197
198   /* This isn't inherited across forks... */
199   if(lockfd >= 0) noit_lockfile_release(lockfd);
200
201   fd = open("/dev/null", O_RDWR);
202   dup2(fd, STDIN_FILENO);
203   dup2(fd, STDOUT_FILENO);
204   dup2(fd, STDERR_FILENO);
205   if(fork()) exit(0);
206   setsid();
207   if(fork()) exit(0);
208
209   /* Reacquire the lock */
210   if(*lockfile) {
211     if(noit_lockfile_acquire(lockfile) < 0) {
212       noitL(noit_stderr, "Failed to acquire lock: %s\n", lockfile);
213       exit(-1);
214     }
215   }
216
217   signal(SIGHUP, SIG_IGN);
218   return noit_watchdog_start_child("noitd", passed_child_main, 0);
219 }
Note: See TracBrowser for help on using the browser.