ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/trunk/src/main.c
Revision: 5093
Committed: Tue Dec 23 20:21:18 2014 UTC (10 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 6537 byte(s)
Log Message:
- main.c:main(): use our own xstrdup() instead of strdup()

File Contents

# User Rev Content
1 michael 5052 /*
2     Copyright (C) 2002-2003 Erik Fears
3    
4     This program is free software; you can redistribute it and/or
5     modify it under the terms of the GNU General Public License
6     as published by the Free Software Foundation; either version 2
7     of the License, or (at your option) any later version.
8    
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     GNU General Public License for more details.
13    
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16    
17     Foundation, Inc.
18     59 Temple Place - Suite 330
19     Boston, MA 02111-1307, USA.
20    
21     */
22    
23     #include "setup.h"
24    
25     #include <stdio.h>
26     #include <sys/types.h>
27     #include <sys/stat.h>
28     #include <sys/socket.h>
29     #include <netinet/in.h>
30     #include <arpa/inet.h>
31     #include <signal.h>
32     #include <unistd.h>
33     #include <errno.h>
34     #include <sys/resource.h> /* getrlimit */
35     #include <fcntl.h>
36    
37     #ifdef STDC_HEADERS
38     #include <stdlib.h>
39     #include <string.h>
40     #endif
41    
42     #include "compat.h"
43     #include "config.h"
44     #include "extern.h"
45     #include "irc.h"
46     #include "log.h"
47     #include "opercmd.h"
48     #include "scan.h"
49     #include "stats.h"
50     #include "negcache.h"
51     #include "options.h"
52     #include "malloc.h"
53     #include "firedns.h"
54     #include "main.h"
55    
56    
57     static RETSIGTYPE do_signal(int signum);
58    
59     int RESTART = 0; /* Flagged to restart on next cycle */
60     int ALARMED = 0; /* Flagged to call timer functions on next cycle */
61     int REOPEN = 0; /* Flagged to reopen log files on next cycle */
62     unsigned int OPT_DEBUG = 0; /* Debug level */
63    
64     char *CONFNAME = DEFAULTNAME;
65 michael 5072 static const char *CONFDIR = HOPM_ETCDIR;
66     static const char *LOGDIR = HOPM_LOGDIR;
67 michael 5052 char *CONFFILE, *LOGFILE;
68    
69     struct sigaction ALARMACTION;
70     struct sigaction INTACTION;
71     struct sigaction USR1ACTION;
72    
73 michael 5082 int main(int argc, char *argv[])
74 michael 5052 {
75     pid_t pid;
76     int c;
77 michael 5072 size_t lenc, lenl;
78     unsigned int i;
79 michael 5052 FILE *pidout;
80     struct rlimit rlim;
81    
82     while (1)
83     {
84     c = getopt(argc, argv, "dc:");
85    
86     if (c == -1)
87     break;
88    
89     switch (c)
90     {
91     case 'c':
92 michael 5093 CONFNAME = xstrdup(optarg);
93 michael 5052 break;
94     case 'd':
95     OPT_DEBUG++;
96     break;
97     case '?':
98     default:
99     /* Unknown arg, guess we'll just do nothing for now. */
100     break;
101     }
102     }
103    
104     lenc = strlen(CONFDIR) + strlen(CONFNAME) + strlen(CONFEXT) + 3;
105     lenl = strlen(LOGDIR) + strlen(CONFNAME) + strlen(LOGEXT) + 3;
106    
107     CONFFILE = MyMalloc(lenc * sizeof *CONFFILE);
108     LOGFILE = MyMalloc(lenl * sizeof *LOGFILE);
109    
110     snprintf(CONFFILE, lenc, "%s/%s.%s", CONFDIR, CONFNAME, CONFEXT);
111     snprintf(LOGFILE, lenl, "%s/%s.%s", LOGDIR, CONFNAME, LOGEXT);
112    
113     /* Fork off. */
114    
115     if (OPT_DEBUG <= 0)
116     {
117     if ((pid = fork()) < 0)
118     {
119     perror("fork()");
120     exit(EXIT_FAILURE);
121     }
122     else if (pid != 0)
123     {
124     _exit(EXIT_SUCCESS);
125     }
126    
127     /* Get us in our own process group. */
128     if (setpgid(0, 0) < 0)
129     {
130     perror("setpgid()");
131     exit(EXIT_FAILURE);
132     }
133    
134     /* Reset file mode. */
135     /* shasta: o+w is BAD, mmkay? */
136     umask(002);
137    
138     /* Close file descriptors. */
139     close(STDIN_FILENO);
140     close(STDOUT_FILENO);
141     close(STDERR_FILENO);
142    
143     log_open(LOGFILE);
144     }
145     else
146     log_printf("MAIN -> Debug level %d", OPT_DEBUG);
147    
148    
149 michael 5069 log_printf("MAIN -> HOPM %s started.", VERSION);
150 michael 5052 log_printf("MAIN -> Reading configuration file...");
151    
152     config_load(CONFFILE);
153    
154     if (OptionsItem->scanlog)
155     scanlog_open(OptionsItem->scanlog);
156    
157 michael 5082 pidout = fopen(OptionsItem->pidfile, "w");
158 michael 5052
159 michael 5082 if (pidout)
160     {
161     char spid[16];
162 michael 5052
163 michael 5082 snprintf(spid, sizeof(spid), "%u", getpid());
164 michael 5052 fwrite(spid, sizeof(char), strlen(spid), pidout);
165     fclose(pidout);
166 michael 5082 }
167     else
168     {
169     log_printf("MAIN -> Error opening %s: %s", OptionsItem->pidfile,
170     strerror(errno));
171     exit(EXIT_FAILURE);
172     }
173 michael 5052
174     /* Setup alarm & int handlers. */
175    
176     ALARMACTION.sa_handler = &(do_signal);
177     ALARMACTION.sa_flags = SA_RESTART;
178     INTACTION.sa_handler = &(do_signal);
179     USR1ACTION.sa_handler = &(do_signal);
180    
181     sigaction(SIGALRM, &ALARMACTION, 0);
182     sigaction(SIGINT, &INTACTION, 0);
183     sigaction(SIGUSR1, &USR1ACTION, 0);
184    
185     /* Ignore SIGPIPE. */
186     signal(SIGPIPE, SIG_IGN);
187    
188     alarm(1);
189    
190     while (1)
191     {
192    
193    
194     /* Main cycles */
195     irc_cycle();
196     scan_cycle();
197    
198    
199     /* Restart bopm if main_restart() was called (usually happens by m_kill in irc.c) */
200     if(RESTART)
201     {
202     /* If restarted in debug mode, die */
203     if(OPT_DEBUG)
204     return(1);
205    
206     log_printf("MAIN -> Restarting process");
207    
208     /* Get upper file descriptor limit */
209     if(getrlimit(RLIMIT_NOFILE, &rlim) == -1)
210     {
211     log_printf("MAIN RESTART -> getrlimit() error retrieving RLIMIT_NOFILE (%s)", strerror(errno));
212     return(1);
213     }
214    
215     /* Set file descriptors 0-rlim_cur close on exec */
216     for(i = 0; i < rlim.rlim_cur; i++)
217     fcntl(i, F_SETFD, FD_CLOEXEC);
218    
219     /* execute new process */
220     if(execve(argv[0], argv, NULL) == -1)
221     log_printf("MAIN RESTART -> Execution of \"%s\" failed. ERROR: %s", argv[0], strerror(errno));
222    
223     /* Should only get here if execve failed */
224     RESTART = 0;
225     }
226    
227     /* Check for log reopen */
228     if(REOPEN)
229     {
230     log_printf("MAIN -> Caught SIGUSR1, reopening logfiles");
231     log_close();
232     log_open(LOGFILE);
233    
234     if(OptionsItem->scanlog)
235     {
236     scanlog_close();
237     scanlog_open(OptionsItem->scanlog);
238     }
239    
240     log_printf("MAIN -> reopened logfiles");
241    
242     REOPEN = 0;
243     }
244    
245     /* Call 1 second timers */
246     if(ALARMED)
247     {
248     irc_timer();
249     scan_timer();
250     command_timer();
251    
252     ALARMED = 0;
253     }
254    
255    
256     }
257    
258     if (!OPT_DEBUG)
259     log_close();
260    
261     /* If there's no scanlog open then this will do nothing anyway */
262     scanlog_close();
263    
264     return(0);
265     }
266    
267     static void do_signal(int signum)
268     {
269     switch (signum)
270     {
271     case SIGALRM:
272     ALARMED = 1;
273     alarm(1);
274     break;
275     case SIGINT:
276     log_printf("MAIN -> Caught SIGINT, bye!");
277     exit(0);
278     break;
279     case SIGUSR1:
280     REOPEN = 1;
281     break;
282     }
283     }
284    
285    
286     void main_restart(void)
287     {
288     RESTART = 1;
289     }