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#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
44#ifndef UTIME_NOW
45#define UTIME_NOW ((1l << 30) - 1l)
46#endif
47#ifndef UTIME_OMIT
48#define UTIME_OMIT ((1l << 30) - 2l)
49#endif
50#endif /* LINUX */
51
52struct timeval32
53{
54	u_int32_t tv_sec, tv_usec;
55};
56
57static void
58tprint_timeval32(struct tcb *tcp, const struct timeval32 *tv)
59{
60	tprintf("{%u, %u}", tv->tv_sec, tv->tv_usec);
61}
62
63static void
64tprint_timeval(struct tcb *tcp, const struct timeval *tv)
65{
66	tprintf("{%lu, %lu}",
67		(unsigned long) tv->tv_sec, (unsigned long) tv->tv_usec);
68}
69
70void
71printtv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness, int special)
72{
73	if (addr == 0)
74		tprintf("NULL");
75	else if (!verbose(tcp))
76		tprintf("%#lx", addr);
77	else {
78		int rc;
79
80		if (bitness == BITNESS_32
81#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
82		    || personality_wordsize[current_personality] == 4
83#endif
84			)
85		{
86			struct timeval32 tv;
87
88			if ((rc = umove(tcp, addr, &tv)) >= 0) {
89				if (special && tv.tv_sec == 0 &&
90				    tv.tv_usec == UTIME_NOW)
91					tprintf("UTIME_NOW");
92				else if (special && tv.tv_sec == 0 &&
93					 tv.tv_usec == UTIME_OMIT)
94					tprintf("UTIME_OMIT");
95				else
96					tprint_timeval32(tcp, &tv);
97			}
98		} else {
99			struct timeval tv;
100
101			if ((rc = umove(tcp, addr, &tv)) >= 0) {
102				if (special && tv.tv_sec == 0 &&
103				    tv.tv_usec == UTIME_NOW)
104					tprintf("UTIME_NOW");
105				else if (special && tv.tv_sec == 0 &&
106					 tv.tv_usec == UTIME_OMIT)
107					tprintf("UTIME_OMIT");
108				else
109					tprint_timeval(tcp, &tv);
110			}
111		}
112		if (rc < 0)
113			tprintf("{...}");
114	}
115}
116
117void
118sprinttv(struct tcb *tcp, long addr, enum bitness_t bitness, char *buf)
119{
120	if (addr == 0)
121		strcpy(buf, "NULL");
122	else if (!verbose(tcp))
123		sprintf(buf, "%#lx", addr);
124	else {
125		int rc;
126
127		if (bitness == BITNESS_32
128#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
129		    || personality_wordsize[current_personality] == 4
130#endif
131			)
132		{
133			struct timeval32 tv;
134
135			if ((rc = umove(tcp, addr, &tv)) >= 0)
136				sprintf(buf, "{%u, %u}",
137					tv.tv_sec, tv.tv_usec);
138		} else {
139			struct timeval tv;
140
141			if ((rc = umove(tcp, addr, &tv)) >= 0)
142				sprintf(buf, "{%lu, %lu}",
143					(unsigned long) tv.tv_sec,
144					(unsigned long) tv.tv_usec);
145		}
146		if (rc < 0)
147			strcpy(buf, "{...}");
148	}
149}
150
151void print_timespec(struct tcb *tcp, long addr)
152{
153	if (addr == 0)
154		tprintf("NULL");
155	else if (!verbose(tcp))
156		tprintf("%#lx", addr);
157	else {
158		int rc;
159
160#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
161		if (personality_wordsize[current_personality] == 4) {
162			struct timeval32 tv;
163
164			if ((rc = umove(tcp, addr, &tv)) >= 0)
165				tprintf("{%u, %u}",
166					tv.tv_sec, tv.tv_usec);
167		} else
168#endif
169		{
170			struct timespec ts;
171
172			if ((rc = umove(tcp, addr, &ts)) >= 0)
173				tprintf("{%lu, %lu}",
174					(unsigned long) ts.tv_sec,
175					(unsigned long) ts.tv_nsec);
176		}
177		if (rc < 0)
178			tprintf("{...}");
179	}
180}
181
182void sprint_timespec(char *buf, struct tcb *tcp, long addr)
183{
184	if (addr == 0)
185		strcpy(buf, "NULL");
186	else if (!verbose(tcp))
187		sprintf(buf, "%#lx", addr);
188	else {
189		int rc;
190
191#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
192		if (personality_wordsize[current_personality] == 4) {
193			struct timeval32 tv;
194
195			if ((rc = umove(tcp, addr, &tv)) >= 0)
196				sprintf(buf, "{%u, %u}",
197					tv.tv_sec, tv.tv_usec);
198		} else
199#endif
200		{
201			struct timespec ts;
202
203			if ((rc = umove(tcp, addr, &ts)) >= 0)
204				sprintf(buf, "{%lu, %lu}",
205					(unsigned long) ts.tv_sec,
206					(unsigned long) ts.tv_nsec);
207		}
208		if (rc < 0)
209			strcpy(buf, "{...}");
210	}
211}
212
213int
214sys_time(tcp)
215struct tcb *tcp;
216{
217	if (exiting(tcp)) {
218#ifndef SVR4
219		printnum(tcp, tcp->u_arg[0], "%ld");
220#endif /* SVR4 */
221	}
222	return 0;
223}
224
225int
226sys_stime(tcp)
227struct tcb *tcp;
228{
229	if (exiting(tcp)) {
230		printnum(tcp, tcp->u_arg[0], "%ld");
231	}
232	return 0;
233}
234
235int
236sys_gettimeofday(tcp)
237struct tcb *tcp;
238{
239	if (exiting(tcp)) {
240		if (syserror(tcp)) {
241			tprintf("%#lx, %#lx",
242				tcp->u_arg[0], tcp->u_arg[1]);
243			return 0;
244		}
245		printtv(tcp, tcp->u_arg[0]);
246#ifndef SVR4
247		tprintf(", ");
248		printtv(tcp, tcp->u_arg[1]);
249#endif /* !SVR4 */
250	}
251	return 0;
252}
253
254
255#ifdef ALPHA
256int
257sys_osf_gettimeofday(tcp)
258struct tcb *tcp;
259{
260	if (exiting(tcp)) {
261		if (syserror(tcp)) {
262			tprintf("%#lx, %#lx", tcp->u_arg[0], tcp->u_arg[1]);
263			return 0;
264		}
265		printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32, 0);
266#ifndef SVR4
267		tprintf(", ");
268		printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32, 0);
269#endif /* !SVR4 */
270	}
271	return 0;
272}
273#endif
274
275int
276sys_settimeofday(tcp)
277struct tcb *tcp;
278{
279	if (entering(tcp)) {
280		printtv(tcp, tcp->u_arg[0]);
281#ifndef SVR4
282		tprintf(", ");
283		printtv(tcp, tcp->u_arg[1]);
284#endif /* !SVR4 */
285	}
286	return 0;
287}
288
289#ifdef ALPHA
290int
291sys_osf_settimeofday(tcp)
292struct tcb *tcp;
293{
294	if (entering(tcp)) {
295		printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32, 0);
296#ifndef SVR4
297		tprintf(", ");
298		printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32, 0);
299#endif /* !SVR4 */
300	}
301	return 0;
302}
303#endif
304
305int
306sys_adjtime(tcp)
307struct tcb *tcp;
308{
309	if (entering(tcp)) {
310		printtv(tcp, tcp->u_arg[0]);
311		tprintf(", ");
312	} else {
313		if (syserror(tcp))
314			tprintf("%#lx", tcp->u_arg[1]);
315		else
316			printtv(tcp, tcp->u_arg[1]);
317	}
318	return 0;
319}
320
321int
322sys_nanosleep(struct tcb *tcp)
323{
324	if (entering(tcp)) {
325		print_timespec(tcp, tcp->u_arg[0]);
326		tprintf(", ");
327	} else {
328		if (!tcp->u_arg[1] || is_restart_error(tcp))
329			print_timespec(tcp, tcp->u_arg[1]);
330		else
331			tprintf("%#lx", tcp->u_arg[1]);
332	}
333	return 0;
334}
335
336static const struct xlat which[] = {
337	{ ITIMER_REAL,	"ITIMER_REAL"	},
338	{ ITIMER_VIRTUAL,"ITIMER_VIRTUAL"},
339	{ ITIMER_PROF,	"ITIMER_PROF"	},
340	{ 0,		NULL		},
341};
342
343static void
344printitv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness)
345{
346	if (addr == 0)
347		tprintf("NULL");
348	else if (!verbose(tcp))
349		tprintf("%#lx", addr);
350	else {
351		int rc;
352
353		if (bitness == BITNESS_32
354#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
355		    || personality_wordsize[current_personality] == 4
356#endif
357			)
358		{
359			struct {
360				struct timeval32 it_interval, it_value;
361			} itv;
362
363			if ((rc = umove(tcp, addr, &itv)) >= 0) {
364				tprintf("{it_interval=");
365				tprint_timeval32(tcp, &itv.it_interval);
366				tprintf(", it_value=");
367				tprint_timeval32(tcp, &itv.it_value);
368				tprintf("}");
369			}
370		} else {
371			struct itimerval itv;
372
373			if ((rc = umove(tcp, addr, &itv)) >= 0)	{
374				tprintf("{it_interval=");
375				tprint_timeval(tcp, &itv.it_interval);
376				tprintf(", it_value=");
377				tprint_timeval(tcp, &itv.it_value);
378				tprintf("}");
379			}
380		}
381		if (rc < 0)
382			tprintf("{...}");
383	}
384}
385
386#define printitv(tcp, addr)	\
387	printitv_bitness((tcp), (addr), BITNESS_CURRENT)
388
389int
390sys_getitimer(tcp)
391struct tcb *tcp;
392{
393	if (entering(tcp)) {
394		printxval(which, tcp->u_arg[0], "ITIMER_???");
395		tprintf(", ");
396	} else {
397		if (syserror(tcp))
398			tprintf("%#lx", tcp->u_arg[1]);
399		else
400			printitv(tcp, tcp->u_arg[1]);
401	}
402	return 0;
403}
404
405
406#ifdef ALPHA
407int
408sys_osf_getitimer(tcp)
409struct tcb *tcp;
410{
411	if (entering(tcp)) {
412		printxval(which, tcp->u_arg[0], "ITIMER_???");
413		tprintf(", ");
414	} else {
415		if (syserror(tcp))
416			tprintf("%#lx", tcp->u_arg[1]);
417		else
418			printitv_bitness(tcp, tcp->u_arg[1], BITNESS_32);
419	}
420	return 0;
421}
422#endif
423
424int
425sys_setitimer(tcp)
426struct tcb *tcp;
427{
428	if (entering(tcp)) {
429		printxval(which, tcp->u_arg[0], "ITIMER_???");
430		tprintf(", ");
431		printitv(tcp, tcp->u_arg[1]);
432		tprintf(", ");
433	} else {
434		if (syserror(tcp))
435			tprintf("%#lx", tcp->u_arg[2]);
436		else
437			printitv(tcp, tcp->u_arg[2]);
438	}
439	return 0;
440}
441
442#ifdef ALPHA
443int
444sys_osf_setitimer(tcp)
445struct tcb *tcp;
446{
447	if (entering(tcp)) {
448		printxval(which, tcp->u_arg[0], "ITIMER_???");
449		tprintf(", ");
450		printitv_bitness(tcp, tcp->u_arg[1], BITNESS_32);
451		tprintf(", ");
452	} else {
453		if (syserror(tcp))
454			tprintf("%#lx", tcp->u_arg[2]);
455		else
456			printitv_bitness(tcp, tcp->u_arg[2], BITNESS_32);
457	}
458	return 0;
459}
460#endif
461
462#ifdef LINUX
463
464static const struct xlat adjtimex_modes[] = {
465  { 0, "0" },
466#ifdef ADJ_OFFSET
467  { ADJ_OFFSET, "ADJ_OFFSET" },
468#endif
469#ifdef ADJ_FREQUENCY
470  { ADJ_FREQUENCY, "ADJ_FREQUENCY" },
471#endif
472#ifdef ADJ_MAXERROR
473  { ADJ_MAXERROR, "ADJ_MAXERROR" },
474#endif
475#ifdef ADJ_ESTERROR
476  { ADJ_ESTERROR, "ADJ_ESTERROR" },
477#endif
478#ifdef ADJ_STATUS
479  { ADJ_STATUS, "ADJ_STATUS" },
480#endif
481#ifdef ADJ_TIMECONST
482  { ADJ_TIMECONST, "ADJ_TIMECONST" },
483#endif
484#ifdef ADJ_TICK
485  { ADJ_TICK, "ADJ_TICK" },
486#endif
487#ifdef ADJ_OFFSET_SINGLESHOT
488  { ADJ_OFFSET_SINGLESHOT, "ADJ_OFFSET_SINGLESHOT" },
489#endif
490  { 0,             NULL }
491};
492
493static const struct xlat adjtimex_status[] = {
494#ifdef STA_PLL
495  { STA_PLL, "STA_PLL" },
496#endif
497#ifdef STA_PPSFREQ
498  { STA_PPSFREQ, "STA_PPSFREQ" },
499#endif
500#ifdef STA_PPSTIME
501  { STA_PPSTIME, "STA_PPSTIME" },
502#endif
503#ifdef STA_FLL
504  { STA_FLL, "STA_FLL" },
505#endif
506#ifdef STA_INS
507  { STA_INS, "STA_INS" },
508#endif
509#ifdef STA_DEL
510  { STA_DEL, "STA_DEL" },
511#endif
512#ifdef STA_UNSYNC
513  { STA_UNSYNC, "STA_UNSYNC" },
514#endif
515#ifdef STA_FREQHOLD
516  { STA_FREQHOLD, "STA_FREQHOLD" },
517#endif
518#ifdef STA_PPSSIGNAL
519  { STA_PPSSIGNAL, "STA_PPSSIGNAL" },
520#endif
521#ifdef STA_PPSJITTER
522  { STA_PPSJITTER, "STA_PPSJITTER" },
523#endif
524#ifdef STA_PPSWANDER
525  { STA_PPSWANDER, "STA_PPSWANDER" },
526#endif
527#ifdef STA_PPSERROR
528  { STA_PPSERROR, "STA_PPSERROR" },
529#endif
530#ifdef STA_CLOCKERR
531  { STA_CLOCKERR, "STA_CLOCKERR" },
532#endif
533  { 0,             NULL }
534};
535
536static const struct xlat adjtimex_state[] = {
537#ifdef TIME_OK
538  { TIME_OK, "TIME_OK" },
539#endif
540#ifdef TIME_INS
541  { TIME_INS, "TIME_INS" },
542#endif
543#ifdef TIME_DEL
544  { TIME_DEL, "TIME_DEL" },
545#endif
546#ifdef TIME_OOP
547  { TIME_OOP, "TIME_OOP" },
548#endif
549#ifdef TIME_WAIT
550  { TIME_WAIT, "TIME_WAIT" },
551#endif
552#ifdef TIME_ERROR
553  { TIME_ERROR, "TIME_ERROR" },
554#endif
555  { 0,             NULL }
556};
557
558#if SUPPORTED_PERSONALITIES > 1
559static int
560tprint_timex32(struct tcb *tcp, long addr)
561{
562	struct {
563		unsigned int modes;
564		int     offset;
565		int     freq;
566		int     maxerror;
567		int     esterror;
568		int     status;
569		int     constant;
570		int     precision;
571		int     tolerance;
572		struct timeval32 time;
573		int     tick;
574		int     ppsfreq;
575		int     jitter;
576		int     shift;
577		int     stabil;
578		int     jitcnt;
579		int     calcnt;
580		int     errcnt;
581		int     stbcnt;
582	} tx;
583
584	if (umove(tcp, addr, &tx) < 0)
585		return -1;
586
587	tprintf("{modes=");
588	printflags(adjtimex_modes, tx.modes, "ADJ_???");
589	tprintf(", offset=%d, freq=%d, maxerror=%d, ",
590		tx.offset, tx.freq, tx.maxerror);
591	tprintf("esterror=%u, status=", tx.esterror);
592	printflags(adjtimex_status, tx.status, "STA_???");
593	tprintf(", constant=%d, precision=%u, ",
594		tx.constant, tx.precision);
595	tprintf("tolerance=%d, time=", tx.tolerance);
596	tprint_timeval32(tcp, &tx.time);
597	tprintf(", tick=%d, ppsfreq=%d, jitter=%d",
598		tx.tick, tx.ppsfreq, tx.jitter);
599	tprintf(", shift=%d, stabil=%d, jitcnt=%d",
600		tx.shift, tx.stabil, tx.jitcnt);
601	tprintf(", calcnt=%d, errcnt=%d, stbcnt=%d",
602		tx.calcnt, tx.errcnt, tx.stbcnt);
603	tprintf("}");
604	return 0;
605}
606#endif /* SUPPORTED_PERSONALITIES > 1 */
607
608static int
609tprint_timex(struct tcb *tcp, long addr)
610{
611	struct timex tx;
612
613#if SUPPORTED_PERSONALITIES > 1
614	if (personality_wordsize[current_personality] == 4)
615		return tprint_timex32(tcp, addr);
616#endif
617	if (umove(tcp, addr, &tx) < 0)
618		return -1;
619
620#if LINUX_VERSION_CODE < 66332
621	tprintf("{mode=%d, offset=%ld, frequency=%ld, ",
622		tx.mode, tx.offset, tx.frequency);
623	tprintf("maxerror=%ld, esterror=%lu, status=%u, ",
624		tx.maxerror, tx.esterror, tx.status);
625	tprintf("time_constant=%ld, precision=%lu, ",
626		tx.time_constant, tx.precision);
627	tprintf("tolerance=%ld, time=", tx.tolerance);
628	tprint_timeval(tcp, &tx.time);
629#else
630	tprintf("{modes=");
631	printflags(adjtimex_modes, tx.modes, "ADJ_???");
632	tprintf(", offset=%ld, freq=%ld, maxerror=%ld, ",
633		tx.offset, tx.freq, tx.maxerror);
634	tprintf("esterror=%lu, status=", tx.esterror);
635	printflags(adjtimex_status, tx.status, "STA_???");
636	tprintf(", constant=%ld, precision=%lu, ",
637		tx.constant, tx.precision);
638	tprintf("tolerance=%ld, time=", tx.tolerance);
639	tprint_timeval(tcp, &tx.time);
640	tprintf(", tick=%ld, ppsfreq=%ld, jitter=%ld",
641		tx.tick, tx.ppsfreq, tx.jitter);
642	tprintf(", shift=%d, stabil=%ld, jitcnt=%ld",
643		tx.shift, tx.stabil, tx.jitcnt);
644	tprintf(", calcnt=%ld, errcnt=%ld, stbcnt=%ld",
645		tx.calcnt, tx.errcnt, tx.stbcnt);
646#endif
647	tprintf("}");
648	return 0;
649}
650
651int
652sys_adjtimex(struct tcb *tcp)
653{
654	if (exiting(tcp)) {
655		if (tcp->u_arg[0] == 0)
656			tprintf("NULL");
657		else if (syserror(tcp) || !verbose(tcp))
658			tprintf("%#lx", tcp->u_arg[0]);
659		else if (tprint_timex(tcp, tcp->u_arg[0]) < 0)
660			tprintf("{...}");
661		if (syserror(tcp))
662			return 0;
663		tcp->auxstr = xlookup(adjtimex_state, tcp->u_rval);
664		if (tcp->auxstr)
665			return RVAL_STR;
666	}
667	return 0;
668}
669
670static const struct xlat clockflags[] = {
671  { TIMER_ABSTIME, "TIMER_ABSTIME" },
672  { 0,             NULL }
673};
674
675static const struct xlat clocknames[] = {
676#ifdef CLOCK_REALTIME
677  { CLOCK_REALTIME, "CLOCK_REALTIME" },
678#endif
679#ifdef CLOCK_MONOTONIC
680  { CLOCK_MONOTONIC, "CLOCK_MONOTONIC" },
681#endif
682#ifdef CLOCK_PROCESS_CPUTIME_ID
683  { CLOCK_PROCESS_CPUTIME_ID, "CLOCK_PROCESS_CPUTIME_ID" },
684#endif
685#ifdef CLOCK_THREAD_CPUTIME_ID
686  { CLOCK_THREAD_CPUTIME_ID, "CLOCK_THREAD_CPUTIME_ID" },
687#endif
688#ifdef CLOCK_MONOTONIC_RAW
689  { CLOCK_MONOTONIC_RAW, "CLOCK_MONOTONIC_RAW" },
690#endif
691#ifdef CLOCK_REALTIME_COARSE
692  { CLOCK_REALTIME_COARSE, "CLOCK_REALTIME_COARSE" },
693#endif
694#ifdef CLOCK_MONOTONIC_COARSE
695  { CLOCK_MONOTONIC_COARSE, "CLOCK_MONOTONIC_COARSE" },
696#endif
697  { 0, NULL }
698};
699
700int
701sys_clock_settime(tcp)
702struct tcb *tcp;
703{
704	if (entering(tcp)) {
705		printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
706		tprintf(", ");
707		printtv(tcp, tcp->u_arg[1]);
708	}
709	return 0;
710}
711
712int
713sys_clock_gettime(tcp)
714struct tcb *tcp;
715{
716	if (entering(tcp)) {
717		printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
718		tprintf(", ");
719	} else {
720		if (syserror(tcp))
721			tprintf("%#lx", tcp->u_arg[1]);
722		else
723			printtv(tcp, tcp->u_arg[1]);
724	}
725	return 0;
726}
727
728int
729sys_clock_nanosleep(tcp)
730struct tcb *tcp;
731{
732	if (entering(tcp)) {
733		printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
734		tprintf(", ");
735		printflags(clockflags, tcp->u_arg[1], "TIMER_???");
736		tprintf(", ");
737		printtv(tcp, tcp->u_arg[2]);
738		tprintf(", ");
739	} else {
740		if (syserror(tcp))
741			tprintf("%#lx", tcp->u_arg[3]);
742		else
743			printtv(tcp, tcp->u_arg[3]);
744	}
745	return 0;
746}
747
748#ifndef SIGEV_THREAD_ID
749# define SIGEV_THREAD_ID 4
750#endif
751static const struct xlat sigev_value[] = {
752	{ SIGEV_SIGNAL+1, "SIGEV_SIGNAL" },
753	{ SIGEV_NONE+1, "SIGEV_NONE" },
754	{ SIGEV_THREAD+1, "SIGEV_THREAD" },
755	{ SIGEV_THREAD_ID+1, "SIGEV_THREAD_ID" },
756	{ 0, NULL }
757};
758
759#if SUPPORTED_PERSONALITIES > 1
760static void
761printsigevent32(struct tcb *tcp, long arg)
762{
763	struct {
764		int     sigev_value;
765		int     sigev_signo;
766		int     sigev_notify;
767
768		union {
769			int     tid;
770			struct {
771				int     function, attribute;
772			} thread;
773		} un;
774	} sev;
775
776	if (umove(tcp, arg, &sev) < 0)
777		tprintf("{...}");
778	else {
779		tprintf("{%#x, ", sev.sigev_value);
780		if (sev.sigev_notify == SIGEV_SIGNAL)
781			tprintf("%s, ", signame(sev.sigev_signo));
782		else
783			tprintf("%u, ", sev.sigev_signo);
784		printxval(sigev_value, sev.sigev_notify + 1, "SIGEV_???");
785		tprintf(", ");
786		if (sev.sigev_notify == SIGEV_THREAD_ID)
787			tprintf("{%d}", sev.un.tid);
788		else if (sev.sigev_notify == SIGEV_THREAD)
789			tprintf("{%#x, %#x}",
790				sev.un.thread.function,
791				sev.un.thread.attribute);
792		else
793			tprintf("{...}");
794		tprintf("}");
795	}
796}
797#endif
798
799void
800printsigevent(struct tcb *tcp, long arg)
801{
802	struct sigevent sev;
803
804#if SUPPORTED_PERSONALITIES > 1
805	if (personality_wordsize[current_personality] == 4)
806	{
807		printsigevent32(tcp, arg);
808		return;
809	}
810#endif
811	if (umove (tcp, arg, &sev) < 0)
812		tprintf("{...}");
813	else {
814		tprintf("{%p, ", sev.sigev_value.sival_ptr);
815		if (sev.sigev_notify == SIGEV_SIGNAL)
816			tprintf("%s, ", signame(sev.sigev_signo));
817		else
818			tprintf("%u, ", sev.sigev_signo);
819		printxval(sigev_value, sev.sigev_notify+1, "SIGEV_???");
820		tprintf(", ");
821		if (sev.sigev_notify == SIGEV_THREAD_ID)
822			/* _pad[0] is the _tid field which might not be
823			   present in the userlevel definition of the
824			   struct.  */
825			tprintf("{%d}", sev._sigev_un._pad[0]);
826		else if (sev.sigev_notify == SIGEV_THREAD)
827			tprintf("{%p, %p}", sev.sigev_notify_function,
828				sev.sigev_notify_attributes);
829		else
830			tprintf("{...}");
831		tprintf("}");
832	}
833}
834
835int
836sys_timer_create(tcp)
837struct tcb *tcp;
838{
839	if (entering(tcp)) {
840		printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
841		tprintf(", ");
842		printsigevent(tcp, tcp->u_arg[1]);
843		tprintf(", ");
844	} else {
845		void *p;
846
847		if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &p) < 0)
848			tprintf("%#lx", tcp->u_arg[2]);
849		else
850			tprintf("{%p}", p);
851	}
852	return 0;
853}
854
855int
856sys_timer_settime(tcp)
857struct tcb *tcp;
858{
859	if (entering(tcp)) {
860		tprintf("%#lx, ", tcp->u_arg[0]);
861		printflags(clockflags, tcp->u_arg[1], "TIMER_???");
862		tprintf(", ");
863		printitv(tcp, tcp->u_arg[2]);
864		tprintf(", ");
865	} else {
866		if (syserror(tcp))
867			tprintf("%#lx", tcp->u_arg[3]);
868		else
869			printitv(tcp, tcp->u_arg[3]);
870	}
871	return 0;
872}
873
874int
875sys_timer_gettime(tcp)
876struct tcb *tcp;
877{
878	if (entering(tcp)) {
879		tprintf("%#lx, ", tcp->u_arg[0]);
880	} else {
881		if (syserror(tcp))
882			tprintf("%#lx", tcp->u_arg[1]);
883		else
884			printitv(tcp, tcp->u_arg[1]);
885	}
886	return 0;
887}
888
889static void
890print_rtc(tcp, rt)
891struct tcb *tcp;
892const struct rtc_time *rt;
893{
894	tprintf("{tm_sec=%d, tm_min=%d, tm_hour=%d, "
895		"tm_mday=%d, tm_mon=%d, tm_year=%d, ",
896		rt->tm_sec, rt->tm_min, rt->tm_hour,
897		rt->tm_mday, rt->tm_mon, rt->tm_year);
898	if (!abbrev(tcp))
899		tprintf("tm_wday=%d, tm_yday=%d, tm_isdst=%d}",
900			rt->tm_wday, rt->tm_yday, rt->tm_isdst);
901	else
902		tprintf("...}");
903}
904
905int
906rtc_ioctl(tcp, code, arg)
907struct tcb *tcp;
908long code;
909long arg;
910{
911	switch (code) {
912	case RTC_ALM_SET:
913	case RTC_SET_TIME:
914		if (entering(tcp)) {
915			struct rtc_time rt;
916			if (umove(tcp, arg, &rt) < 0)
917				tprintf(", %#lx", arg);
918			else {
919				tprintf(", ");
920				print_rtc(tcp, &rt);
921			}
922		}
923		break;
924	case RTC_ALM_READ:
925	case RTC_RD_TIME:
926		if (exiting(tcp)) {
927			struct rtc_time rt;
928			if (syserror(tcp) || umove(tcp, arg, &rt) < 0)
929				tprintf(", %#lx", arg);
930			else {
931				tprintf(", ");
932				print_rtc(tcp, &rt);
933			}
934		}
935		break;
936	case RTC_IRQP_SET:
937	case RTC_EPOCH_SET:
938		if (entering(tcp))
939			tprintf(", %lu", arg);
940		break;
941	case RTC_IRQP_READ:
942	case RTC_EPOCH_READ:
943		if (exiting(tcp))
944			tprintf(", %lu", arg);
945		break;
946	case RTC_WKALM_SET:
947		if (entering(tcp)) {
948			struct rtc_wkalrm wk;
949			if (umove(tcp, arg, &wk) < 0)
950				tprintf(", %#lx", arg);
951			else {
952				tprintf(", {enabled=%d, pending=%d, ",
953					wk.enabled, wk.pending);
954				print_rtc(tcp, &wk.time);
955				tprintf("}");
956			}
957		}
958		break;
959	case RTC_WKALM_RD:
960		if (exiting(tcp)) {
961			struct rtc_wkalrm wk;
962			if (syserror(tcp) || umove(tcp, arg, &wk) < 0)
963				tprintf(", %#lx", arg);
964			else {
965				tprintf(", {enabled=%d, pending=%d, ",
966					wk.enabled, wk.pending);
967				print_rtc(tcp, &wk.time);
968				tprintf("}");
969			}
970		}
971		break;
972	default:
973		if (entering(tcp))
974			tprintf(", %#lx", arg);
975		break;
976	}
977	return 1;
978}
979
980#ifndef TFD_TIMER_ABSTIME
981#define TFD_TIMER_ABSTIME (1 << 0)
982#endif
983
984static const struct xlat timerfdflags[] = {
985	{ TFD_TIMER_ABSTIME,	"TFD_TIMER_ABSTIME"	},
986	{ 0,			NULL			}
987};
988
989int
990sys_timerfd(tcp)
991struct tcb *tcp;
992{
993	if (entering(tcp)) {
994		/* It does not matter that the kernel uses itimerspec.  */
995		tprintf("%ld, ", tcp->u_arg[0]);
996		printxval(clocknames, tcp->u_arg[1], "CLOCK_???");
997		tprintf(", ");
998		printflags(timerfdflags, tcp->u_arg[2], "TFD_???");
999		tprintf(", ");
1000		printitv(tcp, tcp->u_arg[3]);
1001	}
1002	return 0;
1003}
1004
1005int
1006sys_timerfd_create(struct tcb *tcp)
1007{
1008	if (entering(tcp)) {
1009		printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
1010		tprintf(", ");
1011		printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
1012	}
1013	return 0;
1014}
1015
1016int
1017sys_timerfd_settime(struct tcb *tcp)
1018{
1019	if (entering(tcp)) {
1020		printfd(tcp, tcp->u_arg[0]);
1021		tprintf(", ");
1022		printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
1023		tprintf(", ");
1024		printitv(tcp, tcp->u_arg[2]);
1025		tprintf(", ");
1026		printitv(tcp, tcp->u_arg[3]);
1027	}
1028	return 0;
1029}
1030
1031int
1032sys_timerfd_gettime(struct tcb *tcp)
1033{
1034	if (entering(tcp)) {
1035		printfd(tcp, tcp->u_arg[0]);
1036		tprintf(", ");
1037		printitv(tcp, tcp->u_arg[1]);
1038	}
1039	return 0;
1040}
1041
1042#endif /* LINUX */
1043