* Copyright (c) 1985 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
"@(#) Copyright (c) 1985 Regents of the University of California.\n\
static char *sccsid
= "@(#)date.c 4.22 (Berkeley) %G%";
* Date - print and set date
#define WTMP "/usr/adm/wtmp"
#define ATOI2(ar) (ar[0] - '0') * 10 + (ar[1] - '0'); ar += 2;
static struct timeval tv
;
{ -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
static struct utmp wtmp
[2] = {
char *ap
, /* time string */
int ch
, /* getopts char */
uflag
, /* do it in GMT */
nflag
, /* only set time locally */
wf
; /* wtmp file descriptor */
char *username
, *getlogin();
tz
.tz_dsttime
= tz
.tz_minuteswest
= 0;
while ((ch
= getopt(argc
,argv
,"d:nut:")) != EOF
)
tz
.tz_dsttime
= atoi(optarg
) ? 1 : 0;
case 't': /* error check; we can't allow "PST" */
tz
.tz_minuteswest
= atoi(optarg
);
if ((tz
.tz_minuteswest
|| tz
.tz_dsttime
) &&
settimeofday((struct timeval
*)NULL
,&tz
)) {
if (gettimeofday(&tv
,&tz
)) {
wtmp
[0].ut_time
= tv
.tv_sec
;
if (!uflag
) { /* convert to GMT assuming local time */
tv
.tv_sec
+= (long)tz
.tz_minuteswest
* SECS_PER_MIN
;
/* now fix up local daylight time */
if (localtime((time_t *)&tv
.tv_sec
)->tm_isdst
)
tv
.tv_sec
-= SECS_PER_HOUR
;
if (nflag
|| !netsettime(tv
)) {
if (settimeofday(&tv
,(struct timezone
*)0)) {
if ((wf
= open(WTMP
,O_WRONLY
|O_APPEND
)) < 0)
fputs("date: can't write wtmp file.\n",stderr
);
(void)time((time_t *)&wtmp
[1].ut_time
);
(void)write(wf
,(char *)wtmp
,sizeof(wtmp
));
if (!username
|| *username
== '\0') /* single-user or no tty */
syslog(LOG_AUTH
| LOG_NOTICE
,"date set by %s",username
);
if (gettimeofday(&tv
,(struct timezone
*)0)) {
ap
= asctime(gmtime((time_t *)&tv
.tv_sec
));
tp
= localtime((time_t *)&tv
.tv_sec
);
printf("%.20s%s%s",ap
,tzn
,ap
+ 19);
* convert user's time into number of seconds
register char *ap
; /* user argument */
register int year
, month
;
register char *C
; /* pointer into time argument */
int day
, hour
, mins
, secs
;
for (secs
= 0, C
= ap
;*C
;++C
) {
if (*C
== '.') { /* seconds provided */
secs
= (C
[1] - '0') * 10 + (C
[2] - '0');
L
= localtime((time_t *)&tv
.tv_sec
);
year
= L
->tm_year
; /* defaults */
switch ((int)(C
- ap
)) { /* length */
case 10: /* yymmddhhmm */
if (*ap
|| month
< 1 || month
> 12 || day
< 1 || day
> 31 ||
mins
< 0 || mins
> 59 || secs
< 0 || secs
> 59)
else if (hour
< 0 || hour
> 23)
if (isleap(year
) && month
> 2)
for (--year
;year
>= EPOCH_YEAR
;--year
)
tv
.tv_sec
+= isleap(year
) ? DAYS_PER_LYEAR
: DAYS_PER_NYEAR
;
tv
.tv_sec
+= dmsize
[month
];
tv
.tv_sec
= HOURS_PER_DAY
* tv
.tv_sec
+ hour
;
tv
.tv_sec
= MINS_PER_HOUR
* tv
.tv_sec
+ mins
;
tv
.tv_sec
= SECS_PER_MIN
* tv
.tv_sec
+ secs
;
#include <protocols/timed.h>
#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.
int s
, length
, port
, timed_ack
, found
, err
;
char hostname
[MAXHOSTNAMELEN
];
struct sockaddr_in sin
, dest
, from
;
sp
= getservbyname("timed", "udp");
fputs("udp/timed: unknown service\n",stderr
);
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 (errno
!= EPROTONOSUPPORT
)
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)
if (errno
!= EADDRINUSE
) {
if (errno
!= EADDRNOTAVAIL
)
if (port
== IPPORT_RESERVED
/ 2) {
fputs("date: All ports in use\n",stderr
);
msg
.tsp_type
= TSP_SETDATE
;
msg
.tsp_vers
= TSPVERSION
;
if (gethostname(hostname
, sizeof (hostname
))) {
(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) {
if (send(s
, (char *)&msg
, sizeof (struct tsp
), 0) < 0) {
if (errno
!= ECONNREFUSED
)
found
= select(FD_SETSIZE
, &ready
, (fd_set
*)0, (fd_set
*)0, &tout
);
if (getsockopt(s
, SOL_SOCKET
, SO_ERROR
, (char *)&err
, &length
) == 0
if (errno
!= ECONNREFUSED
)
perror("date: send (delayed error)");
if (found
> 0 && FD_ISSET(s
, &ready
)) {
length
= sizeof (struct sockaddr_in
);
if (recvfrom(s
, (char *)&msg
, sizeof (struct tsp
), 0, &from
,
if (errno
!= ECONNREFUSED
)
perror("date: recvfrom");
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
);
"date: Wrong ack received from timed: %s\n",
fputs("date: Can't reach time daemon, time set locally.\n",
fputs("usage: date [-nu] [-d dst] [-t minutes_west] [yymmddhhmm[.ss]]\n",stderr
);