Submitted By: Matthew Burgess <matthew_at_linuxfromscratch_dot_org>
Date: 2009-04-18
Initial Package Version: 7.2
Upstream Status: Rejected
Origin: Scot McPherson
Description: Fix the output of uname once and for all.

diff -Naur -i coreutils-7.2.orig/src/uname.c coreutils-7.2/src/uname.c
--- coreutils-7.2.orig/src/uname.c	2009-03-29 18:43:41.000000000 +0100
+++ coreutils-7.2/src/uname.c	2009-04-18 10:36:41.000000000 +0100
@@ -28,6 +28,12 @@
 # include <sys/systeminfo.h>
 #endif
 
+#ifdef linux
+#define cpuid(in,a,b,c,d)\
+  asm("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));
+int has_sse( void );
+#endif
+
 #if HAVE_SYS_SYSCTL_H
 # if HAVE_SYS_PARAM_H
 #  include <sys/param.h> /* needed for OpenBSD 3.0 */
@@ -308,6 +314,96 @@
 	if (0 <= sysinfo (SI_ARCHITECTURE, processor, sizeof processor))
 	  element = processor;
       }
+#else
+      {
+	struct utsname u;
+	uname (&u);
+	element = u.machine;
+#ifdef linux
+/******************************************************************************
+ *
+ * Hello, major hack.  I shouldn't have to do this.  struct utsname should
+ * have another element with this info in it.  There's probably a struct
+ * somewhere that has this info, I just don't know where it is.
+ *
+ *****************************************************************************/
+
+	if( !strcmp( element, "i586" ) || !strcmp( element, "i686" ) ) {
+	  int eax, ebx, ecx, edx, unused;
+	  int model, family, sse;
+     
+	  cpuid(0,unused,ebx,ecx,edx);
+	  cpuid(1,eax,unused,unused,unused);
+	  model = (eax >> 4) & 0xf;
+	  family = (eax >> 8) & 0xf;
+
+	  switch(ebx) {
+	  case 0x756e6547: // Intel
+	    switch( family ) {
+	    case 5: // Pentium
+	      if( model <= 3 )
+		element="pentium";
+	      if( model > 3 )
+		element="pentium-mmx";
+	      break;
+	    case 6: // PentiumPro - Pentium III
+	      if( model == 1 ) // Pentium Pro
+		element="pentiumpro";
+	      if( ( model == 3 ) || ( model == 5 ) ||
+		  ( model == 6 ) ) // Pentium II
+		element="pentium2";
+	      if( ( model == 7 ) || ( model == 8 ) ||
+		  ( model == 10 ) || ( model == 11 ) ) // These are all Pentium III
+		element="pentium3";
+	      break;
+	    case 15: // Pentium4
+	      element="pentium4";
+	      break;
+	    default:
+	      break;
+	    } // end switch( family )
+	    break;
+	  case 0x68747541: // AMD
+	    switch(family) {
+	    case 5:
+	      if( ( model == 0 ) || ( model == 1 ) || 
+		  ( model == 2 ) || ( model == 3 ) ) // K5
+		element="i586";
+	      if( ( model == 6 ) || ( model == 7 ) ) // K6
+		element="k6";
+	      if( model == 8 ) // K6-2
+		element="k6-2";
+	      if( model == 9 ) // K6-3
+		element="k6-3";
+	      break;
+	    case 6:
+	      if( model <= 4 )
+		element="athlon";
+	      if( model > 4 ) {
+		sse = has_sse();
+		if( sse == 0 )
+		  element="athlon";
+		if( sse == 1 )
+		  element="athlon-4";
+	      }
+	      break;
+	    case 15:
+	      element="athlon-4";
+	      break;
+	    default:
+	      break;
+	    } // end switch( family )
+	    break;
+	  case 0x69727943: // Cyrix
+	    element="i386"; // who knows what cyrix supports, lets be safe
+	    break;
+	  default:
+	    break;
+	  } // end switch(ebx)
+	}
+
+#endif
+      }
 #endif
 #ifdef UNAME_PROCESSOR
       if (element == unknown)
@@ -345,7 +441,7 @@
 
   if (toprint & PRINT_HARDWARE_PLATFORM)
     {
-      char const *element = unknown;
+      char *element = unknown;
 #if HAVE_SYSINFO && defined SI_PLATFORM
       {
 	static char hardware_platform[257];
@@ -353,6 +449,15 @@
 			  hardware_platform, sizeof hardware_platform))
 	  element = hardware_platform;
       }
+#else
+      {
+	struct utsname u;
+	uname (&u);
+	element = u.machine;
+	if (strlen (element) == 4 && element[0] == 'i' && element[2] == '8'
+	    && element[3] == '6')
+	  element[1] = '3';
+      }
 #endif
 #ifdef UNAME_HARDWARE_PLATFORM
       if (element == unknown)
@@ -375,3 +480,29 @@
 
   exit (EXIT_SUCCESS);
 }
+
+#ifdef linux
+
+/******************************************************************************
+ *
+ * int has_sse( void )
+ * Checks Athlon CPU's to see if they support SSE.
+ *
+ *****************************************************************************/
+
+int has_sse( void )
+{
+  unsigned long edx, unused;
+  int sse;
+  cpuid(1,unused,unused,unused,edx);
+  // I think, I need this tested on a Duron with SSE
+  // and one without it.
+  sse = edx & 0x2000000;
+  if( sse == 0 ) {
+    return 0;
+  } else {
+    return 1;
+  }
+
+}
+#endif
diff -Naur -i coreutils-7.2.orig/src/uname.c.orig coreutils-7.2/src/uname.c.orig
--- coreutils-7.2.orig/src/uname.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ coreutils-7.2/src/uname.c.orig	2009-03-29 18:43:41.000000000 +0100
@@ -0,0 +1,377 @@
+/* uname -- print system information
+
+   Copyright (C) 1989, 1992, 1993, 1996, 1997, 1999-2005, 2007-2008
+   Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu> */
+
+#include <config.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <getopt.h>
+
+#if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H
+# include <sys/systeminfo.h>
+#endif
+
+#if HAVE_SYS_SYSCTL_H
+# if HAVE_SYS_PARAM_H
+#  include <sys/param.h> /* needed for OpenBSD 3.0 */
+# endif
+# include <sys/sysctl.h>
+# ifdef HW_MODEL
+#  ifdef HW_MACHINE_ARCH
+/* E.g., FreeBSD 4.5, NetBSD 1.5.2 */
+#   define UNAME_HARDWARE_PLATFORM HW_MODEL
+#   define UNAME_PROCESSOR HW_MACHINE_ARCH
+#  else
+/* E.g., OpenBSD 3.0 */
+#   define UNAME_PROCESSOR HW_MODEL
+#  endif
+# endif
+#endif
+
+#ifdef __APPLE__
+# include <mach/machine.h>
+# include <mach-o/arch.h>
+#endif
+
+#include "system.h"
+#include "error.h"
+#include "quote.h"
+#include "uname.h"
+
+/* The official name of this program (e.g., no `g' prefix).  */
+#define PROGRAM_NAME (uname_mode == UNAME_UNAME ? "uname" : "arch")
+
+#define AUTHORS proper_name ("David MacKenzie")
+#define ARCH_AUTHORS "David MacKenzie", "Karel Zak"
+
+/* Values that are bitwise or'd into `toprint'. */
+/* Kernel name. */
+#define PRINT_KERNEL_NAME 1
+
+/* Node name on a communications network. */
+#define PRINT_NODENAME 2
+
+/* Kernel release. */
+#define PRINT_KERNEL_RELEASE 4
+
+/* Kernel version. */
+#define PRINT_KERNEL_VERSION 8
+
+/* Machine hardware name. */
+#define PRINT_MACHINE 16
+
+/* Processor type. */
+#define PRINT_PROCESSOR 32
+
+/* Hardware platform.  */
+#define PRINT_HARDWARE_PLATFORM 64
+
+/* Operating system.  */
+#define PRINT_OPERATING_SYSTEM 128
+
+static struct option const uname_long_options[] =
+{
+  {"all", no_argument, NULL, 'a'},
+  {"kernel-name", no_argument, NULL, 's'},
+  {"sysname", no_argument, NULL, 's'},	/* Obsolescent.  */
+  {"nodename", no_argument, NULL, 'n'},
+  {"kernel-release", no_argument, NULL, 'r'},
+  {"release", no_argument, NULL, 'r'},  /* Obsolescent.  */
+  {"kernel-version", no_argument, NULL, 'v'},
+  {"machine", no_argument, NULL, 'm'},
+  {"processor", no_argument, NULL, 'p'},
+  {"hardware-platform", no_argument, NULL, 'i'},
+  {"operating-system", no_argument, NULL, 'o'},
+  {GETOPT_HELP_OPTION_DECL},
+  {GETOPT_VERSION_OPTION_DECL},
+  {NULL, 0, NULL, 0}
+};
+
+static struct option const arch_long_options[] =
+{
+  {GETOPT_HELP_OPTION_DECL},
+  {GETOPT_VERSION_OPTION_DECL},
+  {NULL, 0, NULL, 0}
+};
+
+void
+usage (int status)
+{
+  if (status != EXIT_SUCCESS)
+    fprintf (stderr, _("Try `%s --help' for more information.\n"),
+	     program_name);
+  else
+    {
+      printf (_("Usage: %s [OPTION]...\n"), program_name);
+
+      if (uname_mode == UNAME_UNAME)
+        {
+          fputs (_("\
+Print certain system information.  With no OPTION, same as -s.\n\
+\n\
+  -a, --all                print all information, in the following order,\n\
+                             except omit -p and -i if unknown:\n\
+  -s, --kernel-name        print the kernel name\n\
+  -n, --nodename           print the network node hostname\n\
+  -r, --kernel-release     print the kernel release\n\
+"), stdout);
+          fputs (_("\
+  -v, --kernel-version     print the kernel version\n\
+  -m, --machine            print the machine hardware name\n\
+  -p, --processor          print the processor type or \"unknown\"\n\
+  -i, --hardware-platform  print the hardware platform or \"unknown\"\n\
+  -o, --operating-system   print the operating system\n\
+"), stdout);
+	}
+      else
+        {
+	  fputs (_("\
+Print machine architecture.\n\
+\n\
+"), stdout);
+	}
+
+      fputs (HELP_OPTION_DESCRIPTION, stdout);
+      fputs (VERSION_OPTION_DESCRIPTION, stdout);
+      emit_bug_reporting_address ();
+    }
+  exit (status);
+}
+
+/* Print ELEMENT, preceded by a space if something has already been
+   printed.  */
+
+static void
+print_element (char const *element)
+{
+  static bool printed;
+  if (printed)
+    putchar (' ');
+  printed = true;
+  fputs (element, stdout);
+}
+
+
+/* Set all the option flags according to the switches specified.
+   Return the mask indicating which elements to print.  */
+
+static int
+decode_switches (int argc, char **argv)
+{
+  int c;
+  unsigned int toprint = 0;
+
+  if (uname_mode == UNAME_ARCH)
+    {
+      while ((c = getopt_long (argc, argv, "",
+			       arch_long_options, NULL)) != -1)
+	{
+	  switch (c)
+	    {
+	    case_GETOPT_HELP_CHAR;
+
+	    case_GETOPT_VERSION_CHAR (PROGRAM_NAME, ARCH_AUTHORS);
+
+	    default:
+	      usage (EXIT_FAILURE);
+	    }
+        }
+      toprint = PRINT_MACHINE;
+    }
+  else
+    {
+      while ((c = getopt_long (argc, argv, "asnrvmpio",
+			       uname_long_options, NULL)) != -1)
+        {
+	  switch (c)
+	    {
+	    case 'a':
+	      toprint = UINT_MAX;
+	      break;
+
+	    case 's':
+	      toprint |= PRINT_KERNEL_NAME;
+	      break;
+
+	    case 'n':
+	      toprint |= PRINT_NODENAME;
+	      break;
+
+	    case 'r':
+	      toprint |= PRINT_KERNEL_RELEASE;
+	      break;
+
+	    case 'v':
+	      toprint |= PRINT_KERNEL_VERSION;
+	      break;
+
+	    case 'm':
+	      toprint |= PRINT_MACHINE;
+	      break;
+
+	    case 'p':
+	      toprint |= PRINT_PROCESSOR;
+	      break;
+
+	    case 'i':
+	      toprint |= PRINT_HARDWARE_PLATFORM;
+	      break;
+
+	    case 'o':
+	      toprint |= PRINT_OPERATING_SYSTEM;
+	      break;
+
+	    case_GETOPT_HELP_CHAR;
+
+	    case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
+
+	    default:
+	      usage (EXIT_FAILURE);
+	    }
+	}
+    }
+
+  if (argc != optind)
+    {
+      error (0, 0, _("extra operand %s"), quote (argv[optind]));
+      usage (EXIT_FAILURE);
+    }
+
+  return toprint;
+}
+
+int
+main (int argc, char **argv)
+{
+  static char const unknown[] = "unknown";
+
+  /* Mask indicating which elements to print. */
+  unsigned int toprint = 0;
+
+  initialize_main (&argc, &argv);
+  set_program_name (argv[0]);
+  setlocale (LC_ALL, "");
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  atexit (close_stdout);
+
+  toprint = decode_switches (argc, argv);
+
+  if (toprint == 0)
+    toprint = PRINT_KERNEL_NAME;
+
+  if (toprint
+       & (PRINT_KERNEL_NAME | PRINT_NODENAME | PRINT_KERNEL_RELEASE
+	  | PRINT_KERNEL_VERSION | PRINT_MACHINE))
+    {
+      struct utsname name;
+
+      if (uname (&name) == -1)
+	error (EXIT_FAILURE, errno, _("cannot get system name"));
+
+      if (toprint & PRINT_KERNEL_NAME)
+	print_element (name.sysname);
+      if (toprint & PRINT_NODENAME)
+	print_element (name.nodename);
+      if (toprint & PRINT_KERNEL_RELEASE)
+	print_element (name.release);
+      if (toprint & PRINT_KERNEL_VERSION)
+	print_element (name.version);
+      if (toprint & PRINT_MACHINE)
+	print_element (name.machine);
+    }
+
+  if (toprint & PRINT_PROCESSOR)
+    {
+      char const *element = unknown;
+#if HAVE_SYSINFO && defined SI_ARCHITECTURE
+      {
+	static char processor[257];
+	if (0 <= sysinfo (SI_ARCHITECTURE, processor, sizeof processor))
+	  element = processor;
+      }
+#endif
+#ifdef UNAME_PROCESSOR
+      if (element == unknown)
+	{
+	  static char processor[257];
+	  size_t s = sizeof processor;
+	  static int mib[] = { CTL_HW, UNAME_PROCESSOR };
+	  if (sysctl (mib, 2, processor, &s, 0, 0) >= 0)
+	    element = processor;
+
+# ifdef __APPLE__
+	  /* This kludge works around a bug in Mac OS X.  */
+	  if (element == unknown)
+	    {
+	      cpu_type_t cputype;
+	      size_t s = sizeof cputype;
+	      NXArchInfo const *ai;
+	      if (sysctlbyname ("hw.cputype", &cputype, &s, NULL, 0) == 0
+		  && (ai = NXGetArchInfoFromCpuType (cputype,
+						     CPU_SUBTYPE_MULTIPLE))
+		  != NULL)
+		element = ai->name;
+
+	      /* Hack "safely" around the ppc vs. powerpc return value. */
+	      if (cputype == CPU_TYPE_POWERPC
+		  && strncmp (element, "ppc", 3) == 0)
+		element = "powerpc";
+	    }
+# endif
+	}
+#endif
+      if (! (toprint == UINT_MAX && element == unknown))
+	print_element (element);
+    }
+
+  if (toprint & PRINT_HARDWARE_PLATFORM)
+    {
+      char const *element = unknown;
+#if HAVE_SYSINFO && defined SI_PLATFORM
+      {
+	static char hardware_platform[257];
+	if (0 <= sysinfo (SI_PLATFORM,
+			  hardware_platform, sizeof hardware_platform))
+	  element = hardware_platform;
+      }
+#endif
+#ifdef UNAME_HARDWARE_PLATFORM
+      if (element == unknown)
+	{
+	  static char hardware_platform[257];
+	  size_t s = sizeof hardware_platform;
+	  static int mib[] = { CTL_HW, UNAME_HARDWARE_PLATFORM };
+	  if (sysctl (mib, 2, hardware_platform, &s, 0, 0) >= 0)
+	    element = hardware_platform;
+	}
+#endif
+      if (! (toprint == UINT_MAX && element == unknown))
+	print_element (element);
+    }
+
+  if (toprint & PRINT_OPERATING_SYSTEM)
+    print_element (HOST_OPERATING_SYSTEM);
+
+  putchar ('\n');
+
+  exit (EXIT_SUCCESS);
+}
