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

This is os-aix.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/os-aix.c,v 1.15 1992/12/12 23:48:04 mcooper Exp mcooper $";
#endif

/*
 * $Log: os-aix.c,v $
 * Revision 1.15  1992/12/12  23:48:04  mcooper
 * Call MkDevName() with correct number of parameters.
 *
 * Revision 1.14  1992/12/12  23:18:58  mcooper
 * Only print unknown VPD in Debug mode.
 *
 * Revision 1.13  1992/11/30  01:27:55  mcooper
 * Print unknown VPD info.
 *
 * Revision 1.12  1992/11/30  01:19:04  mcooper
 * Add support for looking up VPD from CuVPD.
 *
 * Revision 1.11  1992/11/24  01:57:19  mcooper
 * Change GetKernelVersionStr() to NOOP.
 *
 * Revision 1.11  1992/11/24  01:57:19  mcooper
 * Change GetKernelVersionStr() to NOOP.
 *
 * Revision 1.10  1992/11/24  00:54:19  mcooper
 * Fix buffer problem with GetDescript().
 *
 * Revision 1.9  1992/11/24  00:51:07  mcooper
 * Make NLS catalog lookups more robust.
 *
 * Revision 1.8  1992/11/23  23:23:51  mcooper
 * Get amount of real memory from ODM CuAt.
 *
 * Revision 1.7  1992/11/23  22:53:02  mcooper
 * Get system model name from ODM CuAt.
 *
 * Revision 1.6  1992/11/21  04:32:38  mcooper
 * Add device support using ODM.
 *
 * Revision 1.5  1992/04/26  23:32:06  mcooper
 * Add Copyright notice
 *
 * Revision 1.4  1992/04/17  23:27:51  mcooper
 * Add support for ROM Version information (Sun only for now).
 *
 * Revision 1.3  1992/04/17  01:07:59  mcooper
 * More de-linting
 *
 * Revision 1.2  1992/04/15  02:04:16  mcooper
 * Change GetMemoryStr() to GetMemory().
 *
 * Revision 1.1  1992/03/28  23:57:38  mcooper
 * Initial revision
 *
 */


/*
 * AIX specific functions
 */

#include <stdio.h>
#include "system.h"
#include "defs.h"
#include "info-aix.h"
#include <nl_types.h>
#include <locale.h>


/*
 * Get ODM Error string.
 */
static char *odmerror()
{
    static char odmerrstr[BUFSIZ];

    if (odm_err_msg(odmerrno, &odmerrstr) != 0)
	(void) sprintf(odmerrstr, "unknown ODM error %d", odmerrno);

    return(odmerrstr);
}

/*
 * Get the value of attribute 'Attr' with name 'Name' 
 * from the Custom Attribute ODM.
 */
static char *GetAttrVal(Name, Attr)
    char		       *Name;
    char		       *Attr;
{
    static struct CuAt		CuAt;
    static char			buff[BUFSIZ];
    char		       *errstr = NULL;
    int				ret;

    if (odm_initialize() == -1) {
	Error("ODM initialize failed: %s", odmerror());
	return(-1);
    }

    (void) sprintf(buff, "attribute = '%s' and name = '%s'", Attr, Name);

    ret = (int) odm_get_obj(CuAt_CLASS, buff, &CuAt, ODM_FIRST);
    if (ret == -1)
	errstr = odmerror();
    else if (ret == 0)
	errstr = "No entry found";

    if (errstr) {
	if (Debug) Error("ODM get \"%s\" from \"%s\" failed: %s",
			 buff, CuAt_CLASS[0].classname, errstr);
	return((char *) NULL);
    }

    return((CuAt.value[0]) ? CuAt.value : (char *) NULL);
}

/*
 * Get the PvDv ODM entry with the criteria 'Criteria'.
 */
static struct PdDv *GetPdDv(Criteria)
    char		       *Criteria;
{
    static struct PdDv		PdDv;
    char		       *errstr = NULL;
    int				ret;

    if (odm_initialize() == -1) {
	Error("ODM initialize failed: %s", odmerror());
	return((struct PdDv *) NULL);
    }

    ret = (int) odm_get_obj(PdDv_CLASS, Criteria, &PdDv, ODM_FIRST);
    if (ret == -1)
	errstr = odmerror();
    else if (ret == 0)
	errstr = "No entry found";

    if (errstr) {
	if (Debug) Error("ODM get \"%s\" from \"%s\" failed: %s",
			 Criteria, PdDv_CLASS[0].classname, errstr);
	return((struct PdDv *) NULL);
    }

    return(&PdDv);
}

/* 
 * Clean up a VPD string.  Remove initial non alpha-numeric characters
 * as well as any trailing white space.
 */
static char *CleanVPD(string)
    char		       *string;
{
    register char	       *cp, *end;

    while (string && *string && !isalnum(*string))
	++string;

    cp = end = &string[strlen(string) - 1];

    while (cp && *cp && isspace(*cp))
	--cp;

    if (cp != end)
	*(cp+1) = C_NULL;

    return(string);
}

/*
 * Find the VPD info entry for "string".  Return a vpdinfo_t
 * entry for the matching entry and set it's "value" correctly.
 */
static vpdinfo_t *GetVPDinfo(string)
    char		       *string;
{
    extern vpdinfo_t		VPDinfo[];
    static char			buff[BUFSIZ];
    static vpdinfo_t		vpdinfo;
    register int		i;

    for (i = 0; VPDinfo[i].code; ++i) {
	if (strncasecmp(string, VPDinfo[i].code, strlen(VPDinfo[i].code)))
	    continue;

	vpdinfo.code = VPDinfo[i].code;
	vpdinfo.title = VPDinfo[i].title;
	/*
	 * The "value" portion of "string" starts after the "code" portion.
	 * CleanVPD() is harmful, so we need to pass it a private copy.
	 */
	(void) strcpy(buff, string + strlen(VPDinfo[i].code));
	vpdinfo.value = CleanVPD(buff);

	return(&vpdinfo);
    }

    if (Debug)
	printf("Unknown VPD info \"%s\".\n", string);

    return((vpdinfo_t *) NULL);
}

/*
 * Given a VPD string "vpdstr", decode it into a list of strings.
 */
static char **DecodeVPD(vpdstr)
    char		       *vpdstr;
{
    static char			buff[BUFSIZ];
    char		       *myvpdstr;
    register char	       *cp;
    vpdinfo_t		       *vpdinfo;
    char		      **list;
    int				count;

    if (!vpdstr)
	return((char **) NULL);

    /*
     * Count number of fields and allocate list accordingly.
     */
    for (count = 1; cp; cp = index(++cp, '*'));
    list = (char **) xcalloc(count + 1, sizeof(char *));
    list[0] = NULL;

    /* strtok() is destructive */
    myvpdstr = strdup(vpdstr);

    /*
     * Each field in "vpdstr" is seperated by a "*", followed by
     * the code for the field and it's value.  Looks something like:
     *
     *		*TM 19445*MF IBM
     */
    for (count = 0, cp = strtok(myvpdstr, "*"); cp; 
	 cp = strtok((char *)NULL, "*")) {
	if (!(vpdinfo = GetVPDinfo(cp)))
	    continue;

	(void) sprintf(buff, "%s is %s", vpdinfo->title, vpdinfo->value);
	list[count++] = strdup(buff);
	list[count] = (char *) NULL;
    }

    if (myvpdstr)
	(void) free(myvpdstr);

    return(list);
}

/*
 * Get and decode the Vital Product Data informatin for device "Name".
 */
static char **GetVPD(Name)
    char		       *Name;
{
    static struct CuVPD		cuvpd;
    static char			buff[BUFSIZ];
    int 			ret;

    if (odm_initialize() == -1) {
	Error("ODM initialize failed: %s", odmerror());
	return((char *) NULL);
    }

    (void) sprintf(buff, "name=%s", Name);
    ret = (int) odm_get_obj(CuVPD_CLASS, buff, &cuvpd, ODM_FIRST);
    if (ret == -1) {
	if (Debug)
	    Error("ODM get VPD object for \"%s\" failed: %s", 
		  Name, odmerror());
	return((char **) NULL);
    } else if (ret == 0) {
	if (Debug) 
	    Error("No VPD information for \"%s\".", Name);
	return((char **) NULL);
    }

    if (Debug)
	printf("VPD: name = '%s' type = %d VPD = '%s'\n", 
	       cuvpd.name, cuvpd.vpd_type, cuvpd.vpd);

    return(DecodeVPD(cuvpd.vpd));
}

/*
 * Get the system model name.
 */
extern char *GetModelName()
{
    extern NAMETAB		ModelTab[];
    register char	       *val, *cp;
    register int		i, type;

    if ((val = GetAttrVal(NN_SYS0, AT_MODELCODE)) == NULL) {
	if (Debug) Error("Cannot get \"%s\" for \"%s\" from ODM.",
			 AT_MODELCODE, NN_SYS0);
	return((char *) NULL);
    }

    type = (int) strtol(val, NULL, 0);

    if (Debug)
	printf("System type = 0x%x\n", type);

    for (i = 0; ModelTab[i].name; ++i)
	if (type == ModelTab[i].value)
	    return(ModelTab[i].name);

    if (Debug)
	Error("system model/type 0x%x is unknown.", type);

    return((char *) NULL);
}

/*
 * Get kernel version string.
 */
extern char *GetKernelVersionStr()
{
    /* No such thing in AIX */
    return((char *) NULL);
}

/*
 * Get amount of physical memory from the ODM CuAt data.
 */
extern char *GetMemory()
{
    register char	       *val;
    register int		amtval;
    static char			buff[BUFSIZ];

    if ((val = GetAttrVal(NN_SYS0, AT_REALMEM)) == NULL) {
	if (Debug) Error("Cannot get \"%s\" for \"%s\" from ODM.",
			 AT_REALMEM, NN_SYS0);
	return((char *) NULL);
    }

    amtval = (int) strtol(val, NULL, 0);
    (void) sprintf(buff, "%d MB", DivRndUp(amtval, KBYTES));

    return(buff);
}

/*
 * Get system serial number
 */
extern char *GetSerialNoStr()
{
    /* No support */
    return((char *) NULL);
}

/*
 * Get name of OS
 */
extern char *GetOSNameStr()
{
    return(GetOSNameFromUname());
}

/*
 * Get version of OS
 */
extern char *GetOSVersionStr()
{
    return(GetOSVersionFromUname());
}

/*
 * Get ROM Version
 */
extern char *GetRomVer()
{
    /* No support */
    return((char *) NULL);
}

/*
 * Take a device name, remove and then return the unit number.
 * e.g. Take "hdisk0", remove "0", and then return 0.
 */
static int GetUnit(Name)
    char		       *Name;
{
    int				unit;
    register char	       *cp;

    for (cp = Name; cp && *cp; ++cp)
	if (isdigit(*cp)) {
	    unit = (int) atoi(cp);
	    *cp = C_NULL;
	    return(unit);
	}

    return(-1);
}

/*
 * Get the location information from CuDvPtr.
 */
static char *GetLocation(CuDvPtr)
    struct CuDv		       *CuDvPtr;
{
    static char			buff[BUFSIZ];

    if (CuDvPtr->location[0]) {
	(void) sprintf(buff, "Location is %s", CuDvPtr->location);
	return(buff);
    }

    return((char *) NULL);
}

/*
 * Get Class information.
 */
static char *GetClassInfo(CuDvPtr)
    struct CuDv		       *CuDvPtr;
{
    static char			buff[BUFSIZ];

    if (CuDvPtr->PdDvLn_Lvalue[0]) {
	(void) sprintf(buff, "Class/SubClass/Type is %s", 
		       CuDvPtr->PdDvLn_Lvalue);
	return(buff);
    }

    return((char *) NULL);
}

/*
 * Set the description informatin for Device.
 */
static void SetDescript(Device, CuDvPtr)
    DEVICE		       *Device;
    struct CuDv		       *CuDvPtr;
{
    register char	       *cp;
    register char	      **cpp;
    char		      **vpdlist;
    char		      **list;
    char		       *loc = NULL, *class = NULL;
    register int		listc;

    /*
     * Get the info to be composed
     */
    loc = GetLocation(CuDvPtr);
    class = GetClassInfo(CuDvPtr);
    vpdlist = GetVPD(Device->dv_name);

    /*
     * Count the number of entries and allocate list accordingly
     */
    for (listc = 0; vpdlist && vpdlist[listc]; ++listc);
    if (loc)
	++listc;
    if (class)
	++listc;
    list = (char **) xcalloc(listc + 1, sizeof(char *));

    /*
     * Add the easy entries first
     */
    listc = 0;
    if (loc)
	list[listc++] = strdup(loc);
    if (class)
	list[listc++] = strdup(class);

    /*
     * Add each VPD item
     */
    for (cpp = vpdlist; cpp && *cpp; ++cpp)
	if (*cpp)
	    list[listc++] = *cpp;

    if (vpdlist)
	(void) free(vpdlist);

    if (list && list[0])
	Device->dv_desclist = list;
}

/*
 * Special routine to get memory information.
 */
extern DEVICE *ProbeMemory(Name, DevData, DevDataTab, CuDvPtr, PdDvPtr)
    /*ARGSUSED*/
    char 		       *Name;
    DEVDATA 		       *DevData;
    DEVDATATAB 	     	       *DevDataTab;
    struct CuDv		       *CuDvPtr;
    struct PdDv		       *PdDvPtr;
{
    DEVICE 		       *device;
    char		       *devname;
    char		       *cp;
    char			buff[BUFSIZ];

    if ((cp = GetAttrVal(Name, AT_SIZE)) == NULL)
	return((DEVICE *) NULL);

    device = NewDevice((DEVICE *) NULL);

    (void) sprintf(buff, "%s MB Memory Card", cp);
    device->dv_model = strdup(buff);

    device->dv_name = Name;
    device->dv_unit = DevData->dd_devunit;
    device->dv_master = MkMasterFromDevData(DevData);
    device->dv_type = DT_MEMORY;
    SetDescript(device, CuDvPtr);

    return(device);
}

/*
 * Get description information
 */
static char *GetDescript(CuDvPtr, PdDvPtr)
    struct CuDv		       *CuDvPtr;
    struct PdDv		       *PdDvPtr;
{
    static char			buff[BUFSIZ];
    static char			lastcat[BUFSIZ];
    static nl_catd		catd;
    char		       *msg = NULL;
    char		       *cp;

    if (!PdDvPtr->catalog[0])
	return((char *) NULL);

    /* 
     * Reuse open catalog if it's the same as the last time 
     */
    if ((int) catd <= 0 || !lastcat[0] || strcmp(PdDvPtr->catalog, lastcat)) {
	if ((int) catd > 0)
	    (void) catclose(catd);

	if ((int) catd == 0) {
	    /*
	     * First time stuff.
	     */

	    if (putenv(ENV_NLSPATH) != 0)
		if (Debug) Error("Cannot set environment $NLSPATH.");

	    /*
	     * If our LANG is "C", then set to our default in order to
	     * avoid a bug in AIX that fails to find any catalogs in 
	     * this case.
	     */
	    cp = getenv("LANG");
	    if (!cp || (cp && EQ(cp, "C"))) {
		(void) sprintf(buff, "LANG=%s", DEFAULT_LANG);
		if (putenv(strdup(buff)) != 0)
		    if (Debug) Error("Cannot set environment %s.", buff);
		buff[0] = C_NULL;
	    }
	    (void) setlocale(LC_ALL, "");
	}

	catd = catopen(PdDvPtr->catalog, 0);
	if ((int) catd <= 0)
	    if (Debug) Error("Catalog open of \"%s\" failed: %s.",
			     PdDvPtr->catalog, SYSERR);
    }

    /*
     * Retrieve the message from the catalog
     */
    if ((int) catd > 0) {
	msg = catgets(catd, PdDvPtr->setno, PdDvPtr->msgno, buff);
	/* Save catalog name */
	(void) strcpy(lastcat, PdDvPtr->catalog);
    }

    return((msg && *msg) ? msg : (char *) NULL);
}

/*
 * General routine to get device information from ODM.
 */
extern DEVICE *ProbeODM(DevData, TreePtr, CuDvPtr)
    /*ARGSUSED*/
    DEVDATA 		       *DevData;
    DEVICE 		      **TreePtr;
    struct CuDv		       *CuDvPtr;
{
    register DEVDATATAB        *pddt;
    DEVICE 		       *device;
    char		       *devname;
    char		       *desc;
    char		       *cp;
    static char			buff[BUFSIZ];
    struct PdDv		       *PdDvPtr;

    devname = MkDevName(DevData->dd_devname, DevData->dd_devunit, 0, 0);
    if (FindDeviceByName(devname, *TreePtr)) {
	if (Debug) printf("Device %s already exists.\n", devname);
	return((DEVICE *) NULL);
    }

    if (CuDvPtr->PdDvLn_Lvalue[0]) {
	(void) sprintf(buff, "uniquetype='%s'", CuDvPtr->PdDvLn_Lvalue);
	PdDvPtr = GetPdDv(buff);
    } else {
	if (Debug) Error("No PdDv link value for '%s'.", devname);
	return((char *) NULL);
    }

    /*
     * If we can't get the description for this device, then
     * use the device specific probe routine if one is defined.
     */
    if ((desc = GetDescript(CuDvPtr, PdDvPtr)) == (char *) NULL) {
	if ((pddt = GetDevDataTab(DevData->dd_devname)) && pddt->ddt_probe)
	    return((*pddt->ddt_probe)(devname, DevData, pddt, 
				      CuDvPtr, PdDvPtr));
	else {
	    if (Debug) 
		Error("No description found for '%s'.", devname);
	    return((DEVICE *) NULL);
	}
    }

    device = NewDevice((DEVICE *) NULL);

    device->dv_name = devname;
    device->dv_unit = DevData->dd_devunit;
    device->dv_master = MkMasterFromDevData(DevData);
    device->dv_type = DT_GENERIC;
    device->dv_model = strdup(desc);
    SetDescript(device, CuDvPtr);

    return(device);
}

/*
 * Build device tree by looking at the Object Database Manager (ODM)
 */
static int BuildODM(TreePtr)
    DEVICE 		      **TreePtr;
{
    static struct CuDv		CuDv;
    extern struct Class		CuDv_CLASS[];
    static DEVDATA 		DevData;
    DEVICE 		       *Dev;
    int 			op, ret;

    if (odm_initialize() == -1) {
	Error("ODM initialize failed: %s", odmerror());
	return(-1);
    }

    for (op = ODM_FIRST; ; op = ODM_NEXT) {
	/*
	 * Retrieve the object from ODM.
	 */
	ret = (int) odm_get_obj(CuDv_CLASS, (char *)NULL, &CuDv, op);
	if (ret == -1) {
	    if (Debug) Error("ODM get object \"%s\" failed: %s", 
			     CuDv_CLASS[0].classname, odmerror());
	    return(-1);
	} else if (ret == 0)
	    /*
	     * We're done
	     */
	    break;

	if (CuDv.status != AVAILABLE) {
	    if (Debug) printf("Device \"%s\" is not available.\n", CuDv.name);
	    continue;
	}

	/*
	 * This should never happen
	 */
	if (CuDv.name[0] == C_NULL)
	    continue;

	/* Make sure devdata is clean */
	bzero(&DevData, sizeof(DEVDATA));

	/* Set what we know */
	DevData.dd_devname = strdup(CuDv.name);
	DevData.dd_devunit = GetUnit(DevData.dd_devname);
	if (CuDv.parent[0]) {
	    DevData.dd_ctlrname = strdup(CuDv.parent);
	    DevData.dd_ctlrunit = GetUnit(DevData.dd_ctlrname);
	}
	DevData.dd_flags |= DD_IS_ALIVE;

	if (Debug)
	    printf("ODM: Found '%s' parent '%s' location '%s' uniq = '%s'\n",
		   CuDv.name, CuDv.parent, CuDv.location, CuDv.PdDvLn_Lvalue);

	/* Probe and add device */
	if (Dev = ProbeODM(&DevData, TreePtr, &CuDv))
	    AddDevice(Dev, TreePtr);
    }

    if (odm_terminate() != 0)
	if (Debug) Error("ODM Terminate did not succeed.");

    return(0);
}

/*
 * Build device tree using TreePtr.
 * Calls bus and method specific functions to
 * search for devices.
 */
extern int BuildDevicesAIX(TreePtr)
    DEVICE 		       **TreePtr;
{
    int 			 Found = 1;

    if (BuildODM(TreePtr) == 0)
	Found = 0;

    return(Found);
}

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