1/* uname -- print system information 2 3 Copyright (C) 1989, 1992-1993, 1996-1997, 1999-2005, 2007-2010 Free Software 4 Foundation, Inc. 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19/* Written by David MacKenzie <djm@gnu.ai.mit.edu> */ 20 21#include <config.h> 22#include <stdio.h> 23#include <sys/types.h> 24#include <sys/utsname.h> 25#include <getopt.h> 26 27#if HAVE_SYSINFO && HAVE_SYS_SYSTEMINFO_H 28# include <sys/systeminfo.h> 29#endif 30 31#if HAVE_SYS_SYSCTL_H 32# if HAVE_SYS_PARAM_H 33# include <sys/param.h> /* needed for OpenBSD 3.0 */ 34# endif 35# include <sys/sysctl.h> 36# ifdef HW_MODEL 37# ifdef HW_MACHINE_ARCH 38/* E.g., FreeBSD 4.5, NetBSD 1.5.2 */ 39# define UNAME_HARDWARE_PLATFORM HW_MODEL 40# define UNAME_PROCESSOR HW_MACHINE_ARCH 41# else 42/* E.g., OpenBSD 3.0 */ 43# define UNAME_PROCESSOR HW_MODEL 44# endif 45# endif 46#endif 47 48#ifdef __APPLE__ 49# include <mach/machine.h> 50# include <mach-o/arch.h> 51#endif 52 53#include "system.h" 54#include "error.h" 55#include "quote.h" 56#include "uname.h" 57 58/* The official name of this program (e.g., no `g' prefix). */ 59#define PROGRAM_NAME (uname_mode == UNAME_UNAME ? "uname" : "arch") 60 61#define AUTHORS proper_name ("David MacKenzie") 62#define ARCH_AUTHORS "David MacKenzie", "Karel Zak" 63 64/* Values that are bitwise or'd into `toprint'. */ 65/* Kernel name. */ 66#define PRINT_KERNEL_NAME 1 67 68/* Node name on a communications network. */ 69#define PRINT_NODENAME 2 70 71/* Kernel release. */ 72#define PRINT_KERNEL_RELEASE 4 73 74/* Kernel version. */ 75#define PRINT_KERNEL_VERSION 8 76 77/* Machine hardware name. */ 78#define PRINT_MACHINE 16 79 80/* Processor type. */ 81#define PRINT_PROCESSOR 32 82 83/* Hardware platform. */ 84#define PRINT_HARDWARE_PLATFORM 64 85 86/* Operating system. */ 87#define PRINT_OPERATING_SYSTEM 128 88 89static struct option const uname_long_options[] = 90{ 91 {"all", no_argument, NULL, 'a'}, 92 {"kernel-name", no_argument, NULL, 's'}, 93 {"sysname", no_argument, NULL, 's'}, /* Obsolescent. */ 94 {"nodename", no_argument, NULL, 'n'}, 95 {"kernel-release", no_argument, NULL, 'r'}, 96 {"release", no_argument, NULL, 'r'}, /* Obsolescent. */ 97 {"kernel-version", no_argument, NULL, 'v'}, 98 {"machine", no_argument, NULL, 'm'}, 99 {"processor", no_argument, NULL, 'p'}, 100 {"hardware-platform", no_argument, NULL, 'i'}, 101 {"operating-system", no_argument, NULL, 'o'}, 102 {GETOPT_HELP_OPTION_DECL}, 103 {GETOPT_VERSION_OPTION_DECL}, 104 {NULL, 0, NULL, 0} 105}; 106 107static struct option const arch_long_options[] = 108{ 109 {GETOPT_HELP_OPTION_DECL}, 110 {GETOPT_VERSION_OPTION_DECL}, 111 {NULL, 0, NULL, 0} 112}; 113 114void 115usage (int status) 116{ 117 if (status != EXIT_SUCCESS) 118 fprintf (stderr, _("Try `%s --help' for more information.\n"), 119 program_name); 120 else 121 { 122 printf (_("Usage: %s [OPTION]...\n"), program_name); 123 124 if (uname_mode == UNAME_UNAME) 125 { 126 fputs (_("\ 127Print certain system information. With no OPTION, same as -s.\n\ 128\n\ 129 -a, --all print all information, in the following order,\n\ 130 except omit -p and -i if unknown:\n\ 131 -s, --kernel-name print the kernel name\n\ 132 -n, --nodename print the network node hostname\n\ 133 -r, --kernel-release print the kernel release\n\ 134"), stdout); 135 fputs (_("\ 136 -v, --kernel-version print the kernel version\n\ 137 -m, --machine print the machine hardware name\n\ 138 -p, --processor print the processor type or \"unknown\"\n\ 139 -i, --hardware-platform print the hardware platform or \"unknown\"\n\ 140 -o, --operating-system print the operating system\n\ 141"), stdout); 142 } 143 else 144 { 145 fputs (_("\ 146Print machine architecture.\n\ 147\n\ 148"), stdout); 149 } 150 151 fputs (HELP_OPTION_DESCRIPTION, stdout); 152 fputs (VERSION_OPTION_DESCRIPTION, stdout); 153 emit_ancillary_info (); 154 } 155 exit (status); 156} 157 158/* Print ELEMENT, preceded by a space if something has already been 159 printed. */ 160 161static void 162print_element (char const *element) 163{ 164 static bool printed; 165 if (printed) 166 putchar (' '); 167 printed = true; 168 fputs (element, stdout); 169} 170 171 172/* Set all the option flags according to the switches specified. 173 Return the mask indicating which elements to print. */ 174 175static int 176decode_switches (int argc, char **argv) 177{ 178 int c; 179 unsigned int toprint = 0; 180 181 if (uname_mode == UNAME_ARCH) 182 { 183 while ((c = getopt_long (argc, argv, "", 184 arch_long_options, NULL)) != -1) 185 { 186 switch (c) 187 { 188 case_GETOPT_HELP_CHAR; 189 190 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, ARCH_AUTHORS); 191 192 default: 193 usage (EXIT_FAILURE); 194 } 195 } 196 toprint = PRINT_MACHINE; 197 } 198 else 199 { 200 while ((c = getopt_long (argc, argv, "asnrvmpio", 201 uname_long_options, NULL)) != -1) 202 { 203 switch (c) 204 { 205 case 'a': 206 toprint = UINT_MAX; 207 break; 208 209 case 's': 210 toprint |= PRINT_KERNEL_NAME; 211 break; 212 213 case 'n': 214 toprint |= PRINT_NODENAME; 215 break; 216 217 case 'r': 218 toprint |= PRINT_KERNEL_RELEASE; 219 break; 220 221 case 'v': 222 toprint |= PRINT_KERNEL_VERSION; 223 break; 224 225 case 'm': 226 toprint |= PRINT_MACHINE; 227 break; 228 229 case 'p': 230 toprint |= PRINT_PROCESSOR; 231 break; 232 233 case 'i': 234 toprint |= PRINT_HARDWARE_PLATFORM; 235 break; 236 237 case 'o': 238 toprint |= PRINT_OPERATING_SYSTEM; 239 break; 240 241 case_GETOPT_HELP_CHAR; 242 243 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); 244 245 default: 246 usage (EXIT_FAILURE); 247 } 248 } 249 } 250 251 if (argc != optind) 252 { 253 error (0, 0, _("extra operand %s"), quote (argv[optind])); 254 usage (EXIT_FAILURE); 255 } 256 257 return toprint; 258} 259 260int 261main (int argc, char **argv) 262{ 263 static char const unknown[] = "unknown"; 264 265 /* Mask indicating which elements to print. */ 266 unsigned int toprint = 0; 267 268 initialize_main (&argc, &argv); 269 set_program_name (argv[0]); 270 setlocale (LC_ALL, ""); 271 bindtextdomain (PACKAGE, LOCALEDIR); 272 textdomain (PACKAGE); 273 274 atexit (close_stdout); 275 276 toprint = decode_switches (argc, argv); 277 278 if (toprint == 0) 279 toprint = PRINT_KERNEL_NAME; 280 281 if (toprint 282 & (PRINT_KERNEL_NAME | PRINT_NODENAME | PRINT_KERNEL_RELEASE 283 | PRINT_KERNEL_VERSION | PRINT_MACHINE)) 284 { 285 struct utsname name; 286 287 if (uname (&name) == -1) 288 error (EXIT_FAILURE, errno, _("cannot get system name")); 289 290 if (toprint & PRINT_KERNEL_NAME) 291 print_element (name.sysname); 292 if (toprint & PRINT_NODENAME) 293 print_element (name.nodename); 294 if (toprint & PRINT_KERNEL_RELEASE) 295 print_element (name.release); 296 if (toprint & PRINT_KERNEL_VERSION) 297 print_element (name.version); 298 if (toprint & PRINT_MACHINE) 299 print_element (name.machine); 300 } 301 302 if (toprint & PRINT_PROCESSOR) 303 { 304 char const *element = unknown; 305#if HAVE_SYSINFO && defined SI_ARCHITECTURE 306 { 307 static char processor[257]; 308 if (0 <= sysinfo (SI_ARCHITECTURE, processor, sizeof processor)) 309 element = processor; 310 } 311#endif 312#ifdef UNAME_PROCESSOR 313 if (element == unknown) 314 { 315 static char processor[257]; 316 size_t s = sizeof processor; 317 static int mib[] = { CTL_HW, UNAME_PROCESSOR }; 318 if (sysctl (mib, 2, processor, &s, 0, 0) >= 0) 319 element = processor; 320 321# ifdef __APPLE__ 322 /* This kludge works around a bug in Mac OS X. */ 323 if (element == unknown) 324 { 325 cpu_type_t cputype; 326 size_t s = sizeof cputype; 327 NXArchInfo const *ai; 328 if (sysctlbyname ("hw.cputype", &cputype, &s, NULL, 0) == 0 329 && (ai = NXGetArchInfoFromCpuType (cputype, 330 CPU_SUBTYPE_MULTIPLE)) 331 != NULL) 332 element = ai->name; 333 334 /* Hack "safely" around the ppc vs. powerpc return value. */ 335 if (cputype == CPU_TYPE_POWERPC 336 && strncmp (element, "ppc", 3) == 0) 337 element = "powerpc"; 338 } 339# endif 340 } 341#endif 342 if (! (toprint == UINT_MAX && element == unknown)) 343 print_element (element); 344 } 345 346 if (toprint & PRINT_HARDWARE_PLATFORM) 347 { 348 char const *element = unknown; 349#if HAVE_SYSINFO && defined SI_PLATFORM 350 { 351 static char hardware_platform[257]; 352 if (0 <= sysinfo (SI_PLATFORM, 353 hardware_platform, sizeof hardware_platform)) 354 element = hardware_platform; 355 } 356#endif 357#ifdef UNAME_HARDWARE_PLATFORM 358 if (element == unknown) 359 { 360 static char hardware_platform[257]; 361 size_t s = sizeof hardware_platform; 362 static int mib[] = { CTL_HW, UNAME_HARDWARE_PLATFORM }; 363 if (sysctl (mib, 2, hardware_platform, &s, 0, 0) >= 0) 364 element = hardware_platform; 365 } 366#endif 367 if (! (toprint == UINT_MAX && element == unknown)) 368 print_element (element); 369 } 370 371 if (toprint & PRINT_OPERATING_SYSTEM) 372 print_element (HOST_OPERATING_SYSTEM); 373 374 putchar ('\n'); 375 376 exit (EXIT_SUCCESS); 377} 378