source: mainline/uspace/app/date/date.c@ f4ebaf3c

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f4ebaf3c was f4ebaf3c, checked in by Maurizio Lombardi <m.lombardi85@…>, 14 years ago

date: Let the user set current date/time

  • Property mode set to 100644
File size: 6.1 KB
Line 
1/*
2 * Copyright (c) 2012 Maurizio Lombardi
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29
30#include <stdio.h>
31#include <device/clock_dev.h>
32#include <errno.h>
33#include <loc.h>
34#include <time.h>
35#include <malloc.h>
36#include <ipc/clock_ctl.h>
37#include <getopt.h>
38#include <ctype.h>
39
40#define NAME "date"
41
42static int read_date_from_arg(char *wdate, struct tm *t);
43static int read_time_from_arg(char *wdate, struct tm *t);
44static int read_num_from_str(char *str, size_t len, int *n);
45static void usage(void);
46
47int
48main(int argc, char **argv)
49{
50 int rc, c;
51 category_id_t cat_id;
52 size_t svc_cnt;
53 service_id_t *svc_ids = NULL;
54 service_id_t svc_id;
55 char *svc_name = NULL;
56 bool read_only = true;
57 char *wdate = NULL;
58 char *wtime = NULL;
59 sysarg_t battery_ok;
60 struct tm t;
61
62 while ((c = getopt(argc, argv, "d:t:")) != -1) {
63 switch (c) {
64 case 'd':
65 wdate = (char *)optarg;
66 read_only = false;
67 break;
68 case 't':
69 wtime = (char *)optarg;
70 read_only = false;
71 break;
72 case '?':
73 usage();
74 return 1;
75 }
76 }
77
78 /* Get the id of the clock category */
79 rc = loc_category_get_id("clock", &cat_id, IPC_FLAG_BLOCKING);
80 if (rc != EOK) {
81 printf(NAME ": Cannot get clock category id\n");
82 goto exit;
83 }
84
85 /* Get the list of available services in the clock category */
86 rc = loc_category_get_svcs(cat_id, &svc_ids, &svc_cnt);
87 if (rc != EOK) {
88 printf(NAME ": Cannot get the list of services in category \
89 clock\n");
90 goto exit;
91 }
92
93 /* Check if the are available services in the clock category */
94 if (svc_cnt == 0) {
95 printf(NAME ": No available service found in \
96 the clock category\n");
97 goto exit;
98 }
99
100 /* Get the name of the clock service */
101 rc = loc_service_get_name(svc_ids[0], &svc_name);
102 if (rc != EOK) {
103 printf(NAME ": Cannot get the name of the service\n");
104 goto exit;
105 }
106
107 /* Get the service id for the device */
108 rc = loc_service_get_id(svc_name, &svc_id, 0);
109 if (rc != EOK) {
110 printf(NAME ": Cannot get the service id for device %s",
111 svc_name);
112 goto exit;
113 }
114
115 /* Connect to the device */
116 async_sess_t *sess = loc_service_connect(EXCHANGE_SERIALIZE,
117 svc_id, 0);
118 if (!sess) {
119 printf(NAME ": Cannot connect to the device\n");
120 goto exit;
121 }
122
123 /* Check the battery status (if present) */
124 async_exch_t *exch = async_exchange_begin(sess);
125 rc = async_req_0_1(exch, CLOCK_GET_BATTERY_STATUS, &battery_ok);
126 async_exchange_end(exch);
127
128 if (rc == EOK && !battery_ok)
129 printf(NAME ": Warning! RTC battery dead\n");
130
131 /* Read the current date/time */
132 rc = clock_dev_time_get(sess, &t);
133 if (rc != EOK) {
134 printf(NAME ": Cannot read the current time\n");
135 goto exit;
136 }
137
138 if (read_only) {
139 /* Print the current time and exit */
140 printf("%02d/%02d/%d ", t.tm_mday,
141 t.tm_mon + 1, 1900 + t.tm_year);
142 printf("%02d:%02d:%02d\n", t.tm_hour, t.tm_min, t.tm_sec);
143 } else {
144 if (wdate) {
145 rc = read_date_from_arg(wdate, &t);
146 if (rc != EOK) {
147 printf(NAME ": error, date format not "
148 "recognized\n");
149 usage();
150 goto exit;
151 }
152 }
153 if (wtime) {
154 rc = read_time_from_arg(wtime, &t);
155 if (rc != EOK) {
156 printf(NAME ": error, time format not "
157 "recognized\n");
158 usage();
159 goto exit;
160 }
161 }
162
163 rc = clock_dev_time_set(sess, &t);
164 if (rc != EOK) {
165 printf(NAME ": error, Unable to set date/time\n");
166 goto exit;
167 }
168 }
169
170exit:
171 free(svc_name);
172 free(svc_ids);
173 return rc;
174}
175
176static int
177read_date_from_arg(char *wdate, struct tm *t)
178{
179 int rc;
180
181 if (str_size(wdate) != 10) /* DD/MM/YYYY */
182 return EINVAL;
183
184 if (wdate[2] != '/' ||
185 wdate[5] != '/') {
186 return EINVAL;
187 }
188
189 rc = read_num_from_str(&wdate[0], 2, &t->tm_mday);
190 if (rc != EOK)
191 return rc;
192
193 rc = read_num_from_str(&wdate[3], 2, &t->tm_mon);
194 if (rc != EOK)
195 return rc;
196 t->tm_mon--;
197
198 rc = read_num_from_str(&wdate[6], 4, &t->tm_year);
199 t->tm_year -= 1900;
200 return rc;
201}
202
203static int
204read_time_from_arg(char *wtime, struct tm *t)
205{
206 int rc;
207 size_t len = str_size(wtime);
208 bool sec_present = len > 5;
209
210 if (len > 8 || len < 5) /* HH:MM[:SS] */
211 return EINVAL;
212
213 if (sec_present && wtime[5] != ':')
214 return EINVAL;
215
216 if (wtime[2] != ':')
217 return EINVAL;
218
219 rc = read_num_from_str(&wtime[0], 2, &t->tm_hour);
220 if (rc != EOK)
221 return rc;
222
223 rc = read_num_from_str(&wtime[3], 2, &t->tm_min);
224 if (rc != EOK)
225 return rc;
226
227 if (sec_present)
228 rc = read_num_from_str(&wtime[6], 2, &t->tm_sec);
229 else
230 t->tm_sec = 0;
231
232 return rc;
233}
234
235static int
236read_num_from_str(char *str, size_t len, int *n)
237{
238 size_t i;
239
240 *n = 0;
241
242 for (i = 0; i < len; ++i, ++str) {
243 if (!isdigit(*str))
244 return EINVAL;
245 *n *= 10;
246 *n += *str - '0';
247 }
248
249 return EOK;
250}
251
252static void
253usage(void)
254{
255 printf("Usage: date [-d DD/MM/YYYY] [-t HH:MM[:SS]]\n");
256 printf(" -d Change the current date\n");
257 printf(" -t Change the current time\n");
258}
259
Note: See TracBrowser for help on using the repository browser.