#!/usr/bin/perl -w
use strict;
use POSIX ":sys_wait_h";

my $dryrun=0;
$dryrun=1 if(@ARGV and "-d" eq $ARGV[0] and shift @ARGV);
my $secs_to_wait=10;
$secs_to_wait=shift @ARGV if(1<@ARGV and "-w" eq $ARGV[0] and $ARGV[1] =~ /^\d+$/s and shift @ARGV);
die "usage: $0 [-d] [-w <seconds>]\n" if(@ARGV);

# We can't IGNORE the SIGCHLD, as we want it to stick around until our wait():
$SIG{CHLD}="DEFAULT";
my %kids=();

my @user;
while(@user=getpwent()) {
	my ($user,$home,$shell)=@user[0,7,8];
# 0=user pass 2=uid 3=gid quota comment gcos 7=dir 8=shell expire
	next if("/bin/false" eq $shell);
	next unless(-x "$home/.runonstop");
	if($dryrun) {
		print "Running $home/.runonstop as $user\n";
		next;
	}
	my $pid=fork();
	die "fork: $!" if($pid<0);
	if(0==$pid) {
		close(STDIN);
		close(STDOUT);
		close(STDERR);
		exec "su","-l","-c","./.runonstop",$user;
		exit -1;
	}
	$kids{$pid}=$user;
}
endpwent() or die "endpwent: $!";

if(%kids) {
	$|=1;
	print "Waiting for runonstop programs to finish...";
	while(%kids) {
		my $kid=waitpid(-1,WNOHANG);
		die "waitpid: $!" if($kid<0);
		if(0==$kid) {
			last unless($secs_to_wait--);
			sleep(1);
			print "$secs_to_wait..." if($secs_to_wait);
			next;
		}
		delete $kids{$kid};
	}
	print "\n";
	if(%kids) {
		my @kids=keys %kids;
		print "runonstop took too long for: ".join(" ",sort map {$kids{$_}} @kids)."\n";
	}
}
0;
