Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions man/wtmpdb.8.xml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,17 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-L, --legacy</option>
</term>
<listitem>
<para>
Display session duration with precision in minutes instead of seconds,
which is the default setting for the legacy 'last' command.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-n, --limit</option> <replaceable>N</replaceable>
Expand Down
24 changes: 22 additions & 2 deletions src/wtmpdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ static int iflag = 0;
static int jflag = 0;
static int wflag = 0;
static int xflag = 0;
static int legacy = 0;
static const int name_len = 8; /* LAST_LOGIN_LEN */
static int login_fmt = TIMEFMT_SHORT;
static int login_len = 16; /* 16 = short, 24 = full */
Expand Down Expand Up @@ -283,6 +284,16 @@ calc_time_length(char *dst, size_t dstlen, uint64_t start, uint64_t stop)
int hours = (secs / 3600) % 24;
uint64_t days = secs / 86400;

if (!legacy) {
secs %= 60;
if (days)
snprintf (dst, dstlen, "(%" PRId64 "+%02d:%02d:%02lu)", days, hours, mins, secs);
else if (hours)
snprintf (dst, dstlen, " (%02d:%02d:%02lu)", hours, mins, secs);
else
snprintf (dst, dstlen, " (00:%02d:%02lu)", mins, secs);
return;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation looks good in github, but not if you look at the file with less or vi or any other editor.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, probably. I haven’t found any documentation about it (I saw a mix of tabs and spaces), so I decided to use 2 spaces to get it properly aligned at least with the surrounding lines. Actually, I prefer tabs with a tab width of 4 and wrote the changes with vim ;-).

}
if (days)
snprintf (dst, dstlen, "(%" PRId64 "+%02d:%02d)", days, hours, mins);
else if (hours)
Expand Down Expand Up @@ -657,6 +668,7 @@ usage (int retval)
fputs (" -F, --fulltimes Display full times and dates\n", output);
fputs (" -i, --ip Translate hostnames to IP addresses\n", output);
fputs (" -j, --json Generate JSON output\n", output);
fputs (" -L, --legacy Session duration precision in minutes instead of seconds\n", output);
fputs (" -n, --limit N, -N Display only first N entries\n", output);
fputs (" -p, --present TIME Display who was present at TIME\n", output);
fputs (" -R, --nohostname Don't display hostname\n", output);
Expand Down Expand Up @@ -774,6 +786,7 @@ main_last (int argc, char **argv)
{"fullnames", no_argument, NULL, 'w'},
{"fulltimes", no_argument, NULL, 'F'},
{"ip", no_argument, NULL, 'i'},
{"legacy", no_argument, NULL, 'L'},
{"limit", required_argument, NULL, 'n'},
{"present", required_argument, NULL, 'p'},
{"nohostname", no_argument, NULL, 'R'},
Expand All @@ -789,7 +802,7 @@ main_last (int argc, char **argv)
char *error = NULL;
int c;

while ((c = getopt_long (argc, argv, "0123456789adf:Fijn:p:RSs:t:wx",
while ((c = getopt_long (argc, argv, "0123456789adf:FijLn:p:RSs:t:wx",
longopts, NULL)) != -1)
{
switch (c)
Expand Down Expand Up @@ -827,6 +840,9 @@ main_last (int argc, char **argv)
case 'j':
jflag = 1;
break;
case 'L':
legacy = 1;
break;
case 'n':
maxentries = strtoul (optarg, NULL, 10);
break;
Expand Down Expand Up @@ -1280,7 +1296,11 @@ main (int argc, char **argv)
};
int c;

if (strcmp (basename(argv[0]), "last") == 0)
if (strcmp (basename(argv[0]), "last") == 0) {
legacy = 1;
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's confusing for users, if called via the symlink last it runs in legacy, but as wtmpdb command in non legacy mode.
This should always be the same.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just in case someone insists on compatibility with the legacy tool. Intention is, that sooner or later the legacy last goes away and and wtmpdb gets linked to it. And to avoid any surprise ... However, if one calls the modern version of last (e.g. wlast), it behaves intended (uses same defaults as wtmpdb last does).

return main_last (argc, argv);
}
if (strcmp (basename(argv[0]), "wlast") == 0)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wlast is nowhere documented. And I don't think we should introduce more "compat" symlinks for things which didn't exist before.
I would just use last with the new behavior.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a modern last didn’t exist before, and on most distributions the legacy last is still installed (on Ubuntu, for example, it comes as part of the util-linux package). Since many users and admins are lazy (and don’t like typing long command lines), I wanted something similarly short — like last — but with modern behavior (essentially wtmpdb last) that can coexist with the legacy tool. So I simply prefixed it with w (perhaps because adding a suffix like ng felt too long ;-)) and ship it as part of our wtmp package, which gets automatically installed on all containers/hosts w/o getting into trouble with e.g. the util-linux package.

return main_last (argc, argv);
else if (argc == 1)
usage (EXIT_SUCCESS);
Expand Down