# 2.11BSD#431 - /usr/src/bin/date.c

##### Functions

    main              X

##### Variables

    copyright         X

##### Macros

    ATOI2             X
    TSPTYPES          X
    WAITACK           X
    WAITDATEACK       X
    WTMP              X

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

#### Defined functions

gtime defined in line 161; used 1 times

- in line 104

main defined in line 46; never used
netsettime defined in line 248; used 1 times

- in line 116

#### Defined variables

copyright defined in line 8; never used
dmsize defined in line 38; used 1 times

- in line 223

retval defined in line 36; used 6 times

- in line 91, 106, 119, 154, 264, 364

sccsid defined in line 12; never used
tv defined in line 35; used 22 times

- in line 95, 103, 111-117(5), 138-143(2), 149, 182, 212, 219-227(10)

wtmp defined in line 41; used 4 times

- in line 103, 125-127(3)

#### Defined macros

ATOI2 defined in line 33; used 5 times

- in line 189-196(5)

TSPTYPES defined in line 234; never used
WAITACK defined in line 237; used 1 times

- in line 314

WAITDATEACK defined in line 238; used 1 times

- in line 344

WTMP defined in line 32; used 1 times

- in line 122

Last modified: 1996-07-11 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1860 |