From 4440a86cfa359b8e40a484a2cd46d33db5455d8a Mon Sep 17 00:00:00 2001 From: Jonas Gunz Date: Mon, 25 May 2020 20:09:04 +0200 Subject: Initial --- contrib/ircdwatch/README | 56 +++++ contrib/ircdwatch/ircdwatch.8 | 50 +++++ contrib/ircdwatch/ircdwatch.c | 499 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 605 insertions(+) create mode 100644 contrib/ircdwatch/README create mode 100644 contrib/ircdwatch/ircdwatch.8 create mode 100644 contrib/ircdwatch/ircdwatch.c (limited to 'contrib/ircdwatch') diff --git a/contrib/ircdwatch/README b/contrib/ircdwatch/README new file mode 100644 index 0000000..80653bd --- /dev/null +++ b/contrib/ircdwatch/README @@ -0,0 +1,56 @@ +$Id: README,v 1.5 1998/11/09 22:56:34 borud Exp $ + +DESCRIPTION +=========== + ircdwatch is a daemon that regularly checks to see if ircd is running. + if ircd should die or somehow stop running, ircdwatch will respawn the + ircd daemon. if desirable, ircdwatch can be configured to check if + the ircd configuration file is changed and send a SIGHUP to the ircd + daemon which then causes the daemon to reload the configuration + file. + + the ircdwatch program itself is also used as sort of a remote + control depending on what command line arguments you feed it. you + can use it to start ircd and stop ircd and ircdwatch. + +OPTIONS +======= + if you invoke ircdwatch without any command line arguments it will + either daemonize itself and become a daemon, or it will exit if it + detects that an ircdwatch daemon is already running. + + for using the ircdwatch program as a remote control the following + command line options are available: + + --kill + stop both ircdwatch and ircd + + --rest + stop ircdwatch but leave ircd running + + --help + list command line arguments + + +COMPILE TIME CONFIGURATION +========================== + you configure ircdwatch by editing config.h in the directory where + you build ircd. the configuration parameters available for + ircdwatch are those starting with the prefix "IRCDWATCH_". please + refer to the config.h file for more information on the parameter + settings. most of the defaults should be okay if you want to use + ircdwatch though. + + +ADMINISTRATIVIA +=============== + ircdwatch was written by Bjorn Borud and is + Copyright (C) 1998 Bjorn Borud + + the program is released under the GNU General Public License + + the current maintainer can be reached at: + + please report bugs to + improvements are welcome. + diff --git a/contrib/ircdwatch/ircdwatch.8 b/contrib/ircdwatch/ircdwatch.8 new file mode 100644 index 0000000..cc944b1 --- /dev/null +++ b/contrib/ircdwatch/ircdwatch.8 @@ -0,0 +1,50 @@ +.\" @(#)$Id: ircdwatch.8,v 1.1 1998/06/12 22:57:40 kalt Exp $ +.TH IRCDWATCH 8 "$Date: 1998/06/12 22:57:40 $" +.SH NAME +ircdwatch \- Daemon for monitoring ircd and ircd.conf +.SH SYNOPSIS +.hy 0 +.IP \fBircdwatch\fP +[ +.BI \-\-kill +] [ +.BI \-\-rest +] [ +.BI \-\-help +] +.SH DESCRIPTION +.LP +\fIircdwatch\fP is a daemon that periodically checks that the +\fIircd\fP daemon is running, restarting it of necessary. This +daemon can also be configured (at compile time) to check for +changes to the \fIircd\fP configuration file and make \fIircd\fP +reload its configuration file by sending it a SIGHUP signal. +.LP +Given command line arguments \fIircdwatch\fP will serve as a remote +control for stopping both \fIircdwatch\fP and \fIircd\fP or just +\fIircdwatch\fP. + +.SH OPTIONS +.TP +.B \-\-kill +Stop both \fIircd\fP and \fIircdwatch\fP +.TP +.B \-\-rest +Stop \fIircdwatch\fP but leave \fIircd\fP running +.TP +.B \-\-help +List command line arguments +.SH COPYRIGHT +Copyright (C) 1998 Bjorn Borud, +.LP +.RE +.SH FILES + "ircd.conf" + "ircd.pid" + "ircdwatch.pid" +.SH "SEE ALSO" +ircd(8) +.SH BUGS +There may be some portability issues. Report bugs to +.SH AUTHOR +Bjorn Borud, diff --git a/contrib/ircdwatch/ircdwatch.c b/contrib/ircdwatch/ircdwatch.c new file mode 100644 index 0000000..c384578 --- /dev/null +++ b/contrib/ircdwatch/ircdwatch.c @@ -0,0 +1,499 @@ +/* + * Copyright (C) 1998 Bjorn Borud + * + * 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 1, 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. + * + */ + +#ifndef lint +static char rcsid[] = "@(#)$Id: ircdwatch.c,v 1.3 1999/02/21 00:33:44 kalt Exp $"; +#endif + +#include +#include /* atol() */ +#include /* fork() exec() */ +#include +#include /* stat() */ +#include +#include +#include /* strncmp() */ +#include + +#include "os.h" +#include "config.h" + +/* + * Try and find the correct name to use with getrlimit() for setting + * the max. number of files allowed to be open by this process. + * (borrowed from ircd/s_bsd.c) + */ +#ifdef RLIMIT_FDMAX +# define RLIMIT_FD_MAX RLIMIT_FDMAX +#else +# ifdef RLIMIT_NOFILE +# define RLIMIT_FD_MAX RLIMIT_NOFILE +# else +# ifdef RLIMIT_OPEN_MAX +# define RLIMIT_FD_MAX RLIMIT_OPEN_MAX +# else +# undef RLIMIT_FD_MAX +# endif +# endif +#endif + +#define PID_LEN 7 /* overkill, but hey */ +#define MAX_OPEN_FILEDESCRIPTORS_WILD_GUESS 256 + +static int want_to_quit = 0; + +void finalize(int i) +{ +#ifdef IRCDWATCH_USE_SYSLOG + syslog(LOG_NOTICE, "ircdwatch daemon exiting"); + closelog(); +#endif + exit(i); +} + +int daemonize(void) +{ + pid_t pid; + int i; + int open_max; + +#ifdef RLIMIT_FD_MAX + struct rlimit rlim; + + if (getrlimit(RLIMIT_FD_MAX, &rlim) != 0) { + perror("getrlimit"); + finalize(1); + } + + /* if we get a lame answer we just take a wild guess */ + if (rlim.rlim_max == 0) { + open_max = MAX_OPEN_FILEDESCRIPTORS_WILD_GUESS; + } + + open_max = rlim.rlim_max; + +#else + + /* no RLIMIT_FD_MAX? take a wild guess */ + open_max = MAX_OPEN_FILEDESCRIPTORS_WILD_GUESS; + +#endif + + pid = fork(); + if (pid < 0) { + perror("fork"); + exit(1); + } + + /* parent process dies */ + if (pid != 0) { + exit(0); + } + + setsid(); + umask(0); + + /* close file descriptors */ + for (i=0; i < open_max; i++) { + close(i); + } + + return(0); +} + +static void sig_handler (int signo) +{ + if (signo == SIGHUP) { + want_to_quit = 1; + return; + } + + if (signo == SIGALRM) { + +#ifndef POSIX_SIGNALS + (void)signal(SIGALRM, &sig_handler); +#endif; + + return; + } +} + + +void set_up_signals(void) +{ +#ifdef POSIX_SIGNALS + struct sigaction act; + + act.sa_handler = sig_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + + if (sigaction(SIGHUP, &act, NULL) < 0) { + perror("sigaction"); + } + + if (sigaction(SIGALRM, &act, NULL) < 0) { + perror("sigaction"); + } +#else + (void)signal(SIGHUP, &sig_handler); + (void)signal(SIGALRM, &sig_handler); +#endif + + /* ignore it if child processes die */ + signal(SIGCHLD, SIG_IGN); +} + +int write_my_pid(void) +{ + FILE *f; + + f = fopen(IRCDWATCH_PID_FILENAME, "w"); + if (f == NULL) { + return(-1); + } + + fprintf(f, "%d\n", getpid()); + fclose(f); + + return(0); +} + + +int file_modified(char *s) +{ + struct stat st; + + if (stat(s, &st) < 0) { + return(-1); + } + return(st.st_ctime); +} + + +int spawn (char *cmd) +{ + pid_t pid; + + pid = fork(); + + if (pid == -1) { +#ifdef IRCDWATCH_USE_SYSLOG + syslog(LOG_ERR, "spawn() unable to fork, errno=%d", errno); +#endif + return(-1); + } + + if (pid == 0) { + execl("/bin/sh", "sh", "-c", cmd, (char *) NULL); + _exit(127); + } + return(0); +} + +int read_pid(char *pid_filename) +{ + FILE *f; + char pidbuf[PID_LEN]; + pid_t pid; + + f = fopen(pid_filename, "r"); + if (f == NULL) { +#ifdef IRCDWATCH_USE_SYSLOG + syslog(LOG_ERR, "unable to fopen() %s: %s", pid_filename, strerror(errno)); +#endif + return(-1); + } + + if (fgets(pidbuf, PID_LEN, f) != NULL) { + pid = atol(pidbuf); + } else { +#ifdef IRCDWATCH_USE_SYSLOG + syslog(LOG_ERR, "fgets() %s: %s", pid_filename, strerror(errno)); +#endif + fclose(f); + return(-1); + } + + fclose(f); + return(pid); +} + +int file_exists (char *s) +{ + struct stat st; + if ((stat(s, &st) < 0) && (errno == ENOENT)) { + return(0); + } + return(1); +} + +/* yeah, I'll get around to these in some later version */ + +int file_readable (char *s) +{ + return(access(s, R_OK) == 0); +} + +int file_writable (char *s) +{ + return(access(s, W_OK) == 0); +} + +int file_executable (char *s) +{ + int rc; + rc = (access(IRCD_PATH, X_OK) == 0); + return rc; +} + +int verify_pid(int pid) +{ + int res; + + res = kill(pid, 0); + if (res < 0 && errno == EPERM) { + fprintf(stderr, "Not process owner\n"); + exit(1); + } + + return(res == 0); +} + +int ircdwatch_running () { + int pid; + + if (file_exists(IRCDWATCH_PID_FILENAME)) { + pid = read_pid(IRCDWATCH_PID_FILENAME); + if (pid > 0) { + return(verify_pid(pid) == 1); + } else { + return(-1); + } + } + return(0); +} + +int ircd_running () { + int pid; + + if (file_exists(IRCDPID_PATH)) { + pid = read_pid(IRCDPID_PATH); + if (pid > 0) { + return(verify_pid(pid) == 1); + } else { + return(-1); + } + } + return(0); +} + +void hup_ircd () +{ + int pid; + int res; + + if (file_exists(IRCDPID_PATH)) { + pid = read_pid(IRCDPID_PATH); + if (pid > 0) { + res = kill(pid, SIGHUP); + if (res < 0 && errno == EPERM) { +#ifdef IRCDWATCH_USE_SYSLOG + syslog(LOG_ERR, "not allowed to send SIGHUP to ircd"); +#endif + finalize(1); + } + } + } +} + + +void daemon_run () +{ + int i; + int last_config_time = 0; + + /* is ircdwatch already running? */ + i = ircdwatch_running(); + if (i == -1) { + /* unable to open pid file. wrong user? */ + fprintf(stderr, "ircdwatch pid file exists but is unreadable\n"); + exit(1); + } else if (i) { + fprintf(stderr, "ircdwatch is already running\n"); + exit(0); + } + + /* is ircd running? */ + i = ircd_running(); + if (i == -1) { + /* unable to open pid file. wrong user? */ + fprintf(stderr, "ircdwatch pid file exists but is unreadable\n"); + exit(1); + } else if (!i) { + fprintf(stderr, "ircd not running. attempting to start ircd...\n"); + if (file_exists(IRCD_PATH)) { + if (file_executable(IRCD_PATH)) { + spawn(IRCD_PATH); + } else { + fprintf(stderr, "%s not executable\n", IRCD_PATH); + exit(1); + } + } else { + fprintf(stderr, "%s does not exist\n", IRCD_PATH); + exit(1); + } + } + + set_up_signals(); + closelog(); + /* daemonize(); */ + +#ifdef IRCDWATCH_USE_SYSLOG + openlog(IRCDWATCH_SYSLOG_IDENT, + IRCDWATCH_SYSLOG_OPTIONS, + IRCDWATCH_SYSLOG_FACILITY); + + syslog(LOG_NOTICE, "starting ircdwatch daemon"); +#endif + + alarm(IRCDWATCH_POLLING_INTERVAL); + pause(); + + while (!want_to_quit) { + if (! ircd_running() ) { + +#ifdef IRCDWATCH_USE_SYSLOG + syslog(LOG_ERR, "spawning %s", IRCD_PATH); +#endif + + spawn(IRCD_PATH); + } + +#ifdef IRCDWATCH_HUP_ON_CONFIG_CHANGE + i = file_modified(IRCDCONF_PATH); + if (i != -1) { + + if (last_config_time == 0) { + last_config_time = i; + } + + else if (i > last_config_time) { + last_config_time = i; + hup_ircd(); + +#ifdef IRCDWATCH_USE_SYSLOG + syslog(LOG_NOTICE, "config change, HUPing ircd"); +#endif + + } + } +#endif + + alarm(IRCDWATCH_POLLING_INTERVAL); + pause(); + } + return; +} + +void kill_ircd () +{ + int pid; + int res; + + if (file_exists(IRCDPID_PATH)) { + pid = read_pid(IRCDPID_PATH); + if (pid > 0) { + res = kill(pid, SIGTERM); + if (res < 0) { + perror("ircd kill"); + finalize(1); + } else { + fprintf(stderr, "killed ircd\n"); + } + } + } else { + fprintf(stderr, "File %s does not exist\n", IRCDPID_PATH); + } +} + +void kill_ircdwatch () +{ + int pid; + int res; + + if (file_exists(IRCDWATCH_PID_FILENAME)) { + pid = read_pid(IRCDWATCH_PID_FILENAME); + if (pid > 0) { + res = kill(pid, SIGHUP); + if (res < 0) { + perror("ircdwatch kill"); + finalize(1); + } else { + fprintf(stderr, "Sent HUP to ircdwatch. it will die soon...\n"); + } + } + } else { + fprintf(stderr, "File %s does not exist\n", IRCDWATCH_PID_FILENAME); + } +} + + +void usage (void) +{ + fprintf(stderr,"\n\ +Usage:\n\ + ircdwatch [--kill | --rest | --help]\n\ +\n\ + --kill, stop both ircdwatch and ircd\n\ + --rest, stop ircdwatch but let ircd alone\n\ + --help, display this text\n\ +\n\ +%s\n", rcsid); +} + +int +main (int argc, char **argv) { + int i; + +#ifdef IRCDWATCH_USE_SYSLOG + openlog(IRCDWATCH_SYSLOG_IDENT, + IRCDWATCH_SYSLOG_OPTIONS, + IRCDWATCH_SYSLOG_FACILITY); +#endif + + if (argc > 1) { + if (strncmp(argv[1], "--rest", 6) == 0) { + kill_ircdwatch(); + exit(0); + } + + if (strncmp(argv[1], "--kill", 6) == 0) { + kill_ircdwatch(); + kill_ircd(); + exit(0); + } + + usage(); + exit(0); + } + + daemon_run(); + finalize(0); +} -- cgit v1.2.3