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