More missing IPv6 definitions and autoconf checks to make sure it compiles
[tinc] / src / process.c
1 /*
2     process.c -- process management functions
3     Copyright (C) 1999-2002 Ivo Timmermans <ivo@o2w.nl>,
4                   2000-2002 Guus Sliepen <guus@sliepen.eu.org>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20     $Id: process.c,v 1.1.2.53 2003/07/11 16:13:00 guus Exp $
21 */
22
23 #include "config.h"
24
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <signal.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <sys/ioctl.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <sys/wait.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <termios.h>
37
38 #include <pidfile.h>
39 #include <utils.h>
40 #include <xalloc.h>
41
42 #include "conf.h"
43 #include "process.h"
44 #include "subnet.h"
45 #include "device.h"
46 #include "connection.h"
47 #include "device.h"
48 #include "logger.h"
49
50 #include "system.h"
51
52 /* If zero, don't detach from the terminal. */
53 int do_detach = 1;
54
55 extern char *identname;
56 extern char *pidfilename;
57 extern char **g_argv;
58 extern int use_logfile;
59
60 sigset_t emptysigset;
61
62 static int saved_debug_level = -1;
63
64 extern int sighup;
65 extern int sigalrm;
66 extern int do_purge;
67
68 static void memory_full(int size)
69 {
70         logger(DEBUG_ALWAYS, LOG_ERR, _("Memory exhausted (couldn't allocate %d bytes), exitting."), size);
71         cp_trace();
72         exit(1);
73 }
74
75 /* Some functions the less gifted operating systems might lack... */
76
77 #ifndef HAVE_FCLOSEALL
78 static int fcloseall(void)
79 {
80         fflush(stdin);
81         fflush(stdout);
82         fflush(stderr);
83         fclose(stdin);
84         fclose(stdout);
85         fclose(stderr);
86         return 0;
87 }
88 #endif
89
90 /*
91   Close network connections, and terminate neatly
92 */
93 void cleanup_and_exit(int c)
94 {
95         cp();
96
97         close_network_connections();
98
99         if(debug_level > DEBUG_NOTHING)
100                 dump_device_stats();
101
102         logger(DEBUG_ALWAYS, LOG_NOTICE, _("Terminating"));
103
104         closelog();
105         exit(c);
106 }
107
108 /*
109   check for an existing tinc for this net, and write pid to pidfile
110 */
111 static int write_pidfile(void)
112 {
113         int pid;
114
115         cp();
116
117         pid = check_pid(pidfilename);
118
119         if(pid) {
120                 if(netname)
121                         fprintf(stderr, _("A tincd is already running for net `%s' with pid %d.\n"),
122                                         netname, pid);
123                 else
124                         fprintf(stderr, _("A tincd is already running with pid %d.\n"), pid);
125                 return 1;
126         }
127
128         /* if it's locked, write-protected, or whatever */
129         if(!write_pid(pidfilename))
130                 return 1;
131
132         return 0;
133 }
134
135 /*
136   kill older tincd for this net
137 */
138 int kill_other(int signal)
139 {
140         int pid;
141
142         cp();
143
144         pid = read_pid(pidfilename);
145
146         if(!pid) {
147                 if(netname)
148                         fprintf(stderr, _("No other tincd is running for net `%s'.\n"),
149                                         netname);
150                 else
151                         fprintf(stderr, _("No other tincd is running.\n"));
152                 return 1;
153         }
154
155         errno = 0;                                      /* No error, sometimes errno is only changed on error */
156
157         /* ESRCH is returned when no process with that pid is found */
158         if(kill(pid, signal) && errno == ESRCH) {
159                 if(netname)
160                         fprintf(stderr, _("The tincd for net `%s' is no longer running. "),
161                                         netname);
162                 else
163                         fprintf(stderr, _("The tincd is no longer running. "));
164
165                 fprintf(stderr, _("Removing stale lock file.\n"));
166                 remove_pid(pidfilename);
167         }
168
169         return 0;
170 }
171
172 /*
173   Detach from current terminal, write pidfile, kill parent
174 */
175 int detach(void)
176 {
177         cp();
178
179         setup_signals();
180
181         /* First check if we can open a fresh new pidfile */
182
183         if(write_pidfile())
184                 return -1;
185
186         /* If we succeeded in doing that, detach */
187
188         closelog();
189
190         if(do_detach) {
191                 if(daemon(0, 0) < 0) {
192                         fprintf(stderr, _("Couldn't detach from terminal: %s"),
193                                         strerror(errno));
194                         return -1;
195                 }
196
197                 /* Now UPDATE the pid in the pidfile, because we changed it... */
198
199                 if(!write_pid(pidfilename))
200                         return -1;
201         }
202
203         openlogger(identname, use_logfile?LOGMODE_FILE:(do_detach?LOGMODE_SYSLOG:LOGMODE_STDERR));
204
205         logger(DEBUG_ALWAYS, LOG_NOTICE, _("tincd %s (%s %s) starting, debug level %d"),
206                            VERSION, __DATE__, __TIME__, debug_level);
207
208         xalloc_fail_func = memory_full;
209
210         return 0;
211 }
212
213 /*
214   Execute the program name, with sane environment.
215 */
216 static void _execute_script(const char *scriptname, char **envp)
217         __attribute__ ((noreturn));
218 static void _execute_script(const char *scriptname, char **envp)
219 {
220         cp();
221
222         while(*envp)
223                 putenv(*envp++);
224
225         chdir("/");
226
227         closelogger();
228
229         /* Close all file descriptors */
230         fcloseall();
231
232         execl(scriptname, NULL);
233         /* No return on success */
234
235         openlogger(identname, use_logfile?LOGMODE_FILE:(do_detach?LOGMODE_SYSLOG:LOGMODE_STDERR));
236         logger(DEBUG_ALWAYS, LOG_ERR, _("Could not execute `%s': %s"), scriptname,
237                    strerror(errno));
238         exit(errno);
239 }
240
241 /*
242   Fork and execute the program pointed to by name.
243 */
244 int execute_script(const char *name, char **envp)
245 {
246         pid_t pid;
247         int status;
248         struct stat s;
249         char *scriptname;
250
251         cp();
252
253         asprintf(&scriptname, "%s/%s", confbase, name);
254
255         /* First check if there is a script */
256
257         if(stat(scriptname, &s))
258                 return 0;
259
260         pid = fork();
261
262         if(pid < 0) {
263                 logger(DEBUG_ALWAYS, LOG_ERR, _("System call `%s' failed: %s"), "fork",
264                            strerror(errno));
265                 return -1;
266         }
267
268         if(pid) {
269                 logger(DEBUG_STATUS, LOG_INFO, _("Executing script %s"), name);
270
271                 free(scriptname);
272
273                 if(waitpid(pid, &status, 0) == pid) {
274                         if(WIFEXITED(status)) { /* Child exited by itself */
275                                 if(WEXITSTATUS(status)) {
276                                         logger(DEBUG_ALWAYS, LOG_ERR, _("Process %d (%s) exited with non-zero status %d"),
277                                                    pid, name, WEXITSTATUS(status));
278                                         return -1;
279                                 } else
280                                         return 0;
281                         } else if(WIFSIGNALED(status)) {        /* Child was killed by a signal */
282                                 logger(DEBUG_ALWAYS, LOG_ERR, _("Process %d (%s) was killed by signal %d (%s)"), pid,
283                                            name, WTERMSIG(status), strsignal(WTERMSIG(status)));
284                                 return -1;
285                         } else {                        /* Something strange happened */
286                                 logger(DEBUG_ALWAYS, LOG_ERR, _("Process %d (%s) terminated abnormally"), pid,
287                                            name);
288                                 return -1;
289                         }
290                 } else if (errno != EINTR) {
291                         logger(DEBUG_ALWAYS, LOG_ERR, _("System call `%s' failed: %s"), "waitpid",
292                                    strerror(errno));
293                         return -1;
294                 }
295
296                 /* Why do we get EINTR? */
297                 return 0;
298         }
299
300         /* Child here */
301
302         _execute_script(scriptname, envp);
303 }
304
305
306 /*
307   Signal handlers.
308 */
309
310 static RETSIGTYPE sigterm_handler(int a)
311 {
312         logger(DEBUG_ALWAYS, LOG_NOTICE, _("Got TERM signal"));
313
314         cleanup_and_exit(0);
315 }
316
317 static RETSIGTYPE sigquit_handler(int a)
318 {
319         logger(DEBUG_ALWAYS, LOG_NOTICE, _("Got QUIT signal"));
320         cleanup_and_exit(0);
321 }
322
323 static RETSIGTYPE fatal_signal_square(int a)
324 {
325         logger(DEBUG_ALWAYS, LOG_ERR, _("Got another fatal signal %d (%s): not restarting."), a,
326                    strsignal(a));
327         cp_trace();
328         exit(1);
329 }
330
331 static RETSIGTYPE fatal_signal_handler(int a)
332 {
333         struct sigaction act;
334         logger(DEBUG_ALWAYS, LOG_ERR, _("Got fatal signal %d (%s)"), a, strsignal(a));
335         cp_trace();
336
337         if(do_detach) {
338                 logger(DEBUG_ALWAYS, LOG_NOTICE, _("Trying to re-execute in 5 seconds..."));
339
340                 act.sa_handler = fatal_signal_square;
341                 act.sa_mask = emptysigset;
342                 act.sa_flags = 0;
343                 sigaction(SIGSEGV, &act, NULL);
344
345                 close_network_connections();
346                 sleep(5);
347                 remove_pid(pidfilename);
348                 execvp(g_argv[0], g_argv);
349         } else {
350                 logger(DEBUG_ALWAYS, LOG_NOTICE, _("Not restarting."));
351                 exit(1);
352         }
353 }
354
355 static RETSIGTYPE sighup_handler(int a)
356 {
357         logger(DEBUG_ALWAYS, LOG_NOTICE, _("Got HUP signal"));
358         sighup = 1;
359 }
360
361 static RETSIGTYPE sigint_handler(int a)
362 {
363         if(saved_debug_level != -1) {
364                 logger(DEBUG_ALWAYS, LOG_NOTICE, _("Reverting to old debug level (%d)"),
365                         saved_debug_level);
366                 debug_level = saved_debug_level;
367                 saved_debug_level = -1;
368         } else {
369                 logger(DEBUG_ALWAYS, LOG_NOTICE,
370                         _("Temporarily setting debug level to 5.  Kill me with SIGINT again to go back to level %d."),
371                         debug_level);
372                 saved_debug_level = debug_level;
373                 debug_level = 5;
374         }
375 }
376
377 static RETSIGTYPE sigalrm_handler(int a)
378 {
379         logger(DEBUG_ALWAYS, LOG_NOTICE, _("Got ALRM signal"));
380         sigalrm = 1;
381 }
382
383 static RETSIGTYPE sigusr1_handler(int a)
384 {
385         dump_connections();
386 }
387
388 static RETSIGTYPE sigusr2_handler(int a)
389 {
390         dump_device_stats();
391         dump_nodes();
392         dump_edges();
393         dump_subnets();
394 }
395
396 static RETSIGTYPE sigwinch_handler(int a)
397 {
398         extern int do_purge;
399         do_purge = 1;
400 }
401
402 static RETSIGTYPE unexpected_signal_handler(int a)
403 {
404         logger(DEBUG_ALWAYS, LOG_WARNING, _("Got unexpected signal %d (%s)"), a, strsignal(a));
405         cp_trace();
406 }
407
408 static RETSIGTYPE ignore_signal_handler(int a)
409 {
410         logger(DEBUG_SCARY_THINGS, LOG_DEBUG, _("Ignored signal %d (%s)"), a, strsignal(a));
411 }
412
413 static struct {
414         int signal;
415         void (*handler)(int);
416 } sighandlers[] = {
417         {
418         SIGHUP, sighup_handler}, {
419         SIGTERM, sigterm_handler}, {
420         SIGQUIT, sigquit_handler}, {
421         SIGSEGV, fatal_signal_handler}, {
422         SIGBUS, fatal_signal_handler}, {
423         SIGILL, fatal_signal_handler}, {
424         SIGPIPE, ignore_signal_handler}, {
425         SIGINT, sigint_handler}, {
426         SIGUSR1, sigusr1_handler}, {
427         SIGUSR2, sigusr2_handler}, {
428         SIGCHLD, ignore_signal_handler}, {
429         SIGALRM, sigalrm_handler}, {
430         SIGWINCH, sigwinch_handler}, {
431         0, NULL}
432 };
433
434 void setup_signals(void)
435 {
436         int i;
437         struct sigaction act;
438
439         sigemptyset(&emptysigset);
440         act.sa_handler = NULL;
441         act.sa_mask = emptysigset;
442         act.sa_flags = 0;
443
444         /* Set a default signal handler for every signal, errors will be
445            ignored. */
446         for(i = 0; i < NSIG; i++) {
447                 if(!do_detach)
448                         act.sa_handler = SIG_DFL;
449                 else
450                         act.sa_handler = unexpected_signal_handler;
451                 sigaction(i, &act, NULL);
452         }
453
454         /* If we didn't detach, allow coredumps */
455         if(!do_detach)
456                 sighandlers[3].handler = SIG_DFL;
457
458         /* Then, for each known signal that we want to catch, assign a
459            handler to the signal, with error checking this time. */
460         for(i = 0; sighandlers[i].signal; i++) {
461                 act.sa_handler = sighandlers[i].handler;
462                 if(sigaction(sighandlers[i].signal, &act, NULL) < 0)
463                         fprintf(stderr, _("Installing signal handler for signal %d (%s) failed: %s\n"),
464                                         sighandlers[i].signal, strsignal(sighandlers[i].signal),
465                                         strerror(errno));
466         }
467 }