]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - login-utils/last.c
scriptreplay: cleanup usage()
[thirdparty/util-linux.git] / login-utils / last.c
index d230deb7c7735cc73e6750440ea2b6308588c1bd..20d69e9b581db2e6db835ecd247dfcdeca8a727a 100644 (file)
@@ -145,8 +145,8 @@ static struct last_timefmt timefmts[] = {
        },
        [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
        }
@@ -349,7 +349,7 @@ static int time_formatter(int fmt, char *dst, size_t dlen, time_t *when)
                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();
@@ -394,8 +394,7 @@ static int list(const struct last_control *ctl, struct utmpx *p, time_t logout_t
        /*
         *      uucp and ftp have special-type entries
         */
-       utline[0] = 0;
-       strncat(utline, p->ut_line, sizeof(p->ut_line));
+       mem2strcpy(utline, p->ut_line, sizeof(p->ut_line), sizeof(utline));
        if (strncmp(utline, "ftp", 3) == 0 && isdigit(utline[3]))
                utline[3] = 0;
        if (strncmp(utline, "uucp", 4) == 0 && isdigit(utline[4]))
@@ -435,7 +434,7 @@ static int list(const struct last_control *ctl, struct utmpx *p, time_t logout_t
                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;
@@ -454,9 +453,13 @@ static int list(const struct last_control *ctl, struct utmpx *p, time_t logout_t
                        sprintf(length, "running");
                }
        } else if (days) {
-               sprintf(length, "(%d+%02d:%02d)", days, hours, mins);
-       } else {
+               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, " (-00:%02d)", abs(mins));  /* mins always shown as positive (w/o minus sign!) even if secs < 0 */
        }
 
        switch(what) {
@@ -504,15 +507,8 @@ static int list(const struct last_control *ctl, struct utmpx *p, time_t logout_t
        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) {
@@ -560,8 +556,9 @@ static int list(const struct last_control *ctl, struct utmpx *p, time_t logout_t
 }
 
 
-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);
@@ -588,9 +585,8 @@ static void __attribute__((__noreturn__)) usage(const struct last_control *ctl,
                "                               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);
 }
@@ -598,11 +594,12 @@ static void __attribute__((__noreturn__)) usage(const struct last_control *ctl,
 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[sizeof(ut->ut_user) - 1] = '\0';
        pw = getpwnam(ut->ut_user);
        if (!pw)
                return 1;
@@ -941,7 +938,7 @@ int main(int argc, char **argv)
        setlocale(LC_ALL, "");
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
-       atexit(close_stdout);
+       close_stdout_atexit();
        /*
         * Which file do we want to read?
         */
@@ -953,11 +950,10 @@ int main(int argc, char **argv)
 
                switch(c) {
                case 'h':
-                       usage(&ctl, stdout);
+                       usage(&ctl);
                        break;
                case 'V':
-                       printf(UTIL_LINUX_VERSION);
-                       return EXIT_SUCCESS;
+                       print_version(EXIT_SUCCESS);
                case 'R':
                        ctl.showhost = 0;
                        break;