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