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 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 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 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 162 usage(void) 163 { 164 if (!quiet) printf("Usage: readclock [-nqwW2]\n"); 165 exit(1); 166 } 167