diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-14 19:33:34 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-14 19:33:34 +0000 |
commit | 1272be04be0cb803eec87f602edb2e3e6f111aea (patch) | |
tree | bce17f6478cdd9f3c4ec3d751135dc42786d6a56 /login-utils/last.c | |
parent | Releasing progress-linux version 2.39.3-11~progress7.99u1. (diff) | |
download | util-linux-1272be04be0cb803eec87f602edb2e3e6f111aea.tar.xz util-linux-1272be04be0cb803eec87f602edb2e3e6f111aea.zip |
Merging upstream version 2.40.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'login-utils/last.c')
-rw-r--r-- | login-utils/last.c | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/login-utils/last.c b/login-utils/last.c index 37c6abe..f5a9fec 100644 --- a/login-utils/last.c +++ b/login-utils/last.c @@ -95,6 +95,7 @@ struct last_control { time_t until; /* at what time to stop displaying the file */ time_t present; /* who where present at time_t */ unsigned int time_fmt; /* time format */ + char separator; /* output separator */ }; /* Double linked list of struct utmp's */ @@ -111,6 +112,7 @@ enum { R_NORMAL, /* Normal */ R_NOW, /* Still logged in */ R_REBOOT, /* Reboot record. */ + R_REBOOT_CRASH, /* Reboot record without matching shutdown */ R_PHANTOM, /* No logout record but session is stale. */ R_TIMECHANGE /* NEW_TIME or OLD_TIME */ }; @@ -349,7 +351,10 @@ static int time_formatter(int fmt, char *dst, size_t dlen, time_t *when) { char buf[CTIME_BUFSIZ]; - ctime_r(when, buf); + if (!ctime_r(when, buf)) { + ret = -1; + break; + } snprintf(dst, dlen, "%s", buf); ret = rtrim_whitespace((unsigned char *) dst); break; @@ -469,6 +474,7 @@ static int list(const struct last_control *ctl, struct utmpx *p, time_t logout_t switch(what) { case R_CRASH: + case R_REBOOT_CRASH: snprintf(logouttime, sizeof(logouttime), "- crash"); break; case R_DOWN: @@ -518,24 +524,24 @@ static int list(const struct last_control *ctl, struct utmpx *p, time_t logout_t if (ctl->showhost) { if (!ctl->altlist) { len = snprintf(final, sizeof(final), - "%-8.*s %-12.12s %-16.*s %-*.*s %-*.*s %s\n", - ctl->name_len, p->ut_user, utline, - ctl->domain_len, domain, - fmt->in_len, fmt->in_len, logintime, fmt->out_len, fmt->out_len, - logouttime, length); + "%-8.*s%c%-12.12s%c%-16.*s%c%-*.*s%c%-*.*s%c%s\n", + ctl->name_len, p->ut_user, ctl->separator, utline, ctl->separator, + ctl->domain_len, domain, ctl->separator, + fmt->in_len, fmt->in_len, logintime, ctl->separator, fmt->out_len, fmt->out_len, + logouttime, ctl->separator, length); } else { len = snprintf(final, sizeof(final), - "%-8.*s %-12.12s %-*.*s %-*.*s %-12.12s %s\n", - ctl->name_len, p->ut_user, utline, - fmt->in_len, fmt->in_len, logintime, fmt->out_len, fmt->out_len, - logouttime, length, domain); + "%-8.*s%c%-12.12s%c%-*.*s%c%-*.*s%c%-12.12s%c%s\n", + ctl->name_len, p->ut_user, ctl->separator, utline, ctl->separator, + fmt->in_len, fmt->in_len, logintime, ctl->separator, fmt->out_len, fmt->out_len, + logouttime, ctl->separator, length, ctl->separator, domain); } } else len = snprintf(final, sizeof(final), - "%-8.*s %-12.12s %-*.*s %-*.*s %s\n", - ctl->name_len, p->ut_user, utline, - fmt->in_len, fmt->in_len, logintime, fmt->out_len, fmt->out_len, - logouttime, length); + "%-8.*s%c%-12.12s%c%-*.*s%c%-*.*s%c%s\n", + ctl->name_len, p->ut_user, ctl->separator, utline, ctl->separator, + fmt->in_len, fmt->in_len, logintime, ctl->separator, fmt->out_len, fmt->out_len, + logouttime, ctl->separator, length); #if defined(__GLIBC__) # if (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0) @@ -582,6 +588,7 @@ static void __attribute__((__noreturn__)) usage(const struct last_control *ctl) fputs(_(" -R, --nohostname don't display the hostname field\n"), out); fputs(_(" -s, --since <time> display the lines since the specified time\n"), out); fputs(_(" -t, --until <time> display the lines until the specified time\n"), out); + fputs(_(" -T, --tab-separated use tabs as delimiters\n"), out); fputs(_(" -p, --present <time> display who were present at the specified time\n"), out); fputs(_(" -w, --fullnames display full user and domain names\n"), out); fputs(_(" -x, --system display system shutdown entries and run level changes\n"), out); @@ -589,8 +596,8 @@ static void __attribute__((__noreturn__)) usage(const struct last_control *ctl) " notime|short|full|iso\n"), out); fputs(USAGE_SEPARATOR, out); - printf(USAGE_HELP_OPTIONS(22)); - printf(USAGE_MAN_TAIL("last(1)")); + fprintf(out, USAGE_HELP_OPTIONS(22)); + fprintf(out, USAGE_MAN_TAIL("last(1)")); exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } @@ -786,7 +793,10 @@ static void process_wtmp_file(const struct last_control *ctl, break; case BOOT_TIME: strcpy(ut.ut_line, "system boot"); - quit = list(ctl, &ut, lastdown, R_REBOOT); + if (lastdown > lastboot && lastdown != currentdate) + quit = list(ctl, &ut, lastboot, R_REBOOT_CRASH); + else + quit = list(ctl, &ut, lastdown, R_REBOOT); lastboot = ut.ut_tv.tv_sec; down = 1; break; @@ -973,6 +983,7 @@ int main(int argc, char **argv) { "ip", no_argument, NULL, 'i' }, { "fulltimes", no_argument, NULL, 'F' }, { "fullnames", no_argument, NULL, 'w' }, + { "tab-separated", no_argument, NULL, 'T' }, { "time-format", required_argument, NULL, OPT_TIME_FORMAT }, { NULL, 0, NULL, 0 } }; @@ -990,8 +1001,9 @@ int main(int argc, char **argv) * Which file do we want to read? */ ctl.lastb = strcmp(program_invocation_short_name, "lastb") == 0 ? 1 : 0; + ctl.separator = ' '; while ((c = getopt_long(argc, argv, - "hVf:n:RxadFit:p:s:0123456789w", long_opts, NULL)) != -1) { + "hVf:n:RxadFit:p:s:T0123456789w", long_opts, NULL)) != -1) { err_exclusive_options(c, long_opts, excl, excl_st); @@ -1055,6 +1067,9 @@ int main(int argc, char **argv) case OPT_TIME_FORMAT: ctl.time_fmt = which_time_format(optarg); break; + case 'T': + ctl.separator = '\t'; + break; default: errtryhelp(EXIT_FAILURE); } |