2013-08-02 16:10:30 +02:00
|
|
|
/* frontend to the readclock.drv driver for getting/setting hw clock. */
|
|
|
|
|
|
|
|
#include <sys/cdefs.h>
|
|
|
|
#include <lib.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <stdlib.h>
|
2013-11-04 22:48:08 +01:00
|
|
|
#include <string.h>
|
2013-08-02 16:10:30 +02:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <minix/type.h>
|
|
|
|
#include <minix/const.h>
|
|
|
|
#include <minix/syslib.h>
|
|
|
|
#include <minix/sysutil.h>
|
|
|
|
#include <minix/com.h>
|
|
|
|
#include <minix/rs.h>
|
|
|
|
#include <sys/ipc.h>
|
|
|
|
|
|
|
|
void errmsg(char *s);
|
2013-08-08 02:06:47 +02:00
|
|
|
static void readclock(int type, struct tm *t, int flags);
|
2013-08-02 16:10:30 +02:00
|
|
|
void usage(void);
|
|
|
|
|
2013-08-08 02:06:47 +02:00
|
|
|
int quiet = 0;
|
|
|
|
|
2013-08-02 16:10:30 +02:00
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
2013-08-08 02:06:47 +02:00
|
|
|
int flags = RTCDEV_NOFLAGS;
|
|
|
|
int nflag = 0; /* Tell what, but don't do it. */
|
|
|
|
int wflag = 0; /* Set the CMOS clock. */
|
2013-08-02 16:10:30 +02:00
|
|
|
struct tm time1;
|
|
|
|
struct tm time2;
|
|
|
|
struct tm tmnow;
|
|
|
|
char date[64];
|
|
|
|
time_t now, rtc;
|
|
|
|
int i, s;
|
|
|
|
|
|
|
|
/* Process options. */
|
|
|
|
while (argc > 1) {
|
|
|
|
char *p = *++argv;
|
|
|
|
|
|
|
|
if (*p++ != '-')
|
|
|
|
usage();
|
|
|
|
|
|
|
|
while (*p != 0) {
|
|
|
|
switch (*p++) {
|
|
|
|
case 'n':
|
|
|
|
nflag = 1;
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
wflag = 1;
|
|
|
|
break;
|
|
|
|
case 'W':
|
2013-08-08 02:06:47 +02:00
|
|
|
flags |= RTCDEV_CMOSREG;
|
|
|
|
wflag = 1; /* -W implies -w */
|
2013-08-02 16:10:30 +02:00
|
|
|
break;
|
|
|
|
case '2':
|
2013-08-08 02:06:47 +02:00
|
|
|
flags |= RTCDEV_Y2KBUG;
|
|
|
|
break;
|
|
|
|
case 'q':
|
|
|
|
quiet = 1;
|
2013-08-02 16:10:30 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
argc--;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read the CMOS real time clock. */
|
|
|
|
for (i = 0; i < 10; i++) {
|
2013-08-08 02:06:47 +02:00
|
|
|
readclock(RTCDEV_GET_TIME, &time1, flags);
|
2013-08-02 16:10:30 +02:00
|
|
|
now = time(NULL);
|
|
|
|
|
|
|
|
time1.tm_isdst = -1; /* Do timezone calculations. */
|
|
|
|
time2 = time1;
|
|
|
|
|
|
|
|
rtc = mktime(&time1); /* Transform to a time_t. */
|
|
|
|
if (rtc != -1)
|
|
|
|
break;
|
|
|
|
|
2013-08-08 02:06:47 +02:00
|
|
|
if (!quiet) printf
|
2013-08-02 16:10:30 +02:00
|
|
|
("readclock: Invalid time read from CMOS RTC: %d-%02d-%02d %02d:%02d:%02d\n",
|
|
|
|
time2.tm_year + 1900, time2.tm_mon + 1, time2.tm_mday,
|
|
|
|
time2.tm_hour, time2.tm_min, time2.tm_sec);
|
|
|
|
sleep(5);
|
|
|
|
}
|
|
|
|
if (i == 10)
|
|
|
|
exit(1);
|
|
|
|
|
|
|
|
if (!wflag) {
|
|
|
|
/* Set system time. */
|
|
|
|
if (nflag) {
|
2013-08-08 02:06:47 +02:00
|
|
|
if (!quiet)
|
|
|
|
printf("stime(%lu)\n", (unsigned long) rtc);
|
2013-08-02 16:10:30 +02:00
|
|
|
} else {
|
|
|
|
if (stime(&rtc) < 0) {
|
2013-08-08 02:06:47 +02:00
|
|
|
if (!quiet)
|
|
|
|
errmsg("Not allowed to set time.");
|
2013-08-02 16:10:30 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tmnow = *localtime(&rtc);
|
|
|
|
if (strftime(date, sizeof(date),
|
|
|
|
"%a %b %d %H:%M:%S %Z %Y", &tmnow) != 0) {
|
|
|
|
if (date[8] == '0')
|
|
|
|
date[8] = ' ';
|
2013-08-08 02:06:47 +02:00
|
|
|
if (!quiet) printf("%s\n", date);
|
2013-08-02 16:10:30 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Set the CMOS clock to the system time. */
|
|
|
|
tmnow = *localtime(&now);
|
|
|
|
if (nflag) {
|
2013-08-08 02:06:47 +02:00
|
|
|
if (!quiet)
|
|
|
|
printf("%04d-%02d-%02d %02d:%02d:%02d\n",
|
|
|
|
tmnow.tm_year + 1900,
|
|
|
|
tmnow.tm_mon + 1,
|
|
|
|
tmnow.tm_mday,
|
|
|
|
tmnow.tm_hour, tmnow.tm_min, tmnow.tm_sec);
|
2013-08-02 16:10:30 +02:00
|
|
|
} else {
|
2013-08-08 02:06:47 +02:00
|
|
|
readclock(RTCDEV_SET_TIME, &tmnow, flags);
|
2013-08-02 16:10:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
errmsg(char *s)
|
|
|
|
{
|
|
|
|
static char *prompt = "readclock: ";
|
|
|
|
|
2013-08-08 02:06:47 +02:00
|
|
|
if (!quiet) printf("%s%s\n", prompt, s);
|
2013-08-02 16:10:30 +02:00
|
|
|
prompt = "";
|
|
|
|
}
|
|
|
|
|
2013-08-08 02:06:47 +02:00
|
|
|
static void
|
|
|
|
readclock(int type, struct tm *t, int flags)
|
2013-08-02 16:10:30 +02:00
|
|
|
{
|
|
|
|
int r;
|
|
|
|
message m;
|
|
|
|
endpoint_t ep;
|
|
|
|
|
|
|
|
r = minix_rs_lookup("readclock.drv", &ep);
|
|
|
|
if (r != 0) {
|
2013-08-08 02:06:47 +02:00
|
|
|
if (!quiet) errmsg("Couldn't locate readclock.drv\n");
|
2013-08-02 16:10:30 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2013-11-04 22:48:08 +01:00
|
|
|
memset(&m, 0, sizeof(m));
|
2013-08-08 02:06:47 +02:00
|
|
|
m.RTCDEV_TM = (char *) t;
|
|
|
|
m.RTCDEV_FLAGS = flags;
|
2013-08-02 16:10:30 +02:00
|
|
|
|
2013-08-08 02:06:47 +02:00
|
|
|
r = _syscall(ep, type, &m);
|
2013-08-02 16:10:30 +02:00
|
|
|
if (r != RTCDEV_REPLY || m.RTCDEV_STATUS != 0) {
|
2013-08-08 02:06:47 +02:00
|
|
|
if (!quiet) errmsg("Call to readclock.drv failed\n");
|
2013-08-02 16:10:30 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
usage(void)
|
|
|
|
{
|
2013-08-08 02:06:47 +02:00
|
|
|
if (!quiet) printf("Usage: readclock [-nqwW2]\n");
|
2013-08-02 16:10:30 +02:00
|
|
|
exit(1);
|
|
|
|
}
|