1 /*
2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $Id: time.c,v 1.12 2005/06/01 19:02:38 roland Exp $
30 */
31
32 #include "defs.h"
33
34 #ifdef LINUX
35 #include <linux/version.h>
36 #ifdef HAVE_ANDROID_OS
37 #include <linux/timex.h>
38 #else
39 #include <sys/timex.h>
40 #endif
41 #include <linux/ioctl.h>
42 #include <linux/rtc.h>
43 #endif /* LINUX */
44
45 void
printtv(tcp,addr)46 printtv(tcp, addr)
47 struct tcb *tcp;
48 long addr;
49 {
50 struct timeval tv;
51
52 if (addr == 0)
53 tprintf("NULL");
54 else if (!verbose(tcp))
55 tprintf("%#lx", addr);
56 else if (umove(tcp, addr, &tv) < 0)
57 tprintf("{...}");
58 else
59 tprintf("{%lu, %lu}", (long) tv.tv_sec, (long) tv.tv_usec);
60 }
61
62 #ifdef ALPHA
63 struct timeval32
64 {
65 unsigned tv_sec;
66 unsigned tv_usec;
67 };
68
69 void
printtv32(tcp,addr)70 printtv32(tcp, addr)
71 struct tcb *tcp;
72 long addr;
73 {
74 struct timeval32 tv;
75
76 if (addr == 0)
77 tprintf("NULL");
78 else if (!verbose(tcp))
79 tprintf("%#lx", addr);
80 else if (umove(tcp, addr, &tv) < 0)
81 tprintf("{...}");
82 else
83 tprintf("{%u, %u}", tv.tv_sec, tv.tv_usec);
84 }
85 #endif
86
87
88 int
sys_time(tcp)89 sys_time(tcp)
90 struct tcb *tcp;
91 {
92 if (exiting(tcp)) {
93 #ifndef SVR4
94 printnum(tcp, tcp->u_arg[0], "%ld");
95 #endif /* SVR4 */
96 }
97 return 0;
98 }
99
100 int
sys_stime(tcp)101 sys_stime(tcp)
102 struct tcb *tcp;
103 {
104 if (exiting(tcp)) {
105 printnum(tcp, tcp->u_arg[0], "%ld");
106 }
107 return 0;
108 }
109
110 int
sys_gettimeofday(tcp)111 sys_gettimeofday(tcp)
112 struct tcb *tcp;
113 {
114 if (exiting(tcp)) {
115 if (syserror(tcp)) {
116 tprintf("%#lx, %#lx",
117 tcp->u_arg[0], tcp->u_arg[1]);
118 return 0;
119 }
120 printtv(tcp, tcp->u_arg[0]);
121 #ifndef SVR4
122 tprintf(", ");
123 printtv(tcp, tcp->u_arg[1]);
124 #endif /* !SVR4 */
125 }
126 return 0;
127 }
128
129
130 #ifdef ALPHA
131 int
sys_osf_gettimeofday(tcp)132 sys_osf_gettimeofday(tcp)
133 struct tcb *tcp;
134 {
135 if (exiting(tcp)) {
136 if (syserror(tcp)) {
137 tprintf("%#lx, %#lx",
138 tcp->u_arg[0], tcp->u_arg[1]);
139 return 0;
140 }
141 printtv32(tcp, tcp->u_arg[0]);
142 #ifndef SVR4
143 tprintf(", ");
144 printtv32(tcp, tcp->u_arg[1]);
145 #endif /* !SVR4 */
146 }
147 return 0;
148 }
149 #endif
150
151 int
sys_settimeofday(tcp)152 sys_settimeofday(tcp)
153 struct tcb *tcp;
154 {
155 if (entering(tcp)) {
156 printtv(tcp, tcp->u_arg[0]);
157 #ifndef SVR4
158 tprintf(", ");
159 printtv(tcp, tcp->u_arg[1]);
160 #endif /* !SVR4 */
161 }
162 return 0;
163 }
164
165 #ifdef ALPHA
166 int
sys_osf_settimeofday(tcp)167 sys_osf_settimeofday(tcp)
168 struct tcb *tcp;
169 {
170 if (entering(tcp)) {
171 printtv32(tcp, tcp->u_arg[0]);
172 #ifndef SVR4
173 tprintf(", ");
174 printtv32(tcp, tcp->u_arg[1]);
175 #endif /* !SVR4 */
176 }
177 return 0;
178 }
179 #endif
180
181 int
sys_adjtime(tcp)182 sys_adjtime(tcp)
183 struct tcb *tcp;
184 {
185 if (entering(tcp)) {
186 printtv(tcp, tcp->u_arg[0]);
187 tprintf(", ");
188 } else {
189 if (syserror(tcp))
190 tprintf("%#lx", tcp->u_arg[1]);
191 else
192 printtv(tcp, tcp->u_arg[1]);
193 }
194 return 0;
195 }
196
197 static const struct xlat which[] = {
198 { ITIMER_REAL, "ITIMER_REAL" },
199 { ITIMER_VIRTUAL,"ITIMER_VIRTUAL"},
200 { ITIMER_PROF, "ITIMER_PROF" },
201 { 0, NULL },
202 };
203
204 static void
printitv(tcp,addr)205 printitv(tcp, addr)
206 struct tcb *tcp;
207 long addr;
208 {
209 struct itimerval itv;
210
211 if (addr == 0)
212 tprintf("NULL");
213 else if (!verbose(tcp))
214 tprintf("%#lx", addr);
215 else if (umove(tcp, addr, &itv) < 0)
216 tprintf("{...}");
217 else {
218 tprintf("{it_interval={%lu, %lu}, it_value={%lu, %lu}}",
219 (long) itv.it_interval.tv_sec, (long) itv.it_interval.tv_usec,
220 (long) itv.it_value.tv_sec, (long) itv.it_value.tv_usec);
221 }
222 }
223
224
225 #ifdef ALPHA
226 static void
printitv32(tcp,addr)227 printitv32(tcp, addr)
228 struct tcb *tcp;
229 long addr;
230 {
231 struct itimerval32
232 {
233 struct timeval32 it_interval;
234 struct timeval32 it_value;
235 } itv;
236
237 if (addr == 0)
238 tprintf("NULL");
239 else if (!verbose(tcp))
240 tprintf("%#lx", addr);
241 else if (umove(tcp, addr, &itv) < 0)
242 tprintf("{...}");
243 else {
244 tprintf("{it_interval={%u, %u}, it_value={%u, %u}}",
245 itv.it_interval.tv_sec, itv.it_interval.tv_usec,
246 itv.it_value.tv_sec, itv.it_value.tv_usec);
247 }
248 }
249 #endif
250
251 int
sys_getitimer(tcp)252 sys_getitimer(tcp)
253 struct tcb *tcp;
254 {
255 if (entering(tcp)) {
256 printxval(which, tcp->u_arg[0], "ITIMER_???");
257 tprintf(", ");
258 } else {
259 if (syserror(tcp))
260 tprintf("%#lx", tcp->u_arg[1]);
261 else
262 printitv(tcp, tcp->u_arg[1]);
263 }
264 return 0;
265 }
266
267
268 #ifdef ALPHA
269 int
sys_osf_getitimer(tcp)270 sys_osf_getitimer(tcp)
271 struct tcb *tcp;
272 {
273 if (entering(tcp)) {
274 printxval(which, tcp->u_arg[0], "ITIMER_???");
275 tprintf(", ");
276 } else {
277 if (syserror(tcp))
278 tprintf("%#lx", tcp->u_arg[1]);
279 else
280 printitv32(tcp, tcp->u_arg[1]);
281 }
282 return 0;
283 }
284 #endif
285
286 int
sys_setitimer(tcp)287 sys_setitimer(tcp)
288 struct tcb *tcp;
289 {
290 if (entering(tcp)) {
291 printxval(which, tcp->u_arg[0], "ITIMER_???");
292 tprintf(", ");
293 printitv(tcp, tcp->u_arg[1]);
294 tprintf(", ");
295 } else {
296 if (syserror(tcp))
297 tprintf("%#lx", tcp->u_arg[2]);
298 else
299 printitv(tcp, tcp->u_arg[2]);
300 }
301 return 0;
302 }
303
304 #ifdef ALPHA
305 int
sys_osf_setitimer(tcp)306 sys_osf_setitimer(tcp)
307 struct tcb *tcp;
308 {
309 if (entering(tcp)) {
310 printxval(which, tcp->u_arg[0], "ITIMER_???");
311 tprintf(", ");
312 printitv32(tcp, tcp->u_arg[1]);
313 tprintf(", ");
314 } else {
315 if (syserror(tcp))
316 tprintf("%#lx", tcp->u_arg[2]);
317 else
318 printitv32(tcp, tcp->u_arg[2]);
319 }
320 return 0;
321 }
322 #endif
323
324 #ifdef LINUX
325
326 int
sys_adjtimex(tcp)327 sys_adjtimex(tcp)
328 struct tcb *tcp;
329 {
330 struct timex txc;
331
332 if (exiting(tcp)) {
333 if (tcp->u_arg[0] == 0)
334 tprintf("NULL");
335 else if (syserror(tcp) || !verbose(tcp))
336 tprintf("%#lx", tcp->u_arg[0]);
337 else if (umove(tcp, tcp->u_arg[0], &txc) < 0)
338 tprintf("{...}");
339 else {
340 #if LINUX_VERSION_CODE < 66332
341 tprintf("{mode=%d, offset=%ld, frequency=%ld, ",
342 txc.mode, txc.offset, txc.frequency);
343 tprintf("maxerror=%ld, esterror=%lu, status=%u, ",
344 txc.maxerror, txc.esterror, txc.status);
345 tprintf("time_constant=%ld, precision=%lu, ",
346 txc.time_constant, txc.precision);
347 tprintf("tolerance=%ld, time={%lu, %lu}}",
348 txc.tolerance, (long) txc.time.tv_sec,
349 (long) txc.time.tv_usec);
350 #else
351 tprintf("{modes=%d, offset=%ld, freq=%ld, ",
352 txc.modes, txc.offset, txc.freq);
353 tprintf("maxerror=%ld, esterror=%lu, status=%u, ",
354 txc.maxerror, txc.esterror, txc.status);
355 tprintf("constant=%ld, precision=%lu, ",
356 txc.constant, txc.precision);
357 tprintf("tolerance=%ld, time={%lu, %lu}}",
358 txc.tolerance, (long) txc.time.tv_sec,
359 (long) txc.time.tv_usec);
360 /* there's a bunch of other stuff, but it's not
361 * worth the time or the trouble to include */
362 #endif
363 }
364 }
365 return 0;
366 }
367
368 static const struct xlat clockflags[] = {
369 { TIMER_ABSTIME, "TIMER_ABSTIME" },
370 { 0, NULL }
371 };
372
373 static const struct xlat clocknames[] = {
374 #ifdef CLOCK_REALTIME
375 { CLOCK_REALTIME, "CLOCK_REALTIME" },
376 #endif
377 #ifdef CLOCK_MONOTONIC
378 { CLOCK_MONOTONIC, "CLOCK_MONOTONIC" },
379 #endif
380 { 0, NULL }
381 };
382
383 int
sys_clock_settime(tcp)384 sys_clock_settime(tcp)
385 struct tcb *tcp;
386 {
387 if (entering(tcp)) {
388 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
389 tprintf(", ");
390 printtv(tcp, tcp->u_arg[1]);
391 }
392 return 0;
393 }
394
395 int
sys_clock_gettime(tcp)396 sys_clock_gettime(tcp)
397 struct tcb *tcp;
398 {
399 if (entering(tcp)) {
400 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
401 tprintf(", ");
402 } else {
403 if (syserror(tcp))
404 tprintf("%#lx", tcp->u_arg[1]);
405 else
406 printtv(tcp, tcp->u_arg[1]);
407 }
408 return 0;
409 }
410
411 int
sys_clock_nanosleep(tcp)412 sys_clock_nanosleep(tcp)
413 struct tcb *tcp;
414 {
415 if (entering(tcp)) {
416 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
417 tprintf(", ");
418 printflags(clockflags, tcp->u_arg[1], "TIMER_???");
419 tprintf(", ");
420 printtv(tcp, tcp->u_arg[2]);
421 tprintf(", ");
422 } else {
423 if (syserror(tcp))
424 tprintf("%#lx", tcp->u_arg[3]);
425 else
426 printtv(tcp, tcp->u_arg[3]);
427 }
428 return 0;
429 }
430
431 #ifndef SIGEV_THREAD_ID
432 # define SIGEV_THREAD_ID 4
433 #endif
434 static const struct xlat sigev_value[] = {
435 { SIGEV_SIGNAL+1, "SIGEV_SIGNAL" },
436 { SIGEV_NONE+1, "SIGEV_NONE" },
437 { SIGEV_THREAD+1, "SIGEV_THREAD" },
438 { SIGEV_THREAD_ID+1, "SIGEV_THREAD_ID" },
439 { 0, NULL }
440 };
441
442 void
printsigevent(tcp,arg)443 printsigevent(tcp, arg)
444 struct tcb *tcp;
445 long arg;
446 {
447 struct sigevent sev;
448 if (umove (tcp, arg, &sev) < 0)
449 tprintf("{...}");
450 else {
451 tprintf("{%p, ", sev.sigev_value.sival_ptr);
452 if (sev.sigev_notify == SIGEV_SIGNAL)
453 tprintf("%s, ", signame(sev.sigev_signo));
454 else
455 tprintf("%u, ", sev.sigev_signo);
456 printxval(sigev_value, sev.sigev_notify+1, "SIGEV_???");
457 tprintf(", ");
458 if (sev.sigev_notify == SIGEV_THREAD_ID)
459 /* _pad[0] is the _tid field which might not be
460 present in the userlevel definition of the
461 struct. */
462 tprintf("{%d}", sev._sigev_un._pad[0]);
463 else if (sev.sigev_notify == SIGEV_THREAD)
464 tprintf("{%p, %p}", sev.sigev_notify_function,
465 sev.sigev_notify_attributes);
466 else
467 tprintf("{...}");
468 tprintf("}");
469 }
470 }
471
472 int
sys_timer_create(tcp)473 sys_timer_create(tcp)
474 struct tcb *tcp;
475 {
476 if (entering(tcp)) {
477 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
478 tprintf(", ");
479 printsigevent(tcp, tcp->u_arg[1]);
480 tprintf(", ");
481 } else {
482 if (syserror(tcp))
483 tprintf("%#lx", tcp->u_arg[2]);
484 else {
485 void *p;
486 umove(tcp, tcp->u_arg[2], &p);
487 tprintf("{%p}", p);
488 }
489 }
490 return 0;
491 }
492
493 int
sys_timer_settime(tcp)494 sys_timer_settime(tcp)
495 struct tcb *tcp;
496 {
497 if (entering(tcp)) {
498 tprintf("%#lx, ", tcp->u_arg[0]);
499 printflags(clockflags, tcp->u_arg[1], "TIMER_???");
500 tprintf(", ");
501 printitv(tcp, tcp->u_arg[2]);
502 tprintf(", ");
503 } else {
504 if (syserror(tcp))
505 tprintf("%#lx", tcp->u_arg[3]);
506 else
507 printitv(tcp, tcp->u_arg[3]);
508 }
509 return 0;
510 }
511
512 int
sys_timer_gettime(tcp)513 sys_timer_gettime(tcp)
514 struct tcb *tcp;
515 {
516 if (entering(tcp)) {
517 tprintf("%#lx, ", tcp->u_arg[0]);
518 } else {
519 if (syserror(tcp))
520 tprintf("%#lx", tcp->u_arg[1]);
521 else
522 printitv(tcp, tcp->u_arg[1]);
523 }
524 return 0;
525 }
526
527 static void
print_rtc(tcp,rt)528 print_rtc(tcp, rt)
529 struct tcb *tcp;
530 const struct rtc_time *rt;
531 {
532 tprintf("{tm_sec=%d, tm_min=%d, tm_hour=%d, "
533 "tm_mday=%d, tm_mon=%d, tm_year=%d, ",
534 rt->tm_sec, rt->tm_min, rt->tm_hour,
535 rt->tm_mday, rt->tm_mon, rt->tm_year);
536 if (!abbrev(tcp))
537 tprintf("tm_wday=%d, tm_yday=%d, tm_isdst=%d}",
538 rt->tm_wday, rt->tm_yday, rt->tm_isdst);
539 else
540 tprintf("...}");
541 }
542
543 int
rtc_ioctl(tcp,code,arg)544 rtc_ioctl(tcp, code, arg)
545 struct tcb *tcp;
546 long code;
547 long arg;
548 {
549 switch (code) {
550 case RTC_ALM_SET:
551 case RTC_SET_TIME:
552 if (entering(tcp)) {
553 struct rtc_time rt;
554 if (umove(tcp, arg, &rt) < 0)
555 tprintf(", %#lx", arg);
556 else {
557 tprintf(", ");
558 print_rtc(tcp, &rt);
559 }
560 }
561 break;
562 case RTC_ALM_READ:
563 case RTC_RD_TIME:
564 if (exiting(tcp)) {
565 struct rtc_time rt;
566 if (syserror(tcp) || umove(tcp, arg, &rt) < 0)
567 tprintf(", %#lx", arg);
568 else {
569 tprintf(", ");
570 print_rtc(tcp, &rt);
571 }
572 }
573 break;
574 case RTC_IRQP_SET:
575 case RTC_EPOCH_SET:
576 if (entering(tcp))
577 tprintf(", %lu", arg);
578 break;
579 case RTC_IRQP_READ:
580 case RTC_EPOCH_READ:
581 if (exiting(tcp))
582 tprintf(", %lu", arg);
583 break;
584 case RTC_WKALM_SET:
585 if (entering(tcp)) {
586 struct rtc_wkalrm wk;
587 if (umove(tcp, arg, &wk) < 0)
588 tprintf(", %#lx", arg);
589 else {
590 tprintf(", {enabled=%d, pending=%d, ",
591 wk.enabled, wk.pending);
592 print_rtc(tcp, &wk.time);
593 tprintf("}");
594 }
595 }
596 break;
597 case RTC_WKALM_RD:
598 if (exiting(tcp)) {
599 struct rtc_wkalrm wk;
600 if (syserror(tcp) || umove(tcp, arg, &wk) < 0)
601 tprintf(", %#lx", arg);
602 else {
603 tprintf(", {enabled=%d, pending=%d, ",
604 wk.enabled, wk.pending);
605 print_rtc(tcp, &wk.time);
606 tprintf("}");
607 }
608 }
609 break;
610 default:
611 if (entering(tcp))
612 tprintf(", %#lx", arg);
613 break;
614 }
615 return 1;
616 }
617 #endif /* LINUX */
618