home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / sysinfo-1.0 / part01 / sysinfo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-10  |  25.7 KB  |  1,157 lines

  1. /*
  2.  * Copyright (c) 1992 Michael A. Cooper.
  3.  * This software may be freely distributed provided it is not sold for 
  4.  * profit and the author is credited appropriately.
  5.  */
  6.  
  7. #ifndef lint
  8. static char *RCSid = "$Header: /src/common/usc/bin/sysinfo/RCS/sysinfo.c,v 1.47 1992/04/26 23:32:06 mcooper Exp $";
  9. #endif
  10.  
  11. /*
  12.  * $Log: sysinfo.c,v $
  13.  * Revision 1.47  1992/04/26  23:32:06  mcooper
  14.  * Add Copyright notice
  15.  *
  16.  * Revision 1.46  1992/04/17  23:27:51  mcooper
  17.  * Add support for ROM Version information (Sun only for now).
  18.  *
  19.  * Revision 1.45  1992/04/17  01:07:59  mcooper
  20.  * More de-linting
  21.  *
  22.  * Revision 1.44  1992/04/16  02:25:39  mcooper
  23.  * Bug fixes, de-linting, and other changes found with CodeCenter.
  24.  *
  25.  * Revision 1.43  1992/04/15  02:07:45  mcooper
  26.  * Fixed problem with "-show man +terse".
  27.  *
  28.  * Revision 1.42  1992/04/15  02:00:36  mcooper
  29.  * Major re-write and simplification of command line options.
  30.  *
  31.  * Revision 1.41  1992/03/31  18:57:40  mcooper
  32.  * - Don't stomp on Kernel Version strings.
  33.  * - Change "verbose" to "Show".
  34.  *
  35.  * Revision 1.40  1992/03/25  02:29:51  mcooper
  36.  * Add verbose keywords.
  37.  *
  38.  * Revision 1.39  1992/03/22  00:56:12  mcooper
  39.  * Updates for NeXT.
  40.  *
  41.  * Revision 1.38  1992/03/22  00:20:10  mcooper
  42.  * Major cleanup and re-org.
  43.  *
  44.  * Revision 1.37  1992/03/03  23:57:23  mcooper
  45.  * Make HAVE_KVM and HAVE_NLIST consistant.
  46.  *
  47.  * Revision 1.36  1992/03/03  02:51:07  mcooper
  48.  * Move strdup() to strdup.c
  49.  *
  50.  * Revision 1.35  1992/03/01  23:27:30  mcooper
  51.  * Move bulk of OS specific routines to OS specific files.
  52.  *
  53.  * Revision 1.34  1992/03/01  20:30:06  mcooper
  54.  * Cleanup handling of general info.
  55.  *
  56.  * Revision 1.33  1992/03/01  19:00:55  mcooper
  57.  * Fixed memory size code to be more portable.
  58.  *
  59.  * Revision 1.32  1992/02/22  02:18:20  mcooper
  60.  * Use new KVM() calling convention.
  61.  *
  62.  * Revision 1.31  1992/02/17  01:00:51  mcooper
  63.  * Changes for devices and "general" info.
  64.  *
  65.  * Revision 1.30  1992/02/13  22:37:18  mcooper
  66.  * Add 4/25 hostid.
  67.  *
  68.  * Revision 1.29  1992/02/10  21:06:22  mcooper
  69.  * Cleanup, add support for Sun4m and devices.
  70.  *
  71.  * Revision 1.28  1991/11/10  01:13:41  mcooper
  72.  * Use math function floor() instead of rnddown().
  73.  *
  74.  * Revision 1.27  1991/10/14  21:09:39  mcooper
  75.  * Fix get_memory() bug that caused incorrect
  76.  * results when bytes%DIV_BYTES==0.
  77.  *
  78.  * Revision 1.26  1991/10/14  20:29:59  mcooper
  79.  * Fixed get_memory() for Sun's the RIGHT WAY.
  80.  *
  81.  * Revision 1.25  1991/10/12  02:13:16  mcooper
  82.  * Fix memory page counting on Suns again and
  83.  * add -debug option.
  84.  *
  85.  * Revision 1.24  1991/10/10  00:44:54  mcooper
  86.  * Fixed memory calculation.
  87.  *
  88.  * Revision 1.23  1991/10/09  03:37:17  mcooper
  89.  * Add support for getting serial number
  90.  * and model name directly from system on
  91.  * Alliant FX80 series.
  92.  *
  93.  * Revision 1.22  1991/10/01  01:49:15  mcooper
  94.  * Add new system serial number code.
  95.  *
  96.  * Revision 1.21  1991/09/30  05:21:57  mcooper
  97.  * Add support for getting memory and model
  98.  * number on Alliant 2800's.
  99.  *
  100.  * Revision 1.20  1991/09/30  04:33:45  mcooper
  101.  * - Move system dependant stuff to system.h.
  102.  * - Create error() function.
  103.  *
  104.  * Revision 1.19  1991/09/30  04:04:50  mcooper
  105.  * Cleanup Solbourne stuff.
  106.  *
  107.  * Revision 1.18  1991/09/30  01:57:46  mcooper
  108.  * Sun's now use SUN?_ARCH for determining
  109.  * kernel architecture from gethostid().
  110.  *
  111.  * Revision 1.17  1991/09/28  03:42:24  mcooper
  112.  * Fixed Sun 386i model names.
  113.  *
  114.  * Revision 1.16  1991/09/28  03:36:32  mcooper
  115.  * Fixed get_memory() when converting bytes to MB.
  116.  *
  117.  * Revision 1.15  1991/09/28  03:20:00  mcooper
  118.  * Fixed NULL cast problem.
  119.  *
  120.  * Revision 1.14  1991/09/28  03:13:38  mcooper
  121.  * - Cleanup kvm stuff.
  122.  * - Now works on FX alliants.
  123.  *
  124.  * Revision 1.13  1991/09/27  23:03:12  mcooper
  125.  * Major cleanup/re-write.
  126.  *
  127.  * Revision 1.12  1991/09/26  05:24:22  mcooper
  128.  * - Added memory lookup support for Sun's.
  129.  * - Added printing kernel version string.
  130.  *
  131.  * Revision 1.11  1991/09/22  23:50:23  mcooper
  132.  * Use new NeXT/Mach host_info() calls.
  133.  *
  134.  * Revision 1.10  1991/08/31  03:25:50  mcooper
  135.  * Add defines for SPARCstation ELC and IPX.
  136.  *
  137.  * Revision 1.9  1991/03/12  01:26:03  mcooper
  138.  * Changes for AIX on the RS6000.
  139.  *
  140.  * Revision 1.8  1991/02/27  20:14:15  mcooper
  141.  * Add back in the 4_460.  Need both that
  142.  * and 4_470 since Sun changed to 4_470 in 4.1.1.
  143.  *
  144.  * Revision 1.7  1991/02/27  19:25:04  mcooper
  145.  * Change CPU_SUN4_460 to CPU_SUN4_470.
  146.  *
  147.  * Revision 1.6  1991/02/21  02:20:25  mcooper
  148.  * Add OS name and OS version stuff.
  149.  *
  150.  * Revision 1.5  1991/02/20  20:24:16  mcooper
  151.  * Re-arrange default output order.
  152.  *
  153.  * Revision 1.4  1991/02/20  20:19:34  mcooper
  154.  * If any item is enabled from the command
  155.  * line (via a + option), then only print selected
  156.  * item(s) in non verbose mode.
  157.  *
  158.  * Revision 1.3  1991/02/12  17:27:08  root
  159.  * Ported to NeXT 2.0.
  160.  *
  161.  * Revision 1.2  91/02/11  21:58:35  mcooper
  162.  * - Add new routines to print host name, host
  163.  *   name aliases, network addresses, and hostid.
  164.  * - Make verbose format easier to read with new
  165.  *   PrintLabel() function.
  166.  * 
  167.  * Revision 1.1  1991/02/09  01:33:40  mcooper
  168.  * Initial revision
  169.  *
  170.  */
  171.  
  172. /*
  173.  * Display System Information
  174.  */
  175.  
  176. #include <stdio.h>
  177. #include <sys/types.h>
  178. #include <sys/socket.h>
  179. #include <netinet/in.h>
  180. #include <arpa/inet.h>
  181. #include <netdb.h>
  182.  
  183. #include "system.h"
  184. #include "defs.h"
  185.  
  186. #if    defined(HAVE_UNAME)
  187. #include <sys/utsname.h>
  188. #endif    /* HAVE_UNAME */
  189.  
  190. /*
  191.  * Local declarations
  192.  */
  193. extern char               *AppArchCmds[];
  194. extern char               *KernArchCmds[];
  195. extern char               *ArchFiles[];
  196. extern char               *CPUFiles[];
  197.  
  198. int                 DoPrintAll = TRUE;
  199. int                 DoPrintUnknown = FALSE;
  200. int                 DoPrintVersion = FALSE;
  201. int                 Level = L_BRIEF;
  202. int                 Terse = FALSE;
  203. int                 Debug = 0;
  204. char                    *ShowStr = NULL;
  205. char                    *LevelStr = NULL;
  206. char                    *ListStr = NULL;
  207.  
  208. #if    defined(OPTION_COMPAT)
  209. /*
  210.  * Old options here for backwards compatibility
  211.  */
  212. int                DoPrintCPU = FALSE;
  213. int                DoPrintAppArch = FALSE;
  214. int                DoPrintHostID = FALSE;
  215. int                DoPrintHostName = FALSE;
  216. int                DoPrintHostAlias = FALSE;
  217. int                DoPrintHostAddrs = FALSE;
  218. int                DoPrintKernArch = FALSE;
  219. int                DoPrintKernVer = FALSE;
  220. int                DoPrintMan = FALSE;
  221. int                DoPrintModel = FALSE;
  222. int                DoPrintMemory = FALSE;
  223. int                DoPrintOSName = FALSE;
  224. int                DoPrintOSVer = FALSE;
  225. int                DoPrintSerialNo = FALSE;
  226. #endif    /* OPTION_COMPAT */
  227.  
  228. /*
  229.  * Command line options table.
  230.  */
  231. OptionDescRec Opts[] = {
  232.     {"+all",     NoArg,        OptBool,     __ &DoPrintAll,        "1",
  233.      NULL,    "Print all information"},
  234.     {"-all",     NoArg,        OptBool,     __ &DoPrintAll,        "0",
  235.      NULL,    "Don't print all information"},
  236.     {"-level",    SepArg,        OptStr,     __ &LevelStr,        NULL,
  237.      "<see \"-list level\">",    "Level names"},
  238.     {"-list",    SepArg,        OptStr,     __ &ListStr,        "-",
  239.      "level,show",    "List information about values"},
  240.     {"-show",    SepArg,        OptStr,     __ &ShowStr,        NULL,
  241.      "<see \"-list show\">",    "Show names"},
  242.     {"+terse",     NoArg,        OptBool,     __ &Terse,        "1",
  243.      NULL,    "Print info in terse format"},
  244.     {"-terse",     NoArg,        OptBool,     __ &Terse,        "0",
  245.      NULL,    "Don't print info in terse format"},
  246.     {"+unknown",NoArg,        OptBool,     __ &DoPrintUnknown,    "1",
  247.      NULL,    "Print unknown devices"},
  248.     {"-unknown",NoArg,        OptBool,     __ &DoPrintUnknown,    "0",
  249.      NULL,    "Don't print unknown devices"},
  250.     {"-version",NoArg,        OptBool,     __ &DoPrintVersion,    "1",
  251.      NULL,    "Print version of this program" },
  252.     {"-debug",ArgHidden|SepArg,    OptInt,     __ &Debug,        "1",
  253.      NULL,    "Enable debugging"},
  254. #if    defined(OPTION_COMPAT)
  255.     {"+cpu",     NoArg|ArgHidden,OptBool,__ &DoPrintCPU,        "1" },
  256.     {"-cpu",     NoArg|ArgHidden,OptBool,__ &DoPrintCPU,        "0" },
  257.     {"+arch",     NoArg|ArgHidden,OptBool,__ &DoPrintAppArch,    "1" },
  258.     {"-arch",     NoArg|ArgHidden,OptBool,__ &DoPrintAppArch,    "0" },
  259.     {"+hostid",    NoArg|ArgHidden,OptBool,__ &DoPrintHostID,    "1" },
  260.     {"-hostid",    NoArg|ArgHidden,OptBool,__ &DoPrintHostID,    "0" },
  261.     {"+hostname",NoArg|ArgHidden,OptBool,__ &DoPrintHostName,    "1" },
  262.     {"-hostname",NoArg|ArgHidden,OptBool,__ &DoPrintHostName,    "0" },
  263.     {"+hostaliases",NoArg|ArgHidden,OptBool,__ &DoPrintHostAlias,"1" },
  264.     {"-hostaliases",NoArg|ArgHidden,OptBool,__ &DoPrintHostAlias,"0" },
  265.     {"+hostaddrs",NoArg|ArgHidden,OptBool,__ &DoPrintHostAddrs,    "1" },
  266.     {"-hostaddrs",NoArg|ArgHidden,OptBool,__ &DoPrintHostAddrs,    "0" },
  267.     {"+karch",     NoArg|ArgHidden,OptBool,__ &DoPrintKernArch,    "1" },
  268.     {"-karch",     NoArg|ArgHidden,OptBool,__ &DoPrintKernArch,    "0" },
  269.     {"+kernver",NoArg|ArgHidden,OptBool,__ &DoPrintKernVer,    "1" },
  270.     {"-kernver",NoArg|ArgHidden,OptBool,__ &DoPrintKernVer,    "0" },
  271.     {"+man",     NoArg|ArgHidden,OptBool,__ &DoPrintMan,        "1" },
  272.     {"-man",     NoArg|ArgHidden,OptBool,__ &DoPrintMan,        "0" },
  273.     {"+model",     NoArg|ArgHidden,OptBool,__ &DoPrintModel,    "1" },
  274.     {"-model",     NoArg|ArgHidden,OptBool,__ &DoPrintModel,    "0" },
  275.     {"+memory",    NoArg|ArgHidden,OptBool,__ &DoPrintMemory,    "1" },
  276.     {"-memory",    NoArg|ArgHidden,OptBool,__ &DoPrintMemory,    "0" },
  277.     {"+osname",    NoArg|ArgHidden,OptBool,__ &DoPrintOSName,    "1" },
  278.     {"-osname",    NoArg|ArgHidden,OptBool,__ &DoPrintOSName,    "0" },
  279.     {"+osvers",    NoArg|ArgHidden,OptBool,__ &DoPrintOSVer,    "1" },
  280.     {"-osvers",    NoArg|ArgHidden,OptBool,__ &DoPrintOSVer,    "0" },
  281.     {"+serial",    NoArg|ArgHidden,OptBool,__ &DoPrintSerialNo,    "1" },
  282.     {"-serial",    NoArg|ArgHidden,OptBool,__ &DoPrintSerialNo,    "0" },
  283. #endif    /* OPTION_COMPAT */
  284. };
  285.  
  286. /*
  287.  * Option compatibility support
  288.  */
  289. #if    defined(OPTION_COMPAT)
  290. static void            SetOptionCompat();
  291. #define OptCom(v) v
  292. #else
  293. #define OptCom(v) 0
  294. #endif
  295.  
  296. SHOWINFO ShowInfo[] = {
  297.     { S_GEN, "general",    "GENERAL INFORMATION",    ShowGeneral },
  298.     { S_GEN, "hostname",    "Host Name",        NULL, GetHostName,
  299.                         OptCom(&DoPrintHostName) },
  300.     { S_GEN, "hostaliases",    "Host Aliases",        NULL, GetHostAliases,
  301.                         OptCom(&DoPrintHostAlias) },
  302.     { S_GEN, "hostaddrs",    "Host Address(es)",    NULL, GetHostAddrs,
  303.                         OptCom(&DoPrintHostAddrs) },
  304.     { S_GEN, "hostid",        "Host ID",        NULL, GetHostID,
  305.                         OptCom(&DoPrintHostID) },
  306.     { S_GEN, "serial",        "Serial Number",    NULL, GetSerialNo,
  307.                         OptCom(&DoPrintSerialNo) },
  308.     { S_GEN, "man",        "Manufacturer",        NULL, GetMan,
  309.                         OptCom(&DoPrintMan) },
  310.     { S_GEN, "model",        "System Model",        NULL, GetModel,
  311.                         OptCom(&DoPrintModel) },
  312.     { S_GEN, "memory",        "Main Memory",        NULL, GetMemory,
  313.                         OptCom(&DoPrintMemory) },
  314.     { S_GEN, "romver",        "ROM Version",        NULL, GetRomVer },
  315.     { S_GEN, "cpu",        "CPU Type",        NULL, GetCPU,
  316.                         OptCom(&DoPrintCPU) },
  317.     { S_GEN, "arch",        "App Architecture",    NULL, GetAppArch,
  318.                         OptCom(&DoPrintAppArch) },
  319.     { S_GEN, "karch",        "Kernel Architecture",    NULL, GetKernArch,
  320.                         OptCom(&DoPrintKernArch) },
  321.     { S_GEN, "osname",        "OS Name",        NULL, GetOSName,
  322.                         OptCom(&DoPrintOSName) },
  323.     { S_GEN, "osvers",        "OS Version",        NULL, GetOSVersion,
  324.                         OptCom(&DoPrintOSVer) },
  325.     { S_GEN, "kernver",        "Kernel Version",    NULL, GetKernelVersion,
  326.                         OptCom(&DoPrintKernVer) },
  327.     { S_DEV, "devices",    "DEVICE INFORMATION",    ShowDevices },
  328.     { 0 },
  329. };
  330.  
  331. /*
  332.  * Values and names of levels
  333.  */
  334. NAMETAB LevelNames[] = {
  335.     { L_BRIEF,        "brief" },
  336.     { L_GENERAL,    "general" },
  337.     { L_DESC,        "descriptions" },
  338.     { L_CONFIG,        "config" },
  339.     { L_ALL,        "all" },
  340.     { L_DEBUG,        "debug" },
  341.     { 0 },
  342. };
  343.  
  344. /*
  345.  * List table
  346.  */
  347. struct listtab {
  348.     char               *Name;
  349.     char               *Desc;
  350.     void              (*Func)();
  351. };
  352. typedef struct listtab LISTTAB;
  353.  
  354. static void            List();
  355. static void            ListLevel();
  356. static void            ListShow();
  357.  
  358. LISTTAB ListTab[] = {
  359.     { "level",        "Values for -level option",    ListLevel },
  360.     { "show",        "Values for -show option",    ListShow },
  361.     { 0 },
  362. };
  363.  
  364. /*
  365.  * Print a label and an argument
  366.  */
  367. static void PrintLabel(Lbl, Str)
  368.      char                *Lbl;
  369.      char                *Str;
  370. {
  371.     if (!Terse)
  372.     printf("%-*s: ", 20, Lbl);
  373.     printf("%s\n", (Str && *Str) ? Str : "");
  374. }
  375.  
  376. /*
  377.  * Print general info
  378.  */
  379. extern void ShowGeneral(MyInfo, SpecInfo)
  380.     SHOWINFO               *MyInfo;
  381.     SHOWINFO               *SpecInfo;
  382. {
  383.     register int        i;
  384.     int                ShowAll = TRUE;
  385.  
  386.     /*
  387.      * Do a specific info item
  388.      */
  389.     if (SpecInfo) {
  390.     PrintLabel(SpecInfo->Label, (*SpecInfo->GetFunc)());
  391.     SpecInfo->Enable = FALSE;
  392.     return;
  393.     }
  394.  
  395.     /*
  396.      * See if we are going to show all items
  397.      */
  398.     if (!DoPrintAll)
  399.     for (i = 0; ShowInfo[i].Name; i++)
  400.         if (ShowInfo[i].Type == MyInfo->Type && 
  401.         ShowInfo[i].GetFunc && !ShowInfo[i].Enable) {
  402.         ShowAll = FALSE;
  403.         break;
  404.         }
  405.  
  406.     if (MyInfo && (DoPrintAll || ShowAll || MyInfo->Enable))
  407.     printf("\n\n\t%s\n\n", MyInfo->Label);
  408.  
  409.     /*
  410.      * Print each enabled item of our type
  411.      */
  412.     for (i = 0; ShowInfo[i].Name; i++)
  413.     if ((ShowInfo[i].Type == MyInfo->Type) &&
  414.         (ShowInfo[i].Enable || MyInfo->Enable) && ShowInfo[i].GetFunc) {
  415.         PrintLabel(ShowInfo[i].Label, (*ShowInfo[i].GetFunc)());
  416.         ShowInfo[i].Enable = FALSE;
  417.     }
  418.  
  419.     if (MyInfo)
  420.     MyInfo->Enable = FALSE;
  421. }
  422.  
  423. /*
  424.  * List Show values
  425.  */
  426. static void ListShow()
  427. {
  428.     register int        i;
  429.  
  430.     printf(
  431.     "The following values may be specified with the \"-show\" option:\n");
  432.     printf("\t%-20s %s\n", "VALUE", "DESCRIPTION");
  433.  
  434.     for (i = 0; ShowInfo[i].Name; i++)
  435.     printf("\t%-20s %s%s\n",
  436.            ShowInfo[i].Name,
  437.            (ShowInfo[i].ShowFunc) ? "Show all " : "",
  438.            ShowInfo[i].Label
  439.            );
  440. }
  441.  
  442. /*
  443.  * List Level values
  444.  */
  445. static void ListLevel()
  446. {
  447.     register int        i;
  448.  
  449.     printf(
  450.     "The following values may be specified with the \"-level\" option:\n");
  451.     printf("\t%-20s\n", "VALUE");
  452.  
  453.     for (i = 0; LevelNames[i].name; i++) {
  454.     printf("\t%s\n", LevelNames[i].name);
  455.     }
  456. }
  457.  
  458. /*
  459.  * List list values
  460.  */
  461. static void ListList()
  462. {
  463.     register int        i;
  464.  
  465.     printf(
  466.     "The following values may be specified with the \"-list\" option:\n");
  467.     printf("\t%-20s %s\n", "VALUE", "DESCRIPTION");
  468.  
  469.     for (i = 0; ListTab[i].Name; i++) {
  470.     printf("\t%-20s %s\n",
  471.            ListTab[i].Name,
  472.            ListTab[i].Desc
  473.            );
  474.     }
  475. }
  476.  
  477. /*
  478.  * List information about each word found in Str.
  479.  */
  480. static void List(Str)
  481.     char               *Str;
  482. {
  483.     register int        i;
  484.     char               *Word;
  485.     int                Found;
  486.  
  487.     if (EQ(Str, "-")) {
  488.     ListList();
  489.     return;
  490.     }
  491.  
  492.     for (Word = strtok(Str, ","); Word; Word = strtok((char *)NULL, ",")) {
  493.     for (i = 0, Found = FALSE; ListTab[i].Name && !Found; i++)
  494.         if (EQ(Word, ListTab[i].Name)) {
  495.         Found = TRUE;
  496.         (*ListTab[i].Func)();
  497.         }
  498.  
  499.     if (!Found) {
  500.         Error("The word \"%s\" is invalid.", Word);
  501.         ListList();
  502.         return;
  503.     }
  504.     }
  505. }
  506.  
  507. /*
  508.  * Get argument number "arg" from "str".
  509.  */
  510. static char *GetArg(Str, ArgNum)
  511.     char                *Str;
  512.     int             ArgNum;
  513. {
  514.     register char            *p, *start;
  515.     register int         c;
  516.  
  517.     for (c = 1, p = Str; p && *p; ++c) {
  518.     /* set start of word */
  519.     start = p; 
  520.  
  521.     /* skip over word */
  522.     while (p && *p && *p != ' ' && *p != '\t' && *p != '\n')
  523.         ++p;
  524.  
  525.     /* is this what we want? */
  526.     if (c == ArgNum) {
  527.         if (p) *p = C_NULL;
  528.         break;
  529.     }
  530.  
  531.     /* skip white space */
  532.     while (*p == ' ' || *p == '\t')
  533.         ++p;
  534.     }
  535.  
  536.     return(start);
  537. }
  538.  
  539. /*
  540.  * Convert integer to ASCII
  541.  */
  542. char *itoa(Num)
  543.     int             Num;
  544. {
  545.     static char         Buf[BUFSIZ];
  546.  
  547.     (void) sprintf(Buf, "%d", Num);
  548.  
  549.     return(Buf);
  550. }
  551.  
  552. /*
  553.  * Get kernel version string
  554.  */
  555. extern char *GetKernelVersion()
  556. {
  557.     static char               *Ptr = NULL;
  558.     char               *GetKernelVersionStr();
  559.  
  560.     /*
  561.      * See if we already know the answer
  562.      */
  563.     if (Ptr)
  564.     return(Ptr);
  565.  
  566.     return(Ptr = GetKernelVersionStr());
  567. }
  568.  
  569. #if    defined(HAVE_UNAME)
  570. /*
  571.  * Get name of OS using uname()
  572.  */
  573. extern char *GetOSNameFromUname()
  574. {
  575.     static struct utsname     un;
  576.  
  577.     if (uname(&un) != 0)
  578.     return((char *) NULL);
  579.     else
  580.     return(un.sysname);
  581. }
  582. #endif    /* HAVE_UNAME */
  583.  
  584. /*
  585.  * Get Operating System name.
  586.  */
  587. extern char *GetOSName()
  588. {
  589. #if    defined(OS_NAME)
  590.     return(OS_NAME);
  591. #else
  592.     return(GetOSNameStr());
  593. #endif    /* OS_NAME */
  594. }
  595.  
  596. #if    defined(HAVE_UNAME)
  597. /*
  598.  * Get OS version number using uname()
  599.  */
  600. extern char *GetOSVersionFromUname()
  601. {
  602.     static char            Buf[BUFSIZ];
  603.     struct utsname         un;
  604.  
  605.     if (uname(&un) != 0) {
  606.     return((char *) NULL);
  607.     }
  608.  
  609.     /*
  610.      * Vendors don't all do the same thing for storing
  611.      * version numbers via uname().
  612.      */
  613. #if    defined(UNAME_REL_VER_COMB)
  614.     (void) sprintf(Buf, "%s.%s", un.version, un.release);
  615. #else
  616.     (void) sprintf(Buf, "%s", un.release);
  617. #endif     /* UNAME_REL_VER_COMB */
  618.  
  619.     return(Buf);
  620. }
  621. #endif    /* HAVE_UNAME */
  622.  
  623. #if    defined(OSVERS_FROM_KERNVER)
  624. /*
  625.  * Get OS version by reading an a specific argument out of
  626.  * the kernel version string.
  627.  */
  628. extern char *GetOSVersionFromKernVer()
  629. {
  630.     static char            Buf[BUFSIZ];
  631.     register char           *p;
  632.  
  633.     if (!(p = GetKernelVersion()))
  634.     return((char *) NULL);
  635.  
  636.     (void) strcpy(Buf, p);
  637.     p = GetArg(Buf, OSVERS_FROM_KERNVER);
  638.     (void) strcpy(Buf, p);
  639.     if ((p = index(Buf, ':')) != NULL)
  640.     *p = C_NULL;
  641.  
  642.     return(Buf);
  643. }
  644. #endif    /* OSVERS_FROM_KERNVER */
  645.  
  646. /*
  647.  * Get Operating System version
  648.  */
  649. extern char *GetOSVersion()
  650. {
  651. #if    defined(OS_VERSION)
  652.     return(OS_VERSION);
  653. #else
  654.     char                *Str;
  655.     char                *p;
  656.  
  657.     if (!(Str = GetOSVersionStr()))
  658.     return(Str);
  659.  
  660.     /*
  661.      * Zap "*-PL*".
  662.      */
  663.     if (*Str && 
  664.     ((p = rindex(Str, '-')) != NULL) && (strncmp(p, "-PL", 3) == 0))
  665.     *p = C_NULL;
  666.  
  667.     return(Str);
  668. #endif    /* !OS_VERSION */
  669. }
  670.  
  671. /*
  672.  * Get our hostname
  673.  */
  674. extern char *GetHostName()
  675. {
  676.     static char         Buf[MAXHOSTNAMLEN+1];
  677.  
  678.     gethostname(Buf, sizeof(Buf));
  679.  
  680.     return((Buf[0]) ? Buf : (char *) NULL);
  681. }
  682.  
  683. /*
  684.  * Get aliases for this hostname
  685.  */
  686. extern char *GetHostAliases()
  687. {
  688.     static char         Buf[BUFSIZ];
  689.     struct hostent            *hp;
  690.     register char          **pp;
  691.     char                *HName;
  692.  
  693.     if ((HName = GetHostName()) == NULL)
  694.     return((char *) NULL);
  695.  
  696.     if ((hp = gethostbyname(HName)) == NULL) {
  697.     Error("Cannot find lookup host info for \"%s\": %s", HName, SYSERR);
  698.     return((char *) NULL);
  699.     }
  700.  
  701.     for (pp = hp->h_aliases, Buf[0] = C_NULL; pp && *pp; ++pp) {
  702.     (void) strcat(Buf, *pp);
  703.     (void) strcat(Buf, " ");
  704.     }
  705.  
  706.     return((Buf[0]) ? Buf : (char *) NULL);
  707. }
  708.  
  709. /*
  710.  * Get addresses for this host
  711.  */
  712. extern char *GetHostAddrs()
  713. {
  714.     static char         Buf[BUFSIZ];
  715.     struct hostent            *hp;
  716.     register char          **pp;
  717.     char                *HName;
  718.  
  719.     if ((HName = GetHostName()) == NULL)
  720.     return((char *) NULL);
  721.  
  722.     if ((hp = gethostbyname(HName)) == NULL) {
  723.     Error("Cannot find lookup host info for \"%s\": %s", HName, SYSERR);
  724.     return((char *) NULL);
  725.     }
  726.  
  727.     for (pp = hp->h_addr_list, Buf[0] = C_NULL; pp && *pp; ++pp) {
  728.     if (hp->h_addrtype == AF_INET) {
  729.         (void) strcat(Buf, (char *) inet_ntoa(*(struct in_addr *)*pp));
  730.         (void) strcat(Buf, " ");
  731.     }
  732.     }
  733.  
  734.     return((Buf[0]) ? Buf : (char *) NULL);
  735. }
  736.  
  737. /*
  738.  * Get system model
  739.  */
  740. extern char *GetModel()
  741. {
  742.     int             Len;
  743.     FILE                *fd;
  744.     char             Buf[BUFSIZ];
  745.     char               *GetModelName();
  746. #if    defined(MODEL_COMMAND)
  747.     extern char            *ModelCommand[];
  748. #endif    /* MODEL_COMMAND */
  749.  
  750.     /*
  751.      * Use model file if it exists.
  752.      */
  753.     if ((fd = fopen(MODELFILE, "r")) != NULL) {
  754.     fgets(Buf, sizeof(Buf), fd);
  755.     Len = strlen(Buf);
  756.     if (Buf[Len-1] == '\n') 
  757.         Buf[Len-1] = C_NULL;
  758.     return(Buf);
  759.     }
  760.  
  761.     /*
  762.      * If a command to get model name has been defined, try it.
  763.      */
  764. #if    defined(MODEL_COMMAND)
  765.     if (p = RunCmds(ModelCommand))
  766.     return(p);
  767. #endif    /* MODEL_COMMAND */
  768.  
  769.     /*
  770.      * Use a method specific to this OS
  771.      */
  772.     return(GetModelName());
  773. }
  774.  
  775. /*
  776.  * Get the short manufacturer name
  777.  */
  778. static char *GetManShort()
  779. {
  780.     return(MAN_SHORT);
  781. }
  782.  
  783. /*
  784.  * Get the long manufacturer name
  785.  */
  786. static char *GetManLong()
  787. {
  788.     return(MAN_LONG);
  789. }
  790.  
  791. /*
  792.  * Get the manufacturer info.
  793.  */
  794. extern char *GetMan()
  795. {
  796.     char                *ms, *ml;
  797.     static char         Buf[BUFSIZ];
  798.  
  799.     ms = GetManShort();
  800.     ml = GetManLong();
  801.  
  802.     if (!Terse)
  803.     (void) sprintf(Buf, "%s (%s)", ms, ml);
  804.     else
  805.     (void) sprintf(Buf, "%s", ms);
  806.  
  807.     return(Buf);
  808. }
  809.  
  810. /*
  811.  * Get application architecture.
  812.  */
  813. extern char *GetAppArch()
  814. {
  815.     char                *arch = NULL;
  816.  
  817. #if    defined(ARCH_TYPE)
  818.     /*
  819.      * Use predefined name if present.
  820.      */
  821.     if (!arch)
  822.     return(ARCH_TYPE);
  823. #endif    /* ARCH_TYPE */
  824.  
  825. #if    defined(HAVE_AARCHNAME)
  826.     /*
  827.      * Use OS specific method
  828.      */
  829.     if (arch = (char *) GetAppArchName())
  830.     return(arch);
  831. #endif    /* HAVE_AARCHNAME */
  832.  
  833.     /*
  834.      * Try running App Arch commands
  835.      */
  836.     if (arch = RunCmds(AppArchCmds))
  837.     return(arch);
  838.  
  839.     /*
  840.      * Try testing Architecture files
  841.      */
  842.     if (arch = RunTestFiles(ArchFiles))
  843.     return(arch);
  844.  
  845.     return(arch);
  846. }
  847.  
  848. /*
  849.  * Get kernel architecture
  850.  */
  851. extern char *GetKernArch()
  852. {
  853.     char                *arch = NULL;
  854.  
  855. #if    defined(KARCH_TYPE)
  856.     /*
  857.      * If there's a predefined KArch name, use it.
  858.      */
  859.     if (!arch)
  860.     return(KARCH_TYPE);
  861. #endif    /* KARCH_TYPE */
  862.  
  863. #if    defined(HAVE_KARCHNAME)
  864.     /*
  865.      * Try OS specific method
  866.      */
  867.     if (arch = GetKernArchName())
  868.     return(arch);
  869. #endif    /* HAVE_KARCHNAME */
  870.  
  871.     /*
  872.      * Try running the KArch test commands
  873.      */
  874.     if (arch = RunCmds(KernArchCmds))
  875.     return(arch);
  876.  
  877.     /*
  878.      * We're desperate, so try using the Application Architecture
  879.      */
  880.     if (arch = GetAppArch())
  881.     return(arch);
  882.  
  883.     return((char *) NULL);
  884. }
  885.  
  886. /*
  887.  * Get host ID
  888.  */
  889. extern char *GetHostID()
  890. {
  891.     static char         Buf[100];
  892.  
  893.     (void) sprintf(Buf, "%08x", gethostid());
  894.  
  895.     return(Buf);
  896. }
  897.  
  898. /*
  899.  * Get system serial number
  900.  */
  901. extern char *GetSerialNo()
  902. {
  903.     return(GetSerialNoStr());
  904. }
  905.  
  906. /*
  907.  * Get CPU type
  908.  */
  909. extern char *GetCPU()
  910. {
  911.     char                *cpu = NULL;
  912.  
  913. #if    defined(CPU_NAME)
  914.     cpu = CPU_NAME;
  915. #else
  916. #if    defined(HAVE_HOST_INFO)
  917.     /*
  918.      * Try the Mach method.
  919.      * This should be in os-mach.c, but this is the only
  920.      * OS specific case so far.
  921.      */
  922.     cpu = (char *) GetCpuTypeFromHostInfo();
  923. #endif     /* HAVE_HOST_INFO */
  924. #endif     /* CPU_NAME */
  925.  
  926.     if (!cpu) {
  927.     cpu = RunTestFiles(CPUFiles);
  928.  
  929.     /*
  930.      * If that didn't work, try the architecture commands.
  931.      */
  932.     if (!cpu)
  933.         cpu = RunCmds(AppArchCmds);
  934.     }
  935.  
  936.     return(cpu);
  937. }
  938.  
  939. /*
  940.  * Print error message
  941.  */
  942. #if    defined(HAVE_VARARGS)
  943. #include <varargs.h>
  944. /*
  945.  * Varargs version of Error()
  946.  */
  947. extern void Error(va_alist)
  948.     va_dcl
  949. {
  950.     va_list             args;
  951.     char                *fmt;
  952.     extern char            *ProgramName;
  953.  
  954.     (void) fprintf(stderr, "%s: ", ProgramName);
  955.     va_start(args);
  956.     fmt = (char *) va_arg(args, char *);
  957.     (void) vfprintf(stderr, fmt, args);
  958.     va_end(args);
  959.     (void) fprintf(stderr, "\n");
  960. }
  961. #else
  962. /*
  963.  * Non-Varargs version of Error()
  964.  */
  965. extern void Error(fmt, a1, a2, a3, a4, a5, a6)
  966.     char                *fmt;
  967. {
  968.     extern char            *ProgramName;
  969.  
  970.     (void) fprintf(stderr, "%s: ", ProgramName);
  971.     (void) fprintf(stderr, fmt, a1, a2, a3, a4, a5, a6);
  972.     (void) fprintf(stderr, "\n");
  973. }
  974. #endif     /* !HAVE_VARARGS */
  975.  
  976. /*
  977.  * Parse and set the level keyword list
  978.  */
  979. static int ParseLevel(Str)
  980.     char               *Str;
  981. {
  982.     register int        i;
  983.     char               *Word;
  984.     int                Found;
  985.  
  986.     /*
  987.      * Check each word in the LevelNames table
  988.      */
  989.     for (Word = strtok(Str, ","); Word; Word = strtok((char *)NULL, ",")) {
  990.     for (i = 0, Found = FALSE; LevelNames[i].name && !Found; i++) {
  991.         if (strncasecmp(Word, LevelNames[i].name, strlen(Word)) == 0) {
  992.         Level |= LevelNames[i].value;
  993.         Found = TRUE;
  994.         }
  995.     }
  996.     if (!Found) {
  997.         Error("The word \"%s\" is not a valid verbosity level.", Word);
  998.         return(-1);
  999.     }
  1000.     }
  1001.  
  1002.     return(0);
  1003. }
  1004.  
  1005. /*
  1006.  * Parse and set the showinfo items
  1007.  */
  1008. static int ParseShow(Str)
  1009.     char               *Str;
  1010. {
  1011.     register int        x;
  1012.     char               *Word;
  1013.     int                Found;
  1014.  
  1015.     /*
  1016.      * Check each word.
  1017.      */
  1018.     for (Word = strtok(Str, ","); Word; Word = strtok((char *)NULL, ",")) {
  1019.     /*
  1020.      * Search the ShowInfo entries for a match.
  1021.      */
  1022.     for (x = 0, Found = FALSE; !Found && ShowInfo[x].Name; x++)
  1023.         if (EQ(Word, ShowInfo[x].Name)) {
  1024.         ShowInfo[x].Enable = TRUE;
  1025.         DoPrintAll = FALSE;
  1026.         Found = TRUE;
  1027.         }
  1028.  
  1029.     if (!Found) {
  1030.         Error("The word \"%s\" is not valid.", Word);
  1031.         ListShow();
  1032.         return(-1);
  1033.     }
  1034.     }
  1035.  
  1036.     return(0);
  1037. }
  1038.  
  1039. /*
  1040.  * Front end to calloc()
  1041.  */
  1042. char *xcalloc(nele, esize)
  1043.     int             nele;
  1044.     int             esize;
  1045. {
  1046.     char                *p, *calloc();
  1047.  
  1048.     if ((p = calloc(nele, esize)) == NULL) {
  1049.     Error("calloc(%d, %d) failed.", nele, esize);
  1050.     return((char *) NULL);
  1051.     }
  1052.  
  1053.     return(p);
  1054. }
  1055.  
  1056. #if    defined(OPTION_COMPAT)
  1057. /*
  1058.  * Set option compatibility
  1059.  */
  1060. static void SetOptionCompat()
  1061. {
  1062.     register int        i;
  1063.  
  1064.     /*
  1065.      * For every OptCompat that's TRUE, enable the real value
  1066.      */
  1067.     for (i = 0; ShowInfo[i].Name; i++) 
  1068.     if (ShowInfo[i].OptCompat && *ShowInfo[i].OptCompat) {
  1069.         ShowInfo[i].Enable = TRUE;
  1070.         /*
  1071.          * These is also part of the old behavior
  1072.          */
  1073.         DoPrintAll = FALSE;
  1074.         Terse = TRUE;
  1075.     }
  1076.  
  1077. }
  1078. #endif    /* OPTION_COMPAT */
  1079.  
  1080. /*
  1081.  * The beginning
  1082.  */
  1083. main(Argc, Argv)
  1084.     int             Argc;
  1085.     char               **Argv;
  1086. {
  1087.     register int        i;
  1088.  
  1089.     if (ParseOptions(Opts, Num_Opts(Opts), Argc, Argv) < 0) {
  1090.         exit(1);
  1091.     }
  1092.  
  1093.     /*
  1094.      * Show version info
  1095.      */
  1096.     if (DoPrintVersion) {
  1097.     printf("Sysinfo version %s.%d\n", VERSION_STR, PATCHLEVEL);
  1098.     exit(0);
  1099.     }
  1100.  
  1101.     /*
  1102.      * Do any list commands and exit
  1103.      */
  1104.     if (ListStr) {
  1105.     List(ListStr);
  1106.     exit(0);
  1107.     }
  1108.  
  1109. #if    defined(OPTION_COMPAT)
  1110.     SetOptionCompat();
  1111. #endif
  1112.  
  1113.     /*
  1114.      * Set verbosity strings
  1115.      */
  1116.     if (LevelStr && ParseLevel(LevelStr))
  1117.     exit(1);
  1118.  
  1119.     if (ShowStr && ParseShow(ShowStr))
  1120.     exit(1);
  1121.  
  1122.     /*
  1123.      * Run down the main topics
  1124.      */
  1125.     for (i = 0; ShowInfo[i].Name; i++) {
  1126.     if (!(DoPrintAll || ShowInfo[i].Enable))
  1127.         continue;
  1128.  
  1129.     if (ShowInfo[i].ShowFunc) {
  1130.         /*
  1131.          * The item has a show function
  1132.          */
  1133.         (*ShowInfo[i].ShowFunc)(&ShowInfo[i], NULL);
  1134.     } else {
  1135.         register int    x;
  1136.         int            Found;
  1137.  
  1138.         /*
  1139.          * Search for and call a search function for this type of item
  1140.          */
  1141.         for (x = 0, Found = FALSE; !Found && ShowInfo[x].Name; x++)
  1142.         if ((ShowInfo[x].Type == ShowInfo[i].Type) &&
  1143.             ShowInfo[x].ShowFunc) {
  1144.             Found = TRUE;
  1145.             (*ShowInfo[x].ShowFunc)(&ShowInfo[x], &ShowInfo[i]);
  1146.         }
  1147.         if (!Found) {
  1148.         Error("No show function exists for \"%s\".", 
  1149.               ShowInfo[i].Name);
  1150.         exit(1);
  1151.         }
  1152.     }
  1153.     }
  1154.  
  1155.     exit(0);
  1156. }
  1157.