386BSD 0.1 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Fri, 5 Apr 1991 02:19:45 +0000 (18:19 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Fri, 5 Apr 1991 02:19:45 +0000 (18:19 -0800)
Work on file usr/src/bin/date/date.c
Work on file usr/src/bin/date/netdate.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.1

usr/src/bin/date/date.c [new file with mode: 0644]
usr/src/bin/date/netdate.c [new file with mode: 0644]

diff --git a/usr/src/bin/date/date.c b/usr/src/bin/date/date.c
new file mode 100644 (file)
index 0000000..0c57318
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 1985, 1987, 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1985, 1987, 1988 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)date.c     5.5 (Berkeley) 3/18/91";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+time_t tval;
+int retval, nflag;
+
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       extern int optind;
+       extern char *optarg;
+       struct timezone tz;
+       int ch, rflag;
+       char *format, buf[1024];
+
+       tz.tz_dsttime = tz.tz_minuteswest = 0;
+       rflag = 0;
+       while ((ch = getopt(argc, argv, "d:nr:ut:")) != EOF)
+               switch((char)ch) {
+               case 'd':               /* daylight savings time */
+                       tz.tz_dsttime = atoi(optarg) ? 1 : 0;
+                       break;
+               case 'n':               /* don't set network */
+                       nflag = 1;
+                       break;
+               case 'r':               /* user specified seconds */
+                       rflag = 1;
+                       tval = atol(optarg);
+                       break;
+               case 'u':               /* do everything in GMT */
+                       (void)setenv("TZ", "GMT0", 1);
+                       break;
+               case 't':               /* minutes west of GMT */
+                                       /* error check; don't allow "PST" */
+                       if (isdigit(*optarg)) {
+                               tz.tz_minuteswest = atoi(optarg);
+                               break;
+                       }
+                       /* FALLTHROUGH */
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       /*
+        * If -d or -t, set the timezone or daylight savings time; this
+        * doesn't belong here, there kernel should not know about either.
+        */
+       if ((tz.tz_minuteswest || tz.tz_dsttime) &&
+           settimeofday((struct timeval *)NULL, &tz)) {
+               perror("date: settimeofday");
+               exit(1);
+       }
+
+       if (!rflag && time(&tval) == -1) {
+               perror("date: time");
+               exit(1);
+       }
+
+       format = "%a %b %e %H:%M:%S %Z %Y\n";
+
+       /* allow the operands in any order */
+       if (*argv && **argv == '+') {
+               format = *argv + 1;
+               ++argv;
+       }
+
+       if (*argv) {
+               setthetime(*argv);
+               ++argv;
+       }
+
+       if (*argv && **argv == '+')
+               format = *argv + 1;
+
+       (void)strftime(buf, sizeof(buf), format, localtime(&tval));
+       (void)printf("%s", buf);
+       exit(retval);
+}
+
+#define        ATOI2(ar)       ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
+setthetime(p)
+       register char *p;
+{
+       register struct tm *lt;
+       struct timeval tv;
+       int dot;
+       char *t;
+
+       for (t = p, dot = 0; *t; ++t)
+               if (!isdigit(*t) && (*t != '.' || dot++))
+                       badformat();
+
+       lt = localtime(&tval);
+
+       if (t = index(p, '.')) {                /* .ss */
+               *t++ = '\0';
+               if (lt->tm_sec > 61)
+                       badformat();
+       } else
+               lt->tm_sec = 0;
+
+       for (t = p; *t; ++t)
+               if (!isdigit(*t))
+                       badformat();
+
+       switch (strlen(p)) {
+       case 10:                                /* yy */
+               lt->tm_year = ATOI2(p);
+               if (lt->tm_year < 69)           /* hack for 2000 ;-} */
+                       lt->tm_year += 100;
+               /* FALLTHROUGH */
+       case 8:                                 /* mm */
+               lt->tm_mon = ATOI2(p);
+               if (lt->tm_mon > 12)
+                       badformat();
+               --lt->tm_mon;                   /* time struct is 0 - 11 */
+               /* FALLTHROUGH */
+       case 6:                                 /* dd */
+               lt->tm_mday = ATOI2(p);
+               if (lt->tm_mday > 31)
+                       badformat();
+               /* FALLTHROUGH */
+       case 4:                                 /* hh */
+               lt->tm_hour = ATOI2(p);
+               if (lt->tm_hour > 23)
+                       badformat();
+               /* FALLTHROUGH */
+       case 2:                                 /* mm */
+               lt->tm_min = ATOI2(p);
+               if (lt->tm_min > 59)
+                       badformat();
+               break;
+       default:
+               badformat();
+       }
+
+       /* convert broken-down time to GMT clock time */
+       if ((tval = mktime(lt)) == -1)
+               badformat();
+
+       if (!(p = getlogin()))                  /* single-user or no tty */
+               p = "root";
+       syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
+
+       /* set the time */
+       if (nflag || netsettime(tval)) {
+               logwtmp("|", "date", "");
+               tv.tv_sec = tval;
+               tv.tv_usec = 0;
+               if (settimeofday(&tv, (struct timezone *)NULL)) {
+                       perror("date: settimeofday");
+                       exit(1);
+               }
+               logwtmp("{", "date", "");
+       }
+}
+
+badformat()
+{
+       (void)fprintf(stderr, "date: illegal time format.\n");
+       usage();
+}
+
+usage()
+{
+       (void)fprintf(stderr,
+           "usage: date [-nu] [-d dst] [-r seconds] [-t west] [+format]\n");
+       (void)fprintf(stderr, "            [yy[mm[dd[hh]]]]mm[.ss]]\n");
+       exit(1);
+}
diff --git a/usr/src/bin/date/netdate.c b/usr/src/bin/date/netdate.c
new file mode 100644 (file)
index 0000000..6ecfae1
--- /dev/null
@@ -0,0 +1,178 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)netdate.c  5.2 (Berkeley) 2/25/91";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#define TSPTYPES
+#include <protocols/timed.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+#define        WAITACK         2       /* seconds */
+#define        WAITDATEACK     5       /* seconds */
+
+extern int retval;
+
+/*
+ * Set the date in the machines controlled by timedaemons by communicating the
+ * new date to the local timedaemon.  If the timedaemon is in the master state,
+ * it performs the correction on all slaves.  If it is in the slave state, it
+ * notifies the master that a correction is needed.
+ * Returns 0 on success.  Returns > 0 on failure, setting retval to 2;
+ */
+netsettime(tval)
+       time_t tval;
+{
+       struct timeval tout;
+       struct servent *sp;
+       struct tsp msg;
+       struct sockaddr_in sin, dest, from;
+       fd_set ready;
+       long waittime;
+       int s, length, port, timed_ack, found, err;
+       char hostname[MAXHOSTNAMELEN];
+
+       if ((sp = getservbyname("timed", "udp")) == NULL) {
+               (void)fprintf(stderr, "date: udp/timed: unknown service.n");
+               return (retval = 2);
+       }
+
+       dest.sin_port = sp->s_port;
+       dest.sin_family = AF_INET;
+       dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY);
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s < 0) {
+               if (errno != EPROTONOSUPPORT)
+                       perror("date: timed");
+               return(retval = 2);
+       }
+
+       bzero((char *)&sin, sizeof(sin));
+       sin.sin_family = AF_INET;
+       for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
+               sin.sin_port = htons((u_short)port);
+               if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+                       break;
+               if (errno == EADDRINUSE)
+                       continue;
+               if (errno != EADDRNOTAVAIL)
+                       perror("date: bind");
+               goto bad;
+       }
+       if (port == IPPORT_RESERVED / 2) {
+               (void)fprintf(stderr, "date: all ports in use.\n");
+               goto bad;
+       }
+       msg.tsp_type = TSP_SETDATE;
+       msg.tsp_vers = TSPVERSION;
+       if (gethostname(hostname, sizeof(hostname))) {
+               perror("date: gethostname");
+               goto bad;
+       }
+       (void)strncpy(msg.tsp_name, hostname, sizeof(hostname));
+       msg.tsp_seq = htons((u_short)0);
+       msg.tsp_time.tv_sec = htonl((u_long)tval);
+       msg.tsp_time.tv_usec = htonl((u_long)0);
+       length = sizeof(struct sockaddr_in);
+       if (connect(s, (struct sockaddr *)&dest, length) < 0) {
+               perror("date: connect");
+               goto bad;
+       }
+       if (send(s, (char *)&msg, sizeof(struct tsp), 0) < 0) {
+               if (errno != ECONNREFUSED)
+                       perror("date: send");
+               goto bad;
+       }
+
+       timed_ack = -1;
+       waittime = WAITACK;
+loop:
+       tout.tv_sec = waittime;
+       tout.tv_usec = 0;
+
+       FD_ZERO(&ready);
+       FD_SET(s, &ready);
+       found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout);
+
+       length = sizeof(err);
+       if (!getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&err, &length)
+           && err) {
+               if (err != ECONNREFUSED)
+                       perror("date: send (delayed error)");
+               goto bad;
+       }
+
+       if (found > 0 && FD_ISSET(s, &ready)) {
+               length = sizeof(struct sockaddr_in);
+               if (recvfrom(s, &msg, sizeof(struct tsp), 0,
+                   (struct sockaddr *)&from, &length) < 0) {
+                       if (errno != ECONNREFUSED)
+                               perror("date: recvfrom");
+                       goto bad;
+               }
+               msg.tsp_seq = ntohs(msg.tsp_seq);
+               msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec);
+               msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec);
+               switch (msg.tsp_type) {
+               case TSP_ACK:
+                       timed_ack = TSP_ACK;
+                       waittime = WAITDATEACK;
+                       goto loop;
+               case TSP_DATEACK:
+                       (void)close(s);
+                       return (0);
+               default:
+                       (void)fprintf(stderr,
+                           "date: wrong ack received from timed: %s.\n", 
+                           tsptype[msg.tsp_type]);
+                       timed_ack = -1;
+                       break;
+               }
+       }
+       if (timed_ack == -1)
+               (void)fprintf(stderr,
+                   "date: can't reach time daemon, time set locally.\n");
+
+bad:
+       (void)close(s);
+       return(retval = 2);
+}