[alt.sources] rdate - set time from another network system

keith@sequoia.execu.com (Keith Pyle) (11/29/90)

rdate is functionally similar to the rdate command found in SunOS 4.1.
It is not based on or written with knowledge of source code from
SunOS.  rdate provides a means for setting the date of the local
machine from another machine through use of the TCP time protocol
defined in RFC868.  Extensions are provided over the SunOS rdate: (1)
to allow specification of multiple time servers, (2) to simply display
the server(s) time and not set the local machine's date, and (3) to
optionally use the adjtime system call, if available, to gradually
adjust the local time.

----- cut here and run through unshar or sh -----
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  INSTALL MANIFEST Makefile PORTING README port.c rdate.8
#   rdate.c rdate.h sockio.c
# Wrapped by keith@lime on Wed Nov 28 13:04:37 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'INSTALL' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'INSTALL'\"
else
echo shar: Extracting \"'INSTALL'\" \(963 characters\)
sed "s/^X//" >'INSTALL' <<'END_OF_FILE'
XSoftware Requirements
X---------------------
X
X- C compiler
X
X- support for sockets
X
X- at least one machine providing timed service
X
XInstallation
X------------
X
X1) Unpack the package in an appropriate directory
X
X2) Edit the Makefile to specify the desired configuration items
X
X3) Issue the command 'make' to build the binary
X
X4) Test the program with the following commands (not run as root):
X
X   ./rdate -d server
X   ./rdate server
X
X   where server is a machine providing timed service.  The first command
X   should display the server's time.  The second should fail with an
X   error message: "couldn't set time of day: Not owner".
X
X5) Login as root
X
X6) Repeat the second command from step 4 if you wish to actually set
X   the local machine's date
X
X7) Type 'make install' to copy the binary and the man page to the
X   directories specified in the Makefile.
X
X8) Modify your system files (e.g., /etc/rc.local or root's crontab)
X   as appropriate for your use of rdate
END_OF_FILE
if test 963 -ne `wc -c <'INSTALL'`; then
    echo shar: \"'INSTALL'\" unpacked with wrong size!
fi
# end of 'INSTALL'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(248 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
XINSTALL			Installation instructions
XMANIFEST		This file
XMakefile		The name says it
XPORTING			Comments on porting rdate to a new environment
XREADME			Some important comments
Xrdate.8			man page for rdate
X
Xcode files:
X
Xrdate.c
Xport.c
Xsockio.c
Xrdate.h
END_OF_FILE
if test 248 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(875 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# rdate Makefile
X
X# --- Uncomment one set of the following flag definitions ---
X
X# For SunOS, Ultrix, HP/UX, or generic BSD
X
XCFLAGS = -O
XLDFLAGS =
X
X# For Sequent Dynix
X
X# CFLAGS = -O
X# LDFLAGS = -lseq
X
X# For other BSD which have adjtime(2)
X
X# CFLAGS = -O -DHAS_ADJTIME
X# LDFLAGS =
X
X# For AIX, generic System V
X
X# CFLAGS = -O -DSYSV
X# LDFLAGS =
X
X# For Unisys U6000
X
X# CFLAGS = -O -DSYSV
X# LDFLAGS = -lsocket
X
X# For Interactive 386/ix
X
X# CFLAGS = -O -DSYSV -D386IX
X# LDFLAGS = -linet
X
X# --- Define the installation parameters ---
X
XBINDIR = /usr/local/bin
XMANEXT = 8
XMANDIR = /usr/man/man$(MANEXT)
X
X# --- The following should not need to be changed ---
X
XRDATE_OBJS = rdate.o port.o sockio.o
X
Xall: rdate
X
Xrdate: $(RDATE_OBJS)
X	cc $(CFLAGS) -o rdate $(RDATE_OBJS) $(LDFLAGS)
X
Xrdate.o port.o: $($@:.o=.c) rdate.h
X
Xinstall:
X	cp rdate $(BINDIR)
X	cp rdate.8 $(MANDIR)/rdate.$(MANEXT)
END_OF_FILE
if test 875 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'PORTING' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'PORTING'\"
else
echo shar: Extracting \"'PORTING'\" \(1651 characters\)
sed "s/^X//" >'PORTING' <<'END_OF_FILE'
XPorting
X-------
X
XThe initial porting effort identified three items which were version
Xspecific.  Each of the affect areas of the code is wrapped in cpp(1)
Xdirectives to allow selection of known alternatives through appropriate
X#define statements.  The file rdate.h uses preset cpp(1) definitions
X(e.g., sun on SunOS systems) to specify the correct set of #define
Xstatements, where possible.  It is still necessary to specify some
Xflags through the Makefile.  The current code has been ported to and
Xtested on the following hardware/software combinations:
X
XHP 9000/825, HP/UX A.B7.00
XSun 3, SunOS 4.1
XSequent Symmetry, DYNIX 3.0.17
XVAX 3602, Ultrix 3.1
XPS/2, AIX
XUnisys U6000/51, System Vr3
XInteractive 386/ix
X
XTo port rdate to another environment:
X
X1) Determine if your system is BSD-like or System V-like: does it use
X   settimeofday(2) or stime(2), respectively?
X
X2) If it is BSD-like, does it have adjtime(2)?
X
X3) Modify Makefile, and possibly rdate.h, according to the following:
X
X   If it is BSD-like and does not have adjtime(2), just use the generic
X   BSD compile and link flags.
X
X   If it is BSD-like and has adjtime(2), use the BSD flags which define
X   HAS_ADJTIME or modify rdate.h (in the manner used for sun and ultrix)
X   to automatically define this).
X
X   If it is System V-like, start by using the generic System V flags.
X   If this results in undefined references at link time, there is
X   probably a special link flag to include the socket routines.  Delve
X   into the manuals and determine what standard you vendor has chosen
X   to set.
X
X4) If this still isn't sufficient, get out the Veg-O-Matic and
X   start slicing and dicing.
X
END_OF_FILE
if test 1651 -ne `wc -c <'PORTING'`; then
    echo shar: \"'PORTING'\" unpacked with wrong size!
fi
# end of 'PORTING'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(2288 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XKeith's rdate
X
XCopyright (c) 1990, W. Keith Pyle, Austin, Texas
X
XDescription
X-----------
X
Xrdate is functionally similar to the rdate command found in SunOS 4.1.
XIt is not based on or written with knowledge of source code from
XSunOS.  rdate provides a means for setting the date of the local
Xmachine from another machine through use of the TCP time protocol
Xdefined in RFC868.  Extensions are provided over the SunOS rdate: (1)
Xto allow specification of multiple time servers, (2) to simply display
Xthe server(s) time and not set the local machine's date, and (3) to
Xoptionally use the adjtime system call, if available, to gradually
Xadjust the local time.
X
Xrdate has been ported to:
X
XHP 9000/825, HP/UX A.B7.00
XSun 3, SunOS 4.1
XSequent Symmetry, DYNIX 3.0.17
XVAX 3602, Ultrix 3.1
XPS/2, AIX
XUnisys U6000/51, System Vr3
XInteractive 386/ix
X
XSee the man page for more information on the command.
XSee the file INSTALL for installation instructions.
XSee the file PORTING for porting comments.
X
XQualifications
X--------------
X
XThis program may be copied, transferred, or used in any manner subject
Xto the following conditions:
X
X1) The original README and MANIFEST files must be retained
X   in any subsequent source distributions, whether unaltered or not.
X
X2) Neither the author nor his employer make any express or implied
X   warranties as to the fitness of this program for any particular
X   purpose.  The user assumes full responsible for the use of this
X   program and any consequences of its use whether due to defect,
X   misuse, abuse, etc.
X        
X3) The origin of this program must not be misrepresented, either
X   by explicit claim or omission.
X        
X4) Altered versions of this program must be clearly identified as
X   such and may not be represented as the original.
X        
X5) This program may not be sold in any form without the express
X   written consent of the author.
X
X6) Should any of the above be held unenforceable, the remainder shall
X   remain in force.
X
XContacting the Author
X---------------------
X 
XReports of bugs, requests for enhancements, comments, compliments, and
Xflames may be sent to the author at the following address.
X
XKeith Pyle                                UUCP: ...!uunet!execu!keith
XExecucom Systems Corp., Austin, Texas     Internet: keith@execu.com
END_OF_FILE
if test 2288 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'port.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'port.c'\"
else
echo shar: Extracting \"'port.c'\" \(1201 characters\)
sed "s/^X//" >'port.c' <<'END_OF_FILE'
X/* port --- routines to deal with sockets and ports for user programs */
X
X/* Copyright (c) 1990, W. Keith Pyle, Austin, Texas */
X
X#include "rdate.h"
X
X/* ------------------------------------------------------------------------- */
X
Xopen_port(host, port)
X
Xchar *host;
Xint port;
X
X{
X	int socket_fd;
X
X	struct hostent *hentry;
X	struct sockaddr_in sa;
X
X	/* Make sure there is a host name specified */
X
X	if (host == NULL || *host == '\0') {
X
X		errno = EDESTADDRREQ;
X		return(-1);
X	}
X
X	/* Get the host file entry for the named host */
X
X	if ((hentry = gethostbyname(host)) == NULL) {
X
X		errno = ECONNREFUSED;
X		return(-1);
X	}
X
X	/* Clear the socket structure */
X
X	bzero((char *)&sa, sizeof(sa));
X
X	/* Put the host's address in the socket structure */
X
X	bcopy(hentry->h_addr, (char *)&sa.sin_addr, hentry->h_length);
X
X	/* Set the address type and port */
X
X	sa.sin_family = hentry->h_addrtype;
X	sa.sin_port = htons((unsigned short)port);
X
X	/* Open the socket */
X
X	if ((socket_fd = socket(hentry->h_addrtype, SOCK_STREAM, 0)) < 0)
X		return(-1);
X	
X	/* Connect to the port */
X
X	if (connect(socket_fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)
X		return(-1);
X	
X	/* Return the socket descriptor */
X
X	return(socket_fd);
X}
END_OF_FILE
if test 1201 -ne `wc -c <'port.c'`; then
    echo shar: \"'port.c'\" unpacked with wrong size!
fi
# end of 'port.c'
fi
if test -f 'rdate.8' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rdate.8'\"
else
echo shar: Extracting \"'rdate.8'\" \(2296 characters\)
sed "s/^X//" >'rdate.8' <<'END_OF_FILE'
X.TH "RDATE" 8L "14 November 1990" "Execucom" "LOCAL USER COMMANDS"
X.SH NAME
Xrdate \- set the system date/time from a remote host
X.SH SYNOPSIS
X.LP
X.B rdate
X[
X.B \-adD
X]
X.I host
X[
X.I host
X] ...
X.SH DESCRIPTION
X.B rdate
Xuses a specified remote host as a time server and resets the local system
Xdate/time to the value supplied by the remote host.  One or more hosts
Xcan be specified on the command line.
X.B rdate
Xwill use the value from the first host which responds.  Thus, the date/time
Xcan be reset even if the primary time server does not respond.
X.LP
XWhen a host has responded to the
X.B rdate
Xrequest and the local date/time has been set, the name of the responding
Xhost and the time will be displayed on standard output.
X.LP
X.B rdate
Xuses the TCP Time Protocol service specified in RFC868.  This service
Xprovides the number of seconds since 00:00:00 1 January 1900 GMT on port 37.
XThe returned value is corrected to the Unix epoch, 00:00:00 1 January 1970
XGMT. Depending on the command line options, this value is used
X(1) to reset the local machine's date/time immediately to the new value,
X(2) to adjust the local machine's date/time gradually to the new value,
Xor (3) for display only.  The default is to reset the local date/time.
XSince the system calls used to modify the date/time
Xare privileged,
X.B rdate
Xmust be run by root to successfully change the local date/time.
X.LP
X.B rdate
Xis often used in a startup file such as /etc/rc.local to set the system
Xdate/time.
X.SH OPTIONS
X.TP
X.B \-a
XUse the server's time to gradually adjust the local date/time to the new
Xvalue.
XThis technique guarantees that there are no time discontinuities as the
Xtime is changed.
X.ft I
X(N.B.:
XThe system call to gradually adjust time
Xis not available on all versions of Unix and this
Xoption will not be provided on those systems.)
X.ft R
X.TP
X.B \-d
XDisplay the time from the first server to respond.
XDo not adjust or set the local machine's date/time.
X.TP
X.B \-D
XDisplay the time from all servers that respond.
XDo not adjust or set the local machine's date/time.
X.SH AUTHOR
XKeith Pyle
X.SH DIAGNOSTICS
XThe exit status is 0 for mormal execution.  If none of the specified hosts
Xrespond or if the time can not changed, the exit status is set to 1.  Syntax
Xerrors result in a usage message and an exit status of 2.
END_OF_FILE
if test 2296 -ne `wc -c <'rdate.8'`; then
    echo shar: \"'rdate.8'\" unpacked with wrong size!
fi
# end of 'rdate.8'
fi
if test -f 'rdate.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rdate.c'\"
else
echo shar: Extracting \"'rdate.c'\" \(3339 characters\)
sed "s/^X//" >'rdate.c' <<'END_OF_FILE'
X/* rdate --- get the date from the date server on a specified host */
X/*           and reset the local system date/time */
X
X/* Copyright (c) 1990, W. Keith Pyle, Austin, Texas */
X
X#include "rdate.h"
X
Xextern int optind;
Xextern int opterr;
X
Xvoid change_time();
X
X/* ------------------------------------------------------------------------- */
X
Xmain(argc, argv)
X
Xint argc;
Xchar *argv[];
X
X{
X	int adjust;
X	int argno;
X	int display_all;
X	int display_only;
X	int flag;
X	int socket_fd;
X	int success;
X
X	unsigned long tod;
X
X	adjust = FALSE;
X	display_all = FALSE;
X	display_only = FALSE;
X	opterr = 0;
X	success = FALSE;
X
X	while ((flag = getopt(argc, argv, "adD")) != EOF) {
X
X		switch (flag) {
X
X			case 'a':
X
X#ifdef HAS_ADJTIME
X				adjust = TRUE;
X#else
X				(void)fprintf(stderr, "-a not supported on this system\n");
X				exit(1);
X#endif
X				break;
X			
X			case 'd':
X
X				display_only = TRUE;
X				break;
X			
X			case 'D':
X
X				display_only = TRUE;
X				display_all = TRUE;
X				break;
X			
X			default:
X
X				(void)fprintf(stderr, "%s: invalid argument: %c\n", argv[0],
X					flag);
X				exit(1);
X		}
X	}
X
X	/* Was a host specified? */
X
X	if ((argc - optind) < 1) {
X
X		(void)fprintf(stderr, "usage: %s [-ad] host [host] ...\n", argv[0]);
X		exit(2);
X	}
X
X	/* Try the hosts in order until one of them responds */
X
X	for (argno = optind ; argno < argc ; argno++) {
X
X		/* Open the timed port on the host specified by the argument */
X
X		if ((socket_fd = open_port(argv[argno], TIME_PORT)) < 0)
X			continue;
X
X		/* Get the time value */
X
X		if (read_socket(socket_fd, (char *)&tod, sizeof(int)) == sizeof(int)) {
X
X			success = TRUE;
X
X			/* Convert tod to host byte order and correct it to Unix time */
X			/* (timed returns seconds since 00:00:00 1 January 1900 GMT) */
X
X			tod = ntohl(tod);
X			tod -= 2208988800;
X
X			if (!display_only)
X				change_time(tod, adjust);
X			
X			/* Display the value and where we got it */
X
X			(void)printf("%s%s: %s",
X				display_only ? "" : (adjust ? "adjusted to " : "set to "),
X				argv[argno], ctime((time_t *)&tod));
X
X			if (!display_all)
X				break;
X		}
X		
X		(void)close(socket_fd);
X	}
X
X	/* Was an attempt successful? */
X
X	if (!success) {
X
X		(void)fprintf(stderr, "couldn't get time from any listed host\n");
X		exit(1);
X	}
X
X	/* We're done */
X
X	(void)close(socket_fd);
X	exit(0);
X	/* NOTREACHED */
X}
X
X/* ------------------------------------------------------------------------- */
X
Xvoid
Xchange_time(tod, adjust)
X
Xunsigned long tod;
Xint adjust;
X
X{
X#ifndef SYSV
X	struct timeval timeval;
X
X	/* Put it in the timeval structure for settimeofday */
X
X	timeval.tv_sec = tod;
X	timeval.tv_usec = 0;
X#endif
X
X	/* Are we to adjust the time or just set it? */
X
X	if (adjust) {
X
X#ifdef HAS_ADJTIME
X		struct timeval currtime;
X
X		/* Get the local time and determine the adjustment */
X
X		if (gettimeofday(&currtime, (struct timezone *)NULL) < 0) {
X
X			perror("couldn't get local time of day");
X			exit(1);
X		}
X
X		timeval.tv_sec -= currtime.tv_sec;
X		timeval.tv_usec -= currtime.tv_usec;
X
X		/* Adjust it */
X
X		if (adjtime(&timeval, (struct timeval *)NULL) < 0) {
X
X			perror("couldn't adjust time");
X			exit(1);
X		}
X#endif
X	}
X
X	/* Set the time of day, but leave the timezone alone */
X
X#ifndef SYSV
X	else if (settimeofday(&timeval, (struct timezone *)NULL) < 0) {
X#else
X	else if (stime(&tod) < 0) {
X#endif
X
X		perror("couldn't set time of day");
X		exit(1);
X	}
X
X	return;
X}
END_OF_FILE
if test 3339 -ne `wc -c <'rdate.c'`; then
    echo shar: \"'rdate.c'\" unpacked with wrong size!
fi
# end of 'rdate.c'
fi
if test -f 'rdate.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rdate.h'\"
else
echo shar: Extracting \"'rdate.h'\" \(688 characters\)
sed "s/^X//" >'rdate.h' <<'END_OF_FILE'
X/* rdate.h --- include file for remote server date setting utility */
X
X/* Copyright (c) 1990, W. Keith Pyle, Austin, Texas */
X
X#if defined(sun) || defined(ultrix)
X#define HAS_ADJTIME
X#endif
X
X#if defined(hpux)
X#define bcopy(from, to, count) memcpy(to, from, count)
X#define bzero(to, count) memset(to, 0, count)
X#endif
X
X#if defined(SYSV) && defined(HAS_ADJTIME)
X#undef HAS_ADJTIME
X#endif
X
X#include <stdio.h>
X#include <errno.h>
X#include <time.h>
X#include <sys/types.h>
X#include <sys/time.h>
X#include <sys/uio.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <netdb.h>
X
X#ifdef 386IX
X#include <net/errno.h>
X#endif
X
X#define TIME_PORT	37
X
X#define FALSE	0
X#define TRUE	1
X
Xvoid exit();
END_OF_FILE
if test 688 -ne `wc -c <'rdate.h'`; then
    echo shar: \"'rdate.h'\" unpacked with wrong size!
fi
# end of 'rdate.h'
fi
if test -f 'sockio.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sockio.c'\"
else
echo shar: Extracting \"'sockio.c'\" \(866 characters\)
sed "s/^X//" >'sockio.c' <<'END_OF_FILE'
X/* sockio --- read and write routines for use with sockets */
X
X/* Copyright (c) 1990, W. Keith Pyle, Austin, Texas */
X
X/* ------------------------------------------------------------------------- */
X
Xread_socket(socket_fd, buffer, size)
X
Xint socket_fd;
Xregister char *buffer;
Xregister int size;
X
X{
X	register int bytes;
X	register int n;
X
X	bytes = 0;
X
X	while (bytes < size) {
X
X		if ((n = read(socket_fd, buffer + bytes, size - bytes)) < 0)
X			return(n);
X		
X		bytes += n;
X	}
X
X	return(bytes);
X}
X
X/* ------------------------------------------------------------------------- */
X
Xwrite_socket(socket_fd, buffer, size)
X
Xint socket_fd;
Xregister char *buffer;
Xregister int size;
X
X{
X	register int bytes;
X	register int n;
X
X	bytes = 0;
X
X	while (bytes < size) {
X
X		if ((n = write(socket_fd, buffer + bytes, size - bytes)) < 0)
X			return(n);
X		
X		bytes += n;
X	}
X
X	return(bytes);
X}
END_OF_FILE
if test 866 -ne `wc -c <'sockio.c'`; then
    echo shar: \"'sockio.c'\" unpacked with wrong size!
fi
# end of 'sockio.c'
fi
echo shar: End of shell archive.
exit 0
-----------------------------------------------------------------------------
Keith Pyle                                UUCP: ...!cs.utexas.edu!execu!keith
Execucom Systems Corp., Austin, Texas     Internet: keith@execu.com
"It's 10 o'clock.  Do you know where      Disclaimer: Everything I say is
   your child processes are?"               true unless I use the word 'the'.
-----------------------------------------------------------------------------

keith@sequoia.execu.com (Keith Pyle) (11/29/90)

A small oops in the source posting:  in the rdate.h and Makefile, the
string 386IX should be I386IX.  Last minute changes always bite...
-- 
-----------------------------------------------------------------------------
Keith Pyle                                UUCP: ...!cs.utexas.edu!execu!keith
Execucom Systems Corp., Austin, Texas     Internet: keith@execu.com
"It's 10 o'clock.  Do you know where      Disclaimer: Everything I say is
   your child processes are?"               true unless I use the word 'the'.
-----------------------------------------------------------------------------