diff options
Diffstat (limited to 'kcontrol/info/info_linux.cpp')
-rw-r--r-- | kcontrol/info/info_linux.cpp | 595 |
1 files changed, 595 insertions, 0 deletions
diff --git a/kcontrol/info/info_linux.cpp b/kcontrol/info/info_linux.cpp new file mode 100644 index 000000000..9d29e890e --- /dev/null +++ b/kcontrol/info/info_linux.cpp @@ -0,0 +1,595 @@ +/* + + Linux-specific Information about the Hardware. + + (C) Copyright 1998-2006 by Helge Deller <[email protected]> + (C) Copyright 2006 by Jahshan Bhatti <[email protected]> (CD-ROM Info) + + To do (maybe?): + - include Information about XFree86 and/or Accelerated X + (needs to change configure-skript, to see, if Header-files are available !) + - maybe also include information about the video-framebuffer devices + - rewrite detection-routines (maybe not to use the /proc-fs) + - more & better sound-information + + /dev/sndstat support added: 1998-12-08 Duncan Haldane ([email protected]) + +*/ + +#include <unistd.h> +#include <syscall.h> +#include <stdio.h> +#include <sys/stat.h> +#include <linux/kernel.h> +#include <ctype.h> +#include <config.h> + +#ifdef HAVE_FSTAB_H /* some Linux-versions don't have fstab.h */ +# include <fstab.h> +# include <sys/statfs.h> +# define INFO_PARTITIONS_FULL_INFO /* show complete info */ +#elif defined HAVE_MNTENT_H /* but maybe they have mntent.h ? */ +# include <mntent.h> +# include <sys/vfs.h> +# define INFO_PARTITIONS_FULL_INFO /* show complete info */ +#else +# undef INFO_PARTITIONS_FULL_INFO /* no partitions-info */ +#endif + +#include <qregexp.h> + +#include <kapplication.h> +#include <kiconloader.h> +#include <kstdguiitem.h> + +#define INFO_CPU_AVAILABLE +#define INFO_CPU "/proc/cpuinfo" + +#define INFO_IRQ_AVAILABLE +#define INFO_IRQ "/proc/interrupts" + +#define INFO_DMA_AVAILABLE +#define INFO_DMA "/proc/dma" + +#define INFO_PCI_AVAILABLE +#define INFO_PCI "/proc/pci" + +#define INFO_IOPORTS_AVAILABLE +#define INFO_IOPORTS "/proc/ioports" + +#define INFO_SOUND_AVAILABLE +#define INFO_DEV_SNDSTAT "/dev/sndstat" +#define INFO_SOUND "/proc/sound" +#define INFO_ASOUND "/proc/asound/oss/sndstat" +#define INFO_ASOUND09 "/proc/asound/sndstat" + +#define INFO_DEVICES_AVAILABLE +#define INFO_DEVICES "/proc/devices" +#define INFO_MISC "/proc/misc" + +#define INFO_SCSI_AVAILABLE +#define INFO_SCSI "/proc/scsi/scsi" + +#define INFO_PARTITIONS_AVAILABLE +#define INFO_PARTITIONS "/proc/partitions" +#define INFO_MOUNTED_PARTITIONS "/etc/mtab" /* on Linux... */ + +#define INFO_XSERVER_AVAILABLE + +#define INFO_CD_ROM_AVAILABLE +#define INFO_CD_ROM "/proc/sys/dev/cdrom/info" /* Feature 47242 */ + + +#define MAXCOLUMNWIDTH 600 + +bool GetInfo_ReadfromFile(QListView * lbox, const char *FileName, + const QChar& splitChar, + QListViewItem * lastitem = 0, + QListViewItem ** newlastitem = 0) +{ + bool added = false; + QFile file(FileName); + + if (!file.exists()) { + return false; + } + + if (!file.open(IO_ReadOnly)) { + /* *GetInfo_ErrorString = + i18n("You do not have read-access for the file %1!\nPlease ask your system-administrator for advice!") + .arg(FileName); + */ + return false; + } + QTextStream stream(&file); + QString line; + + while (!stream.atEnd()) { + QString s1, s2; + line = stream.readLine(); + if (!line.isEmpty()) { + if (!splitChar.isNull()) { + int pos = line.find(splitChar); + s1 = line.left(pos-1).stripWhiteSpace(); + s2 = line.mid(pos+1).stripWhiteSpace(); + } + else + s1 = line; + } + lastitem = new QListViewItem(lbox, lastitem, s1, s2); + added = true; + } + + file.close(); + if (newlastitem) + *newlastitem = lastitem; + + return added; +} + + + + +bool GetInfo_CPU(QListView * lBox) +{ + lBox->addColumn(i18n("Information")); + lBox->addColumn(i18n("Value")); + return GetInfo_ReadfromFile(lBox, INFO_CPU, ':'); +} + + +bool GetInfo_IRQ(QListView * lBox) +{ + lBox->setFont(KGlobalSettings::fixedFont()); + return GetInfo_ReadfromFile(lBox, INFO_IRQ, 0); +} + +bool GetInfo_DMA(QListView * lBox) +{ + QFile file(INFO_DMA); + + lBox->addColumn(i18n("DMA-Channel")); + lBox->addColumn(i18n("Used By")); + + if (file.exists() && file.open(IO_ReadOnly)) { + QTextStream stream(&file); + QString line; + QListViewItem *child=0L; + + while (!stream.atEnd()) { + line = stream.readLine(); + if (!line.isEmpty()) { + QRegExp rx("^\\s*(\\S+)\\s*:\\s*(\\S+)"); + if (-1 != rx.search(line)) { + child = new QListViewItem(lBox,child,rx.cap(1),rx.cap(2)); + } + } + } + file.close(); + } else { + return false; + } + + return true; +} + +bool GetInfo_PCI(QListView * lBox) +{ + int num; + sorting_allowed = false; /* no sorting by user */ + + /* ry to get the output of the lspci package first */ + if ((num = GetInfo_ReadfromPipe(lBox, "lspci -v", true)) || + (num = GetInfo_ReadfromPipe(lBox, "/sbin/lspci -v", true)) || + (num = GetInfo_ReadfromPipe(lBox, "/usr/sbin/lspci -v", true)) || + (num = GetInfo_ReadfromPipe(lBox, "/usr/local/sbin/lspci -v", true))) + return num; + + /* if lspci failed, read the contents of /proc/pci */ + return GetInfo_ReadfromFile(lBox, INFO_PCI, 0); +} + +bool GetInfo_IO_Ports(QListView * lBox) +{ + lBox->addColumn(i18n("I/O-Range")); + lBox->addColumn(i18n("Used By")); + return GetInfo_ReadfromFile(lBox, INFO_IOPORTS, ':'); +} + +bool GetInfo_Sound(QListView * lBox) +{ + sorting_allowed = false; /* no sorting by user */ + if (GetInfo_ReadfromFile(lBox, INFO_DEV_SNDSTAT, 0)) + return true; + else if (GetInfo_ReadfromFile(lBox, INFO_SOUND, 0)) + return true; + else if (GetInfo_ReadfromFile(lBox, INFO_ASOUND, 0)) + return true; + else + return GetInfo_ReadfromFile(lBox, INFO_ASOUND09, 0); +} + +bool GetInfo_Devices(QListView * lBox) +{ + QFile file; + QListViewItem *misc=0L; + + lBox->setRootIsDecorated(true); + lBox->addColumn(i18n("Devices")); + lBox->addColumn(i18n("Major Number")); + lBox->addColumn(i18n("Minor Number")); + + file.setName(INFO_DEVICES); + if (file.exists() && file.open(IO_ReadOnly)) { + QTextStream stream(&file); + QString line; + QListViewItem *parent=0L, *child=0L; + + while (!stream.atEnd()) { + line = stream.readLine(); + if (!line.isEmpty()) { + if (-1 != line.find("character device",0,false)) { + parent = new QListViewItem(lBox,parent,i18n("Character Devices")); + parent->setPixmap(0,SmallIcon("chardevice")); + parent->setOpen(true); + } else if (-1 != line.find("block device",0,false)) { + parent = new QListViewItem(lBox,parent,i18n("Block Devices")); + parent->setPixmap(0,SmallIcon("blockdevice")); + parent->setOpen(true); + } else { + QRegExp rx("^\\s*(\\S+)\\s+(\\S+)"); + if (-1 != rx.search(line)) { + if (parent) { + child = new QListViewItem(parent,child,rx.cap(2),rx.cap(1)); + } else { + child = new QListViewItem(lBox,parent,rx.cap(2),rx.cap(1)); + } + if (rx.cap(2)=="misc") { + misc=child; + } + } + } + } + } + file.close(); + } else { + return false; + } + + file.setName(INFO_MISC); + if (misc && file.exists() && file.open(IO_ReadOnly)) { + QTextStream stream(&file); + QString line; + QListViewItem *child=0L; + + misc->setText(0,i18n("Miscellaneous Devices")); + misc->setPixmap(0,SmallIcon("memory")); + misc->setOpen(true); + + while (!stream.atEnd()) { + line = stream.readLine(); + if (!line.isEmpty()) { + QRegExp rx("^\\s*(\\S+)\\s+(\\S+)"); + if (-1 != rx.search(line)) { + child = new QListViewItem(misc,child,rx.cap(2),"10",rx.cap(1)); + } + } + } + file.close(); + } + + return true; +} + +bool GetInfo_SCSI(QListView * lBox) +{ + return GetInfo_ReadfromFile(lBox, INFO_SCSI, 0); +} + +static void cleanPassword(QString & str) +{ + int index = 0; + QString passwd("password="); + + while (index >= 0) + { + index = str.find(passwd, index, FALSE); + if (index >= 0) { + index += passwd.length(); + while (index < (int) str.length() && + str[index] != ' ' && str[index] != ',') + str[index++] = '*'; + } + } +} + +#ifndef INFO_PARTITIONS_FULL_INFO + +bool GetInfo_Partitions(QListView * lBox) +{ + return GetInfo_ReadfromFile(lBox, INFO_PARTITIONS, 0); +} + +#else /* INFO_PARTITIONS_FULL_INFO */ + +// Some Ideas taken from garbazo from his source in info_fbsd.cpp + +#if SIZEOF_LONG > 4 +#define LONG_TYPE unsigned long +#else +#ifdef HAVE_LONG_LONG +#define LONG_TYPE unsigned long long +#else +/* On 32-bit systems we would get an overflow in unsigned int for + drives bigger than 4GB. Let's use the ugly type double ! */ +#define LONG_TYPE double +#endif +#endif + + + +#if ( defined(HAVE_LINUX_RAW_H) || defined(HAVE_SYS_RAW_H) ) && defined(HAVE_SYS_IOCTL_H) && defined(__GNUC__) && !defined(__STRICT_ANSI__) +#include <sys/ioctl.h> +#include <fcntl.h> + +#if defined(HAVE_SYS_RAW_H) +#include <sys/raw.h> +#elif defined(HAVE_LINUX_RAW_H) +#include <linux/raw.h> +#endif + +/* + * get raw device bindings and information + */ +void Get_LinuxRawDevices(QListView *lbox) +{ + int f, i, err; + int new_raw_devs = 1; + struct raw_config_request rq; + QString devname; + QString MB(i18n("MB")); /* "MB" = "Mega-Byte" */ + + /* try to open the raw device control file */ + f = open("/dev/rawctl", O_RDWR); + if (f == -1) { + f = open("/dev/raw", O_RDWR); + new_raw_devs = 0; + } + if (f == -1) + return; + + for (i=1; i<256; i++) { + rq.raw_minor = i; + if (ioctl(f, RAW_GETBIND, &rq)) + continue; + if (!rq.block_major) /* unbound ? */ + continue; + unsigned int minor = rq.block_minor; + char first_letter; + switch ((int)rq.block_major) { + + /* IDE drives */ + case 3: first_letter = 'a'; + set_ide_name: + devname = QString("/dev/hd%1%2") + .arg(QChar(first_letter + minor/64)) + .arg(minor&63); + break; + case 22:first_letter = 'c'; goto set_ide_name; + case 33:first_letter = 'e'; goto set_ide_name; + case 34:first_letter = 'g'; goto set_ide_name; + case 56:first_letter = 'i'; goto set_ide_name; + case 57:first_letter = 'k'; goto set_ide_name; + case 88:first_letter = 'm'; goto set_ide_name; + case 89:first_letter = 'o'; goto set_ide_name; + case 90:first_letter = 'q'; goto set_ide_name; + case 91:first_letter = 's'; goto set_ide_name; + + /* SCSI drives */ + case 8: first_letter = 'a'; + set_scsi_name: + devname = QString("/dev/sd%1%2") + .arg(QChar(first_letter + minor/16)) + .arg(minor&15); + break; + case 65:first_letter = 'q'; goto set_scsi_name; + + /* Compaq /dev/cciss devices */ + case 104: case 105: case 106: + case 107: case 108: case 109: + devname = QString("/dev/cciss/c%1d%2") + .arg((int)rq.block_major-104) + .arg(minor&15); + break; + + /* Compaq Intelligent Drive Array (ida) */ + case 72: case 73: case 74: case 75: + case 76: case 77: case 78: case 79: + devname = QString("/dev/ida/c%1d%2") + .arg((int)rq.block_major-72) + .arg(minor&15); + break; + + default: devname = QString("%1/%2") + .arg((int)rq.block_major) + .arg(minor); + + } + + /* TODO: get device size */ + QString size = ""; + + new QListViewItem(lbox, devname, + QString(new_raw_devs ? "/dev/raw/raw%1" : "/dev/raw%1").arg(i), + "raw", size, " ", ""); + } + close(f); +} +#else +#define Get_LinuxRawDevices(x) /* nothing */ +#endif + +bool GetInfo_Partitions(QListView * lbox) +{ +#define NUMCOLS 6 + QString Title[NUMCOLS]; + QStringList Mounted_Partitions; + bool found_in_List; + int n; + +#ifdef HAVE_FSTAB_H + struct fstab *fstab_ent; +# define FS_NAME fstab_ent->fs_spec // device-name +# define FS_FILE fstab_ent->fs_file // mount-point +# define FS_TYPE fstab_ent->fs_vfstype // fs-type +# define FS_MNTOPS fstab_ent->fs_mntops // mount-options +#else + struct mntent *mnt_ent; + FILE *fp; +# define FS_NAME mnt_ent->mnt_fsname // device-name +# define FS_FILE mnt_ent->mnt_dir // mount-point +# define FS_TYPE mnt_ent->mnt_type // fs-type +# define FS_MNTOPS mnt_ent->mnt_opts // mount-options +#endif + + struct statfs sfs; + LONG_TYPE total, avail; + QString str, mountopts; + QString MB(i18n("MB")); /* "MB" = "Mega-Byte" */ + + +#ifdef HAVE_FSTAB_H + if (setfsent() == 0) /* Try to open fstab */ + return false; +#else + if (!(fp = setmntent("/etc/fstab", "r"))) + return false; +#endif + + /* read the list of already mounted file-systems.. */ + QFile *file = new QFile(INFO_MOUNTED_PARTITIONS); + if (file->open(IO_ReadOnly)) { + char buf[1024]; + while (file->readLine(buf, sizeof( buf )) > 0) { + str = QString::fromLocal8Bit(buf); + if (str.length()) { + int p = str.find(' '); /* find first space. */ + if (p) + str.remove(p, 1024); /* erase all chars including space. */ + Mounted_Partitions.append(str); + } + } + file->close(); + } + delete file; + + /* create the header-tables */ + MB = QString(" ") + MB; + Title[0] = i18n("Device"); + Title[1] = i18n("Mount Point"); + Title[2] = i18n("FS Type"); + Title[3] = i18n("Total Size"); + Title[4] = i18n("Free Size"); + Title[5] = i18n("Mount Options"); + + for (n = 0; n < NUMCOLS; ++n) + lbox->addColumn(Title[n]); + + /* loop through all partitions... */ +#ifdef HAVE_FSTAB_H + while ((fstab_ent = getfsent()) != NULL) +#else + while ((mnt_ent = getmntent(fp)) != NULL) +#endif + { + total = avail = 0; /* initialize size.. */ + found_in_List = (Mounted_Partitions.contains(FS_NAME) > 0); + if (found_in_List && statfs(FS_FILE, &sfs) == 0) { + total = ((LONG_TYPE) sfs.f_blocks) * sfs.f_bsize; + avail = (getuid()? sfs.f_bavail : sfs.f_bfree) + * ((LONG_TYPE) sfs.f_bsize); + }; + /* + if (stat(fstab_ent->fs_file,&st)!=0) + total = 0; + if (!S_ISDIR(st.st_mode)) + total = 0; + */ + mountopts = FS_MNTOPS; + cleanPassword(mountopts); + if (total) + new QListViewItem(lbox, QString(FS_NAME) + " ", + QString(FS_FILE) + " ", + QString(FS_TYPE) + " ", + Value((int) (((total / 1024) + 512) / 1024), + 6) + MB, + Value((int) (((avail / 1024) + 512) / 1024), + 6) + MB, mountopts); + else + new QListViewItem(lbox, QString(FS_NAME), QString(FS_FILE), + QString(FS_TYPE), " ", " ", mountopts); + } + +#ifdef HAVE_FSTAB_H + endfsent(); /* close fstab.. */ +#else + endmntent(fp); /* close fstab.. */ +#endif + + /* get raw device entires if available... */ + Get_LinuxRawDevices(lbox); + + sorting_allowed = true; /* sorting by user allowed ! */ + lbox->setSorting(1); + + return true; +} +#endif /* INFO_PARTITIONS_FULL_INFO */ + + + + +bool GetInfo_XServer_and_Video(QListView * lBox) +{ + return GetInfo_XServer_Generic(lBox); +} + +/* GetInfo for CD-ROM Info by Jahshan Bhatti */ +bool GetInfo_CD_ROM(QListView * lBox) +{ + QFile file(INFO_CD_ROM); + lBox->addColumn(i18n("Information")); + lBox->addColumn(i18n("Value")); + + if (file.exists() && file.open(IO_ReadOnly)) { + QRegExp rx("(.+):\\s+(\\S.*)"); + QTextStream stream(&file); + QString line; + QListViewItem *child = NULL; + + while (!stream.atEnd()) { + line = stream.readLine(); + if (!line.isEmpty()) { + if (-1 != rx.search(line)) { + QString text = rx.cap(1); + QString value = rx.cap(2); + if (!text.contains('#')) { + if (value == "0") + value = KStdGuiItem::no().plainText(); + if (value == "1") + value = KStdGuiItem::yes().plainText(); + } + child = new QListViewItem(lBox,child,text,value); + } + } else { + child = new QListViewItem(lBox,child,QString::null,QString::null); + } + } + file.close(); + } else { + return false; + } + + return true; +} + |