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.