},
[LAST_TIMEFTM_ISO8601] = {
.name = "iso",
- .in_len = 24,
- .out_len = 26,
+ .in_len = 25,
+ .out_len = 27,
.in_fmt = LAST_TIMEFTM_ISO8601,
.out_fmt = LAST_TIMEFTM_ISO8601
}
ret = rtrim_whitespace((unsigned char *) dst);
break;
case LAST_TIMEFTM_ISO8601:
- ret = strtime_iso(when, ISO_8601_DATE|ISO_8601_TIME|ISO_8601_TIMEZONE, dst, dlen);
+ ret = strtime_iso(when, ISO_TIMESTAMP_T, dst, dlen);
break;
default:
abort();
* uucp and ftp have special-type entries
*/
utline[0] = 0;
- strncat(utline, p->ut_line, sizeof(p->ut_line));
+ strncat(utline, p->ut_line, sizeof(utline) - 1);
if (strncmp(utline, "ftp", 3) == 0 && isdigit(utline[3]))
utline[3] = 0;
if (strncmp(utline, "uucp", 4) == 0 && isdigit(utline[4]))
errx(EXIT_FAILURE, _("preallocation size exceeded"));
/* log-out time */
- secs = logout_time - utmp_time;
+ secs = logout_time - utmp_time; /* Under strange circumstances, secs < 0 can happen */
mins = (secs / 60) % 60;
hours = (secs / 3600) % 24;
days = secs / 86400;
sprintf(length, "running");
}
} else if (days) {
- sprintf(length, "(%d+%02d:%02d)", days, hours, mins);
+ sprintf(length, "(%d+%02d:%02d)", days, abs(hours), abs(mins)); /* hours and mins always shown as positive (w/o minus sign!) even if secs < 0 */
+ } else if (hours) {
+ sprintf(length, " (%02d:%02d)", hours, abs(mins)); /* mins always shown as positive (w/o minus sign!) even if secs < 0 */
+ } else if (secs >= 0) {
+ sprintf(length, " (%02d:%02d)", hours, mins);
} else {
- sprintf(length, " (%02d:%02d)", hours, mins);
+ sprintf(length, " (-00:%02d)", abs(mins)); /* mins always shown as positive (w/o minus sign!) even if secs < 0 */
}
switch(what) {
r = -1;
if (ctl->usedns || ctl->useip)
r = dns_lookup(domain, sizeof(domain), ctl->useip, (int32_t*)p->ut_addr_v6);
- if (r < 0) {
- size_t sz = sizeof(p->ut_host);
-
- if (sz > sizeof(domain))
- sz = sizeof(domain);
-
- xstrncpy(domain, p->ut_host, sz);
- }
-
+ if (r < 0)
+ mem2strcpy(domain, p->ut_host, sizeof(p->ut_host), sizeof(domain));
if (ctl->showhost) {
if (!ctl->altlist) {
}
-static void __attribute__((__noreturn__)) usage(const struct last_control *ctl, FILE *out)
+static void __attribute__((__noreturn__)) usage(const struct last_control *ctl)
{
+ FILE *out = stdout;
fputs(USAGE_HEADER, out);
fprintf(out, _(
" %s [options] [<username>...] [<tty>...]\n"), program_invocation_short_name);
" notime|short|full|iso\n"), out);
fputs(USAGE_SEPARATOR, out);
- fputs(USAGE_HELP, out);
- fputs(USAGE_VERSION, out);
- fprintf(out, USAGE_MAN_TAIL("last(1)"));
+ printf(USAGE_HELP_OPTIONS(22));
+ printf(USAGE_MAN_TAIL("last(1)"));
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
static int is_phantom(const struct last_control *ctl, struct utmpx *ut)
{
struct passwd *pw;
- char path[32];
+ char path[sizeof(ut->ut_line) + 16];
int ret = 0;
if (ut->ut_tv.tv_sec < ctl->boot_time.tv_sec)
return 1;
+ ut->ut_user[__UT_NAMESIZE - 1] = '\0';
pw = getpwnam(ut->ut_user);
if (!pw)
return 1;
c = whydown;
quit = list(ctl, &ut, lastboot, c);
}
- /* FALLTHRU */
+ /* fallthrough */
case DEAD_PROCESS:
/*
switch(c) {
case 'h':
- usage(&ctl, stdout);
+ usage(&ctl);
break;
case 'V':
printf(UTIL_LINUX_VERSION);