X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=time.c;h=b5fdc5233c4f773c56117b6e242b122f2caccb07;hb=3138213bc9a827a372ad9f8009ebcc5d8797ce2d;hp=ebd788f36cc31c476761def7ce0c00d7f03c5abf;hpb=ac518d10777f9dd95aad22939da6c867cf4c193e;p=strace diff --git a/time.c b/time.c index ebd788f3..b5fdc523 100644 --- a/time.c +++ b/time.c @@ -36,50 +36,175 @@ #include #include #include + +#ifndef UTIME_NOW +#define UTIME_NOW ((1l << 30) - 1l) +#endif +#ifndef UTIME_OMIT +#define UTIME_OMIT ((1l << 30) - 2l) +#endif #endif /* LINUX */ -void -printtv(tcp, addr) -struct tcb *tcp; -long addr; +struct timeval32 { - struct timeval tv; + u_int32_t tv_sec, tv_usec; +}; +static void +tprint_timeval32(struct tcb *tcp, const struct timeval32 *tv) +{ + tprintf("{%u, %u}", tv->tv_sec, tv->tv_usec); +} + +static void +tprint_timeval(struct tcb *tcp, const struct timeval *tv) +{ + tprintf("{%lu, %lu}", + (unsigned long) tv->tv_sec, (unsigned long) tv->tv_usec); +} + +void +printtv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness, int special) +{ if (addr == 0) tprintf("NULL"); else if (!verbose(tcp)) tprintf("%#lx", addr); - else if (umove(tcp, addr, &tv) < 0) - tprintf("{...}"); - else - tprintf("{%lu, %lu}", (long) tv.tv_sec, (long) tv.tv_usec); + else { + int rc; + + if (bitness == BITNESS_32 +#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1 + || personality_wordsize[current_personality] == 4 +#endif + ) + { + struct timeval32 tv; + + if ((rc = umove(tcp, addr, &tv)) >= 0) { + if (special && tv.tv_sec == 0 && + tv.tv_usec == UTIME_NOW) + tprintf("UTIME_NOW"); + else if (special && tv.tv_sec == 0 && + tv.tv_usec == UTIME_OMIT) + tprintf("UTIME_OMIT"); + else + tprint_timeval32(tcp, &tv); + } + } else { + struct timeval tv; + + if ((rc = umove(tcp, addr, &tv)) >= 0) { + if (special && tv.tv_sec == 0 && + tv.tv_usec == UTIME_NOW) + tprintf("UTIME_NOW"); + else if (special && tv.tv_sec == 0 && + tv.tv_usec == UTIME_OMIT) + tprintf("UTIME_OMIT"); + else + tprint_timeval(tcp, &tv); + } + } + if (rc < 0) + tprintf("{...}"); + } } -#ifdef ALPHA -struct timeval32 +void +sprinttv(struct tcb *tcp, long addr, enum bitness_t bitness, char *buf) { - unsigned tv_sec; - unsigned tv_usec; -}; + if (addr == 0) + strcpy(buf, "NULL"); + else if (!verbose(tcp)) + sprintf(buf, "%#lx", addr); + else { + int rc; -void -printtv32(tcp, addr) -struct tcb *tcp; -long addr; + if (bitness == BITNESS_32 +#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1 + || personality_wordsize[current_personality] == 4 +#endif + ) + { + struct timeval32 tv; + + if ((rc = umove(tcp, addr, &tv)) >= 0) + sprintf(buf, "{%u, %u}", + tv.tv_sec, tv.tv_usec); + } else { + struct timeval tv; + + if ((rc = umove(tcp, addr, &tv)) >= 0) + sprintf(buf, "{%lu, %lu}", + (unsigned long) tv.tv_sec, + (unsigned long) tv.tv_usec); + } + if (rc < 0) + strcpy(buf, "{...}"); + } +} + +void print_timespec(struct tcb *tcp, long addr) { - struct timeval32 tv; + if (addr == 0) + tprintf("NULL"); + else if (!verbose(tcp)) + tprintf("%#lx", addr); + else { + int rc; - if (addr == 0) - tprintf("NULL"); - else if (!verbose(tcp)) - tprintf("%#lx", addr); - else if (umove(tcp, addr, &tv) < 0) - tprintf("{...}"); - else - tprintf("{%u, %u}", tv.tv_sec, tv.tv_usec); +#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1 + if (personality_wordsize[current_personality] == 4) { + struct timeval32 tv; + + if ((rc = umove(tcp, addr, &tv)) >= 0) + tprintf("{%u, %u}", + tv.tv_sec, tv.tv_usec); + } else +#endif + { + struct timespec ts; + + if ((rc = umove(tcp, addr, &ts)) >= 0) + tprintf("{%lu, %lu}", + (unsigned long) ts.tv_sec, + (unsigned long) ts.tv_nsec); + } + if (rc < 0) + tprintf("{...}"); + } } + +void sprint_timespec(char *buf, struct tcb *tcp, long addr) +{ + if (addr == 0) + strcpy(buf, "NULL"); + else if (!verbose(tcp)) + sprintf(buf, "%#lx", addr); + else { + int rc; + +#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1 + if (personality_wordsize[current_personality] == 4) { + struct timeval32 tv; + + if ((rc = umove(tcp, addr, &tv)) >= 0) + sprintf(buf, "{%u, %u}", + tv.tv_sec, tv.tv_usec); + } else #endif + { + struct timespec ts; + if ((rc = umove(tcp, addr, &ts)) >= 0) + sprintf(buf, "{%lu, %lu}", + (unsigned long) ts.tv_sec, + (unsigned long) ts.tv_nsec); + } + if (rc < 0) + strcpy(buf, "{...}"); + } +} int sys_time(tcp) @@ -128,19 +253,18 @@ int sys_osf_gettimeofday(tcp) struct tcb *tcp; { - if (exiting(tcp)) { - if (syserror(tcp)) { - tprintf("%#lx, %#lx", - tcp->u_arg[0], tcp->u_arg[1]); - return 0; - } - printtv32(tcp, tcp->u_arg[0]); + if (exiting(tcp)) { + if (syserror(tcp)) { + tprintf("%#lx, %#lx", tcp->u_arg[0], tcp->u_arg[1]); + return 0; + } + printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32, 0); #ifndef SVR4 - tprintf(", "); - printtv32(tcp, tcp->u_arg[1]); + tprintf(", "); + printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32, 0); #endif /* !SVR4 */ - } - return 0; + } + return 0; } #endif @@ -163,14 +287,14 @@ int sys_osf_settimeofday(tcp) struct tcb *tcp; { - if (entering(tcp)) { - printtv32(tcp, tcp->u_arg[0]); + if (entering(tcp)) { + printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32, 0); #ifndef SVR4 - tprintf(", "); - printtv32(tcp, tcp->u_arg[1]); + tprintf(", "); + printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32, 0); #endif /* !SVR4 */ - } - return 0; + } + return 0; } #endif @@ -190,6 +314,21 @@ struct tcb *tcp; return 0; } +int +sys_nanosleep(struct tcb *tcp) +{ + if (entering(tcp)) { + print_timespec(tcp, tcp->u_arg[0]); + tprintf(", "); + } else { + if (!tcp->u_arg[1] || is_restart_error(tcp)) + print_timespec(tcp, tcp->u_arg[1]); + else + tprintf("%#lx", tcp->u_arg[1]); + } + return 0; +} + static const struct xlat which[] = { { ITIMER_REAL, "ITIMER_REAL" }, { ITIMER_VIRTUAL,"ITIMER_VIRTUAL"}, @@ -198,51 +337,50 @@ static const struct xlat which[] = { }; static void -printitv(tcp, addr) -struct tcb *tcp; -long addr; +printitv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness) { - struct itimerval itv; - if (addr == 0) tprintf("NULL"); else if (!verbose(tcp)) tprintf("%#lx", addr); - else if (umove(tcp, addr, &itv) < 0) - tprintf("{...}"); else { - tprintf("{it_interval={%lu, %lu}, it_value={%lu, %lu}}", - (long) itv.it_interval.tv_sec, (long) itv.it_interval.tv_usec, - (long) itv.it_value.tv_sec, (long) itv.it_value.tv_usec); - } -} + int rc; + if (bitness == BITNESS_32 +#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1 + || personality_wordsize[current_personality] == 4 +#endif + ) + { + struct { + struct timeval32 it_interval, it_value; + } itv; -#ifdef ALPHA -static void -printitv32(tcp, addr) -struct tcb *tcp; -long addr; -{ - struct itimerval32 - { - struct timeval32 it_interval; - struct timeval32 it_value; - } itv; + if ((rc = umove(tcp, addr, &itv)) >= 0) { + tprintf("{it_interval="); + tprint_timeval32(tcp, &itv.it_interval); + tprintf(", it_value="); + tprint_timeval32(tcp, &itv.it_value); + tprintf("}"); + } + } else { + struct itimerval itv; - if (addr == 0) - tprintf("NULL"); - else if (!verbose(tcp)) - tprintf("%#lx", addr); - else if (umove(tcp, addr, &itv) < 0) - tprintf("{...}"); - else { - tprintf("{it_interval={%u, %u}, it_value={%u, %u}}", - itv.it_interval.tv_sec, itv.it_interval.tv_usec, - itv.it_value.tv_sec, itv.it_value.tv_usec); - } + if ((rc = umove(tcp, addr, &itv)) >= 0) { + tprintf("{it_interval="); + tprint_timeval(tcp, &itv.it_interval); + tprintf(", it_value="); + tprint_timeval(tcp, &itv.it_value); + tprintf("}"); + } + } + if (rc < 0) + tprintf("{...}"); + } } -#endif + +#define printitv(tcp, addr) \ + printitv_bitness((tcp), (addr), BITNESS_CURRENT) int sys_getitimer(tcp) @@ -266,16 +404,16 @@ int sys_osf_getitimer(tcp) struct tcb *tcp; { - if (entering(tcp)) { - printxval(which, tcp->u_arg[0], "ITIMER_???"); - tprintf(", "); - } else { - if (syserror(tcp)) - tprintf("%#lx", tcp->u_arg[1]); - else - printitv32(tcp, tcp->u_arg[1]); - } - return 0; + if (entering(tcp)) { + printxval(which, tcp->u_arg[0], "ITIMER_???"); + tprintf(", "); + } else { + if (syserror(tcp)) + tprintf("%#lx", tcp->u_arg[1]); + else + printitv_bitness(tcp, tcp->u_arg[1], BITNESS_32); + } + return 0; } #endif @@ -302,61 +440,225 @@ int sys_osf_setitimer(tcp) struct tcb *tcp; { - if (entering(tcp)) { - printxval(which, tcp->u_arg[0], "ITIMER_???"); - tprintf(", "); - printitv32(tcp, tcp->u_arg[1]); - tprintf(", "); - } else { - if (syserror(tcp)) - tprintf("%#lx", tcp->u_arg[2]); - else - printitv32(tcp, tcp->u_arg[2]); - } - return 0; + if (entering(tcp)) { + printxval(which, tcp->u_arg[0], "ITIMER_???"); + tprintf(", "); + printitv_bitness(tcp, tcp->u_arg[1], BITNESS_32); + tprintf(", "); + } else { + if (syserror(tcp)) + tprintf("%#lx", tcp->u_arg[2]); + else + printitv_bitness(tcp, tcp->u_arg[2], BITNESS_32); + } + return 0; } #endif #ifdef LINUX -int -sys_adjtimex(tcp) -struct tcb *tcp; +static const struct xlat adjtimex_modes[] = { + { 0, "0" }, +#ifdef ADJ_OFFSET + { ADJ_OFFSET, "ADJ_OFFSET" }, +#endif +#ifdef ADJ_FREQUENCY + { ADJ_FREQUENCY, "ADJ_FREQUENCY" }, +#endif +#ifdef ADJ_MAXERROR + { ADJ_MAXERROR, "ADJ_MAXERROR" }, +#endif +#ifdef ADJ_ESTERROR + { ADJ_ESTERROR, "ADJ_ESTERROR" }, +#endif +#ifdef ADJ_STATUS + { ADJ_STATUS, "ADJ_STATUS" }, +#endif +#ifdef ADJ_TIMECONST + { ADJ_TIMECONST, "ADJ_TIMECONST" }, +#endif +#ifdef ADJ_TICK + { ADJ_TICK, "ADJ_TICK" }, +#endif +#ifdef ADJ_OFFSET_SINGLESHOT + { ADJ_OFFSET_SINGLESHOT, "ADJ_OFFSET_SINGLESHOT" }, +#endif + { 0, NULL } +}; + +static const struct xlat adjtimex_status[] = { +#ifdef STA_PLL + { STA_PLL, "STA_PLL" }, +#endif +#ifdef STA_PPSFREQ + { STA_PPSFREQ, "STA_PPSFREQ" }, +#endif +#ifdef STA_PPSTIME + { STA_PPSTIME, "STA_PPSTIME" }, +#endif +#ifdef STA_FLL + { STA_FLL, "STA_FLL" }, +#endif +#ifdef STA_INS + { STA_INS, "STA_INS" }, +#endif +#ifdef STA_DEL + { STA_DEL, "STA_DEL" }, +#endif +#ifdef STA_UNSYNC + { STA_UNSYNC, "STA_UNSYNC" }, +#endif +#ifdef STA_FREQHOLD + { STA_FREQHOLD, "STA_FREQHOLD" }, +#endif +#ifdef STA_PPSSIGNAL + { STA_PPSSIGNAL, "STA_PPSSIGNAL" }, +#endif +#ifdef STA_PPSJITTER + { STA_PPSJITTER, "STA_PPSJITTER" }, +#endif +#ifdef STA_PPSWANDER + { STA_PPSWANDER, "STA_PPSWANDER" }, +#endif +#ifdef STA_PPSERROR + { STA_PPSERROR, "STA_PPSERROR" }, +#endif +#ifdef STA_CLOCKERR + { STA_CLOCKERR, "STA_CLOCKERR" }, +#endif + { 0, NULL } +}; + +static const struct xlat adjtimex_state[] = { +#ifdef TIME_OK + { TIME_OK, "TIME_OK" }, +#endif +#ifdef TIME_INS + { TIME_INS, "TIME_INS" }, +#endif +#ifdef TIME_DEL + { TIME_DEL, "TIME_DEL" }, +#endif +#ifdef TIME_OOP + { TIME_OOP, "TIME_OOP" }, +#endif +#ifdef TIME_WAIT + { TIME_WAIT, "TIME_WAIT" }, +#endif +#ifdef TIME_ERROR + { TIME_ERROR, "TIME_ERROR" }, +#endif + { 0, NULL } +}; + +#if SUPPORTED_PERSONALITIES > 1 +static int +tprint_timex32(struct tcb *tcp, long addr) { - struct timex txc; + struct { + unsigned int modes; + int offset; + int freq; + int maxerror; + int esterror; + int status; + int constant; + int precision; + int tolerance; + struct timeval32 time; + int tick; + int ppsfreq; + int jitter; + int shift; + int stabil; + int jitcnt; + int calcnt; + int errcnt; + int stbcnt; + } tx; + + if (umove(tcp, addr, &tx) < 0) + return -1; + tprintf("{modes="); + printflags(adjtimex_modes, tx.modes, "ADJ_???"); + tprintf(", offset=%d, freq=%d, maxerror=%d, ", + tx.offset, tx.freq, tx.maxerror); + tprintf("esterror=%u, status=", tx.esterror); + printflags(adjtimex_status, tx.status, "STA_???"); + tprintf(", constant=%d, precision=%u, ", + tx.constant, tx.precision); + tprintf("tolerance=%d, time=", tx.tolerance); + tprint_timeval32(tcp, &tx.time); + tprintf(", tick=%d, ppsfreq=%d, jitter=%d", + tx.tick, tx.ppsfreq, tx.jitter); + tprintf(", shift=%d, stabil=%d, jitcnt=%d", + tx.shift, tx.stabil, tx.jitcnt); + tprintf(", calcnt=%d, errcnt=%d, stbcnt=%d", + tx.calcnt, tx.errcnt, tx.stbcnt); + tprintf("}"); + return 0; +} +#endif /* SUPPORTED_PERSONALITIES > 1 */ + +static int +tprint_timex(struct tcb *tcp, long addr) +{ + struct timex tx; + +#if SUPPORTED_PERSONALITIES > 1 + if (personality_wordsize[current_personality] == 4) + return tprint_timex32(tcp, addr); +#endif + if (umove(tcp, addr, &tx) < 0) + return -1; + +#if LINUX_VERSION_CODE < 66332 + tprintf("{mode=%d, offset=%ld, frequency=%ld, ", + tx.mode, tx.offset, tx.frequency); + tprintf("maxerror=%ld, esterror=%lu, status=%u, ", + tx.maxerror, tx.esterror, tx.status); + tprintf("time_constant=%ld, precision=%lu, ", + tx.time_constant, tx.precision); + tprintf("tolerance=%ld, time=", tx.tolerance); + tprint_timeval(tcp, &tx.time); +#else + tprintf("{modes="); + printflags(adjtimex_modes, tx.modes, "ADJ_???"); + tprintf(", offset=%ld, freq=%ld, maxerror=%ld, ", + tx.offset, tx.freq, tx.maxerror); + tprintf("esterror=%lu, status=", tx.esterror); + printflags(adjtimex_status, tx.status, "STA_???"); + tprintf(", constant=%ld, precision=%lu, ", + tx.constant, tx.precision); + tprintf("tolerance=%ld, time=", tx.tolerance); + tprint_timeval(tcp, &tx.time); + tprintf(", tick=%ld, ppsfreq=%ld, jitter=%ld", + tx.tick, tx.ppsfreq, tx.jitter); + tprintf(", shift=%d, stabil=%ld, jitcnt=%ld", + tx.shift, tx.stabil, tx.jitcnt); + tprintf(", calcnt=%ld, errcnt=%ld, stbcnt=%ld", + tx.calcnt, tx.errcnt, tx.stbcnt); +#endif + tprintf("}"); + return 0; +} + +int +sys_adjtimex(struct tcb *tcp) +{ if (exiting(tcp)) { if (tcp->u_arg[0] == 0) tprintf("NULL"); else if (syserror(tcp) || !verbose(tcp)) tprintf("%#lx", tcp->u_arg[0]); - else if (umove(tcp, tcp->u_arg[0], &txc) < 0) + else if (tprint_timex(tcp, tcp->u_arg[0]) < 0) tprintf("{...}"); - else { -#if LINUX_VERSION_CODE < 66332 - tprintf("{mode=%d, offset=%ld, frequency=%ld, ", - txc.mode, txc.offset, txc.frequency); - tprintf("maxerror=%ld, esterror=%lu, status=%u, ", - txc.maxerror, txc.esterror, txc.status); - tprintf("time_constant=%ld, precision=%lu, ", - txc.time_constant, txc.precision); - tprintf("tolerance=%ld, time={%lu, %lu}}", - txc.tolerance, (long) txc.time.tv_sec, - (long) txc.time.tv_usec); -#else - tprintf("{modes=%d, offset=%ld, freq=%ld, ", - txc.modes, txc.offset, txc.freq); - tprintf("maxerror=%ld, esterror=%lu, status=%u, ", - txc.maxerror, txc.esterror, txc.status); - tprintf("constant=%ld, precision=%lu, ", - txc.constant, txc.precision); - tprintf("tolerance=%ld, time={%lu, %lu}}", - txc.tolerance, (long) txc.time.tv_sec, - (long) txc.time.tv_usec); - /* there's a bunch of other stuff, but it's not - * worth the time or the trouble to include */ -#endif - } + if (syserror(tcp)) + return 0; + tcp->auxstr = xlookup(adjtimex_state, tcp->u_rval); + if (tcp->auxstr) + return RVAL_STR; } return 0; } @@ -373,7 +675,22 @@ static const struct xlat clocknames[] = { #ifdef CLOCK_MONOTONIC { CLOCK_MONOTONIC, "CLOCK_MONOTONIC" }, #endif - { 0, NULL } +#ifdef CLOCK_PROCESS_CPUTIME_ID + { CLOCK_PROCESS_CPUTIME_ID, "CLOCK_PROCESS_CPUTIME_ID" }, +#endif +#ifdef CLOCK_THREAD_CPUTIME_ID + { CLOCK_THREAD_CPUTIME_ID, "CLOCK_THREAD_CPUTIME_ID" }, +#endif +#ifdef CLOCK_MONOTONIC_RAW + { CLOCK_MONOTONIC_RAW, "CLOCK_MONOTONIC_RAW" }, +#endif +#ifdef CLOCK_REALTIME_COARSE + { CLOCK_REALTIME_COARSE, "CLOCK_REALTIME_COARSE" }, +#endif +#ifdef CLOCK_MONOTONIC_COARSE + { CLOCK_MONOTONIC_COARSE, "CLOCK_MONOTONIC_COARSE" }, +#endif + { 0, NULL } }; int @@ -435,12 +752,58 @@ static const struct xlat sigev_value[] = { { 0, NULL } }; +#if SUPPORTED_PERSONALITIES > 1 +static void +printsigevent32(struct tcb *tcp, long arg) +{ + struct { + int sigev_value; + int sigev_signo; + int sigev_notify; + + union { + int tid; + struct { + int function, attribute; + } thread; + } un; + } sev; + + if (umove(tcp, arg, &sev) < 0) + tprintf("{...}"); + else { + tprintf("{%#x, ", sev.sigev_value); + if (sev.sigev_notify == SIGEV_SIGNAL) + tprintf("%s, ", signame(sev.sigev_signo)); + else + tprintf("%u, ", sev.sigev_signo); + printxval(sigev_value, sev.sigev_notify + 1, "SIGEV_???"); + tprintf(", "); + if (sev.sigev_notify == SIGEV_THREAD_ID) + tprintf("{%d}", sev.un.tid); + else if (sev.sigev_notify == SIGEV_THREAD) + tprintf("{%#x, %#x}", + sev.un.thread.function, + sev.un.thread.attribute); + else + tprintf("{...}"); + tprintf("}"); + } +} +#endif + void -printsigevent(tcp, arg) -struct tcb *tcp; -long arg; +printsigevent(struct tcb *tcp, long arg) { struct sigevent sev; + +#if SUPPORTED_PERSONALITIES > 1 + if (personality_wordsize[current_personality] == 4) + { + printsigevent32(tcp, arg); + return; + } +#endif if (umove (tcp, arg, &sev) < 0) tprintf("{...}"); else { @@ -609,4 +972,67 @@ long arg; } return 1; } + +#ifndef TFD_TIMER_ABSTIME +#define TFD_TIMER_ABSTIME (1 << 0) +#endif + +static const struct xlat timerfdflags[] = { + { TFD_TIMER_ABSTIME, "TFD_TIMER_ABSTIME" }, + { 0, NULL } +}; + +int +sys_timerfd(tcp) +struct tcb *tcp; +{ + if (entering(tcp)) { + /* It does not matter that the kernel uses itimerspec. */ + tprintf("%ld, ", tcp->u_arg[0]); + printxval(clocknames, tcp->u_arg[1], "CLOCK_???"); + tprintf(", "); + printflags(timerfdflags, tcp->u_arg[2], "TFD_???"); + tprintf(", "); + printitv(tcp, tcp->u_arg[3]); + } + return 0; +} + +int +sys_timerfd_create(struct tcb *tcp) +{ + if (entering(tcp)) { + printxval(clocknames, tcp->u_arg[0], "CLOCK_???"); + tprintf(", "); + printflags(timerfdflags, tcp->u_arg[1], "TFD_???"); + } + return 0; +} + +int +sys_timerfd_settime(struct tcb *tcp) +{ + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + tprintf(", "); + printflags(timerfdflags, tcp->u_arg[1], "TFD_???"); + tprintf(", "); + printitv(tcp, tcp->u_arg[2]); + tprintf(", "); + printitv(tcp, tcp->u_arg[3]); + } + return 0; +} + +int +sys_timerfd_gettime(struct tcb *tcp) +{ + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + tprintf(", "); + printitv(tcp, tcp->u_arg[1]); + } + return 0; +} + #endif /* LINUX */