Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / apps / kinfocenter / info / info_linux.cpp
blob406c34aa7ee8359a03e5e2ea94a7359d1a40221c
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 #include <QRegExp>
40 #include <kiconloader.h>
42 #define INFO_CPU_AVAILABLE
43 #define INFO_CPU "/proc/cpuinfo"
45 #define INFO_IRQ_AVAILABLE
46 #define INFO_IRQ "/proc/interrupts"
48 #define INFO_DMA_AVAILABLE
49 #define INFO_DMA "/proc/dma"
51 #define INFO_PCI_AVAILABLE
52 #define INFO_PCI "/proc/pci"
54 #define INFO_IOPORTS_AVAILABLE
55 #define INFO_IOPORTS "/proc/ioports"
57 #define INFO_SOUND_AVAILABLE
58 #define INFO_DEV_SNDSTAT "/dev/sndstat"
59 #define INFO_SOUND "/proc/sound"
60 #define INFO_ASOUND "/proc/asound/oss/sndstat"
61 #define INFO_ASOUND09 "/proc/asound/sndstat"
63 #define INFO_DEVICES_AVAILABLE
64 #define INFO_DEVICES "/proc/devices"
65 #define INFO_MISC "/proc/misc"
67 #define INFO_SCSI_AVAILABLE
68 #define INFO_SCSI "/proc/scsi/scsi"
70 #define INFO_PARTITIONS_AVAILABLE
71 #define INFO_PARTITIONS "/proc/partitions"
72 #define INFO_MOUNTED_PARTITIONS "/etc/mtab" /* on Linux... */
74 #define INFO_XSERVER_AVAILABLE
77 #define MAXCOLUMNWIDTH 600
79 bool GetInfo_ReadfromFile(Q3ListView * lbox, const char *FileName,
80 const QChar& splitChar,
81 Q3ListViewItem * lastitem = 0,
82 Q3ListViewItem ** newlastitem = 0)
84 bool added = false;
85 QFile file(FileName);
87 if (!file.exists()) {
88 return false;
91 if (!file.open(QIODevice::ReadOnly)) {
92 /* *GetInfo_ErrorString =
93 i18n("You do not have read-access to the file %1.\nPlease ask your system administrator for advice.")
94 .arg(FileName);
96 return false;
98 QTextStream stream(&file);
99 QString line;
101 while (!stream.atEnd()) {
102 QString s1, s2;
103 line = stream.readLine();
104 if (!line.isEmpty()) {
105 if (!splitChar.isNull()) {
106 int pos = line.indexOf(splitChar);
107 s1 = line.left(pos-1).trimmed();
108 s2 = line.mid(pos+1).trimmed();
110 else
111 s1 = line;
113 lastitem = new Q3ListViewItem(lbox, lastitem, s1, s2);
114 added = true;
117 file.close();
118 if (newlastitem)
119 *newlastitem = lastitem;
121 return added;
127 bool GetInfo_CPU(Q3ListView * lBox)
129 lBox->addColumn(i18n("Information"));
130 lBox->addColumn(i18n("Value"));
131 return GetInfo_ReadfromFile(lBox, INFO_CPU, ':');
135 bool GetInfo_IRQ(Q3ListView * lBox)
137 lBox->setFont(KGlobalSettings::fixedFont());
138 return GetInfo_ReadfromFile(lBox, INFO_IRQ, 0);
141 bool GetInfo_DMA(Q3ListView * lBox)
143 QFile file(INFO_DMA);
145 lBox->addColumn(i18n("DMA-Channel"));
146 lBox->addColumn(i18n("Used By"));
148 if (file.exists() && file.open(QIODevice::ReadOnly)) {
149 QTextStream stream(&file);
150 QString line;
151 Q3ListViewItem *child=0L;
153 while (!stream.atEnd()) {
154 line = stream.readLine();
155 if (!line.isEmpty()) {
156 QRegExp rx("^\\s*(\\S+)\\s*:\\s*(\\S+)");
157 if (-1 != rx.indexIn(line)) {
158 child = new Q3ListViewItem(lBox,child,rx.cap(1),rx.cap(2));
162 file.close();
163 } else {
164 return false;
167 return true;
170 bool GetInfo_PCI(Q3ListView * lBox)
172 int num;
173 sorting_allowed = false; /* no sorting by user */
175 /* ry to get the output of the lspci package first */
176 if ((num = GetInfo_ReadfromPipe(lBox, "lspci -v", true)) ||
177 (num = GetInfo_ReadfromPipe(lBox, "/sbin/lspci -v", true)) ||
178 (num = GetInfo_ReadfromPipe(lBox, "/usr/sbin/lspci -v", true)) ||
179 (num = GetInfo_ReadfromPipe(lBox, "/usr/local/sbin/lspci -v", true)) ||
180 (num = GetInfo_ReadfromPipe(lBox, "/usr/bin/lspci -v", true)))
181 return num;
183 /* if lspci failed, read the contents of /proc/pci */
184 return GetInfo_ReadfromFile(lBox, INFO_PCI, 0);
187 bool GetInfo_IO_Ports(Q3ListView * lBox)
189 lBox->addColumn(i18n("I/O-Range"));
190 lBox->addColumn(i18n("Used By"));
191 return GetInfo_ReadfromFile(lBox, INFO_IOPORTS, ':');
194 bool GetInfo_Sound(Q3ListView * lBox)
196 sorting_allowed = false; /* no sorting by user */
197 if (GetInfo_ReadfromFile(lBox, INFO_DEV_SNDSTAT, 0))
198 return true;
199 else if (GetInfo_ReadfromFile(lBox, INFO_SOUND, 0))
200 return true;
201 else if (GetInfo_ReadfromFile(lBox, INFO_ASOUND, 0))
202 return true;
203 else
204 return GetInfo_ReadfromFile(lBox, INFO_ASOUND09, 0);
207 bool GetInfo_Devices(Q3ListView * lBox)
209 QFile file;
210 Q3ListViewItem *misc=0L;
212 lBox->setRootIsDecorated(true);
213 lBox->addColumn(i18n("Devices"));
214 lBox->addColumn(i18n("Major Number"));
215 lBox->addColumn(i18n("Minor Number"));
217 file.setFileName(INFO_DEVICES);
218 if (file.exists() && file.open(QIODevice::ReadOnly)) {
219 QTextStream stream(&file);
220 QString line;
221 Q3ListViewItem *parent=0L, *child=0L;
223 while (!stream.atEnd()) {
224 line = stream.readLine();
225 if (!line.isEmpty()) {
226 if (-1 != line.indexOf("character device",0,Qt::CaseInsensitive)) {
227 parent = new Q3ListViewItem(lBox,parent,i18n("Character Devices"));
228 parent->setPixmap(0,SmallIcon("chardevice"));
229 parent->setOpen(true);
230 } else if (-1 != line.indexOf("block device",0,Qt::CaseInsensitive)) {
231 parent = new Q3ListViewItem(lBox,parent,i18n("Block Devices"));
232 parent->setPixmap(0,SmallIcon("blockdevice"));
233 parent->setOpen(true);
234 } else {
235 QRegExp rx("^\\s*(\\S+)\\s+(\\S+)");
236 if (-1 != rx.indexIn(line)) {
237 if (parent) {
238 child = new Q3ListViewItem(parent,child,rx.cap(2),rx.cap(1));
239 } else {
240 child = new Q3ListViewItem(lBox,parent,rx.cap(2),rx.cap(1));
242 if (rx.cap(2)=="misc") {
243 misc=child;
249 file.close();
250 } else {
251 return false;
254 file.setFileName(INFO_MISC);
255 if (misc && file.exists() && file.open(QIODevice::ReadOnly)) {
256 QTextStream stream(&file);
257 QString line;
258 Q3ListViewItem *child=0L;
260 misc->setText(0,i18n("Miscellaneous Devices"));
261 misc->setPixmap(0,SmallIcon("memory"));
262 misc->setOpen(true);
264 while (!stream.atEnd()) {
265 line = stream.readLine();
266 if (!line.isEmpty()) {
267 QRegExp rx("^\\s*(\\S+)\\s+(\\S+)");
268 if (-1 != rx.indexIn(line)) {
269 child = new Q3ListViewItem(misc,child,rx.cap(2),"10",rx.cap(1));
273 file.close();
276 return true;
279 bool GetInfo_SCSI(Q3ListView * lBox)
281 return GetInfo_ReadfromFile(lBox, INFO_SCSI, 0);
284 static void cleanPassword(QString & str)
286 int index = 0;
287 QString passwd("password=");
289 while (index >= 0)
291 index = str.indexOf(passwd, index, Qt::CaseInsensitive);
292 if (index >= 0) {
293 index += passwd.length();
294 while (index < (int) str.length() &&
295 str[index] != ' ' && str[index] != ',')
296 str[index++] = '*';
301 #ifndef INFO_PARTITIONS_FULL_INFO
303 bool GetInfo_Partitions(Q3ListView * lBox)
305 return GetInfo_ReadfromFile(lBox, INFO_PARTITIONS, 0);
308 #else /* INFO_PARTITIONS_FULL_INFO */
310 // Some Ideas taken from garbazo from his source in info_fbsd.cpp
313 #if ( defined(HAVE_LINUX_RAW_H) || defined(HAVE_SYS_RAW_H) ) && defined(HAVE_SYS_IOCTL_H) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
314 #include <sys/ioctl.h>
315 #include <fcntl.h>
317 #if defined(HAVE_SYS_RAW_H)
318 #include <sys/raw.h>
319 #elif defined(HAVE_LINUX_RAW_H)
320 #include <linux/raw.h>
321 #endif
324 * get raw device bindings and information
326 void Get_LinuxRawDevices(Q3ListView *lbox)
328 int f, i, err;
329 int new_raw_devs = 1;
330 struct raw_config_request rq;
331 QString devname;
332 QString MB(i18n("MB")); /* "MB" = "Mega-Byte" */
334 /* try to open the raw device control file */
335 f = open("/dev/rawctl", O_RDWR);
336 if (f == -1) {
337 f = open("/dev/raw", O_RDWR);
338 new_raw_devs = 0;
340 if (f == -1)
341 return;
343 for (i=1; i<256; i++) {
344 rq.raw_minor = i;
345 if (ioctl(f, RAW_GETBIND, &rq))
346 continue;
347 if (!rq.block_major) /* unbound ? */
348 continue;
349 unsigned int minor = rq.block_minor;
350 char first_letter;
351 switch ((int)rq.block_major) {
353 /* IDE drives */
354 case 3: first_letter = 'a';
355 set_ide_name:
356 devname = QString("/dev/hd%1%2")
357 .arg(QChar(first_letter + minor/64))
358 .arg(minor&63);
359 break;
360 case 22:first_letter = 'c'; goto set_ide_name;
361 case 33:first_letter = 'e'; goto set_ide_name;
362 case 34:first_letter = 'g'; goto set_ide_name;
363 case 56:first_letter = 'i'; goto set_ide_name;
364 case 57:first_letter = 'k'; goto set_ide_name;
365 case 88:first_letter = 'm'; goto set_ide_name;
366 case 89:first_letter = 'o'; goto set_ide_name;
367 case 90:first_letter = 'q'; goto set_ide_name;
368 case 91:first_letter = 's'; goto set_ide_name;
370 /* SCSI drives */
371 case 8: first_letter = 'a';
372 set_scsi_name:
373 devname = QString("/dev/sd%1%2")
374 .arg(QChar(first_letter + minor/16))
375 .arg(minor&15);
376 break;
377 case 65:first_letter = 'q'; goto set_scsi_name;
379 /* Compaq /dev/cciss devices */
380 case 104: case 105: case 106:
381 case 107: case 108: case 109:
382 devname = QString("/dev/cciss/c%1d%2")
383 .arg((int)rq.block_major-104)
384 .arg(minor&15);
385 break;
387 /* Compaq Intelligent Drive Array (ida) */
388 case 72: case 73: case 74: case 75:
389 case 76: case 77: case 78: case 79:
390 devname = QString("/dev/ida/c%1d%2")
391 .arg((int)rq.block_major-72)
392 .arg(minor&15);
393 break;
395 default: devname = QString("%1/%2")
396 .arg((int)rq.block_major)
397 .arg(minor);
401 /* TODO: get device size */
402 QString size = "";
404 new Q3ListViewItem(lbox, devname,
405 QString(new_raw_devs ? "/dev/raw/raw%1" : "/dev/raw%1").arg(i),
406 "raw", size, " ", "");
408 close(f);
410 #else
411 #define Get_LinuxRawDevices(x) /* nothing */
412 #endif
414 bool GetInfo_Partitions(Q3ListView * lbox)
416 #define NUMCOLS 6
417 QString Title[NUMCOLS];
418 QStringList Mounted_Partitions;
419 bool found_in_List;
420 int n;
422 #ifdef HAVE_FSTAB_H
423 struct fstab *fstab_ent;
424 # define FS_NAME fstab_ent->fs_spec // device-name
425 # define FS_FILE fstab_ent->fs_file // mount-point
426 # define FS_TYPE fstab_ent->fs_vfstype // fs-type
427 # define FS_MNTOPS fstab_ent->fs_mntops // mount-options
428 #else
429 struct mntent *mnt_ent;
430 FILE *fp;
431 # define FS_NAME mnt_ent->mnt_fsname // device-name
432 # define FS_FILE mnt_ent->mnt_dir // mount-point
433 # define FS_TYPE mnt_ent->mnt_type // fs-type
434 # define FS_MNTOPS mnt_ent->mnt_opts // mount-options
435 #endif
437 struct statfs sfs;
438 quint64 total, avail;
439 QString str, mountopts;
440 QString MB(i18n("MB")); /* "MB" = "Mega-Byte" */
443 #ifdef HAVE_FSTAB_H
444 if (setfsent() == 0) /* Try to open fstab */
445 return false;
446 #else
447 if (!(fp = setmntent("/etc/fstab", "r")))
448 return false;
449 #endif
451 /* read the list of already mounted file-systems.. */
452 QFile *file = new QFile(INFO_MOUNTED_PARTITIONS);
453 if (file->open(QIODevice::ReadOnly)) {
454 char buf[1024];
455 while (file->readLine(buf, sizeof( buf )) > 0) {
456 str = QString::fromLocal8Bit(buf);
457 if (str.length()) {
458 int p = str.indexOf(' '); /* find first space. */
459 if (p)
460 str.remove(p, 1024); /* erase all chars including space. */
461 Mounted_Partitions.append(str);
464 file->close();
466 delete file;
468 /* create the header-tables */
469 MB = QString(" ") + MB;
470 Title[0] = i18n("Device");
471 Title[1] = i18n("Mount Point");
472 Title[2] = i18n("FS Type");
473 Title[3] = i18n("Total Size");
474 Title[4] = i18n("Free Size");
475 Title[5] = i18n("Mount Options");
477 for (n = 0; n < NUMCOLS; ++n)
478 lbox->addColumn(Title[n]);
480 /* loop through all partitions... */
481 #ifdef HAVE_FSTAB_H
482 while ((fstab_ent = getfsent()) != NULL)
483 #else
484 while ((mnt_ent = getmntent(fp)) != NULL)
485 #endif
487 total = avail = 0; /* initialize size.. */
488 found_in_List = (Mounted_Partitions.contains(FS_NAME) > 0);
489 if (found_in_List && statfs(FS_FILE, &sfs) == 0) {
490 total = ((quint64) sfs.f_blocks) * sfs.f_bsize;
491 avail = (getuid()? sfs.f_bavail : sfs.f_bfree)
492 * ((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 new Q3ListViewItem(lbox, QString(FS_NAME) + " ",
504 QString(FS_FILE) + " ",
505 QString(FS_TYPE) + " ",
506 Value((int) (((total / 1024) + 512) / 1024),
507 6) + MB,
508 Value((int) (((avail / 1024) + 512) / 1024),
509 6) + MB, mountopts);
510 else
511 new Q3ListViewItem(lbox, QString(FS_NAME), QString(FS_FILE),
512 QString(FS_TYPE), " ", " ", mountopts);
515 #ifdef HAVE_FSTAB_H
516 endfsent(); /* close fstab.. */
517 #else
518 endmntent(fp); /* close fstab.. */
519 #endif
521 /* get raw device entires if available... */
522 Get_LinuxRawDevices(lbox);
524 sorting_allowed = true; /* sorting by user allowed ! */
525 lbox->setSorting(1);
527 return true;
529 #endif /* INFO_PARTITIONS_FULL_INFO */
534 bool GetInfo_XServer_and_Video(Q3ListView * lBox)
536 return GetInfo_XServer_Generic(lBox);