From f581b96e7fa8342329a82d0cd88280917d8f701c Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Tue, 22 Jun 2004 14:56:46 +0000 Subject: The 2004-06-19 fix for who and pinky was incomplete, as ctime has undefined behavior if the year precedes -999 or follows 9999. Since we have to stop using ctime anyway, we might as well use strftime and fix the FIXME, and support internationalized dates. Include "hard-locale.h". (time_format, time_format_width): New vars. (time_string, print_line): Use them. (main): Set them. (time_string): Use localtime + strftime instead of ctime, to avoid problems with years before -999 or after 9999. --- src/who.c | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) (limited to 'src/who.c') diff --git a/src/who.c b/src/who.c index f8da4737e..49209a562 100644 --- a/src/who.c +++ b/src/who.c @@ -33,6 +33,7 @@ #include "readutmp.h" #include "error.h" +#include "hard-locale.h" #include "inttostr.h" #include "quote.h" #include "vasprintf.h" @@ -168,6 +169,11 @@ static int need_users; /* If nonzero, display info only for the controlling tty */ static int my_line_only; +/* The strftime format to use for login times, and its expected + output width. */ +static char const *time_format; +static int time_format_width; + /* for long options with no corresponding short option, use enum */ enum { @@ -222,31 +228,28 @@ idle_string (time_t when) return _(" old "); } -/* Return a standard time string, "mon dd hh:mm" - FIXME: handle localization */ +/* Return a time string. */ static const char * time_string (const STRUCT_UTMP *utmp_ent) { + static char buf[INT_STRLEN_BOUND (intmax_t) + sizeof "-%m-%d %H:%M"]; + /* Don't take the address of UT_TIME_MEMBER directly. Ulrich Drepper wrote: ``... GNU libc (and perhaps other libcs as well) have extended utmp file formats which do not use a simple time_t ut_time field. In glibc, ut_time is a macro which selects for backward compatibility the tv_sec member of a struct timeval value.'' */ - time_t tm = UT_TIME_MEMBER (utmp_ent); + time_t t = UT_TIME_MEMBER (utmp_ent); + struct tm *tmp = localtime (&t); - char *ptr = ctime (&tm); - if (ptr) + if (tmp) { - ptr += 4; - ptr[12] = '\0'; + strftime (buf, sizeof buf, time_format, tmp); + return buf; } else - { - static char buf[INT_BUFSIZE_BOUND (intmax_t)]; - ptr = (TYPE_SIGNED (time_t) ? imaxtostr (tm, buf) : umaxtostr (tm, buf)); - } - return ptr; + return TYPE_SIGNED (time_t) ? imaxtostr (t, buf) : umaxtostr (t, buf); } /* Print formatted output line. Uses mostly arbitrary field sizes, probably @@ -286,7 +289,7 @@ print_line (const char *user, const char state, const char *line, "%-8s" "%s" " %-12s" - " %-12s" + " %-*s" "%s" "%s" " %-8s" @@ -295,6 +298,7 @@ print_line (const char *user, const char state, const char *line, user ? user : " .", include_mesg ? mesg : "", line, + time_format_width, time_str, x_idle, x_pid, @@ -796,6 +800,17 @@ main (int argc, char **argv) short_output = 0; } + if (hard_locale (LC_TIME)) + { + time_format = "%Y-%m-%d %H:%M"; + time_format_width = 4 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2; + } + else + { + time_format = "%b %e %H:%M"; + time_format_width = 3 + 1 + 2 + 1 + 2 + 1 + 2; + } + switch (argc - optind) { case -1: -- cgit v1.2.3-54-g00ecf