#ifndef lint #ifndef NOID static char elsieid[] = "@(#)date.c 7.45"; /* ** Modified from the UCB version with the SCCS ID appearing below. */ #endif /* !defined NOID */ #endif /* !defined lint */ /* * Copyright (c) 1985, 1987, 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANT[A]BILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include /* for O_WRONLY, O_APPEND */ #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 4.23 (Berkeley) 9/20/88"; #endif /* not lint */ #include "private.h" #if HAVE_ADJTIME || HAVE_SETTIMEOFDAY #include "sys/time.h" /* for struct timeval, struct timezone */ #endif /* HAVE_ADJTIME || HAVE_SETTIMEOFDAY */ #include "locale.h" #include "utmp.h" /* for OLD_TIME (or its absence) */ #if HAVE_UTMPX_H #include "utmpx.h" #endif #ifndef OTIME_MSG #define OTIME_MSG "old time" #endif #ifndef NTIME_MSG #define NTIME_MSG "new time" #endif /* ** The two things date knows about time are. . . */ #ifndef TM_YEAR_BASE #define TM_YEAR_BASE 1900 #endif /* !defined TM_YEAR_BASE */ #ifndef SECSPERMIN #define SECSPERMIN 60 #endif /* !defined SECSPERMIN */ extern char ** environ; #if 0 extern double atof(); extern char * getlogin(); extern time_t mktime(); extern char * optarg; extern int optind; extern char * strchr(); extern time_t time(); extern char * tzname[2]; #endif static int retval = EXIT_SUCCESS; static void checkfinal P((const char *, int, time_t, time_t)); static int comptm P((const struct tm *, const struct tm *)); static time_t convert P((const char *, int, time_t)); static void display P((const char *)); static void dogmt P((void)); static void errensure P((void)); static void iffy P((time_t, time_t, const char *, const char *)); int main P((int, char**)); static const char * nondigit P((const char *)); static void oops P((const char *)); static void reset P((time_t, int)); static void timeout P((FILE *, const char *, const struct tm *)); static void usage P((void)); static void wildinput P((const char *, const char *, const char *)); int main(argc, argv) const int argc; char * argv[]; { register const char * format; register const char * value; register const char * cp; register int ch; register int dousg; register int aflag = 0; register int dflag = 0; register int nflag = 0; register int tflag = 0; register int minuteswest; register int dsttime; register double adjust; time_t now; time_t t; INITIALIZE(dousg); INITIALIZE(minuteswest); INITIALIZE(dsttime); INITIALIZE(adjust); INITIALIZE(t); #ifdef LC_ALL (void) setlocale(LC_ALL, ""); #endif /* defined(LC_ALL) */ #if HAVE_GETTEXT #ifdef TZ_DOMAINDIR (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR); #endif /* defined(TEXTDOMAINDIR) */ (void) textdomain(TZ_DOMAIN); #endif /* HAVE_GETTEXT */ (void) time(&now); format = value = NULL; while ((ch = getopt(argc, argv, "ucnd:t:a:")) != EOF && ch != -1) { switch (ch) { default: usage(); case 'u': /* do it in UTC */ case 'c': dogmt(); break; case 'n': /* don't set network */ nflag = 1; break; case 'd': /* daylight saving time */ if (dflag) { (void) fprintf(stderr, _("date: error: multiple -d's used")); usage(); } dflag = 1; cp = optarg; dsttime = atoi(cp); if (*cp == '\0' || *nondigit(cp) != '\0') wildinput(_("-t value"), optarg, _("must be a non-negative number")); break; case 't': /* minutes west of UTC */ if (tflag) { (void) fprintf(stderr, _("date: error: multiple -t's used")); usage(); } tflag = 1; cp = optarg; minuteswest = atoi(cp); if (*cp == '+' || *cp == '-') ++cp; if (*cp == '\0' || *nondigit(cp) != '\0') wildinput(_("-d value"), optarg, _("must be a number")); break; case 'a': /* adjustment */ if (aflag) { (void) fprintf(stderr, _("date: error: multiple -a's used")); usage(); } aflag = 1; cp = optarg; adjust = atof(cp); if (*cp == '+' || *cp == '-') ++cp; if (*cp == '\0' || strcmp(cp, ".") == 0) wildinput(_("-a value"), optarg, _("must be a number")); cp = nondigit(cp); if (*cp == '.') ++cp; if (*nondigit(cp) != '\0') wildinput(_("-a value"), optarg, _("must be a number")); break; } } while (optind < argc) { cp = argv[optind++]; if (*cp == '+') if (format == NULL) format = cp + 1; else { (void) fprintf(stderr, _("date: error: multiple formats in command line\n")); usage(); } else if (value == NULL) value = cp; else { (void) fprintf(stderr, _("date: error: multiple values in command line\n")); usage(); } } if (value != NULL) { /* ** This order ensures that "reasonable" twelve-digit inputs ** (such as 120203042006) won't be misinterpreted ** even if time_t's range all the way back to the thirteenth ** century. Do not change the order. */ t = convert(value, (dousg = TRUE), now); if (t == -1) t = convert(value, (dousg = FALSE), now); if (t == -1) { /* ** Out of range values, ** or time that falls in a DST transition hole? */ if ((cp = strchr(value, '.')) != NULL) { /* ** Ensure that the failure of ** TZ=America/New_York date 8712312359.60 ** doesn't get misdiagnosed. (It was ** TZ=America/New_York date 8712311859.60 ** when the leap second was inserted.) ** The normal check won't work since ** the given time is valid in UTC. */ if (atoi(cp + 1) >= SECSPERMIN) wildinput(_("time"), value, _("out of range seconds given")); } dogmt(); t = convert(value, FALSE, now); if (t == -1) t = convert(value, TRUE, now); wildinput(_("time"), value, (t == -1) ? _("out of range value given") : _("time skipped when clock springs forward")); } } /* ** Entire command line has now been checked. */ if (aflag) { #if HAVE_ADJTIME struct timeval tv; tv.tv_sec = (int) adjust; tv.tv_usec = (int) ((adjust - tv.tv_sec) * 1000000L); if (adjtime(&tv, (struct timeval *) NULL) != 0) oops("adjtime"); #endif /* HAVE_ADJTIME */ #if !HAVE_ADJTIME reset((time_t) (now + adjust), nflag); #endif /* !HAVE_ADJTIME */ /* ** Sun silently ignores everything else; we follow suit. */ exit(retval); } if (dflag || tflag) { #if HAVE_SETTIMEOFDAY == 2 struct timezone tz; if (!dflag || !tflag) if (gettimeofday((struct timeval *) NULL, &tz) != 0) oops("gettimeofday"); if (dflag) tz.tz_dsttime = dsttime; if (tflag) tz.tz_minuteswest = minuteswest; if (settimeofday((struct timeval *) NULL, &tz) != 0) oops("settimeofday"); #endif /* HAVE_SETTIMEOFDAY == 2 */ #if HAVE_SETTIMEOFDAY != 2 (void) fprintf(stderr, _("date: warning: kernel doesn't keep -d/-t information, option ignored\n")); #endif /* HAVE_SETTIMEOFDAY != 2 */ } if (value == NULL) display(format); reset(t, nflag); checkfinal(value, dousg, t, now); #ifdef EBUG { struct tm tm; tm = *localtime(&t); timeout(stdout, "%c\n", &tm); exit(retval); } #endif /* defined EBUG */ display(format); /* gcc -Wall pacifier */ for ( ; ; ) continue; } static void dogmt() { static char ** fakeenv; if (fakeenv == NULL) { register int from; register int to; register int n; static char tzegmt0[] = "TZ=GMT0"; for (n = 0; environ[n] != NULL; ++n) continue; fakeenv = (char **) malloc((size_t) (n + 2) * sizeof *fakeenv); if (fakeenv == NULL) { (void) perror(_("Memory exhausted")); errensure(); exit(retval); } to = 0; fakeenv[to++] = tzegmt0; for (from = 1; environ[from] != NULL; ++from) if (strncmp(environ[from], "TZ=", 3) != 0) fakeenv[to++] = environ[from]; fakeenv[to] = NULL; environ = fakeenv; } } #ifdef OLD_TIME /* ** We assume we're on a System-V-based system, ** should use stime, ** should write System-V-format utmp entries, ** and don't have network notification to worry about. */ /*ARGSUSED*/ static void #if __STDC__ reset(const time_t newt, const int nflag) #else /* !__STDC__ */ reset(newt, nflag) const time_t newt; const int nflag; #endif /* !__STDC__ */ { register int fid; time_t oldt; static struct { struct utmp before; struct utmp after; } s; #if HAVE_UTMPX_H static struct { struct utmpx before; struct utmpx after; } sx; #endif /* ** Wouldn't it be great if stime returned the old time? */ (void) time(&oldt); if (stime(&newt) != 0) oops("stime"); s.before.ut_type = OLD_TIME; s.before.ut_time = oldt; (void) strcpy(s.before.ut_line, OTIME_MSG); s.after.ut_type = NEW_TIME; s.after.ut_time = newt; (void) strcpy(s.after.ut_line, NTIME_MSG); fid = open(WTMP_FILE, O_WRONLY | O_APPEND); if (fid < 0) oops(_("log file open")); if (write(fid, (char *) &s, sizeof s) != sizeof s) oops(_("log file write")); if (close(fid) != 0) oops(_("log file close")); #if !HAVE_UTMPX_H pututline(&s.before); pututline(&s.after); #endif /* !HAVE_UTMPX_H */ #if HAVE_UTMPX_H sx.before.ut_type = OLD_TIME; sx.before.ut_tv.tv_sec = oldt; (void) strcpy(sx.before.ut_line, OTIME_MSG); sx.after.ut_type = NEW_TIME; sx.after.ut_tv.tv_sec = newt; (void) strcpy(sx.after.ut_line, NTIME_MSG); #if !SUPPRESS_WTMPX_FILE_UPDATE /* In Solaris 2.5 (and presumably other systems), `date' does not update /var/adm/wtmpx. This must be a bug. If you'd like to reproduce the bug, define SUPPRESS_WTMPX_FILE_UPDATE to be nonzero. */ fid = open(WTMPX_FILE, O_WRONLY | O_APPEND); if (fid < 0) oops(_("log file open")); if (write(fid, (char *) &sx, sizeof sx) != sizeof sx) oops(_("log file write")); if (close(fid) != 0) oops(_("log file close")); #endif /* !SUPPRESS_WTMPX_FILE_UPDATE */ pututxline(&sx.before); pututxline(&sx.after); #endif /* HAVE_UTMPX_H */ } #endif /* defined OLD_TIME */ #ifndef OLD_TIME /* ** We assume we're on a BSD-based system, ** should use settimeofday, ** should write BSD-format utmp entries (using logwtmp), ** and may get to worry about network notification. ** The "time name" changes between 4.3-tahoe and 4.4; ** we include sys/param.h to determine which we should use. */ #ifndef TIME_NAME #include "sys/param.h" #ifdef BSD4_4 #define TIME_NAME "date" #endif /* defined BSD4_4 */ #ifndef BSD4_4 #define TIME_NAME "" #endif /* !defined BSD4_4 */ #endif /* !defined TIME_NAME */ #include "syslog.h" #include "sys/socket.h" #include "netinet/in.h" #include "netdb.h" #define TSPTYPES #if 0 extern int logwtmp(); #endif #if HAVE_SETTIMEOFDAY == 1 #define settimeofday(t, tz) (settimeofday)(t) #endif /* HAVE_SETTIMEOFDAY == 1 */ #ifndef TSP_SETDATE /*ARGSUSED*/ #endif /* !defined TSP_SETDATE */ static void reset(newt, nflag) const time_t newt; const int nflag; { register const char * username; static struct timeval tv; /* static so tv_usec is 0 */ #ifdef EBUG return; #endif /* defined EBUG */ username = getlogin(); if (username == NULL || *username == '\0') /* single-user or no tty */ username = "root"; tv.tv_sec = newt; #ifdef TSP_SETDATE if (nflag || !netsettime(tv)) #endif /* defined TSP_SETDATE */ { /* ** "old" entry is always written, for compatibility. */ logwtmp("|", TIME_NAME, ""); if (settimeofday(&tv, (struct timezone *) NULL) == 0) { logwtmp("{", TIME_NAME, ""); /* } */ syslog(LOG_AUTH | LOG_NOTICE, _("date set by %s"), username); } else oops("settimeofday"); } } #endif /* !defined OLD_TIME */ static void wildinput(item, value, reason) const char * const item; const char * const value; const char * const reason; { (void) fprintf(stderr, _("date: error: bad command line %s \"%s\", %s\n"), item, value, reason); usage(); } static void errensure P((void)) { if (retval == EXIT_SUCCESS) retval = EXIT_FAILURE; } static const char * nondigit(cp) register const char * cp; { while (is_digit(*cp)) ++cp; return cp; } static void usage P((void)) { (void) fprintf(stderr, _("date: usage is date [-u] [-c] [-n] [-d dst] \ [-t min-west] [-a sss.fff] [[yyyy]mmddhhmm[yyyy][.ss]] [+format]\n")); errensure(); exit(retval); } static void oops(string) const char * const string; { int e = errno; (void) fprintf(stderr, _("date: error: ")); errno = e; (void) perror(string); errensure(); display((char *) NULL); } static void display(format) const char * const format; { struct tm tm; time_t now; (void) time(&now); tm = *localtime(&now); timeout(stdout, format ? format : "%+", &tm); (void) putchar('\n'); (void) fflush(stdout); (void) fflush(stderr); if (ferror(stdout) || ferror(stderr)) { (void) fprintf(stderr, _("date: error: couldn't write results\n")); errensure(); } exit(retval); } #if 0 extern size_t strftime(); #endif #define INCR 1024 static void timeout(fp, format, tmp) FILE * const fp; const char * const format; const struct tm * const tmp; { char * cp; size_t result; size_t size; if (*format == '\0') return; size = INCR; cp = malloc((size_t) size); for ( ; ; ) { if (cp == NULL) { (void) fprintf(stderr, _("date: error: can't get memory\n")); errensure(); exit(retval); } cp[0] = '\1'; result = strftime(cp, size, format, tmp); if (result != 0 || cp[0] == '\0') break; size += INCR; cp = realloc(cp, (size_t) size); } (void) fwrite(cp, 1, result, fp); free(cp); } static int comptm(atmp, btmp) register const struct tm * const atmp; register const struct tm * const btmp; { register int result; if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && (result = (atmp->tm_min - btmp->tm_min)) == 0) result = atmp->tm_sec - btmp->tm_sec; return result; } /* ** convert -- ** convert user's input into a time_t. */ #define ATOI2(ar) (ar[0] - '0') * 10 + (ar[1] - '0'); ar += 2; static time_t #if __STDC__ convert(register const char * const value, const int dousg, const time_t t) #else /* !__STDC__ */ convert(value, dousg, t) register const char * const value; const int dousg; const time_t t; #endif /* !__STDC__ */ { register const char * cp; register const char * dotp; register int cent, year_in_cent, month, hour, day, mins, secs; struct tm tm, outtm; time_t outt; tm = *localtime(&t); #define DIVISOR 100 year_in_cent = tm.tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR; cent = tm.tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR + year_in_cent / DIVISOR; year_in_cent %= DIVISOR; if (year_in_cent < 0) { year_in_cent += DIVISOR; --cent; } month = tm.tm_mon + 1; day = tm.tm_mday; hour = tm.tm_hour; mins = tm.tm_min; secs = 0; dotp = strchr(value, '.'); for (cp = value; *cp != '\0'; ++cp) if (!is_digit(*cp) && cp != dotp) wildinput(_("time"), value, _("contains a nondigit")); if (dotp == NULL) dotp = strchr(value, '\0'); else { cp = dotp + 1; if (strlen(cp) != 2) wildinput(_("time"), value, _("seconds part is not two digits")); secs = ATOI2(cp); } cp = value; switch (dotp - cp) { default: wildinput(_("time"), value, _("main part is wrong length")); case 12: if (!dousg) { cent = ATOI2(cp); year_in_cent = ATOI2(cp); } month = ATOI2(cp); day = ATOI2(cp); hour = ATOI2(cp); mins = ATOI2(cp); if (dousg) { cent = ATOI2(cp); year_in_cent = ATOI2(cp); } break; case 8: /* mmddhhmm */ month = ATOI2(cp); /* fall through to. . . */ case 6: /* ddhhmm */ day = ATOI2(cp); /* fall through to. . . */ case 4: /* hhmm */ hour = ATOI2(cp); mins = ATOI2(cp); break; case 10: if (!dousg) { year_in_cent = ATOI2(cp); } month = ATOI2(cp); day = ATOI2(cp); hour = ATOI2(cp); mins = ATOI2(cp); if (dousg) { year_in_cent = ATOI2(cp); } break; } tm.tm_year = cent * 100 + year_in_cent - TM_YEAR_BASE; tm.tm_mon = month - 1; tm.tm_mday = day; tm.tm_hour = hour; tm.tm_min = mins; tm.tm_sec = secs; tm.tm_isdst = -1; outtm = tm; outt = mktime(&outtm); return (comptm(&tm, &outtm) == 0) ? outt : -1; } /* ** Code from here on out is either based on code provided by UCB ** or is only called just before the program exits. */ /* ** Check for iffy input. */ static void #if __STDC__ checkfinal(const char * const value, const int didusg, const time_t t, const time_t oldnow) #else /* !__STDC__ */ checkfinal(value, didusg, t, oldnow) const char * const value; const int didusg; const time_t t; const time_t oldnow; #endif /* !__STDC__ */ { time_t othert; struct tm tm; struct tm othertm; register int pass; register long offset; /* ** See if there's both a USG and a BSD interpretation. */ othert = convert(value, !didusg, oldnow); if (othert != -1 && othert != t) iffy(t, othert, value, _("year could be at start or end")); /* ** See if there's both a DST and a STD version. */ tm = *localtime(&t); othertm = tm; othertm.tm_isdst = !tm.tm_isdst; othert = mktime(&othertm); if (othert != -1 && othertm.tm_isdst != tm.tm_isdst && comptm(&tm, &othertm) == 0) iffy(t, othert, value, _("both standard and summer time versions exist")); /* ** Final check. ** ** If a jurisdiction shifts time *without* shifting whether time is ** summer or standard (as Hawaii, the United Kingdom, and Saudi Arabia ** have done), routine checks for iffy times may not work. ** So we perform this final check, deferring it until after the time has ** been set--it may take a while, and we don't want to introduce an unnecessary ** lag between the time the user enters their command and the time that ** stime/settimeofday is called. ** ** We just check nearby times to see if any have the same representation ** as the time that convert returned. We work our way out from the center ** for quick response in solar time situations. We only handle common cases-- ** offsets of at most a minute, and offsets of exact numbers of minutes ** and at most an hour. */ for (offset = 1; offset <= 60; ++offset) for (pass = 1; pass <= 4; ++pass) { if (pass == 1) othert = t + offset; else if (pass == 2) othert = t - offset; else if (pass == 3) othert = t + 60 * offset; else othert = t - 60 * offset; othertm = *localtime(&othert); if (comptm(&tm, &othertm) == 0) iffy(t, othert, value, _("multiple matching times exist")); } } static void #if __STDC__ iffy(const time_t thist, const time_t thatt, const char * const value, const char * const reason) #else /* !__STDC__ */ iffy(thist, thatt, value, reason) const time_t thist; const time_t thatt; const char * const value; const char * const reason; #endif /* !__STDC__ */ { struct tm tm; (void) fprintf(stderr, _("date: warning: ambiguous time \"%s\", %s.\n"), value, reason); tm = *gmtime(&thist); /* ** Avoid running afoul of SCCS! */ timeout(stderr, _("Time was set as if you used\n\tdate -u %m%d%H\ %M\ %Y.%S\n"), &tm); tm = *localtime(&thist); timeout(stderr, _("to get %c"), &tm); (void) fprintf(stderr, _(" (%s). Use\n"), tm.tm_isdst ? _("summer time") : _("standard time")); tm = *gmtime(&thatt); timeout(stderr, _("\tdate -u %m%d%H\ %M\ %Y.%S\n"), &tm); tm = *localtime(&thatt); timeout(stderr, _("to get %c"), &tm); (void) fprintf(stderr, _(" (%s).\n"), tm.tm_isdst ? _("summer time") : _("standard time")); errensure(); exit(retval); } #ifdef TSP_SETDATE #define WAITACK 2 /* seconds */ #define WAITDATEACK 5 /* seconds */ /* * 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 1 on success, 0 on failure. */ netsettime(ntv) struct timeval ntv; { int s, length, port, timed_ack, found, err; long waittime; fd_set ready; char hostname[MAXHOSTNAMELEN]; struct timeval tout; struct servent *sp; struct tsp msg; struct sockaddr_in sin, dest, from; sp = getservbyname("timed", "udp"); if (sp == 0) { fputs(_("udp/timed: unknown service\n"), stderr); retval = 2; return (0); } 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: socket"); goto bad; } 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) { if (errno != EADDRNOTAVAIL) perror("date: bind"); goto bad; } } if (port == IPPORT_RESERVED / 2) { fputs(_("date: All ports in use\n"), stderr); goto bad; } msg.tsp_type = TSP_SETDATE; msg.tsp_vers = TSPVERSION; if (gethostname(hostname, sizeof (hostname))) { perror("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)ntv.tv_sec); msg.tsp_time.tv_usec = htonl((u_long)ntv.tv_usec); length = sizeof (struct sockaddr_in); if (connect(s, &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) == 0 && err) { errno = err; if (errno != ECONNREFUSED) perror(_("date: send (delayed error)")); goto bad; } if (found > 0 && FD_ISSET(s, &ready)) { length = sizeof (struct sockaddr_in); if (recvfrom(s, (char *)&msg, sizeof (struct tsp), 0, &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 (1); default: fprintf(stderr, _("date: Wrong ack received from timed: %s\n"), tsptype[msg.tsp_type]); timed_ack = -1; break; } } if (timed_ack == -1) fputs(_("date: Can't reach time daemon, time set locally.\n"), stderr); bad: (void)close(s); retval = 2; return (0); } #endif /* defined TSP_SETDATE */