Fix crash if key bindings specified in profile cannot be found. Improve
[personal-kdebase.git] / apps / kinfocenter / base / info_linux.cpp
blobcee8cb429b6a0488c1bf11b8501de7ce65cb6330
1 /*
3 Linux-specific Information about the Hardware.
5 (C) Copyright 1998-2001 by Helge Deller <deller@gmx.de>
7 To do (maybe?):
8 - include Information about XFree86 and/or Accelerated X
9 (needs to change configure-script, to see, if Header-files are available !)
10 - maybe also include information about the video-framebuffer devices
11 - rewrite detection-routines (maybe not to use the /proc-fs)
12 - more & better sound-information
14 /dev/sndstat support added: 1998-12-08 Duncan Haldane (f.d.m.haldane@cwix.com)
18 #include <unistd.h>
19 #include <syscall.h>
20 #include <stdio.h>
21 #include <sys/stat.h>
22 #include <linux/kernel.h>
23 #include <ctype.h>
24 #include "config-infocenter.h"
26 #ifdef HAVE_FSTAB_H /* some Linux-versions don't have fstab.h */
27 # include <fstab.h>
28 # include <sys/statfs.h>
29 # define INFO_PARTITIONS_FULL_INFO /* show complete info */
30 #elif defined HAVE_MNTENT_H /* but maybe they have mntent.h ? */
31 # include <mntent.h>
32 # include <sys/vfs.h>
33 # define INFO_PARTITIONS_FULL_INFO /* show complete info */
34 #else
35 # undef INFO_PARTITIONS_FULL_INFO /* no partitions-info */
36 #endif
38 #ifdef HAVE_PCIUTILS
39 #include "kpci.h"
40 #endif //HAVE_PCIUTILS
41 #include <QRegExp>
42 #include <QFile>
43 #include <QHeaderView>
45 #include <klocale.h>
46 #include <kiconloader.h>
47 #include <kglobalsettings.h>
48 #include <kdebug.h>
50 #define INFO_CPU "/proc/cpuinfo"
52 #define INFO_IRQ "/proc/interrupts"
53 #define INFO_DMA "/proc/dma"
55 #define INFO_PCI "/proc/pci"
57 #define INFO_IOPORTS "/proc/ioports"
59 #define INFO_DEV_SNDSTAT "/dev/sndstat"
60 #define INFO_SOUND "/proc/sound"
61 #define INFO_ASOUND "/proc/asound/oss/sndstat"
62 #define INFO_ASOUND09 "/proc/asound/sndstat"
64 #define INFO_DEVICES "/proc/devices"
65 #define INFO_MISC "/proc/misc"
67 #define INFO_SCSI "/proc/scsi/scsi"
69 #define INFO_PARTITIONS "/proc/partitions"
70 #define INFO_MOUNTED_PARTITIONS "/etc/mtab" /* on Linux... */
72 #define MAXCOLUMNWIDTH 600
74 bool GetInfo_ReadfromFile(QTreeWidget* tree, const char *FileName, const QChar& splitChar) {
75 bool added = false;
76 QFile file(FileName);
78 if (!file.exists()) {
79 return false;
82 if (!file.open(QIODevice::ReadOnly)) {
83 return false;
85 QTextStream stream(&file);
87 QString line = stream.readLine();
89 while (!line.isNull()) {
90 QString s1, s2;
91 if (!line.isEmpty()) {
92 if (!splitChar.isNull()) {
93 int pos = line.indexOf(splitChar);
94 s1 = line.left(pos-1).trimmed();
95 s2 = line.mid(pos+1).trimmed();
96 } else
97 s1 = line;
99 QStringList list;
100 list << s1 << s2;
101 new QTreeWidgetItem(tree, list);
102 added = true;
103 line = stream.readLine();
106 file.close();
108 return added;
111 bool GetInfo_CPU(QTreeWidget* tree) {
112 QStringList headers;
113 headers << i18n("Information") << i18n("Value");
114 tree->setHeaderLabels(headers);
116 return GetInfo_ReadfromFile(tree, INFO_CPU, ':');
119 bool GetInfo_IRQ(QTreeWidget* tree) {
120 tree->setFont(KGlobalSettings::fixedFont());
121 tree->setHeaderHidden(true);
123 return GetInfo_ReadfromFile(tree, INFO_IRQ, 0);
126 bool GetInfo_DMA(QTreeWidget* tree) {
127 QFile file(INFO_DMA);
129 QStringList headers;
130 headers << i18n("DMA-Channel") << i18n("Used By");
131 tree->setHeaderLabels(headers);
133 if (file.exists() && file.open(QIODevice::ReadOnly)) {
134 QTextStream stream(&file);
135 QString line;
137 line = stream.readLine();
138 while (!line.isNull()) {
139 if (!line.isEmpty()) {
140 QRegExp rx("^\\s*(\\S+)\\s*:\\s*(\\S+)");
141 if (-1 != rx.indexIn(line)) {
142 QStringList list;
143 list << rx.cap(1) << rx.cap(2);
144 new QTreeWidgetItem(tree, list);
147 line = stream.readLine();
149 file.close();
150 } else {
151 return false;
154 return true;
157 bool GetInfo_PCI(QTreeWidget* tree) {
158 int num;
160 #ifdef HAVE_PCIUTILS
161 if ( (num = GetInfo_PCIUtils(tree))) {
162 return num;
165 #endif //HAVE_PCIUTILS
166 tree->setHeaderHidden(true);
167 tree->setSortingEnabled(false);
169 /* try to get the output of the lspci package first */
170 if ((num = GetInfo_ReadfromPipe(tree, "lspci -v", true)) || (num = GetInfo_ReadfromPipe(tree, "/sbin/lspci -v", true)) || (num = GetInfo_ReadfromPipe(tree, "/usr/sbin/lspci -v", true)) || (num = GetInfo_ReadfromPipe(tree, "/usr/local/sbin/lspci -v", true)) || (num = GetInfo_ReadfromPipe(tree,
171 "/usr/bin/lspci -v", true)))
172 return num;
174 /* if lspci failed, read the contents of /proc/pci */
175 return GetInfo_ReadfromFile(tree, INFO_PCI, 0);
179 bool GetInfo_IO_Ports(QTreeWidget* tree) {
180 QStringList headers;
181 headers << i18n("I/O-Range") << i18n("Used By");
182 tree->setHeaderLabels(headers);
183 return GetInfo_ReadfromFile(tree, INFO_IOPORTS, ':');
186 bool GetInfo_Sound(QTreeWidget* tree) {
187 tree->setSortingEnabled(false);
189 if (GetInfo_ReadfromFile(tree, INFO_DEV_SNDSTAT, 0))
190 return true;
191 else if (GetInfo_ReadfromFile(tree, INFO_SOUND, 0))
192 return true;
193 else if (GetInfo_ReadfromFile(tree, INFO_ASOUND, 0))
194 return true;
195 else
196 return GetInfo_ReadfromFile(tree, INFO_ASOUND09, 0);
199 bool GetInfo_Devices(QTreeWidget* tree) {
200 kDebug() << "Linux Info Devices" << endl;
201 QFile file;
202 QTreeWidgetItem *misc=NULL;
204 tree->setRootIsDecorated(true);
205 QStringList headers;
206 headers << i18n("Devices") << i18n("Major Number") << i18n("Minor Number");
207 tree->setHeaderLabels(headers);
209 file.setFileName(INFO_DEVICES);
210 if (file.exists() && file.open(QIODevice::ReadOnly)) {
211 QTextStream stream(&file);
212 QTreeWidgetItem *parent=0L, *child=0L;
214 QString line = stream.readLine();
216 while (!line.isNull()) {
217 if (!line.isEmpty()) {
218 if (-1 != line.indexOf("character device", 0, Qt::CaseInsensitive)) {
219 QStringList list;
220 list << i18n("Character Devices");
221 parent = new QTreeWidgetItem(tree, list);
222 parent->setIcon(0, SmallIcon("chardevice"));
223 parent->setExpanded(true);
225 } else if (-1 != line.indexOf("block device", 0, Qt::CaseInsensitive)) {
226 QStringList list;
227 list << i18n("Block Devices");
228 parent = new QTreeWidgetItem(tree, list);
229 parent->setIcon(0, SmallIcon("blockdevice"));
230 parent->setExpanded(true);
232 } else {
233 QRegExp rx("^\\s*(\\S+)\\s+(\\S+)");
234 if (-1 != rx.indexIn(line)) {
235 if (parent) {
236 QStringList list;
237 list << rx.cap(2) << rx.cap(1);
238 child = new QTreeWidgetItem(parent, list);
239 } else {
240 QStringList list;
241 list << rx.cap(2) << rx.cap(1);
242 child = new QTreeWidgetItem(tree, list);
245 if (rx.cap(2)=="misc") {
246 misc=child;
251 line = stream.readLine();
253 file.close();
254 } else {
255 return false;
258 file.setFileName(INFO_MISC);
259 if (misc && file.exists() && file.open(QIODevice::ReadOnly)) {
260 QTextStream stream(&file);
262 misc->setText(0, i18n("Miscellaneous Devices"));
263 misc->setIcon(0, SmallIcon("memory"));
264 misc->setExpanded(true);
266 QString line = stream.readLine();
268 while (!line.isNull()) {
269 if (!line.isEmpty()) {
270 QRegExp rx("^\\s*(\\S+)\\s+(\\S+)");
271 if (-1 != rx.indexIn(line)) {
272 QStringList list;
273 list << rx.cap(2) << "10" << rx.cap(1);
274 new QTreeWidgetItem(misc, list);
277 line = stream.readLine();
279 file.close();
282 return true;
285 bool GetInfo_SCSI(QTreeWidget* tree) {
286 return GetInfo_ReadfromFile(tree, INFO_SCSI, 0);
289 static void cleanPassword(QString & str) {
290 int index = 0;
291 QString passwd("password=");
293 while (index >= 0) {
294 index = str.indexOf(passwd, index, Qt::CaseInsensitive);
295 if (index >= 0) {
296 index += passwd.length();
297 while (index < (int) str.length() && str[index] != ' ' && str[index] != ',')
298 str[index++] = '*';
303 #ifndef INFO_PARTITIONS_FULL_INFO
305 bool GetInfo_Partitions(QTreeWidget* tree)
307 return GetInfo_ReadfromFile(tree, INFO_PARTITIONS, 0);
310 #else /* INFO_PARTITIONS_FULL_INFO */
312 // Some Ideas taken from garbazo from his source in info_fbsd.cpp
315 #if ( defined(HAVE_LINUX_RAW_H) || defined(HAVE_SYS_RAW_H) ) && defined(HAVE_SYS_IOCTL_H) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
316 #include <sys/ioctl.h>
317 #include <fcntl.h>
319 #if defined(HAVE_SYS_RAW_H)
320 #include <sys/raw.h>
321 #elif defined(HAVE_LINUX_RAW_H)
322 #include <linux/raw.h>
323 #endif
326 * get raw device bindings and information
328 void Get_LinuxRawDevices(QTreeWidget* tree)
330 int f, i, err;
331 int new_raw_devs = 1;
332 struct raw_config_request rq;
333 QString devname;
334 QString MB(i18n("MB")); /* "MB" = "Mega-Byte" */
336 /* try to open the raw device control file */
337 f = open("/dev/rawctl", O_RDWR);
338 if (f == -1) {
339 f = open("/dev/raw", O_RDWR);
340 new_raw_devs = 0;
342 if (f == -1)
343 return;
345 for (i=1; i<256; i++) {
346 rq.raw_minor = i;
347 if (ioctl(f, RAW_GETBIND, &rq))
348 continue;
349 if (!rq.block_major) /* unbound ? */
350 continue;
351 unsigned int minor = rq.block_minor;
352 char first_letter;
353 switch ((int)rq.block_major) {
355 /* IDE drives */
356 case 3: first_letter = 'a';
357 set_ide_name:
358 devname = QString("/dev/hd%1%2")
359 .arg(QChar(first_letter + minor/64))
360 .arg(minor&63);
361 break;
362 case 22:first_letter = 'c'; goto set_ide_name;
363 case 33:first_letter = 'e'; goto set_ide_name;
364 case 34:first_letter = 'g'; goto set_ide_name;
365 case 56:first_letter = 'i'; goto set_ide_name;
366 case 57:first_letter = 'k'; goto set_ide_name;
367 case 88:first_letter = 'm'; goto set_ide_name;
368 case 89:first_letter = 'o'; goto set_ide_name;
369 case 90:first_letter = 'q'; goto set_ide_name;
370 case 91:first_letter = 's'; goto set_ide_name;
372 /* SCSI drives */
373 case 8: first_letter = 'a';
374 set_scsi_name:
375 devname = QString("/dev/sd%1%2")
376 .arg(QChar(first_letter + minor/16))
377 .arg(minor&15);
378 break;
379 case 65:first_letter = 'q'; goto set_scsi_name;
381 /* Compaq /dev/cciss devices */
382 case 104: case 105: case 106:
383 case 107: case 108: case 109:
384 devname = QString("/dev/cciss/c%1d%2")
385 .arg((int)rq.block_major-104)
386 .arg(minor&15);
387 break;
389 /* Compaq Intelligent Drive Array (ida) */
390 case 72: case 73: case 74: case 75:
391 case 76: case 77: case 78: case 79:
392 devname = QString("/dev/ida/c%1d%2")
393 .arg((int)rq.block_major-72)
394 .arg(minor&15);
395 break;
397 default: devname = QString("%1/%2")
398 .arg((int)rq.block_major)
399 .arg(minor);
403 /* TODO: get device size */
404 QString size = "";
406 QStringList list;
407 list << devname;
408 if (new_raw_devs)
409 list << QString("/dev/raw/raw%1").arg(i);
410 else
411 list << QString("/dev/raw%1").arg(i);
413 list << "raw" << size << " " << "";
414 new QTreeWidgetItem(tree, list);
416 close(f);
418 #else
419 #define Get_LinuxRawDevices(x) /* nothing */
420 #endif
422 bool GetInfo_Partitions(QTreeWidget* tree) {
423 QStringList Mounted_Partitions;
424 bool found_in_List;
425 int n;
427 #ifdef HAVE_FSTAB_H
428 struct fstab *fstab_ent;
429 # define FS_NAME fstab_ent->fs_spec // device-name
430 # define FS_FILE fstab_ent->fs_file // mount-point
431 # define FS_TYPE fstab_ent->fs_vfstype // fs-type
432 # define FS_MNTOPS fstab_ent->fs_mntops // mount-options
433 #else
434 struct mntent *mnt_ent;
435 FILE *fp;
436 # define FS_NAME mnt_ent->mnt_fsname // device-name
437 # define FS_FILE mnt_ent->mnt_dir // mount-point
438 # define FS_TYPE mnt_ent->mnt_type // fs-type
439 # define FS_MNTOPS mnt_ent->mnt_opts // mount-options
440 #endif
442 struct statfs sfs;
443 quint64 total, avail;
444 QString str, mountopts;
445 QString MB(i18n("MB")); /* "MB" = "Mega-Byte" */
447 #ifdef HAVE_FSTAB_H
448 if (setfsent() == 0) /* Try to open fstab */
449 return false;
450 #else
451 if (!(fp = setmntent("/etc/fstab", "r")))
452 return false;
453 #endif
455 /* read the list of already mounted file-systems.. */
456 QFile *file = new QFile(INFO_MOUNTED_PARTITIONS);
457 if (file->open(QIODevice::ReadOnly)) {
458 char buf[1024];
459 while (file->readLine(buf, sizeof(buf )) > 0) {
460 str = QString::fromLocal8Bit(buf);
461 if (str.length()) {
462 int p = str.indexOf(' '); /* find first space. */
463 if (p)
464 str.remove(p, 1024); /* erase all chars including space. */
465 Mounted_Partitions.append(str);
468 file->close();
470 delete file;
472 /* create the header-tables */
473 MB = QString(" ") + MB;
475 QStringList headers;
476 headers << i18n("Device") << i18n("Mount Point") << i18n("FS Type") << i18n("Total Size") << i18n("Free Size") << i18n("Mount Options");
477 tree->setHeaderLabels(headers);
479 for (n = 0; n < 6; ++n)
481 /* loop through all partitions... */
482 #ifdef HAVE_FSTAB_H
483 while ((fstab_ent = getfsent()) != NULL)
484 #else
485 while ((mnt_ent = getmntent(fp)) != NULL)
486 #endif
488 total = avail = 0; /* initialize size.. */
489 found_in_List = (Mounted_Partitions.contains(FS_NAME) > 0);
490 if (found_in_List && statfs(FS_FILE, &sfs) == 0) {
491 total = ((quint64) sfs.f_blocks) * sfs.f_bsize;
492 avail = (getuid() ? sfs.f_bavail : sfs.f_bfree) * ((quint64) sfs.f_bsize);
495 if (stat(fstab_ent->fs_file,&st)!=0)
496 total = 0;
497 if (!S_ISDIR(st.st_mode))
498 total = 0;
500 mountopts = FS_MNTOPS;
501 cleanPassword(mountopts);
502 if (total) {
503 QStringList list;
504 list << 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;
506 new QTreeWidgetItem(tree, list);
507 } else {
508 QStringList list;
509 list << QString(FS_NAME) + " " << QString(FS_FILE) + " " << QString(FS_TYPE) + " " << " " << " " << mountopts;
511 new QTreeWidgetItem(tree, list);
516 #ifdef HAVE_FSTAB_H
517 endfsent(); /* close fstab.. */
518 #else
519 endmntent(fp); /* close fstab.. */
520 #endif
522 /* get raw device entires if available... */
523 Get_LinuxRawDevices(tree);
525 tree->sortItems(1, Qt::AscendingOrder);
527 return true;
529 #endif /* INFO_PARTITIONS_FULL_INFO */
531 bool GetInfo_XServer_and_Video(QTreeWidget* tree) {
532 return GetInfo_XServer_Generic(tree);