source: mainline/uspace/app/date/date.c@ 289fa65

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

date: remove dead code

  • Property mode set to 100644
File size: 7.7 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 <getopt.h>
37#include <ctype.h>
38
39#define NAME "date"
40
41static int read_date_from_arg(char *wdate, struct tm *t);
42static int read_time_from_arg(char *wdate, struct tm *t);
43static int read_num_from_str(char *str, size_t len, int *n);
44static int tm_sanity_check(struct tm *t);
45static bool is_leap_year(int year);
46
47static void usage(void);
48
49static int days_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
50
51int
52main(int argc, char **argv)
53{
54 int rc, c;
55 category_id_t cat_id;
56 size_t svc_cnt;
57 service_id_t *svc_ids = NULL;
58 service_id_t svc_id;
59 char *svc_name = NULL;
60 bool read_only = true;
61 char *wdate = NULL;
62 char *wtime = NULL;
63 struct tm t;
64 int n_args = argc;
65
66 while ((c = getopt(argc, argv, "hd:t:")) != -1) {
67 switch (c) {
68 case 'h':
69 usage();
70 return 0;
71 case 'd':
72 if (wdate) {
73 usage();
74 return 1;
75 }
76 wdate = (char *)optarg;
77 read_only = false;
78 n_args -= 2;
79 break;
80 case 't':
81 if (wtime) {
82 usage();
83 return 1;
84 }
85 wtime = (char *)optarg;
86 read_only = false;
87 n_args -= 2;
88 break;
89 case '?':
90 usage();
91 return 1;
92 }
93 }
94
95 if (n_args != 1) {
96 printf(NAME ": Unrecognized parameter\n");
97 usage();
98 return 1;
99 }
100
101 /* Get the id of the clock category */
102 rc = loc_category_get_id("clock", &cat_id, IPC_FLAG_BLOCKING);
103 if (rc != EOK) {
104 printf(NAME ": Cannot get clock category id\n");
105 goto exit;
106 }
107
108 /* Get the list of available services in the clock category */
109 rc = loc_category_get_svcs(cat_id, &svc_ids, &svc_cnt);
110 if (rc != EOK) {
111 printf(NAME ": Cannot get the list of services in the clock "
112 "category\n");
113 goto exit;
114 }
115
116 /* Check if there are available services in the clock category */
117 if (svc_cnt == 0) {
118 printf(NAME ": No available service found in "
119 "the clock category\n");
120 goto exit;
121 }
122
123 /* Get the name of the clock service */
124 rc = loc_service_get_name(svc_ids[0], &svc_name);
125 if (rc != EOK) {
126 printf(NAME ": Cannot get the name of the service\n");
127 goto exit;
128 }
129
130 /* Get the service id for the device */
131 rc = loc_service_get_id(svc_name, &svc_id, 0);
132 if (rc != EOK) {
133 printf(NAME ": Cannot get the service id for device %s",
134 svc_name);
135 goto exit;
136 }
137
138 /* Connect to the device */
139 async_sess_t *sess = loc_service_connect(EXCHANGE_SERIALIZE,
140 svc_id, 0);
141 if (!sess) {
142 printf(NAME ": Cannot connect to the device\n");
143 goto exit;
144 }
145
146 /* Read the current date/time */
147 rc = clock_dev_time_get(sess, &t);
148 if (rc != EOK) {
149 printf(NAME ": Cannot read the current time\n");
150 goto exit;
151 }
152
153 if (read_only) {
154 /* Print the current time and exit */
155 printf("%02d/%02d/%d ", t.tm_mday,
156 t.tm_mon + 1, 1900 + t.tm_year);
157 printf("%02d:%02d:%02d\n", t.tm_hour, t.tm_min, t.tm_sec);
158 } else {
159 if (wdate) {
160 rc = read_date_from_arg(wdate, &t);
161 if (rc != EOK) {
162 printf(NAME ": error, date format not "
163 "recognized\n");
164 usage();
165 goto exit;
166 }
167 }
168 if (wtime) {
169 rc = read_time_from_arg(wtime, &t);
170 if (rc != EOK) {
171 printf(NAME ": error, time format not "
172 "recognized\n");
173 usage();
174 goto exit;
175 }
176 }
177
178 rc = tm_sanity_check(&t);
179 if (rc != EOK) {
180 printf(NAME ": error, invalid date/time\n");
181 goto exit;
182 }
183
184 rc = clock_dev_time_set(sess, &t);
185 if (rc != EOK) {
186 printf(NAME ": error, Unable to set date/time\n");
187 goto exit;
188 }
189 }
190
191exit:
192 free(svc_name);
193 free(svc_ids);
194 return rc;
195}
196
197/** Read the day, month and year from a string
198 * with the following format: DD/MM/YYYY
199 */
200static int
201read_date_from_arg(char *wdate, struct tm *t)
202{
203 int rc;
204
205 if (str_size(wdate) != 10) /* str_size("DD/MM/YYYY") == 10 */
206 return EINVAL;
207
208 if (wdate[2] != '/' ||
209 wdate[5] != '/') {
210 return EINVAL;
211 }
212
213 rc = read_num_from_str(&wdate[0], 2, &t->tm_mday);
214 if (rc != EOK)
215 return rc;
216
217 rc = read_num_from_str(&wdate[3], 2, &t->tm_mon);
218 if (rc != EOK)
219 return rc;
220 t->tm_mon--;
221
222 rc = read_num_from_str(&wdate[6], 4, &t->tm_year);
223 t->tm_year -= 1900;
224 return rc;
225}
226
227/** Read the hours, minutes and seconds from a string
228 * with the following format: HH:MM:SS or HH:MM
229 */
230static int
231read_time_from_arg(char *wtime, struct tm *t)
232{
233 int rc;
234 size_t len = str_size(wtime);
235 bool sec_present = len == 8;
236
237 /* str_size("HH:MM") == 5 */
238 /* str_size("HH:MM:SS") == 8 */
239 if (len != 8 && len != 5)
240 return EINVAL;
241
242 if (sec_present && wtime[5] != ':')
243 return EINVAL;
244
245 if (wtime[2] != ':')
246 return EINVAL;
247
248 rc = read_num_from_str(&wtime[0], 2, &t->tm_hour);
249 if (rc != EOK)
250 return rc;
251
252 rc = read_num_from_str(&wtime[3], 2, &t->tm_min);
253 if (rc != EOK)
254 return rc;
255
256 if (sec_present)
257 rc = read_num_from_str(&wtime[6], 2, &t->tm_sec);
258 else
259 t->tm_sec = 0;
260
261 return rc;
262}
263
264static int
265read_num_from_str(char *str, size_t len, int *n)
266{
267 size_t i;
268
269 *n = 0;
270
271 for (i = 0; i < len; ++i, ++str) {
272 if (!isdigit(*str))
273 return EINVAL;
274 *n *= 10;
275 *n += *str - '0';
276 }
277
278 return EOK;
279}
280
281/** Check if the tm structure contains valid values
282 *
283 * @param t The tm structure to check
284 *
285 * @return EOK on success or EINVAL
286 */
287static int
288tm_sanity_check(struct tm *t)
289{
290 int ndays;
291
292 if (t->tm_sec < 0 || t->tm_sec > 59)
293 return EINVAL;
294 else if (t->tm_min < 0 || t->tm_min > 59)
295 return EINVAL;
296 else if (t->tm_hour < 0 || t->tm_hour > 23)
297 return EINVAL;
298 else if (t->tm_mday < 1 || t->tm_mday > 31)
299 return EINVAL;
300 else if (t->tm_mon < 0 || t->tm_mon > 11)
301 return EINVAL;
302 else if (t->tm_year < 0 || t->tm_year > 199)
303 return EINVAL;
304
305 if (t->tm_mon == 1/* FEB */ && is_leap_year(t->tm_year))
306 ndays = 29;
307 else
308 ndays = days_month[t->tm_mon];
309
310 if (t->tm_mday > ndays)
311 return EINVAL;
312
313 return EOK;
314}
315
316/** Check if a year is a leap year
317 *
318 * @param year The year to check
319 *
320 * @return true if it is a leap year, false otherwise
321 */
322static bool
323is_leap_year(int year)
324{
325 bool r = false;
326
327 if (year % 4 == 0) {
328 if (year % 100 == 0)
329 r = year % 400 == 0;
330 else
331 r = true;
332 }
333
334 return r;
335}
336
337static void
338usage(void)
339{
340 printf("Usage: date [-d DD/MM/YYYY] [-t HH:MM[:SS]]\n");
341 printf(" -d Change the current date\n");
342 printf(" -t Change the current time\n");
343 printf(" -h Display this information\n");
344}
345
Note: See TracBrowser for help on using the repository browser.