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: }

Defined functions

gp defined in line 208; used 6 times
gtime defined in line 149; used 1 times
main defined in line 56; never used
settime defined in line 239; used 1 times

Defined variables

ap defined in line 33; used 8 times
copyright defined in line 8; never used
dmsize defined in line 38; used 1 times
ep defined in line 33; used 6 times
nflag defined in line 34; used 2 times
now defined in line 31; used 1 times
  • in line 64
retval defined in line 35; used 6 times
sccsid defined in line 14; never used
sp defined in line 33; used 16 times
tv defined in line 31; used 28 times
tz defined in line 32; used 3 times
uflag defined in line 34; used 3 times
usage defined in line 40; used 3 times
username defined in line 52; used 5 times
wtmp defined in line 42; used 4 times

Defined macros

TSPTYPES defined in line 224; never used
WAITACK defined in line 227; used 1 times
WAITDATEACK defined in line 228; used 1 times
WTMP defined in line 29; used 1 times
Last modified: 1986-05-19
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1038
Valid CSS Valid XHTML 1.0 Strict