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