You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
596 lines
15 KiB
596 lines
15 KiB
/*
|
|
|
|
Linux-specific Information about the Hardware.
|
|
|
|
(C) Copyright 1998-2006 by Helge Deller <deller@gmx.de>
|
|
(C) Copyright 2006 by Jahshan Bhatti <jabhatti91@gmail.com> (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 (f.d.m.haldane@cwix.com)
|
|
|
|
*/
|
|
|
|
#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 <tqregexp.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(TQListView * lbox, const char *FileName,
|
|
const TQChar& splitChar,
|
|
TQListViewItem * lastitem = 0,
|
|
TQListViewItem ** newlastitem = 0)
|
|
{
|
|
bool added = false;
|
|
TQFile 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;
|
|
}
|
|
TQTextStream stream(&file);
|
|
TQString line;
|
|
|
|
while (!stream.atEnd()) {
|
|
TQString 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 TQListViewItem(lbox, lastitem, s1, s2);
|
|
added = true;
|
|
}
|
|
|
|
file.close();
|
|
if (newlastitem)
|
|
*newlastitem = lastitem;
|
|
|
|
return added;
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GetInfo_CPU(TQListView * lBox)
|
|
{
|
|
lBox->addColumn(i18n("Information"));
|
|
lBox->addColumn(i18n("Value"));
|
|
return GetInfo_ReadfromFile(lBox, INFO_CPU, ':');
|
|
}
|
|
|
|
|
|
bool GetInfo_IRQ(TQListView * lBox)
|
|
{
|
|
lBox->setFont(KGlobalSettings::fixedFont());
|
|
return GetInfo_ReadfromFile(lBox, INFO_IRQ, 0);
|
|
}
|
|
|
|
bool GetInfo_DMA(TQListView * lBox)
|
|
{
|
|
TQFile file(INFO_DMA);
|
|
|
|
lBox->addColumn(i18n("DMA-Channel"));
|
|
lBox->addColumn(i18n("Used By"));
|
|
|
|
if (file.exists() && file.open(IO_ReadOnly)) {
|
|
TQTextStream stream(&file);
|
|
TQString line;
|
|
TQListViewItem *child=0L;
|
|
|
|
while (!stream.atEnd()) {
|
|
line = stream.readLine();
|
|
if (!line.isEmpty()) {
|
|
TQRegExp rx("^\\s*(\\S+)\\s*:\\s*(\\S+)");
|
|
if (-1 != rx.search(line)) {
|
|
child = new TQListViewItem(lBox,child,rx.cap(1),rx.cap(2));
|
|
}
|
|
}
|
|
}
|
|
file.close();
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool GetInfo_PCI(TQListView * 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(TQListView * lBox)
|
|
{
|
|
lBox->addColumn(i18n("I/O-Range"));
|
|
lBox->addColumn(i18n("Used By"));
|
|
return GetInfo_ReadfromFile(lBox, INFO_IOPORTS, ':');
|
|
}
|
|
|
|
bool GetInfo_Sound(TQListView * 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(TQListView * lBox)
|
|
{
|
|
TQFile file;
|
|
TQListViewItem *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)) {
|
|
TQTextStream stream(&file);
|
|
TQString line;
|
|
TQListViewItem *parent=0L, *child=0L;
|
|
|
|
while (!stream.atEnd()) {
|
|
line = stream.readLine();
|
|
if (!line.isEmpty()) {
|
|
if (-1 != line.find("character device",0,false)) {
|
|
parent = new TQListViewItem(lBox,parent,i18n("Character Devices"));
|
|
parent->setPixmap(0,SmallIcon("chardevice"));
|
|
parent->setOpen(true);
|
|
} else if (-1 != line.find("block device",0,false)) {
|
|
parent = new TQListViewItem(lBox,parent,i18n("Block Devices"));
|
|
parent->setPixmap(0,SmallIcon("blockdevice"));
|
|
parent->setOpen(true);
|
|
} else {
|
|
TQRegExp rx("^\\s*(\\S+)\\s+(\\S+)");
|
|
if (-1 != rx.search(line)) {
|
|
if (parent) {
|
|
child = new TQListViewItem(parent,child,rx.cap(2),rx.cap(1));
|
|
} else {
|
|
child = new TQListViewItem(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)) {
|
|
TQTextStream stream(&file);
|
|
TQString line;
|
|
TQListViewItem *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()) {
|
|
TQRegExp rx("^\\s*(\\S+)\\s+(\\S+)");
|
|
if (-1 != rx.search(line)) {
|
|
child = new TQListViewItem(misc,child,rx.cap(2),"10",rx.cap(1));
|
|
}
|
|
}
|
|
}
|
|
file.close();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool GetInfo_SCSI(TQListView * lBox)
|
|
{
|
|
return GetInfo_ReadfromFile(lBox, INFO_SCSI, 0);
|
|
}
|
|
|
|
static void cleanPassword(TQString & str)
|
|
{
|
|
int index = 0;
|
|
TQString 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(TQListView * 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(TQListView *lbox)
|
|
{
|
|
int f, i, err;
|
|
int new_raw_devs = 1;
|
|
struct raw_config_request rq;
|
|
TQString devname;
|
|
TQString 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 = TQString("/dev/hd%1%2")
|
|
.arg(TQChar(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 = TQString("/dev/sd%1%2")
|
|
.arg(TQChar(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 = TQString("/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 = TQString("/dev/ida/c%1d%2")
|
|
.arg((int)rq.block_major-72)
|
|
.arg(minor&15);
|
|
break;
|
|
|
|
default: devname = TQString("%1/%2")
|
|
.arg((int)rq.block_major)
|
|
.arg(minor);
|
|
|
|
}
|
|
|
|
/* TODO: get device size */
|
|
TQString size = "";
|
|
|
|
new TQListViewItem(lbox, devname,
|
|
TQString(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(TQListView * lbox)
|
|
{
|
|
#define NUMCOLS 6
|
|
TQString Title[NUMCOLS];
|
|
TQStringList 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;
|
|
TQString str, mountopts;
|
|
TQString 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.. */
|
|
TQFile *file = new TQFile(INFO_MOUNTED_PARTITIONS);
|
|
if (file->open(IO_ReadOnly)) {
|
|
char buf[1024];
|
|
while (file->readLine(buf, sizeof( buf )) > 0) {
|
|
str = TQString::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 = TQString(" ") + 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 TQListViewItem(lbox, TQString(FS_NAME) + " ",
|
|
TQString(FS_FILE) + " ",
|
|
TQString(FS_TYPE) + " ",
|
|
Value((int) (((total / 1024) + 512) / 1024),
|
|
6) + MB,
|
|
Value((int) (((avail / 1024) + 512) / 1024),
|
|
6) + MB, mountopts);
|
|
else
|
|
new TQListViewItem(lbox, TQString(FS_NAME), TQString(FS_FILE),
|
|
TQString(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(TQListView * lBox)
|
|
{
|
|
return GetInfo_XServer_Generic(lBox);
|
|
}
|
|
|
|
/* GetInfo for CD-ROM Info by Jahshan Bhatti */
|
|
bool GetInfo_CD_ROM(TQListView * lBox)
|
|
{
|
|
TQFile file(INFO_CD_ROM);
|
|
lBox->addColumn(i18n("Information"));
|
|
lBox->addColumn(i18n("Value"));
|
|
|
|
if (file.exists() && file.open(IO_ReadOnly)) {
|
|
TQRegExp rx("(.+):\\s+(\\S.*)");
|
|
TQTextStream stream(&file);
|
|
TQString line;
|
|
TQListViewItem *child = NULL;
|
|
|
|
while (!stream.atEnd()) {
|
|
line = stream.readLine();
|
|
if (!line.isEmpty()) {
|
|
if (-1 != rx.search(line)) {
|
|
TQString text = rx.cap(1);
|
|
TQString value = rx.cap(2);
|
|
if (!text.contains('#')) {
|
|
if (value == "0")
|
|
value = KStdGuiItem::no().plainText();
|
|
if (value == "1")
|
|
value = KStdGuiItem::yes().plainText();
|
|
}
|
|
child = new TQListViewItem(lBox,child,text,value);
|
|
}
|
|
} else {
|
|
child = new TQListViewItem(lBox,child,TQString::null,TQString::null);
|
|
}
|
|
}
|
|
file.close();
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|