Submitted By: Jim Gifford (jim at cross-lfs dot org) Date: 01-07-2008 Initial Package Version: 2.86 Origin: Various Upstream Status: Unknown Description: Fixes to Major issues in Sysvinit -- listed Below IPV6 Displayed Incorrectly On 64bit which have 32bit multilib support, the utmp struct is the same Fix bug where proc names are truncated Fixed support for POSIX capabilite All halt/reboot to handle being called by login correctly Preserve waiting state across re-exec Allow failed console opens some time to resolve themselves New: Added kexec support diff -Naur sysvinit-2.86.orig/man/halt.8 sysvinit-2.86/man/halt.8 --- sysvinit-2.86.orig/man/halt.8 2001-11-21 13:11:22.000000000 -0800 +++ sysvinit-2.86/man/halt.8 2009-01-07 11:07:06.000000000 -0800 @@ -23,6 +23,7 @@ .RB [ \-d ] .RB [ \-f ] .RB [ \-i ] +.RB [ \-k ] .br .B /sbin/poweroff .RB [ \-n ] @@ -65,6 +66,8 @@ .IP \fB\-p\fP When halting the system, do a poweroff. This is the default when halt is called as \fBpoweroff\fP. +.IP \fB\-k\fP +Try to reboot using \fBkexec\fP, if kernel supports it. .\"}}} .\"{{{ Diagnostics .SH DIAGNOSTICS diff -Naur sysvinit-2.86.orig/man/init.8 sysvinit-2.86/man/init.8 --- sysvinit-2.86.orig/man/init.8 2004-07-29 04:21:31.000000000 -0700 +++ sysvinit-2.86/man/init.8 2009-01-07 11:23:45.000000000 -0800 @@ -64,7 +64,7 @@ .PP Runlevel \fBS\fP or \fBs\fP bring the system to single user mode and do not require an \fB/etc/inittab\fP file. In single user mode, -\fB/sbin/sulogin\fP is invoked on \fB/dev/console\fP. +a root shell is opened on \fB/dev/console\fP. .PP When entering single user mode, \fBinit\fP initializes the consoles \fBstty\fP settings to sane values. Clocal mode is set. Hardware diff -Naur sysvinit-2.86.orig/man/last.1 sysvinit-2.86/man/last.1 --- sysvinit-2.86.orig/man/last.1 2004-07-30 04:39:18.000000000 -0700 +++ sysvinit-2.86/man/last.1 2009-01-07 11:23:45.000000000 -0800 @@ -60,6 +60,8 @@ useful, e.g., to determine easily who was logged in at a particular time -- specify that time with \fB\-t\fP and look for "still logged in". +.IP "\fB\-f\fP \fIfile\fP" +Specifies a file to search other than \fB/var/log/wtmp\fP. .IP \fB\-R\fP Suppresses the display of the hostname field. .IP \fB\-a\fP diff -Naur sysvinit-2.86.orig/man/pidof.8 sysvinit-2.86/man/pidof.8 --- sysvinit-2.86.orig/man/pidof.8 1998-09-02 05:49:33.000000000 -0700 +++ sysvinit-2.86/man/pidof.8 2009-01-07 11:22:28.000000000 -0800 @@ -4,6 +4,7 @@ .SH SYNOPSIS .B pidof .RB [ \-s ] +.RB [ \-c ] .RB [ \-x ] .RB [ \-o .IR omitpid ] @@ -24,6 +25,10 @@ .SH OPTIONS .IP -s Single shot - this instructs the program to only return one \fIpid\fP. +.IP -c +Only return process ids that are running with the same root directory. +This option is ignored for non-root users, as they will be unable to check +the current root directory of processes they do not own. .IP -x Scripts too - this causes the program to also return process id's of shells running the named scripts. diff -Naur sysvinit-2.86.orig/man/shutdown.8 sysvinit-2.86/man/shutdown.8 --- sysvinit-2.86.orig/man/shutdown.8 2004-06-09 05:47:45.000000000 -0700 +++ sysvinit-2.86/man/shutdown.8 2009-01-07 11:08:22.000000000 -0800 @@ -9,11 +9,11 @@ .\"{{{ Synopsis .SH SYNOPSIS .B /sbin/shutdown +.RB [ \-akrhPHfFnc ] .RB [ \-t .IR sec ] -.RB [ \-arkhncfFHP ] .I time -.RI [ warning-message ] +.RI [ "warning message" ] .\"}}} .\"{{{ Description .SH DESCRIPTION @@ -39,11 +39,6 @@ .IP "\fB\-a\fP Use \fB/etc/shutdown.allow\fP. .\"}}} -.\"{{{ -t sec -.IP "\fB\-t\fP \fIsec\fP" -Tell \fBinit\fP(8) to wait \fIsec\fP seconds between sending processes the -warning and the kill signal, before changing to another runlevel. -.\"}}} .\"{{{ -k .IP \fB\-k\fP Don't really shutdown; only send the warning messages to everybody. @@ -56,20 +51,14 @@ .IP \fB\-h\fP Halt or poweroff after shutdown. .\"}}} -.\"{{{ -H -.IP \fB\-H\fP -Halt action is to halt or drop into boot monitor on systems that -support it. -.\"}}} .\"{{{ -P .IP \fB\-P\fP Halt action is to turn off the power. .\"}}} -.\"{{{ -n -.IP \fB\-n\fP -[DEPRECATED] Don't call \fBinit\fP(8) to do the shutdown but do it ourself. -The use of this option is discouraged, and its results are not always what -you'd expect. +.\"{{{ -H +.IP \fB\-H\fP +Halt action is to halt or drop into boot monitor on systems that +support it. .\"}}} .\"{{{ -f .IP \fB\-f\fP @@ -79,18 +68,29 @@ .IP \fB\-F\fP Force fsck on reboot. .\"}}} +.\"{{{ -n +.IP \fB\-n\fP +[DEPRECATED] Don't call \fBinit\fP(8) to do the shutdown but do it ourself. +The use of this option is discouraged, and its results are not always what +you'd expect. +.\"}}} .\"{{{ -c .IP \fB\-c\fP Cancel an already running shutdown. With this option it is of course not possible to give the \fBtime\fP argument, but you can enter a explanatory message on the command line that will be sent to all users. .\"}}} +.\"{{{ -t sec +.IP "\fB\-t\fP \fIsec\fP" +Tell \fBinit\fP(8) to wait \fIsec\fP seconds between sending processes the +warning and the kill signal, before changing to another runlevel. +.\"}}} .\"{{{ time .IP \fItime\fP When to shutdown. .\"}}} .\"{{{ warning-message -.IP \fIwarning-message\fP +.IP "\fIwarning message\fP" Message to send to all users. .\"}}} .PP diff -Naur sysvinit-2.86.orig/man/sulogin.8 sysvinit-2.86/man/sulogin.8 --- sysvinit-2.86.orig/man/sulogin.8 2004-06-09 05:47:45.000000000 -0700 +++ sysvinit-2.86/man/sulogin.8 2009-01-07 11:23:45.000000000 -0800 @@ -9,7 +9,7 @@ .RB [ " tty-device " ] .SH DESCRIPTION .I sulogin -is invoked by \fBinit(8)\fP when the system goes into single user mode +can be invoked by \fBinit(8)\fP when the system goes into single user mode (this is done through an entry in \fIinittab(5)\fP). \fBInit\fP also tries to execute \fIsulogin\fP when it is passed the \fB-b\fP flag from the bootmonitor (eg, LILO). diff -Naur sysvinit-2.86.orig/src/bootlogd.c sysvinit-2.86/src/bootlogd.c --- sysvinit-2.86.orig/src/bootlogd.c 2004-06-09 05:47:45.000000000 -0700 +++ sysvinit-2.86/src/bootlogd.c 2009-01-07 11:34:12.000000000 -0800 @@ -609,7 +609,7 @@ else todo = endptr - outptr; if (fp && todo) - writelog(fp, outptr, todo); + writelog(fp, (unsigned char *)outptr, todo); } if (fp) { diff -Naur sysvinit-2.86.orig/src/halt.c sysvinit-2.86/src/halt.c --- sysvinit-2.86.orig/src/halt.c 2004-07-30 05:16:18.000000000 -0700 +++ sysvinit-2.86/src/halt.c 2009-01-07 11:25:19.000000000 -0800 @@ -8,7 +8,7 @@ * execute an "shutdown -r". This is for compatibility with * sysvinit 2.4. * - * Usage: halt [-n] [-w] [-d] [-f] [-h] [-i] [-p] + * Usage: halt [-n] [-w] [-d] [-f] [-h] [-i] [-p] [-k] * -n: don't sync before halting the system * -w: only write a wtmp reboot record and exit. * -d: don't write a wtmp record. @@ -16,6 +16,7 @@ * -h: put harddisks in standby mode * -i: shut down all network interfaces. * -p: power down the system (if possible, otherwise halt). + * -k: reboot the system using kexec. * * Reboot and halt are both this program. Reboot * is just a link to halt. Invoking the program @@ -64,8 +65,10 @@ */ void usage(void) { - fprintf(stderr, "usage: %s [-n] [-w] [-d] [-f] [-h] [-i]%s\n", - progname, strcmp(progname, "halt") ? "" : " [-p]"); + fprintf(stderr, "usage: %s [-n] [-w] [-d] [-f] [-h] [-i]%s%s\n", + progname, + strcmp(progname, "halt") ? "" : " [-p]", + strcmp(progname, "reboot") ? "" : " [-k]"); fprintf(stderr, "\t-n: don't sync before halting the system\n"); fprintf(stderr, "\t-w: only write a wtmp reboot record and exit.\n"); fprintf(stderr, "\t-d: don't write a wtmp record.\n"); @@ -74,6 +77,8 @@ fprintf(stderr, "\t-i: shut down all network interfaces.\n"); if (!strcmp(progname, "halt")) fprintf(stderr, "\t-p: power down the system (if possible, otherwise halt).\n"); + if (!strcmp(progname, "reboot")) + fprintf(stderr, "\t-k: reboot the system using kexec.\n"); exit(1); } @@ -172,12 +177,14 @@ int do_ifdown = 0; int do_hddown = 0; int do_poweroff = 0; + int do_kexec = 0; int c; char *tm = NULL; /* * Find out who we are */ + if (argv[0][0] == '-') argv[0]++; if ((progname = strrchr(argv[0], '/')) != NULL) progname++; else @@ -189,7 +196,7 @@ /* * Get flags */ - while((c = getopt(argc, argv, ":ihdfnpwt:")) != EOF) { + while((c = getopt(argc, argv, ":ihdfnpwkt:")) != EOF) { switch(c) { case 'n': do_sync = 0; @@ -213,6 +220,9 @@ case 'p': do_poweroff = 1; break; + case 'k': + do_kexec = 1; + break; case 't': tm = optarg; break; @@ -230,12 +240,37 @@ (void)chdir("/"); if (!do_hard && !do_nothing) { + c = get_runlevel(); + + /* + * We can't reboot using kexec through this path. + */ + if (c != '6' && do_reboot && do_kexec) { + fprintf(stderr, "ERROR: using -k at this" + " runlevel requires also -f\n" + " (You probably want instead to reboot" + " normally and let your reboot\n" + " script, usually /etc/init.d/reboot," + " specify -k)\n"); + exit(1); + } + /* * See if we are in runlevel 0 or 6. */ - c = get_runlevel(); - if (c != '0' && c != '6') - do_shutdown(do_reboot ? "-r" : "-h", tm); + if (c != '0' && c != '6') { + char *file; + + if (do_poweroff) { + file = strdup("/poweroff"); + } else { + file = strdup("/halt"); + } + close(open(file, O_CREAT|O_RDWR, 0644)); + free(file); + + do_shutdown(do_reboot ? "-r" : "-h", tm); + } } /* @@ -263,6 +298,16 @@ if (do_nothing) exit(0); if (do_reboot) { + /* + * kexec or reboot + */ + if (do_kexec) { + init_reboot(BMAGIC_KEXEC); + } + + /* + * Fall through if failed + */ init_reboot(BMAGIC_REBOOT); } else { /* diff -Naur sysvinit-2.86.orig/src/init.c sysvinit-2.86/src/init.c --- sysvinit-2.86.orig/src/init.c 2004-07-30 05:16:20.000000000 -0700 +++ sysvinit-2.86/src/init.c 2009-01-07 14:02:51.000000000 -0800 @@ -185,6 +185,7 @@ {"RU",RUNNING}, {"DE",DEMAND}, {"XD",XECUTED}, + {"WT",WAITING}, {NULL,0} }; @@ -466,7 +467,7 @@ if (maxproclen > 2) { memset(argv0, 0, maxproclen); - strncpy(argv0, buf, maxproclen - 2); + strncpy(argv0, buf, maxproclen - 1); } return len; @@ -527,8 +528,10 @@ /* * Retry the open five times. */ - for(f = 0; f < 5; f++) + for(f = 0; f < 5; f++) { if ((fd = open(console_dev, m)) >= 0) break; + usleep(100); + } if (fd < 0) return fd; @@ -949,11 +952,30 @@ sigprocmask(SIG_SETMASK, &omask, NULL); /* + * Update utmp/wtmp file prior to starting + * any child. This MUST be done right here in + * the child process in order to prevent a race + * condition that occurs when the child + * process' time slice executes before the + * parent (can and does happen in a uniprocessor + * environment). If the child is a getty and + * the race condition happens, then init's utmp + * update will happen AFTER the getty runs + * and expects utmp to be updated already! + * + * Do NOT log if process field starts with '+' + * FIXME: that's for compatibility with *very* + * old getties - probably it can be taken out. + */ + if (ch->action == RESPAWN && ch->process[0] != '+') + write_utmp_wtmp("", ch->id, getpid(), INIT_PROCESS, ""); + + /* * In sysinit, boot, bootwait or single user mode: * for any wait-type subprocess we _force_ the console * to be its controlling tty. */ - if (strchr("*#sS", runlevel) && ch->flags & WAITING) { + if ((strchr("*#sS", runlevel) || (ch->id[0] == 'l' && isdigit(ch->id[1]))) && ch->flags & WAITING) { /* * We fork once extra. This is so that we can * wait and change the process group and session @@ -1088,15 +1110,7 @@ case ONDEMAND: case RESPAWN: ch->flags |= RUNNING; - if (spawn(ch, &(ch->pid)) < 0) break; - /* - * Do NOT log if process field starts with '+' - * FIXME: that's for compatibility with *very* - * old getties - probably it can be taken out. - */ - if (ch->process[0] != '+') - write_utmp_wtmp("", ch->id, ch->pid, - INIT_PROCESS, ""); + (void)spawn(ch, &(ch->pid)); break; } } @@ -1373,14 +1387,14 @@ case 0: /* Send TERM signal */ if (talk) initlog(L_CO, - "Sending processes the TERM signal"); + "Sending processes started by init the TERM signal"); kill(-(ch->pid), SIGTERM); foundOne = 1; break; case 1: /* Send KILL signal and collect status */ if (talk) initlog(L_CO, - "Sending processes the KILL signal"); + "Sending processes started by init the KILL signal"); kill(-(ch->pid), SIGKILL); break; } @@ -1884,7 +1898,7 @@ * The existing init process execs a new init binary. */ env = init_buildenv(0); - execl(myname, myname, "--init", NULL, env); + execle(myname, myname, "--init", NULL, env); /* * We shouldn't be here, something failed. diff -Naur sysvinit-2.86.orig/src/killall5.c sysvinit-2.86/src/killall5.c --- sysvinit-2.86.orig/src/killall5.c 2004-07-30 05:16:23.000000000 -0700 +++ sysvinit-2.86/src/killall5.c 2009-01-07 14:10:41.000000000 -0800 @@ -51,9 +51,8 @@ char *argv0base; /* `basename argv[1]` */ char *argv1; /* Name as found out from argv[1] */ char *argv1base; /* `basename argv[1]` */ + char *pathname; /* full path to executable */ char *statname; /* the statname without braces */ - ino_t ino; /* Inode number */ - dev_t dev; /* Device it is on */ pid_t pid; /* Process ID. */ int sid; /* Session ID. */ int kernel; /* Kernel thread or zombie. */ @@ -172,7 +171,6 @@ FILE *fp; PROC *p, *n; struct dirent *d; - struct stat st; char path[256]; char buf[256]; char *s, *q; @@ -191,6 +189,8 @@ n = p->next; if (p->argv0) free(p->argv0); if (p->argv1) free(p->argv1); + if (p->pathname) free(p->pathname); + if (p->statname) free(p->statname); free(p); } plist = NULL; @@ -248,6 +248,7 @@ p->sid = 0; nsyslog(LOG_ERR, "can't read sid from %s\n", path); + if (p->statname) free(p->statname); free(p); continue; } @@ -300,15 +301,18 @@ } else { /* Process disappeared.. */ + if (p->statname) free(p->statname); free(p); continue; } /* Try to stat the executable. */ snprintf(path, sizeof(path), "/proc/%s/exe", d->d_name); - if (stat(path, &st) == 0) { - p->dev = st.st_dev; - p->ino = st.st_ino; + p->pathname = (char *)xmalloc(PATH_MAX); + if (readlink(path, p->pathname, PATH_MAX) == -1) { + p->pathname = NULL; + } else { + p->pathname[PATH_MAX-1] = '\0'; } /* Link it into the list. */ @@ -372,14 +376,14 @@ { PROC *p; PIDQ_HEAD *q; - struct stat st; char *s; int dostat = 0; int foundone = 0; int ok = 0; + char *real_path; /* Try to stat the executable. */ - if (prog[0] == '/' && stat(prog, &st) == 0) dostat++; + if (prog[0] == '/' && (real_path = canonicalize_file_name(prog))) dostat++; /* Get basename of program. */ if ((s = strrchr(prog, '/')) == NULL) @@ -390,10 +394,10 @@ q = (PIDQ_HEAD *)xmalloc(sizeof(PIDQ_HEAD)); q = init_pid_q(q); - /* First try to find a match based on dev/ino pair. */ + /* First try to find a match based on pathname. */ if (dostat) { for (p = plist; p; p = p->next) { - if (p->dev == st.st_dev && p->ino == st.st_ino) { + if (p->pathname && strcmp(real_path, p->pathname) == 0) { add_pid_to_q(q, p); foundone++; } @@ -408,11 +412,14 @@ ok += (p->argv0 && strcmp(p->argv0, prog) == 0); ok += (p->argv0 && strcmp(p->argv0base, s) == 0); + if (prog[0] == '/' && p->pathname && strcmp(prog, p->pathname)) + ok = 0; + /* For scripts, compare argv[1] as well. */ if (scripts_too && p->argv1 && !strncmp(p->statname, p->argv1base, STATNAMELEN)) { ok += (strcmp(p->argv1, prog) == 0); - ok += (strcmp(p->argv1base, s) == 0); + if (prog[0] != '/') ok += (strcmp(p->argv1base, s) == 0); } /* @@ -476,16 +483,22 @@ int f; int first = 1; int i, oind, opt, flags = 0; + int chroot_check = 0; + struct stat st; + char tmp[512]; for (oind = PIDOF_OMITSZ-1; oind > 0; oind--) opid[oind] = 0; opterr = 0; - while ((opt = getopt(argc,argv,"ho:sx")) != EOF) switch (opt) { + while ((opt = getopt(argc,argv,"hco:sx")) != EOF) switch (opt) { case '?': nsyslog(LOG_ERR,"invalid options on command line!\n"); closelog(); exit(1); + case 'c': + if (geteuid() == 0) chroot_check = 1; + break; case 'o': if (oind >= PIDOF_OMITSZ -1) { nsyslog(LOG_ERR,"omit pid buffer size %d " @@ -518,6 +531,16 @@ argc -= optind; argv += optind; + /* Check if we are in a chroot */ + if (chroot_check) { + snprintf(tmp, 512, "/proc/%d/root", getpid()); + if (stat(tmp, &st) < 0) { + nsyslog(LOG_ERR, "stat failed for %s!\n", tmp); + closelog(); + exit(1); + } + } + /* Print out process-ID's one by one. */ readproc(); for(f = 0; f < argc; f++) { @@ -541,6 +564,16 @@ else spid = 1; } + if (chroot_check) { + struct stat st2; + snprintf(tmp, 512, "/proc/%d/root", + p->pid); + if (stat(tmp, &st2) < 0 || + st.st_dev != st2.st_dev || + st.st_ino != st2.st_ino) { + continue; + } + } if (!first) printf(" "); printf("%d", p->pid); diff -Naur sysvinit-2.86.orig/src/last.c sysvinit-2.86/src/last.c --- sysvinit-2.86.orig/src/last.c 2004-07-30 05:16:26.000000000 -0700 +++ sysvinit-2.86/src/last.c 2009-01-07 11:18:38.000000000 -0800 @@ -307,14 +307,15 @@ struct sockaddr *sa; int salen, flags; unsigned int topnibble; + unsigned int azero = 0, sitelocal = 0; int mapped = 0; flags = useip ? NI_NUMERICHOST : 0; /* * IPv4 or IPv6 ? We use 2 heuristics: - * 1. Current IPv6 range uses 2000-3fff. Outside of - * that is illegal and must be IPv4. + * 1. Current IPv6 range uses 2000-3fff or fec0-feff. + * Outside of that is illegal and must be IPv4. * 2. If last 3 bytes are 0, must be IPv4 * 3. If IPv6 in IPv4, handle as IPv4 * @@ -323,7 +324,11 @@ if (a[0] == 0 && a[1] == 0 && a[2] == htonl (0xffff)) mapped = 1; topnibble = ntohl((unsigned int)a[0]) >> 28; - if (topnibble < 2 || topnibble > 3 || mapped || + + azero = ntohl((unsigned int)a[0]) >> 16; + sitelocal = (azero >= 0xfec0 && azero <= 0xfeff) ? 1 : 0; + + if (((topnibble < 2 || topnibble > 3) && (!sitelocal)) || mapped || (a[1] == 0 && a[2] == 0 && a[3] == 0)) { /* IPv4 */ sin.sin_family = AF_INET; diff -Naur sysvinit-2.86.orig/src/reboot.h sysvinit-2.86/src/reboot.h --- sysvinit-2.86.orig/src/reboot.h 2004-06-09 05:47:45.000000000 -0700 +++ sysvinit-2.86/src/reboot.h 2009-01-07 11:07:06.000000000 -0800 @@ -32,5 +32,8 @@ # define BMAGIC_POWEROFF BMAGIC_HALT #endif +/* for kexec support */ +#define BMAGIC_KEXEC 0x45584543 + #define init_reboot(magic) reboot(magic) diff -Naur sysvinit-2.86.orig/src/shutdown.c sysvinit-2.86/src/shutdown.c --- sysvinit-2.86.orig/src/shutdown.c 2004-07-30 04:59:04.000000000 -0700 +++ sysvinit-2.86/src/shutdown.c 2009-01-07 11:09:43.000000000 -0800 @@ -102,7 +102,7 @@ void usage(void) { fprintf(stderr, - "Usage:\t shutdown [-akrhHPfnc] [-t secs] time [warning message]\n" + "Usage:\t shutdown [-akrhPHfFnc] [-t sec] time [warning message]\n" "\t\t -a: use /etc/shutdown.allow\n" "\t\t -k: don't really shutdown, only warn.\n" "\t\t -r: reboot after shutdown.\n" @@ -460,6 +460,7 @@ if (getuid() != 0) { fprintf(stderr, "shutdown: you must be root to do that!\n"); + usage(); exit(1); } strcpy(down_level, "1"); diff -Naur sysvinit-2.86.orig/src/utmp.c sysvinit-2.86/src/utmp.c --- sysvinit-2.86.orig/src/utmp.c 1999-06-09 04:11:33.000000000 -0700 +++ sysvinit-2.86/src/utmp.c 2009-01-07 11:11:29.000000000 -0800 @@ -47,6 +47,7 @@ int fd; struct utmp utmp; struct utsname uname_buf; + struct timeval tv; /* * Try to open the wtmp file. Note that we even try @@ -76,7 +77,9 @@ */ memset(&utmp, 0, sizeof(utmp)); #if defined(__GLIBC__) - gettimeofday(&utmp.ut_tv, NULL); + gettimeofday(&tv, NULL); + utmp.ut_tv.tv_sec = tv.tv_sec; + utmp.ut_tv.tv_usec = tv.tv_usec; #else time(&utmp.ut_time); #endif @@ -113,6 +116,7 @@ struct utmp utmp; struct utmp tmp; struct utmp *utmptr; + struct timeval tv; /* * Can't do much if UTMP_FILE is not present. @@ -144,7 +148,9 @@ utmp.ut_pid = pid; strncpy(utmp.ut_id, id, sizeof(utmp.ut_id)); #if defined(__GLIBC__) - gettimeofday(&utmp.ut_tv, NULL); + gettimeofday(&tv, NULL); + utmp.ut_tv.tv_sec = tv.tv_sec; + utmp.ut_tv.tv_usec = tv.tv_usec; #else time(&utmp.ut_time); #endif