fnf@unisoft.UUCP (Fred Fish) (02/28/85)
Here is a new distribution of setdate (many people on BSD systems complained about a missing liby.a). It turns out the only thing needed was yyerror(). Don't forget to define OLDFORMAT when appropriate (you get a "bad conversion" message from "date" otherwise). -Fred #--------CUT---------CUT---------CUT---------CUT--------# ######################################################### # # # This is a shell archive file. To extract files: # # # # 1) Make a directory for the files. # # 2) Write a file, such as "file.shar", containing # # this archive file into the directory. # # 3) Type "sh file.shar". Do not use csh. # # # ######################################################### # # echo Extracting Makefile: sed 's/^Z//' >Makefile <<\STUNKYFLUFF Z# Z# FILE Z# Z# Makefile Z# Z# SCCS Z# Z# @(#)Makefile 1.3 2/27/85 Z# Z# DESCRIPTION Z# Z# Makefile for the system boot utility "setdate" which Z# sets the current date and time. Accepts a wide variety Z# of date formats. Z# Z# AUTHOR Z# Z# Fred Fish Z# (Currently at UniSoft Systems Inc.) Z# Z Z.l~.c: Z $(GET) $(GFLAGS) -p $< >$*.l Z $(LEX) $(LFLAGS) $*.l Z mv lex.yy.c $*.c Z rm -f $*.l Z Z.y~.y: Z $(GET) $(GFLAGS) -p $< >$*.y Z Zsetdate : setdate.o Z $(CC) -o $@ $? Z Zsetdate.o : setdate.c lex.c Z Zsetdate.c : setdate.y Z Z# Z# Clean up the directory. Z# Z Zclean : Z rm -f *.BAK *.o Z Zclobber : Z rm -f setdate.c lex.c setdate Z Z STUNKYFLUFF set `sum Makefile` if test 40062 != $1 then echo Makefile: Checksum error. Is: $1, should be: 40062. fi # # echo Extracting lex.l: sed 's/^Z//' >lex.l <<\STUNKYFLUFF Z%{ Z/************************************************************************ Z * * Z * Copyright (c) 1985, Fred Fish * Z * All Rights Reserved * Z * * Z * This software and/or documentation is released into the * Z * public domain for personal, non-commercial use only. * Z * Limited rights to use, modify, and redistribute are hereby * Z * granted for non-commercial purposes, provided that all * Z * copyright notices remain intact and all changes are clearly * Z * documented. The author makes no warranty of any kind with * Z * respect to this product and explicitly disclaims any implied * Z * warranties of merchantability or fitness for any particular * Z * purpose. * Z * * Z ************************************************************************ Z */ Z Z Z/* Z * FILE Z * Z * lex.l Z * Z * SCCS Z * Z * @(#)lex.l 1.2 2/10/85 Z * Z * DESCRIPTION Z * Z * Lex code for setdate utility. This must be processed by the Z * UNIX "lex" utility to produce a lexical analyzer. Z * Z * Note that month names and other such strings are recognized Z * case independently. Z * Z * The values returned for month names are in the range [1-12] Z * for the months [Jan-Dec] respectively. Z * Z * AUTHOR Z * Z * Fred Fish Z * (Currently at UniSoft Systems Inc.) Z * Z */ Z%} Z Z%% Z Z(P|p)(M|m) { Z return (PM); Z } Z Z(A|a)(M|m) { Z return (AM); Z } Z Z[0-9]+ { Z yylval = atoi(yytext); Z return(DIGITS); Z } Z Z((J|j)(A|a)(N|n))((U|u)(A|a)(R|r)(Y|y))? { Z yylval = 1; Z return (MONTH); Z } Z Z((F|f)(E|e)(B|b))((R|r)(U|u)(A|a)(R|r)(Y|y))? { Z yylval = 2; Z return (MONTH); Z } Z Z((M|m)(A|a)(R|r))((C|c)(H|h))? { Z yylval = 3; Z return (MONTH); Z } Z Z((A|a)(P|p)(R|r))((I|i)(L|l))? { Z yylval = 4; Z return (MONTH); Z } Z Z(M|m)(A|a)(Y|y) { Z yylval = 5; Z return(MONTH); Z } Z Z((J|j)(U|u)(N|n))((E|e))? { Z yylval = 6; Z return(MONTH); Z } Z Z((J|j)(U|u)(L|l))((Y|y))? { Z yylval = 7; Z return(MONTH); Z } Z Z((A|a)(U|u)(G|g))((U|u)(S|s)(T|t))? { Z yylval = 8; Z return(MONTH); Z } Z Z((S|s)(E|e)(P|p))((T|t)(E|e)(M|m)(B|b)(E|e)(R|r))? { Z yylval = 9; Z return(MONTH); Z } Z Z((O|o)(C|c)(T|t))((O|o)(B|b)(E|e)(R|r))? { Z yylval = 10; Z return(MONTH); Z } Z Z((N|n)(O|o)(V|v))((E|e)(M|m)(B|b)(E|e)(R|r))? { Z yylval = 11; Z return(MONTH); Z } Z Z((D|d)(E|e)(C|c))((E|e)(M|m)(B|b)(E|e)(R|r))? { Z yylval = 12; Z return(MONTH); Z } Z Z"," { Z return(COMMA); Z } Z Z"/" { Z return(SLASH); Z } Z Z"-" { Z return(DASH); Z } Z Z":" { Z return(COLON); Z } Z Z[ \t] {;} Z Z[\n] { Z return(-1); Z } Z%% Z STUNKYFLUFF set `sum lex.l` if test 41284 != $1 then echo lex.l: Checksum error. Is: $1, should be: 41284. fi # # echo Extracting setdate.y: sed 's/^Z//' >setdate.y <<\STUNKYFLUFF Z/************************************************************************ Z * * Z * Copyright (c) 1985, Fred Fish * Z * All Rights Reserved * Z * * Z * This software and/or documentation is released into the * Z * public domain for personal, non-commercial use only. * Z * Limited rights to use, modify, and redistribute are hereby * Z * granted for non-commercial purposes, provided that all * Z * copyright notices remain intact and all changes are clearly * Z * documented. The author makes no warranty of any kind with * Z * respect to this product and explicitly disclaims any implied * Z * warranties of merchantability or fitness for any particular * Z * purpose. * Z * * Z ************************************************************************ Z */ Z Z Z/* Z * FILE Z * Z * setdate.y Z * Z * SCCS Z * Z * @(#)setdate.y 1.2 2/27/85 Z * Z * DESCRIPTION Z * Z * YACC grammar for a system bootup time/date set utility. Z * Z * Accepts date and time in several common formats, for Z * example: Z * Z * January 18,1983 18:45 Z * Jan 18, 1983 18:45:00 Z * Jan 18, 1983 6:45 PM Z * 18:43 18-Jan-83 Z * 01/18/83 Z * 18:43 Z * 8 AM Z * Z * AUTHOR Z * Z * Fred Fish Z * (Currently at UniSoft Systems Inc.) Z * Z */ Z Z%{ Z#include <stdio.h> Z#include <time.h> Z Z#define SYS_ERROR (-1) /* Returned by system calls on error */ Z#define FALSE (0) /* Boolean false */ Z#define TRUE (1) /* Boolean true */ Z Zstatic struct tm *newtime; /* Time to set current time to */ Zstatic int morning = FALSE; /* Explicit morning specified */ Zstatic int evening = FALSE; /* Explicit evening specified */ Z Zextern long time (); /* Get current clock value */ Zextern struct tm *localtime (); /* Get local time from clock value */ Zextern char *asctime (); /* Convert local time to string form */ Z Z%} Z Z%token DIGITS MONTH SLASH DASH COMMA COLON AM PM Z Z%% Z Zwhen : date Z | time Z | date time Z | time date Z | /* empty */ Z ; Z Zdate : DIGITS SLASH DIGITS SLASH DIGITS Z { Z newtime -> tm_mon = $1 - 1; Z newtime -> tm_mday = $3; Z newtime -> tm_year = $5 % 100; Z } Z | DIGITS DASH MONTH DASH DIGITS Z { Z newtime -> tm_mday = $1; Z newtime -> tm_mon = $3 - 1; Z newtime -> tm_year = $5 % 100; Z } Z | MONTH DIGITS COMMA DIGITS Z { Z newtime -> tm_mon = $1 - 1; Z newtime -> tm_mday = $2; Z newtime -> tm_year = $4 % 100; Z } Z | MONTH DIGITS Z { Z newtime -> tm_mon = $1 - 1; Z newtime -> tm_mday = $2; Z } Z ; Z Ztime : clock Z | clock period Z ; Z Zclock : DIGITS COLON DIGITS COLON DIGITS Z { Z newtime -> tm_hour = $1; Z newtime -> tm_min = $3; Z newtime -> tm_sec = $5; Z } Z | DIGITS COLON DIGITS Z { Z newtime -> tm_hour = $1; Z newtime -> tm_min = $3; Z newtime -> tm_sec = 0; Z } Z | DIGITS Z { Z newtime -> tm_hour = $1; Z newtime -> tm_min = 0; Z newtime -> tm_sec = 0; Z } Z ; Z Zperiod : AM Z { Z morning = TRUE; Z } Z | PM Z { Z evening = TRUE; Z } Z ; Z Z%% Z Zint main (argc, argv) Zint argc; Zchar *argv[]; Z{ Z char buffer[64]; /* buffer to hold arg for date util */ Z register char ch; /* peek at first character of input */ Z register int status; /* system call result code */ Z auto long systime; /* Current system time */ Z Z if (time (&systime) == SYS_ERROR) { Z fprintf (stderr, "%s: can't get current time: ", argv[0]); Z perror (""); Z } Z newtime = localtime (&systime); Z do { Z printf ("Enter current date & time (? for help) >> "); Z fflush (stdout); Z ch = getchar (); /* Peek at first */ Z if (ch == '?') { /* Wants help? */ Z usage (); /* Give good help */ Z while (getchar () != '\n') {;} /* Flush line */ Z } else { Z ungetc (ch, stdin); /* Put back peek */ Z } Z } while (ch == '?'); /* Until no ? */ Z yyparse (); Z if (morning) { Z newtime -> tm_hour %= 12; Z } else if (evening) { Z newtime -> tm_hour %= 12; Z newtime -> tm_hour += 12; Z } Z#ifdef OLDFORMAT Z sprintf (buffer,"date %02.2d%02.2d%02.2d%02.2d%02.2d.%02.2d", Z newtime -> tm_year, Z newtime -> tm_mon + 1, Z newtime -> tm_mday, Z newtime -> tm_hour, Z newtime -> tm_min, Z newtime -> tm_sec); Z#else Z sprintf (buffer,"date %02.2d%02.2d%02.2d%02.2d%02.2d", Z newtime -> tm_mon + 1, Z newtime -> tm_mday, Z newtime -> tm_hour, Z newtime -> tm_min, Z newtime -> tm_year); Z#endif Z status = system (buffer); Z if (status == SYS_ERROR) { Z fprintf (stderr, "%s: can't set time: ", argv[0]); Z perror (""); Z } Z return (status); Z} Z Zstatic char *documentation[] = { Z "", Z "Date and time may be entered in any of several common formats.", Z "Default is current date and time. Examples are:", Z "", Z "\tApril 14, 1983 13:41", Z "\t14-Apr-83 13:41:00", Z "\t4/14/83 13:41", Z "\t1:41 PM", Z "\tApr 14", Z "", Z "Acceptable but not recommended are:", Z "", Z "\tApr 14, 83", Z "\t14-April-1983", Z "\t4/14/1983", Z "", Z 0, /* MARKS END OF STRING LIST */ Z}; Z Zstatic usage() Z{ Z register char **dp; Z Z dp = documentation; /* Init string pointer pointer */ Z while (*dp) { /* While another good pointer */ Z printf ("%s\n", *dp++); /* Print what it points to */ Z } Z} Z Zyywrap () /* Thought this was in library */ Z{ Z return (1); Z} Z Zyyerror (s) /* Provide default error handling */ Zchar *s; Z{ Z fprintf (stderr, "%s\n", s); Z} Z Z#include "lex.c" /* Output of "lex" from lex.l */ Z STUNKYFLUFF set `sum setdate.y` if test 42629 != $1 then echo setdate.y: Checksum error. Is: $1, should be: 42629. fi echo ALL DONE BUNKY! exit 0
root@bu-cs.UUCP (Barry Shein) (03/04/85)
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) ; }