Linux-realtimed

 view release on metacpan or  search on metacpan

bin/realtimed  view on Meta::CPAN

use Time::HiRes;
use warnings;
use strict;
use Socket;
#use Fcntl;
use JSON;
use v5.10;
use EV;

BEGIN {
	sub lg ($;$$) {
		my ($message, $activity, $priority) = @_;
		$priority //= 'info';
		state $status = {};
		my $curtime = [Time::HiRes::gettimeofday()];
		my $elapsed = '';
		if($activity) {
			$elapsed = Time::HiRes::tv_interval($status->{$activity}->{timestamp}) if $status->{$activity}->{timestamp};
			$status->{$activity}->{timestamp} = $curtime;
			$elapsed = qq|- elapsed time: ${\sprintf("%.6f", $elapsed)} seconds| if $elapsed;
		}

		my @caller = caller(1);
		syslog $priority , '%s %s %s', $message, $elapsed, "at line $caller[2]";
	}

	my @priorities = ('emerg', 'alert', 'crit', 'err', 'warning', 'notice', 'info', 'debug');

	{
		no strict 'refs'; ## no critic
		for (@priorities) {
			my $priority = $_;
			*{__PACKAGE__ . "::$priority"} = sub ($;$) {
				my ($message, $activity) = @_;
				lg $message, $activity, $priority;
			};
		}
	}
}

# resolved to name this daemon "realtimed" cause
# suitable names already taken by other entities:
# inotifyd by Alpine Linux
# notifyd by Cyrus IMAP
# eventd by eventd.org
my $myrelpath = __FILE__;
open my $fh, '<', $myrelpath;
my $fd = fileno $fh;
my $myfullpath = readlink("/proc/$$/fd/$fd");
close $fh;
my $programname = 'realtimed';
$programname = $1 if $myfullpath =~ m{([^/]+)$};

openlog $programname, 'ndelay,pid', 'daemon';
info "detected current realtimed relative path as: $myrelpath";
info "detected current realtimed absolute path as: $myfullpath";
info "detected program name as: $programname";

my $euid = geteuid;
my $uid = getuid;
my $user = getpwuid($uid);
my $euser = getpwuid($euid);
my $rootuser = getpwuid(0);

unless ($euid == $uid){
	my $msg = "you ($user) are executing this program with setuid to $euser credentials, exiting";
	emerg $msg;
	say $msg;
	exit;
}

unless ($uid == 0){
	my $msg = "you are executing this program with $user credentials, this program requires $rootuser (uid 0) credentials to work";
	emerg $msg;
	say $msg;
	exit;
}

my $pidfile = "/var/run/${programname}.pid";
if ( -e $pidfile ) {
	my $msg = "unable to open PID file $pidfile";
	open my $fh, '<', $pidfile or emerg $msg && die $msg;
	my $pid = <$fh>;
	close $fh;
	if($pid) {
		alert "PID file $pidfile already existent for process $pid";
		if (kill 0, $pid) {
			emerg "preexistent process $pid still running, exiting";
			stopDaemon(1);
		}
	}
	alert "removing PID file $pidfile for defunct process $pid, that probably didn't shut down properly";
	unlink $pidfile;
}

my $confdir = "/etc/$programname";
unless ( -e $confdir && -d $confdir ){
	# no need for 'mkdir -p' or make_path from File::Path cause /etc must exists
	warning "main configuration directory $confdir does not exist, creating it";
	mkdir $confdir, 0755 or crit "cannot create conf directory $confdir" && exit 0;
}

my $rsyslogconffile = "/etc/rsyslog.d/${programname}.conf";
unless(-e $rsyslogconffile && -T $rsyslogconffile) {
	my $message = "$programname rsyslog conf file $rsyslogconffile does not exist, creating it";
	warning $message;
	say $message;

	my $rsyslogconf = qq{\$template	$programname,"%TIMESTAMP:::date-rfc3339% %syslogtag% %syslogseverity-text%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\\n"
:programname, isequal, "$programname" -/var/log/${programname}.log;$programname & stop
};

	# we assume rsyslog is installed, as it is for all main Linux distributions
	open my $fh, '>', $rsyslogconffile or die "cannot set rsyslog template: $@ $!";
	print $fh $rsyslogconf;
	close $fh;

	info 'restarting rsyslog:';
	info qx{systemctl restart rsyslog};

	info 'closing and reopening syslog';
	closelog;
	openlog $programname, 'ndelay,pid', 'daemon';



( run in 3.196 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )