|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985, 1987, 1988 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that: (1) source distributions retain this entire copyright ! 7: * notice and comment, and (2) distributions including binaries display ! 8: * the following acknowledgement: ``This product includes software ! 9: * developed by the University of California, Berkeley and its contributors'' ! 10: * in the documentation or other materials provided with the distribution ! 11: * and in all advertising materials mentioning features or use of this ! 12: * software. Neither the name of the University nor the names of its ! 13: * contributors may be used to endorse or promote products derived ! 14: * from this software without specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #ifndef lint ! 21: char copyright[] = ! 22: "@(#) Copyright (c) 1985, 1987, 1988 The Regents of the University of California.\n\ ! 23: All rights reserved.\n"; ! 24: #endif /* not lint */ ! 25: ! 26: #ifndef lint ! 27: static char sccsid[] = "@(#)date.c 4.27 (Berkeley) 5/31/90"; ! 28: #endif /* not lint */ ! 29: ! 30: /* ! 31: * Date - print and set date ! 32: */ ! 33: ! 34: #include <sys/param.h> ! 35: #include <sys/time.h> ! 36: #include <sys/file.h> ! 37: #include <errno.h> ! 38: #include <syslog.h> ! 39: #include <utmp.h> ! 40: #include <tzfile.h> ! 41: #include <stdio.h> ! 42: #include <ctype.h> ! 43: #include <string.h> ! 44: ! 45: #define ATOI2(ar) (ar[0] - '0') * 10 + (ar[1] - '0'); ar += 2; ! 46: ! 47: static struct timeval tv; ! 48: static int retval; ! 49: ! 50: static int dmsize[] = ! 51: { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; ! 52: ! 53: main(argc, argv) ! 54: int argc; ! 55: char **argv; ! 56: { ! 57: extern int optind; ! 58: extern char *optarg; ! 59: struct timezone tz; ! 60: char *ap, *tzn; ! 61: int ch, uflag, nflag; ! 62: char *username, *getlogin(); ! 63: time_t time(); ! 64: ! 65: nflag = uflag = 0; ! 66: tz.tz_dsttime = tz.tz_minuteswest = 0; ! 67: while ((ch = getopt(argc, argv, "d:nut:")) != EOF) ! 68: switch((char)ch) { ! 69: case 'd': /* daylight savings time */ ! 70: tz.tz_dsttime = atoi(optarg) ? 1 : 0; ! 71: break; ! 72: case 'n': /* don't set network */ ! 73: nflag = 1; ! 74: break; ! 75: case 'u': /* do it in GMT */ ! 76: uflag = 1; ! 77: break; ! 78: case 't': /* minutes west of GMT */ ! 79: /* error check; we can't allow "PST" */ ! 80: if (isdigit(*optarg)) { ! 81: tz.tz_minuteswest = atoi(optarg); ! 82: break; ! 83: } ! 84: /*FALLTHROUGH*/ ! 85: default: ! 86: usage(); ! 87: exit(1); ! 88: } ! 89: argc -= optind; ! 90: argv += optind; ! 91: ! 92: if (argc > 1) { ! 93: usage(); ! 94: exit(1); ! 95: } ! 96: ! 97: if ((tz.tz_minuteswest || tz.tz_dsttime) && ! 98: settimeofday((struct timeval *)NULL, &tz)) { ! 99: perror("date: settimeofday"); ! 100: exit(1); ! 101: } ! 102: ! 103: if (gettimeofday(&tv, &tz)) { ! 104: perror("date: gettimeofday"); ! 105: exit(1); ! 106: } ! 107: ! 108: if (!argc) ! 109: goto display; ! 110: ! 111: if (gtime(*argv)) { ! 112: usage(); ! 113: exit(1); ! 114: } ! 115: ! 116: if (!uflag) { /* convert to GMT assuming local time */ ! 117: tv.tv_sec += (long)tz.tz_minuteswest * SECSPERMIN; ! 118: /* now fix up local daylight time */ ! 119: if (localtime((time_t *)&tv.tv_sec)->tm_isdst) ! 120: tv.tv_sec -= SECSPERHOUR; ! 121: } ! 122: if (nflag || !netsettime(tv)) { ! 123: logwtmp("|", "date", ""); ! 124: if (settimeofday(&tv, (struct timezone *)NULL)) { ! 125: perror("date: settimeofday"); ! 126: exit(1); ! 127: } ! 128: logwtmp("{", "date", ""); ! 129: } ! 130: ! 131: username = getlogin(); ! 132: if (!username || *username == '\0') /* single-user or no tty */ ! 133: username = "root"; ! 134: syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", username); ! 135: ! 136: display: ! 137: if (gettimeofday(&tv, (struct timezone *)NULL)) { ! 138: perror("date: gettimeofday"); ! 139: exit(1); ! 140: } ! 141: if (uflag) { ! 142: ap = asctime(gmtime((time_t *)&tv.tv_sec)); ! 143: tzn = "GMT"; ! 144: } ! 145: else { ! 146: struct tm *tp; ! 147: ! 148: tp = localtime((time_t *)&tv.tv_sec); ! 149: ap = asctime(tp); ! 150: tzn = tp->tm_zone; ! 151: } ! 152: printf("%.20s%s%s", ap, tzn, ap + 19); ! 153: exit(retval); ! 154: } ! 155: ! 156: /* ! 157: * gtime -- ! 158: * convert user's time into number of seconds ! 159: */ ! 160: static ! 161: gtime(ap) ! 162: register char *ap; ! 163: { ! 164: register int year, month; ! 165: register char *C; ! 166: struct tm *L; ! 167: int day, hour, mins, secs; ! 168: ! 169: for (secs = 0, C = ap; *C; ++C) { ! 170: if (*C == '.') { /* seconds provided */ ! 171: if (strlen(C) != 3) ! 172: return(1); ! 173: *C = NULL; ! 174: secs = (C[1] - '0') * 10 + (C[2] - '0'); ! 175: break; ! 176: } ! 177: if (!isdigit(*C)) ! 178: return(-1); ! 179: } ! 180: ! 181: L = localtime((time_t *)&tv.tv_sec); ! 182: year = L->tm_year; /* defaults */ ! 183: month = L->tm_mon + 1; ! 184: day = L->tm_mday; ! 185: ! 186: switch ((int)(C - ap)) { /* length */ ! 187: case 10: /* yymmddhhmm */ ! 188: year = ATOI2(ap); ! 189: case 8: /* mmddhhmm */ ! 190: month = ATOI2(ap); ! 191: case 6: /* ddhhmm */ ! 192: day = ATOI2(ap); ! 193: case 4: /* hhmm */ ! 194: hour = ATOI2(ap); ! 195: mins = ATOI2(ap); ! 196: break; ! 197: default: ! 198: return(1); ! 199: } ! 200: ! 201: if (*ap || month < 1 || month > 12 || day < 1 || day > 31 || ! 202: hour < 0 || hour > 23 || mins < 0 || mins > 59 || ! 203: secs < 0 || secs > 59) ! 204: return(1); ! 205: ! 206: tv.tv_sec = 0; ! 207: year += TM_YEAR_BASE; ! 208: if (isleap(year) && month > 2) ! 209: ++tv.tv_sec; ! 210: for (--year;year >= EPOCH_YEAR;--year) ! 211: tv.tv_sec += isleap(year) ? DAYSPERLYEAR : DAYSPERNYEAR; ! 212: while (--month) ! 213: tv.tv_sec += dmsize[month]; ! 214: tv.tv_sec += day - 1; ! 215: tv.tv_sec = HOURSPERDAY * tv.tv_sec + hour; ! 216: tv.tv_sec = MINSPERHOUR * tv.tv_sec + mins; ! 217: tv.tv_sec = SECSPERMIN * tv.tv_sec + secs; ! 218: return(0); ! 219: } ! 220: ! 221: #include <sys/socket.h> ! 222: #include <netinet/in.h> ! 223: #include <netdb.h> ! 224: #define TSPTYPES ! 225: #include <protocols/timed.h> ! 226: ! 227: #define WAITACK 2 /* seconds */ ! 228: #define WAITDATEACK 5 /* seconds */ ! 229: ! 230: extern int errno; ! 231: /* ! 232: * Set the date in the machines controlled by timedaemons ! 233: * by communicating the new date to the local timedaemon. ! 234: * If the timedaemon is in the master state, it performs the ! 235: * correction on all slaves. If it is in the slave state, it ! 236: * notifies the master that a correction is needed. ! 237: * Returns 1 on success, 0 on failure. ! 238: */ ! 239: netsettime(ntv) ! 240: struct timeval ntv; ! 241: { ! 242: int s, length, port, timed_ack, found, err; ! 243: long waittime; ! 244: fd_set ready; ! 245: char hostname[MAXHOSTNAMELEN]; ! 246: struct timeval tout; ! 247: struct servent *sp; ! 248: struct tsp msg; ! 249: struct sockaddr_in sin, dest, from; ! 250: ! 251: sp = getservbyname("timed", "udp"); ! 252: if (sp == 0) { ! 253: fputs("udp/timed: unknown service\n", stderr); ! 254: retval = 2; ! 255: return (0); ! 256: } ! 257: dest.sin_port = sp->s_port; ! 258: dest.sin_family = AF_INET; ! 259: dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY); ! 260: s = socket(AF_INET, SOCK_DGRAM, 0); ! 261: if (s < 0) { ! 262: if (errno != EPROTONOSUPPORT) ! 263: perror("date: socket"); ! 264: goto bad; ! 265: } ! 266: bzero((char *)&sin, sizeof (sin)); ! 267: sin.sin_family = AF_INET; ! 268: for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) { ! 269: sin.sin_port = htons((u_short)port); ! 270: if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0) ! 271: break; ! 272: if (errno != EADDRINUSE) { ! 273: if (errno != EADDRNOTAVAIL) ! 274: perror("date: bind"); ! 275: goto bad; ! 276: } ! 277: } ! 278: if (port == IPPORT_RESERVED / 2) { ! 279: fputs("date: All ports in use\n", stderr); ! 280: goto bad; ! 281: } ! 282: msg.tsp_type = TSP_SETDATE; ! 283: msg.tsp_vers = TSPVERSION; ! 284: if (gethostname(hostname, sizeof (hostname))) { ! 285: perror("date: gethostname"); ! 286: goto bad; ! 287: } ! 288: (void) strncpy(msg.tsp_name, hostname, sizeof (hostname)); ! 289: msg.tsp_seq = htons((u_short)0); ! 290: msg.tsp_time.tv_sec = htonl((u_long)ntv.tv_sec); ! 291: msg.tsp_time.tv_usec = htonl((u_long)ntv.tv_usec); ! 292: length = sizeof (struct sockaddr_in); ! 293: if (connect(s, &dest, length) < 0) { ! 294: perror("date: connect"); ! 295: goto bad; ! 296: } ! 297: if (send(s, (char *)&msg, sizeof (struct tsp), 0) < 0) { ! 298: if (errno != ECONNREFUSED) ! 299: perror("date: send"); ! 300: goto bad; ! 301: } ! 302: timed_ack = -1; ! 303: waittime = WAITACK; ! 304: loop: ! 305: tout.tv_sec = waittime; ! 306: tout.tv_usec = 0; ! 307: FD_ZERO(&ready); ! 308: FD_SET(s, &ready); ! 309: found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout); ! 310: length = sizeof(err); ! 311: if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&err, &length) == 0 ! 312: && err) { ! 313: errno = err; ! 314: if (errno != ECONNREFUSED) ! 315: perror("date: send (delayed error)"); ! 316: goto bad; ! 317: } ! 318: if (found > 0 && FD_ISSET(s, &ready)) { ! 319: length = sizeof (struct sockaddr_in); ! 320: if (recvfrom(s, (char *)&msg, sizeof (struct tsp), 0, &from, ! 321: &length) < 0) { ! 322: if (errno != ECONNREFUSED) ! 323: perror("date: recvfrom"); ! 324: goto bad; ! 325: } ! 326: msg.tsp_seq = ntohs(msg.tsp_seq); ! 327: msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec); ! 328: msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec); ! 329: switch (msg.tsp_type) { ! 330: ! 331: case TSP_ACK: ! 332: timed_ack = TSP_ACK; ! 333: waittime = WAITDATEACK; ! 334: goto loop; ! 335: ! 336: case TSP_DATEACK: ! 337: (void)close(s); ! 338: return (1); ! 339: ! 340: default: ! 341: fprintf(stderr, ! 342: "date: Wrong ack received from timed: %s\n", ! 343: tsptype[msg.tsp_type]); ! 344: timed_ack = -1; ! 345: break; ! 346: } ! 347: } ! 348: if (timed_ack == -1) ! 349: fputs("date: Can't reach time daemon, time set locally.\n", ! 350: stderr); ! 351: bad: ! 352: (void)close(s); ! 353: retval = 2; ! 354: return (0); ! 355: } ! 356: ! 357: usage() ! 358: { ! 359: fputs("usage: date [-nu] [-d dst] [-t minutes_west] [yymmddhhmm[.ss]]\n", stderr); ! 360: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.