w: use environment to set user and from/host column widths

A patch from Debian.

Bug-Debian: http://bugs.debian.org/396423
Bug-Debian: http://bugs.debian.org/341439
Backported-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
Craig Small 2009-11-24 11:00:44 +11:00 committed by Craig Small
parent 88f485e20a
commit 99bebff06a
2 changed files with 45 additions and 18 deletions

10
w.1
View File

@ -1,6 +1,6 @@
.\" -*-Nroff-*- .\" -*-Nroff-*-
.\" .\"
.TH W 1 "8 Dec 1993 " " " "Linux User's Manual" .TH W 1 "5 October 2009 " " " "Linux User's Manual"
.SH NAME .SH NAME
w \- Show who is logged on and what they are doing. w \- Show who is logged on and what they are doing.
.SH SYNOPSIS .SH SYNOPSIS
@ -61,6 +61,14 @@ Old style output. Prints blank space for idle times less than one minute.
.B "user " .B "user "
Show information about the specified user only. Show information about the specified user only.
.SH ENVIRONMENT
.TP
PROCPS_USERLEN
Override the default width of the username column. Defaults to 8.
.TP
PROCPS_FROMLEN
Override the default width of the from column. Defaults to 16.
.SH FILES .SH FILES
.TP .TP
.I /var/run/utmp .I /var/run/utmp

53
w.c
View File

@ -45,20 +45,19 @@ typedef struct utmp utmp_t;
/* Uh... same thing as UT_NAMESIZE */ /* Uh... same thing as UT_NAMESIZE */
#define USERSZ (sizeof u->ut_user) #define USERSZ (sizeof u->ut_user)
/* Arbitary setting, not too big for the screen, max host size */
#define HOSTSZ 40
/* This routine is careful since some programs leave utmp strings /* This routine is careful since some programs leave utmp strings
* unprintable. Always outputs at least 16 chars padded with spaces * unprintable. Always outputs at least fromlen chars padded with spaces
* on the right if necessary. * on the right if necessary.
*/ */
static void print_host(const char *restrict host, int len) { static void print_host(const char *restrict host, int len, const int fromlen) {
const char *last; const char *last;
int width = 0; int width = 0;
/* FIXME: there should really be a way to configure this... */ if (len > fromlen) len = fromlen;
/* for now, we'll just limit it to the 16 that the libc5 version
* of utmp uses.
*/
if (len > 16) len = 16;
last = host + len; last = host + len;
for ( ; host < last ; host++){ for ( ; host < last ; host++){
if (isprint(*host) && *host != ' ') { if (isprint(*host) && *host != ' ') {
@ -69,7 +68,8 @@ static void print_host(const char *restrict host, int len) {
} }
} }
// space-fill, and a '-' too if needed to ensure the column exists // space-fill, and a '-' too if needed to ensure the column exists
if(width < 16) fputs("- "+width, stdout); while(width++ < fromlen)
fputc(' ',stdout);
} }
/***** compact 7 char format for time intervals (belongs in libproc?) */ /***** compact 7 char format for time intervals (belongs in libproc?) */
@ -181,7 +181,7 @@ static const proc_t *getproc(const utmp_t *restrict const u, const char *restric
/***** showinfo */ /***** showinfo */
static void showinfo(utmp_t *u, int formtype, int maxcmd, int from) { static void showinfo(utmp_t *u, int formtype, int maxcmd, int from, const int userlen, const int fromlen) {
unsigned long long jcpu; unsigned long long jcpu;
int ut_pid_found; int ut_pid_found;
unsigned i; unsigned i;
@ -206,9 +206,9 @@ static void showinfo(utmp_t *u, int formtype, int maxcmd, int from) {
strncpy(uname, u->ut_user, USERSZ); /* force NUL term for printf */ strncpy(uname, u->ut_user, USERSZ); /* force NUL term for printf */
if (formtype) { if (formtype) {
printf("%-9.8s%-9.8s", uname, u->ut_line); printf("%-*.*s%-9.8s", userlen+1, userlen, uname, u->ut_line);
if (from) if (from)
print_host(u->ut_host, sizeof u->ut_host); print_host(u->ut_host, sizeof u->ut_host, fromlen);
print_logintime(u->ut_time, stdout); print_logintime(u->ut_time, stdout);
if (*u->ut_line == ':') /* idle unknown for xdm logins */ if (*u->ut_line == ':') /* idle unknown for xdm logins */
printf(" ?xdm? "); printf(" ?xdm? ");
@ -221,9 +221,9 @@ static void showinfo(utmp_t *u, int formtype, int maxcmd, int from) {
} else } else
printf(" ? "); printf(" ? ");
} else { } else {
printf("%-9.8s%-9.8s", u->ut_user, u->ut_line); printf("%-*.*s%-9.8s", userlen+1, userlen, u->ut_user, u->ut_line);
if (from) if (from)
print_host(u->ut_host, sizeof u->ut_host); print_host(u->ut_host, sizeof u->ut_host, fromlen);
if (*u->ut_line == ':') /* idle unknown for xdm logins */ if (*u->ut_line == ':') /* idle unknown for xdm logins */
printf(" ?xdm? "); printf(" ?xdm? ");
else else
@ -246,6 +246,9 @@ int main(int argc, char **argv) {
utmp_t *u; utmp_t *u;
struct winsize win; struct winsize win;
int header=1, longform=1, from=1, args, maxcmd=80, ch; int header=1, longform=1, from=1, args, maxcmd=80, ch;
int userlen = 8;
int fromlen = 16;
char *env_var;
#ifndef W_SHOWFROM #ifndef W_SHOWFROM
from = 0; from = 0;
@ -276,6 +279,22 @@ int main(int argc, char **argv) {
if ((argv[optind])) if ((argv[optind]))
user = (argv[optind]); user = (argv[optind]);
/* Get user field length from environment */
if ( (env_var = getenv("PROCPS_USERLEN")) != NULL) {
userlen = atoi(env_var);
if (userlen < 8 || userlen > USERSZ) {
fprintf(stderr, "User length environment PROCPS_USERLEN must be between 8 and %d, ignoring.\n", USERSZ);
userlen=8;
}
}
/* Get from field length from environment */
if ( (env_var = getenv("PROCPS_FROMLEN")) != NULL) {
fromlen = atoi(env_var);
if (fromlen < 8 || fromlen > HOSTSZ) {
fprintf(stderr, "From length environment PROCPS_FROMLEN must be between 8 and %d, ignoring.\n", HOSTSZ);
fromlen=16;
}
}
if (ioctl(1, TIOCGWINSZ, &win) != -1 && win.ws_col > 0) if (ioctl(1, TIOCGWINSZ, &win) != -1 && win.ws_col > 0)
maxcmd = win.ws_col; maxcmd = win.ws_col;
else if (p = getenv("COLUMNS")) else if (p = getenv("COLUMNS"))
@ -286,7 +305,7 @@ int main(int argc, char **argv) {
fprintf(stderr, "%d column window is too narrow\n", maxcmd); fprintf(stderr, "%d column window is too narrow\n", maxcmd);
exit(1); exit(1);
} }
maxcmd -= 29 + (from ? 16 : 0) + (longform ? 20 : 0); maxcmd -= 21 + userlen + (from ? fromlen : 0) + (longform ? 20 : 0);
if (maxcmd < 3) if (maxcmd < 3)
fprintf(stderr, "warning: screen width %d suboptimal.\n", win.ws_col); fprintf(stderr, "warning: screen width %d suboptimal.\n", win.ws_col);
@ -294,7 +313,7 @@ int main(int argc, char **argv) {
if (header) { /* print uptime and headers */ if (header) { /* print uptime and headers */
print_uptime(); print_uptime();
printf("USER TTY "); printf("%-*s TTY ",userlen,"USER");
if (from) if (from)
printf("FROM "); printf("FROM ");
if (longform) if (longform)
@ -310,14 +329,14 @@ int main(int argc, char **argv) {
u = getutent(); u = getutent();
if (unlikely(!u)) break; if (unlikely(!u)) break;
if (u->ut_type != USER_PROCESS) continue; if (u->ut_type != USER_PROCESS) continue;
if (!strncmp(u->ut_user, user, USERSZ)) showinfo(u, longform, maxcmd, from); if (!strncmp(u->ut_user, user, USERSZ)) showinfo(u, longform, maxcmd, from, userlen, fromlen);
} }
} else { } else {
for (;;) { for (;;) {
u = getutent(); u = getutent();
if (unlikely(!u)) break; if (unlikely(!u)) break;
if (u->ut_type != USER_PROCESS) continue; if (u->ut_type != USER_PROCESS) continue;
if (*u->ut_user) showinfo(u, longform, maxcmd, from); if (*u->ut_user) showinfo(u, longform, maxcmd, from, userlen, fromlen);
} }
} }
endutent(); endutent();