--- coreutils-5.97/src/who.c.orig	2006-05-27 15:09:15.243817480 -0400
+++ coreutils-6.10/src/who.c	2006-05-27 15:08:16.704965910 -0400
@@ -29,6 +29,8 @@
 #include <stdio.h>
 
 #include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
 #include "system.h"
 
 #include "canon-host.h"
@@ -107,6 +109,9 @@
 /* If true, attempt to canonicalize hostnames via a DNS lookup. */
 static bool do_lookup;
 
+/* If true, display ips instead of hostnames */
+static bool do_ips;
+
 /* If true, display only a list of usernames and count of
    the users logged on.
    Ignored for `who am i'.  */
@@ -162,7 +167,8 @@
 /* for long options with no corresponding short option, use enum */
 enum
 {
-  LOOKUP_OPTION = CHAR_MAX + 1
+  LOOKUP_OPTION = CHAR_MAX + 1,
+  IPS_OPTION = CHAR_MAX + 2
 };
 
 static struct option const longopts[] = {
@@ -172,5 +178,6 @@
   {"dead", no_argument, NULL, 'd'},
   {"heading", no_argument, NULL, 'H'},
+  {"ips", no_argument, NULL, IPS_OPTION},
   {"login", no_argument, NULL, 'l'},
   {"lookup", no_argument, NULL, LOOKUP_OPTION},
   {"message", no_argument, NULL, 'T'},
@@ -422,6 +429,57 @@
     }
 #endif
 
+  /* Needs configure check for ut_addr_v6, etc */
+  if (do_ips &&
+      memcmp(utmp_ent->ut_addr_v6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
+  {
+        /* Following code is from sysvinit-2.86.ds1 
+           (GPL Copyright 1991-2004 Miquel van Smoorenburg) */
+        struct sockaddr_in      sin;
+        struct sockaddr_in6     sin6;
+        struct sockaddr         *sa;
+        int                     salen, flags;
+        unsigned int            topnibble;
+        int                     mapped = 0;
+        int			*a = utmp_ent->ut_addr_v6;
+
+        hoststr = xrealloc(hoststr, 256);
+
+        flags = do_lookup ? 0 : NI_NUMERICHOST;
+
+        /*
+         *      IPv4 or IPv6 ? We use 2 heuristics:
+         *      1. Current IPv6 range uses 2000-3fff. Outside of
+         *         that is illegal and must be IPv4.
+         *      2. If last 3 bytes are 0, must be IPv4
+         *      3. If IPv6 in IPv4, handle as IPv4
+         *
+         *      Ugly.
+         */
+        if (a[0] == 0 && a[1] == 0 && a[2] == htonl (0xffff))
+                mapped = 1;
+        topnibble = ntohl((unsigned int)a[0]) >> 28;
+        if (topnibble < 2 || topnibble > 3 || mapped ||
+            (a[1] == 0 && a[2] == 0 && a[3] == 0)) {
+                /* IPv4 */
+                sin.sin_family = AF_INET;
+                sin.sin_port = 0;
+                sin.sin_addr.s_addr = mapped ? a[3] : a[0];
+                sa = (struct sockaddr *)&sin;
+                salen = sizeof(sin);
+        } else {
+                /* IPv6 */
+                memset(&sin6, 0, sizeof(sin6));
+                sin6.sin6_family = AF_INET6;
+                sin6.sin6_port = 0;
+                memcpy(sin6.sin6_addr.s6_addr, a, 16);
+                sa = (struct sockaddr *)&sin6;
+                salen = sizeof(sin6);
+        }
+
+	getnameinfo(sa, salen, hoststr, 256, NULL, 0, flags);
+  }
+
   print_line (sizeof UT_USER (utmp_ent), UT_USER (utmp_ent), mesg,
 	      sizeof utmp_ent->ut_line, utmp_ent->ut_line,
 	      time_string (utmp_ent), idlestr, pidstr,
@@ -641,6 +697,11 @@
   -H, --heading     print line of column headings\n\
 "), stdout);
       fputs (_("\
+      --ips         print ips instead of hostnames. with --lookup,\n\
+                    canonicalizes based on stored IP, if available,\n\
+                    rather than stored hostname\n\
+"), stdout);
+      fputs (_("\
   -l, --login       print system login processes\n\
 "), stdout);
       fputs (_("\
@@ -775,6 +836,10 @@
 	  do_lookup = true;
 	  break;
 
+        case IPS_OPTION:
+          do_ips = true;
+          break;
+
 	  case_GETOPT_HELP_CHAR;
 
 	  case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
