Package: coreutils
Version: 5.97-5.2
Followup-For: Bug #400467

Hi,
here is a ptahc that does implement IP address sorting.  It currently
only does IPv4 (though adding IPv6 would not be complicated).  What's
still missing is documentation and possibly configure checks for
inet_pton and ntohl.  Any chance something like this could be added?

Best,
  Norbert

-- System Information:
Debian Release: 4.0
  APT prefers unstable
  APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.18.2
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)

Versions of packages coreutils depends on:
ii  libacl1                      2.2.41-1    Access control list shared library
ii  libc6                        2.3.6.ds1-8 GNU C Library: Shared libraries
ii  libselinux1                  1.32-3      SELinux shared libraries

coreutils recommends no packages.

-- no debconf information
--- src/sort.c~	2006-11-26 03:57:00.000000000 -0800
+++ src/sort.c	2006-11-26 10:37:04.000000000 -0800
@@ -25,6 +25,8 @@
 
 #include <getopt.h>
 #include <sys/types.h>
+#include <sys/socket.h> 
+#include <arpa/inet.h> 
 #include <signal.h>
 #include "system.h"
 #include "error.h"
@@ -150,6 +152,7 @@
   bool general_numeric;		/* Flag for general, numeric comparison.
 				   Handle numbers in exponential notation. */
   bool month;			/* Flag for comparison by month name. */
+  bool ipaddress;		/* Flag for comparison as ip address. */
   bool reverse;			/* Reverse the sense of comparison. */
   struct keyfield *next;	/* Next keyfield to try. */
 };
@@ -302,6 +305,7 @@
   -g, --general-numeric-sort  compare according to general numerical value\n\
   -i, --ignore-nonprinting    consider only printable characters\n\
   -M, --month-sort            compare (unknown) < `JAN' < ... < `DEC'\n\
+  -I, --ipaddress-sort        compare according to IP address value\n\
   -n, --numeric-sort          compare according to string numerical value\n\
   -r, --reverse               reverse the result of comparisons\n\
 \n\
@@ -353,7 +357,7 @@
   exit (status);
 }
 
-static char const short_options[] = "-bcdfgik:mMno:rsS:t:T:uy:z";
+static char const short_options[] = "-bcdfgik:mMIno:rsS:t:T:uy:z";
 
 static struct option const long_options[] =
 {
@@ -366,6 +370,7 @@
   {"key", required_argument, NULL, 'k'},
   {"merge", no_argument, NULL, 'm'},
   {"month-sort", no_argument, NULL, 'M'},
+  {"ipaddress-sort", no_argument, NULL, 'I'},
   {"numeric-sort", no_argument, NULL, 'n'},
   {"output", required_argument, NULL, 'o'},
   {"reverse", no_argument, NULL, 'r'},
@@ -1106,6 +1111,31 @@
 	  : memcmp ((char *) &a, (char *) &b, sizeof a));
 }
 
+static int
+ipaddresscompare (const char *a, const char *b)
+{
+  struct in_addr ia;
+  struct in_addr ib;
+
+  int is_a;
+  int is_b;
+  
+  while (blanks[to_uchar (*a)])
+    a++;
+  while (blanks[to_uchar (*b)])
+    b++;
+
+  is_a = inet_pton (AF_INET, a, &ia);
+  is_b = inet_pton (AF_INET, b, &ib);
+  if (is_a > 0 && is_b > 0)
+    {
+      uint32_t sa = ntohl (ia.s_addr);
+      uint32_t sb = ntohl (ib.s_addr);
+      return sa == sb ? 0 : sa < sb ? -1 : 1;
+    }
+  return is_a > 0 ? -1 : is_b > 0 ? 1 : 0;
+}
+
 /* Return an integer in 1..12 of the month name MONTH with length LEN.
    Return 0 if the name in S is not recognized.  */
 
@@ -1192,6 +1222,14 @@
 	diff = getmonth (texta, lena) - getmonth (textb, lenb);
       /* Sorting like this may become slow, so in a simple locale the user
 	 can select a faster sort that is similar to ascii sort.  */
+      else if (key->ipaddress)
+	{
+	  char savea = *lima, saveb = *limb;
+
+	  *lima = *limb = '\0';
+	  diff = ipaddresscompare (texta, textb);
+	  *lima = savea, *limb = saveb;
+	}
       else if (hard_LC_COLLATE)
 	{
 	  if (ignore || translate)
@@ -2078,6 +2116,9 @@
 	case 'M':
 	  key->month = true;
 	  break;
+	case 'I':
+	  key->ipaddress = true;
+	  break;
 	case 'n':
 	  key->numeric = true;
 	  break;
@@ -2187,7 +2228,7 @@
   gkey.sword = gkey.eword = SIZE_MAX;
   gkey.ignore = NULL;
   gkey.translate = NULL;
-  gkey.numeric = gkey.general_numeric = gkey.month = gkey.reverse = false;
+  gkey.numeric = gkey.general_numeric = gkey.month = gkey.ipaddress = gkey.reverse = false;
   gkey.skipsblanks = gkey.skipeblanks = false;
 
   files = xnmalloc (argc, sizeof *files);
@@ -2263,6 +2304,7 @@
 	case 'g':
 	case 'i':
 	case 'M':
+	case 'I':
 	case 'n':
 	case 'r':
 	  {
@@ -2419,7 +2461,7 @@
   for (key = keylist; key; key = key->next)
     if (! (key->ignore || key->translate
 	   || (key->skipsblanks | key->reverse
-	       | key->skipeblanks | key->month | key->numeric
+	       | key->skipeblanks | key->month | key->ipaddress | key->numeric
 	       | key->general_numeric)))
       {
 	key->ignore = gkey.ignore;
@@ -2427,13 +2469,14 @@
 	key->skipsblanks = gkey.skipsblanks;
 	key->skipeblanks = gkey.skipeblanks;
 	key->month = gkey.month;
+	key->ipaddress = gkey.ipaddress;
 	key->numeric = gkey.numeric;
 	key->general_numeric = gkey.general_numeric;
 	key->reverse = gkey.reverse;
       }
 
   if (!keylist && (gkey.ignore || gkey.translate
-		   || (gkey.skipsblanks | gkey.skipeblanks | gkey.month
+		   || (gkey.skipsblanks | gkey.skipeblanks | gkey.month | gkey.ipaddress
 		       | gkey.numeric | gkey.general_numeric)))
     insertkey (&gkey);
   reverse = gkey.reverse;

Reply via email to