1/* See LICENSE file for copyright and license details. */
2
3
4#include <sys/ioctl.h>
5#include <sys/stat.h>
6#include <sys/time.h>
7#include <sys/types.h>
8
9#include <fcntl.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <time.h>
14#include <unistd.h>
15
16#include "rtc.h"
17#include "util.h"
18
19static void
20readrtctm(struct tm *tm, int fd)
21{
22 struct rtc_time rt;
23
24 memset(&rt, 0, sizeof(rt));
25 if (ioctl(fd, (int)RTC_RD_TIME, &rt) < 0)
26 eprintf("RTC_RD_TIME:");
27 tm->tm_sec = rt.tm_sec;
28 tm->tm_min = rt.tm_min;
29 tm->tm_hour = rt.tm_hour;
30 tm->tm_mday = rt.tm_mday;
31 tm->tm_mon = rt.tm_mon;
32 tm->tm_year = rt.tm_year;
33 tm->tm_wday = rt.tm_wday;
34 tm->tm_yday = rt.tm_yday;
35 tm->tm_isdst = rt.tm_isdst;
36}
37
38static void
39writertctm(struct tm *tm, int fd)
40{
41 struct rtc_time rt;
42
43 rt.tm_sec = tm->tm_sec;
44 rt.tm_min = tm->tm_min;
45 rt.tm_hour = tm->tm_hour;
46 rt.tm_mday = tm->tm_mday;
47 rt.tm_mon = tm->tm_mon;
48 rt.tm_year = tm->tm_year;
49 rt.tm_wday = tm->tm_wday;
50 rt.tm_yday = tm->tm_yday;
51 rt.tm_isdst = tm->tm_isdst;
52 if (ioctl(fd, (int)RTC_SET_TIME, &rt) < 0)
53 eprintf("RTC_SET_TIME:");
54}
55
56static void
57show(char *dev)
58{
59 struct tm tm;
60 time_t t;
61 int fd;
62
63 fd = open(dev, O_RDONLY);
64 if (fd < 0)
65 eprintf("open %s:", dev);
66 readrtctm(&tm, fd);
67 t = mktime(&tm);
68 printf("%s", asctime(localtime(&t)));
69 close(fd);
70}
71
72static void
73hctosys(char *dev)
74{
75 struct timeval tv;
76 struct tm tm;
77 int r;
78 int fd;
79
80 fd = open(dev, O_RDONLY);
81 if (fd < 0)
82 eprintf("open %s:", dev);
83 readrtctm(&tm, fd);
84 tv.tv_sec = mktime(&tm);
85 tv.tv_usec = 0;
86 r = settimeofday(&tv, NULL);
87 if (r < 0)
88 eprintf("settimeofday:");
89 close(fd);
90}
91
92static void
93systohc(char *dev)
94{
95 struct timeval tv;
96 struct tm *tm;
97 time_t t;
98 int fd;
99
100 fd = open(dev, O_WRONLY);
101 if (fd < 0)
102 eprintf("open %s:", dev);
103 gettimeofday(&tv, NULL);
104 t = tv.tv_sec;
105 tm = gmtime(&t);
106 weprintf("warning: assuming UTC for systohc\n");
107 writertctm(tm, fd);
108 close(fd);
109}
110
111static void
112usage(void)
113{
114 eprintf("usage: %s [-rsw] [-u] [dev]\n", argv0);
115}
116
117// ?man hwclock: query or set the hardware clock
118// ?man arguments: dev
119// ?man view or adjust the hardware real time clock
120int
121main(int argc, char *argv[])
122{
123 char *dev = "/dev/rtc";
124 int rflag = 0;
125 int sflag = 0;
126 int wflag = 0;
127
128 ARGBEGIN {
129 // ?man -r: operate recursively
130 case 'r':
131 rflag = 1;
132 break;
133 // ?man -s: silent mode or print summary
134 case 's':
135 sflag = 1;
136 break;
137 // ?man -w: wait for completion
138 case 'w':
139 wflag = 1;
140 break;
141 // ?man -u: unbuffered output
142 case 'u':
143 break;
144 default:
145 usage();
146 } ARGEND;
147
148 if (argc > 1)
149 usage();
150 else if (argc == 1)
151 dev = argv[0];
152
153 if ((rflag ^ sflag ^ wflag) == 0)
154 eprintf("missing or incompatible function\n");
155
156 /* Only UTC support at the moment */
157 setenv("TZ", "UTC0", 1);
158 tzset();
159
160 if (rflag == 1)
161 show(dev);
162 else if (sflag == 1)
163 hctosys(dev);
164 else if (wflag == 1)
165 systohc(dev);
166
167 return 0;
168}