ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/trunk/src/main.c
Revision: 6018
Committed: Sun May 31 14:08:36 2015 UTC (10 years, 3 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

# User Rev Content
1 michael 5052 /*
2 michael 5351 * 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 michael 5052
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 michael 5333 #include "memory.h"
45 michael 5052 #include "main.h"
46    
47    
48 michael 5217 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 michael 5052
52 michael 5217 static struct sigaction ALARMACTION;
53     static struct sigaction INTACTION;
54     static struct sigaction USR1ACTION;
55 michael 5052
56 michael 5930 static const char *CONFNAME = DEFAULTNAME;
57 michael 5072 static const char *CONFDIR = HOPM_ETCDIR;
58     static const char *LOGDIR = HOPM_LOGDIR;
59 michael 5217 static char *CONFFILE, *LOGFILE;
60 michael 5052
61 michael 5217 unsigned int OPT_DEBUG = 0; /* Debug level */
62 michael 5052
63 michael 5217
64     static void
65     do_signal(int signum)
66 michael 5052 {
67 michael 5217 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 michael 5052
83 michael 5217 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 michael 5052
91 michael 5217 while (1)
92     {
93     int c = getopt(argc, argv, "dc:");
94 michael 5052
95 michael 5217 if (c == -1)
96     break;
97 michael 5052
98 michael 5217 switch (c)
99     {
100     case 'c':
101     CONFNAME = xstrdup(optarg);
102     break;
103     case 'd':
104 michael 5219 ++OPT_DEBUG;
105 michael 5217 break;
106     default: /* Unknown arg, guess we'll just do nothing for now. */
107     break;
108     }
109     }
110 michael 5052
111 michael 5217 lenc = strlen(CONFDIR) + strlen(CONFNAME) + strlen(CONFEXT) + 3;
112     lenl = strlen(LOGDIR) + strlen(CONFNAME) + strlen(LOGEXT) + 3;
113 michael 5052
114 michael 5274 CONFFILE = xcalloc(lenc * sizeof *CONFFILE);
115     LOGFILE = xcalloc(lenl * sizeof *LOGFILE);
116 michael 5052
117 michael 5217 snprintf(CONFFILE, lenc, "%s/%s.%s", CONFDIR, CONFNAME, CONFEXT);
118     snprintf(LOGFILE, lenl, "%s/%s.%s", LOGDIR, CONFNAME, LOGEXT);
119 michael 5052
120 michael 5217 /* Fork off. */
121 michael 5219 if (OPT_DEBUG == 0)
122 michael 5217 {
123     if ((pid = fork()) < 0)
124     {
125     perror("fork()");
126     exit(EXIT_FAILURE);
127     }
128     else if (pid != 0)
129     _exit(EXIT_SUCCESS);
130 michael 5052
131 michael 5217 /* Get us in our own process group. */
132     if (setpgid(0, 0) < 0)
133     {
134     perror("setpgid()");
135     exit(EXIT_FAILURE);
136     }
137 michael 5052
138 michael 5217 /* Reset file mode. */
139 michael 5724 umask(077); /* umask 077: u=rwx,g=,o= */
140 michael 5052
141 michael 5217 /* Close file descriptors. */
142     close(STDIN_FILENO);
143     close(STDOUT_FILENO);
144     close(STDERR_FILENO);
145 michael 5052
146 michael 5217 log_open(LOGFILE);
147     }
148     else
149     log_printf("MAIN -> Debug level %d", OPT_DEBUG);
150 michael 5052
151 michael 5217 log_printf("MAIN -> HOPM %s started.", VERSION);
152     log_printf("MAIN -> Reading configuration file...");
153 michael 5052
154 michael 5217 config_load(CONFFILE);
155 michael 5052
156 michael 5217 if (OptionsItem->scanlog)
157     scanlog_open(OptionsItem->scanlog);
158 michael 5052
159 michael 5217 pidout = fopen(OptionsItem->pidfile, "w");
160 michael 5052
161 michael 5217 if (pidout)
162     {
163 michael 5323 fprintf(pidout, "%u\n", (unsigned int)getpid());
164 michael 5217 fclose(pidout);
165     }
166     else
167     {
168 michael 6018 log_printf("MAIN -> Error opening pid file %s: %s", OptionsItem->pidfile,
169 michael 5217 strerror(errno));
170     exit(EXIT_FAILURE);
171     }
172 michael 5052
173 michael 5217 /* 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 michael 5052
179 michael 5217 sigaction(SIGALRM, &ALARMACTION, 0);
180     sigaction(SIGINT, &INTACTION, 0);
181     sigaction(SIGUSR1, &USR1ACTION, 0);
182 michael 5052
183 michael 5217 /* Ignore SIGPIPE. */
184     signal(SIGPIPE, SIG_IGN);
185 michael 5052
186 michael 5217 alarm(1);
187 michael 5052
188 michael 5217 while (1)
189     {
190     /* Main cycles */
191     irc_cycle();
192     scan_cycle();
193 michael 5052
194 michael 5217 /* 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 michael 5052
201 michael 5217 log_printf("MAIN -> Restarting process");
202 michael 5052
203 michael 5217 /* Get upper file descriptor limit */
204     if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
205 michael 5052 {
206 michael 5217 log_printf("MAIN RESTART -> getrlimit() error retrieving RLIMIT_NOFILE (%s)", strerror(errno));
207     return 1;
208 michael 5052 }
209    
210 michael 5217 /* 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 michael 5052
214 michael 5217 /* execute new process */
215 michael 5971 if (execv(argv[0], argv) == -1)
216 michael 5217 log_printf("MAIN RESTART -> Execution of \"%s\" failed. ERROR: %s", argv[0], strerror(errno));
217 michael 5052
218 michael 5972 /* Should only get here if execv() failed */
219 michael 5217 RESTART = 0;
220     }
221 michael 5052
222 michael 5217 /* Check for log reopen */
223     if (REOPEN)
224     {
225     log_printf("MAIN -> Caught SIGUSR1, reopening logfiles");
226     log_close();
227     log_open(LOGFILE);
228 michael 5052
229 michael 5217 if (OptionsItem->scanlog)
230 michael 5052 {
231 michael 5217 scanlog_close();
232     scanlog_open(OptionsItem->scanlog);
233 michael 5052 }
234    
235 michael 5217 log_printf("MAIN -> reopened logfiles");
236 michael 5052
237 michael 5217 REOPEN = 0;
238     }
239 michael 5052
240 michael 5217 /* Call 1 second timers */
241     if (ALARMED)
242     {
243     irc_timer();
244     scan_timer();
245     command_timer();
246 michael 5052
247 michael 5217 ALARMED = 0;
248     }
249     }
250 michael 5052
251 michael 5217 if (!OPT_DEBUG)
252     log_close();
253 michael 5052
254 michael 5217 /* If there's no scanlog open then this will do nothing anyway */
255     scanlog_close();
256     return 0;
257 michael 5052 }
258    
259 michael 5217 void
260     main_restart(void)
261 michael 5052 {
262 michael 5217 RESTART = 1;
263 michael 5052 }

Properties

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