ftp.nice.ch/pub/next/unix/admin/sysinfo.1.1.0.s.tar.gz#/sysinfo.c

This is sysinfo.c in view mode; [Download] [Up]

/*
 * Copyright (c) 1992 Michael A. Cooper.
 * This software may be freely distributed provided it is not sold for 
 * profit and the author is credited appropriately.
 */

#ifndef lint
static char *RCSid = "$Header: /src/common/usc/bin/sysinfo/RCS/sysinfo.c,v 1.48 1992/12/02 04:20:46 mcooper Exp mcooper $";
#endif

/*
 * $Log: sysinfo.c,v $
 * Revision 1.48  1992/12/02  04:20:46  mcooper
 * Enable "unknown" mode by default.
 *
 * Revision 1.47  1992/04/26  23:32:06  mcooper
 * Add Copyright notice
 *
 * Revision 1.46  1992/04/17  23:27:51  mcooper
 * Add support for ROM Version information (Sun only for now).
 *
 * Revision 1.45  1992/04/17  01:07:59  mcooper
 * More de-linting
 *
 * Revision 1.44  1992/04/16  02:25:39  mcooper
 * Bug fixes, de-linting, and other changes found with CodeCenter.
 *
 * Revision 1.43  1992/04/15  02:07:45  mcooper
 * Fixed problem with "-show man +terse".
 *
 * Revision 1.42  1992/04/15  02:00:36  mcooper
 * Major re-write and simplification of command line options.
 *
 * Revision 1.41  1992/03/31  18:57:40  mcooper
 * - Don't stomp on Kernel Version strings.
 * - Change "verbose" to "Show".
 *
 * Revision 1.40  1992/03/25  02:29:51  mcooper
 * Add verbose keywords.
 *
 * Revision 1.39  1992/03/22  00:56:12  mcooper
 * Updates for NeXT.
 *
 * Revision 1.38  1992/03/22  00:20:10  mcooper
 * Major cleanup and re-org.
 *
 * Revision 1.37  1992/03/03  23:57:23  mcooper
 * Make HAVE_KVM and HAVE_NLIST consistant.
 *
 * Revision 1.36  1992/03/03  02:51:07  mcooper
 * Move strdup() to strdup.c
 *
 * Revision 1.35  1992/03/01  23:27:30  mcooper
 * Move bulk of OS specific routines to OS specific files.
 *
 * Revision 1.34  1992/03/01  20:30:06  mcooper
 * Cleanup handling of general info.
 *
 * Revision 1.33  1992/03/01  19:00:55  mcooper
 * Fixed memory size code to be more portable.
 *
 * Revision 1.32  1992/02/22  02:18:20  mcooper
 * Use new KVM() calling convention.
 *
 * Revision 1.31  1992/02/17  01:00:51  mcooper
 * Changes for devices and "general" info.
 *
 * Revision 1.30  1992/02/13  22:37:18  mcooper
 * Add 4/25 hostid.
 *
 * Revision 1.29  1992/02/10  21:06:22  mcooper
 * Cleanup, add support for Sun4m and devices.
 *
 * Revision 1.28  1991/11/10  01:13:41  mcooper
 * Use math function floor() instead of rnddown().
 *
 * Revision 1.27  1991/10/14  21:09:39  mcooper
 * Fix get_memory() bug that caused incorrect
 * results when bytes%DIV_BYTES==0.
 *
 * Revision 1.26  1991/10/14  20:29:59  mcooper
 * Fixed get_memory() for Sun's the RIGHT WAY.
 *
 * Revision 1.25  1991/10/12  02:13:16  mcooper
 * Fix memory page counting on Suns again and
 * add -debug option.
 *
 * Revision 1.24  1991/10/10  00:44:54  mcooper
 * Fixed memory calculation.
 *
 * Revision 1.23  1991/10/09  03:37:17  mcooper
 * Add support for getting serial number
 * and model name directly from system on
 * Alliant FX80 series.
 *
 * Revision 1.22  1991/10/01  01:49:15  mcooper
 * Add new system serial number code.
 *
 * Revision 1.21  1991/09/30  05:21:57  mcooper
 * Add support for getting memory and model
 * number on Alliant 2800's.
 *
 * Revision 1.20  1991/09/30  04:33:45  mcooper
 * - Move system dependant stuff to system.h.
 * - Create error() function.
 *
 * Revision 1.19  1991/09/30  04:04:50  mcooper
 * Cleanup Solbourne stuff.
 *
 * Revision 1.18  1991/09/30  01:57:46  mcooper
 * Sun's now use SUN?_ARCH for determining
 * kernel architecture from gethostid().
 *
 * Revision 1.17  1991/09/28  03:42:24  mcooper
 * Fixed Sun 386i model names.
 *
 * Revision 1.16  1991/09/28  03:36:32  mcooper
 * Fixed get_memory() when converting bytes to MB.
 *
 * Revision 1.15  1991/09/28  03:20:00  mcooper
 * Fixed NULL cast problem.
 *
 * Revision 1.14  1991/09/28  03:13:38  mcooper
 * - Cleanup kvm stuff.
 * - Now works on FX alliants.
 *
 * Revision 1.13  1991/09/27  23:03:12  mcooper
 * Major cleanup/re-write.
 *
 * Revision 1.12  1991/09/26  05:24:22  mcooper
 * - Added memory lookup support for Sun's.
 * - Added printing kernel version string.
 *
 * Revision 1.11  1991/09/22  23:50:23  mcooper
 * Use new NeXT/Mach host_info() calls.
 *
 * Revision 1.10  1991/08/31  03:25:50  mcooper
 * Add defines for SPARCstation ELC and IPX.
 *
 * Revision 1.9  1991/03/12  01:26:03  mcooper
 * Changes for AIX on the RS6000.
 *
 * Revision 1.8  1991/02/27  20:14:15  mcooper
 * Add back in the 4_460.  Need both that
 * and 4_470 since Sun changed to 4_470 in 4.1.1.
 *
 * Revision 1.7  1991/02/27  19:25:04  mcooper
 * Change CPU_SUN4_460 to CPU_SUN4_470.
 *
 * Revision 1.6  1991/02/21  02:20:25  mcooper
 * Add OS name and OS version stuff.
 *
 * Revision 1.5  1991/02/20  20:24:16  mcooper
 * Re-arrange default output order.
 *
 * Revision 1.4  1991/02/20  20:19:34  mcooper
 * If any item is enabled from the command
 * line (via a + option), then only print selected
 * item(s) in non verbose mode.
 *
 * Revision 1.3  1991/02/12  17:27:08  root
 * Ported to NeXT 2.0.
 *
 * Revision 1.2  91/02/11  21:58:35  mcooper
 * - Add new routines to print host name, host
 *   name aliases, network addresses, and hostid.
 * - Make verbose format easier to read with new
 *   PrintLabel() function.
 * 
 * Revision 1.1  1991/02/09  01:33:40  mcooper
 * Initial revision
 *
 */

/*
 * Display System Information
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "system.h"
#include "defs.h"

#if	defined(HAVE_UNAME)
#include <sys/utsname.h>
#endif	/* HAVE_UNAME */

/*
 * Local declarations
 */
extern char		       *AppArchCmds[];
extern char		       *KernArchCmds[];
extern char		       *ArchFiles[];
extern char		       *CPUFiles[];

int 				DoPrintAll = TRUE;
int 				DoPrintUnknown = TRUE;
int 				DoPrintVersion = FALSE;
int 				Level = L_BRIEF;
int 				Terse = FALSE;
int 				Debug = 0;
char 			       *ShowStr = NULL;
char 			       *LevelStr = NULL;
char 			       *ListStr = NULL;

#if	defined(OPTION_COMPAT)
/*
 * Old options here for backwards compatibility
 */
int				DoPrintCPU = FALSE;
int				DoPrintAppArch = FALSE;
int				DoPrintHostID = FALSE;
int				DoPrintHostName = FALSE;
int				DoPrintHostAlias = FALSE;
int				DoPrintHostAddrs = FALSE;
int				DoPrintKernArch = FALSE;
int				DoPrintKernVer = FALSE;
int				DoPrintMan = FALSE;
int				DoPrintModel = FALSE;
int				DoPrintMemory = FALSE;
int				DoPrintOSName = FALSE;
int				DoPrintOSVer = FALSE;
int				DoPrintSerialNo = FALSE;
#endif	/* OPTION_COMPAT */

/*
 * Command line options table.
 */
OptionDescRec Opts[] = {
    {"+all", 	NoArg,		OptBool, 	__ &DoPrintAll,		"1",
	 NULL,	"Print all information"},
    {"-all", 	NoArg,		OptBool, 	__ &DoPrintAll,		"0",
	 NULL,	"Don't print all information"},
    {"-level",	SepArg,		OptStr, 	__ &LevelStr,		NULL,
	 "<see \"-list level\">",	"Level names"},
    {"-list",	SepArg,		OptStr, 	__ &ListStr,		"-",
	 "level,show",	"List information about values"},
    {"-show",	SepArg,		OptStr, 	__ &ShowStr,		NULL,
	 "<see \"-list show\">",	"Show names"},
    {"+terse", 	NoArg,		OptBool, 	__ &Terse,		"1",
	 NULL,	"Print info in terse format"},
    {"-terse", 	NoArg,		OptBool, 	__ &Terse,		"0",
	 NULL,	"Don't print info in terse format"},
    {"+unknown",NoArg,		OptBool, 	__ &DoPrintUnknown,	"1",
	 NULL,	"Print unknown devices"},
    {"-unknown",NoArg,		OptBool, 	__ &DoPrintUnknown,	"0",
	 NULL,	"Don't print unknown devices"},
    {"-version",NoArg,		OptBool, 	__ &DoPrintVersion,	"1",
	 NULL,	"Print version of this program" },
    {"-debug",ArgHidden|SepArg,	OptInt, 	__ &Debug,		"1",
	 NULL,	"Enable debugging"},
#if	defined(OPTION_COMPAT)
    {"+cpu", 	NoArg|ArgHidden,OptBool,__ &DoPrintCPU,		"1" },
    {"-cpu", 	NoArg|ArgHidden,OptBool,__ &DoPrintCPU,		"0" },
    {"+arch", 	NoArg|ArgHidden,OptBool,__ &DoPrintAppArch,	"1" },
    {"-arch", 	NoArg|ArgHidden,OptBool,__ &DoPrintAppArch,	"0" },
    {"+hostid",	NoArg|ArgHidden,OptBool,__ &DoPrintHostID,	"1" },
    {"-hostid",	NoArg|ArgHidden,OptBool,__ &DoPrintHostID,	"0" },
    {"+hostname",NoArg|ArgHidden,OptBool,__ &DoPrintHostName,	"1" },
    {"-hostname",NoArg|ArgHidden,OptBool,__ &DoPrintHostName,	"0" },
    {"+hostaliases",NoArg|ArgHidden,OptBool,__ &DoPrintHostAlias,"1" },
    {"-hostaliases",NoArg|ArgHidden,OptBool,__ &DoPrintHostAlias,"0" },
    {"+hostaddrs",NoArg|ArgHidden,OptBool,__ &DoPrintHostAddrs,	"1" },
    {"-hostaddrs",NoArg|ArgHidden,OptBool,__ &DoPrintHostAddrs,	"0" },
    {"+karch", 	NoArg|ArgHidden,OptBool,__ &DoPrintKernArch,	"1" },
    {"-karch", 	NoArg|ArgHidden,OptBool,__ &DoPrintKernArch,	"0" },
    {"+kernver",NoArg|ArgHidden,OptBool,__ &DoPrintKernVer,	"1" },
    {"-kernver",NoArg|ArgHidden,OptBool,__ &DoPrintKernVer,	"0" },
    {"+man", 	NoArg|ArgHidden,OptBool,__ &DoPrintMan,		"1" },
    {"-man", 	NoArg|ArgHidden,OptBool,__ &DoPrintMan,		"0" },
    {"+model", 	NoArg|ArgHidden,OptBool,__ &DoPrintModel,	"1" },
    {"-model", 	NoArg|ArgHidden,OptBool,__ &DoPrintModel,	"0" },
    {"+memory",	NoArg|ArgHidden,OptBool,__ &DoPrintMemory,	"1" },
    {"-memory",	NoArg|ArgHidden,OptBool,__ &DoPrintMemory,	"0" },
    {"+osname",	NoArg|ArgHidden,OptBool,__ &DoPrintOSName,	"1" },
    {"-osname",	NoArg|ArgHidden,OptBool,__ &DoPrintOSName,	"0" },
    {"+osvers",	NoArg|ArgHidden,OptBool,__ &DoPrintOSVer,	"1" },
    {"-osvers",	NoArg|ArgHidden,OptBool,__ &DoPrintOSVer,	"0" },
    {"+serial",	NoArg|ArgHidden,OptBool,__ &DoPrintSerialNo,	"1" },
    {"-serial",	NoArg|ArgHidden,OptBool,__ &DoPrintSerialNo,	"0" },
#endif	/* OPTION_COMPAT */
};

/*
 * Option compatibility support
 */
#if	defined(OPTION_COMPAT)
static void			SetOptionCompat();
#define OptCom(v) v
#else
#define OptCom(v) 0
#endif

SHOWINFO ShowInfo[] = {
    { S_GEN, "general",	"GENERAL INFORMATION",	ShowGeneral },
    { S_GEN, "hostname",	"Host Name",		NULL, GetHostName,
						OptCom(&DoPrintHostName) },
    { S_GEN, "hostaliases",	"Host Aliases",		NULL, GetHostAliases,
						OptCom(&DoPrintHostAlias) },
    { S_GEN, "hostaddrs",	"Host Address(es)",	NULL, GetHostAddrs,
						OptCom(&DoPrintHostAddrs) },
    { S_GEN, "hostid",		"Host ID",		NULL, GetHostID,
						OptCom(&DoPrintHostID) },
    { S_GEN, "serial",		"Serial Number",	NULL, GetSerialNo,
						OptCom(&DoPrintSerialNo) },
    { S_GEN, "man",		"Manufacturer",		NULL, GetMan,
						OptCom(&DoPrintMan) },
    { S_GEN, "model",		"System Model",		NULL, GetModel,
						OptCom(&DoPrintModel) },
    { S_GEN, "memory",		"Main Memory",		NULL, GetMemory,
						OptCom(&DoPrintMemory) },
    { S_GEN, "romver",		"ROM Version",		NULL, GetRomVer },
    { S_GEN, "cpu",		"CPU Type",		NULL, GetCPU,
						OptCom(&DoPrintCPU) },
    { S_GEN, "arch",		"App Architecture",	NULL, GetAppArch,
						OptCom(&DoPrintAppArch) },
    { S_GEN, "karch",		"Kernel Architecture",	NULL, GetKernArch,
						OptCom(&DoPrintKernArch) },
    { S_GEN, "osname",		"OS Name",		NULL, GetOSName,
						OptCom(&DoPrintOSName) },
    { S_GEN, "osvers",		"OS Version",		NULL, GetOSVersion,
						OptCom(&DoPrintOSVer) },
    { S_GEN, "kernver",		"Kernel Version",	NULL, GetKernelVersion,
						OptCom(&DoPrintKernVer) },
    { S_DEV, "devices",	"DEVICE INFORMATION",	ShowDevices },
    { 0 },
};

/*
 * Values and names of levels
 */
NAMETAB LevelNames[] = {
    { L_BRIEF,		"brief" },
    { L_GENERAL,	"general" },
    { L_DESC,		"descriptions" },
    { L_CONFIG,		"config" },
    { L_ALL,		"all" },
    { L_DEBUG,		"debug" },
    { 0 },
};

/*
 * List table
 */
struct listtab {
    char		       *Name;
    char		       *Desc;
    void		      (*Func)();
};
typedef struct listtab LISTTAB;

static void			List();
static void			ListLevel();
static void			ListShow();

LISTTAB ListTab[] = {
    { "level",		"Values for -level option",	ListLevel },
    { "show",		"Values for -show option",	ListShow },
    { 0 },
};

/*
 * Print a label and an argument
 */
static void PrintLabel(Lbl, Str)
     char 		       *Lbl;
     char 		       *Str;
{
    if (!Terse)
	printf("%-*s: ", 20, Lbl);
    printf("%s\n", (Str && *Str) ? Str : "");
}

/*
 * Print general info
 */
extern void ShowGeneral(MyInfo, SpecInfo)
    SHOWINFO		       *MyInfo;
    SHOWINFO		       *SpecInfo;
{
    register int		i;
    int				ShowAll = TRUE;

    /*
     * Do a specific info item
     */
    if (SpecInfo) {
	PrintLabel(SpecInfo->Label, (*SpecInfo->GetFunc)());
	SpecInfo->Enable = FALSE;
	return;
    }

    /*
     * See if we are going to show all items
     */
    if (!DoPrintAll)
	for (i = 0; ShowInfo[i].Name; i++)
	    if (ShowInfo[i].Type == MyInfo->Type && 
		ShowInfo[i].GetFunc && !ShowInfo[i].Enable) {
		ShowAll = FALSE;
		break;
	    }

    if (MyInfo && (DoPrintAll || ShowAll || MyInfo->Enable))
	printf("\n\n\t%s\n\n", MyInfo->Label);

    /*
     * Print each enabled item of our type
     */
    for (i = 0; ShowInfo[i].Name; i++)
	if ((ShowInfo[i].Type == MyInfo->Type) &&
	    (ShowInfo[i].Enable || MyInfo->Enable) && ShowInfo[i].GetFunc) {
	    PrintLabel(ShowInfo[i].Label, (*ShowInfo[i].GetFunc)());
	    ShowInfo[i].Enable = FALSE;
	}

    if (MyInfo)
	MyInfo->Enable = FALSE;
}

/*
 * List Show values
 */
static void ListShow()
{
    register int		i;

    printf(
	"The following values may be specified with the \"-show\" option:\n");
    printf("\t%-20s %s\n", "VALUE", "DESCRIPTION");

    for (i = 0; ShowInfo[i].Name; i++)
	printf("\t%-20s %s%s\n",
	       ShowInfo[i].Name,
	       (ShowInfo[i].ShowFunc) ? "Show all " : "",
	       ShowInfo[i].Label
	       );
}

/*
 * List Level values
 */
static void ListLevel()
{
    register int		i;

    printf(
	"The following values may be specified with the \"-level\" option:\n");
    printf("\t%-20s\n", "VALUE");

    for (i = 0; LevelNames[i].name; i++) {
	printf("\t%s\n", LevelNames[i].name);
    }
}

/*
 * List list values
 */
static void ListList()
{
    register int		i;

    printf(
	"The following values may be specified with the \"-list\" option:\n");
    printf("\t%-20s %s\n", "VALUE", "DESCRIPTION");

    for (i = 0; ListTab[i].Name; i++) {
	printf("\t%-20s %s\n",
	       ListTab[i].Name,
	       ListTab[i].Desc
	       );
    }
}

/*
 * List information about each word found in Str.
 */
static void List(Str)
    char		       *Str;
{
    register int		i;
    char		       *Word;
    int				Found;

    if (EQ(Str, "-")) {
	ListList();
	return;
    }

    for (Word = strtok(Str, ","); Word; Word = strtok((char *)NULL, ",")) {
	for (i = 0, Found = FALSE; ListTab[i].Name && !Found; i++)
	    if (EQ(Word, ListTab[i].Name)) {
		Found = TRUE;
		(*ListTab[i].Func)();
	    }

	if (!Found) {
	    Error("The word \"%s\" is invalid.", Word);
	    ListList();
	    return;
	}
    }
}

/*
 * Get argument number "arg" from "str".
 */
static char *GetArg(Str, ArgNum)
    char 		       *Str;
    int 			ArgNum;
{
    register char 	       *p, *start;
    register int 		c;

    for (c = 1, p = Str; p && *p; ++c) {
	/* set start of word */
	start = p; 

	/* skip over word */
	while (p && *p && *p != ' ' && *p != '\t' && *p != '\n')
	    ++p;

	/* is this what we want? */
	if (c == ArgNum) {
	    if (p) *p = C_NULL;
	    break;
	}

	/* skip white space */
	while (*p == ' ' || *p == '\t')
	    ++p;
    }

    return(start);
}

/*
 * Convert integer to ASCII
 */
char *itoa(Num)
    int 			Num;
{
    static char 		Buf[BUFSIZ];

    (void) sprintf(Buf, "%d", Num);

    return(Buf);
}

/*
 * Get kernel version string
 */
extern char *GetKernelVersion()
{
    static char		       *Ptr = NULL;
    char		       *GetKernelVersionStr();

    /*
     * See if we already know the answer
     */
    if (Ptr)
	return(Ptr);

    return(Ptr = GetKernelVersionStr());
}

#if	defined(HAVE_UNAME)
/*
 * Get name of OS using uname()
 */
extern char *GetOSNameFromUname()
{
    static struct utsname 	un;

    if (uname(&un) != 0)
	return((char *) NULL);
    else
	return(un.sysname);
}
#endif	/* HAVE_UNAME */

/*
 * Get Operating System name.
 */
extern char *GetOSName()
{
#if	defined(OS_NAME)
    return(OS_NAME);
#else
    return(GetOSNameStr());
#endif	/* OS_NAME */
}

#if	defined(HAVE_UNAME)
/*
 * Get OS version number using uname()
 */
extern char *GetOSVersionFromUname()
{
    static char			Buf[BUFSIZ];
    struct utsname 		un;

    if (uname(&un) != 0) {
	return((char *) NULL);
    }

    /*
     * Vendors don't all do the same thing for storing
     * version numbers via uname().
     */
#if	defined(UNAME_REL_VER_COMB)
    (void) sprintf(Buf, "%s.%s", un.version, un.release);
#else
    (void) sprintf(Buf, "%s", un.release);
#endif 	/* UNAME_REL_VER_COMB */

    return(Buf);
}
#endif	/* HAVE_UNAME */

#if	defined(OSVERS_FROM_KERNVER)
/*
 * Get OS version by reading an a specific argument out of
 * the kernel version string.
 */
extern char *GetOSVersionFromKernVer()
{
    static char			Buf[BUFSIZ];
    register char	       *p;

    if (!(p = GetKernelVersion()))
	return((char *) NULL);

    (void) strcpy(Buf, p);
    p = GetArg(Buf, OSVERS_FROM_KERNVER);
    (void) strcpy(Buf, p);
    if ((p = index(Buf, ':')) != NULL)
	*p = C_NULL;

    return(Buf);
}
#endif	/* OSVERS_FROM_KERNVER */

/*
 * Get Operating System version
 */
extern char *GetOSVersion()
{
#if	defined(OS_VERSION)
    return(OS_VERSION);
#else
    char 		       *Str;
    char 		       *p;

    if (!(Str = GetOSVersionStr()))
	return(Str);

    /*
     * Zap "*-PL*".
     */
    if (*Str && 
	((p = rindex(Str, '-')) != NULL) && (strncmp(p, "-PL", 3) == 0))
	*p = C_NULL;

    return(Str);
#endif	/* !OS_VERSION */
}

/*
 * Get our hostname
 */
extern char *GetHostName()
{
    static char 		Buf[MAXHOSTNAMLEN+1];

    gethostname(Buf, sizeof(Buf));

    return((Buf[0]) ? Buf : (char *) NULL);
}

/*
 * Get aliases for this hostname
 */
extern char *GetHostAliases()
{
    static char 		Buf[BUFSIZ];
    struct hostent 	       *hp;
    register char	      **pp;
    char 		       *HName;

    if ((HName = GetHostName()) == NULL)
	return((char *) NULL);

    if ((hp = gethostbyname(HName)) == NULL) {
	Error("Cannot find lookup host info for \"%s\": %s", HName, SYSERR);
	return((char *) NULL);
    }

    for (pp = hp->h_aliases, Buf[0] = C_NULL; pp && *pp; ++pp) {
	(void) strcat(Buf, *pp);
	(void) strcat(Buf, " ");
    }

    return((Buf[0]) ? Buf : (char *) NULL);
}

/*
 * Get addresses for this host
 */
extern char *GetHostAddrs()
{
    static char 		Buf[BUFSIZ];
    struct hostent 	       *hp;
    register char	      **pp;
    char 		       *HName;

    if ((HName = GetHostName()) == NULL)
	return((char *) NULL);

    if ((hp = gethostbyname(HName)) == NULL) {
	Error("Cannot find lookup host info for \"%s\": %s", HName, SYSERR);
	return((char *) NULL);
    }

    for (pp = hp->h_addr_list, Buf[0] = C_NULL; pp && *pp; ++pp) {
	if (hp->h_addrtype == AF_INET) {
	    (void) strcat(Buf, (char *) inet_ntoa(*(struct in_addr *)*pp));
	    (void) strcat(Buf, " ");
	}
    }

    return((Buf[0]) ? Buf : (char *) NULL);
}

/*
 * Get system model
 */
extern char *GetModel()
{
    int 			Len;
    FILE 		       *fd;
    char 			Buf[BUFSIZ];
    char		       *GetModelName();
#if	defined(MODEL_COMMAND)
    extern char 	       *ModelCommand[];
#endif	/* MODEL_COMMAND */

    /*
     * Use model file if it exists.
     */
    if ((fd = fopen(MODELFILE, "r")) != NULL) {
	fgets(Buf, sizeof(Buf), fd);
	Len = strlen(Buf);
	if (Buf[Len-1] == '\n') 
	    Buf[Len-1] = C_NULL;
	return(Buf);
    }

    /*
     * If a command to get model name has been defined, try it.
     */
#if	defined(MODEL_COMMAND)
    if (p = RunCmds(ModelCommand))
	return(p);
#endif	/* MODEL_COMMAND */

    /*
     * Use a method specific to this OS
     */
    return(GetModelName());
}

/*
 * Get the short manufacturer name
 */
static char *GetManShort()
{
    return(MAN_SHORT);
}

/*
 * Get the long manufacturer name
 */
static char *GetManLong()
{
    return(MAN_LONG);
}

/*
 * Get the manufacturer info.
 */
extern char *GetMan()
{
    char 		       *ms, *ml;
    static char 		Buf[BUFSIZ];

    ms = GetManShort();
    ml = GetManLong();

    if (!Terse)
	(void) sprintf(Buf, "%s (%s)", ms, ml);
    else
	(void) sprintf(Buf, "%s", ms);

    return(Buf);
}

/*
 * Get application architecture.
 */
extern char *GetAppArch()
{
    char 		       *arch = NULL;

#if	defined(ARCH_TYPE)
    /*
     * Use predefined name if present.
     */
    if (!arch)
	return(ARCH_TYPE);
#endif	/* ARCH_TYPE */

#if	defined(HAVE_AARCHNAME)
    /*
     * Use OS specific method
     */
    if (arch = (char *) GetAppArchName())
	return(arch);
#endif	/* HAVE_AARCHNAME */

    /*
     * Try running App Arch commands
     */
    if (arch = RunCmds(AppArchCmds))
	return(arch);

    /*
     * Try testing Architecture files
     */
    if (arch = RunTestFiles(ArchFiles))
	return(arch);

    return(arch);
}

/*
 * Get kernel architecture
 */
extern char *GetKernArch()
{
    char 		       *arch = NULL;

#if	defined(KARCH_TYPE)
    /*
     * If there's a predefined KArch name, use it.
     */
    if (!arch)
	return(KARCH_TYPE);
#endif	/* KARCH_TYPE */

#if	defined(HAVE_KARCHNAME)
    /*
     * Try OS specific method
     */
    if (arch = GetKernArchName())
	return(arch);
#endif	/* HAVE_KARCHNAME */

    /*
     * Try running the KArch test commands
     */
    if (arch = RunCmds(KernArchCmds))
	return(arch);

    /*
     * We're desperate, so try using the Application Architecture
     */
    if (arch = GetAppArch())
	return(arch);

    return((char *) NULL);
}

/*
 * Get host ID
 */
extern char *GetHostID()
{
    static char 		Buf[100];

    (void) sprintf(Buf, "%08x", gethostid());

    return(Buf);
}

/*
 * Get system serial number
 */
extern char *GetSerialNo()
{
    return(GetSerialNoStr());
}

/*
 * Get CPU type
 */
extern char *GetCPU()
{
    char 		       *cpu = NULL;

#if	defined(CPU_NAME)
    cpu = CPU_NAME;
#else
#if	defined(HAVE_HOST_INFO)
    /*
     * Try the Mach method.
     * This should be in os-mach.c, but this is the only
     * OS specific case so far.
     */
    cpu = (char *) GetCpuTypeFromHostInfo();
#endif 	/* HAVE_HOST_INFO */
#endif 	/* CPU_NAME */

    if (!cpu) {
	cpu = RunTestFiles(CPUFiles);

	/*
	 * If that didn't work, try the architecture commands.
	 */
	if (!cpu)
	    cpu = RunCmds(AppArchCmds);
    }

    return(cpu);
}

/*
 * Print error message
 */
#if	defined(HAVE_VARARGS)
#include <varargs.h>
/*
 * Varargs version of Error()
 */
extern void Error(va_alist)
    va_dcl
{
    va_list 			args;
    char 		       *fmt;
    extern char 	       *ProgramName;

    (void) fprintf(stderr, "%s: ", ProgramName);
    va_start(args);
    fmt = (char *) va_arg(args, char *);
    (void) vfprintf(stderr, fmt, args);
    va_end(args);
    (void) fprintf(stderr, "\n");
}
#else
/*
 * Non-Varargs version of Error()
 */
extern void Error(fmt, a1, a2, a3, a4, a5, a6)
    char 		       *fmt;
{
    extern char 	       *ProgramName;

    (void) fprintf(stderr, "%s: ", ProgramName);
    (void) fprintf(stderr, fmt, a1, a2, a3, a4, a5, a6);
    (void) fprintf(stderr, "\n");
}
#endif 	/* !HAVE_VARARGS */

/*
 * Parse and set the level keyword list
 */
static int ParseLevel(Str)
    char		       *Str;
{
    register int		i;
    char		       *Word;
    int				Found;

    /*
     * Check each word in the LevelNames table
     */
    for (Word = strtok(Str, ","); Word; Word = strtok((char *)NULL, ",")) {
	for (i = 0, Found = FALSE; LevelNames[i].name && !Found; i++) {
	    if (strncasecmp(Word, LevelNames[i].name, strlen(Word)) == 0) {
		Level |= LevelNames[i].value;
		Found = TRUE;
	    }
	}
	if (!Found) {
	    Error("The word \"%s\" is not a valid verbosity level.", Word);
	    return(-1);
	}
    }

    return(0);
}

/*
 * Parse and set the showinfo items
 */
static int ParseShow(Str)
    char		       *Str;
{
    register int		x;
    char		       *Word;
    int				Found;

    /*
     * Check each word.
     */
    for (Word = strtok(Str, ","); Word; Word = strtok((char *)NULL, ",")) {
	/*
	 * Search the ShowInfo entries for a match.
	 */
	for (x = 0, Found = FALSE; !Found && ShowInfo[x].Name; x++)
	    if (EQ(Word, ShowInfo[x].Name)) {
		ShowInfo[x].Enable = TRUE;
		DoPrintAll = FALSE;
		Found = TRUE;
	    }

	if (!Found) {
	    Error("The word \"%s\" is not valid.", Word);
	    ListShow();
	    return(-1);
	}
    }

    return(0);
}

/*
 * Front end to calloc()
 */
char *xcalloc(nele, esize)
    int 			nele;
    int 			esize;
{
    char 		       *p, *calloc();

    if ((p = calloc(nele, esize)) == NULL) {
	Error("calloc(%d, %d) failed.", nele, esize);
	return((char *) NULL);
    }

    return(p);
}

#if	defined(OPTION_COMPAT)
/*
 * Set option compatibility
 */
static void SetOptionCompat()
{
    register int		i;

    /*
     * For every OptCompat that's TRUE, enable the real value
     */
    for (i = 0; ShowInfo[i].Name; i++) 
	if (ShowInfo[i].OptCompat && *ShowInfo[i].OptCompat) {
	    ShowInfo[i].Enable = TRUE;
	    /*
	     * These is also part of the old behavior
	     */
	    DoPrintAll = FALSE;
	    Terse = TRUE;
	}

}
#endif	/* OPTION_COMPAT */

/*
 * The beginning
 */
main(Argc, Argv)
    int 			Argc;
    char 		      **Argv;
{
    register int		i;

    if (ParseOptions(Opts, Num_Opts(Opts), Argc, Argv) < 0) {
	    exit(1);
    }

    /*
     * Show version info
     */
    if (DoPrintVersion) {
	printf("Sysinfo version %s.%d\n", VERSION_STR, PATCHLEVEL);
	exit(0);
    }
 
    /*
     * Do any list commands and exit
     */
    if (ListStr) {
	List(ListStr);
	exit(0);
    }

#if	defined(OPTION_COMPAT)
    SetOptionCompat();
#endif

    /*
     * Set verbosity strings
     */
    if (LevelStr && ParseLevel(LevelStr))
	exit(1);

    if (ShowStr && ParseShow(ShowStr))
	exit(1);

    /*
     * Run down the main topics
     */
    for (i = 0; ShowInfo[i].Name; i++) {
	if (!(DoPrintAll || ShowInfo[i].Enable))
	    continue;

	if (ShowInfo[i].ShowFunc) {
	    /*
	     * The item has a show function
	     */
	    (*ShowInfo[i].ShowFunc)(&ShowInfo[i], NULL);
	} else {
	    register int	x;
	    int			Found;

	    /*
	     * Search for and call a search function for this type of item
	     */
	    for (x = 0, Found = FALSE; !Found && ShowInfo[x].Name; x++)
		if ((ShowInfo[x].Type == ShowInfo[i].Type) &&
		    ShowInfo[x].ShowFunc) {
		    Found = TRUE;
		    (*ShowInfo[x].ShowFunc)(&ShowInfo[x], &ShowInfo[i]);
		}
	    if (!Found) {
		Error("No show function exists for \"%s\".", 
		      ShowInfo[i].Name);
		exit(1);
	    }
	}
    }

    exit(0);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.