#!/usr/bin/perl # The TIMECRISIS TIME SYNC PROGRAM! YEAH! YEAH! YEAH! BOOOOOOYEAH! # TIME SYNCH! YOU BET YOUR BE-YOOOOOOOOOOOOOUTIFUL SELF! # There's no time like the present, and darn it, we'll drag you there! # A Quinn Martin^W^WCameron Kaiser production, based on RFC 868 # This code is actually based on the fault-tolerant Gopher network client # used in the helsinki-generation V-2 robot. select(stdout); $|++; $TIMEOUT = 60; # longer for thule because it's slow, sigh $MAX_SOCK_RETRIES = 5; $NET_OK = 0; $NET_ERROR = 1; sub network { my ($them, $port) = (@_); local $kid; local $buffer; $kid = 0; die if (!length($them)); $port ||= 37; my $child = open(NETW, "-|"); if ($child) { my $rc; # parent process while() { $buffer .= $_; } close(NETW); $rc = $?; if ($rc) { return ($NET_ERROR, $buffer); } else { return ($NET_OK, $buffer); } die; } # child $SIG{'USR1'} = $SIG{'ALRM'} = sub { print "Timeout/user signal"; exit 255; }; $SIG{'INT'} = sub { print "Interrupt"; exit 1; }; alarm $TIMEOUT; RETRY: sleep 2 if ($sockaddr); $stries++; if ($stries >= $MAX_SOCK_RETRIES) { print "Repeated connect failure"; exit 255; } $sockaddr = 'S n a4 x8'; ($name, $aliases, $type, $len, $thataddr) = gethostbyname($them); if (!$name) { print "No such server"; exit 254; } $that = pack($sockaddr, 2, $port, $thataddr, 0); # AF_INET SOCK_STREAM IPPROTO_TCP socket(SOCK, 2, 1, 6) || (goto RETRY); if (!connect(SOCK, $that)) { if ($! =~ /refused/i) { print "connect: $!"; exit 254; } if ($! =~ /socket name/i) { print "connect: $!"; exit 254; } goto RETRY; } # Read the 32 bit network order time code. sysread(SOCK, $buffer, 4); print $buffer; close(SOCK); exit 0; } ($rc, $data) = &network('oslo'); die("Network failure: $data\n") if ($rc != $NET_OK); die("Time signal corrupt\n") if (length($data) != 4); # convert to seconds past the time(1) epoch # range 1 year of fudging to ensure we don't get crap from our server $w = unpack("N", $data) - 2240524800; # not 2208988800 ; die("Epoch range fault! The end of the world is near! => $w") if ($w < 1); $w += 31536000; # 365*24*60*60; # add back one year to get the right time $compiler = "/bin/cc"; $compiler = "/usr/bin/gcc" if (! -x $compiler); $temp = "/tmp/settime-$$"; open(W, ">${temp}.c") || die("Unable to write $temp for timeset: $!\n"); print W <<"EOF"; #include #include #include #include main(argc, argv) int argc; char **argv; { struct timeval tp; tp.tv_sec = $w; tp.tv_usec = 0; exit((settimeofday(&tp,0)) ? errno : 0); } EOF close(W); system("$compiler -o $temp ${temp}.c"); die("Compile step failure\n") if (! -x $temp); system("$temp"); warn("Unable to set time: errno = $?\n") if ($?); unlink($temp, "${temp}.c"); exit;