summaryrefslogtreecommitdiff
path: root/src/who.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2004-06-22 14:56:46 +0000
committerJim Meyering <jim@meyering.net>2004-06-22 14:56:46 +0000
commitf581b96e7fa8342329a82d0cd88280917d8f701c (patch)
tree67cebfb2e32083bb25a85f885f67b1f36ec41f90 /src/who.c
parentf1317a406025f5ceaf34709b370a53062f54ee8b (diff)
downloadcoreutils-f581b96e7fa8342329a82d0cd88280917d8f701c.tar.xz
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.
Diffstat (limited to 'src/who.c')
-rw-r--r--src/who.c41
1 files changed, 28 insertions, 13 deletions
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: