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