summaryrefslogtreecommitdiffstats
path: root/kcontrol/info/info_solaris.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/info/info_solaris.cpp')
-rw-r--r--kcontrol/info/info_solaris.cpp705
1 files changed, 705 insertions, 0 deletions
diff --git a/kcontrol/info/info_solaris.cpp b/kcontrol/info/info_solaris.cpp
new file mode 100644
index 000000000..761200e75
--- /dev/null
+++ b/kcontrol/info/info_solaris.cpp
@@ -0,0 +1,705 @@
+/*
+ * info_solaris.cpp
+ *
+ * Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mnttab.h>
+#include <kstat.h>
+#include <sys/types.h>
+#include <sys/statvfs.h>
+#include <time.h>
+
+#ifdef HAVE_LIBDEVINFO_H
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mkdev.h>
+#include <sys/stat.h>
+#include <devid.h>
+#include <libdevinfo.h>
+#endif /* HAVE_LIBDEVINFO_H */
+
+#define INFO_CPU_AVAILABLE
+#define INFO_IRQ_AVAILABLE
+#define INFO_DMA_AVAILABLE
+#define INFO_PCI_AVAILABLE
+#define INFO_IOPORTS_AVAILABLE
+#define INFO_SOUND_AVAILABLE
+#define INFO_DEVICES_AVAILABLE
+#define INFO_SCSI_AVAILABLE
+#define INFO_PARTITIONS_AVAILABLE
+#define INFO_XSERVER_AVAILABLE
+
+
+bool GetInfo_CPU( QListView *lBox ) {
+
+ kstat_ctl_t *kctl;
+ kstat_t *ksp;
+ kstat_named_t *kdata;
+ char cputype[16],
+ fputype[16];
+ char *timetxt;
+ char *ptr;
+ uint32_t i, ncpus;
+ unsigned long state_begin;
+ QString state;
+ QString mhz;
+ QString inst;
+
+ /*
+ * get a kstat handle first and update the user's kstat chain
+ */
+ if( (kctl = kstat_open()) == NULL ) {
+ return false;
+ }
+ while( kstat_chain_update( kctl ) != 0 )
+ ;
+
+ /*
+ * get the # of CPUs
+ */
+ if( (ksp = kstat_lookup( kctl, "unix", 0, "system_misc" )) == NULL ) {
+ return false;
+ }
+ if( kstat_read( kctl, ksp, NULL ) == -1 ) {
+ return false;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "ncpus" );
+ if( kdata != NULL ) {
+ ncpus = kdata->value.ui32;
+ } else {
+ ncpus = 0;
+ }
+
+ lBox->addColumn( i18n( "Instance" ));
+ lBox->addColumn( i18n( "CPU Type" ));
+ lBox->addColumn( i18n( "FPU Type" ));
+ lBox->addColumn( i18n( "MHz" ));
+ lBox->addColumn( i18n( "State" ));
+
+ /*
+ * get the per-processor info
+ */
+ for( i = 0; i < ncpus; i++ ) {
+
+ if( (ksp = kstat_lookup( kctl, "cpu_info", i, NULL )) == NULL ){
+ return false;
+ }
+
+ if( kstat_read( kctl, ksp, NULL ) == -1 ) {
+ return false;
+ }
+
+ inst.setNum( i );
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "cpu_type" );
+ if( kdata != NULL ) {
+ strcpy( cputype, kdata->value.c );
+ } else {
+ sprintf( cputype, "???" );
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "fpu_type" );
+ if( kdata != NULL ) {
+ strcpy( fputype, kdata->value.c );
+ } else {
+ sprintf( fputype, "???" );
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "clock_MHz" );
+ if( kdata != NULL ) {
+ mhz.setNum( kdata->value.ul );
+ } else {
+ mhz.setNum( 0 );
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "state" );
+ if( kdata != NULL ) {
+ state = QString( kdata->value.c );
+ } else {
+ state = "???";
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "state_begin" );
+ if( kdata != NULL ) {
+ state_begin = kdata->value.i32;
+ if( (timetxt = ctime( (time_t *) &state_begin )) != NULL ) {
+ ptr = strrchr( timetxt, '\n' );
+ *ptr = '\0';
+ state += " since " + QString( timetxt );
+ }
+ }
+
+ new QListViewItem( lBox, inst, cputype, fputype, mhz, state );
+ }
+
+ // sorting_allowed = true;
+ lBox->setSorting( 0 );
+
+ return true;
+}
+
+bool GetInfo_IRQ( QListView * ) {
+ return false;
+}
+
+bool GetInfo_DMA( QListView * ) {
+ return false;
+}
+
+bool GetInfo_PCI( QListView * ) {
+ return false;
+}
+
+bool GetInfo_IO_Ports( QListView * ) {
+ return false;
+}
+
+bool GetInfo_Sound( QListView * ) {
+ return false;
+}
+
+bool GetInfo_SCSI( QListView * ) {
+ return false;
+}
+
+bool GetInfo_Partitions( QListView *lBox ) {
+
+ FILE *mnttab;
+ struct mnttab mnt;
+ struct statvfs statbuf;
+ fsblkcnt_t tmp;
+ QString total;
+ QString avail;
+ time_t mnttime;
+ char *timetxt;
+ char *ptr;
+
+ if( (mnttab = fopen( MNTTAB, "r" )) == NULL ) {
+ return false;
+ }
+
+ /*
+ * set up column headers
+ */
+ lBox->addColumn( i18n( "Device" ));
+ lBox->addColumn( i18n( "Mount Point" ));
+ lBox->addColumn( i18n( "FS Type" ));
+ lBox->addColumn( i18n( "Total Size" ));
+ // XXX: FIXME: how do I set column alignment correctly?
+ lBox->setColumnAlignment( 3, 2 );
+ lBox->addColumn( i18n( "Free Size" ));
+ // XXX: FIXME: how do I set column alignment correctly?
+ lBox->setColumnAlignment( 4, 2 );
+ lBox->addColumn( i18n( "Mount Time" ));
+ lBox->addColumn( i18n( "Mount Options" ));
+
+ /*
+ * get info about mounted file systems
+ */
+ rewind( mnttab );
+ while( getmntent( mnttab, &mnt ) == 0 ) {
+ /*
+ * skip fstype "nfs" and "autofs" for two reasons:
+ * o if the mountpoint is visible, the fs is not
+ * necessarily available (autofs option "-nobrowse")
+ * and we don't want to mount every remote fs just
+ * to get its size, do we?
+ * o the name "Partitions" for this statistics implies
+ * "local file systems only"
+ */
+ if( (strcmp( mnt.mnt_fstype, "nfs" ) == 0)
+ || (strcmp( mnt.mnt_fstype, "autofs" ) == 0) )
+ continue;
+ if( statvfs( mnt.mnt_mountp, &statbuf ) == 0 ) {
+ if( statbuf.f_blocks > 0 ) {
+ /*
+ * produce output in KB, MB, or GB for
+ * readability -- unfortunately, this
+ * breaks sorting for these columns...
+ */
+ tmp = statbuf.f_blocks
+ * (statbuf.f_frsize / 1024);
+ if( tmp > 9999 ) {
+ tmp /= 1024;
+ if( tmp > 9999 ) {
+ tmp /= 1024;
+ total.setNum( tmp );
+ total += " G";
+ } else {
+ total.setNum( tmp );
+ total += " M";
+ }
+ } else {
+ total.setNum( tmp );
+ total += " K";
+ }
+// avail.setNum( statbuf.f_bavail );
+// avail += " K";
+ tmp = statbuf.f_bavail
+ * (statbuf.f_frsize / 1024);
+ if( tmp > 9999 ) {
+ tmp /= 1024;
+ if( tmp > 9999 ) {
+ tmp /= 1024;
+ avail.setNum( tmp );
+ avail += " G";
+ } else {
+ avail.setNum( tmp );
+ avail += " M";
+ }
+ } else {
+ avail.setNum( tmp );
+ avail += " K";
+ }
+ } else {
+ total = "-";
+ avail = "-";
+ }
+ } else {
+ total = "???";
+ avail = "???";
+ }
+ /*
+ * ctime() adds a '\n' which we have to remove
+ * so that we get a one-line output for the QListViewItem
+ */
+ mnttime = (time_t) atol( mnt.mnt_time );
+ if( (timetxt = ctime( &mnttime )) != NULL ) {
+ ptr = strrchr( timetxt, '\n' );
+ *ptr = '\0';
+ }
+
+ new QListViewItem(
+ lBox,
+ mnt.mnt_special,
+ mnt.mnt_mountp,
+ mnt.mnt_fstype,
+ total,
+ avail,
+ QString( timetxt ),
+ mnt.mnt_mntopts
+ );
+ }
+ fclose( mnttab );
+
+ lBox->setSorting( 0 );
+ // sorting_allowed = true;
+
+ return true;
+}
+
+bool GetInfo_XServer_and_Video( QListView *lBox ) {
+ return GetInfo_XServer_Generic( lBox );
+}
+
+#ifdef HAVE_LIBDEVINFO_H
+/*
+ * get Solaris' device configuration data through libdevinfo(3)
+ * and display it in a prtconf(1M) style tree
+ *
+ * NOTE: though the devinfo library seems to be present on earlier
+ * Solaris releases, this interface is documented to be available
+ * since Solaris 7 (libdevinfo.h is missing on pre-Solaris 7 systems)
+ *
+ * documentation for libdevinfo(3) including code samples on which
+ * this implementation is based on is available at
+ * http://soldc.sun.com/developer/support/driver/wps/libdevinfo/
+ */
+
+/*
+ * we start with various helper routines for GetInfo_Devices()
+ */
+
+/*
+ * mktree() -- break up the device path and place its components
+ * into the tree widget
+ */
+QListViewItem *mktree( QListViewItem *top, const char *path ) {
+
+ QListViewItem *parent,
+ *previous,
+ *result;
+ char *str = strdup( path ),
+ *token;
+
+ /*
+ * start at "/"
+ */
+ parent = top;
+ result = (*top).firstChild();
+ previous = (*top).firstChild();
+
+ token = strtok( str, "/" );
+ while( token != NULL ) {
+ /*
+ * find insert pos:
+ * try to match the node at the current level
+ *
+ * NOTE: this implementation assumes that there are
+ * no two nodes with identical names at the
+ * same level of the device tree
+ */
+ while( result != NULL ) {
+ if( strcmp( token, (*result).text( 0 ).latin1()) == 0 )
+ break;
+ previous = result;
+ result = (*result).nextSibling();
+ }
+ if( result == NULL ) {
+ /*
+ * we haven't found the node, create a new one
+ */
+ result = new QListViewItem( parent,
+ previous,
+ token );
+ } else {
+ /*
+ * we've found the node
+ */
+ parent = result;
+ previous = NULL;
+ if( (*result).firstChild() == NULL ) {
+ /*
+ * create new node during next iteration
+ */
+ result->setExpandable( true );
+ result->setOpen( false );
+ } else {
+ /*
+ * follow the child path
+ */
+ result = (*result).firstChild();
+ }
+ }
+ token = strtok( NULL, "/" );
+ }
+ free( str );
+
+ return( result );
+}
+
+/*
+ * prop_type_str() -- return the property type as a string
+ */
+char *prop_type_str( di_prop_t prop ) {
+
+ switch( di_prop_type( prop )) {
+ case DI_PROP_TYPE_UNDEF_IT:
+ return( "undefined" );
+ case DI_PROP_TYPE_BOOLEAN:
+ return( "BOOL" );
+ case DI_PROP_TYPE_INT:
+ return( "INT" );
+ case DI_PROP_TYPE_STRING:
+ return( "STRING" );
+ case DI_PROP_TYPE_BYTE:
+ return( "BYTE" );
+ default:
+ return( "unknown" );
+ }
+}
+
+/*
+ * prop_type_guess() -- guess the property type
+ */
+int prop_type_guess( uchar_t *data, int len ) {
+
+ int slen;
+ int guess;
+ int i, c;
+
+ if( len < 0 )
+ return( -1 );
+ else if( len == 0 )
+ return( DI_PROP_TYPE_BOOLEAN );
+
+ slen = 0;
+ guess = DI_PROP_TYPE_STRING;
+
+ for( i = 0; i < len; i++ ) {
+ c = (int) data[i];
+ switch( c ) {
+ case 0:
+ if( i == (len - 1 ))
+ break;
+ if( slen == 0 )
+ guess = DI_PROP_TYPE_BYTE;
+ else
+ guess = slen = 0;
+ break;
+ default:
+ if( ! isprint( c ))
+ guess = DI_PROP_TYPE_BYTE;
+ else
+ slen++;
+ }
+ if( guess != DI_PROP_TYPE_STRING )
+ break;
+ }
+
+// if( (guess == DI_PROP_TYPE_BYTE) && (len % sizeof( int ) == 0 ))
+// guess = DI_PROP_TYPE_INT;
+
+ return( guess );
+}
+
+/*
+ * dump_minor_node() -- examine a device minor node
+ * this routine gets passed to di_walk_node()
+ */
+int dump_minor_node( di_node_t node, di_minor_t minor, void *arg ) {
+
+ QListViewItem *item;
+ QString majmin;
+ char *type;
+ dev_t dev;
+
+ item = new QListViewItem( (QListViewItem *) arg,
+ di_minor_name( minor ));
+ item->setExpandable( true );
+ item->setOpen( false );
+ new QListViewItem( item, i18n( "Spectype:" ),
+ (di_minor_spectype( minor ) == S_IFCHR)
+ ? i18n( "character special" )
+ : i18n( "block special" ));
+ type = di_minor_nodetype( minor );
+ new QListViewItem( item, i18n( "Nodetype:" ),
+ (type == NULL) ? "NULL" : type );
+
+ if( (dev = di_minor_devt( minor )) != DDI_DEV_T_NONE ) {
+ majmin.sprintf( "%ld/%ld", major( dev ), minor( dev ));
+ new QListViewItem( item, i18n( "Major/Minor:" ), majmin );
+ }
+
+ if( di_minor_next( node, minor ) == DI_MINOR_NIL )
+ return( DI_WALK_TERMINATE );
+ else
+ return( DI_WALK_CONTINUE );
+}
+
+/*
+ * propvalue() -- return the property value
+ */
+QString propvalue( di_prop_t prop ) {
+
+ int type;
+ int i, n;
+ char *strp;
+ int *intp;
+ uchar_t *bytep;
+ QString result;
+
+ /*
+ * Since a lot of printable strings seem to be tagged as 'byte',
+ * we're going to guess, if the property is not STRING or INT
+ * The actual type is shown in the info tree, though.
+ */
+ type = di_prop_type( prop );
+ if( (type != DI_PROP_TYPE_STRING) && (type != DI_PROP_TYPE_INT) ) {
+ n = di_prop_bytes( prop, &bytep );
+ type = prop_type_guess( bytep, n );
+ }
+
+ result = "";
+ switch( type ) {
+ case DI_PROP_TYPE_STRING:
+ if( (n = di_prop_strings( prop, &strp )) < 0 ) {
+ result = "(error)";
+ } else {
+ for( i = 0; i < n; i++ ) {
+ result += "\"";
+ result += strp;
+ result += "\" ";
+ strp += strlen( strp ) + 1;
+ }
+ }
+ break;
+ case DI_PROP_TYPE_INT:
+ if( (n = di_prop_ints( prop, &intp )) < 0 ) {
+ result = "(error)";
+ } else {
+ for( i = 0; i < n; i++ ) {
+ QString tmp;
+ tmp.setNum( intp[i] );
+ result += tmp;
+ result += " ";
+ }
+ }
+ break;
+ case DI_PROP_TYPE_BOOLEAN:
+ /*
+ * hmm, Sun's sample code handles the existence
+ * of a boolean property as "true", whereas
+ * prtconf(1M) obviously does not (Sol8, at least)
+ * -- we're doing the same and handle "bool" as "byte"
+ */
+ case DI_PROP_TYPE_BYTE:
+ if( (n = di_prop_bytes( prop, &bytep )) < 0 ) {
+ result = "(error)";
+ } else {
+ if( n == 0 ) {
+ result = i18n( "(no value)" );
+ break;
+ }
+ result = "0x";
+ for( i = 0; i < n; i++ ) {
+ QString tmp;
+ unsigned byte = (unsigned) bytep[i];
+ tmp.sprintf( "%2.2x", byte );
+ result += tmp;
+ }
+ }
+ break;
+ default:
+ result = "???";
+ }
+
+ return( result );
+}
+
+/*
+ * dump_node() -- examine a device node and its children
+ * this routine gets passed to di_walk_node()
+ */
+int dump_node( di_node_t node, void *arg ) {
+
+ QListViewItem *top = (QListViewItem *) arg,
+ *parent,
+ *previous;
+ char *path;
+ char *drivername;
+ char *names;
+ QString compatnames;
+ int i, n;
+ di_prop_t prop;
+
+ path = di_devfs_path( node );
+
+ /*
+ * if this is the root node ("/"), initialize the tree
+ */
+ if( strlen( path ) == 1 ) {
+ top->setText( 0, QString( di_binding_name( node )));
+ top->setPixmap( 0, SmallIcon( "kcmdevices" ));
+ top->setOpen( true );
+ top->setSelectable( false );
+ top->setExpandable( false );
+ }
+
+ /*
+ * place the node in the tree
+ */
+ parent = mktree( top, path );
+
+ /*
+ * we have to handle the root node differently...
+ */
+ if( strlen( path ) > 1 ) {
+ parent->setExpandable( true );
+ parent->setOpen( false );
+ } else {
+ previous = parent;
+ parent = top;
+ }
+
+ /*
+ * node name and physical device path
+ */
+ drivername = di_driver_name( node );
+ previous = new QListViewItem( parent,
+ i18n( "Driver Name:" ),
+ (drivername == NULL)
+ ? i18n( "(driver not attached)" )
+ : drivername );
+ previous = new QListViewItem( parent, previous,
+ i18n( "Binding Name:" ), di_binding_name( node ));
+
+ n = di_compatible_names( node, &names );
+ if( n < 1 ) {
+ compatnames = i18n( "(none)" );
+ } else {
+ for( i = 0; i < n; i++ ) {
+ compatnames += names;
+ compatnames += " ";
+ names += strlen( names ) + 1;
+ }
+ }
+
+ previous = new QListViewItem( parent, previous,
+ i18n( "Compatible Names:" ), compatnames );
+
+ previous = new QListViewItem( parent, previous,
+ i18n( "Physical Path:" ), QString( path ));
+
+ /*
+ * dump the node's property list (if any)
+ */
+ if( (prop = di_prop_next( node, DI_PROP_NIL )) != DI_PROP_NIL ) {
+ previous = new QListViewItem( parent, previous, i18n( "Properties" ));
+ previous->setExpandable( true );
+ previous->setOpen( false );
+ do {
+ /*
+ * property type & value
+ */
+ QListViewItem *tmp,
+ *prev;
+ tmp = new QListViewItem( previous, di_prop_name( prop ));
+ tmp->setExpandable( true );
+ tmp->setOpen( false );
+ prev = new QListViewItem( tmp, i18n( "Type:" ),
+ prop_type_str( prop ));
+ new QListViewItem( tmp, prev, i18n( "Value:" ),
+ propvalue( prop ));
+ } while( (prop = di_prop_next( node, prop )) != DI_PROP_NIL );
+ }
+
+ /*
+ * if there are minor nodes, expand the tree appropriately
+ */
+ if( di_minor_next( node, DI_MINOR_NIL ) != DI_MINOR_NIL ) {
+ previous = new QListViewItem( parent, previous, i18n( "Minor Nodes" ));
+ previous->setExpandable( true );
+ previous->setOpen( false );
+ di_walk_minor( node, NULL, 0, previous, dump_minor_node );
+ }
+
+ return( DI_WALK_CONTINUE );
+}
+
+bool GetInfo_Devices( QListView *lBox ) {
+
+ QListViewItem *top;
+ di_node_t root_node;
+
+ /*
+ * create a snapshot of the device tree
+ */
+ if( (root_node = di_init( "/", DINFOCPYALL )) == DI_NODE_NIL ) {
+ return( false );
+ }
+ // XXX: might try to di_prom_init() here as well (if we're setgid sys)
+
+ /*
+ * prepare the tree widget
+ */
+ lBox->addColumn( i18n( "Device Information" ));
+ lBox->addColumn( i18n( "Value" ));
+
+ top = new QListViewItem( lBox );
+
+ /*
+ * traverse the device tree
+ */
+ di_walk_node( root_node, DI_WALK_CLDFIRST, top, dump_node );
+
+ di_fini( root_node );
+
+ sorting_allowed = false;
+ return true;
+}
+
+#else /* ! HAVE_LIBDEVINFO_H */
+bool GetInfo_Devices( QListView * ) {
+ return false;
+}
+#endif /* ! HAVE_LIBDEVINFO_H */