new setdate (source for a B.U. 4.2bsd version)

Barry Shein root at bu-cs.UUCP
Mon Mar 4 08:39:35 AEST 1985


This made me think of something we use here that I wrote.
It is only useful to those running TCP/IP (4.2bsd) although I
suppose it could be adapted to some other net.
Look at it a bit before relying on it, it is very simple:

Rdate just execs itself on a remote system to generate a
string which, when passed to system() will set the local time.
Some will consider this too naive to be relied on as a
remote time-server which is technically true but it is
going to be more accurate than just looking at your watch.
By accurate I mean: Will bring two systems into very close time
which may or may not be the correct time.

--------------------CUT HERE: /usr/man/man8/rdate.8--------------------
.TH RDATE 8L "20 Aug 1984"
.UC 4
.SH NAME
rdate \- remote date and time service
.SH SYNOPSIS
.B rdate
[
.B \-h
host
] [
.B \-u
user
] [
.B \-p
passwd
] [
.B \-s
] [
.B \-t
]
.SH DESCRIPTION
.I Rdate
sets the system's date and time by querying
another system over the network.
.PP
The
.I host
should default to a reasonable value or can be
overridden with the
.B \-h
flag followed by the host name. Obviously this other
host must also have this service.
.PP
You must be logged in as the super-user in order to
set the date on the current system. Unfortunately,
you must not be logged in as the super-user in order
to access the remote system (these are both intentional
features.)
.PP
To get around this you must specify
a non-privileged user name and password for
an account on the remote machine. This can
be done either on the command line via the
.B \-u
and
.B \-p
commands for
.I user
and
.I password
respectively
or, if either is
missing,
you will be prompted from
the terminal.
It is probably better to let
.B rdate
prompt for the password as it
is more secure (it will not echo.)
.PP
The
.B \-s
flag is for server mode and causes
.B rdate
to simply put out the system's current
date and time in a format that can be
executed to set the date and time.
This is the form that is used on the remote
machine by the local
.B rdate.
.PP
If the
.B \-t
flag is used
.B rdate
only prints the date command to the standard
output rather than actually setting the date.
This could be useful to check that the
remote system has a reasonable date
before actually setting it.
.SH FILES
/etc/hosts
.br
/etc/services
.SH SEE ALSO
rsh(1C), rexec(3X)
.SH AUTHOR
Barry Shein, Boston University Distributed Systems Group

--------------------CUT HERE rdate.c--------------------
#include <stdio.h>
#include <netdb.h>
#include <sys/time.h>

/*
 *	Very simple remote date routine for 4.2bsd
 *	Barry Shein, Boston University
 *
 *	The basic idea is that in one mode rdate remote-execs
 *	a copy of rdate on another machine with an appropiate
 *	flag. This remote rdate will produce the string for a
 *	UNIX date command which, when locally exec'd, will
 *	set the date.
 *	Net delays are not taken into account.
 */
#define RDATE	"/etc/rdate -s"
#define DEFHOST	"bu-cs"		/* YOUR REMOTE HOST HERE */
char *myname ;
int tflag = 0 ;
usage()
{
	fprintf(stderr,
		"Usage: %s [-s][-h host][-u user][-p passwd]\n",myname) ;
	exit(1) ;
}
main(argc,argv) int argc ; char **argv ;
{
	struct servent *s ;
	char *host = NULL, *user = NULL, *passwd = NULL ;
	char buf[BUFSIZ] ;
	int rfd, i ;
	char *getpass() ;

	myname = *argv ;
	--argc ;
	while(argc--)
	{
		++argv ;
		if(**argv == '-') switch((*argv)[1]) {
			case 'h' :	/* other remote host	*/
				if(argc < 1) usage() ;
				host = *++argv ;
				--argc ;
				break ;
			case 'u' :	/* user name to rexec under	*/
				if(argc < 1) usage() ;
				user = *++argv ;
				--argc ;
				break ;
			case 'p' :	/* passwd to rexec under	*/
					/* note: if omitted will use getpass */
				if(argc < 1) usage() ;
				passwd = *++argv ;
				--argc ;
				break ;
			case 's' :	/* I am the remote	*/
				rdate() ;
				exit(0) ;
			case 't' :	/* just testing		*/
				++tflag ;
				break ;
			default :
				usage() ;
		}
		else usage() ;
	}
	if(host == NULL) host = DEFHOST ;
	if(user == NULL)
	{
		printf("(%s) User: ",host) ;
		gets(buf) ;
		user = (char *) malloc(strlen(buf)+1) ;
		strcpy(user,buf) ;
	}
	if(passwd == NULL)
	{
		sprintf(buf,"(%s) Password: ",host) ;
		passwd = getpass(buf) ;
	}
	if((s = getservbyname("exec","tcp")) == NULL)
	{
		perror("exec/tcp") ;
		exit(1) ;
	}
	if((rfd = rexec(&host,s->s_port,user,passwd,RDATE,(int *)0)) < 0)
	{
		perror("rexec") ;
		exit(1) ;
	}
	if((i = read(rfd,buf,BUFSIZ)) <= 0)
	{
		fprintf(stderr,"protocol failure\n") ;
		exit(1) ;
	}
	buf[i] = '\0' ;
	/*
	 *	Should probably be some error checking
	 *	at the minimum, did we get a 'date' command
	 *	back?
	 */
	if(tflag)
	{
		i = 0 ;
		fputs(buf,stdout) ;
	}
	else i = system(buf) ;
	exit(i) ;
}
/*
 *	Rdate - just generate a UNIX date command for 'now'
 *	on the standard output
 */
rdate()
{
	long int d ;
	struct tm *t, *localtime() ;


	d = time(0) ;
	t = localtime(&d) ;
	printf("date %02d%02d%02d%02d%02d.%02d\n",
		t->tm_year,t->tm_mon+1,t->tm_mday,
		t->tm_hour,t->tm_min,t->tm_sec) ;
}



More information about the Comp.sources.unix mailing list