#! /bin/sh /usr/share/dpatch/dpatch-run @DPATCH@ diff -urNad coreutils-7.5~/src/who.c coreutils-7.5/src/who.c --- coreutils-7.5~/src/who.c 2009-09-02 20:53:38.000000000 -0400 +++ coreutils-7.5/src/who.c 2009-09-04 17:47:42.661391006 -0400 @@ -28,6 +28,8 @@ #include #include +#include +#include #include "system.h" #include "c-ctype.h" @@ -100,6 +102,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'. */ @@ -155,7 +160,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[] = @@ -165,6 +171,7 @@ {"count", no_argument, NULL, 'q'}, {"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'}, @@ -417,6 +424,63 @@ } #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.87dsf + (GPL Copyright 1991-2004 Miquel van Smoorenburg) */ + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr *sa; + int salen, flags; + unsigned int azero=0; + unsigned int glblunicast=0, linklocal=0, localunicast=0; + 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 or fc00-fdff or fec0-feff. + * 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; + + azero = ntohl((unsigned int)a[0]) >> 16; + glblunicast = (azero >= 0x2000 && azero <= 0x3fff) ? 1 : 0; + localunicast = (azero >= 0xfc00 && azero <= 0xfdff) ? 1 : 0; + linklocal = (azero >= 0xfec0 && azero <= 0xfeff) ? 1 : 0; + + if (!(glblunicast || linklocal || localunicast) || 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, @@ -639,6 +703,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 (_("\ @@ -768,6 +837,10 @@ do_lookup = true; break; + case IPS_OPTION: + do_ips = true; + break; + case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);