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