ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/branches/1.0.x/src/main.c
Revision: 6017
Committed: Sun May 31 14:08:19 2015 UTC (8 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 6022 byte(s)
Log Message:
- main.c:main(): improve error message for failed fopen() on the pid file

File Contents

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

Properties

Name Value
svn:eol-style native
svn:keywords Id