From 5baf1e6226f9aa051b5570b655ed49b73ae10061 Mon Sep 17 00:00:00 2001 From: Jan Pazdziora Date: Wed, 22 Jun 2022 12:07:55 +0200 Subject: [PATCH] w: add --pids option to display the pid of the login and best processes. --- man/w.1 | 3 +++ src/w.c | 38 ++++++++++++++++++++++++++++++-------- testsuite/w.test/w.exp | 6 ++++++ 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/man/w.1 b/man/w.1 index 15a94dc1..0c1293cf 100644 --- a/man/w.1 +++ b/man/w.1 @@ -56,6 +56,9 @@ Display help text and exit. \fB\-i\fR, \fB\-\-ip\-addr\fR Display IP address instead of hostname for \fBfrom\fR field. .TP +\fB\-p\fR, \fB\-\-pids\fR +Display pid of the login process/the "what" process in the "what" field. +.TP \fB\-V\fR, \fB\-\-version\fR Display version information. .TP diff --git a/src/w.c b/src/w.c index 63f81c72..2ce2a2e4 100644 --- a/src/w.c +++ b/src/w.c @@ -357,7 +357,8 @@ static int find_best_proc( const char *restrict const tty, unsigned long long *restrict const jcpu, unsigned long long *restrict const pcpu, - char *cmdline) + char *cmdline, + pid_t *pid) { #define PIDS_GETINT(e) PIDS_VAL(EU_ ## e, s_int, reap->stacks[i], info) #define PIDS_GETUNT(e) PIDS_VAL(EU_ ## e, u_int, reap->stacks[i], info) @@ -372,6 +373,7 @@ static int find_best_proc( struct pids_info *info=NULL; struct pids_fetch *reap; enum pids_item items[] = { + PIDS_ID_PID, PIDS_ID_TGID, PIDS_TICS_BEGAN, PIDS_ID_EUID, @@ -382,7 +384,7 @@ static int find_best_proc( PIDS_TICS_ALL, PIDS_CMDLINE}; enum rel_items { - EU_TGID, EU_START, EU_EUID, EU_RUID, EU_TPGID, EU_PGRP, EU_TTY, + EU_PID, EU_TGID, EU_START, EU_EUID, EU_RUID, EU_TPGID, EU_PGRP, EU_TTY, EU_TICS_ALL, EU_CMDLINE}; *jcpu = 0; @@ -400,7 +402,7 @@ static int find_best_proc( line = get_tty_device(tty); - if (procps_pids_new(&info, items, 9) < 0) + if (procps_pids_new(&info, items, 10) < 0) xerrx(EXIT_FAILURE, _("Unable to create pid info structure")); if ((reap = procps_pids_reap(info, PIDS_FETCH_TASKS_ONLY)) == NULL) @@ -415,6 +417,7 @@ static int find_best_proc( if (!best_time) { best_time = PIDS_GETULL(START); strncpy(cmdline, PIDS_GETSTR(CMDLINE), MAX_CMD_WIDTH); + *pid = PIDS_GETULL(PID); *pcpu = PIDS_GETULL(TICS_ALL); } @@ -426,6 +429,7 @@ static int find_best_proc( secondbest_time = PIDS_GETULL(START); if (cmdline[0] == '-' && cmdline[1] == '\0') { strncpy(cmdline, PIDS_GETSTR(CMDLINE), MAX_CMD_WIDTH); + *pid = PIDS_GETULL(PID); *pcpu = PIDS_GETULL(TICS_ALL); } } @@ -438,6 +442,7 @@ static int find_best_proc( continue; best_time = PIDS_GETULL(START); strncpy(cmdline, PIDS_GETSTR(CMDLINE), MAX_CMD_WIDTH); + *pid = PIDS_GETULL(PID); *pcpu = PIDS_GETULL(TICS_ALL); } procps_pids_unref(&info); @@ -450,13 +455,16 @@ static int find_best_proc( static void showinfo( utmp_t * u, int formtype, int maxcmd, int from, - const int userlen, const int fromlen, const int ip_addresses) + const int userlen, const int fromlen, const int ip_addresses, + const int pids) { unsigned long long jcpu, pcpu; unsigned i; char uname[UT_NAMESIZE + 1] = "", tty[5 + UT_LINESIZE + 1] = "/dev/"; long hertz; char cmdline[MAX_CMD_WIDTH + 1]; + pid_t best_pid; + int pids_length = 0; strcpy(cmdline, "-"); @@ -468,7 +476,7 @@ static void showinfo( else tty[i + 5] = '\0'; - if (find_best_proc(u, tty + 5, &jcpu, &pcpu, cmdline) == 0) + if (find_best_proc(u, tty + 5, &jcpu, &pcpu, cmdline, &best_pid) == 0) /* * just skip if stale utmp entry (i.e. login proc doesn't * exist). If there is a desire a cmdline flag could be @@ -513,6 +521,14 @@ static void showinfo( else print_time_ival7(idletime(tty), 0, stdout); } + if (pids) { + pids_length = printf(" %d/%d", u->ut_pid, best_pid); + if (pids_length > maxcmd) { + maxcmd = 0; + } else if (pids_length > 0) { + maxcmd -= pids_length; + } + } printf(" %.*s\n", maxcmd, cmdline); } @@ -529,6 +545,7 @@ static void __attribute__ ((__noreturn__)) fputs(_(" -f, --from show remote hostname field\n"),out); fputs(_(" -o, --old-style old style output\n"),out); fputs(_(" -i, --ip-addr display IP address instead of hostname (if possible)\n"), out); + fputs(_(" -p, --pids show the PID(s) of processes in WHAT\n"), out); fputs(USAGE_SEPARATOR, out); fputs(_(" --help display this help and exit\n"), out); fputs(USAGE_VERSION, out); @@ -553,6 +570,7 @@ int main(int argc, char **argv) int longform = 1; int from = 1; int ip_addresses = 0; + int pids = 0; enum { HELP_OPTION = CHAR_MAX + 1 @@ -565,6 +583,7 @@ int main(int argc, char **argv) {"from", no_argument, NULL, 'f'}, {"old-style", no_argument, NULL, 'o'}, {"ip-addr", no_argument, NULL, 'i'}, + {"pids", no_argument, NULL, 'p'}, {"help", no_argument, NULL, HELP_OPTION}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0} @@ -583,7 +602,7 @@ int main(int argc, char **argv) #endif while ((ch = - getopt_long(argc, argv, "husfoVi", longopts, NULL)) != -1) + getopt_long(argc, argv, "husfoVip", longopts, NULL)) != -1) switch (ch) { case 'h': header = 0; @@ -607,6 +626,9 @@ int main(int argc, char **argv) ip_addresses = 1; from = 1; break; + case 'p': + pids = 1; + break; case HELP_OPTION: usage(stdout); default: @@ -686,7 +708,7 @@ int main(int argc, char **argv) continue; if (!strncmp(u->ut_user, user, UT_NAMESIZE)) showinfo(u, longform, maxcmd, from, userlen, - fromlen, ip_addresses); + fromlen, ip_addresses, pids); } } else { for (;;) { @@ -701,7 +723,7 @@ int main(int argc, char **argv) continue; if (*u->ut_user) showinfo(u, longform, maxcmd, from, userlen, - fromlen, ip_addresses); + fromlen, ip_addresses, pids); } } #ifdef HAVE_UTMPX_H diff --git a/testsuite/w.test/w.exp b/testsuite/w.test/w.exp index 5f1064d7..f0da8034 100644 --- a/testsuite/w.test/w.exp +++ b/testsuite/w.test/w.exp @@ -17,10 +17,12 @@ set w_login "\(\\d+\[A-Z\]\[a-z\]{2}\\d+\|\[A-Z\]\[a-z\]{2}\\d+\|\\d+:\\d+\)" set w_idle "\(\\?xdm\\?\|\\?\|\\d+days\|\\d+:\\d+m?\|\\d+.\\d+s\)" set w_ival7 "\(\\?\|\\d+days\|\\d+:\\d+m?\|\\d+.\\d+s\)" set w_what "\[A-Za-z0-9_\/\\-\]+" +set w_pids "\\d+/\\d+" set w_std_userlines "\(${w_user}\\s+${w_tty}\\s+${w_login}\\s+${w_idle}\\s+${w_ival7}\\s+${w_ival7}\\s+${w_what}\\s*\)*" set w_short_userlines "\(${w_user}\\s+${w_tty}\\s+${w_idle}\\s+${w_what}\\s*\)*" set w_from_userlines "\(${w_user}\\s+${w_tty}\\s+${w_from}\\s+${w_login}\\s+${w_idle}\\s+${w_ival7}\\s+${w_ival7}\\s+${w_what}\\s*\)*" set w_fromshort_userlines "\(${w_user}\\s+${w_tty}\\s+${w_from}\\s+${w_idle}\\s+${w_what}\\s*\)*" +set w_pid_userlines "\(${w_user}\\s+${w_tty}\\s+${w_idle}\\s+%{w_pids}\s+${w_what}\\s*\)*" set test "w with no arguments" spawn $w @@ -51,3 +53,7 @@ set test "w with short and from flags" spawn $w -sf expect_pass "$test" "^${w_fromshort_header}${w_fromshort_userlines}" +set test "w with pids display" +spawn $w -p +expect_pass "$test" "^${w_std_header}${w_pid_userlines}" +