%mode 0750
#!/usr/bin/env perl
-
#
# InspIRCd -- Internet Relay Chat Daemon
#
+# Copyright (C) 2015 Steven Van Acker <steven@singularity.be>
+# Copyright (C) 2015 Attila Molnar <attilamolnar@hush.com>
+# Copyright (C) 2014 Dan Parsons <dparsons@nyip.net>
+# Copyright (C) 2013-2014, 2016-2021 Sadie Powell <sadie@witchery.services>
+# Copyright (C) 2012 Robby <robby@chatbelgie.be>
+# Copyright (C) 2011 DjSlash <djslash@djslash.org>
# Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
+# Copyright (C) 2008-2009 Robin Burchell <robin+git@viroteck.net>
+# Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
+# Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
+# Copyright (C) 2006 Oliver Lupton <om@inspircd.org>
+# Copyright (C) 2006 John Brooks <special@inspircd.org>
+# Copyright (C) 2005-2006, 2008-2009 Craig Edwards <brain@inspircd.org>
+# Copyright (C) 2005 Craig McLure <craig@frostycoolslug.com>
#
# This file is part of InspIRCd. InspIRCd is free software: you can
# redistribute it and/or modify it under the terms of the GNU General Public
use POSIX;
use Fcntl;
-my $basepath = "@BASE_DIR@";
-my $confpath = "@CONFIG_DIR@/";
+# From http://refspecs.linuxbase.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
+use constant {
+ STATUS_EXIT_SUCCESS => 0,
+ STATUS_EXIT_DEAD_WITH_PIDFILE => 1,
+ STATUS_EXIT_DEAD_WITH_LOCKFILE => 2,
+ STATUS_EXIT_NOT_RUNNING => 3,
+ STATUS_EXIT_UNKNOWN => 4,
+
+ GENERIC_EXIT_SUCCESS => 0,
+ GENERIC_EXIT_UNSPECIFIED => 1,
+ GENERIC_EXIT_INVALID_ARGUMENTS => 2,
+ GENERIC_EXIT_UNIMPLEMENTED => 3,
+ GENERIC_EXIT_INSUFFICIENT_PRIVILEGE => 4,
+ GENERIC_EXIT_NOT_INSTALLED => 5,
+ GENERIC_EXIT_NOT_CONFIGURED => 6,
+ GENERIC_EXIT_NOT_RUNNING => 7
+};
+
+my $scriptpath = "@SCRIPT_DIR@";
+my $confpath = "@CONFIG_DIR@";
my $binpath = "@BINARY_DIR@";
-my $runpath = "@BASE_DIR@";
-my $datadir = "@DATA_DIR@";
-my $valgrindlogpath = "$basepath/valgrindlogs";
+my $runtimedir = "@RUNTIME_DIR@";
+my $valgrindlogpath = "@LOG_DIR@/valgrind";
my $executable = "inspircd";
-my $version = "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@+@VERSION_LABEL@";
+my $version = "@VERSION_FULL@";
my $uid = "@UID@";
-if (!("--runasroot" ~~ @ARGV) && ($< == 0 || $> == 0)) {
+my @gdbargs = (
+ '--eval-command', 'handle SIGPIPE pass nostop noprint',
+ '--eval-command', 'handle SIGHUP pass nostop noprint',
+ '--eval-command', 'run',
+ '--args', "$binpath/$executable", qw(--nofork --nolog --debug)
+);
+
+sub expand_fragment($$) {
+ my ($base, $fragment) = @_;
+ if ($fragment =~ /^\//) {
+ return $fragment;
+ } else {
+ return "$base/$fragment";
+ }
+}
+
+if (!(grep { $_ eq '--runasroot' } @ARGV) && ($< == 0 || $> == 0)) {
if ($uid !~ /^\d+$/) {
# Named UID, look it up
$uid = getpwnam $uid;
}
}
if (!defined $conf) {
- $conf = $confpath . "inspircd.conf";
+ $conf = expand_fragment $confpath, "inspircd.conf";
push @ARGV, '--config='.$conf;
}
{
print STDERR "Invalid command or none given.\n";
cmd_help();
- exit 1;
+ exit GENERIC_EXIT_UNIMPLEMENTED;
}
else
{
- $sub->(@ARGV);
- exit 0;
+ exit $sub->(@ARGV); # Error code passed through return value
}
sub cmd_help()
my @cmds = grep /^cmd_/, @subs;
my @devs = grep /^dev_/, @subs;
local $_;
- $_ =~ s/^(cmd|dev)_// foreach (@cmds, @devs);
- $_ =~ s/_/-/g foreach (@cmds, @devs);
+ $_ =~ s/^(cmd|dev)_// for (@cmds, @devs);
+ $_ =~ s/_/-/g for (@cmds, @devs);
print STDERR "Usage: ./inspircd (" . join("|", @cmds) . ")\n";
print STDERR "Developer arguments: (" . join("|", @devs) . ")\n";
- exit 0;
+ exit GENERIC_EXIT_SUCCESS;
}
sub cmd_status()
if (getstatus() == 1) {
my $pid = getprocessid();
print "InspIRCd is running (PID: $pid)\n";
- exit();
+ exit STATUS_EXIT_SUCCESS;
} else {
print "InspIRCd is not running. (Or PID File not found)\n";
- exit();
+ exit STATUS_EXIT_NOT_RUNNING;
}
}
{
if (getstatus() == 1) {
my $pid = getprocessid();
- system("kill -HUP $pid >/dev/null 2>&1");
+ kill HUP => $pid;
print "InspIRCd rehashed (pid: $pid).\n";
- exit();
+ exit GENERIC_EXIT_SUCCESS;
} else {
print "InspIRCd is not running. (Or PID File not found)\n";
- exit();
+ exit GENERIC_EXIT_NOT_RUNNING;
}
}
sub cmd_cron()
{
- if (getstatus() == 0) { goto &cmd_start(); }
- exit();
+ if (getstatus() == 0) { goto &cmd_start(@_); }
+ exit GENERIC_EXIT_UNSPECIFIED;
}
sub cmd_version()
{
print "InspIRCd version: $version\n";
- exit();
+ exit GENERIC_EXIT_SUCCESS;
}
sub cmd_restart(@)
{
cmd_stop();
unlink($pidfile) if (-e $pidfile);
- goto &cmd_start;
+ goto &cmd_start(@_);
}
sub hid_cheese_sandwich()
{
print "Creating Cheese Sandwich..\n";
print "Done.\n";
- exit();
+ exit GENERIC_EXIT_SUCCESS;
}
sub cmd_start(@)
{
# Check to see its not 'running' already.
- if (getstatus() == 1) { print "InspIRCd is already running.\n"; return 0; }
+ if (getstatus() == 1) { print "InspIRCd is already running.\n"; exit GENERIC_EXIT_SUCCESS; }
+
# If we are still alive here.. Try starting the IRCd..
- chdir $runpath;
print "$binpath/$executable doesn't exist\n" and return 0 unless(-e "$binpath/$executable");
print "$binpath/$executable is not executable\n" and return 0 unless(-f "$binpath/$executable" && -x "$binpath/$executable");
# Check to see its not 'running' already.
if (getstatus() == 1) { print "InspIRCd is already running.\n"; return 0; }
- chdir $runpath;
print "$binpath/$executable doesn't exist\n" and return 0 unless(-e "$binpath/$executable");
print "$binpath/$executable is not executable\n" and return 0 unless(-f "$binpath/$executable" && -x "$binpath/$executable");
checkgdb();
# If we are still alive here.. Try starting the IRCd..
- exec 'gdb', "--command=$basepath/.gdbargs", '--args', "$binpath/$executable", qw(--nofork --debug), @_;
+ exec 'gdb', @gdbargs, @_;
die "Failed to start GDB: $!\n";
}
# Check to see its not 'running' already.
if (getstatus() == 1) { print "InspIRCd is already running.\n"; return 0; }
- chdir $runpath;
print "$binpath/$executable doesn't exist\n" and return 0 unless(-e "$binpath/$executable");
#Check we have gdb
# If we are still alive here.. Try starting the IRCd..
print "Starting InspIRCd in `screen`, type `screen -r` when the ircd crashes to view the gdb output and get a backtrace.\n";
print "Once you're inside the screen session press ^C + d to re-detach from the session\n";
- exec qw(screen -m -d gdb), "--command=$basepath/.gdbargs", '-args', "$binpath/$executable", qw(--nofork --debug --nolog), @_;
+ exec qw(screen -m -d gdb), @gdbargs, @_;
die "Failed to start screen: $!\n";
}
# Check to see its not 'running' already.
if (getstatus() == 1) { print "InspIRCd is already running.\n"; return 0; }
- chdir $runpath;
print "$binpath/$executable doesn't exist\n" and return 0 unless(-e "$binpath/$executable");
print "$binpath/$executable is not executable\n" and return 0 unless(-f "$binpath/$executable" && -x "$binpath/$executable");
# If we are still alive here.. Try starting the IRCd..
# May want to do something with these args at some point: --suppressions=.inspircd.sup --gen-suppressions=yes
# Could be useful when we want to stop it complaining about things we're sure aren't issues.
- exec qw(valgrind -v --tool=memcheck --leak-check=yes --db-attach=yes --num-callers=10), "$binpath/$executable", qw(--nofork --debug --nolog), @_;
+ exec qw(valgrind -v --tool=memcheck --leak-check=yes --db-attach=yes --num-callers=30), "$binpath/$executable", qw(--nofork --debug --nolog), @_;
die "Failed to start valgrind: $!\n";
}
# Check to see its not 'running' already.
if (getstatus() == 1) { print "InspIRCd is already running.\n"; return 0; }
- chdir $runpath;
print "$binpath/$executable doesn't exist\n" and return 0 unless(-e "$binpath/$executable");
print "$binpath/$executable is not executable\n" and return 0 unless(-f "$binpath/$executable" && -x "$binpath/$executable");
sysopen STDERR, "$valgrindlogpath/valdebug.$suffix", O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND, 0666 or die "Can't open $valgrindlogpath/valdebug.$suffix: $!\n";
# May want to do something with these args at some point: --suppressions=.inspircd.sup --gen-suppressions=yes
# Could be useful when we want to stop it complaining about things we're sure aren't issues.
- exec qw(valgrind -v --tool=memcheck --leak-check=full --show-reachable=yes --num-callers=15 --track-fds=yes),
+ exec qw(valgrind -v --tool=memcheck --leak-check=full --show-reachable=yes --num-callers=30 --track-fds=yes),
"--suppressions=$binpath/valgrind.sup", qw(--gen-suppressions=all),
qw(--leak-resolution=med --time-stamp=yes --log-fd=2 --),
"$binpath/$executable", qw(--nofork --debug --nolog), @_;
# Check to see its not 'running' already.
if (getstatus() == 1) { print "InspIRCd is already running.\n"; return 0; }
- chdir $runpath;
print "$binpath/$executable doesn't exist\n" and return 0 unless(-e "$binpath/$executable");
print "$binpath/$executable is not executable\n" and return 0 unless(-f "$binpath/$executable" && -x "$binpath/$executable");
# If we are still alive here.. Try starting the IRCd..
print "Starting InspIRCd in `screen`, type `screen -r` when the ircd crashes to view the valgrind and gdb output and get a backtrace.\n";
print "Once you're inside the screen session press ^C + d to re-detach from the session\n";
- exec qw(screen -m -d valgrind -v --tool=memcheck --leak-check=yes --db-attach=yes --num-callers=10), "$binpath/$executable", qw(--nofork --debug --nolog), @_;
+ exec qw(screen -m -d valgrind -v --tool=memcheck --leak-check=yes --db-attach=yes --num-callers=30), "$binpath/$executable", qw(--nofork --debug --nolog), @_;
die "Failed to start screen: $!\n";
}
sub cmd_stop()
{
- if (getstatus() == 0) { print "InspIRCd is not running. (Or PID File not found)\n"; return 0; }
+ if (getstatus() == 0) { print "InspIRCd is not running. (Or PID File not found)\n"; return GENERIC_EXIT_SUCCESS; }
# Get to here, we have something to kill.
my $pid = getprocessid();
print "Stopping InspIRCd (pid: $pid)...\n";
- my $maxwait = (`ps -o command $pid` =~ /valgrind/i) ? 90 : 15;
+ my $maxwait = (`ps -o command $pid 2>/dev/null` =~ /valgrind/i) ? 90 : 15;
kill TERM => $pid or die "Cannot terminate IRCd: $!\n";
for (1..$maxwait) {
sleep 1;
if (getstatus() == 0) {
print "InspIRCd Stopped.\n";
- return;
+ return GENERIC_EXIT_SUCCESS;
}
}
print "InspIRCd not dying quietly -- forcing kill\n";
kill KILL => $pid;
- return 0;
+ return GENERIC_EXIT_SUCCESS;
}
###
# Generic Helper Functions.
###
-# GetPidfile Version 2 - Now With Include Support..
-# I beg for months for include support in insp, then..
-# when it is added, it comes around and BITES ME IN THE ASS,
-# because i then have to code support into this script.. Evil.
-
-# Craig got bitten in the ass again --
-# in 1.1 beta the include file is manditory, therefore
-# if we cant find it, default to %conf%/inspircd.pid.
-# Note, this also contains a fix for when the pid file is
-# defined, but defined in a comment (line starts with #)
-# -- Brain
-
my %filesparsed;
sub getpidfile
if ($pid ne "") {
return;
}
- # Are We using a relative path?
- if ($file !~ /^\//) {
- # Convert it to a full path.
- $file = $runpath .'/'. $file;
- }
+
+ # Expand any relative paths.
+ $file = expand_fragment $confpath, $file;
# Have we checked this file before?
return if $filesparsed{$file};
if (($i =~ /<pid file=\"(\S+)\">/i) && ($i !~ /^#/))
{
# Set the PID file and return.
- $pidfile = $1;
- if (-f $pidfile)
- {
- return;
- }
- elsif (-f "$runpath/$pidfile")
- {
- $pidfile = "$runpath/$pidfile";
- return;
- }
+ $pidfile = expand_fragment $runtimedir, $1;
return;
}
}
}
# End of includes / No includes found. Using default.
- $pidfile = $datadir . "/inspircd.pid";
+ $pidfile = $runtimedir . "/inspircd.pid";
}
sub getstatus {
unless(`valgrind --version`)
{
print "Couldn't start valgrind: $!\n";
- exit;
+ exit GENERIC_EXIT_UNSPECIFIED;
}
}
unless(`gdb --version`)
{
print "Couldn't start gdb: $!\n";
- exit;
+ exit GENERIC_EXIT_UNSPECIFIED;
}
}
unless(`screen --version`)
{
print "Couldn't start screen: $!\n";
- exit;
+ exit GENERIC_EXIT_UNSPECIFIED;
}
}