]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
last: Add -T option for tab-separated output
authorTrag Date <101431599+tragdate@users.noreply.github.com>
Wed, 23 Aug 2023 01:43:04 +0000 (04:43 +0300)
committerGitHub <noreply@github.com>
Wed, 23 Aug 2023 01:43:04 +0000 (04:43 +0300)
This commit introduces a -T option to the last command, allowing for tab-separated output. This change significantly improves the usability of last in conjunction with awk, enabling more efficient and intuitive parsing of command output.

Signed-off-by: Cristian Zmole <chiarel@tragdate.ninja>
login-utils/last.c

index eaebc1fe6a0930ca508d4b52d9bac9ca16b41cdb..dced3f86f07849020ec8059fadddd23c4beb83e4 100644 (file)
@@ -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 */
@@ -520,24 +521,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)
@@ -584,6 +585,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);
@@ -978,6 +980,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 }
        };
@@ -995,8 +998,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);
 
@@ -1060,6 +1064,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);
                }