mirror of
https://git.savannah.gnu.org/git/coreutils.git
synced 2025-09-10 07:59:52 +02:00
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.
This commit is contained in:
41
src/who.c
41
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:
|
||||
|
||||
Reference in New Issue
Block a user