busybox/coreutils/uname.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/* uname -- print system information
   3 * Copyright (C) 1989-1999 Free Software Foundation, Inc.
   4 *
   5 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
   6 */
   7
   8/* BB_AUDIT SUSv3 compliant */
   9/* http://www.opengroup.org/onlinepubs/007904975/utilities/uname.html */
  10
  11/* Option               Example
  12 * -s, --sysname        SunOS
  13 * -n, --nodename       rocky8
  14 * -r, --release        4.0
  15 * -v, --version
  16 * -m, --machine        sun
  17 * -a, --all            SunOS rocky8 4.0  sun
  18 *
  19 * The default behavior is equivalent to '-s'.
  20 *
  21 * David MacKenzie <djm@gnu.ai.mit.edu>
  22 *
  23 * GNU coreutils 6.10:
  24 * Option:                      struct   Example(s):
  25 *                              utsname
  26 *                              field:
  27 * -s, --kernel-name            sysname  Linux
  28 * -n, --nodename               nodename localhost.localdomain
  29 * -r, --kernel-release         release  2.6.29
  30 * -v, --kernel-version         version  #1 SMP Sun Jan 11 20:52:37 EST 2009
  31 * -m, --machine                machine  x86_64   i686
  32 * -p, --processor              (none)   x86_64   i686
  33 * -i, --hardware-platform      (none)   x86_64   i386
  34 *      NB: vanilla coreutils reports "unknown" -p and -i,
  35 *      x86_64 and i686/i386 shown above are Fedora's inventions.
  36 * -o, --operating-system       (none)   GNU/Linux
  37 * -a, --all: all of the above, in the order shown.
  38 *      If -p or -i is not known, don't show them
  39 */
  40
  41/* Busyboxed by Erik Andersen
  42 *
  43 * Before 2003: Glenn McGrath and Manuel Novoa III
  44 *  Further size reductions.
  45 * Mar 16, 2003: Manuel Novoa III (mjn3@codepoet.org)
  46 *  Now does proper error checking on i/o.  Plus some further space savings.
  47 * Jan 2009:
  48 *  Fix handling of -a to not print "unknown", add -o and -i support.
  49 */
  50
  51//usage:#define uname_trivial_usage
  52//usage:       "[-amnrspv]"
  53//usage:#define uname_full_usage "\n\n"
  54//usage:       "Print system information\n"
  55//usage:     "\n        -a      Print all"
  56//usage:     "\n        -m      The machine (hardware) type"
  57//usage:     "\n        -n      Hostname"
  58//usage:     "\n        -r      OS release"
  59//usage:     "\n        -s      OS name (default)"
  60//usage:     "\n        -p      Processor type"
  61//usage:     "\n        -v      OS version"
  62//usage:
  63//usage:#define uname_example_usage
  64//usage:       "$ uname -a\n"
  65//usage:       "Linux debian 2.4.23 #2 Tue Dec 23 17:09:10 MST 2003 i686 GNU/Linux\n"
  66
  67#include "libbb.h"
  68/* After libbb.h, since it needs sys/types.h on some systems */
  69#include <sys/utsname.h>
  70
  71typedef struct {
  72        struct utsname name;
  73        char processor[sizeof(((struct utsname*)NULL)->machine)];
  74        char platform[sizeof(((struct utsname*)NULL)->machine)];
  75        char os[sizeof("GNU/Linux")];
  76} uname_info_t;
  77
  78static const char options[] ALIGN1 = "snrvmpioa";
  79static const unsigned short utsname_offset[] = {
  80        offsetof(uname_info_t, name.sysname), /* -s */
  81        offsetof(uname_info_t, name.nodename), /* -n */
  82        offsetof(uname_info_t, name.release), /* -r */
  83        offsetof(uname_info_t, name.version), /* -v */
  84        offsetof(uname_info_t, name.machine), /* -m */
  85        offsetof(uname_info_t, processor), /* -p */
  86        offsetof(uname_info_t, platform), /* -i */
  87        offsetof(uname_info_t, os), /* -o */
  88};
  89
  90int uname_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  91int uname_main(int argc UNUSED_PARAM, char **argv)
  92{
  93#if ENABLE_LONG_OPTS
  94        static const char uname_longopts[] ALIGN1 =
  95                /* name, has_arg, val */
  96                "all\0"               No_argument       "a"
  97                "kernel-name\0"       No_argument       "s"
  98                "nodename\0"          No_argument       "n"
  99                "kernel-release\0"    No_argument       "r"
 100                "release\0"           No_argument       "r"
 101                "kernel-version\0"    No_argument       "v"
 102                "machine\0"           No_argument       "m"
 103                "processor\0"         No_argument       "p"
 104                "hardware-platform\0" No_argument       "i"
 105                "operating-system\0"  No_argument       "o"
 106        ;
 107#endif
 108        uname_info_t uname_info;
 109#if defined(__sparc__) && defined(__linux__)
 110        char *fake_sparc = getenv("FAKE_SPARC");
 111#endif
 112        const char *unknown_str = "unknown";
 113        const char *fmt;
 114        const unsigned short *delta;
 115        unsigned toprint;
 116
 117        IF_LONG_OPTS(applet_long_options = uname_longopts);
 118        toprint = getopt32(argv, options);
 119
 120        if (argv[optind]) { /* coreutils-6.9 compat */
 121                bb_show_usage();
 122        }
 123
 124        if (toprint & (1 << 8)) { /* -a => all opts on */
 125                toprint = (1 << 8) - 1;
 126                unknown_str = ""; /* -a does not print unknown fields */
 127        }
 128
 129        if (toprint == 0) { /* no opts => -s (sysname) */
 130                toprint = 1;
 131        }
 132
 133        uname(&uname_info.name); /* never fails */
 134
 135#if defined(__sparc__) && defined(__linux__)
 136        if (fake_sparc && (fake_sparc[0] | 0x20) == 'y') {
 137                strcpy(uname_info.name.machine, "sparc");
 138        }
 139#endif
 140        strcpy(uname_info.processor, unknown_str);
 141        strcpy(uname_info.platform, unknown_str);
 142        strcpy(uname_info.os, "GNU/Linux");
 143#if 0
 144        /* Fedora does something like this */
 145        strcpy(uname_info.processor, uname_info.name.machine);
 146        strcpy(uname_info.platform, uname_info.name.machine);
 147        if (uname_info.platform[0] == 'i'
 148         && uname_info.platform[1]
 149         && uname_info.platform[2] == '8'
 150         && uname_info.platform[3] == '6'
 151        ) {
 152                uname_info.platform[1] = '3';
 153        }
 154#endif
 155
 156        delta = utsname_offset;
 157        fmt = " %s" + 1;
 158        do {
 159                if (toprint & 1) {
 160                        const char *p = (char *)(&uname_info) + *delta;
 161                        if (p[0]) {
 162                                printf(fmt, p);
 163                                fmt = " %s";
 164                        }
 165                }
 166                ++delta;
 167        } while (toprint >>= 1);
 168        bb_putchar('\n');
 169
 170        fflush_stdout_and_exit(EXIT_SUCCESS); /* coreutils-6.9 compat */
 171}
 172