xref: /minix3/minix/commands/readclock/readclock.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc /* frontend to the readclock.drv driver for getting/setting hw clock. */
2*433d6423SLionel Sambuc 
3*433d6423SLionel Sambuc #include <sys/cdefs.h>
4*433d6423SLionel Sambuc #include <lib.h>
5*433d6423SLionel Sambuc #include <sys/types.h>
6*433d6423SLionel Sambuc #include <stdlib.h>
7*433d6423SLionel Sambuc #include <string.h>
8*433d6423SLionel Sambuc #include <unistd.h>
9*433d6423SLionel Sambuc #include <stdio.h>
10*433d6423SLionel Sambuc #include <time.h>
11*433d6423SLionel Sambuc #include <errno.h>
12*433d6423SLionel Sambuc #include <minix/type.h>
13*433d6423SLionel Sambuc #include <minix/const.h>
14*433d6423SLionel Sambuc #include <minix/syslib.h>
15*433d6423SLionel Sambuc #include <minix/sysutil.h>
16*433d6423SLionel Sambuc #include <minix/com.h>
17*433d6423SLionel Sambuc #include <minix/rs.h>
18*433d6423SLionel Sambuc #include <sys/ipc.h>
19*433d6423SLionel Sambuc 
20*433d6423SLionel Sambuc void errmsg(char *s);
21*433d6423SLionel Sambuc static void readclock(int type, struct tm *t, int flags);
22*433d6423SLionel Sambuc void usage(void);
23*433d6423SLionel Sambuc 
24*433d6423SLionel Sambuc int quiet = 0;
25*433d6423SLionel Sambuc 
26*433d6423SLionel Sambuc int
main(int argc,char ** argv)27*433d6423SLionel Sambuc main(int argc, char **argv)
28*433d6423SLionel Sambuc {
29*433d6423SLionel Sambuc 	int flags = RTCDEV_NOFLAGS;
30*433d6423SLionel Sambuc 	int nflag = 0;	/* Tell what, but don't do it. */
31*433d6423SLionel Sambuc 	int wflag = 0;	/* Set the CMOS clock. */
32*433d6423SLionel Sambuc 	struct tm time1;
33*433d6423SLionel Sambuc 	struct tm time2;
34*433d6423SLionel Sambuc 	struct tm tmnow;
35*433d6423SLionel Sambuc 	char date[64];
36*433d6423SLionel Sambuc 	time_t now, rtc;
37*433d6423SLionel Sambuc 	int i, s;
38*433d6423SLionel Sambuc 
39*433d6423SLionel Sambuc 	/* Process options. */
40*433d6423SLionel Sambuc 	while (argc > 1) {
41*433d6423SLionel Sambuc 		char *p = *++argv;
42*433d6423SLionel Sambuc 
43*433d6423SLionel Sambuc 		if (*p++ != '-')
44*433d6423SLionel Sambuc 			usage();
45*433d6423SLionel Sambuc 
46*433d6423SLionel Sambuc 		while (*p != 0) {
47*433d6423SLionel Sambuc 			switch (*p++) {
48*433d6423SLionel Sambuc 			case 'n':
49*433d6423SLionel Sambuc 				nflag = 1;
50*433d6423SLionel Sambuc 				break;
51*433d6423SLionel Sambuc 			case 'w':
52*433d6423SLionel Sambuc 				wflag = 1;
53*433d6423SLionel Sambuc 				break;
54*433d6423SLionel Sambuc 			case 'W':
55*433d6423SLionel Sambuc 				flags |= RTCDEV_CMOSREG;
56*433d6423SLionel Sambuc 				wflag = 1; /* -W implies -w */
57*433d6423SLionel Sambuc 				break;
58*433d6423SLionel Sambuc 			case '2':
59*433d6423SLionel Sambuc 				flags |= RTCDEV_Y2KBUG;
60*433d6423SLionel Sambuc 				break;
61*433d6423SLionel Sambuc 			case 'q':
62*433d6423SLionel Sambuc 				quiet = 1;
63*433d6423SLionel Sambuc 				break;
64*433d6423SLionel Sambuc 			default:
65*433d6423SLionel Sambuc 				usage();
66*433d6423SLionel Sambuc 			}
67*433d6423SLionel Sambuc 		}
68*433d6423SLionel Sambuc 		argc--;
69*433d6423SLionel Sambuc 	}
70*433d6423SLionel Sambuc 
71*433d6423SLionel Sambuc 	/* Read the CMOS real time clock. */
72*433d6423SLionel Sambuc 	for (i = 0; i < 10; i++) {
73*433d6423SLionel Sambuc 		readclock(RTCDEV_GET_TIME, &time1, flags);
74*433d6423SLionel Sambuc 		now = time(NULL);
75*433d6423SLionel Sambuc 
76*433d6423SLionel Sambuc 		time1.tm_isdst = -1;	/* Do timezone calculations. */
77*433d6423SLionel Sambuc 		time2 = time1;
78*433d6423SLionel Sambuc 
79*433d6423SLionel Sambuc 		rtc = mktime(&time1);	/* Transform to a time_t. */
80*433d6423SLionel Sambuc 		if (rtc != -1)
81*433d6423SLionel Sambuc 			break;
82*433d6423SLionel Sambuc 
83*433d6423SLionel Sambuc 		if (!quiet) printf
84*433d6423SLionel Sambuc 		    ("readclock: Invalid time read from CMOS RTC: %d-%02d-%02d %02d:%02d:%02d\n",
85*433d6423SLionel Sambuc 		    time2.tm_year + 1900, time2.tm_mon + 1, time2.tm_mday,
86*433d6423SLionel Sambuc 		    time2.tm_hour, time2.tm_min, time2.tm_sec);
87*433d6423SLionel Sambuc 		sleep(5);
88*433d6423SLionel Sambuc 	}
89*433d6423SLionel Sambuc 	if (i == 10)
90*433d6423SLionel Sambuc 		exit(1);
91*433d6423SLionel Sambuc 
92*433d6423SLionel Sambuc 	if (!wflag) {
93*433d6423SLionel Sambuc 		/* Set system time. */
94*433d6423SLionel Sambuc 		if (nflag) {
95*433d6423SLionel Sambuc 			if (!quiet)
96*433d6423SLionel Sambuc 				printf("stime(%lu)\n", (unsigned long) rtc);
97*433d6423SLionel Sambuc 		} else {
98*433d6423SLionel Sambuc 			if (stime(&rtc) < 0) {
99*433d6423SLionel Sambuc 				if (!quiet)
100*433d6423SLionel Sambuc 					errmsg("Not allowed to set time.");
101*433d6423SLionel Sambuc 				exit(1);
102*433d6423SLionel Sambuc 			}
103*433d6423SLionel Sambuc 		}
104*433d6423SLionel Sambuc 		tmnow = *localtime(&rtc);
105*433d6423SLionel Sambuc 		if (strftime(date, sizeof(date),
106*433d6423SLionel Sambuc 			"%a %b %d %H:%M:%S %Z %Y", &tmnow) != 0) {
107*433d6423SLionel Sambuc 			if (date[8] == '0')
108*433d6423SLionel Sambuc 				date[8] = ' ';
109*433d6423SLionel Sambuc 			if (!quiet) printf("%s\n", date);
110*433d6423SLionel Sambuc 		}
111*433d6423SLionel Sambuc 	} else {
112*433d6423SLionel Sambuc 		/* Set the CMOS clock to the system time. */
113*433d6423SLionel Sambuc 		tmnow = *localtime(&now);
114*433d6423SLionel Sambuc 		if (nflag) {
115*433d6423SLionel Sambuc 			if (!quiet)
116*433d6423SLionel Sambuc 				printf("%04d-%02d-%02d %02d:%02d:%02d\n",
117*433d6423SLionel Sambuc 				    tmnow.tm_year + 1900,
118*433d6423SLionel Sambuc 				    tmnow.tm_mon + 1,
119*433d6423SLionel Sambuc 				    tmnow.tm_mday,
120*433d6423SLionel Sambuc 				    tmnow.tm_hour, tmnow.tm_min, tmnow.tm_sec);
121*433d6423SLionel Sambuc 		} else {
122*433d6423SLionel Sambuc 			readclock(RTCDEV_SET_TIME, &tmnow, flags);
123*433d6423SLionel Sambuc 		}
124*433d6423SLionel Sambuc 	}
125*433d6423SLionel Sambuc 	exit(0);
126*433d6423SLionel Sambuc }
127*433d6423SLionel Sambuc 
128*433d6423SLionel Sambuc void
errmsg(char * s)129*433d6423SLionel Sambuc errmsg(char *s)
130*433d6423SLionel Sambuc {
131*433d6423SLionel Sambuc 	static char *prompt = "readclock: ";
132*433d6423SLionel Sambuc 
133*433d6423SLionel Sambuc 	if (!quiet) printf("%s%s\n", prompt, s);
134*433d6423SLionel Sambuc 	prompt = "";
135*433d6423SLionel Sambuc }
136*433d6423SLionel Sambuc 
137*433d6423SLionel Sambuc static void
readclock(int type,struct tm * t,int flags)138*433d6423SLionel Sambuc readclock(int type, struct tm *t, int flags)
139*433d6423SLionel Sambuc {
140*433d6423SLionel Sambuc 	int r;
141*433d6423SLionel Sambuc 	message m;
142*433d6423SLionel Sambuc 	endpoint_t ep;
143*433d6423SLionel Sambuc 
144*433d6423SLionel Sambuc 	r = minix_rs_lookup("readclock.drv", &ep);
145*433d6423SLionel Sambuc 	if (r != 0) {
146*433d6423SLionel Sambuc 		if (!quiet) errmsg("Couldn't locate readclock.drv\n");
147*433d6423SLionel Sambuc 		exit(1);
148*433d6423SLionel Sambuc 	}
149*433d6423SLionel Sambuc 
150*433d6423SLionel Sambuc 	memset(&m, 0, sizeof(m));
151*433d6423SLionel Sambuc 	m.m_lc_readclock_rtcdev.tm = (vir_bytes)t;
152*433d6423SLionel Sambuc 	m.m_lc_readclock_rtcdev.flags = flags;
153*433d6423SLionel Sambuc 
154*433d6423SLionel Sambuc 	r = _syscall(ep, type, &m);
155*433d6423SLionel Sambuc 	if (r != RTCDEV_REPLY || m.m_readclock_lc_rtcdev.status != 0) {
156*433d6423SLionel Sambuc 		if (!quiet) errmsg("Call to readclock.drv failed\n");
157*433d6423SLionel Sambuc 		exit(1);
158*433d6423SLionel Sambuc 	}
159*433d6423SLionel Sambuc }
160*433d6423SLionel Sambuc 
161*433d6423SLionel Sambuc void
usage(void)162*433d6423SLionel Sambuc usage(void)
163*433d6423SLionel Sambuc {
164*433d6423SLionel Sambuc 	if (!quiet) printf("Usage: readclock [-nqwW2]\n");
165*433d6423SLionel Sambuc 	exit(1);
166*433d6423SLionel Sambuc }
167