From: Ivo Timmermans Date: Thu, 16 Nov 2000 17:54:29 +0000 (+0000) Subject: Move all process-related functions into process.c. X-Git-Tag: release-1.0pre4~172 X-Git-Url: https://www.tinc-vpn.org/git/browse?p=tinc;a=commitdiff_plain;h=2764532ea72200d0a27ad2d79e6e299c00c62404 Move all process-related functions into process.c. --- diff --git a/src/Makefile.am b/src/Makefile.am index a1ec3523..4e11d26b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,13 +1,15 @@ ## Produce this file with automake to get Makefile.in -# $Id: Makefile.am,v 1.4.4.6 2000/11/15 13:33:25 guus Exp $ +# $Id: Makefile.am,v 1.4.4.7 2000/11/16 17:54:27 zarq Exp $ sbin_PROGRAMS = tincd -tincd_SOURCES = conf.c connlist.c meta.c net.c netutl.c protocol.c subnet.c tincd.c +tincd_SOURCES = conf.c connlist.c meta.c net.c netutl.c process.c \ + protocol.c subnet.c tincd.c INCLUDES = @INCLUDES@ -I$(top_builddir) -I$(top_srcdir)/lib -I$(top_srcdir)/intl -noinst_HEADERS = conf.h connlist.h meta.h net.h netutl.h protocol.h subnet.h +noinst_HEADERS = conf.h connlist.h meta.h net.h netutl.h process.h \ + protocol.h subnet.h LIBS = @LIBS@ @INTLLIBS@ @@ -16,4 +18,5 @@ tincd_LDADD = \ localedir = $(datadir)/locale -CFLAGS = @CFLAGS@ -DPKGLIBDIR=$(pkglibdir) -DCONFDIR=\"@sysconfdir@\" -DLOCALEDIR=\"$(localedir)\" +CFLAGS = @CFLAGS@ -DPKGLIBDIR=$(pkglibdir) -DCONFDIR=\"@sysconfdir@\" \ + -DLOCALEDIR=\"$(localedir)\" diff --git a/src/net.c b/src/net.c index 2e06a39e..7d81176a 100644 --- a/src/net.c +++ b/src/net.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: net.c,v 1.35.4.74 2000/11/15 22:07:36 zarq Exp $ + $Id: net.c,v 1.35.4.75 2000/11/16 17:54:27 zarq Exp $ */ #include "config.h" @@ -72,6 +72,7 @@ #include "meta.h" #include "net.h" #include "netutl.h" +#include "process.h" #include "protocol.h" #include "subnet.h" @@ -94,134 +95,6 @@ char *unknown = NULL; subnet_t mymac; -list_t *child_pids; - -void _execute_script(const char *name) -{ - int error = 0; - char *scriptname; - char *s; - int fd; - - if(netname) - { - asprintf(&s, "NETNAME=%s", netname); - putenv(s); /* Don't free s! see man 3 putenv */ - } -#ifdef HAVE_UNSETENV - else - { - unsetenv("NETNAME"); - } -#endif - - if(chdir(confbase) < 0) - /* This cannot fail since we already read config files from this - directory. - Guus */ - /* Yes this can fail, somebody could have removed this directory - when we didn't pay attention. - Ivo */ - { - if(chdir("/") < 0) - /* Now if THIS fails, something wicked is going on. - Ivo */ - syslog(LOG_ERR, _("Couldn't chdir to `/': %m")); - - /* Continue anyway. */ - } - - asprintf(&scriptname, "%s/%s", confbase, name); - - /* Close all file descriptors */ - closelog(); - fcloseall(); - - /* Open standard input */ - if(open("/dev/null", O_RDONLY) < 0) - { - syslog(LOG_ERR, _("Opening `/dev/null' failed: %m")); - error = 1; - } - - if(!error) - { - /* Standard output directly goes to syslog */ - openlog(name, LOG_CONS | LOG_PID, LOG_DAEMON); - /* Standard error as well */ - if(dup2(1, 2) < 0) - { - syslog(LOG_ERR, _("System call `%s' failed: %m"), - "dup2"); - error = 1; - } - } - - if(error && debug_lvl > 1) - syslog(LOG_INFO, _("This means that any output the script generates will not be shown in syslog.")); - - execl(scriptname, NULL); - /* No return on success */ - - if(errno != ENOENT) /* Ignore if the file does not exist */ - syslog(LOG_WARNING, _("Error executing `%s': %m"), scriptname); - - /* No need to free things */ - exit(0); -} - -/* - Execute the given script. - This function doesn't really belong here. -*/ -int execute_script(const char *name) -{ - pid_t pid; - - if((pid = fork()) < 0) - { - syslog(LOG_ERR, _("System call `%s' failed: %m"), - "fork"); - return -1; - } - - if(pid) - { - list_append(child_pids, pid); - return 0; - } - - /* Child here */ - - _execute_script(name); -} - -int check_child(void *data) -{ - pid_t pid; - int status; - - pid = (pid_t) data; - pid = waitpid(pid, &status, WNOHANG); - if(WIFEXITED(status)) - { - if(WIFSIGNALED(status)) /* Child was killed by a signal */ - { - syslog(LOG_ERR, _("Child with PID %d was killed by signal %d (%s)"), - pid, WTERMSIG(status), strsignal(WTERMSIG(status))); - return -1; - } - if(WEXITSTATUS(status) != 0) - { - syslog(LOG_INFO, _("Child with PID %d exited with code %d"), - WEXITSTATUS(status)); - } - return -1; - } -} - -void check_children(void) -{ - list_forall_nodes(child_pids, check_child); -} - int xsend(conn_list_t *cl, vpn_packet_t *inpkt) { vpn_packet_t outpkt; diff --git a/src/process.c b/src/process.c new file mode 100644 index 00000000..f221a9aa --- /dev/null +++ b/src/process.c @@ -0,0 +1,348 @@ +/* + process.c -- process management functions + Copyright (C) 1999,2000 Ivo Timmermans , + 2000 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: process.c,v 1.1.2.1 2000/11/16 17:54:28 zarq Exp $ +*/ + +#include "config.h" + +#include + +/* A list containing all our children */ +list_t *child_pids; + +/* If zero, don't detach from the terminal. */ +int do_detach = 1; + +/* + Detach from current terminal, write pidfile, kill parent +*/ +int detach(void) +{ + int fd; + pid_t pid; + + if(do_detach) + { + ppid = getpid(); + + if((pid = fork()) < 0) + { + perror("fork"); + return -1; + } + if(pid) /* parent process */ + { + signal(SIGTERM, parent_exit); + sleep(600); /* wait 10 minutes */ + exit(1); + } + } + + if(write_pidfile()) + return -1; + + if(do_detach) + { + if((fd = open("/dev/tty", O_RDWR)) >= 0) + { + if(ioctl(fd, TIOCNOTTY, NULL)) + { + perror("ioctl"); + return -1; + } + close(fd); + } + + if(setsid() < 0) + return -1; + + kill(ppid, SIGTERM); + } + + chdir("/"); /* avoid keeping a mointpoint busy */ + + openlog(identname, LOG_CONS | LOG_PID, LOG_DAEMON); + + if(debug_lvl > DEBUG_NOTHING) + syslog(LOG_NOTICE, _("tincd %s (%s %s) starting, debug level %d"), + VERSION, __DATE__, __TIME__, debug_lvl); + else + syslog(LOG_NOTICE, _("tincd %s starting"), VERSION); + + xalloc_fail_func = memory_full; + + return 0; +} + +/* + Execute the program name, with sane environment. All output will be + redirected to syslog. +*/ +void _execute_script(const char *name) +{ + int error = 0; + char *scriptname; + char *s; + int fd; + + if(netname) + { + asprintf(&s, "NETNAME=%s", netname); + putenv(s); /* Don't free s! see man 3 putenv */ + } +#ifdef HAVE_UNSETENV + else + { + unsetenv("NETNAME"); + } +#endif + + if(chdir(confbase) < 0) + /* This cannot fail since we already read config files from this + directory. - Guus */ + /* Yes this can fail, somebody could have removed this directory + when we didn't pay attention. - Ivo */ + { + if(chdir("/") < 0) + /* Now if THIS fails, something wicked is going on. - Ivo */ + syslog(LOG_ERR, _("Couldn't chdir to `/': %m")); + + /* Continue anyway. */ + } + + asprintf(&scriptname, "%s/%s", confbase, name); + + /* Close all file descriptors */ + closelog(); + fcloseall(); + + /* Open standard input */ + if(open("/dev/null", O_RDONLY) < 0) + { + syslog(LOG_ERR, _("Opening `/dev/null' failed: %m")); + error = 1; + } + + if(!error) + { + /* Standard output directly goes to syslog */ + openlog(name, LOG_CONS | LOG_PID, LOG_DAEMON); + /* Standard error as well */ + if(dup2(1, 2) < 0) + { + syslog(LOG_ERR, _("System call `%s' failed: %m"), + "dup2"); + error = 1; + } + } + + if(error && debug_lvl > 1) + syslog(LOG_INFO, _("This means that any output the script generates will not be shown in syslog.")); + + execl(scriptname, NULL); + /* No return on success */ + + if(errno != ENOENT) /* Ignore if the file does not exist */ + syslog(LOG_WARNING, _("Error executing `%s': %m"), scriptname); + + /* No need to free things */ + exit(0); +} + +/* + Fork and execute the program pointed to by name. +*/ +int execute_script(const char *name) +{ + pid_t pid; + + if((pid = fork()) < 0) + { + syslog(LOG_ERR, _("System call `%s' failed: %m"), + "fork"); + return -1; + } + + if(pid) + { + list_append(child_pids, pid); + return 0; + } + + /* Child here */ + + _execute_script(name); +} + +/* + Check a child (the pointer data is actually an integer, the PID of + that child. A non-zero return value means that the child has exited + and can be removed from our list. +*/ +int check_child(void *data) +{ + pid_t pid; + int status; + + pid = (pid_t) data; + pid = waitpid(pid, &status, WNOHANG); + if(WIFEXITED(status)) + { + if(WIFSIGNALED(status)) /* Child was killed by a signal */ + { + syslog(LOG_ERR, _("Child with PID %d was killed by signal %d (%s)"), + pid, WTERMSIG(status), strsignal(WTERMSIG(status))); + return -1; + } + if(WEXITSTATUS(status) != 0) + { + syslog(LOG_INFO, _("Child with PID %d exited with code %d"), + WEXITSTATUS(status)); + } + return -1; + } + + /* Child is still running */ + return 0; +} + +/* + Check the status of all our children. +*/ +void check_children(void) +{ + list_forall_nodes(child_pids, check_child); +} + + + +/* + Signal handlers. +*/ + +RETSIGTYPE +sigterm_handler(int a) +{ + if(debug_lvl > DEBUG_NOTHING) + syslog(LOG_NOTICE, _("Got TERM signal")); + + cleanup_and_exit(0); +} + +RETSIGTYPE +sigquit_handler(int a) +{ + if(debug_lvl > DEBUG_NOTHING) + syslog(LOG_NOTICE, _("Got QUIT signal")); + cleanup_and_exit(0); +} + +RETSIGTYPE +sigsegv_square(int a) +{ + syslog(LOG_ERR, _("Got another SEGV signal: not restarting")); + exit(0); +} + +RETSIGTYPE +sigsegv_handler(int a) +{ + syslog(LOG_ERR, _("Got SEGV signal")); + cp_trace(); + + if(do_detach) + { + syslog(LOG_NOTICE, _("Trying to re-execute in 5 seconds...")); + signal(SIGSEGV, sigsegv_square); + close_network_connections(); + sleep(5); + remove_pid(pidfilename); + execvp(g_argv[0], g_argv); + } + else + { + syslog(LOG_NOTICE, _("Not restarting.")); + exit(0); + } +} + +RETSIGTYPE +sighup_handler(int a) +{ + if(debug_lvl > DEBUG_NOTHING) + syslog(LOG_NOTICE, _("Got HUP signal")); + sighup = 1; +} + +RETSIGTYPE +sigint_handler(int a) +{ + if(debug_lvl > DEBUG_NOTHING) + syslog(LOG_NOTICE, _("Got INT signal, exiting")); + cleanup_and_exit(0); +} + +RETSIGTYPE +sigusr1_handler(int a) +{ + dump_conn_list(); +} + +RETSIGTYPE +sigusr2_handler(int a) +{ + dump_subnet_list(); +} + +RETSIGTYPE +sighuh(int a) +{ + syslog(LOG_WARNING, _("Got unexpected signal %d (%s)"), a, strsignal(a)); + cp_trace(); +} + +void +setup_signals(void) +{ + int i; + + for(i=0;i<32;i++) + signal(i,sighuh); + + if(signal(SIGTERM, SIG_IGN) != SIG_ERR) + signal(SIGTERM, sigterm_handler); + if(signal(SIGQUIT, SIG_IGN) != SIG_ERR) + signal(SIGQUIT, sigquit_handler); + if(signal(SIGSEGV, SIG_IGN) != SIG_ERR) + signal(SIGSEGV, sigsegv_handler); + if(signal(SIGHUP, SIG_IGN) != SIG_ERR) + signal(SIGHUP, sighup_handler); + signal(SIGPIPE, SIG_IGN); + if(signal(SIGINT, SIG_IGN) != SIG_ERR) + signal(SIGINT, sigint_handler); + signal(SIGUSR1, sigusr1_handler); + signal(SIGUSR2, sigusr2_handler); + signal(SIGCHLD, SIG_IGN); +} + +RETSIGTYPE parent_exit(int a) +{ + exit(0); +} diff --git a/src/process.h b/src/process.h new file mode 100644 index 00000000..c3514dc4 --- /dev/null +++ b/src/process.h @@ -0,0 +1,30 @@ +/* + process.h -- header file for process.c + Copyright (C) 1999,2000 Ivo Timmermans , + 2000 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id: process.h,v 1.1.2.1 2000/11/16 17:54:28 zarq Exp $ +*/ + +#ifndef __TINC_PROCESS_H__ +#define __TINC_PROCESS_H__ + +#include + +extern list_t *child_pids; + +#endif /* __TINC_PROCESS_H__ */ diff --git a/src/tincd.c b/src/tincd.c index 9c337f88..9f229b30 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: tincd.c,v 1.10.4.28 2000/11/15 01:06:13 zarq Exp $ + $Id: tincd.c,v 1.10.4.29 2000/11/16 17:54:29 zarq Exp $ */ #include "config.h" @@ -83,7 +83,7 @@ static int show_version; static int kill_tincd = 0; /* If zero, don't detach from the terminal. */ -static int do_detach = 1; +extern int do_detach; /* If nonzero, generate public/private keypair for this host/net. */ static int generate_keys = 0; @@ -251,67 +251,6 @@ void memory_full(int size) exit(1); } -/* - Detach from current terminal, write pidfile, kill parent -*/ -int detach(void) -{ - int fd; - pid_t pid; - - if(do_detach) - { - ppid = getpid(); - - if((pid = fork()) < 0) - { - perror("fork"); - return -1; - } - if(pid) /* parent process */ - { - signal(SIGTERM, parent_exit); - sleep(600); /* wait 10 minutes */ - exit(1); - } - } - - if(write_pidfile()) - return -1; - - if(do_detach) - { - if((fd = open("/dev/tty", O_RDWR)) >= 0) - { - if(ioctl(fd, TIOCNOTTY, NULL)) - { - perror("ioctl"); - return -1; - } - close(fd); - } - - if(setsid() < 0) - return -1; - - kill(ppid, SIGTERM); - } - - chdir("/"); /* avoid keeping a mointpoint busy */ - - openlog(identname, LOG_CONS | LOG_PID, LOG_DAEMON); - - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("tincd %s (%s %s) starting, debug level %d"), - VERSION, __DATE__, __TIME__, debug_lvl); - else - syslog(LOG_NOTICE, _("tincd %s starting"), VERSION); - - xalloc_fail_func = memory_full; - - return 0; -} - /* Close network connections, and terminate neatly */ @@ -490,112 +429,3 @@ main(int argc, char **argv, char **envp) } } -RETSIGTYPE -sigterm_handler(int a) -{ - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("Got TERM signal")); - - cleanup_and_exit(0); -} - -RETSIGTYPE -sigquit_handler(int a) -{ - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("Got QUIT signal")); - cleanup_and_exit(0); -} - -RETSIGTYPE -sigsegv_square(int a) -{ - syslog(LOG_ERR, _("Got another SEGV signal: not restarting")); - exit(0); -} - -RETSIGTYPE -sigsegv_handler(int a) -{ - syslog(LOG_ERR, _("Got SEGV signal")); - cp_trace(); - - if(do_detach) - { - syslog(LOG_NOTICE, _("Trying to re-execute in 5 seconds...")); - signal(SIGSEGV, sigsegv_square); - close_network_connections(); - sleep(5); - remove_pid(pidfilename); - execvp(g_argv[0], g_argv); - } - else - { - syslog(LOG_NOTICE, _("Not restarting.")); - exit(0); - } -} - -RETSIGTYPE -sighup_handler(int a) -{ - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("Got HUP signal")); - sighup = 1; -} - -RETSIGTYPE -sigint_handler(int a) -{ - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("Got INT signal, exiting")); - cleanup_and_exit(0); -} - -RETSIGTYPE -sigusr1_handler(int a) -{ - dump_conn_list(); -} - -RETSIGTYPE -sigusr2_handler(int a) -{ - dump_subnet_list(); -} - -RETSIGTYPE -sighuh(int a) -{ - syslog(LOG_WARNING, _("Got unexpected signal %d (%s)"), a, strsignal(a)); - cp_trace(); -} - -void -setup_signals(void) -{ - int i; - - for(i=0;i<32;i++) - signal(i,sighuh); - - if(signal(SIGTERM, SIG_IGN) != SIG_ERR) - signal(SIGTERM, sigterm_handler); - if(signal(SIGQUIT, SIG_IGN) != SIG_ERR) - signal(SIGQUIT, sigquit_handler); - if(signal(SIGSEGV, SIG_IGN) != SIG_ERR) - signal(SIGSEGV, sigsegv_handler); - if(signal(SIGHUP, SIG_IGN) != SIG_ERR) - signal(SIGHUP, sighup_handler); - signal(SIGPIPE, SIG_IGN); - if(signal(SIGINT, SIG_IGN) != SIG_ERR) - signal(SIGINT, sigint_handler); - signal(SIGUSR1, sigusr1_handler); - signal(SIGUSR2, sigusr2_handler); - signal(SIGCHLD, SIG_IGN); -} - -RETSIGTYPE parent_exit(int a) -{ - exit(0); -}