#! /usr/bin/perl -w
use strict;
use Socket; # so we can broadcast on udp
use POSIX;

# A deamon to broadcast our name/ip info once in awhile.
# Some other daemon will be listening and updating its /etc/hosts as required

#****************************************globals
my $time_to_die = 0; # shutdown cleanly
my $pid; # for daemonizing
my @IPs; # for multihomed hosts, just broadcast one
my $debug = 0; # don't print if daemonized
my $name; # my name on the ethernet
my $ipaddr; # my ip on the lan
my $msgsock; # the socket
my $portno = 53831; # birthday port-y
my $dest = sockaddr_in($portno, inet_aton("192.168.1.255"));
my $msg; # what I'm going to broadcast

#****************************************
sub mynetinfo ()
{
# some of this is easier, some harder than for the other machines on the net
 open (MYNAME, "hostname |") or die "Can't run hostname utility: $!";
 $name = <MYNAME>; # note, chomp to get rid of /n
 chomp $name;
 close (MYNAME) or die "Can't close hostname utility: $!";
 
 open (MYIP, "hostname -I |") or die "Can't run hostname -I:$!";
 $ipaddr = <MYIP>;
 close (MYIP) or die "Can't close hostname -I"; 
 @IPs = split /\s+/, $ipaddr; # might be more than one
 print LOG "IPs:@IPs\n" if $debug;
 
foreach (@IPs)
 {
  $ipaddr = $_;
  print LOG "ipaddr:$ipaddr\n" if $debug;
  last if ($ipaddr =~ /192.168.1/);
 }
 print LOG "ipaddr after loop:$ipaddr\n" if $debug;
 chomp $ipaddr;
 
 $msg = "$ipaddr $name";
}
#****************************************
sub setupsock()
{
 socket($msgsock,PF_INET,SOCK_DGRAM,getprotobyname("udp")) or die "socket:$!";
 setsockopt($msgsock, SOL_SOCKET, SO_BROADCAST,1) or die "setsockopt:$!";
}
#****************************************
sub signal_handler 
{ 
 $time_to_die = 1; 
 print LOG "Killed by sig\n" if $debug;
}
########################### main
open (LOG, "> /tmp/tellem.log") or die "couldn't open logfile";
print LOG "started\n";
$pid = fork(); # we're going to detach from whoever started us
exit if $pid; # parent dies
die "Couldn't fork: $!" unless defined($pid);
POSIX::setsid() or die "Can't start new session: $!";
close (STDIN); # never use it anyway
close (STDOUT) unless $debug;
close (STDERR) unless $debug;
$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&signal_handler;
setupsock(); # setup socket we'll broadcast from

until ($time_to_die)
{
 mynetinfo(); # set up/refresh my own net information
 print LOG ("msg:$msg\n");
 send($msgsock,"$msg",0,$dest) or die "send:$!";

 sleep int(rand(31) + 30);  # don't flood network or use too much machine here either
}
print LOG "Died\n";
