- Let user choose whether keys are in the config files or separate
[tinc] / src / process.c
1 /*
2     process.c -- process management functions
3     Copyright (C) 1999,2000 Ivo Timmermans <itimmermans@bigfoot.com>,
4                        2000 Guus Sliepen <guus@sliepen.warande.net>
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.18 2001/01/05 23:53:51 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/wait.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <termios.h>
37
38 #include <list.h>
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 "connection.h"
47
48 #include "system.h"
49
50 /* If zero, don't detach from the terminal. */
51 int do_detach = 1;
52
53 extern char *identname;
54 extern char *pidfilename;
55 extern char **g_argv;
56
57 sigset_t emptysigset;
58
59 void memory_full(int size)
60 {
61   syslog(LOG_ERR, _("Memory exhausted (couldn't allocate %d bytes), exiting."), size);
62   cp_trace();
63   exit(1);
64 }
65
66 /* Some functions the less gifted operating systems might lack... */
67
68 #ifndef HAVE_FCLOSEALL
69 int fcloseall(void)
70 {
71   fflush(stdin);
72   fflush(stdout);
73   fflush(stderr);
74   fclose(stdin);
75   fclose(stdout);
76   fclose(stderr);
77 }
78 #endif
79
80 /*
81   Close network connections, and terminate neatly
82 */
83 void cleanup_and_exit(int c)
84 {
85 cp
86   close_network_connections();
87
88   if(debug_lvl > DEBUG_NOTHING)
89     syslog(LOG_INFO, _("Total bytes written: tap %d, socket %d; bytes read: tap %d, socket %d"),
90            total_tap_out, total_socket_out, total_tap_in, total_socket_in);
91
92   syslog(LOG_NOTICE, _("Terminating"));
93
94   closelog();
95   exit(c);
96 }
97
98 /*
99   check for an existing tinc for this net, and write pid to pidfile
100 */
101 int write_pidfile(void)
102 {
103   int pid;
104 cp
105   if((pid = check_pid(pidfilename)))
106     {
107       if(netname)
108         fprintf(stderr, _("A tincd is already running for net `%s' with pid %d.\n"),
109                 netname, pid);
110       else
111         fprintf(stderr, _("A tincd is already running with pid %d.\n"), pid);
112       return 1;
113     }
114
115   /* if it's locked, write-protected, or whatever */
116   if(!write_pid(pidfilename))
117     return 1;
118 cp
119   return 0;
120 }
121
122 /*
123   kill older tincd for this net
124 */
125 int kill_other(void)
126 {
127   int pid;
128 cp
129   if(!(pid = read_pid(pidfilename)))
130     {
131       if(netname)
132         fprintf(stderr, _("No other tincd is running for net `%s'.\n"), netname);
133       else
134         fprintf(stderr, _("No other tincd is running.\n"));
135       return 1;
136     }
137
138   errno = 0;    /* No error, sometimes errno is only changed on error */
139   /* ESRCH is returned when no process with that pid is found */
140   if(kill(pid, SIGTERM) && errno == ESRCH)
141     fprintf(stderr, _("Removing stale lock file.\n"));
142   remove_pid(pidfilename);
143 cp
144   return 0;
145 }
146
147 /*
148   Detach from current terminal, write pidfile, kill parent
149 */
150 int detach(void)
151 {
152 cp
153   setup_signals();
154
155   /* First check if we can open a fresh new pidfile */
156   
157   if(write_pidfile())
158     return -1;
159
160   /* If we succeeded in doing that, detach */
161
162   closelog();
163
164   if(do_detach)
165     {
166       if(daemon(0, 0) < 0)
167         {
168           fprintf(stderr, _("Couldn't detach from terminal: %m"));
169           return -1;
170         }
171
172       /* Now UPDATE the pid in the pidfile, because we changed it... */
173       
174       if(!write_pid(pidfilename))
175         return -1;
176     }
177   
178   openlog(identname, LOG_CONS | LOG_PID, LOG_DAEMON);
179
180   if(debug_lvl > DEBUG_NOTHING)
181     syslog(LOG_NOTICE, _("tincd %s (%s %s) starting, debug level %d"),
182            VERSION, __DATE__, __TIME__, debug_lvl);
183   else
184     syslog(LOG_NOTICE, _("tincd %s starting"), VERSION);
185
186   xalloc_fail_func = memory_full;
187 cp
188   return 0;
189 }
190
191 /*
192   Execute the program name, with sane environment.  All output will be
193   redirected to syslog.
194 */
195 void _execute_script(const char *name)  __attribute__ ((noreturn));
196 void _execute_script(const char *name)
197 {
198   char *scriptname;
199   char *s;
200 cp
201   if(netname)
202     {
203       asprintf(&s, "NETNAME=%s", netname);
204       putenv(s);        /* Don't free s! see man 3 putenv */
205     }
206 #ifdef HAVE_UNSETENV
207   else
208     {
209       unsetenv("NETNAME");
210     }
211 #endif
212
213   chdir("/");
214   
215   asprintf(&scriptname, "%s/%s", confbase, name);
216
217   /* Close all file descriptors */
218   closelog();           /* <- this means we cannot use syslog() here anymore! */
219   fcloseall();
220
221   execl(scriptname, NULL);
222   /* No return on success */
223   
224   if(errno != ENOENT)   /* Ignore if the file does not exist */
225     exit(-1);           /* Some error while trying execl(). */
226   else
227     exit(0);
228 }
229
230 /*
231   Fork and execute the program pointed to by name.
232 */
233 int execute_script(const char *name)
234 {
235   pid_t pid;
236   int status;
237 cp
238   if((pid = fork()) < 0)
239     {
240       syslog(LOG_ERR, _("System call `%s' failed: %m"),
241              "fork");
242       return -1;
243     }
244
245   if(pid)
246     {
247       if(debug_lvl >= DEBUG_STATUS)
248         syslog(LOG_INFO, _("Executing script %s"), name);
249
250       if(waitpid(pid, &status, 0) == pid)
251         {
252           if(WIFEXITED(status))         /* Child exited by itself */
253             {
254               if(WEXITSTATUS(status))
255                 {
256                   syslog(LOG_ERR, _("Process %d (%s) exited with non-zero status %d"), pid, name, WEXITSTATUS(status));
257                   return -1;
258                 }
259               else
260                 return 0;
261             }
262           else if(WIFSIGNALED(status))  /* Child was killed by a signal */
263             {
264               syslog(LOG_ERR, _("Process %d (%s) was killed by signal %d (%s)"),
265                      pid, name, WTERMSIG(status), strsignal(WTERMSIG(status)));
266               return -1;
267             }
268           else                          /* Something strange happened */
269             {
270               syslog(LOG_ERR, _("Process %d (%s) terminated abnormally"), pid, name);
271               return -1;
272             }
273         }
274       else
275         {
276           syslog(LOG_ERR, _("System call `%s' failed: %m"), "waitpid");
277           return -1;
278         }
279     }
280 cp
281   /* Child here */
282
283   _execute_script(name);
284 }
285
286
287 /*
288   Signal handlers.
289 */
290
291 RETSIGTYPE
292 sigterm_handler(int a, siginfo_t *info, void *b)
293 {
294   if(debug_lvl > DEBUG_NOTHING)
295     syslog(LOG_NOTICE, _("Got TERM signal"));
296
297   cleanup_and_exit(0);
298 }
299
300 RETSIGTYPE
301 sigquit_handler(int a, siginfo_t *info, void *b)
302 {
303   if(debug_lvl > DEBUG_NOTHING)
304     syslog(LOG_NOTICE, _("Got QUIT signal"));
305   cleanup_and_exit(0);
306 }
307
308 RETSIGTYPE
309 sigsegv_square(int a, siginfo_t *info, void *b)
310 {
311   syslog(LOG_ERR, _("Got another SEGV signal: not restarting"));
312   cp_trace();
313   exit(0);
314 }
315
316 RETSIGTYPE
317 sigsegv_handler(int a, siginfo_t *info, void *b)
318 {
319   struct sigaction act;
320   syslog(LOG_ERR, _("Got SEGV signal"));
321   cp_trace();
322
323   if(do_detach)
324     {
325       syslog(LOG_NOTICE, _("Trying to re-execute in 5 seconds..."));
326
327       act.sa_handler = NULL;
328       act.sa_mask = emptysigset;
329       act.sa_flags = SA_SIGINFO;
330       act.sa_sigaction = sigsegv_square;
331
332       close_network_connections();
333       sleep(5);
334       remove_pid(pidfilename);
335       execvp(g_argv[0], g_argv);
336     }
337   else
338     {
339       syslog(LOG_NOTICE, _("Not restarting."));
340       exit(0);
341     }
342 }
343
344 RETSIGTYPE
345 sighup_handler(int a, siginfo_t *info, void *b)
346 {
347   if(debug_lvl > DEBUG_NOTHING)
348     syslog(LOG_NOTICE, _("Got HUP signal"));
349   sighup = 1;
350 }
351
352 RETSIGTYPE
353 sigint_handler(int a, siginfo_t *info, void *b)
354 {
355   if(debug_lvl > DEBUG_NOTHING)
356     syslog(LOG_NOTICE, _("Got INT signal, exiting"));
357   cleanup_and_exit(0);
358 }
359
360 RETSIGTYPE
361 sigusr1_handler(int a, siginfo_t *info, void *b)
362 {
363   dump_connection_list();
364 }
365
366 RETSIGTYPE
367 sigusr2_handler(int a, siginfo_t *info, void *b)
368 {
369   dump_subnet_list();
370 }
371
372 RETSIGTYPE
373 unexpected_signal_handler(int a, siginfo_t *info, void *b)
374 {
375   syslog(LOG_WARNING, _("Got unexpected signal %d (%s)"), a, strsignal(a));
376   cp_trace();
377 }
378
379 struct {
380   int signal;
381   void (*handler)(int, siginfo_t *, void *);
382 } sighandlers[] = {
383   { SIGHUP, sighup_handler },
384   { SIGTERM, sigterm_handler },
385   { SIGQUIT, sigquit_handler },
386   { SIGSEGV, sigsegv_handler },
387   { SIGPIPE, NULL },
388   { SIGINT, sigint_handler },
389   { SIGUSR1, sigusr1_handler },
390   { SIGUSR2, sigusr2_handler },
391   { SIGCHLD, NULL },
392   { 0, NULL }
393 };
394
395 void
396 setup_signals(void)
397 {
398   int i;
399   struct sigaction act;
400
401   sigemptyset(&emptysigset);
402   act.sa_handler = NULL;
403   act.sa_mask = emptysigset;
404   act.sa_flags = SA_SIGINFO;
405
406   /* Set a default signal handler for every signal, errors will be
407      ignored. */
408   for(i = 0; i < NSIG; i++) 
409     {
410       act.sa_sigaction = unexpected_signal_handler;
411       sigaction(sighandlers[i].signal, &act, NULL);
412     }
413
414   /* Then, for each known signal that we want to catch, assign a
415      handler to the signal, with error checking this time. */
416   for(i = 0; sighandlers[i].signal; i++)
417     {
418       act.sa_sigaction = sighandlers[i].handler;
419       if(sigaction(sighandlers[i].signal, &act, NULL) < 0)
420         fprintf(stderr, _("Installing signal handler for signal %d (%s) failed: %m\n"),
421                 sighandlers[i].signal, strsignal(sighandlers[i].signal));
422     }
423 }