/* * info_netbsd.cpp is part of the KDE program kcminfo. This displays * various information about the NetBSD system it's running on. * * Originally written by Jaromir Dolecek <dolecek@ics.muni.cz>. CPU info * code has been imported from implementation of processor.cpp for KDE 1.0 * by David Brownlee <abs@NetBSD.org> as found in NetBSD packages collection. * Hubert Feyer <hubertf@NetBSD.org> enhanced the sound information printing * quite a lot, too. * * The code is placed into public domain. Do whatever you want with it. */ #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 /* * all following functions should return TRUE, when the Information * was filled into the lBox-Widget. Returning FALSE indicates that * information was not available. */ #include <sys/types.h> #include <sys/param.h> #include <sys/sysctl.h> #include <sys/mount.h> #include <stdio.h> /* for NULL */ #include <stdlib.h> /* for malloc(3) */ #include <fstab.h> #include <qfile.h> #include <qfontmetrics.h> #include <qstrlist.h> #include <qtextstream.h> #include <kdebug.h> #include <kio/global.h> /* for KIO::convertSize() */ typedef struct { int string; int name; const char *title; } hw_info_mib_list_t; bool GetInfo_CPU(QListView *lBox) { static hw_info_mib_list_t hw_info_mib_list[]= { { 1, HW_MODEL, "Model" }, { 1, HW_MACHINE, "Machine" }, { 1, HW_MACHINE_ARCH, "Architecture" }, { 0, HW_NCPU, "Number of CPUs" }, { 0, HW_PAGESIZE, "Pagesize" }, { 0,0,0 } }; hw_info_mib_list_t *hw_info_mib; int mib[2], num; char *buf; size_t len; QString value; lBox->addColumn(i18n("Information")); lBox->addColumn(i18n("Value")); for ( hw_info_mib = hw_info_mib_list ; hw_info_mib->title ; ++hw_info_mib ) { mib[0] = CTL_HW; mib[1] = hw_info_mib->name; if ( hw_info_mib->string ) { sysctl(mib,2,NULL,&len,NULL,0); if ( (buf = (char*)malloc(len)) ) { sysctl(mib,2,buf,&len,NULL,0); value = QString::fromLocal8Bit(buf); free(buf); } else { value = QString("Unknown"); } } else { len = sizeof(num); sysctl(mib,2,&num,&len,NULL,0); value = QString::number(num); } new QListViewItem(lBox, hw_info_mib->title, value); } return true; } // this is used to find out which devices are currently // on system static bool GetDmesgInfo(QListView *lBox, const char *filter, void func(QListView *, QString s)) { QFile *dmesg = new QFile("/var/run/dmesg.boot"); bool usepipe = false; FILE *pipe = NULL; QTextStream *t; bool seencpu = false; QString s; bool found = false; if (dmesg->exists() && dmesg->open(IO_ReadOnly)) { t = new QTextStream(dmesg); } else { delete dmesg; pipe = popen("/sbin/dmesg", "r"); if (!pipe) return false; usepipe = true; t = new QTextStream(pipe, IO_ReadOnly); } QListViewItem *olditem = NULL; while(!(s = t->readLine().local8Bit()).isEmpty()) { if (!seencpu) { if (s.contains("cpu")) seencpu = true; else continue; } if (s.contains("boot device") || s.contains("WARNING: old BSD partition ID!")) break; if (!filter || (filter[0] == '^' && s.find(&filter[1]) == 0) || (filter[0] != '^' && s.contains(filter))) { if (func) func(lBox, s); else olditem = new QListViewItem(lBox, olditem, s); found = true; } } delete t; if (pipe) pclose(pipe); else { dmesg->close(); delete dmesg; } return found; } void AddIRQLine(QListView *lBox, QString s) { int pos, irqnum; char numstr[3]; pos = s.find(" irq "); irqnum = (pos < 0) ? 0 : atoi(&s.ascii()[pos+5]); if (irqnum) snprintf(numstr, 3, "%02d", irqnum); else { // this should never happen strcpy(numstr, "??"); } new QListViewItem(lBox, numstr, s); } bool GetInfo_IRQ (QListView *lBox) { lBox->addColumn(i18n("IRQ")); lBox->addColumn(i18n("Device")); lBox->setSorting(0); lBox->setShowSortIndicator(FALSE); (void) GetDmesgInfo(lBox, " irq ", AddIRQLine); return true; } bool GetInfo_DMA (QListView *) { return false; } bool GetInfo_PCI (QListView *lbox) { if (!GetDmesgInfo(lbox, "at pci", NULL)) new QListViewItem(lbox, i18n("No PCI devices found.")); return true; } bool GetInfo_IO_Ports (QListView *lbox) { if (!GetDmesgInfo(lbox, "port 0x", NULL)) new QListViewItem(lbox, i18n("No I/O port devices found.")); return true; } bool GetInfo_Sound (QListView *lbox) { lbox->setSorting(false); if (!GetDmesgInfo(lbox, "audio", NULL)) new QListViewItem(lbox, i18n("No audio devices found.")); // append information for each audio devices found QListViewItem *lvitem = lbox->firstChild(); for(; lvitem; lvitem = lvitem->nextSibling()) { QString s; int pos, len; const char *start; char *dev; s = lvitem->text(0); // The autoconf message is in form 'audio0 at auvia0: ...' if (s.find("audio") == 0 && (pos = s.find(" at ")) > 0) { pos += 4; // skip " at " start = s.ascii() + pos; len = (int) strcspn(start, ":\n\t "); dev = (char *) malloc(1 + len + 1); sprintf(dev, "^%.*s", len, start); /* safe */ GetDmesgInfo(lbox, dev, NULL); free(dev); } } return true; } bool GetInfo_Devices (QListView *lBox) { (void) GetDmesgInfo(lBox, NULL, NULL); return true; } bool GetInfo_SCSI (QListView *lbox) { if (!GetDmesgInfo(lbox, "scsibus", NULL)) new QListViewItem(lbox, i18n("No SCSI devices found.")); // remove the 'waiting %d seconds for devices to settle' message QListViewItem *lvitem = lbox->firstChild(); for(; lvitem; lvitem = lvitem->nextSibling()) { QString s = lvitem->text(0); if (s.contains("seconds for devices to settle")) { lbox->removeItem(lvitem); break; } } return true; } bool GetInfo_Partitions (QListView *lbox) { int num; // number of mounts // FIXME: older pkgsrc patches checked ST_RDONLY for this declaration // what is ST_RDONLY and how does it affect getmntinfo? struct statfs *mnt; // mount data pointer // get mount info if (!(num=getmntinfo(&mnt, MNT_WAIT))) { kdError() << "getmntinfo failed" << endl; return false; } // table headers lbox->addColumn(i18n("Device")); lbox->addColumn(i18n("Mount Point")); lbox->addColumn(i18n("FS Type")); lbox->addColumn(i18n("Total Size")); lbox->addColumn(i18n("Free Size")); lbox->addColumn(i18n("Total Nodes")); lbox->addColumn(i18n("Free Nodes")); lbox->addColumn(i18n("Flags")); // mnt points into a static array (no need to free it) for(; num--; ++mnt) { unsigned long long big[2]; QString vv[5]; big[0] = big[1] = mnt->f_bsize; // coerce the product big[0] *= mnt->f_blocks; big[1] *= mnt->f_bavail; // FIXME: use f_bfree if root? // convert to strings vv[0] = KIO::convertSize(big[0]); vv[1] = QString::fromLatin1("%1 (%2%%)") .arg(KIO::convertSize(big[1])) .arg(mnt->f_blocks ? mnt->f_bavail*100/mnt->f_blocks : 0); // FIXME: these two are large enough to punctuate vv[2] = QString::number(mnt->f_files); vv[3] = QString::fromLatin1("%1 (%2%%) ") .arg(mnt->f_ffree) .arg(mnt->f_files ? mnt->f_ffree*100/mnt->f_files : 0); vv[4] = QString::null; #define MNTF(x) if (mnt->f_flags & MNT_##x) vv[4] += QString::fromLatin1(#x " "); MNTF(ASYNC) MNTF(DEFEXPORTED) MNTF(EXKERB) MNTF(EXNORESPORT) MNTF(EXPORTANON) MNTF(EXPORTED) MNTF(EXPUBLIC) MNTF(EXRDONLY) MNTF(IGNORE) MNTF(LOCAL) MNTF(NOATIME) MNTF(NOCOREDUMP) MNTF(NODEV) MNTF(NODEVMTIME) MNTF(NOEXEC) MNTF(NOSUID) MNTF(QUOTA) MNTF(RDONLY) MNTF(ROOTFS) MNTF(SOFTDEP) MNTF(SYMPERM) MNTF(SYNCHRONOUS) MNTF(UNION) #undef MNTF // put it in the table // FIXME: there're more data but we have limited args (this is wrong! just add!) new QListViewItem(lbox, // FIXME: names need pad space mnt->f_mntfromname, mnt->f_mntonname, mnt->f_fstypename, vv[0], vv[1], vv[2], vv[3], vv[4]); } // job well done return true; } bool GetInfo_XServer_and_Video (QListView *lBox) { return GetInfo_XServer_Generic( lBox ); }