From 2b588624212606c94583f8f90f2fe2cb5bf2c5cb Mon Sep 17 00:00:00 2001 From: Jaromir Capik Date: Tue, 29 May 2012 22:20:36 +1000 Subject: [PATCH] Add -i option to w w can now show IP address for the from field with the -i option --- .gitignore | 1 + NEWS | 1 + w.1 | 5 ++- w.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 111 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 383a8aa1..67b92cbd 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.so .deps .libs +.version ABOUT-NLS aclocal.m4 autom4te.cache diff --git a/NEWS b/NEWS index 32cc76dd..29512ee4 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ procps-ng-3.3.4 --------------- * Removed ps -aux bogus message + * w get -i option to display IP addresses procps-ng-3.3.3 --------------- diff --git a/w.1 b/w.1 index 6adecfac..5b2b2645 100644 --- a/w.1 +++ b/w.1 @@ -1,6 +1,6 @@ .\" -*-Nroff-*- .\" -.TH W "1" "June 2011" "procps-ng" "User Commands" +.TH W "1" "May 2012" "procps-ng" "User Commands" .SH NAME w \- Show who is logged on and what they are doing. .SH SYNOPSIS @@ -49,6 +49,9 @@ field is shown by default. \fB\-\-help\fR Display help text and exit. .TP +\fB\-\-ip\-addr\fR +Display IP address instead of hostname for \fBfrom\fR field. +.TP \fB\-V\fR, \fB\-\-version\fR Display version information. .TP diff --git a/w.c b/w.c index 9c54d102..42854b66 100644 --- a/w.c +++ b/w.c @@ -55,6 +55,7 @@ #include #include #include +#include static int ignoreuser = 0; /* for '-u' */ 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; last = host + len; for (; host < last; host++) { - if (*host == '\0') break; + if (*host == '\0') break; if (isprint(*host) && *host != ' ') { fputc(*host, stdout); ++width; @@ -101,6 +102,89 @@ static void print_host(const char *restrict host, int len, const int fromlen) 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?) */ 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, - const int userlen, const int fromlen) + const int userlen, const int fromlen, const int ip_addresses) { unsigned long long jcpu; int ut_pid_found; @@ -271,7 +355,7 @@ static void showinfo(utmp_t * u, int formtype, int maxcmd, int from, if (formtype) { printf("%-*.*s%-9.8s", userlen + 1, userlen, uname, u->ut_line); if (from) - print_host(u->ut_host, UT_HOSTSIZE, fromlen); + print_from(u, ip_addresses, fromlen); print_logintime(u->ut_time, stdout); if (*u->ut_line == ':') /* 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, u->ut_line); if (from) - print_host(u->ut_host, UT_HOSTSIZE, fromlen); + print_from(u, ip_addresses, fromlen); if (*u->ut_line == ':') /* idle unknown for xdm logins */ printf(" ?xdm? "); @@ -320,7 +404,8 @@ static void __attribute__ ((__noreturn__)) " -u, --no-current ignore current process username\n" " -s, --short short format\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(_(" --help display this help and exit\n"), out); fputs(USAGE_VERSION, out); @@ -334,11 +419,18 @@ int main(int argc, char **argv) char *user = NULL, *p; utmp_t *u; struct winsize win; - int header = 1, longform = 1, from = 1, maxcmd = 80, ch; + int ch; + int maxcmd = 80; int userlen = 8; int fromlen = 16; char *env_var; + /* switches (defaults) */ + int header = 1; + int longform = 1; + int from = 1; + int ip_addresses = 0; + enum { HELP_OPTION = CHAR_MAX + 1 }; @@ -365,7 +457,7 @@ int main(int argc, char **argv) #endif while ((ch = - getopt_long(argc, argv, "husfoV", longopts, NULL)) != -1) + getopt_long(argc, argv, "husfoVi", longopts, NULL)) != -1) switch (ch) { case 'h': header = 0; @@ -388,6 +480,10 @@ int main(int argc, char **argv) case 'o': oldstyle = 1; break; + case 'i': + ip_addresses = 1; + from = 1; + break; case HELP_OPTION: usage(stdout); default: @@ -458,7 +554,7 @@ int main(int argc, char **argv) continue; if (!strncmp(u->ut_user, user, UT_NAMESIZE)) showinfo(u, longform, maxcmd, from, userlen, - fromlen); + fromlen, ip_addresses); } } else { for (;;) { @@ -469,7 +565,7 @@ int main(int argc, char **argv) continue; if (*u->ut_user) showinfo(u, longform, maxcmd, from, userlen, - fromlen); + fromlen, ip_addresses); } } endutent();