|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: char copyright[] = ! 9: "@(#) Copyright (c) 1985 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif not lint ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)date.c 4.19 (Berkeley) 5/18/86"; ! 15: #endif not lint ! 16: ! 17: /* ! 18: * Date - print and set date ! 19: */ ! 20: ! 21: #include <sys/param.h> ! 22: #include <stdio.h> ! 23: #include <sys/time.h> ! 24: #include <sys/file.h> ! 25: #include <errno.h> ! 26: #include <syslog.h> ! 27: #include <utmp.h> ! 28: ! 29: #define WTMP "/usr/adm/wtmp" ! 30: ! 31: struct timeval tv, now; ! 32: struct timezone tz; ! 33: char *ap, *ep, *sp; ! 34: int uflag, nflag; ! 35: int retval; ! 36: ! 37: char *timezone(); ! 38: static int dmsize[12] = ! 39: { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; ! 40: static char *usage = "usage: date [-n] [-u] [yymmddhhmm[.ss]]\n"; ! 41: ! 42: struct utmp wtmp[2] = { ! 43: { "|", "", "", 0 }, ! 44: { "{", "", "", 0 } ! 45: }; ! 46: ! 47: char *ctime(); ! 48: char *asctime(); ! 49: struct tm *localtime(); ! 50: struct tm *gmtime(); ! 51: char *strcpy(), *strncpy(); ! 52: char *username, *getlogin(); ! 53: long time(); ! 54: uid_t getuid(); ! 55: ! 56: main(argc, argv) ! 57: int argc; ! 58: char *argv[]; ! 59: { ! 60: register char *tzn; ! 61: ! 62: openlog("date", LOG_ODELAY, LOG_AUTH); ! 63: (void) gettimeofday(&tv, &tz); ! 64: now = tv; ! 65: ! 66: while (argc > 1 && argv[1][0] == '-') { ! 67: while (*++argv[1]) ! 68: switch ((int)argv[1][0]) { ! 69: ! 70: case 'n': ! 71: nflag++; ! 72: break; ! 73: ! 74: case 'u': ! 75: uflag++; ! 76: break; ! 77: ! 78: default: ! 79: fprintf(stderr, usage); ! 80: exit(1); ! 81: } ! 82: argc--; ! 83: argv++; ! 84: } ! 85: if (argc > 2) { ! 86: fprintf(stderr, usage); ! 87: exit(1); ! 88: } ! 89: if (argc == 1) ! 90: goto display; ! 91: ! 92: if (getuid() != 0) { ! 93: fprintf(stderr, "You are not superuser: date not set\n"); ! 94: retval = 1; ! 95: goto display; ! 96: } ! 97: username = getlogin(); ! 98: if (username == NULL || *username == '\0') /* single-user or no tty */ ! 99: username = "root"; ! 100: ! 101: ap = argv[1]; ! 102: wtmp[0].ut_time = tv.tv_sec; ! 103: if (gtime()) { ! 104: fprintf(stderr, usage); ! 105: retval = 1; ! 106: goto display; ! 107: } ! 108: /* convert to GMT assuming local time */ ! 109: if (uflag == 0) { ! 110: tv.tv_sec += (long)tz.tz_minuteswest*60; ! 111: /* now fix up local daylight time */ ! 112: if (localtime((time_t *)&tv.tv_sec)->tm_isdst) ! 113: tv.tv_sec -= 60*60; ! 114: } ! 115: if (nflag || !settime(tv)) { ! 116: int wf; ! 117: ! 118: if (settimeofday(&tv, (struct timezone *)0) < 0) { ! 119: perror("settimeofday"); ! 120: retval = 1; ! 121: goto display; ! 122: } ! 123: if ((wf = open(WTMP, O_WRONLY|O_APPEND)) >= 0) { ! 124: (void) time((time_t *)&wtmp[1].ut_time); ! 125: (void) write(wf, (char *)wtmp, sizeof(wtmp)); ! 126: (void) close(wf); ! 127: } ! 128: } ! 129: syslog(LOG_NOTICE, "set by %s", username); ! 130: ! 131: display: ! 132: (void) gettimeofday(&tv, (struct timezone *)0); ! 133: if (uflag) { ! 134: ap = asctime(gmtime((time_t *)&tv.tv_sec)); ! 135: tzn = "GMT"; ! 136: } else { ! 137: struct tm *tp; ! 138: tp = localtime((time_t *)&tv.tv_sec); ! 139: ap = asctime(tp); ! 140: tzn = timezone(tz.tz_minuteswest, tp->tm_isdst); ! 141: } ! 142: printf("%.20s", ap); ! 143: if (tzn) ! 144: printf("%s", tzn); ! 145: printf("%s", ap+19); ! 146: exit(retval); ! 147: } ! 148: ! 149: gtime() ! 150: { ! 151: register int i, year, month; ! 152: int day, hour, mins, secs; ! 153: struct tm *L; ! 154: char x; ! 155: ! 156: ep = ap; ! 157: while(*ep) ep++; ! 158: sp = ap; ! 159: while(sp < ep) { ! 160: x = *sp; ! 161: *sp++ = *--ep; ! 162: *ep = x; ! 163: } ! 164: sp = ap; ! 165: (void) gettimeofday(&tv, (struct timezone *)0); ! 166: L = localtime((time_t *)&tv.tv_sec); ! 167: secs = gp(-1); ! 168: if (*sp != '.') { ! 169: mins = secs; ! 170: secs = 0; ! 171: } else { ! 172: sp++; ! 173: mins = gp(-1); ! 174: } ! 175: hour = gp(-1); ! 176: day = gp(L->tm_mday); ! 177: month = gp(L->tm_mon+1); ! 178: year = gp(L->tm_year); ! 179: if (*sp) ! 180: return (1); ! 181: if (month < 1 || month > 12 || ! 182: day < 1 || day > 31 || ! 183: mins < 0 || mins > 59 || ! 184: secs < 0 || secs > 59) ! 185: return (1); ! 186: if (hour == 24) { ! 187: hour = 0; ! 188: day++; ! 189: } ! 190: if (hour < 0 || hour > 23) ! 191: return (1); ! 192: tv.tv_sec = 0; ! 193: year += 1900; ! 194: for (i = 1970; i < year; i++) ! 195: tv.tv_sec += dysize(i); ! 196: /* Leap year */ ! 197: if (dysize(year) == 366 && month >= 3) ! 198: tv.tv_sec++; ! 199: while (--month) ! 200: tv.tv_sec += dmsize[month-1]; ! 201: tv.tv_sec += day-1; ! 202: tv.tv_sec = 24*tv.tv_sec + hour; ! 203: tv.tv_sec = 60*tv.tv_sec + mins; ! 204: tv.tv_sec = 60*tv.tv_sec + secs; ! 205: return (0); ! 206: } ! 207: ! 208: gp(dfault) ! 209: { ! 210: register int c, d; ! 211: ! 212: if (*sp == 0) ! 213: return (dfault); ! 214: c = (*sp++) - '0'; ! 215: d = (*sp ? (*sp++) - '0' : 0); ! 216: if (c < 0 || c > 9 || d < 0 || d > 9) ! 217: return (-1); ! 218: return (c+10*d); ! 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: settime(tv) ! 240: struct timeval tv; ! 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: fprintf(stderr, "udp/timed: unknown service\n"); ! 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: fprintf(stderr, "date: All ports in use\n"); ! 280: goto bad; ! 281: } ! 282: msg.tsp_type = TSP_SETDATE; ! 283: msg.tsp_vers = TSPVERSION; ! 284: (void) gethostname(hostname, sizeof (hostname)); ! 285: (void) strncpy(msg.tsp_name, hostname, sizeof (hostname)); ! 286: msg.tsp_seq = htons((u_short)0); ! 287: msg.tsp_time.tv_sec = htonl((u_long)tv.tv_sec); ! 288: msg.tsp_time.tv_usec = htonl((u_long)tv.tv_usec); ! 289: length = sizeof (struct sockaddr_in); ! 290: if (connect(s, &dest, length) < 0) { ! 291: perror("date: connect"); ! 292: goto bad; ! 293: } ! 294: if (send(s, (char *)&msg, sizeof (struct tsp), 0) < 0) { ! 295: if (errno != ECONNREFUSED) ! 296: perror("date: send"); ! 297: goto bad; ! 298: } ! 299: timed_ack = -1; ! 300: waittime = WAITACK; ! 301: loop: ! 302: tout.tv_sec = waittime; ! 303: tout.tv_usec = 0; ! 304: FD_ZERO(&ready); ! 305: FD_SET(s, &ready); ! 306: found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout); ! 307: length = sizeof(err); ! 308: if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&err, &length) == 0 ! 309: && err) { ! 310: errno = err; ! 311: if (errno != ECONNREFUSED) ! 312: perror("date: send (delayed error)"); ! 313: goto bad; ! 314: } ! 315: if (found > 0 && FD_ISSET(s, &ready)) { ! 316: length = sizeof (struct sockaddr_in); ! 317: if (recvfrom(s, (char *)&msg, sizeof (struct tsp), 0, &from, ! 318: &length) < 0) { ! 319: if (errno != ECONNREFUSED) ! 320: perror("date: recvfrom"); ! 321: goto bad; ! 322: } ! 323: msg.tsp_seq = ntohs(msg.tsp_seq); ! 324: msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec); ! 325: msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec); ! 326: switch (msg.tsp_type) { ! 327: ! 328: case TSP_ACK: ! 329: timed_ack = TSP_ACK; ! 330: waittime = WAITDATEACK; ! 331: goto loop; ! 332: ! 333: case TSP_DATEACK: ! 334: (void)close(s); ! 335: return (1); ! 336: ! 337: default: ! 338: fprintf(stderr, ! 339: "date: Wrong ack received from timed: %s\n", ! 340: tsptype[msg.tsp_type]); ! 341: timed_ack = -1; ! 342: break; ! 343: } ! 344: } ! 345: if (timed_ack == -1) ! 346: fprintf(stderr, ! 347: "date: Can't reach time daemon, time set locally.\n"); ! 348: bad: ! 349: (void)close(s); ! 350: retval = 2; ! 351: return (0); ! 352: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.