1/* vi: set sw=4 ts=4: */ 2/* 3 * The Rdate command will ask a time server for the RFC 868 time 4 * and optionally set the system time. 5 * 6 * by Sterling Huxley <sterling@europa.com> 7 * 8 * Licensed under GPL v2 or later, see file License for details. 9*/ 10 11#include "libbb.h" 12 13enum { RFC_868_BIAS = 2208988800UL }; 14 15static void socket_timeout(int sig) 16{ 17 bb_error_msg_and_die("timeout connecting to time server"); 18} 19 20static time_t askremotedate(const char *host) 21{ 22 uint32_t nett; 23 int fd; 24 25 /* Add a timeout for dead or inaccessible servers */ 26 alarm(10); 27 signal(SIGALRM, socket_timeout); 28 29 fd = create_and_connect_stream_or_die(host, bb_lookup_port("time", "tcp", 37)); 30 31 if (safe_read(fd, (void *)&nett, 4) != 4) /* read time from server */ 32 bb_error_msg_and_die("%s did not send the complete time", host); 33 close(fd); 34 35 /* convert from network byte order to local byte order. 36 * RFC 868 time is the number of seconds 37 * since 00:00 (midnight) 1 January 1900 GMT 38 * the RFC 868 time 2,208,988,800 corresponds to 00:00 1 Jan 1970 GMT 39 * Subtract the RFC 868 time to get Linux epoch 40 */ 41 42 return ntohl(nett) - RFC_868_BIAS; 43} 44 45int rdate_main(int argc, char **argv); 46int rdate_main(int argc, char **argv) 47{ 48 time_t remote_time; 49 unsigned long flags; 50 51 opt_complementary = "-1"; 52 flags = getopt32(argv, "sp"); 53 54 remote_time = askremotedate(argv[optind]); 55 56 if ((flags & 2) == 0) { 57 time_t current_time; 58 59 time(¤t_time); 60 if (current_time == remote_time) 61 bb_error_msg("current time matches remote time"); 62 else 63 if (stime(&remote_time) < 0) 64 bb_perror_msg_and_die("cannot set time of day"); 65 } 66 67 if ((flags & 1) == 0) 68 printf("%s", ctime(&remote_time)); 69 70 return EXIT_SUCCESS; 71} 72