Add -i option to w

w can now show IP address for the from field with the -i option
This commit is contained in:
Jaromir Capik 2012-05-29 22:20:36 +10:00 committed by Craig Small
parent dc1531b211
commit 2b58862421
4 changed files with 111 additions and 10 deletions

1
.gitignore vendored
View File

@ -3,6 +3,7 @@
*.so *.so
.deps .deps
.libs .libs
.version
ABOUT-NLS ABOUT-NLS
aclocal.m4 aclocal.m4
autom4te.cache autom4te.cache

1
NEWS
View File

@ -1,6 +1,7 @@
procps-ng-3.3.4 procps-ng-3.3.4
--------------- ---------------
* Removed ps -aux bogus message * Removed ps -aux bogus message
* w get -i option to display IP addresses
procps-ng-3.3.3 procps-ng-3.3.3
--------------- ---------------

5
w.1
View File

@ -1,6 +1,6 @@
.\" -*-Nroff-*- .\" -*-Nroff-*-
.\" .\"
.TH W "1" "June 2011" "procps-ng" "User Commands" .TH W "1" "May 2012" "procps-ng" "User Commands"
.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
@ -49,6 +49,9 @@ field is shown by default.
\fB\-\-help\fR \fB\-\-help\fR
Display help text and exit. Display help text and exit.
.TP .TP
\fB\-\-ip\-addr\fR
Display IP address instead of hostname for \fBfrom\fR field.
.TP
\fB\-V\fR, \fB\-\-version\fR \fB\-V\fR, \fB\-\-version\fR
Display version information. Display version information.
.TP .TP

114
w.c
View File

@ -55,6 +55,7 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <utmp.h> #include <utmp.h>
#include <arpa/inet.h>
static int ignoreuser = 0; /* for '-u' */ static int ignoreuser = 0; /* for '-u' */
static int oldstyle = 0; /* for '-o' */ static int oldstyle = 0; /* for '-o' */
@ -82,7 +83,7 @@ static void print_host(const char *restrict host, int len, const int fromlen)
len = fromlen; len = fromlen;
last = host + len; last = host + len;
for (; host < last; host++) { for (; host < last; host++) {
if (*host == '\0') break; if (*host == '\0') break;
if (isprint(*host) && *host != ' ') { if (isprint(*host) && *host != ' ') {
fputc(*host, stdout); fputc(*host, stdout);
++width; ++width;
@ -101,6 +102,89 @@ static void print_host(const char *restrict host, int len, const int fromlen)
fputc(' ', stdout); fputc(' ', stdout);
} }
/* This routine prints the display part of the host */
static void print_display(const char *restrict host, int len, int restlen)
{
char *disp;
if (restlen <= 0) return; /* not enough space for the display */
/* search for the display (collon) */
disp = (char *)host;
while ( (disp < (host + len)) && (*disp != ':') && (*disp != '\0') ) disp++;
/* number of chars till the end of the input field */
len -= (disp - host);
/* if it is still longer than the rest of the output field, then cut it */
if (len > restlen) len = restlen;
/* display found, print it */
if (*disp == ':') {
while ((len > 0) && (*disp != '\0')) {
len--; restlen--;
/* print only if printable and non-space */
if (isprint(*host) && *host != ' ') {
fputc(*disp, stdout);
disp++;
} else { /* space or nonprintable - replace with dash and stop printing */
fputc('-', stdout);
break;
}
}
}
/* padding with spaces */
while (restlen > 0) {
fputc(' ', stdout);
restlen--;
}
}
/* This routine prints either the hostname or the IP address of the remote */
static void print_from(const utmp_t *restrict const u, const int ip_addresses, const int fromlen) {
char buf[fromlen + 1];
int len;
int32_t ut_addr_v6[4]; /* IP address of the remote host */
if (ip_addresses) { /* -i switch used */
memcpy(&ut_addr_v6, &u->ut_addr_v6, sizeof(ut_addr_v6));
if (IN6_IS_ADDR_V4MAPPED(&ut_addr_v6)) {
/* map back */
ut_addr_v6[0] = ut_addr_v6[3];
ut_addr_v6[1] = 0;
ut_addr_v6[2] = 0;
ut_addr_v6[3] = 0;
}
if (ut_addr_v6[1] || ut_addr_v6[2] || ut_addr_v6[3]) {
/* IPv6 */
if (!inet_ntop(AF_INET6, &ut_addr_v6, buf, sizeof(buf))) {
strcpy(buf, ""); /* invalid address, clean the buffer */
}
} else {
/* IPv4 */
if (!(ut_addr_v6[0] && inet_ntop(AF_INET, &ut_addr_v6[0], buf, sizeof(buf)))) {
strcpy(buf, ""); /* invalid address, clean the buffer */
}
}
buf[fromlen] = '\0';
len = strlen(buf);
if (len) { /* IP address is non-empty, print it (and concatenate with display, if present) */
fputs(buf, stdout);
/* show the display part of the host, if present */
print_display(u->ut_host, UT_HOSTSIZE, fromlen - len);
} else { /* IP address is empty, print the host instead */
print_host(u->ut_host, UT_HOSTSIZE, fromlen);
}
} else { /* -i switch NOT used */
print_host(u->ut_host, UT_HOSTSIZE, fromlen);
}
}
/* compact 7 char format for time intervals (belongs in libproc?) */ /* compact 7 char format for time intervals (belongs in libproc?) */
static void print_time_ival7(time_t t, int centi_sec, FILE * fout) static void print_time_ival7(time_t t, int centi_sec, FILE * fout)
{ {
@ -239,7 +323,7 @@ static const proc_t *getproc(const utmp_t * restrict const u,
} }
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) const int userlen, const int fromlen, const int ip_addresses)
{ {
unsigned long long jcpu; unsigned long long jcpu;
int ut_pid_found; int ut_pid_found;
@ -271,7 +355,7 @@ static void showinfo(utmp_t * u, int formtype, int maxcmd, int from,
if (formtype) { if (formtype) {
printf("%-*.*s%-9.8s", userlen + 1, userlen, uname, u->ut_line); printf("%-*.*s%-9.8s", userlen + 1, userlen, uname, u->ut_line);
if (from) if (from)
print_host(u->ut_host, UT_HOSTSIZE, fromlen); print_from(u, ip_addresses, fromlen);
print_logintime(u->ut_time, stdout); print_logintime(u->ut_time, stdout);
if (*u->ut_line == ':') if (*u->ut_line == ':')
/* idle unknown for xdm logins */ /* idle unknown for xdm logins */
@ -291,7 +375,7 @@ static void showinfo(utmp_t * u, int formtype, int maxcmd, int from,
printf("%-*.*s%-9.8s", userlen + 1, userlen, u->ut_user, printf("%-*.*s%-9.8s", userlen + 1, userlen, u->ut_user,
u->ut_line); u->ut_line);
if (from) if (from)
print_host(u->ut_host, UT_HOSTSIZE, fromlen); print_from(u, ip_addresses, fromlen);
if (*u->ut_line == ':') if (*u->ut_line == ':')
/* idle unknown for xdm logins */ /* idle unknown for xdm logins */
printf(" ?xdm? "); printf(" ?xdm? ");
@ -320,7 +404,8 @@ static void __attribute__ ((__noreturn__))
" -u, --no-current ignore current process username\n" " -u, --no-current ignore current process username\n"
" -s, --short short format\n" " -s, --short short format\n"
" -f, --from show remote hostname field\n" " -f, --from show remote hostname field\n"
" -o, --old-style old style output\n"), out); " -o, --old-style old style output\n"
" -i, --ip-addr display IP address instead of hostname (if possible)\n"), out);
fputs(USAGE_SEPARATOR, out); fputs(USAGE_SEPARATOR, out);
fputs(_(" --help display this help and exit\n"), out); fputs(_(" --help display this help and exit\n"), out);
fputs(USAGE_VERSION, out); fputs(USAGE_VERSION, out);
@ -334,11 +419,18 @@ int main(int argc, char **argv)
char *user = NULL, *p; char *user = NULL, *p;
utmp_t *u; utmp_t *u;
struct winsize win; struct winsize win;
int header = 1, longform = 1, from = 1, maxcmd = 80, ch; int ch;
int maxcmd = 80;
int userlen = 8; int userlen = 8;
int fromlen = 16; int fromlen = 16;
char *env_var; char *env_var;
/* switches (defaults) */
int header = 1;
int longform = 1;
int from = 1;
int ip_addresses = 0;
enum { enum {
HELP_OPTION = CHAR_MAX + 1 HELP_OPTION = CHAR_MAX + 1
}; };
@ -365,7 +457,7 @@ int main(int argc, char **argv)
#endif #endif
while ((ch = while ((ch =
getopt_long(argc, argv, "husfoV", longopts, NULL)) != -1) getopt_long(argc, argv, "husfoVi", longopts, NULL)) != -1)
switch (ch) { switch (ch) {
case 'h': case 'h':
header = 0; header = 0;
@ -388,6 +480,10 @@ int main(int argc, char **argv)
case 'o': case 'o':
oldstyle = 1; oldstyle = 1;
break; break;
case 'i':
ip_addresses = 1;
from = 1;
break;
case HELP_OPTION: case HELP_OPTION:
usage(stdout); usage(stdout);
default: default:
@ -458,7 +554,7 @@ int main(int argc, char **argv)
continue; continue;
if (!strncmp(u->ut_user, user, UT_NAMESIZE)) if (!strncmp(u->ut_user, user, UT_NAMESIZE))
showinfo(u, longform, maxcmd, from, userlen, showinfo(u, longform, maxcmd, from, userlen,
fromlen); fromlen, ip_addresses);
} }
} else { } else {
for (;;) { for (;;) {
@ -469,7 +565,7 @@ int main(int argc, char **argv)
continue; continue;
if (*u->ut_user) if (*u->ut_user)
showinfo(u, longform, maxcmd, from, userlen, showinfo(u, longform, maxcmd, from, userlen,
fromlen); fromlen, ip_addresses);
} }
} }
endutent(); endutent();