summaryrefslogtreecommitdiffstats
path: root/ksysguard
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit4aed2c8219774f5d797760606b8489a92ddc5163 (patch)
tree3f8c130f7d269626bf6a9447407ef6c35954426a /ksysguard
downloadtdebase-4aed2c8219774f5d797760606b8489a92ddc5163.tar.gz
tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'ksysguard')
-rw-r--r--ksysguard/CContLib/Makefile.am6
-rw-r--r--ksysguard/CContLib/ccont.c364
-rw-r--r--ksysguard/CContLib/ccont.h161
-rw-r--r--ksysguard/Makefile.am9
-rw-r--r--ksysguard/Makefile.in.temp99
-rw-r--r--ksysguard/README26
-rw-r--r--ksysguard/configure.in.in50
-rw-r--r--ksysguard/cr128-app-ksysguard.pngbin0 -> 15389 bytes
-rw-r--r--ksysguard/cr16-app-ksysguard.pngbin0 -> 913 bytes
-rw-r--r--ksysguard/cr32-app-ksysguard.pngbin0 -> 2575 bytes
-rw-r--r--ksysguard/cr48-app-ksysguard.pngbin0 -> 4804 bytes
-rw-r--r--ksysguard/cr64-app-ksysguard.pngbin0 -> 6598 bytes
-rw-r--r--ksysguard/example/Makefile.am5
-rw-r--r--ksysguard/example/eventsrc305
-rw-r--r--ksysguard/example/ksysguarddrc19
-rw-r--r--ksysguard/gui/KSGAppletSettings.cc106
-rw-r--r--ksysguard/gui/KSGAppletSettings.h49
-rw-r--r--ksysguard/gui/KSysGuardApplet.cc495
-rw-r--r--ksysguard/gui/KSysGuardApplet.h85
-rw-r--r--ksysguard/gui/KSysGuardApplet.xml15
-rw-r--r--ksysguard/gui/Makefile.am63
-rw-r--r--ksysguard/gui/ProcessTable.sgrd20
-rw-r--r--ksysguard/gui/SensorBrowser.cc412
-rw-r--r--ksysguard/gui/SensorBrowser.h193
-rw-r--r--ksysguard/gui/SensorDisplayLib/BarGraph.cc177
-rw-r--r--ksysguard/gui/SensorDisplayLib/BarGraph.h94
-rw-r--r--ksysguard/gui/SensorDisplayLib/DancingBars.cc353
-rw-r--r--ksysguard/gui/SensorDisplayLib/DancingBars.h90
-rw-r--r--ksysguard/gui/SensorDisplayLib/DancingBarsSettings.cc398
-rw-r--r--ksysguard/gui/SensorDisplayLib/DancingBarsSettings.h106
-rw-r--r--ksysguard/gui/SensorDisplayLib/DummyDisplay.cc58
-rw-r--r--ksysguard/gui/SensorDisplayLib/DummyDisplay.h44
-rw-r--r--ksysguard/gui/SensorDisplayLib/FancyPlotter.cc457
-rw-r--r--ksysguard/gui/SensorDisplayLib/FancyPlotter.h103
-rw-r--r--ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.cc637
-rw-r--r--ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.h143
-rw-r--r--ksysguard/gui/SensorDisplayLib/ListView.cc371
-rw-r--r--ksysguard/gui/SensorDisplayLib/ListView.h112
-rw-r--r--ksysguard/gui/SensorDisplayLib/ListViewSettings.cc77
-rw-r--r--ksysguard/gui/SensorDisplayLib/ListViewSettings.h57
-rw-r--r--ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui178
-rw-r--r--ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui.h56
-rw-r--r--ksysguard/gui/SensorDisplayLib/LogFile.cc285
-rw-r--r--ksysguard/gui/SensorDisplayLib/LogFile.h85
-rw-r--r--ksysguard/gui/SensorDisplayLib/LogFileSettings.ui345
-rw-r--r--ksysguard/gui/SensorDisplayLib/Makefile.am39
-rw-r--r--ksysguard/gui/SensorDisplayLib/MultiMeter.cc258
-rw-r--r--ksysguard/gui/SensorDisplayLib/MultiMeter.h79
-rw-r--r--ksysguard/gui/SensorDisplayLib/MultiMeterSettings.cc127
-rw-r--r--ksysguard/gui/SensorDisplayLib/MultiMeterSettings.h68
-rw-r--r--ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui475
-rw-r--r--ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui.h123
-rw-r--r--ksysguard/gui/SensorDisplayLib/ProcessController.cc472
-rw-r--r--ksysguard/gui/SensorDisplayLib/ProcessController.h154
-rw-r--r--ksysguard/gui/SensorDisplayLib/ProcessList.cc941
-rw-r--r--ksysguard/gui/SensorDisplayLib/ProcessList.h270
-rw-r--r--ksysguard/gui/SensorDisplayLib/ReniceDlg.cc66
-rw-r--r--ksysguard/gui/SensorDisplayLib/ReniceDlg.h61
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorDisplay.cc611
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorDisplay.h331
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLogger.cc437
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLogger.h184
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.cc106
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.h62
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui263
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui.h89
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.cc77
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.h57
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui180
-rw-r--r--ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui.h56
-rw-r--r--ksysguard/gui/SensorDisplayLib/SignalPlotter.cc648
-rw-r--r--ksysguard/gui/SensorDisplayLib/SignalPlotter.h147
-rw-r--r--ksysguard/gui/SignalIDs.h52
-rw-r--r--ksysguard/gui/SystemLoad.sgrd27
-rw-r--r--ksysguard/gui/Taskmanager.ktop6
-rw-r--r--ksysguard/gui/WorkSheet.cc698
-rw-r--r--ksysguard/gui/WorkSheet.h135
-rw-r--r--ksysguard/gui/WorkSheetSettings.cc153
-rw-r--r--ksysguard/gui/WorkSheetSettings.h60
-rw-r--r--ksysguard/gui/Workspace.cc463
-rw-r--r--ksysguard/gui/Workspace.h84
-rw-r--r--ksysguard/gui/kpm.c8
-rw-r--r--ksysguard/gui/ksgrd/HostConnector.cc217
-rw-r--r--ksysguard/gui/ksgrd/HostConnector.h74
-rw-r--r--ksysguard/gui/ksgrd/Makefile.am34
-rw-r--r--ksysguard/gui/ksgrd/SensorAgent.cc260
-rw-r--r--ksysguard/gui/ksgrd/SensorAgent.h137
-rw-r--r--ksysguard/gui/ksgrd/SensorClient.h209
-rw-r--r--ksysguard/gui/ksgrd/SensorManager.cc432
-rw-r--r--ksysguard/gui/ksgrd/SensorManager.h126
-rw-r--r--ksysguard/gui/ksgrd/SensorShellAgent.cc141
-rw-r--r--ksysguard/gui/ksgrd/SensorShellAgent.h77
-rw-r--r--ksysguard/gui/ksgrd/SensorSocketAgent.cc137
-rw-r--r--ksysguard/gui/ksgrd/SensorSocketAgent.h71
-rw-r--r--ksysguard/gui/ksgrd/StyleEngine.cc176
-rw-r--r--ksysguard/gui/ksgrd/StyleEngine.h86
-rw-r--r--ksysguard/gui/ksgrd/StyleSettings.cc201
-rw-r--r--ksysguard/gui/ksgrd/StyleSettings.h78
-rw-r--r--ksysguard/gui/ksgrd/TimerSettings.cc94
-rw-r--r--ksysguard/gui/ksgrd/TimerSettings.h56
-rw-r--r--ksysguard/gui/ksysguard.cc650
-rw-r--r--ksysguard/gui/ksysguard.desktop102
-rw-r--r--ksysguard/gui/ksysguard.h124
-rw-r--r--ksysguard/gui/ksysguardapplet.desktop120
-rw-r--r--ksysguard/gui/ksysguardui.rc50
-rw-r--r--ksysguard/gui/x-ksysguard.desktop86
-rw-r--r--ksysguard/ksysguardd/Command.c261
-rw-r--r--ksysguard/ksysguardd/Command.h103
-rw-r--r--ksysguard/ksysguardd/FreeBSD/CPU.c263
-rw-r--r--ksysguard/ksysguardd/FreeBSD/CPU.h49
-rw-r--r--ksysguard/ksysguardd/FreeBSD/Makefile.am8
-rw-r--r--ksysguard/ksysguardd/FreeBSD/Memory.c209
-rw-r--r--ksysguard/ksysguardd/FreeBSD/Memory.h45
-rw-r--r--ksysguard/ksysguardd/FreeBSD/ProcessList.c556
-rw-r--r--ksysguard/ksysguardd/FreeBSD/ProcessList.h38
-rw-r--r--ksysguard/ksysguardd/FreeBSD/apm.c102
-rw-r--r--ksysguard/ksysguardd/FreeBSD/apm.h34
-rw-r--r--ksysguard/ksysguardd/FreeBSD/diskstat.c256
-rw-r--r--ksysguard/ksysguardd/FreeBSD/diskstat.h40
-rw-r--r--ksysguard/ksysguardd/FreeBSD/loadavg.c96
-rw-r--r--ksysguard/ksysguardd/FreeBSD/loadavg.h36
-rw-r--r--ksysguard/ksysguardd/FreeBSD/logfile.c175
-rw-r--r--ksysguard/ksysguardd/FreeBSD/logfile.h36
-rw-r--r--ksysguard/ksysguardd/FreeBSD/netdev.c353
-rw-r--r--ksysguard/ksysguardd/FreeBSD/netdev.h35
-rw-r--r--ksysguard/ksysguardd/Irix/LoadAvg.c78
-rw-r--r--ksysguard/ksysguardd/Irix/LoadAvg.h41
-rw-r--r--ksysguard/ksysguardd/Irix/Makefile.am4
-rw-r--r--ksysguard/ksysguardd/Irix/Memory.c128
-rw-r--r--ksysguard/ksysguardd/Irix/Memory.h46
-rw-r--r--ksysguard/ksysguardd/Irix/NetDev.c343
-rw-r--r--ksysguard/ksysguardd/Irix/NetDev.h35
-rw-r--r--ksysguard/ksysguardd/Irix/ProcessList.c462
-rw-r--r--ksysguard/ksysguardd/Irix/ProcessList.h43
-rw-r--r--ksysguard/ksysguardd/Irix/cpu.c262
-rw-r--r--ksysguard/ksysguardd/Irix/cpu.h43
-rw-r--r--ksysguard/ksysguardd/Linux/Makefile.am14
-rw-r--r--ksysguard/ksysguardd/Linux/Memory.c293
-rw-r--r--ksysguard/ksysguardd/Linux/Memory.h45
-rw-r--r--ksysguard/ksysguardd/Linux/ProcessList.c554
-rw-r--r--ksysguard/ksysguardd/Linux/ProcessList.h38
-rw-r--r--ksysguard/ksysguardd/Linux/acpi.c418
-rw-r--r--ksysguard/ksysguardd/Linux/acpi.h45
-rw-r--r--ksysguard/ksysguardd/Linux/apm.c126
-rw-r--r--ksysguard/ksysguardd/Linux/apm.h34
-rw-r--r--ksysguard/ksysguardd/Linux/cpuinfo.c179
-rw-r--r--ksysguard/ksysguardd/Linux/cpuinfo.h32
-rw-r--r--ksysguard/ksysguardd/Linux/diskstat.c265
-rw-r--r--ksysguard/ksysguardd/Linux/diskstat.h40
-rw-r--r--ksysguard/ksysguardd/Linux/i8k.c150
-rw-r--r--ksysguard/ksysguardd/Linux/i8k.h36
-rw-r--r--ksysguard/ksysguardd/Linux/lmsensors.c309
-rw-r--r--ksysguard/ksysguardd/Linux/lmsensors.h30
-rw-r--r--ksysguard/ksysguardd/Linux/loadavg.c143
-rw-r--r--ksysguard/ksysguardd/Linux/loadavg.h36
-rw-r--r--ksysguard/ksysguardd/Linux/logfile.c172
-rw-r--r--ksysguard/ksysguardd/Linux/logfile.h36
-rw-r--r--ksysguard/ksysguardd/Linux/netdev.c367
-rw-r--r--ksysguard/ksysguardd/Linux/netdev.h35
-rw-r--r--ksysguard/ksysguardd/Linux/netstat.c495
-rw-r--r--ksysguard/ksysguardd/Linux/netstat.h39
-rw-r--r--ksysguard/ksysguardd/Linux/stat.c1184
-rw-r--r--ksysguard/ksysguardd/Linux/stat.h66
-rw-r--r--ksysguard/ksysguardd/Makefile.am35
-rw-r--r--ksysguard/ksysguardd/NetBSD/CPU.c206
-rw-r--r--ksysguard/ksysguardd/NetBSD/CPU.h49
-rw-r--r--ksysguard/ksysguardd/NetBSD/Makefile.am8
-rw-r--r--ksysguard/ksysguardd/NetBSD/Memory.c202
-rw-r--r--ksysguard/ksysguardd/NetBSD/Memory.h43
-rw-r--r--ksysguard/ksysguardd/NetBSD/ProcessList.c457
-rw-r--r--ksysguard/ksysguardd/NetBSD/ProcessList.h38
-rw-r--r--ksysguard/ksysguardd/NetBSD/apm.c100
-rw-r--r--ksysguard/ksysguardd/NetBSD/apm.h34
-rw-r--r--ksysguard/ksysguardd/NetBSD/diskstat.c249
-rw-r--r--ksysguard/ksysguardd/NetBSD/diskstat.h40
-rw-r--r--ksysguard/ksysguardd/NetBSD/loadavg.c96
-rw-r--r--ksysguard/ksysguardd/NetBSD/loadavg.h36
-rw-r--r--ksysguard/ksysguardd/NetBSD/logfile.c175
-rw-r--r--ksysguard/ksysguardd/NetBSD/logfile.h36
-rw-r--r--ksysguard/ksysguardd/NetBSD/netdev.c304
-rw-r--r--ksysguard/ksysguardd/NetBSD/netdev.h35
-rw-r--r--ksysguard/ksysguardd/OpenBSD/Makefile.am6
-rw-r--r--ksysguard/ksysguardd/OpenBSD/cpu.c209
-rw-r--r--ksysguard/ksysguardd/OpenBSD/cpu.h51
-rw-r--r--ksysguard/ksysguardd/OpenBSD/memory.c207
-rw-r--r--ksysguard/ksysguardd/OpenBSD/memory.h43
-rw-r--r--ksysguard/ksysguardd/PWUIDCache.c114
-rw-r--r--ksysguard/ksysguardd/PWUIDCache.h36
-rw-r--r--ksysguard/ksysguardd/Porting-HOWTO133
-rw-r--r--ksysguard/ksysguardd/Solaris/LoadAvg.c120
-rw-r--r--ksysguard/ksysguardd/Solaris/LoadAvg.h41
-rw-r--r--ksysguard/ksysguardd/Solaris/Makefile.am10
-rw-r--r--ksysguard/ksysguardd/Solaris/Memory.c223
-rw-r--r--ksysguard/ksysguardd/Solaris/Memory.h46
-rw-r--r--ksysguard/ksysguardd/Solaris/NetDev.c679
-rw-r--r--ksysguard/ksysguardd/Solaris/NetDev.h59
-rw-r--r--ksysguard/ksysguardd/Solaris/ProcessList.c436
-rw-r--r--ksysguard/ksysguardd/Solaris/ProcessList.h43
-rw-r--r--ksysguard/ksysguardd/Tru64/LoadAvg.c121
-rw-r--r--ksysguard/ksysguardd/Tru64/LoadAvg.h41
-rw-r--r--ksysguard/ksysguardd/Tru64/Makefile.am8
-rw-r--r--ksysguard/ksysguardd/Tru64/Memory.c237
-rw-r--r--ksysguard/ksysguardd/Tru64/Memory.h46
-rw-r--r--ksysguard/ksysguardd/Tru64/NetDev.c678
-rw-r--r--ksysguard/ksysguardd/Tru64/NetDev.h59
-rw-r--r--ksysguard/ksysguardd/conf.c137
-rw-r--r--ksysguard/ksysguardd/conf.h38
-rw-r--r--ksysguard/ksysguardd/configure.in.in45
-rw-r--r--ksysguard/ksysguardd/ksysguardd.c633
-rw-r--r--ksysguard/ksysguardd/ksysguardd.h52
-rw-r--r--ksysguard/ksysguardd/modules.h151
-rw-r--r--ksysguard/pics/Makefile.am5
-rw-r--r--ksysguard/pics/X.pngbin0 -> 965 bytes
-rw-r--r--ksysguard/pics/computer.pngbin0 -> 913 bytes
-rw-r--r--ksysguard/pics/daemon.pngbin0 -> 226 bytes
-rw-r--r--ksysguard/pics/kdeapp.pngbin0 -> 1134 bytes
-rw-r--r--ksysguard/pics/kernel.pngbin0 -> 329 bytes
-rw-r--r--ksysguard/pics/ksysguardd.pngbin0 -> 1080 bytes
-rw-r--r--ksysguard/pics/running.pngbin0 -> 661 bytes
-rw-r--r--ksysguard/pics/shell.pngbin0 -> 1070 bytes
-rw-r--r--ksysguard/pics/tools.pngbin0 -> 1055 bytes
-rw-r--r--ksysguard/pics/unknownapp.pngbin0 -> 1059 bytes
-rw-r--r--ksysguard/pics/waiting.pngbin0 -> 963 bytes
-rw-r--r--ksysguard/version.h1
224 files changed, 34725 insertions, 0 deletions
diff --git a/ksysguard/CContLib/Makefile.am b/ksysguard/CContLib/Makefile.am
new file mode 100644
index 000000000..a3f5d786d
--- /dev/null
+++ b/ksysguard/CContLib/Makefile.am
@@ -0,0 +1,6 @@
+AUTOMAKE_OPTIONS = foreign
+
+noinst_LIBRARIES = libccont.a
+noinst_HEADERS = ccont.h
+
+libccont_a_SOURCES = ccont.c
diff --git a/ksysguard/CContLib/ccont.c b/ksysguard/CContLib/ccont.c
new file mode 100644
index 000000000..501429337
--- /dev/null
+++ b/ksysguard/CContLib/ccont.c
@@ -0,0 +1,364 @@
+/*
+ Lightweight C Container Library
+
+ Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
+
+ Original code was written by Chris Schlaeger <cs@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "ccont.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+struct container_info {
+ INDEX count;
+ CONTAINER currentNode;
+};
+
+typedef struct container_info T_CONTAINER_INFO;
+typedef struct container_info* CONTAINER_INFO;
+
+#define rpterr(x) fprintf(stderr, "%s\n", x)
+
+CONTAINER new_ctnr(void)
+{
+ CONTAINER_INFO info;
+ CONTAINER rootNode;
+
+ rootNode = (CONTAINER)malloc(sizeof(T_CONTAINER));
+
+ info = (CONTAINER_INFO)malloc(sizeof(T_CONTAINER_INFO));
+ info->count = 0;
+ info->currentNode = rootNode;
+
+ rootNode->next = rootNode;
+ rootNode->prev = rootNode;
+ rootNode->data = info;
+
+ return rootNode;
+}
+
+void zero_destr_ctnr(CONTAINER rootNode, DESTR_FUNC destr_func)
+{
+ INDEX counter;
+
+ if (rootNode == NIL || destr_func == NIL) {
+ rpterr("destr_ctnr: NIL argument");
+ return;
+ }
+
+ for (counter = level_ctnr(rootNode); counter > -1; --counter)
+ destr_func(pop_ctnr(rootNode));
+
+ if (rootNode->data)
+ free(rootNode->data);
+
+ free(rootNode);
+ rootNode = 0;
+
+ return;
+}
+
+INDEX level_ctnr(CONTAINER rootNode)
+{
+ if (rootNode == NIL) {
+ rpterr("level_ctnr: NIL argument");
+ return -1;
+ }
+
+ return ((CONTAINER_INFO)rootNode->data)->count;
+}
+
+void insert_ctnr(CONTAINER rootNode, void* object, INDEX pos)
+{
+ CONTAINER it;
+ INDEX counter = 0;
+
+ if (rootNode == NIL || object == NIL) {
+ rpterr("insert_ctnr: NIL argument");
+ return;
+ }
+
+ for (it = rootNode->next; it != rootNode; it = it->next) {
+ if (counter == pos) {
+ CONTAINER newNode = (CONTAINER)malloc(sizeof(T_CONTAINER));
+
+ newNode->prev = it;
+ newNode->next = it->next;
+ it->next->prev = newNode;
+ it->next = newNode;
+
+ newNode->data = object;
+ ((CONTAINER_INFO)rootNode->data)->count++;
+ return;
+ }
+
+ counter++;
+ }
+}
+
+void push_ctnr(CONTAINER rootNode, void* object)
+{
+ CONTAINER newNode;
+
+ if (rootNode == NIL || object == NIL) {
+ rpterr("push_ctnr: NIL argument");
+ return;
+ }
+
+ newNode = (CONTAINER)malloc(sizeof(T_CONTAINER));
+ newNode->next = rootNode;
+ newNode->prev = rootNode->prev;
+ rootNode->prev->next = newNode;
+ rootNode->prev = newNode;
+
+ newNode->data = object;
+ ((CONTAINER_INFO)rootNode->data)->count++;
+}
+
+void* remove_at_ctnr(CONTAINER rootNode, INDEX pos)
+{
+ CONTAINER it;
+ INDEX counter = 0;
+ void* retval;
+
+ if (rootNode == NIL) {
+ rpterr("remove_ctnr: NIL argument");
+ return NIL;
+ }
+
+ for (it = rootNode->next; it != rootNode; it = it->next) {
+ if (counter == pos) {
+ retval = it->data;
+
+ it->prev->next = it->next;
+ it->next->prev = it->prev;
+
+ free(it);
+
+ ((CONTAINER_INFO)rootNode->data)->count--;
+ return retval;
+ }
+
+ counter++;
+ }
+
+ return NIL;
+}
+
+void* pop_ctnr(CONTAINER rootNode)
+{
+ CONTAINER ptr;
+ void* retval;
+
+ if (rootNode == NIL) {
+ rpterr("pop_ctnr: NIL argument");
+ return NIL;
+ }
+
+ if (rootNode->next == rootNode)
+ return NIL;
+
+ ptr = rootNode->next;
+ retval = ptr->data;
+
+ rootNode->next = ptr->next;
+ ptr->next->prev = rootNode;
+
+ ((CONTAINER_INFO)rootNode->data)->count--;
+
+ free(ptr);
+
+ return retval;
+}
+
+void* get_ctnr(CONTAINER rootNode, INDEX pos)
+{
+ CONTAINER it;
+ INDEX counter = 0;
+
+ if (rootNode == NIL) {
+ rpterr("get_ctnr: NIL argument");
+ return NIL;
+ }
+
+ for (it = rootNode->next; it != rootNode; it = it->next) {
+ if (counter == pos)
+ return it->data;
+
+ counter++;
+ }
+
+ return NIL;
+}
+
+INDEX search_ctnr(CONTAINER rootNode, COMPARE_FUNC compare_func, void* pattern)
+{
+ CONTAINER it;
+ INDEX counter = 0;
+
+ if (rootNode == NIL || compare_func == NIL || pattern == NIL) {
+ rpterr("search_ctnr: NIL argument");
+ return -1;
+ }
+
+ for (it = rootNode->next; it != rootNode; it = it->next) {
+ if (compare_func(pattern, it->data) == 0)
+ return counter;
+
+ counter++;
+ }
+
+ return -1;
+}
+
+void swop_ctnr(CONTAINER rootNode, INDEX pos1, INDEX pos2)
+{
+ CONTAINER it, node1, node2;
+ INDEX counter = 0;
+ int found = 0;
+ void* tmpData;
+
+ if (rootNode == NIL) {
+ rpterr("swop_ctnr: NIL argument");
+ return;
+ }
+
+ if (pos1 == pos2)
+ return;
+
+ /**
+ * it is a bit hackish because of the 'goto' but it's fast
+ * since we have to run through the list only once
+ */
+ for (it = rootNode->next; it != rootNode; it = it->next) {
+ if (counter == pos1) {
+ node1 = it;
+ if (found)
+ goto swapIt;
+ else
+ found = 1;
+ }
+ if (counter == pos2) {
+ node2 = it;
+ if (found)
+ goto swapIt;
+ else
+ found = 1;
+ }
+
+ counter++;
+ }
+
+ return;
+
+swapIt:
+ tmpData = node1->data;
+ node1->data = node2->data;
+ node2->data = tmpData;
+ return;
+}
+
+void bsort_ctnr(CONTAINER rootNode, COMPARE_FUNC compare_func)
+{
+ INDEX right, i, level, last;
+
+ if (rootNode == NIL || compare_func == NIL) {
+ rpterr("destr_ctnr: NIL argument");
+ return;
+ }
+
+ last = level = level_ctnr(rootNode);
+ do
+ {
+ right = last;
+ last = 0;
+ for (i = 1; i < right; i++)
+ if (compare_func(get_ctnr(rootNode, i - 1), get_ctnr(rootNode, i)) > 0)
+ swop_ctnr(rootNode, i - 1, last = i);
+ } while (last > 0);
+}
+
+void* first_ctnr(CONTAINER rootNode)
+{
+ if (rootNode == NIL) {
+ rpterr("first_ctnr: NIL argument");
+ return NIL;
+ }
+
+ if (rootNode->next == rootNode)
+ return NIL;
+
+ ((CONTAINER_INFO)rootNode->data)->currentNode = rootNode->next;
+
+ return rootNode->next->data;
+}
+
+void* next_ctnr(CONTAINER rootNode)
+{
+ CONTAINER_INFO info;
+
+ if (rootNode == NIL) {
+ rpterr("next_ctnr: NIL argument");
+ return NIL;
+ }
+
+ info = (CONTAINER_INFO)rootNode->data;
+
+ if (info->currentNode->next == rootNode)
+ return NIL;
+
+ info->currentNode = info->currentNode->next;
+
+ return info->currentNode->data;
+}
+
+void* remove_ctnr(CONTAINER rootNode)
+{
+ CONTAINER currentNode, tmp;
+ CONTAINER_INFO info;
+ void* retval;
+
+ if (rootNode == NIL) {
+ rpterr("remove_curr_ctnr: NIL argument");
+ return NIL;
+ }
+
+ info = (CONTAINER_INFO)rootNode->data;
+ currentNode = info->currentNode;
+
+ if (currentNode == rootNode) { /* should never happen */
+ rpterr("remove_curr_ctnr: delete root node");
+ return NIL;
+ }
+
+ retval = currentNode->data;
+ tmp = currentNode->prev;
+
+ currentNode->prev->next = currentNode->next;
+ currentNode->next->prev = currentNode->prev;
+
+ free(currentNode);
+
+ info->count--;
+ info->currentNode = tmp;
+
+ return retval;
+}
diff --git a/ksysguard/CContLib/ccont.h b/ksysguard/CContLib/ccont.h
new file mode 100644
index 000000000..66b22eba4
--- /dev/null
+++ b/ksysguard/CContLib/ccont.h
@@ -0,0 +1,161 @@
+/*
+ Lightweight C Container Library
+
+ Copyright (c) 2002 Tobias Koenig <tokoe@kde.org>
+
+ Original code was written by Chris Schlaeger <cs@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _CCONT_H
+#define _CCONT_H
+
+#ifndef NIL
+#define NIL ((void*) 0)
+#endif
+
+#define destr_ctnr(x, y) zero_destr_ctnr(x, y); x=0
+
+struct container {
+ struct container* next;
+ struct container* prev;
+ void* data;
+};
+
+typedef struct container T_CONTAINER;
+typedef struct container* CONTAINER;
+
+typedef long INDEX;
+
+typedef void (*DESTR_FUNC)(void*);
+typedef int (*COMPARE_FUNC)(void*, void*);
+
+/**
+ * Initialize the container @p ctnr.
+ */
+CONTAINER new_ctnr(void);
+
+/**
+ * Remove all entries from @p ctnr and reset its
+ * internal structure. Use @ref new_ctnr() @em before @em
+ * access the container next time.
+ *
+ * Note: use the 'destr_ctnr' macro to get zeroed pointer
+ * automatically.
+ *
+ * @param destr_func The function that is called to
+ * free the single entries.
+ */
+void zero_destr_ctnr(CONTAINER ctnr, DESTR_FUNC destr_func);
+
+/**
+ * @return the number of entries in @p ctnr.
+ */
+INDEX level_ctnr(CONTAINER ctnr);
+
+/**
+ * Insert a new entry in container.
+ *
+ * @param object A pointer to the object.
+ * @param pos The position where the object should be insert.
+ */
+void insert_ctnr(CONTAINER ctnr, void* object, INDEX pos);
+
+/**
+ * Add a new entry at the end of container.
+ *
+ * @param object The object that should be added.
+ */
+void push_ctnr(CONTAINER ctnr, void* object);
+
+/**
+ * Remove an entry from container.
+ *
+ * @param pos The position of the object that should be removed.
+ *
+ * @return A pointer to the removed object or @p 0L if it doesn't exist.
+ */
+void* remove_at_ctnr(CONTAINER ctnr, INDEX pos);
+
+/**
+ * Remove the first entry of container.
+ *
+ * @return A pointer to the removed object or @p 0L if there is now entry.
+ */
+void* pop_ctnr(CONTAINER ctnr);
+
+/**
+ * @return A pointer to the object at position @a pos
+ * or @p 0L if it doesn't exist.
+ */
+void* get_ctnr(CONTAINER ctnr, INDEX pos);
+
+/**
+ * @return The position of a matching entry.
+ *
+ * @param compare_func A Pointer to the function that is
+ * called to compare all entries in the
+ * container with the given pattern.
+ * @param pattern The pattern for coparison.
+ */
+INDEX search_ctnr(CONTAINER ctnr, COMPARE_FUNC compare_func, void* pattern);
+
+/**
+ * Swap two objects in container.
+ *
+ * @param pos1 Position of the first object.
+ * @param pos2 Position of the second object.
+ */
+void swop_ctnr(CONTAINER ctnr, INDEX pos1, INDEX pos2);
+
+/**
+ * Sort all entries of container.
+ *
+ * @param compare_func A Pointer to the function that is
+ * called to compare to entries of the
+ * container.
+ */
+void bsort_ctnr(CONTAINER ctnr, COMPARE_FUNC compare_func);
+
+/**
+ * Use this function to iterate over the container.
+ *
+ * for (ptr = first_ctnr(ctnr); ptr; ptr = next_ctnr(ctnr)) {
+ * do_anything(ptr);
+ * }
+ *
+ * @return A Pointer to the first object in container.
+ */
+void* first_ctnr(CONTAINER ctnr);
+
+/**
+ * Use this function to iterate over the container.
+ *
+ * @return A Pointer to the next object in container.
+ */
+void* next_ctnr(CONTAINER ctnr);
+
+/**
+ * Use this function to remove the current entry while
+ * iterating over the container.
+ *
+ * @return A Pointer to the removed object or @p 0L if it doesn't exist.
+ */
+void* remove_ctnr(CONTAINER ctnr);
+
+#endif
diff --git a/ksysguard/Makefile.am b/ksysguard/Makefile.am
new file mode 100644
index 000000000..4d4223b60
--- /dev/null
+++ b/ksysguard/Makefile.am
@@ -0,0 +1,9 @@
+if include_ksysguardd
+KSYSGUARDD_DIR = ksysguardd
+endif
+
+# claim, which subdirectories you want to install
+SUBDIRS = CContLib $(KSYSGUARDD_DIR) gui pics example
+
+KDE_ICON = ksysguard
+
diff --git a/ksysguard/Makefile.in.temp b/ksysguard/Makefile.in.temp
new file mode 100644
index 000000000..b8e021dc2
--- /dev/null
+++ b/ksysguard/Makefile.in.temp
@@ -0,0 +1,99 @@
+
+# the most documentation you find in Makefile.am
+# this file is just to demonstrate, how complex it is to
+# write good Makefiles, if you don't use automake ;)
+
+# export the variables, we're using
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+top_srcdir = @top_srcdir@
+kde_appsdir = @kde_appsdir@
+kde_cgidir = @kde_cgidir@
+kde_confdir = @kde_confdir@
+kde_datadir = @kde_datadir@
+kde_htmldir = @kde_htmldir@
+kde_icondir = @kde_icondir@
+kde_locale = @kde_locale@
+kde_mimedir = @kde_mimedir@
+kde_minidir = @kde_minidir@
+kde_toolbardir = @kde_toolbardir@
+kde_wallpaperdir= @kde_wallpaperdir@
+bindir = @bindir@
+
+all_includes = @all_includes@
+all_libraries = @all_libraries@
+
+MOC = @MOC@
+XGETTEXT = @XGETTEXT@
+CXX = @CXX@
+LDFLAGS = @LDFLAGS@
+CXXFLAGS = @CXXFLAGS@
+LIBSOCKET = @LIBSOCKET@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+
+# define some variables
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+APPSDIR = $(kde_appsdir)/Utilities
+INCLUDES = $(all_includes)
+TARGET = khexdit
+LIBS = -lkfm -lkdeui -lkdecore -lqt -lX11 -lXext $(LIBSOCKET)
+LDFLAGS += $(all_libraries)
+
+# rules to make .o files
+.SUFFIXES: .cpp
+.cpp.o:
+ $(CXX) $(CXXFLAGS) $(DEFS) $(INCLUDES) -c $<
+
+OBJECTS = hexfile.o hexwidget.o
+SRCMOCS = hexwidget.moc hexfile.moc
+
+all: $(TARGET)
+
+$(TARGET): $(SRCMOCS) $(OBJECTS)
+ $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS)
+
+# recreate the Makefile
+Makefile: Makefile.in
+ cd .. && CONFIG_FILES=khexdit/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+install: install-data install-exec
+
+# make messages.po. Move this one to ../po/ and "make merge" in po
+messages:
+ $(XGETTEXT) -C -ktranslate *.cpp
+
+install-exec: $(TARGET)
+ $(mkinstalldirs) $(bindir)
+ $(INSTALL_PROGRAM) $(TARGET) $(bindir)
+
+install-data:
+ (cd doc && $(MAKE) install-data)
+ $(mkinstalldirs) $(APPSDIR)
+ $(INSTALL_DATA) khexdit.kdelnk $(APPSDIR)
+ $(mkinstalldirs) $(kde_icondir)
+ $(INSTALL_DATA) khexdit.xpm $(kde_icondir)
+ $(mkinstalldirs) $(kde_minidir)
+ $(INSTALL_DATA) mini-khexdit.xpm $(kde_minidir)/khexdit.xpm
+
+uninstall:
+ (cd doc && $(MAKE) uninstall)
+ -rm -f $(bindir)/$(TARGET)
+ -rm -f $(APPSDIR)/khexdit.kdelnk
+ -rm -f $(kde_icondir)/khexdit.xpm
+ -rm -f $(kde_minidir)/khexdit.xpm
+
+clean:
+ -rm -f $(TARGET) $(OBJECTS) *~ core
+
+distclean: clean
+ -rm -f Makefile $(SRCMOCS)
+
+# add a dependcy for all moc files to help some FreeBSD users ;)
+hexwidget.moc: hexwidget.h
+ $(MOC) hexwidget.h -o hexwidget.moc
+
+hexfile.moc: hexfile.h
+ $(MOC) hexfile.h -o hexfile.moc
diff --git a/ksysguard/README b/ksysguard/README
new file mode 100644
index 000000000..36d81e7a3
--- /dev/null
+++ b/ksysguard/README
@@ -0,0 +1,26 @@
+What is KSysGuard?
+------------------
+
+KSysGuard, formerly known as KTop is a program to monitor various elements
+of your system, or any other remote system with the KSysGuard daemon
+(ksysgardd) installed. Currently the daemon has been ported to FreeBSD
+and Linux with varying degrees of completion.
+
+Notes from the author
+---------------------
+
+KSysGuard, formerly known as KTop is work in progress! Although I only try
+to check in reasonably stable versions, I cannot guarantee this. I
+typically develop on SuSE Linux 6.x with 2.2 kernel. If your system is
+different, this program might not even compile.
+
+If you want to join this development please contact me first. Please
+do *NOT* check in unsolicited code as I might am rearranging the code
+and merging becomes a real headache so your code will be lost.
+
+This does not mean that I don't appreciate your help. Especially
+porting to other platforms is difficult for me. Each platform has it's
+specific back-end. See the ksysguardd directory for details.
+
+5-Jan-2000 Chris Schlaeger <cs@kde.org>
+
diff --git a/ksysguard/configure.in.in b/ksysguard/configure.in.in
new file mode 100644
index 000000000..0173b28ea
--- /dev/null
+++ b/ksysguard/configure.in.in
@@ -0,0 +1,50 @@
+dnl Check whether ksysguardd can run;
+AC_MSG_CHECKING([if ksysguardd can be compiled])
+case "$host" in
+ *-*-linux*) ksysguardd_compile=yes; UNAME='Linux' ;;
+ *-*-freebsd*) ksysguardd_compile=yes; UNAME='FreeBSD' ;;
+ *-*-dragonfly*) ksysguardd_compile=yes; UNAME='FreeBSD' ;;
+ *-*-netbsd*) ksysguardd_compile=yes; UNAME='NetBSD' ;;
+ *-*-solaris*) ksysguardd_compile=yes; UNAME='Solaris' ;;
+ *-*-osf*) ksysguardd_compile=yes; UNAME='Tru64' ;;
+ *-*-irix*) ksysguardd_compile=yes; UNAME='Irix' ;;
+ *-*-openbsd*) ksysguardd_compile=yes; UNAME='OpenBSD' ;;
+ *) ksysguardd_compile=no; UNAME='' ;;
+esac
+
+AC_MSG_RESULT($ksysguardd_compile)
+
+AM_CONDITIONAL(include_ksysguardd, test "$ksysguardd_compile" = "yes")
+AM_CONDITIONAL(include_ksysguardd_linux, test "$UNAME" = Linux)
+AM_CONDITIONAL(include_ksysguardd_freebsd, test "$UNAME" = FreeBSD)
+AM_CONDITIONAL(include_ksysguardd_netbsd, test "$UNAME" = NetBSD)
+AM_CONDITIONAL(include_ksysguardd_solaris, test "$UNAME" = Solaris)
+AM_CONDITIONAL(include_ksysguardd_tru64, test "$UNAME" = Tru64)
+AM_CONDITIONAL(include_ksysguardd_irix, test "$UNAME" = Irix)
+AM_CONDITIONAL(include_ksysguardd_openbsd, test "$UNAME" = OpenBSD)
+AC_SUBST(UNAME)
+
+AC_ARG_WITH(sensors,
+ [AC_HELP_STRING(--with-sensors,
+ [enable support for lm_sensors @<:@default=check@:>@])],
+ [], with_sensors=check)
+
+if test "x$with_sensors" != xno; then
+ KDE_CHECK_HEADERS(sensors/sensors.h)
+ KDE_CHECK_LIB(sensors, sensors_init, [LIBSENSORS="-lsensors"])
+
+ if test "x$with_sensors" != xcheck && test -z "$LIBSENSORS"; then
+ AC_MSG_ERROR([--with-sensors was given, but test for lm_sensors failed])
+ fi
+fi
+
+case "$UNAME" in
+ Linux) LIBHOSTS="$LIBSENSORS" ;;
+ FreeBSD) LIBHOSTS="$LIBSENSORS -lkvm" ;;
+ Solaris) LIBHOSTS="$LIBSENSORS -lkstat -lsocket" ;;
+esac
+AC_SUBST(LIBHOSTS)
+AC_SUBST(LIBSENSORS)
+
+dnl Check for dell laptop support
+AM_CONDITIONAL(supports_i8k, test -f /proc/i8k)
diff --git a/ksysguard/cr128-app-ksysguard.png b/ksysguard/cr128-app-ksysguard.png
new file mode 100644
index 000000000..f2223cde8
--- /dev/null
+++ b/ksysguard/cr128-app-ksysguard.png
Binary files differ
diff --git a/ksysguard/cr16-app-ksysguard.png b/ksysguard/cr16-app-ksysguard.png
new file mode 100644
index 000000000..1c2e678da
--- /dev/null
+++ b/ksysguard/cr16-app-ksysguard.png
Binary files differ
diff --git a/ksysguard/cr32-app-ksysguard.png b/ksysguard/cr32-app-ksysguard.png
new file mode 100644
index 000000000..53005ff57
--- /dev/null
+++ b/ksysguard/cr32-app-ksysguard.png
Binary files differ
diff --git a/ksysguard/cr48-app-ksysguard.png b/ksysguard/cr48-app-ksysguard.png
new file mode 100644
index 000000000..b636ff0e6
--- /dev/null
+++ b/ksysguard/cr48-app-ksysguard.png
Binary files differ
diff --git a/ksysguard/cr64-app-ksysguard.png b/ksysguard/cr64-app-ksysguard.png
new file mode 100644
index 000000000..95ef34953
--- /dev/null
+++ b/ksysguard/cr64-app-ksysguard.png
Binary files differ
diff --git a/ksysguard/example/Makefile.am b/ksysguard/example/Makefile.am
new file mode 100644
index 000000000..67cf43318
--- /dev/null
+++ b/ksysguard/example/Makefile.am
@@ -0,0 +1,5 @@
+ksysguard_example_datadir = $(kde_datadir)/ksysguard
+ksysguard_example_data_DATA = eventsrc
+
+etcdir = $(sysconfdir)
+etc_DATA = ksysguarddrc
diff --git a/ksysguard/example/eventsrc b/ksysguard/example/eventsrc
new file mode 100644
index 000000000..5051f0cf2
--- /dev/null
+++ b/ksysguard/example/eventsrc
@@ -0,0 +1,305 @@
+[!Global!]
+IconName=ksysguard
+Comment=KDE System Guard
+Comment[af]=KDE Stelsel Wag
+Comment[ar]=حارس النظام KDE
+Comment[az]=KDE Sistem Cangüdəni
+Comment[be]=Ахоўнік сістэмы KDE
+Comment[bg]=Системна защита
+Comment[bn]=কে.ডি.ই. সিস্টেম গার্ড
+Comment[br]=Gward Reizhiad KDE
+Comment[bs]=KDE zaštita sistema
+Comment[ca]=Vigilant del sistema KDE
+Comment[cs]=Správce systému KDE
+Comment[csb]=KDE Wachtôrz Systemë
+Comment[cy]=Gwarchodwr Cysawd KDE
+Comment[da]=KDE Systemvagt
+Comment[de]=KDE-Systemüberwachung
+Comment[el]=Φρουρός συστήματος του KDE
+Comment[eo]=KDE-Sistemobservilo
+Comment[es]=Guardián del sistema de KDE
+Comment[et]=KDE süsteemi valvur
+Comment[eu]=KDEren sistemaren kontrola
+Comment[fa]=محافظ سیستم KDE
+Comment[fi]=KDE:n järjestelmänvalvonta
+Comment[fr]=Surveillance du système
+Comment[fy]=KDE systeembefeiliging
+Comment[ga]=Garda an Chórais KDE
+Comment[gl]=Vixiante do Sistema de KDE
+Comment[he]=משמר המערכת של KDE
+Comment[hi]=केडीई तंत्र गार्ड
+Comment[hr]=KDE zaštitnik sustava
+Comment[hu]=KDE rendszermonitor
+Comment[is]=KDE kerfisvörður
+Comment[it]=Controllo di sistema di KDE
+Comment[ja]=KDE システムガード
+Comment[ka]=KDE სისტემური მონიტორი
+Comment[kk]=KDE жүйелік бақылаушысы
+Comment[km]=ការពារ​ប្រព័ន្ធ KDE
+Comment[ko]=KDE 시스템 지킴이
+Comment[lo]=ເຄື່ອງມືຶປ້ອງກັນລະບົບຂອງ KDE
+Comment[lt]=KDE sistemos apsauga
+Comment[lv]=KDE Sistēmas Sargs
+Comment[mk]=KDE Системски чувар
+Comment[mn]=КДЭ-Системийн хяналт
+Comment[ms]=Pengawas Sistem KDE
+Comment[mt]=Gwardja tas-Sistema KDE
+Comment[nb]=KDE Systemovervåker
+Comment[nds]=KDE-Systeemwachter
+Comment[ne]=KDE प्रणाली रक्षक
+Comment[nl]=KDE systeembewaking
+Comment[nn]=KDE Systemvakt
+Comment[nso]=Thlokomelo ya System ya KDE
+Comment[pa]=KDE ਸਿਸਟਮ ਗਾਰਡ
+Comment[pl]=KDE Strażnik Systemu
+Comment[pt]=Vigilante do sistema do KDE
+Comment[pt_BR]=Sistema de Guarda do KDE
+Comment[ro]=Sistem de gardă KDE
+Comment[ru]=Системный монитор
+Comment[rw]=Umurinzi Sisitemu KDE
+Comment[se]=KDE vuogádatfákta
+Comment[sk]=KDE Strážca systému
+Comment[sl]=Sistemski varuh KDE
+Comment[sr]=KDE чувар система
+Comment[sr@Latn]=KDE čuvar sistema
+Comment[sv]=KDE:s systemövervakare
+Comment[ta]=KDE கணினி காவலன்
+Comment[tg]=Муҳофизи системаи KDE
+Comment[th]=เครื่องมือป้องกันระบบ KDE
+Comment[tr]=KDE Sistem Koruyucu
+Comment[tt]=KDE'nıñ Sistem Saqçısı
+Comment[uk]=Системний вартовий KDE
+Comment[uz]=KDE tizim nazoratchisi
+Comment[uz@cyrillic]=KDE тизим назоратчиси
+Comment[ven]=Mulindi wa maitele a KDE
+Comment[vi]=Trình bảo vệ Hệ thống KDE
+Comment[wa]=Gåre sistinme KDE
+Comment[xh]=KDE Ukhuselo lendlela yokusebenza
+Comment[zh_CN]=KDE 系统卫士
+Comment[zh_TW]=KDE 系統守衛
+Comment[zu]=Unogada Wesistimu ye-KDE
+
+[pattern_match]
+Name=pattern_match
+Name[az]=uyğun_naxış
+Name[bn]=নকশা_মিল
+Name[csb]=dopasowanié_mùstra
+Name[cy]=cydweddiad_patrwm
+Name[da]=mønster_match
+Name[de]=Musterübereinstimmung
+Name[eo]=ŝablon_serĉo
+Name[es]=concordancia de patrón
+Name[fr]=correspondance_avec_motif
+Name[gl]=patrón_coincidente
+Name[hi]=पैटर्न-मैच
+Name[hr]=pronalaženje_uzoraka
+Name[hu]=illeszkedő_minta
+Name[it]=corrispondenza_schema
+Name[ja]=パターンマッチ
+Name[km]=លំនាំ ផ្គូផ្គង
+Name[ko]=검색 패턴이 일치함
+Name[lo]=ເຂົ້າກັບຮູບແບບ
+Name[lt]=šablono atitikimas
+Name[lv]=šablona_atbilstība
+Name[mk]=совпаѓање_шема
+Name[mn]=Загвар-зохицуулга
+Name[nb]=mønster_treff
+Name[nds]=Musterövereenstimmen
+Name[ne]=बाँन्की मिल्दो
+Name[nn]=mønster_treff
+Name[nso]=tshwanetsano ya mokgwa
+Name[pa]=ਪੈਟਰਨ ਮੇਲ
+Name[pl]=dopasowanie_wzorca
+Name[ro]=potrivire model
+Name[rw]=Ishusho_bihura
+Name[se]=minsttar_deaivan
+Name[sl]=vzorec_zadetek
+Name[sr]=подударан_узорак
+Name[sr@Latn]=podudaran_uzorak
+Name[sv]=mönsterigenkänning
+Name[ta]=மாதிரி_பொருத்தம்
+Name[ven]=Maitele_Fana
+Name[vi]=khớp_mẫu
+Name[wa]=va_avou_modele
+Name[xh]=umlinganiselo_thelekisa
+Name[zh_TW]=比對正確
+Name[zu]=ukufanisa_iphethini
+Comment=Search pattern matched
+Comment[af]=Soek patroon opgespoor
+Comment[ar]=تم ايجاد تماثل
+Comment[be]=Пошук супадзенняў з шаблонам
+Comment[bg]=Съвпадение на търсения низ
+Comment[bn]=সন্ধান করা প্যাটার্ন-এর মিল পাওয়া গেছে
+Comment[bs]=Pronađen uzorak za pretragu
+Comment[ca]=Cerca coincidència de patró
+Comment[cs]=Hledaný vzor odpovídá
+Comment[csb]=Mùster òstôł dopasowóny
+Comment[da]=Søgemønsteret matchede
+Comment[de]=Übereinstimmung mit Suchmuster
+Comment[el]=Ταίριασμα μοτίβου αναζήτησης
+Comment[eo]=Serĉoŝablonesprimo kongruas
+Comment[es]=Coincidencia con el patrón de búsqueda
+Comment[et]=Otsingu muster sobib
+Comment[eu]=bilatutako eredua bat dator
+Comment[fa]=جستجوی الگوی تطبیق‌شده
+Comment[fi]=Hakumerkkijono osui
+Comment[fr]=Motif de recherche trouvé
+Comment[fy]=Sykpatroan komt oerien
+Comment[gl]=o patrón a procurar atopou-se
+Comment[he]=נמצאה התאמה לדפוס החיפוש
+Comment[hi]=सर्च पैटर्न मेल खाते हैं
+Comment[hr]=Traženi je uzorak pronađen
+Comment[hu]=Illeszkedő keresési minta
+Comment[is]=finna skv. leitarmynstri
+Comment[it]=Schema di ricerca trovato
+Comment[ja]=検索パターンにマッチしました
+Comment[ka]=ძიების ნიმუშთან შესაბამისობა
+Comment[kk]=Ізделген үлгіге сәйкестік
+Comment[km]=លំនាំ​ស្វែងរក​បាន​ផ្គូផ្គង
+Comment[ko]=검색 패턴이 일치함
+Comment[lt]=Paieškos šablonas atitiko
+Comment[lv]=Meklēšanas šablons atbilst
+Comment[mk]=Пребарувањето се поклопува
+Comment[ms]=Cari corak sepadan
+Comment[mt]=skema ta' tfittxija qablet
+Comment[nb]=Søkemønsteret passet
+Comment[nds]=Söökmuster passt
+Comment[ne]=बाँन्की मिल्दो खोजी गर्नुहोस्
+Comment[nl]=Zoekpatroon komt overeen
+Comment[nn]=Søkjemønsteret passa
+Comment[pa]=ਖੋਜ ਤਰਤੀਬ ਮੇਲ
+Comment[pl]=Dopasowano wzorzec
+Comment[pt]=Padrão de pesquisa encontrado
+Comment[pt_BR]=Padrão de busca encontrado
+Comment[ro]=Modelul căutat s-a potrivit
+Comment[ru]=Соответствие шаблону поиска
+Comment[rw]=Gushakisha ishusho byahuye
+Comment[se]=Ohcanminsttar heivii
+Comment[sk]=Nájdené podľa vzorky
+Comment[sl]=Iskalni vzorec se ujema
+Comment[sr]=Подударан узорак је пронађен
+Comment[sr@Latn]=Podudaran uzorak je pronađen
+Comment[sv]=Sökmönster igenkänt
+Comment[ta]=மாதிரி பொருத்தத்தை தேடு
+Comment[th]=ค้นหารูปแบบที่เข้าคู่กัน
+Comment[tr]=Eşleşen örüntüyü ara
+Comment[tt]=Ezlängäne belän kileşte
+Comment[uk]=Знайдено взірець пошуку
+Comment[vi]=Tìm các mẫu khớp
+Comment[wa]=Trover des modeles ki vont avou
+Comment[zh_CN]=搜索匹配的模式
+Comment[zh_TW]=尋找比對正確
+
+[sensor_alarm]
+Name=sensor_alarm
+Name[bn]=বিপদ_সংকেত
+Name[cy]=larwm_synhwyrydd
+Name[de]=Sensormeldung
+Name[eo]=sentilo_alarmo
+Name[es]=alarma de sensor
+Name[fr]=alarme_des_capteurs
+Name[fy]=sensormelding
+Name[gl]=alarma_sensor
+Name[hi]=सेंसर-अलार्म
+Name[hr]=osjetilo_alarma
+Name[hu]=érzékelő_riasztás
+Name[it]=allarme_dei_sensori
+Name[ja]=センサーアラーム
+Name[km]=សំឡេង​រោទិ៍​ឧបករណ៍​ស្ទង់
+Name[ko]=센서 알람
+Name[lo]=ການເຕື່ອນກວດຈັບ
+Name[lt]=daviklio aliarmas
+Name[lv]=sensora_trauksme
+Name[mk]=аларм_сензор
+Name[mn]=Мэдрэгчийн дохио
+Name[nds]=Sensormellen
+Name[ne]=सचेतक
+Name[nl]=sensormelding
+Name[nso]=alamo ya sekwi
+Name[pa]=ਸੰਕੇਤਕ ਚੇਤਾਵਨੀ
+Name[ro]=alarmă senzor
+Name[rw]=impuruza_rukuruzi
+Name[se]=dovddan_alarbma
+Name[sl]=senzor_alarm
+Name[sr]=аларм_сензора
+Name[sr@Latn]=alarm_senzora
+Name[sv]=sensorlarm
+Name[ta]=உணர் எச்சரிக்கை
+Name[ven]=Zwipfi_Alamu
+Name[vi]=báo động của đầu dò
+Name[wa]=sinteu_d'_alarme
+Name[xh]=uluvo_oluvusayo
+Name[zh_TW]=偵測器通知
+Name[zu]=i-alamu_enemizwa
+Comment=Sensor exceeded critical limit
+Comment[af]=Sensor oorskry krities beperk
+Comment[be]=Сэнсар перавысіў крытычную мяжу
+Comment[bg]=Преминат е критичния лимит от даден сензор
+Comment[bn]=সেনসর বিপদসীমা ছাড়িয়ে গেছে
+Comment[bs]=Senzor je prekoračio kritičnu granicu
+Comment[ca]=EL sensor ha excedit el límit crític
+Comment[cs]=Senzor překročil kritickou hodnotu
+Comment[csb]=Czujnik przestãpił kriticzną grańcã
+Comment[cy]=Aethpwyd dros gyfyngder critigol y synhwyrydd
+Comment[da]=Sensor gik ud over kritisk grænse
+Comment[de]=Sensor zeigt Überschreitung der kritischen Grenze an
+Comment[el]=Ο αισθητήρας ξεπέρασε το κρίσιμο όριο
+Comment[eo]=Sentilo transiris danĝeran limon
+Comment[es]=El sensor excedió el límite crítico
+Comment[et]=Sensor ületas kriitilise piiri
+Comment[eu]=Sensoreak bere muga kritikoa gainditu du
+Comment[fa]=حسگر فراتر از حد بحرانی شد
+Comment[fi]=Tunnistin ylitti kriittisen rajan
+Comment[fr]=Le capteur a dépassé sa limite critique
+Comment[fy]=Sensor limyt giet oer de kritike grins
+Comment[gl]=O sensor excedeu o límite crítico
+Comment[he]=החיישן חרג מהמגבלה הקריטית
+Comment[hi]=सेंसर क्रिटिकल लिमिट से ज्यादा
+Comment[hr]=Osjetilo je nadmašilo kritičnu razinu
+Comment[hu]=Egy figyelt érték elérte a kritikus szintet
+Comment[is]=Skynjari fór yfir hámark
+Comment[it]=Il sensore ha superato la soglia critica
+Comment[ja]=センサーは危険度の限界を超えました
+Comment[ka]=სენსორმა გადააჭარბა კრიტიკულ ზღვარს
+Comment[kk]=Сенсор шекті деңгейден асып кетті
+Comment[km]=ឧបករណ៍​ស្ទង់​បាន​លើស​ព្រំដែន​ចុងក្រោយ
+Comment[ko]=센서에서 치명적 한계를 넘었음
+Comment[lt]=Daviklis viršijo kritinį limitą
+Comment[lv]=Sensors pārsniedzis kritisko limitu
+Comment[mk]=Сензорот ја надмина критичната граница
+Comment[mn]=Мэдрэгч критик хязгаарын давалтыг заах
+Comment[ms]=Penderia melebihi had kritikal
+Comment[mt]=Sensur eċċeda l-limitu kritiku
+Comment[nb]=Sensorene oversteg en kritisk grense
+Comment[nds]=En Sensor hett en Weert meldt, de baven vun de kritische Grenz liggt
+Comment[ne]=सचेतक असामान्य सीमा भन्दा अगाडि बढ्यो
+Comment[nl]=Sensor overschreed kritieke limiet
+Comment[nn]=Sensoren gjekk over kritisk grense
+Comment[nso]=Sekwi se fetile magomo a kganetso
+Comment[pa]=ਸੰਕੇਤਕ ਘਾਤਕ ਸੀਮਾ ਨੂੰ ਪਾਰ ਕਰ ਗਿਆ ਹੈ
+Comment[pl]=Czujnik przekroczył granicę krytyczną
+Comment[pt]=o sensor excedeu o limite crítico
+Comment[pt_BR]=Sensor excedeu o limite crítico
+Comment[ro]=Senzorul a depășit limita critică
+Comment[ru]=Датчик превысил критический предел
+Comment[rw]= Rukuruzi yarenze impera ngombwa
+Comment[sk]=Senzor prekročil kritický limit
+Comment[sl]=Senzor je presegel kritično mejo
+Comment[sr]=Сензор је прешао дозвољену границу
+Comment[sr@Latn]=Senzor je prešao dozvoljenu granicu
+Comment[sv]=Sensor överskred den kritiska gränsen
+Comment[ta]=உணர்வான் சிக்கல் கட்டத்தை தாண்டியது
+Comment[tg]=Датчик аз ҳад гузашт
+Comment[th]=ตัวตรวจจับเกินกว่าค่าวิกฤติ
+Comment[tr]=Alıcı kritik limiti geçti
+Comment[tt]=Sizgeçneñ eşläw waqıtı ütte
+Comment[uk]=Датчик перевищив критичний рівень
+Comment[uz]=Sensor havfli chegaradan oʻtdi
+Comment[uz@cyrillic]=Сенсор ҳавфли чегарадан ўтди
+Comment[ven]=Tshisedzi tsho engedza phungudzo i sasaladzeaho
+Comment[vi]=Đầu dò vượt quá giới hạn chịu đựng
+Comment[wa]=Li sinteu a stî pus lon kel limite
+Comment[xh]=Umda wokufumana ingxaki ekhoyo woluvo
+Comment[zh_CN]=传感器达到关键限制
+Comment[zh_TW]=偵測器超過臨界限制
+Comment[zu]=Umuzwa udlule isilinganiso esibucayi
diff --git a/ksysguard/example/ksysguarddrc b/ksysguard/example/ksysguarddrc
new file mode 100644
index 000000000..ba52249fd
--- /dev/null
+++ b/ksysguard/example/ksysguarddrc
@@ -0,0 +1,19 @@
+# /etc/ksysguardd.conf
+
+# LogFiles: the list of all available logfiles
+LogFiles=messages:/var/log/messages,kern:/var/log/kern.log,daemon:/var/log/daemon.log
+
+# Sensors: the list of all accessable sensors
+# ProcessList current processes
+# Memory physical memory and swap
+# Stat interrupts, CPU and disk throughput
+# NetDev throughput of network interfaces
+# NetStat number of TCP/UDP/ICMP/Unix sockets
+# Apm Advanced Power Managment
+# Acpi Advanced Configuration and Power Interface
+# CpuInfo CPU-Clock informations
+# LoadAvg system load values
+# LmSensors informations about motherboard and CPU
+# DiskStat partition space
+# LogFile local logfiles
+Sensors=ProcessList,Memory,Stat,NetDev,NetStat,Apm,Acpi,CpuInfo,LoadAvg,LmSensors,DiskStat,LogFile
diff --git a/ksysguard/gui/KSGAppletSettings.cc b/ksysguard/gui/KSGAppletSettings.cc
new file mode 100644
index 000000000..df4748cb8
--- /dev/null
+++ b/ksysguard/gui/KSGAppletSettings.cc
@@ -0,0 +1,106 @@
+/*
+ This file is part of KSysGuard.
+ Copyright ( C ) 2002 Nadeem Hasan ( nhasan@kde.org )
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or ( at your option ) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qspinbox.h>
+
+#include <kaccelmanager.h>
+#include <klocale.h>
+
+#include "KSGAppletSettings.h"
+
+KSGAppletSettings::KSGAppletSettings( QWidget *parent, const char *name )
+ : KDialogBase( parent, name, false, QString::null, Ok|Apply|Cancel,
+ Ok, true )
+{
+ setCaption( i18n( "System Guard Settings" ) );
+
+ QWidget *page = new QWidget( this );
+ setMainWidget( page );
+
+ QGridLayout *topLayout = new QGridLayout( page, 3, 2, KDialog::marginHint(),
+ KDialog::spacingHint() );
+
+ QLabel *label = new QLabel( i18n( "Number of displays:" ), page );
+ topLayout->addWidget( label, 0, 0 );
+
+ mNumDisplay = new QSpinBox( 1, 32, 1, page );
+ mNumDisplay->setValue(2);
+ topLayout->addWidget( mNumDisplay, 0, 1 );
+ label->setBuddy( mNumDisplay );
+
+ label = new QLabel( i18n( "Size ratio:" ), page );
+ topLayout->addWidget( label, 1, 0 );
+
+ mSizeRatio = new QSpinBox( 50, 500, 50, page );
+ mSizeRatio->setSuffix( i18n( "%" ) );
+ mSizeRatio->setValue(100);
+ topLayout->addWidget( mSizeRatio, 1, 1 );
+ label->setBuddy( mSizeRatio );
+
+ label = new QLabel( i18n( "Update interval:" ), page );
+ topLayout->addWidget( label, 2, 0 );
+
+ mInterval = new QSpinBox( 1, 300, 1, page );
+ mInterval->setValue(2);
+ mInterval->setSuffix( i18n( " sec" ) );
+ topLayout->addWidget( mInterval, 2, 1 );
+ label->setBuddy( mInterval );
+
+ resize( QSize( 250, 130 ).expandedTo( minimumSizeHint() ) );
+
+ KAcceleratorManager::manage( page );
+}
+
+KSGAppletSettings::~KSGAppletSettings()
+{
+}
+
+int KSGAppletSettings::numDisplay() const
+{
+ return mNumDisplay->value();
+}
+
+void KSGAppletSettings::setNumDisplay( int value )
+{
+ mNumDisplay->setValue( value );
+}
+
+int KSGAppletSettings::sizeRatio() const
+{
+ return mSizeRatio->value();
+}
+
+void KSGAppletSettings::setSizeRatio( int value )
+{
+ mSizeRatio->setValue( value );
+}
+
+int KSGAppletSettings::updateInterval() const
+{
+ return mInterval->value();
+}
+
+void KSGAppletSettings::setUpdateInterval( int value )
+{
+ mInterval->setValue( value );
+}
+
diff --git a/ksysguard/gui/KSGAppletSettings.h b/ksysguard/gui/KSGAppletSettings.h
new file mode 100644
index 000000000..a825e2841
--- /dev/null
+++ b/ksysguard/gui/KSGAppletSettings.h
@@ -0,0 +1,49 @@
+/*
+ This file is part of KSysGuard.
+ Copyright ( C ) 2002 Nadeem Hasan ( nhasan@kde.org )
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or ( at your option ) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KSG_APPLETSETTINGS_H
+#define KSG_APPLETSETTINGS_H
+
+#include <kdialogbase.h>
+
+class QSpinBox;
+
+class KSGAppletSettings : public KDialogBase
+{
+ public:
+ KSGAppletSettings( QWidget *parent = 0, const char *name = 0 );
+ ~KSGAppletSettings();
+
+ void setNumDisplay( int );
+ int numDisplay() const;
+
+ void setSizeRatio( int );
+ int sizeRatio() const;
+
+ void setUpdateInterval( int );
+ int updateInterval() const;
+
+ private:
+ QSpinBox *mInterval;
+ QSpinBox *mNumDisplay;
+ QSpinBox *mSizeRatio;
+};
+
+#endif
diff --git a/ksysguard/gui/KSysGuardApplet.cc b/ksysguard/gui/KSysGuardApplet.cc
new file mode 100644
index 000000000..5240a068b
--- /dev/null
+++ b/ksysguard/gui/KSysGuardApplet.cc
@@ -0,0 +1,495 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger
+ <cs@kde.org>. Please do not commit any changes without consulting
+ me first. Thanks!
+
+*/
+
+#include <qcursor.h>
+#include <qdom.h>
+#include <qdragobject.h>
+#include <qfile.h>
+#include <qpushbutton.h>
+#include <qspinbox.h>
+#include <qtooltip.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ksavefile.h>
+#include <kstandarddirs.h>
+#include <kpopupmenu.h>
+
+#include <ksgrd/SensorClient.h>
+#include <ksgrd/SensorManager.h>
+#include <ksgrd/StyleEngine.h>
+
+#include "DancingBars.h"
+#include "FancyPlotter.h"
+#include "KSGAppletSettings.h"
+#include "MultiMeter.h"
+
+#include "KSysGuardApplet.h"
+
+extern "C"
+{
+ KDE_EXPORT KPanelApplet* init( QWidget *parent, const QString& configFile )
+ {
+ KGlobal::locale()->insertCatalogue( "ksysguard" );
+ return new KSysGuardApplet( configFile, KPanelApplet::Normal,
+ KPanelApplet::Preferences, parent,
+ "ksysguardapplet" );
+ }
+}
+
+KSysGuardApplet::KSysGuardApplet( const QString& configFile, Type type,
+ int actions, QWidget *parent,
+ const char *name )
+ : KPanelApplet( configFile, type, actions, parent, name)
+{
+ mSettingsDlg = 0;
+
+ KSGRD::SensorMgr = new KSGRD::SensorManager();
+
+ KSGRD::Style = new KSGRD::StyleEngine();
+
+ mDockCount = 1;
+ mDockList = new QWidget*[ mDockCount ];
+
+ mSizeRatio = 1.0;
+ addEmptyDisplay( mDockList, 0 );
+
+ updateInterval( 2 );
+
+ load();
+
+ setAcceptDrops( true );
+}
+
+KSysGuardApplet::~KSysGuardApplet()
+{
+ save();
+
+ delete [] mDockList;
+ mDockList = 0;
+
+ delete mSettingsDlg;
+ mSettingsDlg = 0;
+
+ delete KSGRD::Style;
+ delete KSGRD::SensorMgr;
+ KSGRD::SensorMgr = 0;
+}
+
+int KSysGuardApplet::widthForHeight( int height ) const
+{
+ return ( (int) ( height * mSizeRatio + 0.5 ) * mDockCount );
+}
+
+int KSysGuardApplet::heightForWidth( int width ) const
+{
+ return ( (int) ( width * mSizeRatio + 0.5 ) * mDockCount );
+}
+
+void KSysGuardApplet::resizeEvent( QResizeEvent* )
+{
+ layout();
+}
+
+void KSysGuardApplet::preferences()
+{
+ if(mSettingsDlg) {
+ return;
+ }
+ mSettingsDlg = new KSGAppletSettings( this );
+
+ connect( mSettingsDlg, SIGNAL( applyClicked() ), SLOT( applySettings() ) );
+ connect( mSettingsDlg, SIGNAL( okClicked() ), SLOT( applySettings() ) );
+ connect( mSettingsDlg, SIGNAL( finished() ), SLOT( preferencesFinished() ) );
+
+ mSettingsDlg->setNumDisplay( mDockCount );
+ mSettingsDlg->setSizeRatio( (int) ( mSizeRatio * 100.0 + 0.5 ) );
+ mSettingsDlg->setUpdateInterval( updateInterval() );
+
+ mSettingsDlg->show();
+}
+void KSysGuardApplet::preferencesFinished()
+{
+ mSettingsDlg->delayedDestruct();
+ mSettingsDlg = 0;
+}
+void KSysGuardApplet::applySettings()
+{
+ updateInterval( mSettingsDlg->updateInterval() );
+ mSizeRatio = mSettingsDlg->sizeRatio() / 100.0;
+ resizeDocks( mSettingsDlg->numDisplay() );
+
+ for ( uint i = 0; i < mDockCount; ++i )
+ if ( !mDockList[ i ]->isA( "QFrame" ) )
+ ((KSGRD::SensorDisplay*)mDockList[ i ])->setUpdateInterval( updateInterval() );
+
+ save();
+}
+
+void KSysGuardApplet::sensorDisplayModified( bool modified )
+{
+ if ( modified )
+ save();
+}
+
+void KSysGuardApplet::layout()
+{
+ if ( orientation() == Horizontal ) {
+ int h = height();
+ int w = (int) ( h * mSizeRatio + 0.5 );
+ for ( uint i = 0; i < mDockCount; ++i )
+ if ( mDockList[ i ] )
+ mDockList[ i ]->setGeometry( i * w, 0, w, h );
+ } else {
+ int w = width();
+ int h = (int) ( w * mSizeRatio + 0.5 );
+ for ( uint i = 0; i < mDockCount; ++i )
+ if ( mDockList[ i ] )
+ mDockList[ i ]->setGeometry( 0, i * h, w, h );
+ }
+}
+
+int KSysGuardApplet::findDock( const QPoint& point )
+{
+ if ( orientation() == Horizontal )
+ return ( point.x() / (int) ( height() * mSizeRatio + 0.5 ) );
+ else
+ return ( point.y() / (int) ( width() * mSizeRatio + 0.5 ) );
+}
+
+void KSysGuardApplet::dragEnterEvent( QDragEnterEvent *e )
+{
+ e->accept( QTextDrag::canDecode( e ) );
+}
+
+void KSysGuardApplet::dropEvent( QDropEvent *e )
+{
+ QString dragObject;
+
+ if ( QTextDrag::decode( e, dragObject ) ) {
+ // The host name, sensor name and type are seperated by a ' '.
+ QStringList parts = QStringList::split( ' ', dragObject );
+
+ QString hostName = parts[ 0 ];
+ QString sensorName = parts[ 1 ];
+ QString sensorType = parts[ 2 ];
+ QString sensorDescr = parts[ 3 ];
+
+ if ( hostName.isEmpty() || sensorName.isEmpty() || sensorType.isEmpty() )
+ return;
+
+ int dock = findDock( e->pos() );
+ if ( mDockList[ dock ]->isA( "QFrame" ) ) {
+ if ( sensorType == "integer" || sensorType == "float" ) {
+ KPopupMenu popup;
+ QWidget *wdg = 0;
+
+ popup.insertTitle( i18n( "Select Display Type" ) );
+ popup.insertItem( i18n( "&Signal Plotter" ), 1 );
+ popup.insertItem( i18n( "&Multimeter" ), 2 );
+ popup.insertItem( i18n( "&Dancing Bars" ), 3 );
+ switch ( popup.exec( QCursor::pos() ) ) {
+ case 1:
+ wdg = new FancyPlotter( this, "FancyPlotter", sensorDescr,
+ 100.0, 100.0, true );
+ break;
+
+ case 2:
+ wdg = new MultiMeter( this, "MultiMeter", sensorDescr,
+ 100.0, 100.0, true );
+ break;
+
+ case 3:
+ wdg = new DancingBars( this, "DancingBars", sensorDescr,
+ 100, 100, true );
+ break;
+ }
+
+ if ( wdg ) {
+ delete mDockList[ dock ];
+ mDockList[ dock ] = wdg;
+ layout();
+
+ connect( wdg, SIGNAL( modified( bool ) ),
+ SLOT( sensorDisplayModified( bool ) ) );
+
+ mDockList[ dock ]->show();
+ }
+ } else {
+ KMessageBox::sorry( this,
+ i18n( "The KSysGuard applet does not support displaying of "
+ "this type of sensor. Please choose another sensor." ) );
+
+ layout();
+ }
+ }
+
+ if ( !mDockList[ dock ]->isA( "QFrame" ) )
+ ((KSGRD::SensorDisplay*)mDockList[ dock ])->
+ addSensor( hostName, sensorName, sensorType, sensorDescr );
+ }
+
+ save();
+}
+
+void KSysGuardApplet::customEvent( QCustomEvent *e )
+{
+ if ( e->type() == QEvent::User ) {
+ // SensorDisplays send out this event if they want to be removed.
+ removeDisplay( (KSGRD::SensorDisplay*)e->data() );
+ save();
+ }
+}
+
+void KSysGuardApplet::removeDisplay( KSGRD::SensorDisplay *display )
+{
+ for ( uint i = 0; i < mDockCount; ++i )
+ if ( display == mDockList[i] ) {
+ delete mDockList[ i ];
+
+ addEmptyDisplay( mDockList, i );
+ return;
+ }
+}
+
+void KSysGuardApplet::resizeDocks( uint newDockCount )
+{
+ /* This function alters the number of available docks. The number of
+ * docks can be increased or decreased. We try to preserve existing
+ * docks if possible. */
+
+ if ( newDockCount == mDockCount ) {
+ emit updateLayout();
+ return;
+ }
+
+ // Create and initialize new dock array.
+ QWidget** tmp = new QWidget*[ newDockCount ];
+
+ uint i;
+ for ( i = 0; ( i < newDockCount ) && ( i < mDockCount ); ++i )
+ tmp[ i ] = mDockList[ i ];
+
+ for ( i = newDockCount; i < mDockCount; ++i )
+ if ( mDockList[ i ] )
+ delete mDockList[ i ];
+
+ for ( i = mDockCount; i < newDockCount; ++i )
+ addEmptyDisplay( tmp, i );
+
+ delete [] mDockList;
+
+ mDockList = tmp;
+ mDockCount = newDockCount;
+
+ emit updateLayout();
+}
+
+bool KSysGuardApplet::load()
+{
+ KStandardDirs* kstd = KGlobal::dirs();
+ kstd->addResourceType( "data", "share/apps/ksysguard" );
+ QString fileName = kstd->findResource( "data", "KSysGuardApplet.xml" );
+
+ QFile file( fileName );
+ if ( !file.open( IO_ReadOnly ) ) {
+ KMessageBox::sorry( this, i18n( "Cannot open the file %1." ).arg( fileName ) );
+ return false;
+ }
+
+ // Parse the XML file.
+ QDomDocument doc;
+
+ // Read in file and check for a valid XML header.
+ if ( !doc.setContent( &file ) ) {
+ KMessageBox::sorry( this, i18n( "The file %1 does not contain valid XML." )
+ .arg( fileName ) );
+ return false;
+ }
+
+ // Check for proper document type.
+ if ( doc.doctype().name() != "KSysGuardApplet" ) {
+ KMessageBox::sorry( this, i18n( "The file %1 does not contain a valid applet "
+ "definition, which must have a document type 'KSysGuardApplet'." )
+ .arg( fileName ) );
+ return false;
+ }
+
+ QDomElement element = doc.documentElement();
+ bool ok;
+ uint count = element.attribute( "dockCnt" ).toUInt( &ok );
+ if ( !ok )
+ count = 1;
+
+ mSizeRatio = element.attribute( "sizeRatio" ).toDouble( &ok );
+ if ( !ok )
+ mSizeRatio = 1.0;
+
+ updateInterval( element.attribute( "interval" ).toUInt( &ok ) );
+ if ( !ok )
+ updateInterval( 2 );
+
+ resizeDocks( count );
+
+ /* Load lists of hosts that are needed for the work sheet and try
+ * to establish a connection. */
+ QDomNodeList dnList = element.elementsByTagName( "host" );
+ uint i;
+ for ( i = 0; i < dnList.count(); ++i ) {
+ QDomElement element = dnList.item( i ).toElement();
+ int port = element.attribute( "port" ).toInt( &ok );
+ if ( !ok )
+ port = -1;
+
+ KSGRD::SensorMgr->engage( element.attribute( "name" ),
+ element.attribute( "shell" ),
+ element.attribute( "command" ), port );
+ }
+ //if no hosts are specified, at least connect to localhost
+ if(dnList.count() == 0)
+ KSGRD::SensorMgr->engage( "localhost", "", "ksysguardd", -1);
+
+ // Load the displays and place them into the work sheet.
+ dnList = element.elementsByTagName( "display" );
+ for ( i = 0; i < dnList.count(); ++i ) {
+ QDomElement element = dnList.item( i ).toElement();
+ uint dock = element.attribute( "dock" ).toUInt();
+ if ( i >= mDockCount ) {
+ kdDebug (1215) << "Dock number " << i << " out of range "
+ << mDockCount << endl;
+ return false;
+ }
+
+ QString classType = element.attribute( "class" );
+ KSGRD::SensorDisplay* newDisplay;
+ if ( classType == "FancyPlotter" )
+ newDisplay = new FancyPlotter( this, "FancyPlotter", "Dummy", 100.0, 100.0, true /*no frame*/, true /*run ksysguard menu*/);
+ else if ( classType == "MultiMeter" )
+ newDisplay = new MultiMeter( this, "MultiMeter", "Dummy", 100.0, 100.0, true /*no frame*/, true /*run ksysguard menu*/ );
+ else if ( classType == "DancingBars" )
+ newDisplay = new DancingBars( this, "DancingBars", "Dummy", 100, 100, true /*no frame*/, true /*run ksysguard menu*/);
+ else {
+ KMessageBox::sorry( this, i18n( "The KSysGuard applet does not support displaying of "
+ "this type of sensor. Please choose another sensor." ) );
+ return false;
+ }
+
+ newDisplay->setUpdateInterval( updateInterval() );
+
+ // load display specific settings
+ if ( !newDisplay->restoreSettings( element ) )
+ return false;
+
+ delete mDockList[ dock ];
+ mDockList[ dock ] = newDisplay;
+
+ connect( newDisplay, SIGNAL( modified( bool ) ),
+ SLOT( sensorDisplayModified( bool ) ) );
+ }
+
+ return true;
+}
+
+bool KSysGuardApplet::save()
+{
+ // Parse the XML file.
+ QDomDocument doc( "KSysGuardApplet" );
+ doc.appendChild( doc.createProcessingInstruction(
+ "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
+
+ // save work sheet information
+ QDomElement ws = doc.createElement( "WorkSheet" );
+ doc.appendChild( ws );
+ ws.setAttribute( "dockCnt", mDockCount );
+ ws.setAttribute( "sizeRatio", mSizeRatio );
+ ws.setAttribute( "interval", updateInterval() );
+
+ QStringList hosts;
+ uint i;
+ for ( i = 0; i < mDockCount; ++i )
+ if ( !mDockList[ i ]->isA( "QFrame" ) )
+ ((KSGRD::SensorDisplay*)mDockList[ i ])->hosts( hosts );
+
+ // save host information (name, shell, etc.)
+ QStringList::Iterator it;
+ for ( it = hosts.begin(); it != hosts.end(); ++it ) {
+ QString shell, command;
+ int port;
+
+ if ( KSGRD::SensorMgr->hostInfo( *it, shell, command, port ) ) {
+ QDomElement host = doc.createElement( "host" );
+ ws.appendChild( host );
+ host.setAttribute( "name", *it );
+ host.setAttribute( "shell", shell );
+ host.setAttribute( "command", command );
+ host.setAttribute( "port", port );
+ }
+ }
+
+ for ( i = 0; i < mDockCount; ++i )
+ if ( !mDockList[ i ]->isA( "QFrame" ) ) {
+ QDomElement element = doc.createElement( "display" );
+ ws.appendChild( element );
+ element.setAttribute( "dock", i );
+ element.setAttribute( "class", mDockList[ i ]->className() );
+
+ ((KSGRD::SensorDisplay*)mDockList[ i ])->saveSettings( doc, element );
+ }
+
+ KStandardDirs* kstd = KGlobal::dirs();
+ kstd->addResourceType( "data", "share/apps/ksysguard" );
+ QString fileName = kstd->saveLocation( "data", "ksysguard" );
+ fileName += "/KSysGuardApplet.xml";
+
+ KSaveFile file( fileName, 0644 );
+
+ if ( file.status() == 0 )
+ {
+ file.textStream()->setEncoding( QTextStream::UnicodeUTF8 );
+ *(file.textStream()) << doc;
+ file.close();
+ }
+ else
+ {
+ KMessageBox::sorry( this, i18n( "Cannot save file %1" ).arg( fileName ) );
+ return false;
+ }
+
+ return true;
+}
+
+void KSysGuardApplet::addEmptyDisplay( QWidget **dock, uint pos )
+{
+ dock[ pos ] = new QFrame( this );
+ ((QFrame*)dock[ pos ])->setFrameStyle( QFrame::WinPanel | QFrame::Sunken );
+ QToolTip::add( dock[ pos ],
+ i18n( "Drag sensors from the KDE System Guard into this cell." ) );
+
+ layout();
+ if ( isVisible() )
+ dock[ pos ]->show();
+}
+
+#include "KSysGuardApplet.moc"
diff --git a/ksysguard/gui/KSysGuardApplet.h b/ksysguard/gui/KSysGuardApplet.h
new file mode 100644
index 000000000..b9d91091e
--- /dev/null
+++ b/ksysguard/gui/KSysGuardApplet.h
@@ -0,0 +1,85 @@
+/*
+ KKSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger
+ <cs@kde.org>. Please do not commit any changes without consulting
+ me first. Thanks!
+
+*/
+
+#ifndef KSG_KSYSGUARDAPPLET_H
+#define KSG_KSYSGUARDAPPLET_H
+
+#include <kpanelapplet.h>
+
+namespace KSGRD
+{
+class SensorBoard;
+class SensorDisplay;
+}
+
+class QDragEnterEvent;
+class QDropEvent;
+class QPoint;
+class KSGAppletSettings;
+
+class KSysGuardApplet : public KPanelApplet, public KSGRD::SensorBoard
+{
+ Q_OBJECT
+
+ public:
+ KSysGuardApplet( const QString& configFile, Type type = Normal,
+ int actions = 0, QWidget *parent = 0,
+ const char *name = 0 );
+ virtual ~KSysGuardApplet();
+
+ virtual int heightForWidth( int width ) const;
+ virtual int widthForHeight( int height ) const;
+
+ virtual void preferences();
+
+ protected:
+ void resizeEvent( QResizeEvent* );
+ void dragEnterEvent( QDragEnterEvent* );
+ void dropEvent( QDropEvent* );
+ void customEvent( QCustomEvent* );
+
+
+ private slots:
+ void applySettings();
+ void sensorDisplayModified( bool );
+ void preferencesFinished();
+
+ private:
+ void layout();
+ void resizeDocks( uint newDockCount );
+ void addEmptyDisplay( QWidget **dock, uint pos );
+
+ bool load();
+ bool save();
+
+ int findDock( const QPoint& );
+ void removeDisplay( KSGRD::SensorDisplay* );
+
+ double mSizeRatio;
+ uint mDockCount;
+ KSGAppletSettings* mSettingsDlg;
+ QWidget** mDockList;
+};
+
+#endif
diff --git a/ksysguard/gui/KSysGuardApplet.xml b/ksysguard/gui/KSysGuardApplet.xml
new file mode 100644
index 000000000..2f115f61e
--- /dev/null
+++ b/ksysguard/gui/KSysGuardApplet.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE KSysGuardApplet>
+<WorkSheet sizeRatio="1.2" dockCnt="2" interval="4" >
+ <host port="-1" shell="" name="localhost" command="ksysguardd" />
+ <display topBar="1" vColor="326429" title="CPU" dock="0" bColor="3223601" graphStyle="0" class="FancyPlotter" unit="" hScale="1" showUnit="0" hLines="1" hCount="2" vLines="1" autoRange="1" min="0" max="0" hColor="14606046" globalUpdate="1" pause="0" fontSize="8" labels="1" vScroll="1" vDistance="30" >
+ <beam sensorName="cpu/user" hostName="localhost" color="1608191" sensorType="integer" />
+ <beam sensorName="cpu/sys" hostName="localhost" color="16743688" sensorType="integer" />
+ <beam sensorName="cpu/nice" hostName="localhost" color="16771600" sensorType="integer" />
+ </display>
+ <display topBar="1" vColor="4605510" title="Mem" dock="1" bColor="3223601" graphStyle="0" class="FancyPlotter" unit="" hScale="5" showUnit="0" hLines="1" hCount="2" vLines="0" autoRange="1" min="0" max="0" hColor="14606046" globalUpdate="1" pause="0" fontSize="8" labels="0" vScroll="1" vDistance="30" >
+ <beam sensorName="mem/physical/application" hostName="localhost" color="1608191" sensorType="integer" />
+ <beam sensorName="mem/physical/buf" hostName="localhost" color="16743688" sensorType="integer" />
+ <beam sensorName="mem/physical/cached" hostName="localhost" color="16771600" sensorType="integer" />
+ </display>
+</WorkSheet>
diff --git a/ksysguard/gui/Makefile.am b/ksysguard/gui/Makefile.am
new file mode 100644
index 000000000..c0b9d12b3
--- /dev/null
+++ b/ksysguard/gui/Makefile.am
@@ -0,0 +1,63 @@
+
+kdemimedir = $(kde_mimedir)/application
+kdemime_DATA = x-ksysguard.desktop
+
+rcdir = $(kde_datadir)/ksysguard
+rc_DATA = ksysguardui.rc
+
+xdg_apps_DATA = ksysguard.desktop
+
+lnkdir = $(kde_datadir)/kicker/applets
+lnk_DATA = ksysguardapplet.desktop
+
+# claim, which subdirectories you want to install
+SUBDIRS = ksgrd SensorDisplayLib
+
+# set the include path for X, qt and KDE
+INCLUDES = -I$(srcdir)/ksgrd -I$(srcdir)/SensorDisplayLib -I$(top_builddir)/ksysguard/gui/SensorDisplayLib $(all_includes)
+
+####### This part is very ksysguard specific
+# you can add here more. This one gets installed
+bin_PROGRAMS = ksysguard kpm
+
+# Which sources should be compiled for ksysguard.
+ksysguard_SOURCES = \
+ SensorBrowser.cc \
+ WorkSheet.cc \
+ WorkSheetSettings.cc \
+ Workspace.cc \
+ ksysguard.cc ksysguard.skel
+
+ksysguard_LDADD = \
+ ksgrd/libksgrd.la \
+ SensorDisplayLib/libsensordisplays.la \
+ $(LIB_KDEUI) $(LIB_KIO) $(LIB_KDNSSD)
+ksysguard_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+
+kpm_SOURCES = kpm.c
+
+appdatadir = $(kde_datadir)/ksysguard
+appdata_DATA = ProcessTable.sgrd SystemLoad.sgrd KSysGuardApplet.xml
+
+# This stuff is now for the kicker applet
+kde_module_LTLIBRARIES = sysguard_panelapplet.la
+
+sysguard_panelapplet_la_SOURCES = \
+ KSysGuardApplet.cc \
+ KSGAppletSettings.cc
+
+sysguard_panelapplet_la_LIBADD = \
+ ksgrd/libksgrd.la \
+ SensorDisplayLib/libsensordisplays.la \
+ $(LIB_KDEUI) $(LIB_KIO)
+sysguard_panelapplet_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+
+EXTRA_DIST = $(lnk_DATA)
+
+# just to make sure, automake makes them
+METASOURCES = AUTO
+
+messages: rc.cpp
+ $(EXTRACTRC) `find . -name "*.ui"` >> rc.cpp
+ $(EXTRACTATTR) --attr=display,title SystemLoad.sgrd KSysGuardApplet.xml >> rc.cpp
+ $(XGETTEXT) `find . -name "*.cpp" -o -name "*.cc"` -o $(podir)/ksysguard.pot
diff --git a/ksysguard/gui/ProcessTable.sgrd b/ksysguard/gui/ProcessTable.sgrd
new file mode 100644
index 000000000..2717a2b9d
--- /dev/null
+++ b/ksysguard/gui/ProcessTable.sgrd
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE KSysGuardWorkSheet>
+<WorkSheet rows="1" interval="2" columns="1" >
+ <host port="-1" shell="" name="localhost" command="ksysguardd" />
+ <display title="" class="ProcessController" row="0" unit="" sensorName="ps" column="0" filter="0" showUnit="0" sortColumn="0" hostName="localhost" globalUpdate="1" incrOrder="1" tree="0" sensorType="table" pause="0" >
+ <column currentWidth="127" savedWidth="126" index="0" />
+ <column currentWidth="42" savedWidth="46" index="1" />
+ <column currentWidth="0" savedWidth="42" index="2" />
+ <column currentWidth="0" savedWidth="33" index="3" />
+ <column currentWidth="0" savedWidth="42" index="4" />
+ <column currentWidth="0" savedWidth="66" index="5" />
+ <column currentWidth="52" savedWidth="45" index="6" />
+ <column currentWidth="72" savedWidth="48" index="7" />
+ <column currentWidth="38" savedWidth="36" index="8" />
+ <column currentWidth="57" savedWidth="65" index="9" />
+ <column currentWidth="52" savedWidth="30" index="10" />
+ <column currentWidth="56" savedWidth="150" index="11" />
+ <column currentWidth="402" savedWidth="150" index="12" />
+ </display>
+</WorkSheet>
diff --git a/ksysguard/gui/SensorBrowser.cc b/ksysguard/gui/SensorBrowser.cc
new file mode 100644
index 000000000..969978947
--- /dev/null
+++ b/ksysguard/gui/SensorBrowser.cc
@@ -0,0 +1,412 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>. Please do
+ not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <qdragobject.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ksgrd/SensorManager.h>
+
+#include "SensorBrowser.h"
+
+class HostItem : public QListViewItem
+{
+ public:
+ HostItem( SensorBrowser *parent, const QString &text, int id,
+ KSGRD::SensorAgent *host)
+ : QListViewItem( parent, text ), mInited( false ), mId( id ),
+ mHost( host ), mParent( parent )
+ {
+ setExpandable( true );
+ }
+
+ void setOpen( bool open )
+ {
+ if ( open && !mInited ) {
+ mInited = true;
+ // request sensor list from host
+ mHost->sendRequest( "monitors", mParent, mId );
+ }
+
+ QListViewItem::setOpen( open );
+ }
+
+ private:
+ bool mInited;
+ int mId;
+ KSGRD::SensorAgent* mHost;
+ SensorBrowser* mParent;
+};
+
+SensorBrowser::SensorBrowser( QWidget* parent, KSGRD::SensorManager* sm,
+ const char* name)
+ : KListView( parent, name ), mSensorManager( sm )
+{
+ mHostInfoList.setAutoDelete(true);
+
+ connect( mSensorManager, SIGNAL( update() ), SLOT( update() ) );
+ connect( this, SIGNAL( clicked( QListViewItem* ) ),
+ SLOT( newItemSelected( QListViewItem* ) ) );
+ connect( this, SIGNAL( returnPressed( QListViewItem* ) ),
+ SLOT( newItemSelected( QListViewItem* ) ) );
+
+ addColumn( i18n( "Sensor Browser" ) );
+ addColumn( i18n( "Sensor Type" ) );
+ setFullWidth( true );
+
+ QToolTip::add( this, i18n( "Drag sensors to empty cells of a worksheet "
+ "or the panel applet." ) );
+ setRootIsDecorated( true );
+
+ // The sensor browser can be completely hidden.
+ setMinimumWidth( 1 );
+
+ QWhatsThis::add( this, i18n( "The sensor browser lists the connected hosts and the sensors "
+ "that they provide. Click and drag sensors into drop zones "
+ "of a worksheet or the panel applet. A display will appear "
+ "that visualizes the "
+ "values provided by the sensor. Some sensor displays can "
+ "display values of multiple sensors. Simply drag other "
+ "sensors on to the display to add more sensors." ) );
+}
+
+SensorBrowser::~SensorBrowser()
+{
+}
+
+void SensorBrowser::disconnect()
+{
+ QPtrListIterator<HostInfo> it( mHostInfoList );
+
+ for ( ; it.current(); ++it )
+ if ( (*it)->listViewItem()->isSelected() ) {
+ kdDebug(1215) << "Disconnecting " << (*it)->hostName() << endl;
+ KSGRD::SensorMgr->requestDisengage( (*it)->sensorAgent() );
+ }
+}
+
+void SensorBrowser::hostReconfigured( const QString& )
+{
+ // TODO: not yet implemented.
+}
+
+void SensorBrowser::update()
+{
+ static int id = 0;
+
+ KSGRD::SensorManagerIterator it( mSensorManager );
+
+ mHostInfoList.clear();
+ clear();
+
+ KSGRD::SensorAgent* host;
+ for ( int i = 0 ; ( host = it.current() ); ++it, ++i ) {
+ QString hostName = mSensorManager->hostName( host );
+ HostItem* lvi = new HostItem( this, hostName, id, host );
+
+ QPixmap pix = KGlobal::iconLoader()->loadIcon( "computer", KIcon::Desktop, KIcon::SizeSmall );
+ lvi->setPixmap( 0, pix );
+
+ HostInfo* hostInfo = new HostInfo( id, host, hostName, lvi );
+ mHostInfoList.append( hostInfo );
+ ++id;
+ }
+
+ setMouseTracking( false );
+}
+
+void SensorBrowser::newItemSelected( QListViewItem *item )
+{
+ static bool showAnnoyingPopup = true;
+ if ( item && item->pixmap( 0 ) && showAnnoyingPopup)
+ {
+ showAnnoyingPopup = false;
+ KMessageBox::information( this, i18n( "Drag sensors to empty fields in a worksheet." ),
+ QString::null, "ShowSBUseInfo" );
+ }
+}
+
+void SensorBrowser::answerReceived( int id, const QString &answer )
+{
+ /* An answer has the following format:
+
+ cpu/idle integer
+ cpu/sys integer
+ cpu/nice integer
+ cpu/user integer
+ ps table
+ */
+
+ QPtrListIterator<HostInfo> it( mHostInfoList );
+
+ /* Check if id is still valid. It can get obsolete by rapid calls
+ * of update() or when the sensor died. */
+ for ( ; it.current(); ++it )
+ if ( (*it)->id() == id )
+ break;
+
+ if ( !it.current() )
+ return;
+
+ KSGRD::SensorTokenizer lines( answer, '\n' );
+
+ for ( uint i = 0; i < lines.count(); ++i ) {
+ if ( lines[ i ].isEmpty() )
+ break;
+
+ KSGRD::SensorTokenizer words( lines[ i ], '\t' );
+ QString sensorName = words[ 0 ];
+ QString sensorType = words[ 1 ];
+
+ /* Calling update() a rapid sequence will create pending
+ * requests that do not get erased by calling
+ * clear(). Subsequent updates will receive the old pending
+ * answers so we need to make sure that we register each
+ * sensor only once. */
+ if ( (*it)->isRegistered( sensorName ) )
+ return;
+
+ /* The sensor browser can display sensors in a hierachical order.
+ * Sensors can be grouped into nodes by seperating the hierachical
+ * nodes through slashes in the sensor name. E. g. cpu/user is
+ * the sensor user in the cpu node. There is no limit for the
+ * depth of nodes. */
+ KSGRD::SensorTokenizer absolutePath( sensorName, '/' );
+
+ QListViewItem* parent = (*it)->listViewItem();
+ for ( uint j = 0; j < absolutePath.count(); ++j ) {
+ // Localize the sensor name part by part.
+ QString name = KSGRD::SensorMgr->translateSensorPath( absolutePath[ j ] );
+
+ bool found = false;
+ QListViewItem* sibling = parent->firstChild();
+ while ( sibling && !found ) {
+ if (sibling->text( 0 ) == name ) {
+ // The node or sensor is already known.
+ found = true;
+ } else
+ sibling = sibling->nextSibling();
+ }
+ if ( !found ) {
+ QListViewItem* lvi = new QListViewItem( parent, name );
+ if ( j == absolutePath.count() - 1 ) {
+ QPixmap pix = KGlobal::iconLoader()->loadIcon( "ksysguardd", KIcon::Desktop,
+ KIcon::SizeSmall );
+ lvi->setPixmap( 0, pix );
+ lvi->setText( 1, KSGRD::SensorMgr->translateSensorType( sensorType ) );
+
+ // add sensor info to internal data structure
+ (*it)->addSensor( lvi, sensorName, name, sensorType );
+ } else
+ parent = lvi;
+
+ // The child indicator might need to be updated.
+ repaintItem( parent );
+ } else
+ parent = sibling;
+ }
+ }
+
+ repaintItem( (*it)->listViewItem() );
+}
+
+void SensorBrowser::viewportMouseMoveEvent( QMouseEvent *e )
+{
+ /* setMouseTracking(false) seems to be broken. With current Qt
+ * mouse tracking cannot be turned off. So we have to check each event
+ * whether the LMB is really pressed. */
+
+ if ( !( e->state() & LeftButton ) )
+ return;
+
+ QListViewItem* item = itemAt( e->pos() );
+ if ( !item ) // no item under cursor
+ return;
+
+ // Make sure that a sensor and not a node or hostname has been picked.
+ QPtrListIterator<HostInfo> it( mHostInfoList );
+ for ( ; it.current() && !(*it)->isRegistered( item ); ++it );
+ if ( !it.current() )
+ return;
+
+ // Create text drag object as
+ // "<hostname> <sensorname> <sensortype> <sensordescription>".
+ // Only the description may contain blanks.
+ mDragText = (*it)->hostName() + " " +
+ (*it)->sensorName( item ) + " " +
+ (*it)->sensorType( item ) + " " +
+ (*it)->sensorDescription( item );
+
+ QDragObject* dragObject = new QTextDrag( mDragText, this );
+ dragObject->dragCopy();
+}
+
+QStringList SensorBrowser::listHosts()
+{
+ QStringList hostList;
+
+ QPtrListIterator<HostInfo> it( mHostInfoList );
+ for ( ; it.current(); ++it )
+ hostList.append( (*it)->hostName() );
+
+ return hostList;
+}
+
+QStringList SensorBrowser::listSensors( const QString &hostName )
+{
+ QPtrListIterator<HostInfo> it( mHostInfoList );
+ for ( ; it.current(); ++it ) {
+ if ( (*it)->hostName() == hostName ) {
+ return (*it)->allSensorNames();
+ }
+ }
+
+ return QStringList();
+}
+
+/**
+ Helper classes
+ */
+SensorInfo::SensorInfo( QListViewItem *lvi, const QString &name,
+ const QString &desc, const QString &type )
+ : mLvi( lvi ), mName( name ), mDesc( desc ), mType( type )
+{
+}
+
+QListViewItem* SensorInfo::listViewItem() const
+{
+ return mLvi;
+}
+
+const QString& SensorInfo::name() const
+{
+ return mName;
+}
+
+const QString& SensorInfo::type() const
+{
+ return mType;
+}
+
+const QString& SensorInfo::description() const
+{
+ return mDesc;
+}
+
+HostInfo::HostInfo( int id, const KSGRD::SensorAgent *agent,
+ const QString &name, QListViewItem *lvi )
+ : mId( id ), mSensorAgent( agent ), mHostName( name ), mLvi( lvi )
+{
+ mSensorList.setAutoDelete( true );
+}
+
+int HostInfo::id() const
+{
+ return ( mId );
+}
+
+const KSGRD::SensorAgent* HostInfo::sensorAgent() const
+{
+ return mSensorAgent;
+}
+
+const QString& HostInfo::hostName() const
+{
+ return mHostName;
+}
+
+QListViewItem* HostInfo::listViewItem() const
+{
+ return mLvi;
+}
+
+const QString& HostInfo::sensorName( const QListViewItem *lvi ) const
+{
+ QPtrListIterator<SensorInfo> it( mSensorList );
+ for ( ; it.current() && (*it)->listViewItem() != lvi; ++it );
+
+ Q_ASSERT( it.current() );
+ return ( (*it)->name() );
+}
+
+QStringList HostInfo::allSensorNames() const
+{
+ QStringList list;
+
+ QPtrListIterator<SensorInfo> it( mSensorList );
+ for ( ; it.current(); ++it )
+ list.append( it.current()->name() );
+
+ return list;
+}
+
+const QString& HostInfo::sensorType( const QListViewItem *lvi ) const
+{
+ QPtrListIterator<SensorInfo> it( mSensorList );
+ for ( ; it.current() && (*it)->listViewItem() != lvi; ++it );
+
+ Q_ASSERT( it.current() );
+ return ( (*it)->type() );
+}
+
+const QString& HostInfo::sensorDescription( const QListViewItem *lvi ) const
+{
+ QPtrListIterator<SensorInfo> it( mSensorList );
+ for ( ; it.current() && (*it)->listViewItem() != lvi; ++it );
+
+ Q_ASSERT( it.current() );
+ return ( (*it)->description() );
+}
+
+void HostInfo::addSensor( QListViewItem *lvi, const QString& name,
+ const QString& desc, const QString& type )
+{
+ SensorInfo* info = new SensorInfo( lvi, name, desc, type );
+ mSensorList.append( info );
+}
+
+bool HostInfo::isRegistered( const QString& name ) const
+{
+ QPtrListIterator<SensorInfo> it( mSensorList );
+ for ( ; it.current(); ++it )
+ if ( (*it)->name() == name )
+ return true;
+
+ return false;
+}
+
+bool HostInfo::isRegistered( QListViewItem *lvi ) const
+{
+ QPtrListIterator<SensorInfo> it( mSensorList );
+ for ( ; it.current(); ++it )
+ if ( (*it)->listViewItem() == lvi )
+ return true;
+
+ return false;
+}
+
+#include "SensorBrowser.moc"
diff --git a/ksysguard/gui/SensorBrowser.h b/ksysguard/gui/SensorBrowser.h
new file mode 100644
index 000000000..9021166d9
--- /dev/null
+++ b/ksysguard/gui/SensorBrowser.h
@@ -0,0 +1,193 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>. Please do
+ not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_SENSORBROWSER_H
+#define KSG_SENSORBROWSER_H
+
+#include <qdict.h>
+
+#include <klistview.h>
+#include <ksgrd/SensorClient.h>
+
+class QMouseEvent;
+
+namespace KSGRD {
+class SensorManager;
+class SensorAgent;
+}
+
+class SensorInfo;
+class HostInfo;
+
+/**
+ * The SensorBrowser is the graphical front-end of the SensorManager. It
+ * displays the currently available hosts and their sensors.
+ */
+class SensorBrowser : public KListView, public KSGRD::SensorClient
+{
+ Q_OBJECT
+
+ public:
+ SensorBrowser( QWidget* parent, KSGRD::SensorManager* sm, const char* name = 0 );
+ ~SensorBrowser();
+
+ QStringList listHosts();
+ QStringList listSensors( const QString &hostName );
+
+ public slots:
+ void disconnect();
+ void hostReconfigured( const QString &hostName );
+ void update();
+ void newItemSelected( QListViewItem *item );
+
+ protected:
+ virtual void viewportMouseMoveEvent( QMouseEvent* );
+
+ private:
+ void answerReceived( int id, const QString& );
+
+ KSGRD::SensorManager* mSensorManager;
+
+ QPtrList<HostInfo> mHostInfoList;
+ QString mDragText;
+
+};
+
+/**
+ Helper classes
+ */
+class SensorInfo
+{
+ public:
+ SensorInfo( QListViewItem *lvi, const QString &name, const QString &desc,
+ const QString &type );
+ ~SensorInfo() {}
+
+ /**
+ Returns a pointer to the list view item of the sensor.
+ */
+ QListViewItem* listViewItem() const;
+
+ /**
+ Returns the name of the sensor.
+ */
+ const QString& name() const;
+
+ /**
+ Returns the description of the sensor.
+ */
+ const QString& description() const;
+
+ /**
+ Returns the type of the sensor.
+ */
+ const QString& type() const;
+
+ private:
+ QListViewItem* mLvi;
+ QString mName;
+ QString mDesc;
+ QString mType;
+};
+
+class HostInfo
+{
+ public:
+ HostInfo( int id, const KSGRD::SensorAgent *agent, const QString &name,
+ QListViewItem *lvi );
+ ~HostInfo() { }
+
+ /**
+ Returns the unique id of the host.
+ */
+ int id() const;
+
+ /**
+ Returns a pointer to the sensor agent of the host.
+ */
+ const KSGRD::SensorAgent* sensorAgent() const;
+
+ /**
+ Returns the name of the host.
+ */
+ const QString& hostName() const;
+
+ /**
+ Returns the a pointer to the list view item of the host.
+ */
+ QListViewItem* listViewItem() const;
+
+ /**
+ Returns the sensor name of a special list view item.
+ */
+ const QString& sensorName( const QListViewItem *lvi ) const;
+
+ /**
+ Returns all sensor names of the host.
+ */
+ QStringList allSensorNames() const;
+
+ /**
+ Returns the type of a special list view item.
+ */
+ const QString& sensorType( const QListViewItem *lvi ) const;
+
+ /**
+ Returns the description of a special list view item.
+ */
+ const QString& sensorDescription( const QListViewItem *lvi ) const;
+
+ /**
+ Adds a new Sensor to the host.
+
+ @param lvi The list view item.
+ @param name The sensor name.
+ @param desc A description.
+ @param type The type of the sensor.
+ */
+ void addSensor( QListViewItem *lvi, const QString& name,
+ const QString& desc, const QString& type );
+
+ /**
+ Returns whether the sensor with @ref name
+ is registered at the host.
+ */
+ bool isRegistered( const QString& name ) const;
+
+ /**
+ Returns whether the sensor with @ref lvi
+ is registered at the host.
+ */
+ bool isRegistered( QListViewItem *lvi ) const;
+
+ private:
+ int mId;
+
+ const KSGRD::SensorAgent* mSensorAgent;
+ const QString mHostName;
+ QListViewItem* mLvi;
+
+ QPtrList<SensorInfo> mSensorList;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/BarGraph.cc b/ksysguard/gui/SensorDisplayLib/BarGraph.cc
new file mode 100644
index 000000000..f6dc741cb
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/BarGraph.cc
@@ -0,0 +1,177 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <assert.h>
+#include <string.h>
+
+#include <qpainter.h>
+
+#include <kdebug.h>
+#include <kiconloader.h>
+
+#include <ksgrd/StyleEngine.h>
+
+#include "BarGraph.h"
+
+BarGraph::BarGraph( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ // paintEvent covers whole widget so we use no background to avoid flicker
+ setBackgroundMode( NoBackground );
+
+ bars = 0;
+ minValue = 0.0;
+ maxValue = 100.0;
+ lowerLimit = upperLimit = 0.0;
+ lowerLimitActive = upperLimitActive = false;
+
+ normalColor = KSGRD::Style->firstForegroundColor();
+ alarmColor = KSGRD::Style->alarmColor();
+ backgroundColor = KSGRD::Style->backgroundColor();
+ fontSize = KSGRD::Style->fontSize();
+
+ // Anything smaller than this does not make sense.
+ setMinimumSize( 16, 16 );
+ setSizePolicy( QSizePolicy( QSizePolicy::Expanding,
+ QSizePolicy::Expanding, false ) );
+}
+
+BarGraph::~BarGraph()
+{
+}
+
+bool BarGraph::addBar( const QString &footer )
+{
+ samples.resize( bars + 1 );
+ samples[ bars++ ] = 0.0;
+ footers.append( footer );
+
+ return true;
+}
+
+bool BarGraph::removeBar( uint idx )
+{
+ if ( idx >= bars ) {
+ kdDebug(1215) << "BarGraph::removeBar: idx " << idx << " out of range "
+ << bars << endl;
+ return false;
+ }
+
+ samples.resize( --bars );
+ footers.remove( footers.at( idx ) );
+ update();
+
+ return true;
+}
+
+void BarGraph::updateSamples( const QMemArray<double> &newSamples )
+{
+ samples = newSamples;
+ update();
+}
+
+void BarGraph::changeRange( double min, double max )
+{
+ minValue = min;
+ maxValue = max;
+}
+
+void BarGraph::paintEvent( QPaintEvent* )
+{
+ int w = width();
+ int h = height();
+
+ QPixmap pm( w, h );
+ QPainter p;
+ p.begin( &pm, this );
+ p.setFont( QFont( p.font().family(), fontSize ) );
+ QFontMetrics fm( p.font() );
+
+ pm.fill( backgroundColor );
+
+ /* Draw white line along the bottom and the right side of the
+ * widget to create a 3D like look. */
+ p.setPen( QColor( colorGroup().light() ) );
+ p.drawLine( 0, h - 1, w - 1, h - 1 );
+ p.drawLine( w - 1, 0, w - 1, h - 1 );
+
+ p.setClipRect( 1, 1, w - 2, h - 2 );
+
+ if ( bars > 0 ) {
+ int barWidth = ( w - 2 ) / bars;
+ uint b;
+ /* Labels are only printed underneath the bars if the labels
+ * for all bars are smaller than the bar width. If a single
+ * label does not fit no label is shown. */
+ bool showLabels = true;
+ for ( b = 0; b < bars; b++ )
+ if ( fm.width( footers[ b ] ) > barWidth )
+ showLabels = false;
+
+ int barHeight;
+ if ( showLabels )
+ barHeight = h - 2 - ( 2 * fm.lineSpacing() ) - 2;
+ else
+ barHeight = h - 2;
+
+ for ( uint b = 0; b < bars; b++ ) {
+ int topVal = (int) ( (float)barHeight / maxValue *
+ ( samples[ b ] - minValue ) );
+ /* TODO: This widget does not handle negative values properly. */
+ if ( topVal < 0 )
+ topVal = 0;
+
+ for ( int i = 0; i < barHeight && i < topVal; i += 2 ) {
+ if ( ( upperLimitActive && samples[ b ] > upperLimit ) ||
+ ( lowerLimitActive && samples[ b ] < lowerLimit ) )
+ p.setPen( alarmColor.light( static_cast<int>( 30 + ( 70.0 /
+ ( barHeight + 1 ) * i ) ) ) );
+ else
+ p.setPen( normalColor.light( static_cast<int>( 30 + ( 70.0 /
+ ( barHeight + 1 ) * i ) ) ) );
+ p.drawLine( b * barWidth + 3, barHeight - i, ( b + 1 ) * barWidth - 3,
+ barHeight - i );
+ }
+
+ if ( ( upperLimitActive && samples[ b ] > upperLimit ) ||
+ ( lowerLimitActive && samples[ b ] < lowerLimit ) )
+ p.setPen( alarmColor );
+ else
+ p.setPen( normalColor );
+
+ if ( showLabels ) {
+ p.drawText( b * barWidth + 3, h - ( 2 * fm.lineSpacing() ) - 2,
+ barWidth - 2 * 3, fm.lineSpacing(), Qt::AlignCenter,
+ footers[ b ] );
+ p.drawText( b * barWidth + 3, h - fm.lineSpacing() - 2,
+ barWidth - 2 * 3, fm.lineSpacing(), Qt::AlignCenter,
+ QString( "%1" ).arg( samples[ b ] ) );
+ }
+ }
+ }
+
+ p.end();
+ bitBlt( this, 0, 0, &pm );
+}
+
+#include "BarGraph.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/BarGraph.h b/ksysguard/gui/SensorDisplayLib/BarGraph.h
new file mode 100644
index 000000000..aca20c629
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/BarGraph.h
@@ -0,0 +1,94 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_BARGRAPH_H
+#define KSG_BARGRAPH_H
+
+#include <qmemarray.h>
+#include <qptrvector.h>
+#include <qwidget.h>
+
+class BarGraph : public QWidget
+{
+ Q_OBJECT
+
+ friend class DancingBars;
+
+ public:
+ BarGraph( QWidget *parent, const char *name = 0 );
+ ~BarGraph();
+
+ bool addBar( const QString &footer );
+ bool removeBar( uint idx );
+
+ void updateSamples( const QMemArray<double> &newSamples );
+
+ double getMin() const
+ {
+ return minValue;
+ }
+
+ double getMax() const
+ {
+ return maxValue;
+ }
+
+ void getLimits( double &l, bool &la, double &u, bool &ua ) const
+ {
+ l = lowerLimit;
+ la = lowerLimitActive;
+ u = upperLimit;
+ ua = upperLimitActive;
+ }
+
+ void setLimits( double l, bool la, double u, bool ua )
+ {
+ lowerLimit = l;
+ lowerLimitActive = la;
+ upperLimit = u;
+ upperLimitActive = ua;
+ }
+
+ void changeRange( double min, double max );
+
+ protected:
+ virtual void paintEvent( QPaintEvent* );
+
+ private:
+ double minValue;
+ double maxValue;
+ double lowerLimit;
+ double lowerLimitActive;
+ double upperLimit;
+ bool upperLimitActive;
+ bool autoRange;
+ QMemArray<double> samples;
+ QStringList footers;
+ uint bars;
+ QColor normalColor;
+ QColor alarmColor;
+ QColor backgroundColor;
+ int fontSize;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/DancingBars.cc b/ksysguard/gui/SensorDisplayLib/DancingBars.cc
new file mode 100644
index 000000000..48c360713
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/DancingBars.cc
@@ -0,0 +1,353 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000, 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <qcheckbox.h>
+#include <qdom.h>
+#include <qlineedit.h>
+#include <qlistview.h>
+#include <qpushbutton.h>
+#include <qspinbox.h>
+#include <qtooltip.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <knumvalidator.h>
+#include <ksgrd/SensorManager.h>
+#include <ksgrd/StyleEngine.h>
+
+#include "BarGraph.h"
+#include "DancingBarsSettings.h"
+
+#include "DancingBars.h"
+
+DancingBars::DancingBars( QWidget *parent, const char *name, const QString &title,
+ int, int, bool noFrame_, bool isApplet )
+ : KSGRD::SensorDisplay( parent, name, title, noFrame_, isApplet )
+{
+ mBars = 0;
+ mFlags = QBitArray(100);
+ mFlags.fill( false );
+
+ if ( noFrame() )
+ mPlotter = new BarGraph( this );
+ else
+ mPlotter = new BarGraph( frame() );
+
+ setMinimumSize( sizeHint() );
+
+ /* All RMB clicks to the mPlotter widget will be handled by
+ * SensorDisplay::eventFilter. */
+ mPlotter->installEventFilter( this );
+
+ setPlotterWidget( mPlotter );
+
+ setModified( false );
+}
+
+DancingBars::~DancingBars()
+{
+}
+
+void DancingBars::configureSettings()
+{
+ mSettingsDialog = new DancingBarsSettings( this );
+
+ mSettingsDialog->setTitle( title() );
+ mSettingsDialog->setMinValue( mPlotter->getMin() );
+ mSettingsDialog->setMaxValue( mPlotter->getMax() );
+
+ double l, u;
+ bool la, ua;
+ mPlotter->getLimits( l, la, u, ua );
+
+ mSettingsDialog->setUseUpperLimit( ua );
+ mSettingsDialog->setUpperLimit( u );
+
+ mSettingsDialog->setUseLowerLimit( la );
+ mSettingsDialog->setLowerLimit( l );
+
+ mSettingsDialog->setForegroundColor( mPlotter->normalColor );
+ mSettingsDialog->setAlarmColor( mPlotter->alarmColor );
+ mSettingsDialog->setBackgroundColor( mPlotter->backgroundColor );
+ mSettingsDialog->setFontSize( mPlotter->fontSize );
+
+ QValueList< QStringList > list;
+ for ( uint i = mBars - 1; i < mBars; i-- ) {
+ QStringList entry;
+ entry << sensors().at( i )->hostName();
+ entry << KSGRD::SensorMgr->translateSensor( sensors().at( i )->name() );
+ entry << mPlotter->footers[ i ];
+ entry << KSGRD::SensorMgr->translateUnit( sensors().at( i )->unit() );
+ entry << ( sensors().at( i )->isOk() ? i18n( "OK" ) : i18n( "Error" ) );
+
+ list.append( entry );
+ }
+ mSettingsDialog->setSensors( list );
+
+ connect( mSettingsDialog, SIGNAL( applyClicked() ), SLOT( applySettings() ) );
+
+ if ( mSettingsDialog->exec() )
+ applySettings();
+
+ delete mSettingsDialog;
+ mSettingsDialog = 0;
+}
+
+void DancingBars::applySettings()
+{
+ setTitle( mSettingsDialog->title() );
+ mPlotter->changeRange( mSettingsDialog->minValue(), mSettingsDialog->maxValue() );
+ mPlotter->setLimits( mSettingsDialog->useLowerLimit() ?
+ mSettingsDialog->lowerLimit() : 0,
+ mSettingsDialog->useLowerLimit(),
+ mSettingsDialog->useUpperLimit() ?
+ mSettingsDialog->upperLimit() : 0,
+ mSettingsDialog->useUpperLimit() );
+
+ mPlotter->normalColor = mSettingsDialog->foregroundColor();
+ mPlotter->alarmColor = mSettingsDialog->alarmColor();
+ mPlotter->backgroundColor = mSettingsDialog->backgroundColor();
+ mPlotter->fontSize = mSettingsDialog->fontSize();
+
+ QValueList< QStringList > list = mSettingsDialog->sensors();
+ QValueList< QStringList >::Iterator it;
+
+ for ( uint i = 0; i < sensors().count(); i++ ) {
+ bool found = false;
+ for ( it = list.begin(); it != list.end(); ++it ) {
+ if ( (*it)[ 0 ] == sensors().at( i )->hostName() &&
+ (*it)[ 1 ] == KSGRD::SensorMgr->translateSensor( sensors().at( i )->name() ) ) {
+ mPlotter->footers[ i ] = (*it)[ 2 ];
+ found = true;
+ break;
+ }
+ }
+
+ if ( !found )
+ removeSensor( i );
+ }
+
+ repaint();
+ setModified( true );
+}
+
+void DancingBars::applyStyle()
+{
+ mPlotter->normalColor = KSGRD::Style->firstForegroundColor();
+ mPlotter->alarmColor = KSGRD::Style->alarmColor();
+ mPlotter->backgroundColor = KSGRD::Style->backgroundColor();
+ mPlotter->fontSize = KSGRD::Style->fontSize();
+
+ repaint();
+ setModified( true );
+}
+
+bool DancingBars::addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &title )
+{
+ if ( type != "integer" && type != "float" )
+ return false;
+
+ if ( mBars >= 32 )
+ return false;
+
+ if ( !mPlotter->addBar( title ) )
+ return false;
+
+ registerSensor( new KSGRD::SensorProperties( hostName, name, type, title ) );
+
+ /* To differentiate between answers from value requests and info
+ * requests we add 100 to the beam index for info requests. */
+ sendRequest( hostName, name + "?", mBars + 100 );
+ ++mBars;
+ mSampleBuffer.resize( mBars );
+
+ QString tooltip;
+ for ( uint i = 0; i < mBars; ++i ) {
+ tooltip += QString( "%1%2:%3" ).arg( i != 0 ? "\n" : "" )
+ .arg( sensors().at( i )->hostName() )
+ .arg( sensors().at( i )->name() );
+ }
+ QToolTip::remove( mPlotter );
+ QToolTip::add( mPlotter, tooltip );
+
+ return true;
+}
+
+bool DancingBars::removeSensor( uint pos )
+{
+ if ( pos >= mBars ) {
+ kdDebug(1215) << "DancingBars::removeSensor: idx out of range ("
+ << pos << ")" << endl;
+ return false;
+ }
+
+ mPlotter->removeBar( pos );
+ mBars--;
+ KSGRD::SensorDisplay::removeSensor( pos );
+
+ QString tooltip;
+ for ( uint i = 0; i < mBars; ++i ) {
+ tooltip += QString( "%1%2:%3" ).arg( i != 0 ? "\n" : "" )
+ .arg( sensors().at( i )->hostName() )
+ .arg( sensors().at( i )->name() );
+ }
+ QToolTip::remove( mPlotter );
+ QToolTip::add( mPlotter, tooltip );
+
+ return true;
+}
+
+void DancingBars::updateSamples( const QMemArray<double> &samples )
+{
+ mPlotter->updateSamples( samples );
+}
+
+void DancingBars::resizeEvent( QResizeEvent* )
+{
+ if ( noFrame() )
+ mPlotter->setGeometry( 0, 0, width(), height() );
+ else
+ frame()->setGeometry( 0, 0, width(), height() );
+}
+
+QSize DancingBars::sizeHint()
+{
+ if ( noFrame() )
+ return ( mPlotter->sizeHint() );
+ else
+ return ( frame()->sizeHint() );
+}
+
+void DancingBars::answerReceived( int id, const QString &answer )
+{
+ /* We received something, so the sensor is probably ok. */
+ sensorError( id, false );
+
+ if ( id < 100 ) {
+ mSampleBuffer[ id ] = answer.toDouble();
+ if ( mFlags.testBit( id ) == true ) {
+ kdDebug(1215) << "ERROR: DancingBars lost sample (" << mFlags
+ << ", " << mBars << ")" << endl;
+ sensorError( id, true );
+ }
+ mFlags.setBit( id, true );
+
+ bool allBitsAvailable = true;
+ for ( uint i = 0; i < mBars; ++i )
+ allBitsAvailable &= mFlags.testBit( i );
+
+ if ( allBitsAvailable ) {
+ mPlotter->updateSamples( mSampleBuffer );
+ mFlags.fill( false );
+ }
+ } else if ( id >= 100 ) {
+ KSGRD::SensorIntegerInfo info( answer );
+ if ( id == 100 )
+ if ( mPlotter->getMin() == 0.0 && mPlotter->getMax() == 0.0 ) {
+ /* We only use this information from the sensor when the
+ * display is still using the default values. If the
+ * sensor has been restored we don't touch the already set
+ * values. */
+ mPlotter->changeRange( info.min(), info.max() );
+ }
+
+ sensors().at( id - 100 )->setUnit( info.unit() );
+ }
+}
+
+bool DancingBars::restoreSettings( QDomElement &element )
+{
+ SensorDisplay::restoreSettings( element );
+
+ mPlotter->changeRange( element.attribute( "min", "0" ).toDouble(),
+ element.attribute( "max", "0" ).toDouble() );
+
+ mPlotter->setLimits( element.attribute( "lowlimit", "0" ).toDouble(),
+ element.attribute( "lowlimitactive", "0" ).toInt(),
+ element.attribute( "uplimit", "0" ).toDouble(),
+ element.attribute( "uplimitactive", "0" ).toInt() );
+
+ mPlotter->normalColor = restoreColor( element, "normalColor",
+ KSGRD::Style->firstForegroundColor() );
+ mPlotter->alarmColor = restoreColor( element, "alarmColor",
+ KSGRD::Style->alarmColor() );
+ mPlotter->backgroundColor = restoreColor( element, "backgroundColor",
+ KSGRD::Style->backgroundColor() );
+ mPlotter->fontSize = element.attribute( "fontSize", QString( "%1" ).arg(
+ KSGRD::Style->fontSize() ) ).toInt();
+
+ QDomNodeList dnList = element.elementsByTagName( "beam" );
+ for ( uint i = 0; i < dnList.count(); ++i ) {
+ QDomElement el = dnList.item( i ).toElement();
+ addSensor( el.attribute( "hostName" ), el.attribute( "sensorName" ),
+ ( el.attribute( "sensorType" ).isEmpty() ? "integer" :
+ el.attribute( "sensorType" ) ), el.attribute( "sensorDescr" ) );
+ }
+
+ setModified( false );
+
+ return true;
+}
+
+bool DancingBars::saveSettings( QDomDocument &doc, QDomElement &element,
+ bool save )
+{
+ element.setAttribute( "min", mPlotter->getMin() );
+ element.setAttribute( "max", mPlotter->getMax() );
+ double l, u;
+ bool la, ua;
+ mPlotter->getLimits( l, la, u, ua );
+ element.setAttribute( "lowlimit", l );
+ element.setAttribute( "lowlimitactive", la );
+ element.setAttribute( "uplimit", u );
+ element.setAttribute( "uplimitactive", ua );
+
+ saveColor( element, "normalColor", mPlotter->normalColor );
+ saveColor( element, "alarmColor", mPlotter->alarmColor );
+ saveColor( element, "backgroundColor", mPlotter->backgroundColor );
+ element.setAttribute( "fontSize", mPlotter->fontSize );
+
+ for ( uint i = 0; i < mBars; ++i ) {
+ QDomElement beam = doc.createElement( "beam" );
+ element.appendChild( beam );
+ beam.setAttribute( "hostName", sensors().at( i )->hostName() );
+ beam.setAttribute( "sensorName", sensors().at( i )->name() );
+ beam.setAttribute( "sensorType", sensors().at( i )->type() );
+ beam.setAttribute( "sensorDescr", mPlotter->footers[ i ] );
+ }
+
+ SensorDisplay::saveSettings( doc, element );
+
+ if ( save )
+ setModified( false );
+
+ return true;
+}
+
+bool DancingBars::hasSettingsDialog() const
+{
+ return true;
+}
+
+#include "DancingBars.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/DancingBars.h b/ksysguard/gui/SensorDisplayLib/DancingBars.h
new file mode 100644
index 000000000..ad671dfe7
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/DancingBars.h
@@ -0,0 +1,90 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_DANCINGBARS_H
+#define KSG_DANCINGBARS_H
+
+#include <SensorDisplay.h>
+#include <qbitarray.h>
+
+class KIntNumInput;
+
+class QGroupBox;
+class QLineEdit;
+class QListViewItem;
+
+class BarGraph;
+class DancingBarsSettings;
+
+class DancingBars : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+
+ public:
+ DancingBars( QWidget *parent = 0, const char *name = 0,
+ const QString &title = QString::null, int min = 0,
+ int max = 100, bool noFrame = false, bool isApplet = false );
+ virtual ~DancingBars();
+
+ void configureSettings();
+
+ bool addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &title );
+ bool removeSensor( uint pos );
+
+ void updateSamples( const QMemArray<double> &samples );
+
+ virtual QSize sizeHint();
+
+ virtual void answerReceived( int id, const QString &answer );
+
+ bool restoreSettings( QDomElement& );
+ bool saveSettings( QDomDocument&, QDomElement&, bool save = true );
+
+ virtual bool hasSettingsDialog() const;
+
+ public slots:
+ void applySettings();
+ virtual void applyStyle();
+
+ protected:
+ virtual void resizeEvent( QResizeEvent* );
+
+ private:
+ uint mBars;
+
+ BarGraph* mPlotter;
+
+ DancingBarsSettings* mSettingsDialog;
+
+ /**
+ The sample buffer and the flags are needed to store the incoming
+ samples for each beam until all samples of the period have been
+ received. The flags variable is used to ensure that all samples have
+ been received.
+ */
+ QMemArray<double> mSampleBuffer;
+ QBitArray mFlags;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/DancingBarsSettings.cc b/ksysguard/gui/SensorDisplayLib/DancingBarsSettings.cc
new file mode 100644
index 000000000..15e6b6ec3
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/DancingBarsSettings.cc
@@ -0,0 +1,398 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <kaccelmanager.h>
+#include <kcolorbutton.h>
+#include <klineedit.h>
+#include <kinputdialog.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+#include <qcheckbox.h>
+#include <qframe.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qwhatsthis.h>
+
+#include "DancingBarsSettings.h"
+
+DancingBarsSettings::DancingBarsSettings( QWidget* parent, const char* name )
+ : KDialogBase( Tabbed, i18n( "Edit BarGraph Preferences" ),
+ Ok | Apply | Cancel, Ok, parent, name, true, true )
+{
+ // Range page
+ QFrame *page = addPage( i18n( "Range" ) );
+ QGridLayout *pageLayout = new QGridLayout( page, 3, 1, 0, spacingHint() );
+
+ QGroupBox *groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Title" ), page );
+ QGridLayout *boxLayout = new QGridLayout( groupBox->layout(), 1, 1 );
+
+ mTitle = new KLineEdit( groupBox );
+ QWhatsThis::add( mTitle, i18n( "Enter the title of the display here." ) );
+ boxLayout->addWidget( mTitle, 0, 0 );
+
+ pageLayout->addWidget( groupBox, 0, 0 );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Display Range" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 1, 5 );
+ boxLayout->setColStretch( 2, 1 );
+
+ QLabel *label = new QLabel( i18n( "Minimum value:" ), groupBox );
+ boxLayout->addWidget( label, 0, 0 );
+
+ mMinValue = new KDoubleSpinBox( 0, 100, 0.5, 0, 2, groupBox );
+ QWhatsThis::add( mMinValue, i18n( "Enter the minimum value for the display here. If both values are 0, automatic range detection is enabled." ) );
+ boxLayout->addWidget( mMinValue, 0, 1 );
+ label->setBuddy( mMinValue );
+
+ label = new QLabel( i18n( "Maximum value:" ), groupBox );
+ boxLayout->addWidget( label, 0, 3 );
+
+ mMaxValue = new KDoubleSpinBox( 0, 10000, 0.5, 100, 2, groupBox );
+ QWhatsThis::add( mMaxValue, i18n( "Enter the maximum value for the display here. If both values are 0, automatic range detection is enabled." ) );
+ boxLayout->addWidget( mMaxValue, 0, 4 );
+ label->setBuddy( mMaxValue );
+
+ pageLayout->addWidget( groupBox, 1, 0 );
+
+ pageLayout->setRowStretch( 2, 1 );
+
+ // Alarm page
+ page = addPage( i18n( "Alarms" ) );
+ pageLayout = new QGridLayout( page, 3, 1, 0, spacingHint() );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Alarm for Minimum Value" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 1, 4 );
+ boxLayout->setColStretch( 1, 1 );
+
+ mUseLowerLimit = new QCheckBox( i18n( "Enable alarm" ), groupBox );
+ QWhatsThis::add( mUseLowerLimit, i18n( "Enable the minimum value alarm." ) );
+ boxLayout->addWidget( mUseLowerLimit, 0, 0 );
+
+ label = new QLabel( i18n( "Lower limit:" ), groupBox );
+ boxLayout->addWidget( label, 0, 2 );
+
+ mLowerLimit = new KDoubleSpinBox( 0, 100, 0.5, 0, 2, groupBox );
+ mLowerLimit->setEnabled( false );
+ boxLayout->addWidget( mLowerLimit, 0, 3 );
+ label->setBuddy( mLowerLimit );
+
+ pageLayout->addWidget( groupBox, 0, 0 );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Alarm for Maximum Value" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 1, 4 );
+ boxLayout->setColStretch( 1, 1 );
+
+ mUseUpperLimit = new QCheckBox( i18n( "Enable alarm" ), groupBox );
+ QWhatsThis::add( mUseUpperLimit, i18n( "Enable the maximum value alarm." ) );
+ boxLayout->addWidget( mUseUpperLimit, 0, 0 );
+
+ label = new QLabel( i18n( "Upper limit:" ), groupBox );
+ boxLayout->addWidget( label, 0, 2 );
+
+ mUpperLimit = new KDoubleSpinBox( 0, 100, 0.5, 0, 2, groupBox );
+ mUpperLimit->setEnabled( false );
+ boxLayout->addWidget( mUpperLimit, 0, 3 );
+ label->setBuddy( mUpperLimit );
+
+ pageLayout->addWidget( groupBox, 1, 0 );
+
+ pageLayout->setRowStretch( 2, 1 );
+
+ // Look page
+ page = addPage( i18n( "Look" ) );
+ pageLayout = new QGridLayout( page, 5, 2, 0, spacingHint() );
+
+ label = new QLabel( i18n( "Normal bar color:" ), page );
+ pageLayout->addWidget( label, 0, 0 );
+
+ mForegroundColor = new KColorButton( page );
+ pageLayout->addWidget( mForegroundColor, 0, 1 );
+ label->setBuddy( mForegroundColor );
+
+ label = new QLabel( i18n( "Out-of-range color:" ), page );
+ pageLayout->addWidget( label, 1, 0 );
+
+ mAlarmColor = new KColorButton( page );
+ pageLayout->addWidget( mAlarmColor, 1, 1 );
+ label->setBuddy( mAlarmColor );
+
+ label = new QLabel( i18n( "Background color:" ), page );
+ pageLayout->addWidget( label, 2, 0 );
+
+ mBackgroundColor = new KColorButton( page );
+ pageLayout->addWidget( mBackgroundColor, 2, 1 );
+ label->setBuddy( mBackgroundColor );
+
+ label = new QLabel( i18n( "Font size:" ), page );
+ pageLayout->addWidget( label, 3, 0 );
+
+ mFontSize = new KIntNumInput( 9, page );
+ QWhatsThis::add( mFontSize, i18n( "This determines the size of the font used to print a label underneath the bars. Bars are automatically suppressed if text becomes too large, so it is advisable to use a small font size here." ) );
+ pageLayout->addWidget( mFontSize, 3, 1 );
+ label->setBuddy( mFontSize );
+
+ pageLayout->setRowStretch( 4, 1 );
+
+ // Sensor page
+ page = addPage( i18n( "Sensors" ) );
+ pageLayout = new QGridLayout( page, 3, 2, 0, spacingHint() );
+ pageLayout->setRowStretch( 2, 1 );
+
+ mSensorView = new KListView( page );
+ mSensorView->addColumn( i18n( "Host" ) );
+ mSensorView->addColumn( i18n( "Sensor" ) );
+ mSensorView->addColumn( i18n( "Label" ) );
+ mSensorView->addColumn( i18n( "Unit" ) );
+ mSensorView->addColumn( i18n( "Status" ) );
+ mSensorView->setAllColumnsShowFocus( true );
+ pageLayout->addMultiCellWidget( mSensorView, 0, 2, 0, 0 );
+
+ mEditButton = new QPushButton( i18n( "Edit..." ), page );
+ mEditButton->setEnabled( false );
+ QWhatsThis::add( mEditButton, i18n( "Push this button to configure the label." ) );
+ pageLayout->addWidget( mEditButton, 0, 1 );
+
+ mRemoveButton = new QPushButton( i18n( "Delete" ), page );
+ mRemoveButton->setEnabled( false );
+ QWhatsThis::add( mRemoveButton, i18n( "Push this button to delete the sensor." ) );
+ pageLayout->addWidget( mRemoveButton, 1, 1 );
+
+ connect( mUseLowerLimit, SIGNAL( toggled( bool ) ),
+ mLowerLimit, SLOT( setEnabled( bool ) ) );
+ connect( mUseUpperLimit, SIGNAL( toggled( bool ) ),
+ mUpperLimit, SLOT( setEnabled( bool ) ) );
+
+ connect( mSensorView, SIGNAL( selectionChanged( QListViewItem* ) ),
+ SLOT( selectionChanged( QListViewItem* ) ) );
+ connect( mEditButton, SIGNAL( clicked() ), SLOT( editSensor() ) );
+ connect( mRemoveButton, SIGNAL( clicked() ), SLOT( removeSensor() ) );
+
+ KAcceleratorManager::manage( this );
+
+ mTitle->setFocus();
+}
+
+DancingBarsSettings::~DancingBarsSettings()
+{
+}
+
+void DancingBarsSettings::setTitle( const QString& title )
+{
+ mTitle->setText( title );
+}
+
+QString DancingBarsSettings::title() const
+{
+ return mTitle->text();
+}
+
+void DancingBarsSettings::setMinValue( double min )
+{
+ mMinValue->setValue( min );
+}
+
+double DancingBarsSettings::minValue() const
+{
+ return mMinValue->value();
+}
+
+void DancingBarsSettings::setMaxValue( double max )
+{
+ mMaxValue->setValue( max );
+}
+
+double DancingBarsSettings::maxValue() const
+{
+ return mMaxValue->value();
+}
+
+void DancingBarsSettings::setUseLowerLimit( bool value )
+{
+ mUseLowerLimit->setChecked( value );
+}
+
+bool DancingBarsSettings::useLowerLimit() const
+{
+ return mUseLowerLimit->isChecked();
+}
+
+void DancingBarsSettings::setLowerLimit( double limit )
+{
+ mLowerLimit->setValue( limit );
+}
+
+double DancingBarsSettings::lowerLimit() const
+{
+ return mLowerLimit->value();
+}
+
+void DancingBarsSettings::setUseUpperLimit( bool value )
+{
+ mUseUpperLimit->setChecked( value );
+}
+
+bool DancingBarsSettings::useUpperLimit() const
+{
+ return mUseUpperLimit->isChecked();
+}
+
+void DancingBarsSettings::setUpperLimit( double limit )
+{
+ mUpperLimit->setValue( limit );
+}
+
+double DancingBarsSettings::upperLimit() const
+{
+ return mUpperLimit->value();
+}
+
+void DancingBarsSettings::setForegroundColor( const QColor &color )
+{
+ mForegroundColor->setColor( color );
+}
+
+QColor DancingBarsSettings::foregroundColor() const
+{
+ return mForegroundColor->color();
+}
+
+void DancingBarsSettings::setAlarmColor( const QColor &color )
+{
+ mAlarmColor->setColor( color );
+}
+
+QColor DancingBarsSettings::alarmColor() const
+{
+ return mAlarmColor->color();
+}
+
+void DancingBarsSettings::setBackgroundColor( const QColor &color )
+{
+ mBackgroundColor->setColor( color );
+}
+
+QColor DancingBarsSettings::backgroundColor() const
+{
+ return mBackgroundColor->color();
+}
+
+void DancingBarsSettings::setFontSize( int size )
+{
+ mFontSize->setValue( size );
+}
+
+int DancingBarsSettings::fontSize() const
+{
+ return mFontSize->value();
+}
+
+void DancingBarsSettings::setSensors( const QValueList< QStringList > &list )
+{
+ mSensorView->clear();
+
+ QValueList< QStringList >::ConstIterator it;
+ for ( it = list.begin(); it != list.end(); ++it ) {
+ new QListViewItem( mSensorView,
+ (*it)[ 0 ], // host name
+ (*it)[ 1 ], // sensor name
+ (*it)[ 2 ], // footer title
+ (*it)[ 3 ], // unit
+ (*it)[ 4 ] ); // status
+ }
+}
+
+QValueList< QStringList > DancingBarsSettings::sensors() const
+{
+ QValueList< QStringList > list;
+
+ QListViewItemIterator it( mSensorView );
+ while ( it.current() && !it.current()->text( 0 ).isEmpty() ) {
+ QStringList entry;
+ entry << it.current()->text( 0 );
+ entry << it.current()->text( 1 );
+ entry << it.current()->text( 2 );
+ entry << it.current()->text( 3 );
+ entry << it.current()->text( 4 );
+
+ list.append( entry );
+ ++it;
+ }
+
+ return list;
+}
+
+void DancingBarsSettings::editSensor()
+{
+ QListViewItem *lvi = mSensorView->currentItem();
+
+ if ( !lvi )
+ return;
+
+ bool ok;
+ QString str = KInputDialog::getText( i18n( "Label of Bar Graph" ),
+ i18n( "Enter new label:" ), lvi->text( 2 ), &ok, this );
+ if ( ok )
+ lvi->setText( 2, str );
+}
+
+void DancingBarsSettings::removeSensor()
+{
+ QListViewItem *lvi = mSensorView->currentItem();
+
+ if ( lvi ) {
+ /* Before we delete the currently selected item, we determine a
+ * new item to be selected. That way we can ensure that multiple
+ * items can be deleted without forcing the user to select a new
+ * item between the deletes. If all items are deleted, the buttons
+ * are disabled again. */
+ QListViewItem* newSelected = 0;
+ if ( lvi->itemBelow() ) {
+ lvi->itemBelow()->setSelected( true );
+ newSelected = lvi->itemBelow();
+ } else if ( lvi->itemAbove() ) {
+ lvi->itemAbove()->setSelected( true );
+ newSelected = lvi->itemAbove();
+ } else
+ selectionChanged( 0 );
+
+ delete lvi;
+
+ if ( newSelected )
+ mSensorView->ensureItemVisible( newSelected );
+ }
+}
+
+void DancingBarsSettings::selectionChanged( QListViewItem* lvi )
+{
+ bool state = ( lvi != 0 );
+
+ mEditButton->setEnabled( state );
+ mRemoveButton->setEnabled( state );
+}
+
+
+#include "DancingBarsSettings.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/DancingBarsSettings.h b/ksysguard/gui/SensorDisplayLib/DancingBarsSettings.h
new file mode 100644
index 000000000..12e559dc0
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/DancingBarsSettings.h
@@ -0,0 +1,106 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_DANCINGBARSSETTINGS_H
+#define KSG_DANCINGBARSSETTINGS_H
+
+#include <kdialogbase.h>
+
+class KColorButton;
+class KDoubleSpinBox;
+class KIntNumInput;
+class KLineEdit;
+class KListView;
+
+class QCheckBox;
+class QListViewItem;
+class QPushButton;
+
+class DancingBarsSettings : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ DancingBarsSettings( QWidget* parent = 0, const char* name = 0 );
+ ~DancingBarsSettings();
+
+ void setTitle( const QString& title );
+ QString title() const;
+
+ void setMinValue( double min );
+ double minValue() const;
+
+ void setMaxValue( double max );
+ double maxValue() const;
+
+ void setUseLowerLimit( bool value );
+ bool useLowerLimit() const;
+
+ void setLowerLimit( double limit );
+ double lowerLimit() const;
+
+ void setUseUpperLimit( bool value );
+ bool useUpperLimit() const;
+
+ void setUpperLimit( double limit );
+ double upperLimit() const;
+
+ void setForegroundColor( const QColor &color );
+ QColor foregroundColor() const;
+
+ void setAlarmColor( const QColor &color );
+ QColor alarmColor() const;
+
+ void setBackgroundColor( const QColor &color );
+ QColor backgroundColor() const;
+
+ void setFontSize( int size );
+ int fontSize() const;
+
+ void setSensors( const QValueList< QStringList > &list );
+ QValueList< QStringList > sensors() const;
+
+ private slots:
+ void editSensor();
+ void removeSensor();
+ void selectionChanged( QListViewItem* );
+
+ private:
+ KColorButton *mForegroundColor;
+ KColorButton *mAlarmColor;
+ KColorButton *mBackgroundColor;
+ KDoubleSpinBox *mMinValue;
+ KDoubleSpinBox *mMaxValue;
+ KDoubleSpinBox *mLowerLimit;
+ KDoubleSpinBox *mUpperLimit;
+ KLineEdit *mTitle;
+ KListView *mSensorView;
+ KIntNumInput *mFontSize;
+
+ QCheckBox *mUseLowerLimit;
+ QCheckBox *mUseUpperLimit;
+ QPushButton *mEditButton;
+ QPushButton *mRemoveButton;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/DummyDisplay.cc b/ksysguard/gui/SensorDisplayLib/DummyDisplay.cc
new file mode 100644
index 000000000..a4ea6afb4
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/DummyDisplay.cc
@@ -0,0 +1,58 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000, 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <klocale.h>
+#include <ksgrd/SensorManager.h>
+
+#include <qwhatsthis.h>
+
+#include "DummyDisplay.h"
+
+DummyDisplay::DummyDisplay( QWidget* parent, const char* name,
+ const QString&, double, double )
+ : KSGRD::SensorDisplay( parent, name, i18n( "Drop Sensor Here" ) )
+{
+ setMinimumSize( 16, 16 );
+
+ QWhatsThis::add( this, i18n(
+ "This is an empty space in a worksheet. Drag a sensor from "
+ "the Sensor Browser and drop it here. A sensor display will "
+ "appear that allows you to monitor the values of the sensor "
+ "over time." ) );
+}
+
+void DummyDisplay::resizeEvent( QResizeEvent* )
+{
+ frame()->setGeometry( 0, 0, width(), height() );
+}
+
+bool DummyDisplay::eventFilter( QObject* object, QEvent* event )
+{
+ if ( event->type() == QEvent::MouseButtonRelease &&
+ ( (QMouseEvent*)event)->button() == LeftButton )
+ setFocus();
+
+ return QWidget::eventFilter( object, event );
+}
+
+#include "DummyDisplay.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/DummyDisplay.h b/ksysguard/gui/SensorDisplayLib/DummyDisplay.h
new file mode 100644
index 000000000..53098fa0c
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/DummyDisplay.h
@@ -0,0 +1,44 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_DUMMYDISPLAY_H
+#define KSG_DUMMYDISPLAY_H
+
+#include <SensorDisplay.h>
+
+class DummyDisplay : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+
+ public:
+ DummyDisplay( QWidget* parent = 0, const char* name = 0,
+ const QString& = QString::null, double min = 0,
+ double max = 0 );
+ virtual ~DummyDisplay() {}
+
+ void resizeEvent( QResizeEvent* );
+
+ virtual bool eventFilter( QObject*, QEvent* );
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/FancyPlotter.cc b/ksysguard/gui/SensorDisplayLib/FancyPlotter.cc
new file mode 100644
index 000000000..361ce16e7
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/FancyPlotter.cc
@@ -0,0 +1,457 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2002 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <qdom.h>
+#include <qimage.h>
+#include <qtooltip.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include <ksgrd/SensorManager.h>
+#include <ksgrd/StyleEngine.h>
+#include "SensorDisplay.h"
+#include "FancyPlotterSettings.h"
+
+#include "FancyPlotter.h"
+
+FancyPlotter::FancyPlotter( QWidget* parent, const char* name,
+ const QString &title, double, double,
+ bool nf, bool isApplet)
+ : KSGRD::SensorDisplay( parent, name, title, nf, isApplet )
+{
+ mBeams = 0;
+ mSettingsDialog = 0;
+
+ if ( noFrame() ) {
+ mPlotter = new SignalPlotter( this );
+ mPlotter->setShowTopBar( true );
+ } else
+ mPlotter = new SignalPlotter( frame() );
+ mPlotter->setTitle( title );
+ mPlotter->setThinFrame(!isApplet); //if we aren't an applet, draw a thin white frame on the left and bottom, for a 3d effect
+
+ setMinimumSize( sizeHint() );
+
+ /* All RMB clicks to the mPlotter widget will be handled by
+ * SensorDisplay::eventFilter. */
+ mPlotter->installEventFilter( this );
+
+ setPlotterWidget( mPlotter );
+
+ setModified( false );
+}
+
+FancyPlotter::~FancyPlotter()
+{
+}
+
+void FancyPlotter::configureSettings()
+{
+ if(mSettingsDialog) {
+ return;
+ }
+ mSettingsDialog = new FancyPlotterSettings( this );
+
+ mSettingsDialog->setTitle( title() );
+ mSettingsDialog->setUseAutoRange( mPlotter->useAutoRange() );
+ mSettingsDialog->setMinValue( mPlotter->minValue() );
+ mSettingsDialog->setMaxValue( mPlotter->maxValue() );
+
+ mSettingsDialog->setUsePolygonStyle( mPlotter->graphStyle() == GRAPH_POLYGON );
+ mSettingsDialog->setHorizontalScale( mPlotter->horizontalScale() );
+
+ mSettingsDialog->setShowVerticalLines( mPlotter->showVerticalLines() );
+ mSettingsDialog->setVerticalLinesColor( mPlotter->verticalLinesColor() );
+ mSettingsDialog->setVerticalLinesDistance( mPlotter->verticalLinesDistance() );
+ mSettingsDialog->setVerticalLinesScroll( mPlotter->verticalLinesScroll() );
+
+ mSettingsDialog->setShowHorizontalLines( mPlotter->showHorizontalLines() );
+ mSettingsDialog->setHorizontalLinesColor( mPlotter->horizontalLinesColor() );
+ mSettingsDialog->setHorizontalLinesCount( mPlotter->horizontalLinesCount() );
+
+ mSettingsDialog->setShowLabels( mPlotter->showLabels() );
+ mSettingsDialog->setShowTopBar( mPlotter->showTopBar() );
+ mSettingsDialog->setFontSize( mPlotter->fontSize() );
+
+ mSettingsDialog->setBackgroundColor( mPlotter->backgroundColor() );
+
+ QValueList< QStringList > list;
+ for ( uint i = 0; i < mBeams; ++i ) {
+ QStringList entry;
+ entry << QString::number(i);
+ entry << sensors().at( i )->hostName();
+ entry << KSGRD::SensorMgr->translateSensor( sensors().at( i )->name() );
+ entry << KSGRD::SensorMgr->translateUnit( sensors().at( i )->unit() );
+ entry << ( sensors().at( i )->isOk() ? i18n( "OK" ) : i18n( "Error" ) );
+ entry << ( mPlotter->beamColors()[ i ].name() );
+
+ list.append( entry );
+ }
+ mSettingsDialog->setSensors( list );
+
+ connect( mSettingsDialog, SIGNAL( applyClicked() ), SLOT( applySettings() ) );
+ connect( mSettingsDialog, SIGNAL( okClicked() ), SLOT( applySettings() ) );
+ connect( mSettingsDialog, SIGNAL( finished() ), SLOT( killDialog() ) );
+
+ mSettingsDialog->show();
+}
+
+void FancyPlotter::killDialog() {
+ mSettingsDialog->delayedDestruct();
+ mSettingsDialog = 0;
+}
+
+void FancyPlotter::applySettings()
+{
+ setTitle( mSettingsDialog->title() );
+ mPlotter->setTitle( title() );
+
+ if ( mSettingsDialog->useAutoRange() )
+ mPlotter->setUseAutoRange( true );
+ else {
+ mPlotter->setUseAutoRange( false );
+ mPlotter->changeRange( 0, mSettingsDialog->minValue(),
+ mSettingsDialog->maxValue() );
+ }
+
+ if ( mSettingsDialog->usePolygonStyle() )
+ mPlotter->setGraphStyle( GRAPH_POLYGON );
+ else
+ mPlotter->setGraphStyle( GRAPH_ORIGINAL );
+
+ if ( mPlotter->horizontalScale() != mSettingsDialog->horizontalScale() ) {
+ mPlotter->setHorizontalScale( mSettingsDialog->horizontalScale() );
+ // Can someone think of a useful QResizeEvent to pass?
+ // It doesn't really matter anyway because it's not used.
+ emit resizeEvent( 0 );
+ }
+
+ mPlotter->setShowVerticalLines( mSettingsDialog->showVerticalLines() );
+ mPlotter->setVerticalLinesColor( mSettingsDialog->verticalLinesColor() );
+ mPlotter->setVerticalLinesDistance( mSettingsDialog->verticalLinesDistance() );
+ mPlotter->setVerticalLinesScroll( mSettingsDialog->verticalLinesScroll() );
+
+ mPlotter->setShowHorizontalLines( mSettingsDialog->showHorizontalLines() );
+ mPlotter->setHorizontalLinesColor( mSettingsDialog->horizontalLinesColor() );
+ mPlotter->setHorizontalLinesCount( mSettingsDialog->horizontalLinesCount() );
+
+ mPlotter->setShowLabels( mSettingsDialog->showLabels() );
+ mPlotter->setShowTopBar( mSettingsDialog->showTopBar() );
+ mPlotter->setFontSize( mSettingsDialog->fontSize() );
+
+ mPlotter->setBackgroundColor( mSettingsDialog->backgroundColor() );
+
+
+ QValueList<int> orderOfSensors = mSettingsDialog->order();
+ QValueList<int> deletedSensors = mSettingsDialog->deleted();
+ mSettingsDialog->clearDeleted();
+ mSettingsDialog->resetOrder();
+ QValueList< int >::Iterator itDelete;
+ for ( itDelete = deletedSensors.begin(); itDelete != deletedSensors.end(); ++itDelete )
+ removeSensor(*itDelete);
+
+ QValueList< int >::Iterator itOrder;
+ mPlotter->reorderBeams(orderOfSensors);
+ reorderSensors(orderOfSensors);
+
+ QValueList< QStringList > list = mSettingsDialog->sensors();
+ QValueList< QStringList >::Iterator it;
+
+ for ( uint i = 0; i < sensors().count(); ++i )
+ mPlotter->beamColors()[ i ] = QColor( list[i][ 5 ] );
+
+ mPlotter->repaint();
+ setModified( true );
+}
+
+void FancyPlotter::applyStyle()
+{
+ mPlotter->setVerticalLinesColor( KSGRD::Style->firstForegroundColor() );
+ mPlotter->setHorizontalLinesColor( KSGRD::Style->secondForegroundColor() );
+ mPlotter->setBackgroundColor( KSGRD::Style->backgroundColor() );
+ mPlotter->setFontSize( KSGRD::Style->fontSize() );
+ for ( uint i = 0; i < mPlotter->beamColors().count() &&
+ i < KSGRD::Style->numSensorColors(); ++i )
+ mPlotter->beamColors()[ i ] = KSGRD::Style->sensorColor( i );
+
+ mPlotter->update();
+ setModified( true );
+}
+
+bool FancyPlotter::addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &title )
+{
+ return addSensor( hostName, name, type, title,
+ KSGRD::Style->sensorColor( mBeams ) );
+}
+
+bool FancyPlotter::addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &title,
+ const QColor &color )
+{
+ if ( type != "integer" && type != "float" )
+ return false;
+
+ if ( mBeams > 0 && hostName != sensors().at( 0 )->hostName() ) {
+ KMessageBox::sorry( this, QString( "All sensors of this display need "
+ "to be from the host %1!" )
+ .arg( sensors().at( 0 )->hostName() ) );
+
+ /* We have to enforce this since the answers to value requests
+ * need to be received in order. */
+ return false;
+ }
+
+ if ( !mPlotter->addBeam( color ) )
+ return false;
+
+ registerSensor( new FPSensorProperties( hostName, name, type, title, color ) );
+
+ /* To differentiate between answers from value requests and info
+ * requests we add 100 to the beam index for info requests. */
+ sendRequest( hostName, name + "?", mBeams + 100 );
+
+ ++mBeams;
+
+ QString tooltip;
+ for ( uint i = 0; i < mBeams; ++i ) {
+ tooltip += QString( "%1%2:%3" ).arg( i != 0 ? "\n" : "" )
+ .arg( sensors().at( mBeams - i - 1 )->hostName() )
+ .arg( sensors().at( mBeams - i - 1 )->name() );
+ }
+
+ QToolTip::remove( mPlotter );
+ QToolTip::add( mPlotter, tooltip );
+
+ return true;
+}
+
+bool FancyPlotter::removeSensor( uint pos )
+{
+ if ( pos >= mBeams ) {
+ kdDebug(1215) << "FancyPlotter::removeSensor: idx out of range ("
+ << pos << ")" << endl;
+ return false;
+ }
+
+ mPlotter->removeBeam( pos );
+ mBeams--;
+ KSGRD::SensorDisplay::removeSensor( pos );
+
+ QString tooltip;
+ for ( uint i = 0; i < mBeams; ++i ) {
+ tooltip += QString( "%1%2:%3" ).arg( i != 0 ? "\n" : "" )
+ .arg( sensors().at( mBeams - i - 1 )->hostName() )
+ .arg( sensors().at( mBeams - i - 1 )->name() );
+ }
+
+ QToolTip::remove( mPlotter );
+ QToolTip::add( mPlotter, tooltip );
+
+ return true;
+}
+
+void FancyPlotter::resizeEvent( QResizeEvent* )
+{
+ if ( noFrame() )
+ mPlotter->setGeometry( 0, 0, width(), height() );
+ else
+ frame()->setGeometry( 0, 0, width(), height() );
+}
+
+QSize FancyPlotter::sizeHint()
+{
+ if ( noFrame() )
+ return mPlotter->sizeHint();
+ else
+ return frame()->sizeHint();
+}
+
+void FancyPlotter::answerReceived( int id, const QString &answer )
+{
+ if ( (uint)id < mBeams ) {
+ if ( id != (int)mSampleBuf.count() ) {
+ if ( id == 0 )
+ sensorError( mBeams - 1, true );
+ else
+ sensorError( id - 1, true );
+ }
+ mSampleBuf.append( answer.toDouble() );
+
+ /* We received something, so the sensor is probably ok. */
+ sensorError( id, false );
+
+ if ( id == (int)mBeams - 1 ) {
+ mPlotter->addSample( mSampleBuf );
+ mSampleBuf.clear();
+ }
+ } else if ( id >= 100 ) {
+ KSGRD::SensorFloatInfo info( answer );
+ if ( !mPlotter->useAutoRange() && mPlotter->minValue() == 0.0 &&
+ mPlotter->maxValue() == 0.0 ) {
+ /* We only use this information from the sensor when the
+ * display is still using the default values. If the
+ * sensor has been restored we don't touch the already set
+ * values. */
+ mPlotter->changeRange( id - 100, info.min(), info.max() );
+ if ( info.min() == 0.0 && info.max() == 0.0 )
+ mPlotter->setUseAutoRange( true );
+ }
+ sensors().at( id - 100 )->setUnit( info.unit() );
+ }
+}
+
+bool FancyPlotter::restoreSettings( QDomElement &element )
+{
+ /* autoRage was added after KDE 2.x and was brokenly emulated by
+ * min == 0.0 and max == 0.0. Since we have to be able to read old
+ * files as well we have to emulate the old behaviour as well. */
+ double min = element.attribute( "min", "0.0" ).toDouble();
+ double max = element.attribute( "max", "0.0" ).toDouble();
+ if ( element.attribute( "autoRange", min == 0.0 && max == 0.0 ? "1" : "0" ).toInt() )
+ mPlotter->setUseAutoRange( true );
+ else {
+ mPlotter->setUseAutoRange( false );
+ mPlotter->changeRange( 0, element.attribute( "min" ).toDouble(),
+ element.attribute( "max" ).toDouble() );
+ }
+
+ mPlotter->setShowVerticalLines( element.attribute( "vLines", "1" ).toUInt() );
+ mPlotter->setVerticalLinesColor( restoreColor( element, "vColor",
+ KSGRD::Style->firstForegroundColor() ) );
+ mPlotter->setVerticalLinesDistance( element.attribute( "vDistance", "30" ).toUInt() );
+ mPlotter->setVerticalLinesScroll( element.attribute( "vScroll", "1" ).toUInt() );
+ mPlotter->setGraphStyle( element.attribute( "graphStyle", "0" ).toUInt() );
+ mPlotter->setHorizontalScale( element.attribute( "hScale", "1" ).toUInt() );
+
+ mPlotter->setShowHorizontalLines( element.attribute( "hLines", "1" ).toUInt() );
+ mPlotter->setHorizontalLinesColor( restoreColor( element, "hColor",
+ KSGRD::Style->secondForegroundColor() ) );
+ mPlotter->setHorizontalLinesCount( element.attribute( "hCount", "5" ).toUInt() );
+
+ mPlotter->setShowLabels( element.attribute( "labels", "1" ).toUInt() );
+ mPlotter->setShowTopBar( element.attribute( "topBar", "0" ).toUInt() );
+ mPlotter->setFontSize( element.attribute( "fontSize",
+ QString( "%1" ).arg( KSGRD::Style->fontSize() ) ).toUInt() );
+
+ mPlotter->setBackgroundColor( restoreColor( element, "bColor",
+ KSGRD::Style->backgroundColor() ) );
+
+ QDomNodeList dnList = element.elementsByTagName( "beam" );
+ for ( uint i = 0; i < dnList.count(); ++i ) {
+ QDomElement el = dnList.item( i ).toElement();
+ addSensor( el.attribute( "hostName" ), el.attribute( "sensorName" ),
+ ( el.attribute( "sensorType" ).isEmpty() ? "integer" :
+ el.attribute( "sensorType" ) ), "", restoreColor( el, "color",
+ KSGRD::Style->sensorColor( i ) ) );
+ }
+
+ SensorDisplay::restoreSettings( element );
+
+ if ( !title().isEmpty() )
+ mPlotter->setTitle( title() );
+
+ setModified( false );
+
+ return true;
+}
+
+bool FancyPlotter::saveSettings( QDomDocument &doc, QDomElement &element,
+ bool save )
+{
+ element.setAttribute( "min", mPlotter->minValue() );
+ element.setAttribute( "max", mPlotter->maxValue() );
+ element.setAttribute( "autoRange", mPlotter->useAutoRange() );
+ element.setAttribute( "vLines", mPlotter->showVerticalLines() );
+ saveColor( element, "vColor", mPlotter->verticalLinesColor() );
+ element.setAttribute( "vDistance", mPlotter->verticalLinesDistance() );
+ element.setAttribute( "vScroll", mPlotter->verticalLinesScroll() );
+
+ element.setAttribute( "graphStyle", mPlotter->graphStyle() );
+ element.setAttribute( "hScale", mPlotter->horizontalScale() );
+
+ element.setAttribute( "hLines", mPlotter->showHorizontalLines() );
+ saveColor( element, "hColor", mPlotter->horizontalLinesColor() );
+ element.setAttribute( "hCount", mPlotter->horizontalLinesCount() );
+
+ element.setAttribute( "labels", mPlotter->showLabels() );
+ element.setAttribute( "topBar", mPlotter->showTopBar() );
+ element.setAttribute( "fontSize", mPlotter->fontSize() );
+
+ saveColor( element, "bColor", mPlotter->backgroundColor() );
+
+ for ( uint i = 0; i < mBeams; ++i ) {
+ QDomElement beam = doc.createElement( "beam" );
+ element.appendChild( beam );
+ beam.setAttribute( "hostName", sensors().at( i )->hostName() );
+ beam.setAttribute( "sensorName", sensors().at( i )->name() );
+ beam.setAttribute( "sensorType", sensors().at( i )->type() );
+ saveColor( beam, "color", mPlotter->beamColors()[ i ] );
+ }
+
+ SensorDisplay::saveSettings( doc, element );
+
+ if ( save )
+ setModified( false );
+
+ return true;
+}
+
+bool FancyPlotter::hasSettingsDialog() const
+{
+ return true;
+}
+
+
+
+FPSensorProperties::FPSensorProperties()
+{
+}
+
+FPSensorProperties::FPSensorProperties( const QString &hostName,
+ const QString &name,
+ const QString &type,
+ const QString &description,
+ const QColor &color )
+ : KSGRD::SensorProperties( hostName, name, type, description ),
+ mColor( color )
+{
+}
+
+FPSensorProperties::~FPSensorProperties()
+{
+}
+
+void FPSensorProperties::setColor( const QColor &color )
+{
+ mColor = color;
+}
+
+QColor FPSensorProperties::color() const
+{
+ return mColor;
+}
+
+#include "FancyPlotter.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/FancyPlotter.h b/ksysguard/gui/SensorDisplayLib/FancyPlotter.h
new file mode 100644
index 000000000..d19c28760
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/FancyPlotter.h
@@ -0,0 +1,103 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_FANCYPLOTTER_H
+#define KSG_FANCYPLOTTER_H
+
+#include <kdialogbase.h>
+
+#include <SensorDisplay.h>
+
+#include "SignalPlotter.h"
+
+class QListViewItem;
+class FancyPlotterSettings;
+
+class FPSensorProperties : public KSGRD::SensorProperties
+{
+ public:
+ FPSensorProperties();
+ FPSensorProperties( const QString &hostName, const QString &name,
+ const QString &type, const QString &description,
+ const QColor &color );
+ ~FPSensorProperties();
+
+ void setColor( const QColor &color );
+ QColor color() const;
+
+ private:
+ QColor mColor;
+};
+
+class FancyPlotter : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+
+ public:
+ FancyPlotter( QWidget* parent = 0, const char* name = 0,
+ const QString& title = QString::null, double min = 0,
+ double max = 100, bool noFrame = false, bool isApplet = false );
+ virtual ~FancyPlotter();
+
+ void configureSettings();
+
+ bool addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &title );
+ bool addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &title,
+ const QColor &color );
+
+ bool removeSensor( uint pos );
+
+ virtual QSize sizeHint(void);
+
+ virtual void answerReceived( int id, const QString &answer );
+
+ virtual bool restoreSettings( QDomElement &element );
+ virtual bool saveSettings( QDomDocument &doc, QDomElement &element,
+ bool save = true );
+
+ virtual bool hasSettingsDialog() const;
+
+ public slots:
+ void applySettings();
+ virtual void applyStyle();
+ void killDialog();
+
+ protected:
+ virtual void resizeEvent( QResizeEvent* );
+
+ private:
+ uint mBeams;
+
+ SignalPlotter* mPlotter;
+
+ FancyPlotterSettings* mSettingsDialog;
+
+ /**
+ The sample buffer and the flags are needed to store the incoming
+ samples for each beam until all samples of the period have been
+ received. The flags variable is used to ensure that all samples have
+ been received.
+ */
+ QValueList<double> mSampleBuf;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.cc b/ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.cc
new file mode 100644
index 000000000..9d4114bd3
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.cc
@@ -0,0 +1,637 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <kaccelmanager.h>
+#include <kcolorbutton.h>
+#include <kcolordialog.h>
+#include <klineedit.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+#include <qcheckbox.h>
+#include <qbuttongroup.h>
+#include <qgroupbox.h>
+#include <qimage.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpixmap.h>
+#include <qpushbutton.h>
+#include <qradiobutton.h>
+#include <qwhatsthis.h>
+#include <qheader.h>
+
+#include "FancyPlotterSettings.h"
+
+FancyPlotterSettings::FancyPlotterSettings( QWidget* parent, const char* name )
+ : KDialogBase( Tabbed, i18n( "Signal Plotter Settings" ), Ok | Apply | Cancel,
+ Ok, parent, name, false, true )
+{
+ QFrame *page = 0;
+ QGridLayout *pageLayout = 0;
+ QGridLayout *boxLayout = 0;
+ QGroupBox *groupBox = 0;
+ QLabel *label = 0;
+
+ // Style page
+ page = addPage( i18n( "Style" ) );
+ pageLayout = new QGridLayout( page, 3, 2, 0, spacingHint() );
+
+ label = new QLabel( i18n( "Title:" ), page );
+ pageLayout->addWidget( label, 0, 0 );
+
+ mTitle = new KLineEdit( page );
+ QWhatsThis::add( mTitle, i18n( "Enter the title of the display here." ) );
+ pageLayout->addWidget( mTitle, 0, 1 );
+ label->setBuddy( mTitle );
+
+ QButtonGroup *buttonBox = new QButtonGroup( 2, Qt::Vertical,
+ i18n( "Graph Drawing Style" ), page );
+
+ mUsePolygonStyle = new QRadioButton( i18n( "Basic polygons" ), buttonBox );
+ mUsePolygonStyle->setChecked( true );
+ mUseOriginalStyle = new QRadioButton( i18n( "Original - single line per data point" ), buttonBox );
+
+ pageLayout->addMultiCellWidget( buttonBox, 1, 1, 0, 1 );
+
+ // Scales page
+ page = addPage( i18n( "Scales" ) );
+ pageLayout = new QGridLayout( page, 2, 1, 0, spacingHint() );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Vertical Scale" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 2, 5, spacingHint() );
+ boxLayout->setColStretch( 2, 1 );
+
+ mUseAutoRange = new QCheckBox( i18n( "Automatic range detection" ), groupBox );
+ QWhatsThis::add( mUseAutoRange, i18n( "Check this box if you want the display range to adapt dynamically to the currently displayed values; if you do not check this, you have to specify the range you want in the fields below." ) );
+ boxLayout->addMultiCellWidget( mUseAutoRange, 0, 0, 0, 4 );
+
+ label = new QLabel( i18n( "Minimum value:" ), groupBox );
+ boxLayout->addWidget( label, 1, 0 );
+
+ mMinValue = new KLineEdit( groupBox );
+ mMinValue->setAlignment( AlignRight );
+ mMinValue->setEnabled( false );
+ QWhatsThis::add( mMinValue, i18n( "Enter the minimum value for the display here. If both values are 0, automatic range detection is enabled." ) );
+ boxLayout->addWidget( mMinValue, 1, 1 );
+ label->setBuddy( mMinValue );
+
+ label = new QLabel( i18n( "Maximum value:" ), groupBox );
+ boxLayout->addWidget( label, 1, 3 );
+
+ mMaxValue = new KLineEdit( groupBox );
+ mMaxValue->setAlignment( AlignRight );
+ mMaxValue->setEnabled( false );
+ QWhatsThis::add( mMaxValue, i18n( "Enter the maximum value for the display here. If both values are 0, automatic range detection is enabled." ) );
+ boxLayout->addWidget( mMaxValue, 1, 4 );
+ label->setBuddy( mMaxValue );
+
+ pageLayout->addWidget( groupBox, 0, 0 );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Horizontal Scale" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 2, 2, spacingHint() );
+ boxLayout->setRowStretch( 1, 1 );
+
+ mHorizontalScale = new KIntNumInput( 1, groupBox );
+ mHorizontalScale->setMinValue( 1 );
+ mHorizontalScale->setMaxValue( 50 );
+ boxLayout->addWidget( mHorizontalScale, 0, 0 );
+
+ label = new QLabel( i18n( "pixel(s) per time period" ), groupBox );
+ boxLayout->addWidget( label, 0, 1 );
+
+ pageLayout->addWidget( groupBox, 1, 0 );
+
+ // Grid page
+ page = addPage( i18n( "Grid" ) );
+ pageLayout = new QGridLayout( page, 3, 2, 0, spacingHint() );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Lines" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 2, 5, spacingHint() );
+ boxLayout->setColStretch( 1, 1 );
+
+ mShowVerticalLines = new QCheckBox( i18n( "Vertical lines" ), groupBox );
+ QWhatsThis::add( mShowVerticalLines, i18n( "Check this to activate the vertical lines if display is large enough." ) );
+ boxLayout->addWidget( mShowVerticalLines, 0, 0 );
+
+ label = new QLabel( i18n( "Distance:" ), groupBox );
+ boxLayout->addWidget( label, 0, 2 );
+
+ mVerticalLinesDistance = new KIntNumInput( 0, groupBox );
+ mVerticalLinesDistance->setMinValue( 10 );
+ mVerticalLinesDistance->setMaxValue( 120 );
+ QWhatsThis::add( mVerticalLinesDistance, i18n( "Enter the distance between two vertical lines here." ) );
+ boxLayout->addWidget( mVerticalLinesDistance , 0, 3 );
+ label->setBuddy( mVerticalLinesDistance );
+
+ mVerticalLinesScroll = new QCheckBox( i18n( "Vertical lines scroll" ), groupBox );
+ boxLayout->addWidget( mVerticalLinesScroll, 0, 4 );
+
+ mShowHorizontalLines = new QCheckBox( i18n( "Horizontal lines" ), groupBox );
+ QWhatsThis::add( mShowHorizontalLines, i18n( "Check this to enable horizontal lines if display is large enough." ) );
+ boxLayout->addWidget( mShowHorizontalLines, 1, 0 );
+
+ label = new QLabel( i18n( "Count:" ), groupBox );
+ boxLayout->addWidget( label, 1, 2 );
+
+ mHorizontalLinesCount = new KIntNumInput( 0, groupBox );
+ mHorizontalLinesCount->setMinValue( 1 );
+ mHorizontalLinesCount->setMaxValue( 100 );
+ QWhatsThis::add( mHorizontalLinesCount, i18n( "Enter the number of horizontal lines here." ) );
+ boxLayout->addWidget( mHorizontalLinesCount , 1, 3 );
+ label->setBuddy( mHorizontalLinesCount );
+
+ boxLayout->setRowStretch( 2, 1 );
+
+ pageLayout->addMultiCellWidget( groupBox, 0, 0, 0, 1 );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Text" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 3, 4, spacingHint() );
+ boxLayout->setColStretch( 1, 1 );
+
+ mShowLabels = new QCheckBox( i18n( "Labels" ), groupBox );
+ QWhatsThis::add( mShowLabels, i18n( "Check this box if horizontal lines should be decorated with the values they mark." ) );
+ boxLayout->addWidget( mShowLabels, 0, 0 );
+
+ label = new QLabel( i18n( "Font size:" ), groupBox );
+ boxLayout->addWidget( label, 0, 2 );
+
+ mFontSize = new KIntNumInput( 9, groupBox );
+ mFontSize->setMinValue( 5 );
+ mFontSize->setMaxValue( 24 );
+ boxLayout->addWidget( mFontSize, 0, 3 );
+ label->setBuddy( mFontSize );
+
+ mShowTopBar = new QCheckBox( i18n( "Top bar" ), groupBox );
+ QWhatsThis::add( mShowTopBar, i18n( "Check this to active the display title bar. This is probably only useful for applet displays. The bar is only visible if the display is large enough." ) );
+ boxLayout->addWidget( mShowTopBar, 1, 0 );
+
+ boxLayout->setRowStretch( 2, 1 );
+
+ pageLayout->addWidget( groupBox, 1, 0 );
+
+ groupBox = new QGroupBox( 0, Qt::Vertical, i18n( "Colors" ), page );
+ boxLayout = new QGridLayout( groupBox->layout(), 4, 2, spacingHint() );
+
+ label = new QLabel( i18n( "Vertical lines:" ), groupBox );
+ boxLayout->addWidget( label, 0, 0 );
+
+ mVerticalLinesColor = new KColorButton( groupBox );
+ boxLayout->addWidget( mVerticalLinesColor, 0, 1 );
+ label->setBuddy( mVerticalLinesColor );
+
+ label = new QLabel( i18n( "Horizontal lines:" ), groupBox );
+ boxLayout->addWidget( label, 1, 0 );
+
+ mHorizontalLinesColor = new KColorButton( groupBox );
+ boxLayout->addWidget( mHorizontalLinesColor, 1, 1 );
+ label->setBuddy( mHorizontalLinesColor );
+
+ label = new QLabel( i18n( "Background:" ), groupBox );
+ boxLayout->addWidget( label, 2, 0 );
+
+ mBackgroundColor = new KColorButton( groupBox );
+ boxLayout->addWidget( mBackgroundColor, 2, 1 );
+ label->setBuddy( mBackgroundColor );
+
+ boxLayout->setRowStretch( 3, 1 );
+
+ pageLayout->addWidget( groupBox, 1, 1 );
+
+ pageLayout->setRowStretch( 2, 1 );
+
+ // Sensors page
+ page = addPage( i18n( "Sensors" ) );
+ pageLayout = new QGridLayout( page, 6, 2, 0, spacingHint() );
+ pageLayout->setRowStretch( 2, 1 );
+ pageLayout->setRowStretch( 5, 1 );
+
+ mSensorView = new KListView( page );
+ mSensorView->addColumn("" , 0);
+ mSensorView->addColumn( i18n( "Host" ) );
+ mSensorView->addColumn( i18n( "Sensor" ) );
+ mSensorView->addColumn( i18n( "Unit" ) );
+ mSensorView->addColumn( i18n( "Status" ) );
+ mSensorView->setResizeMode(QListView::LastColumn);
+ mSensorView->header()->setResizeEnabled(false, 0);
+ mSensorView->hideColumn(0);
+ mSensorView->header()->resizeSection(0, 0);
+ mSensorView->setAllColumnsShowFocus( true );
+ pageLayout->addMultiCellWidget( mSensorView, 0, 5, 0, 0 );
+ mSensorView->setSortColumn ( -1 );
+ mEditButton = new QPushButton( i18n( "Set Color..." ), page );
+ mEditButton->setEnabled( false );
+ QWhatsThis::add( mEditButton, i18n( "Push this button to configure the color of the sensor in the diagram." ) );
+ pageLayout->addWidget( mEditButton, 0, 1 );
+
+ mRemoveButton = new QPushButton( i18n( "Delete" ), page );
+ mRemoveButton->setEnabled( false );
+ QWhatsThis::add( mRemoveButton, i18n( "Push this button to delete the sensor." ) );
+ pageLayout->addWidget( mRemoveButton, 1, 1 );
+
+ mMoveUpButton = new QPushButton( i18n( "Move Up" ), page );
+ mMoveUpButton->setEnabled( false );
+ pageLayout->addWidget( mMoveUpButton, 3, 1 );
+
+ mMoveDownButton = new QPushButton( i18n( "Move Down" ), page );
+ mMoveDownButton->setEnabled( false );
+ pageLayout->addWidget( mMoveDownButton, 4, 1 );
+
+ connect( mUseAutoRange, SIGNAL( toggled( bool ) ), mMinValue,
+ SLOT( setDisabled( bool ) ) );
+ connect( mUseAutoRange, SIGNAL( toggled( bool ) ), mMaxValue,
+ SLOT( setDisabled( bool ) ) );
+ connect( mShowVerticalLines, SIGNAL( toggled( bool ) ), mVerticalLinesDistance,
+ SLOT( setEnabled( bool ) ) );
+ connect( mShowVerticalLines, SIGNAL( toggled( bool ) ), mVerticalLinesScroll,
+ SLOT( setEnabled( bool ) ) );
+ connect( mShowVerticalLines, SIGNAL( toggled( bool ) ), mVerticalLinesColor,
+ SLOT( setEnabled( bool ) ) );
+ connect( mShowHorizontalLines, SIGNAL( toggled( bool ) ), mHorizontalLinesCount,
+ SLOT( setEnabled( bool ) ) );
+ connect( mShowHorizontalLines, SIGNAL( toggled( bool ) ), mHorizontalLinesColor,
+ SLOT( setEnabled( bool ) ) );
+ connect( mShowHorizontalLines, SIGNAL( toggled( bool ) ), mShowLabels,
+ SLOT( setEnabled( bool ) ) );
+ connect( mSensorView, SIGNAL( selectionChanged( QListViewItem* ) ),
+ SLOT( selectionChanged( QListViewItem* ) ) );
+
+ connect( mEditButton, SIGNAL( clicked() ), SLOT( editSensor() ) );
+ connect( mRemoveButton, SIGNAL( clicked() ), SLOT( removeSensor() ) );
+ connect( mMoveUpButton, SIGNAL( clicked() ), SLOT( moveUpSensor() ) );
+ connect( mMoveDownButton, SIGNAL( clicked() ), SLOT( moveDownSensor() ) );
+ connect ( mSensorView, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int )), SLOT(editSensor()));
+
+ KAcceleratorManager::manage( this );
+}
+
+FancyPlotterSettings::~FancyPlotterSettings()
+{
+}
+
+void FancyPlotterSettings::setTitle( const QString &title )
+{
+ mTitle->setText( title );
+}
+
+QString FancyPlotterSettings::title() const
+{
+ return mTitle->text();
+}
+
+void FancyPlotterSettings::setUseAutoRange( bool value )
+{
+ mUseAutoRange->setChecked( value );
+ mMinValue->setEnabled( !value );
+ mMaxValue->setEnabled( !value );
+}
+
+bool FancyPlotterSettings::useAutoRange() const
+{
+ return mUseAutoRange->isChecked();
+}
+
+void FancyPlotterSettings::setMinValue( double min )
+{
+ mMinValue->setText( QString::number( min ) );
+}
+
+double FancyPlotterSettings::minValue() const
+{
+ return mMinValue->text().toDouble();
+}
+
+void FancyPlotterSettings::setMaxValue( double max )
+{
+ mMaxValue->setText( QString::number( max ) );
+}
+
+double FancyPlotterSettings::maxValue() const
+{
+ return mMaxValue->text().toDouble();
+}
+
+void FancyPlotterSettings::setUsePolygonStyle( bool value )
+{
+ if ( value )
+ mUsePolygonStyle->setChecked( true );
+ else
+ mUseOriginalStyle->setChecked( true );
+}
+
+bool FancyPlotterSettings::usePolygonStyle() const
+{
+ return mUsePolygonStyle->isChecked();
+}
+
+void FancyPlotterSettings::setHorizontalScale( int scale )
+{
+ mHorizontalScale->setValue( scale );
+}
+
+int FancyPlotterSettings::horizontalScale() const
+{
+ return mHorizontalScale->value();
+}
+
+void FancyPlotterSettings::setShowVerticalLines( bool value )
+{
+ mShowVerticalLines->setChecked( value );
+ mVerticalLinesDistance->setEnabled( value );
+ mVerticalLinesScroll->setEnabled( value );
+ mVerticalLinesColor->setEnabled( value );
+}
+
+bool FancyPlotterSettings::showVerticalLines() const
+{
+ return mShowVerticalLines->isChecked();
+}
+
+void FancyPlotterSettings::setVerticalLinesColor( const QColor &color )
+{
+ mVerticalLinesColor->setColor( color );
+}
+
+QColor FancyPlotterSettings::verticalLinesColor() const
+{
+ return mVerticalLinesColor->color();
+}
+
+void FancyPlotterSettings::setVerticalLinesDistance( int distance )
+{
+ mVerticalLinesDistance->setValue( distance );
+}
+
+int FancyPlotterSettings::verticalLinesDistance() const
+{
+ return mVerticalLinesDistance->value();
+}
+
+void FancyPlotterSettings::setVerticalLinesScroll( bool value )
+{
+ mVerticalLinesScroll->setChecked( value );
+}
+
+bool FancyPlotterSettings::verticalLinesScroll() const
+{
+ return mVerticalLinesScroll->isChecked();
+}
+
+void FancyPlotterSettings::setShowHorizontalLines( bool value )
+{
+ mShowHorizontalLines->setChecked( value );
+ mHorizontalLinesCount->setEnabled( value );
+ mHorizontalLinesColor->setEnabled( value );
+ mShowLabels->setEnabled( value );
+
+}
+
+bool FancyPlotterSettings::showHorizontalLines() const
+{
+ return mShowHorizontalLines->isChecked();
+}
+
+void FancyPlotterSettings::setHorizontalLinesColor( const QColor &color )
+{
+ mHorizontalLinesColor->setColor( color );
+}
+
+QColor FancyPlotterSettings::horizontalLinesColor() const
+{
+ return mHorizontalLinesColor->color();
+}
+
+void FancyPlotterSettings::setHorizontalLinesCount( int count )
+{
+ mHorizontalLinesCount->setValue( count );
+}
+
+int FancyPlotterSettings::horizontalLinesCount() const
+{
+ return mHorizontalLinesCount->value();
+}
+
+void FancyPlotterSettings::setShowLabels( bool value )
+{
+ mShowLabels->setChecked( value );
+}
+
+bool FancyPlotterSettings::showLabels() const
+{
+ return mShowLabels->isChecked();
+}
+
+void FancyPlotterSettings::setShowTopBar( bool value )
+{
+ mShowTopBar->setChecked( value );
+}
+
+bool FancyPlotterSettings::showTopBar() const
+{
+ return mShowTopBar->isChecked();
+}
+
+void FancyPlotterSettings::setFontSize( int size )
+{
+ mFontSize->setValue( size );
+}
+
+int FancyPlotterSettings::fontSize() const
+{
+ return mFontSize->value();
+}
+
+void FancyPlotterSettings::setBackgroundColor( const QColor &color )
+{
+ mBackgroundColor->setColor( color );
+}
+
+QColor FancyPlotterSettings::backgroundColor() const
+{
+ return mBackgroundColor->color();
+}
+void FancyPlotterSettings::clearDeleted()
+{
+ mDeleted.clear();
+}
+QValueList<int> FancyPlotterSettings::deleted() const
+{
+ return mDeleted;
+}
+
+QValueList<int> FancyPlotterSettings::order() const
+{
+ QValueList<int> newOrder;
+
+ QListViewItemIterator it( mSensorView );
+ for ( ; it.current(); ++it ) {
+ newOrder.prepend(it.current()->text(0).toInt());
+ }
+ return newOrder;
+}
+
+void FancyPlotterSettings::resetOrder()
+{
+ int i = mSensorView->childCount()-1;
+ QListViewItemIterator it( mSensorView );
+ for ( ; it.current(); ++it, --i) {
+ it.current()->setText(0, QString::number(i));
+ }
+}
+
+void FancyPlotterSettings::setSensors( const QValueList< QStringList > &list )
+{
+ mSensorView->clear();
+
+ QValueList< QStringList >::ConstIterator it;
+ for ( it = list.begin(); it != list.end(); ++it ) {
+ QListViewItem* lvi = new QListViewItem( mSensorView,
+ (*it)[ 0 ], // id
+ (*it)[ 1 ], // host name
+ (*it)[ 2 ], // sensor name
+ (*it)[ 3 ], // unit
+ (*it)[ 4 ] ); // status
+ QPixmap pm( 12, 12 );
+ pm.fill( QColor( (*it)[ 5 ] ) );
+ lvi->setPixmap( 2, pm );
+ mSensorView->insertItem( lvi );
+ }
+}
+
+QValueList< QStringList > FancyPlotterSettings::sensors() const
+{
+ QValueList< QStringList > list;
+
+ QListViewItemIterator it( mSensorView );
+
+ for ( ; it.current(); ++it ) {
+ QStringList entry;
+ entry << it.current()->text( 0 );
+ entry << it.current()->text( 1 );
+ entry << it.current()->text( 2 );
+ entry << it.current()->text( 3 );
+ entry << it.current()->text( 4 );
+ QRgb rgb = it.current()->pixmap( 2 )->convertToImage().pixel( 1, 1 );
+ QColor color( qRed( rgb ), qGreen( rgb ), qBlue( rgb ) );
+ entry << ( color.name() );
+
+ list.prepend( entry );
+ }
+
+ return list;
+}
+
+void FancyPlotterSettings::editSensor()
+{
+ QListViewItem* lvi = mSensorView->currentItem();
+
+ if ( !lvi )
+ return;
+
+ QColor color = lvi->pixmap( 2 )->convertToImage().pixel( 1, 1 );
+ int result = KColorDialog::getColor( color, parentWidget() );
+ if ( result == KColorDialog::Accepted ) {
+ QPixmap newPm( 12, 12 );
+ newPm.fill( color );
+ lvi->setPixmap( 2, newPm );
+ }
+}
+
+void FancyPlotterSettings::removeSensor()
+{
+ QListViewItem* lvi = mSensorView->currentItem();
+
+ if ( lvi ) {
+ //Note down the id of the one we are deleting
+ int id = lvi->text(0).toInt();
+ mDeleted.append(id);
+
+ /* Before we delete the currently selected item, we determine a
+ * new item to be selected. That way we can ensure that multiple
+ * items can be deleted without forcing the user to select a new
+ * item between the deletes. If all items are deleted, the buttons
+ * are disabled again. */
+ QListViewItem* newSelected = 0;
+ if ( lvi->itemBelow() ) {
+ lvi->itemBelow()->setSelected( true );
+ newSelected = lvi->itemBelow();
+ } else if ( lvi->itemAbove() ) {
+ lvi->itemAbove()->setSelected( true );
+ newSelected = lvi->itemAbove();
+ } else
+ selectionChanged( 0 );
+
+ delete lvi;
+
+ QListViewItemIterator it( mSensorView );
+ for ( ; it.current(); ++it ) {
+ if(it.current()->text(0).toInt() > id)
+ it.current()->setText(0, QString::number(it.current()->text(0).toInt() -1));
+ }
+
+
+ if ( newSelected )
+ mSensorView->ensureItemVisible( newSelected );
+ }
+}
+
+void FancyPlotterSettings::moveUpSensor()
+{
+ if ( mSensorView->currentItem() != 0 ) {
+ QListViewItem* item = mSensorView->currentItem()->itemAbove();
+ if ( item ) {
+ if ( item->itemAbove() )
+ {
+ mSensorView->currentItem()->moveItem( item->itemAbove() );
+ }
+ else
+ {
+ item->moveItem( mSensorView->currentItem() );
+ }
+ }
+
+ selectionChanged( mSensorView->currentItem() );
+ }
+}
+
+void FancyPlotterSettings::moveDownSensor()
+{
+ if ( mSensorView->currentItem() != 0 ) {
+ if ( mSensorView->currentItem()->itemBelow() )
+ mSensorView->currentItem()->moveItem( mSensorView->currentItem()->itemBelow() );
+
+ selectionChanged( mSensorView->currentItem() );
+ }
+}
+
+void FancyPlotterSettings::selectionChanged( QListViewItem *item )
+{
+ bool state = ( item != 0 );
+
+ mEditButton->setEnabled( state );
+ mRemoveButton->setEnabled( state );
+ mMoveUpButton->setEnabled( state && item->itemAbove() );
+ mMoveDownButton->setEnabled( state && item->itemBelow() );
+}
+
+#include "FancyPlotterSettings.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.h b/ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.h
new file mode 100644
index 000000000..b813bee34
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/FancyPlotterSettings.h
@@ -0,0 +1,143 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef FANCYPLOTTERSETTINGS_H
+#define FANCYPLOTTERSETTINGS_H
+
+#include <kdialogbase.h>
+
+class KColorButton;
+class KIntNumInput;
+class KLineEdit;
+class KListView;
+
+class QCheckBox;
+class QListViewItem;
+class QPushButton;
+class QRadioButton;
+
+class FancyPlotterSettings : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ FancyPlotterSettings( QWidget* parent = 0, const char* name = 0 );
+ ~FancyPlotterSettings();
+
+ void setTitle( const QString &title );
+ QString title() const;
+
+ void setUseAutoRange( bool value );
+ bool useAutoRange() const;
+
+ void setMinValue( double min );
+ double minValue() const;
+
+ void setMaxValue( double max );
+ double maxValue() const;
+
+ void setUsePolygonStyle( bool value );
+ bool usePolygonStyle() const;
+
+ void setHorizontalScale( int scale );
+ int horizontalScale() const;
+
+ void setShowVerticalLines( bool value );
+ bool showVerticalLines() const;
+
+ void setVerticalLinesColor( const QColor &color );
+ QColor verticalLinesColor() const;
+
+ void setVerticalLinesDistance( int distance );
+ int verticalLinesDistance() const;
+
+ void setVerticalLinesScroll( bool value );
+ bool verticalLinesScroll() const;
+
+ void setShowHorizontalLines( bool value );
+ bool showHorizontalLines() const;
+
+ void setHorizontalLinesColor( const QColor &color );
+ QColor horizontalLinesColor() const;
+
+ void setHorizontalLinesCount( int count );
+ int horizontalLinesCount() const;
+
+ void setShowLabels( bool value );
+ bool showLabels() const;
+
+ void setShowTopBar( bool value );
+ bool showTopBar() const;
+
+ void setFontSize( int size );
+ int fontSize() const;
+
+ void setBackgroundColor( const QColor &color );
+ QColor backgroundColor() const;
+
+ void setSensors( const QValueList< QStringList > &list );
+ QValueList< QStringList > sensors() const;
+ QValueList<int> order() const;
+ QValueList<int> deleted() const;
+ void clearDeleted();
+ void resetOrder();
+
+ private slots:
+ void editSensor();
+ void removeSensor();
+ void moveUpSensor();
+ void moveDownSensor();
+ void selectionChanged( QListViewItem* );
+
+ private:
+
+ KColorButton *mVerticalLinesColor;
+ KColorButton *mHorizontalLinesColor;
+ KColorButton *mBackgroundColor;
+ KLineEdit *mMinValue;
+ KLineEdit *mMaxValue;
+ KLineEdit *mTitle;
+ KIntNumInput *mHorizontalScale;
+ KIntNumInput *mVerticalLinesDistance;
+ KIntNumInput *mHorizontalLinesCount;
+ KIntNumInput *mFontSize;
+ KListView *mSensorView;
+
+ QCheckBox *mShowVerticalLines;
+ QCheckBox *mShowHorizontalLines;
+ QCheckBox *mVerticalLinesScroll;
+ QCheckBox *mUseAutoRange;
+ QCheckBox *mShowLabels;
+ QCheckBox *mShowTopBar;
+ QPushButton *mEditButton;
+ QPushButton *mRemoveButton;
+ QPushButton *mMoveUpButton;
+ QPushButton *mMoveDownButton;
+ QRadioButton *mUsePolygonStyle;
+ QRadioButton *mUseOriginalStyle;
+
+ /** The numbers of the sensors to be delete.*/
+ QValueList<int> mDeleted;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/ListView.cc b/ksysguard/gui/SensorDisplayLib/ListView.cc
new file mode 100644
index 000000000..885daded6
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ListView.cc
@@ -0,0 +1,371 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <config.h>
+#include <qdom.h>
+
+#include <kcolorbutton.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ksgrd/SensorManager.h>
+#include <ksgrd/StyleEngine.h>
+
+#include "ListView.h"
+#include "ListView.moc"
+#include "ListViewSettings.h"
+
+PrivateListViewItem::PrivateListViewItem(PrivateListView *parent)
+ : QListViewItem(parent)
+{
+ _parent = parent;
+}
+
+int PrivateListViewItem::compare( QListViewItem *item, int col, bool ascending ) const
+{
+ int type = ((PrivateListView*)listView())->columnType( col );
+
+ if ( type == PrivateListView::Int ) {
+ int prev = (int)KGlobal::locale()->readNumber( key( col, ascending ) );
+ int next = (int)KGlobal::locale()->readNumber( item->key( col, ascending ) );
+ if ( prev < next )
+ return -1;
+ else if ( prev == next )
+ return 0;
+ else
+ return 1;
+ } else if ( type == PrivateListView::Float ) {
+ double prev = KGlobal::locale()->readNumber( key( col, ascending ) );
+ double next = KGlobal::locale()->readNumber( item->key( col, ascending ) );
+ if ( prev < next )
+ return -1;
+ else
+ return 1;
+ } else if ( type == PrivateListView::Time ) {
+ int hourPrev, hourNext, minutesPrev, minutesNext;
+ sscanf( key( col, ascending ).latin1(), "%d:%d", &hourPrev, &minutesPrev );
+ sscanf( item->key( col, ascending ).latin1(), "%d:%d", &hourNext, &minutesNext );
+ int prev = hourPrev * 60 + minutesPrev;
+ int next = hourNext * 60 + minutesNext;
+ if ( prev < next )
+ return -1;
+ else if ( prev == next )
+ return 0;
+ else
+ return 1;
+ } else if ( type == PrivateListView::DiskStat ) {
+ QString prev = key( col, ascending );
+ QString next = item->key( col, ascending );
+ QString prevKey, nextKey;
+
+ uint counter = prev.length();
+ for ( uint i = 0; i < counter; ++i )
+ if ( prev[ i ].isDigit() ) {
+ prevKey.sprintf( "%s%016d", prev.left( i ).latin1(), prev.mid( i ).toInt() );
+ break;
+ }
+
+ counter = next.length();
+ for ( uint i = 0; i < counter; ++i )
+ if ( next[ i ].isDigit() ) {
+ nextKey.sprintf( "%s%016d", next.left( i ).latin1(), next.mid( i ).toInt() );
+ break;
+ }
+
+ return prevKey.compare( nextKey );
+ } else
+ return key( col, ascending ).localeAwareCompare( item->key( col, ascending ) );
+}
+
+PrivateListView::PrivateListView(QWidget *parent, const char *name)
+ : QListView(parent, name)
+{
+ QColorGroup cg = colorGroup();
+
+ cg.setColor(QColorGroup::Link, KSGRD::Style->firstForegroundColor());
+ cg.setColor(QColorGroup::Text, KSGRD::Style->secondForegroundColor());
+ cg.setColor(QColorGroup::Base, KSGRD::Style->backgroundColor());
+
+ setPalette(QPalette(cg, cg, cg));
+}
+
+void PrivateListView::update(const QString& answer)
+{
+ setUpdatesEnabled(false);
+ viewport()->setUpdatesEnabled(false);
+
+ int vpos = verticalScrollBar()->value();
+ int hpos = horizontalScrollBar()->value();
+
+ clear();
+
+ KSGRD::SensorTokenizer lines(answer, '\n');
+ for (uint i = 0; i < lines.count(); i++) {
+ PrivateListViewItem *item = new PrivateListViewItem(this);
+ KSGRD::SensorTokenizer records(lines[i], '\t');
+ for (uint j = 0; j < records.count(); j++) {
+ if ( mColumnTypes[ j ] == "f" )
+ item->setText(j, KGlobal::locale()->formatNumber( records[j].toFloat() ) );
+ else if ( mColumnTypes[ j ] == "D" )
+ item->setText(j, KGlobal::locale()->formatNumber( records[j].toDouble(), 0 ) );
+ else
+ item->setText(j, records[j]);
+ }
+
+ insertItem(item);
+ }
+
+ verticalScrollBar()->setValue(vpos);
+ horizontalScrollBar()->setValue(hpos);
+
+ viewport()->setUpdatesEnabled(true);
+ setUpdatesEnabled(true);
+
+ triggerUpdate();
+}
+
+int PrivateListView::columnType( uint pos ) const
+{
+ if ( pos >= mColumnTypes.count() )
+ return 0;
+
+ if ( mColumnTypes[ pos ] == "d" || mColumnTypes[ pos ] == "D" )
+ return Int;
+ else if ( mColumnTypes[ pos ] == "f" || mColumnTypes[ pos ] == "F" )
+ return Float;
+ else if ( mColumnTypes[ pos ] == "t" )
+ return Time;
+ else if ( mColumnTypes[ pos ] == "M" )
+ return DiskStat;
+ else
+ return Text;
+}
+
+void PrivateListView::removeColumns(void)
+{
+ for (int i = columns() - 1; i >= 0; --i)
+ removeColumn(i);
+}
+
+void PrivateListView::addColumn(const QString& label, const QString& type)
+{
+ QListView::addColumn( label );
+ int col = columns() - 1;
+
+ if (type == "s" || type == "S")
+ setColumnAlignment(col, AlignLeft);
+ else if (type == "d" || type == "D")
+ setColumnAlignment(col, AlignRight);
+ else if (type == "t")
+ setColumnAlignment(col, AlignRight);
+ else if (type == "f")
+ setColumnAlignment(col, AlignRight);
+ else if (type == "M")
+ setColumnAlignment(col, AlignLeft);
+ else
+ {
+ kdDebug(1215) << "Unknown type " << type << " of column " << label
+ << " in ListView!" << endl;
+ return;
+ }
+
+ mColumnTypes.append( type );
+
+ /* Just use some sensible default values as initial setting. */
+ QFontMetrics fm = fontMetrics();
+ setColumnWidth(col, fm.width(label) + 10);
+}
+
+ListView::ListView(QWidget* parent, const char* name, const QString& title, int, int)
+ : KSGRD::SensorDisplay(parent, name, title)
+{
+ setBackgroundColor(KSGRD::Style->backgroundColor());
+
+ monitor = new PrivateListView( frame() );
+ Q_CHECK_PTR(monitor);
+ monitor->setSelectionMode(QListView::NoSelection);
+ monitor->setItemMargin(2);
+
+ setMinimumSize(50, 25);
+
+ setPlotterWidget(monitor);
+
+ setModified(false);
+}
+
+bool
+ListView::addSensor(const QString& hostName, const QString& sensorName, const QString& sensorType, const QString& title)
+{
+ if (sensorType != "listview")
+ return (false);
+
+ registerSensor(new KSGRD::SensorProperties(hostName, sensorName, sensorType, title));
+
+ setTitle(title);
+
+ /* To differentiate between answers from value requests and info
+ * requests we use 100 for info requests. */
+ sendRequest(hostName, sensorName + "?", 100);
+ sendRequest(hostName, sensorName, 19);
+ setModified(true);
+ return (true);
+}
+
+void
+ListView::updateList()
+{
+ sendRequest(sensors().at(0)->hostName(), sensors().at(0)->name(), 19);
+}
+
+void
+ListView::answerReceived(int id, const QString& answer)
+{
+ /* We received something, so the sensor is probably ok. */
+ sensorError(id, false);
+
+ switch (id)
+ {
+ case 100: {
+ /* We have received the answer to a '?' command that contains
+ * the information about the table headers. */
+ KSGRD::SensorTokenizer lines(answer, '\n');
+ if (lines.count() != 2)
+ {
+ kdDebug(1215) << "wrong number of lines" << endl;
+ return;
+ }
+ KSGRD::SensorTokenizer headers(lines[0], '\t');
+ KSGRD::SensorTokenizer colTypes(lines[1], '\t');
+
+ /* remove all columns from list */
+ monitor->removeColumns();
+
+ /* add the new columns */
+ for (unsigned int i = 0; i < headers.count(); i++)
+ /* TODO: Implement translation support for header texts */
+ monitor->addColumn(headers[i], colTypes[i]);
+ break;
+ }
+ case 19: {
+ monitor->update(answer);
+ break;
+ }
+ }
+}
+
+void
+ListView::resizeEvent(QResizeEvent*)
+{
+ frame()->setGeometry(0, 0, width(), height());
+ monitor->setGeometry(10, 20, width() - 20, height() - 30);
+}
+
+bool
+ListView::restoreSettings(QDomElement& element)
+{
+ addSensor(element.attribute("hostName"), element.attribute("sensorName"), (element.attribute("sensorType").isEmpty() ? "listview" : element.attribute("sensorType")), element.attribute("title"));
+
+ QColorGroup colorGroup = monitor->colorGroup();
+ colorGroup.setColor(QColorGroup::Link, restoreColor(element, "gridColor", KSGRD::Style->firstForegroundColor()));
+ colorGroup.setColor(QColorGroup::Text, restoreColor(element, "textColor", KSGRD::Style->secondForegroundColor()));
+ colorGroup.setColor(QColorGroup::Base, restoreColor(element, "backgroundColor", KSGRD::Style->backgroundColor()));
+
+ monitor->setPalette(QPalette(colorGroup, colorGroup, colorGroup));
+
+ SensorDisplay::restoreSettings(element);
+
+ setModified(false);
+
+ return (true);
+}
+
+bool
+ListView::saveSettings(QDomDocument& doc, QDomElement& element, bool save)
+{
+ element.setAttribute("hostName", sensors().at(0)->hostName());
+ element.setAttribute("sensorName", sensors().at(0)->name());
+ element.setAttribute("sensorType", sensors().at(0)->type());
+
+ QColorGroup colorGroup = monitor->colorGroup();
+ saveColor(element, "gridColor", colorGroup.color(QColorGroup::Link));
+ saveColor(element, "textColor", colorGroup.color(QColorGroup::Text));
+ saveColor(element, "backgroundColor", colorGroup.color(QColorGroup::Base));
+
+ SensorDisplay::saveSettings(doc, element);
+
+ if (save)
+ setModified(false);
+
+ return (true);
+}
+
+void
+ListView::configureSettings()
+{
+ lvs = new ListViewSettings(this, "ListViewSettings");
+ Q_CHECK_PTR(lvs);
+ connect(lvs, SIGNAL(applyClicked()), SLOT(applySettings()));
+
+ QColorGroup colorGroup = monitor->colorGroup();
+ lvs->setGridColor(colorGroup.color(QColorGroup::Link));
+ lvs->setTextColor(colorGroup.color(QColorGroup::Text));
+ lvs->setBackgroundColor(colorGroup.color(QColorGroup::Base));
+ lvs->setTitle(title());
+
+ if (lvs->exec())
+ applySettings();
+
+ delete lvs;
+ lvs = 0;
+}
+
+void
+ListView::applySettings()
+{
+ QColorGroup colorGroup = monitor->colorGroup();
+ colorGroup.setColor(QColorGroup::Link, lvs->gridColor());
+ colorGroup.setColor(QColorGroup::Text, lvs->textColor());
+ colorGroup.setColor(QColorGroup::Base, lvs->backgroundColor());
+ monitor->setPalette(QPalette(colorGroup, colorGroup, colorGroup));
+
+ setTitle(lvs->title());
+
+ setModified(true);
+}
+
+void
+ListView::applyStyle()
+{
+ QColorGroup colorGroup = monitor->colorGroup();
+ colorGroup.setColor(QColorGroup::Link, KSGRD::Style->firstForegroundColor());
+ colorGroup.setColor(QColorGroup::Text, KSGRD::Style->secondForegroundColor());
+ colorGroup.setColor(QColorGroup::Base, KSGRD::Style->backgroundColor());
+ monitor->setPalette(QPalette(colorGroup, colorGroup, colorGroup));
+
+ setModified(true);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/ListView.h b/ksysguard/gui/SensorDisplayLib/ListView.h
new file mode 100644
index 000000000..4b96329c0
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ListView.h
@@ -0,0 +1,112 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef _ListView_h_
+#define _ListView_h_
+
+#include <qlistview.h>
+#include <qpainter.h>
+
+#include <SensorDisplay.h>
+
+typedef const char* (*KeyFunc)(const char*);
+
+class QLabel;
+class QBoxGroup;
+class ListViewSettings;
+
+class PrivateListView : public QListView
+{
+ Q_OBJECT
+public:
+ enum ColumnType { Text, Int, Float, Time, DiskStat };
+
+ PrivateListView(QWidget *parent = 0, const char *name = 0);
+
+ void addColumn(const QString& label, const QString& type);
+ void removeColumns(void);
+ void update(const QString& answer);
+ int columnType( uint pos ) const;
+
+private:
+ QStringList mColumnTypes;
+};
+
+class PrivateListViewItem : public QListViewItem
+{
+public:
+ PrivateListViewItem(PrivateListView *parent = 0);
+
+ void paintCell(QPainter *p, const QColorGroup &, int column, int width, int alignment) {
+ QColorGroup cgroup = _parent->colorGroup();
+ QListViewItem::paintCell(p, cgroup, column, width, alignment);
+ p->setPen(cgroup.color(QColorGroup::Link));
+ p->drawLine(0, height() - 1, width - 1, height() - 1);
+ }
+
+ void paintFocus(QPainter *, const QColorGroup, const QRect) {}
+
+ virtual int compare( QListViewItem*, int column, bool ascending ) const;
+
+private:
+ QWidget *_parent;
+};
+
+class ListView : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+public:
+ ListView(QWidget* parent = 0, const char* name = 0,
+ const QString& = QString::null, int min = 0, int max = 0);
+ ~ListView() {}
+
+ bool addSensor(const QString& hostName, const QString& sensorName, const QString& sensorType, const QString& sensorDescr);
+ void answerReceived(int id, const QString& answer);
+ void resizeEvent(QResizeEvent*);
+ void updateList();
+
+ bool restoreSettings(QDomElement& element);
+ bool saveSettings(QDomDocument& doc, QDomElement& element, bool save = true);
+
+ virtual bool hasSettingsDialog() const
+ {
+ return (true);
+ }
+
+ virtual void timerEvent(QTimerEvent*)
+ {
+ updateList();
+ }
+
+ void configureSettings();
+
+public slots:
+ void applySettings();
+ void applyStyle();
+
+private:
+ PrivateListView* monitor;
+ ListViewSettings* lvs;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/ListViewSettings.cc b/ksysguard/gui/SensorDisplayLib/ListViewSettings.cc
new file mode 100644
index 000000000..15822206e
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ListViewSettings.cc
@@ -0,0 +1,77 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ListViewSettings.h"
+#include "ListViewSettingsWidget.h"
+
+#include <klocale.h>
+
+ListViewSettings::ListViewSettings( QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, i18n( "List View Settings" ),
+ Ok|Apply|Cancel, Ok, true )
+{
+ m_settingsWidget = new ListViewSettingsWidget( this, "m_settingsWidget" );
+ setMainWidget( m_settingsWidget );
+}
+
+QString ListViewSettings::title() const
+{
+ return m_settingsWidget->title();
+}
+
+QColor ListViewSettings::textColor() const
+{
+ return m_settingsWidget->textColor();
+}
+
+QColor ListViewSettings::backgroundColor() const
+{
+ return m_settingsWidget->backgroundColor();
+}
+
+QColor ListViewSettings::gridColor() const
+{
+ return m_settingsWidget->gridColor();
+}
+
+void ListViewSettings::setTitle( const QString &title )
+{
+ m_settingsWidget->setTitle( title );
+}
+
+void ListViewSettings::setBackgroundColor( const QColor &c )
+{
+ m_settingsWidget->setBackgroundColor( c );
+}
+
+void ListViewSettings::setTextColor( const QColor &c )
+{
+ m_settingsWidget->setTextColor( c );
+}
+
+void ListViewSettings::setGridColor( const QColor &c )
+{
+ m_settingsWidget->setGridColor( c );
+}
+
+#include "ListViewSettings.moc"
+
+/* vim: et sw=2 ts=2
+*/
+
diff --git a/ksysguard/gui/SensorDisplayLib/ListViewSettings.h b/ksysguard/gui/SensorDisplayLib/ListViewSettings.h
new file mode 100644
index 000000000..9a9790791
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ListViewSettings.h
@@ -0,0 +1,57 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or ( at your option ) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef LISTVIEWSETTINGS_H
+#define LISTVIEWSETTINGS_H
+
+#include <kdialogbase.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+
+class ListViewSettingsWidget;
+
+class ListViewSettings : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+
+ ListViewSettings( QWidget *parent=0, const char *name=0 );
+
+ QString title() const;
+ QColor textColor() const;
+ QColor backgroundColor() const;
+ QColor gridColor() const;
+
+ void setTitle( const QString & );
+ void setTextColor( const QColor & );
+ void setBackgroundColor( const QColor & );
+ void setGridColor( const QColor & );
+
+ private:
+
+ ListViewSettingsWidget *m_settingsWidget;
+};
+
+#endif // LISTVIEWSETTINGS_H
+
+/* vim: et sw=2 ts=2
+*/
diff --git a/ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui b/ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui
new file mode 100644
index 000000000..f61f30dd7
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui
@@ -0,0 +1,178 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ListViewSettingsWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ListViewSettingsWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>399</width>
+ <height>202</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>titleFrame</cstring>
+ </property>
+ <property name="title">
+ <string>Title</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_title</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>colorFrame</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>Box</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>Colors</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter|AlignLeft</set>
+ </property>
+ <property name="vAlign" stdset="0">
+ </property>
+ <property name="wordwrap" stdset="0">
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Text color:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Grid color:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_textColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_gridColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_backgroundColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<includes>
+ <include location="global" impldecl="in implementation">kdialog.h</include>
+ <include location="local" impldecl="in implementation">ListViewSettingsWidget.ui.h</include>
+</includes>
+<functions>
+ <function specifier="non virtual" returnType="QString">title()</function>
+ <function specifier="non virtual" returnType="QColor">gridColor()</function>
+ <function specifier="non virtual" returnType="QColor">backgroundColor()</function>
+ <function specifier="non virtual" returnType="QColor">textColor()</function>
+ <function specifier="non virtual">setTitle( const QString &amp; t )</function>
+ <function specifier="non virtual">setBackgroundColor( const QColor &amp; c )</function>
+ <function specifier="non virtual">setTextColor( const QColor &amp; c )</function>
+ <function specifier="non virtual">setGridColor( const QColor &amp; c )</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+</UI>
diff --git a/ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui.h b/ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui.h
new file mode 100644
index 000000000..14ff5990d
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ListViewSettingsWidget.ui.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+
+QString ListViewSettingsWidget::title()
+{
+ return m_title->text();
+}
+
+
+QColor ListViewSettingsWidget::gridColor()
+{
+ return m_gridColor->color();
+}
+
+
+QColor ListViewSettingsWidget::backgroundColor()
+{
+ return m_backgroundColor->color();
+}
+
+
+QColor ListViewSettingsWidget::textColor()
+{
+ return m_textColor->color();
+}
+
+
+void ListViewSettingsWidget::setTitle( const QString &t )
+{
+ m_title->setText(t);
+}
+
+
+void ListViewSettingsWidget::setBackgroundColor( const QColor &c )
+{
+ m_backgroundColor->setColor(c);
+}
+
+
+void ListViewSettingsWidget::setTextColor( const QColor &c )
+{
+ m_textColor->setColor(c);
+}
+
+
+void ListViewSettingsWidget::setGridColor( const QColor &c )
+{
+ m_gridColor->setColor(c);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/LogFile.cc b/ksysguard/gui/SensorDisplayLib/LogFile.cc
new file mode 100644
index 000000000..9db4c7116
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/LogFile.cc
@@ -0,0 +1,285 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include <qpushbutton.h>
+#include <qregexp.h>
+
+#include <qfile.h>
+#include <qlistbox.h>
+
+#include <kfontdialog.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kcolorbutton.h>
+
+#include <ksgrd/StyleEngine.h>
+
+#include "LogFile.moc"
+
+LogFile::LogFile(QWidget *parent, const char *name, const QString& title)
+ : KSGRD::SensorDisplay(parent, name, title)
+{
+ monitor = new QListBox(this);
+ Q_CHECK_PTR(monitor);
+
+ setMinimumSize(50, 25);
+
+ setPlotterWidget(monitor);
+
+ setModified(false);
+}
+
+LogFile::~LogFile(void)
+{
+ sendRequest(sensors().at(0)->hostName(), QString("logfile_unregister %1" ).arg(logFileID), 43);
+}
+
+bool
+LogFile::addSensor(const QString& hostName, const QString& sensorName, const QString& sensorType, const QString& title)
+{
+ if (sensorType != "logfile")
+ return (false);
+
+ registerSensor(new KSGRD::SensorProperties(hostName, sensorName, sensorType, title));
+
+ QString sensorID = sensorName.right(sensorName.length() - (sensorName.findRev("/") + 1));
+
+ sendRequest(sensors().at(0)->hostName(), QString("logfile_register %1" ).arg(sensorID), 42);
+
+ if (title.isEmpty())
+ setTitle(sensors().at(0)->hostName() + ":" + sensorID);
+ else
+ setTitle(title);
+
+ setModified(true);
+
+ return (true);
+}
+
+
+void LogFile::configureSettings(void)
+{
+ QColorGroup cgroup = monitor->colorGroup();
+
+ lfs = new LogFileSettings(this);
+ Q_CHECK_PTR(lfs);
+
+ lfs->fgColor->setColor(cgroup.text());
+ lfs->fgColor->setText(i18n("Foreground color:"));
+ lfs->bgColor->setColor(cgroup.base());
+ lfs->bgColor->setText(i18n("Background color:"));
+ lfs->fontButton->setFont(monitor->font());
+ lfs->ruleList->insertStringList(filterRules);
+ lfs->title->setText(title());
+
+ connect(lfs->okButton, SIGNAL(clicked()), lfs, SLOT(accept()));
+ connect(lfs->applyButton, SIGNAL(clicked()), this, SLOT(applySettings()));
+ connect(lfs->cancelButton, SIGNAL(clicked()), lfs, SLOT(reject()));
+
+ connect(lfs->fontButton, SIGNAL(clicked()), this, SLOT(settingsFontSelection()));
+ connect(lfs->addButton, SIGNAL(clicked()), this, SLOT(settingsAddRule()));
+ connect(lfs->deleteButton, SIGNAL(clicked()), this, SLOT(settingsDeleteRule()));
+ connect(lfs->changeButton, SIGNAL(clicked()), this, SLOT(settingsChangeRule()));
+ connect(lfs->ruleList, SIGNAL(selected(int)), this, SLOT(settingsRuleListSelected(int)));
+ connect(lfs->ruleText, SIGNAL(returnPressed()), this, SLOT(settingsAddRule()));
+
+ if (lfs->exec()) {
+ applySettings();
+ }
+
+ delete lfs;
+ lfs = 0;
+}
+
+void LogFile::settingsFontSelection()
+{
+ QFont tmpFont = lfs->fontButton->font();
+
+ if (KFontDialog::getFont(tmpFont) == KFontDialog::Accepted) {
+ lfs->fontButton->setFont(tmpFont);
+ }
+}
+
+void LogFile::settingsAddRule()
+{
+ if (!lfs->ruleText->text().isEmpty()) {
+ lfs->ruleList->insertItem(lfs->ruleText->text(), -1);
+ lfs->ruleText->setText("");
+ }
+}
+
+void LogFile::settingsDeleteRule()
+{
+ lfs->ruleList->removeItem(lfs->ruleList->currentItem());
+ lfs->ruleText->setText("");
+}
+
+void LogFile::settingsChangeRule()
+{
+ lfs->ruleList->changeItem(lfs->ruleText->text(), lfs->ruleList->currentItem());
+ lfs->ruleText->setText("");
+}
+
+void LogFile::settingsRuleListSelected(int index)
+{
+ lfs->ruleText->setText(lfs->ruleList->text(index));
+}
+
+void LogFile::applySettings(void)
+{
+ QColorGroup cgroup = monitor->colorGroup();
+
+ cgroup.setColor(QColorGroup::Text, lfs->fgColor->color());
+ cgroup.setColor(QColorGroup::Base, lfs->bgColor->color());
+ monitor->setPalette(QPalette(cgroup, cgroup, cgroup));
+ monitor->setFont(lfs->fontButton->font());
+
+ filterRules.clear();
+ for (uint i = 0; i < lfs->ruleList->count(); i++)
+ filterRules.append(lfs->ruleList->text(i));
+
+ setTitle(lfs->title->text());
+
+ setModified(true);
+}
+
+void
+LogFile::applyStyle()
+{
+ QColorGroup cgroup = monitor->colorGroup();
+
+ cgroup.setColor(QColorGroup::Text, KSGRD::Style->firstForegroundColor());
+ cgroup.setColor(QColorGroup::Base, KSGRD::Style->backgroundColor());
+ monitor->setPalette(QPalette(cgroup, cgroup, cgroup));
+
+ setModified(true);
+}
+
+bool
+LogFile::restoreSettings(QDomElement& element)
+{
+ QFont font;
+ QColorGroup cgroup = monitor->colorGroup();
+
+ cgroup.setColor(QColorGroup::Text, restoreColor(element, "textColor", Qt::green));
+ cgroup.setColor(QColorGroup::Base, restoreColor(element, "backgroundColor", Qt::black));
+ monitor->setPalette(QPalette(cgroup, cgroup, cgroup));
+
+ addSensor(element.attribute("hostName"), element.attribute("sensorName"), (element.attribute("sensorType").isEmpty() ? "logfile" : element.attribute("sensorType")), element.attribute("title"));
+
+ font.fromString( element.attribute( "font" ) );
+ monitor->setFont(font);
+
+ QDomNodeList dnList = element.elementsByTagName("filter");
+ for (uint i = 0; i < dnList.count(); i++) {
+ QDomElement element = dnList.item(i).toElement();
+ filterRules.append(element.attribute("rule"));
+ }
+
+ SensorDisplay::restoreSettings(element);
+
+ setModified(false);
+
+ return true;
+}
+
+bool
+LogFile::saveSettings(QDomDocument& doc, QDomElement& element, bool save)
+{
+ element.setAttribute("hostName", sensors().at(0)->hostName());
+ element.setAttribute("sensorName", sensors().at(0)->name());
+ element.setAttribute("sensorType", sensors().at(0)->type());
+
+ element.setAttribute("font", monitor->font().toString());
+
+ saveColor(element, "textColor", monitor->colorGroup().text());
+ saveColor(element, "backgroundColor", monitor->colorGroup().base());
+
+ for (QStringList::Iterator it = filterRules.begin();
+ it != filterRules.end(); it++)
+ {
+ QDomElement filter = doc.createElement("filter");
+ filter.setAttribute("rule", (*it));
+ element.appendChild(filter);
+ }
+
+ SensorDisplay::saveSettings(doc, element);
+
+ if (save)
+ setModified(false);
+
+ return true;
+}
+
+void
+LogFile::updateMonitor()
+{
+ sendRequest(sensors().at(0)->hostName(),
+ QString("%1 %2" ).arg(sensors().at(0)->name()).arg(logFileID), 19);
+}
+
+void
+LogFile::answerReceived(int id, const QString& answer)
+{
+ /* We received something, so the sensor is probably ok. */
+ sensorError(id, false);
+
+ switch (id)
+ {
+ case 19: {
+ KSGRD::SensorTokenizer lines(answer, '\n');
+
+ for (uint i = 0; i < lines.count(); i++) {
+ if (monitor->count() == MAXLINES)
+ monitor->removeItem(0);
+
+ monitor->insertItem(lines[i], -1);
+
+ for (QStringList::Iterator it = filterRules.begin(); it != filterRules.end(); it++) {
+ QRegExp *expr = new QRegExp((*it).latin1());
+ if (expr->search(lines[i].latin1()) != -1) {
+ KNotifyClient::event(winId(), "pattern_match", QString("rule '%1' matched").arg((*it).latin1()));
+ }
+ delete expr;
+ }
+ }
+
+ monitor->setCurrentItem( monitor->count() - 1 );
+ monitor->ensureCurrentVisible();
+
+ break;
+ }
+
+ case 42: {
+ logFileID = answer.toULong();
+ break;
+ }
+ }
+}
+
+void
+LogFile::resizeEvent(QResizeEvent*)
+{
+ frame()->setGeometry(0, 0, this->width(), this->height());
+ monitor->setGeometry(10, 20, this->width() - 20, this->height() - 30);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/LogFile.h b/ksysguard/gui/SensorDisplayLib/LogFile.h
new file mode 100644
index 000000000..9428f934d
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/LogFile.h
@@ -0,0 +1,85 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _LogFile_h
+#define _LogFile_h
+
+#define MAXLINES 500
+
+class QFile;
+class QListBox;
+
+#include <qdom.h>
+#include <qpopupmenu.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include <SensorDisplay.h>
+
+#include "LogFileSettings.h"
+
+class LogFile : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+public:
+ LogFile(QWidget *parent = 0, const char *name = 0, const QString& title = 0);
+ ~LogFile(void);
+
+ bool addSensor(const QString& hostName, const QString& sensorName,
+ const QString& sensorType, const QString& sensorDescr);
+ void answerReceived(int id, const QString& answer);
+ void resizeEvent(QResizeEvent*);
+
+ bool restoreSettings(QDomElement& element);
+ bool saveSettings(QDomDocument& doc, QDomElement& element, bool save = true);
+
+ void updateMonitor(void);
+
+ void configureSettings(void);
+
+ virtual void timerEvent(QTimerEvent*)
+ {
+ updateMonitor();
+ }
+
+ virtual bool hasSettingsDialog() const
+ {
+ return (true);
+ }
+
+public slots:
+ void applySettings();
+ void applyStyle();
+
+ void settingsFontSelection();
+ void settingsAddRule();
+ void settingsDeleteRule();
+ void settingsChangeRule();
+ void settingsRuleListSelected(int index);
+
+private:
+ LogFileSettings* lfs;
+ QListBox* monitor;
+ QStringList filterRules;
+
+ unsigned long logFileID;
+};
+
+#endif // _LogFile_h
diff --git a/ksysguard/gui/SensorDisplayLib/LogFileSettings.ui b/ksysguard/gui/SensorDisplayLib/LogFileSettings.ui
new file mode 100644
index 000000000..b5dcff0ee
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/LogFileSettings.ui
@@ -0,0 +1,345 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>LogFileSettings</class>
+<author>Tobias Koenig &lt;tokoe@kde.org&gt;</author>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>LogFileSettings</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>438</width>
+ <height>320</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Log File Settings</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>TabWidget</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Text</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox8</cstring>
+ </property>
+ <property name="title">
+ <string>Title</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>title</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>styleGroup</cstring>
+ </property>
+ <property name="title">
+ <string>Colors</string>
+ </property>
+ <property name="exclusive">
+ <bool>true</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Foreground color:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>fgColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>bgColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox11</cstring>
+ </property>
+ <property name="title">
+ <string>Font</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer14</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>fontButton</cstring>
+ </property>
+ <property name="text">
+ <string>Select Font...</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Filter</string>
+ </attribute>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout7</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>ruleText</cstring>
+ </property>
+ </widget>
+ <widget class="QListBox">
+ <property name="name">
+ <cstring>ruleList</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout9</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>addButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Add</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>deleteButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Delete</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>changeButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Change</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer7_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>okButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>applyButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Apply</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>cancelButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<tabstops>
+ <tabstop>okButton</tabstop>
+ <tabstop>applyButton</tabstop>
+ <tabstop>cancelButton</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in implementation">kdialog.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+</UI>
diff --git a/ksysguard/gui/SensorDisplayLib/Makefile.am b/ksysguard/gui/SensorDisplayLib/Makefile.am
new file mode 100644
index 000000000..a1327a4ac
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/Makefile.am
@@ -0,0 +1,39 @@
+
+# set the include path for X, qt and KDE
+INCLUDES= -I$(srcdir)/.. -I$(srcdir)/../ksgrd -I../ksgrd $(all_includes)
+
+noinst_LTLIBRARIES = libsensordisplays.la
+
+libsensordisplays_la_LDFLAGS = $(all_libraries) -no-undefined
+libsensordisplays_la_LIBADD = ../ksgrd/libksgrd.la $(LIB_KIO)
+
+# Which sources should be compiled for the sensor display lib.
+libsensordisplays_la_SOURCES = \
+ SensorDisplay.cc \
+ BarGraph.cc \
+ DancingBars.cc \
+ DancingBarsSettings.cc \
+ DummyDisplay.cc \
+ FancyPlotter.cc \
+ FancyPlotterSettings.cc \
+ ListView.cc \
+ LogFile.cc \
+ MultiMeter.cc \
+ MultiMeterSettings.cc \
+ ProcessController.cc \
+ ProcessList.cc \
+ ReniceDlg.cc \
+ SensorLogger.cc \
+ SensorLoggerDlg.cc \
+ SensorLoggerSettings.cc \
+ ListViewSettings.cc \
+ SignalPlotter.cc \
+ ListViewSettingsWidget.ui \
+ LogFileSettings.ui \
+ MultiMeterSettingsWidget.ui \
+ SensorLoggerDlgWidget.ui \
+ SensorLoggerSettingsWidget.ui
+
+# just to make sure, automake makes them
+METASOURCES = AUTO
+
diff --git a/ksysguard/gui/SensorDisplayLib/MultiMeter.cc b/ksysguard/gui/SensorDisplayLib/MultiMeter.cc
new file mode 100644
index 000000000..14e805b9d
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/MultiMeter.cc
@@ -0,0 +1,258 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000, 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <math.h>
+#include <stdlib.h>
+
+#include <qdom.h>
+#include <qlcdnumber.h>
+#include <qtooltip.h>
+
+#include <kdebug.h>
+
+#include <ksgrd/SensorManager.h>
+#include <ksgrd/StyleEngine.h>
+
+#include "MultiMeter.moc"
+#include "MultiMeterSettings.h"
+
+MultiMeter::MultiMeter(QWidget* parent, const char* name,
+ const QString& title, double, double, bool nf, bool isApplet)
+ : KSGRD::SensorDisplay(parent, name, title, nf, isApplet)
+{
+ setShowUnit( true );
+ lowerLimit = upperLimit = 0;
+ lowerLimitActive = upperLimitActive = false;
+
+ normalDigitColor = KSGRD::Style->firstForegroundColor();
+ alarmDigitColor = KSGRD::Style->alarmColor();
+ if (noFrame())
+ lcd = new QLCDNumber(this, "meterLCD");
+ else
+ lcd = new QLCDNumber(frame(), "meterLCD");
+ Q_CHECK_PTR(lcd);
+ lcd->setSegmentStyle(QLCDNumber::Filled);
+ setDigitColor(KSGRD::Style->backgroundColor());
+ lcd->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,
+ QSizePolicy::Expanding, false));
+
+ setBackgroundColor(KSGRD::Style->backgroundColor());
+ /* All RMB clicks to the lcd widget will be handled by
+ * SensorDisplay::eventFilter. */
+ lcd->installEventFilter(this);
+
+ setPlotterWidget(lcd);
+
+ setMinimumSize(5, 5);
+ setModified(false);
+}
+
+bool
+MultiMeter::addSensor(const QString& hostName, const QString& sensorName,
+ const QString& sensorType, const QString& title)
+{
+ if (sensorType != "integer" && sensorType != "float")
+ return (false);
+
+ registerSensor(new KSGRD::SensorProperties(hostName, sensorName, sensorType, title));
+
+ /* To differentiate between answers from value requests and info
+ * requests we use 100 for info requests. */
+ sendRequest(hostName, sensorName + "?", 100);
+
+ QToolTip::remove(lcd);
+ QToolTip::add(lcd, QString("%1:%2").arg(hostName).arg(sensorName));
+
+ setModified(true);
+ return (true);
+}
+
+void
+MultiMeter::answerReceived(int id, const QString& answer)
+{
+ /* We received something, so the sensor is probably ok. */
+ sensorError(id, false);
+
+ if (id == 100)
+ {
+ KSGRD::SensorIntegerInfo info(answer);
+ setUnit(KSGRD::SensorMgr->translateUnit(info.unit()));
+ }
+ else
+ {
+ double val = answer.toDouble();
+ int digits = (int) log10(val) + 1;
+
+ if (noFrame())
+ if (digits > 4)
+ lcd->setNumDigits(4);
+ else
+ lcd->setNumDigits(digits);
+ else
+ {
+ if (digits > 5)
+ lcd->setNumDigits(digits);
+ else
+ lcd->setNumDigits(5);
+ }
+
+ lcd->display(val);
+ if (lowerLimitActive && val < lowerLimit)
+ {
+ setDigitColor(alarmDigitColor);
+ }
+ else if (upperLimitActive && val > upperLimit)
+ {
+ setDigitColor(alarmDigitColor);
+ }
+ else
+ setDigitColor(normalDigitColor);
+ }
+}
+
+void
+MultiMeter::resizeEvent(QResizeEvent*)
+{
+ if (noFrame())
+ lcd->setGeometry(0, 0, width(), height());
+ else
+ frame()->setGeometry(0, 0, width(), height());
+}
+
+bool
+MultiMeter::restoreSettings(QDomElement& element)
+{
+ lowerLimitActive = element.attribute("lowerLimitActive").toInt();
+ lowerLimit = element.attribute("lowerLimit").toLong();
+ upperLimitActive = element.attribute("upperLimitActive").toInt();
+ upperLimit = element.attribute("upperLimit").toLong();
+
+ normalDigitColor = restoreColor(element, "normalDigitColor",
+ KSGRD::Style->firstForegroundColor());
+ alarmDigitColor = restoreColor(element, "alarmDigitColor",
+ KSGRD::Style->alarmColor());
+ setBackgroundColor(restoreColor(element, "backgroundColor",
+ KSGRD::Style->backgroundColor()));
+
+ addSensor(element.attribute("hostName"), element.attribute("sensorName"), (element.attribute("sensorType").isEmpty() ? "integer" : element.attribute("sensorType")), "");
+
+ SensorDisplay::restoreSettings(element);
+
+ setModified(false);
+
+ return (true);
+}
+
+bool
+MultiMeter::saveSettings(QDomDocument& doc, QDomElement& element, bool save)
+{
+ element.setAttribute("hostName", sensors().at(0)->hostName());
+ element.setAttribute("sensorName", sensors().at(0)->name());
+ element.setAttribute("sensorType", sensors().at(0)->type());
+ element.setAttribute("showUnit", showUnit());
+ element.setAttribute("lowerLimitActive", (int) lowerLimitActive);
+ element.setAttribute("lowerLimit", (int) lowerLimit);
+ element.setAttribute("upperLimitActive", (int) upperLimitActive);
+ element.setAttribute("upperLimit", (int) upperLimit);
+
+ saveColor(element, "normalDigitColor", normalDigitColor);
+ saveColor(element, "alarmDigitColor", alarmDigitColor);
+ saveColor(element, "backgroundColor", lcd->backgroundColor());
+
+ SensorDisplay::saveSettings(doc, element);
+
+ if (save)
+ setModified(false);
+
+ return (true);
+}
+
+void
+MultiMeter::configureSettings()
+{
+ mms = new MultiMeterSettings(this, "MultiMeterSettings");
+ Q_CHECK_PTR(mms);
+ mms->setTitle(title());
+ mms->setShowUnit(showUnit());
+ mms->setLowerLimitActive(lowerLimitActive);
+ mms->setLowerLimit(lowerLimit);
+ mms->setUpperLimitActive(upperLimitActive);
+ mms->setUpperLimit(upperLimit);
+ mms->setNormalDigitColor(normalDigitColor);
+ mms->setAlarmDigitColor(alarmDigitColor);
+ mms->setMeterBackgroundColor(lcd->backgroundColor());
+
+ connect(mms, SIGNAL(applyClicked()), SLOT(applySettings()));
+
+ if (mms->exec())
+ applySettings();
+
+ delete mms;
+ mms = 0;
+}
+
+void
+MultiMeter::applySettings()
+{
+ setShowUnit( mms->showUnit() );
+ setTitle(mms->title());
+ lowerLimitActive = mms->lowerLimitActive();
+ lowerLimit = mms->lowerLimit();
+ upperLimitActive = mms->upperLimitActive();
+ upperLimit = mms->upperLimit();
+
+ normalDigitColor = mms->normalDigitColor();
+ alarmDigitColor = mms->alarmDigitColor();
+ setBackgroundColor(mms->meterBackgroundColor());
+
+ repaint();
+ setModified(true);
+}
+
+void
+MultiMeter::applyStyle()
+{
+ normalDigitColor = KSGRD::Style->firstForegroundColor();
+ setBackgroundColor(KSGRD::Style->backgroundColor());
+ repaint();
+ setModified(true);
+}
+
+void
+MultiMeter::setDigitColor(const QColor& col)
+{
+ QPalette p = lcd->palette();
+ p.setColor(QColorGroup::Foreground, col);
+ lcd->setPalette(p);
+}
+
+void
+MultiMeter::setBackgroundColor(const QColor& col)
+{
+ lcd->setBackgroundColor(col);
+
+ QPalette p = lcd->palette();
+ p.setColor(QColorGroup::Light, col);
+ p.setColor(QColorGroup::Dark, col);
+ lcd->setPalette(p);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/MultiMeter.h b/ksysguard/gui/SensorDisplayLib/MultiMeter.h
new file mode 100644
index 000000000..58d2477c1
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/MultiMeter.h
@@ -0,0 +1,79 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef _MultiMeter_h_
+#define _MultiMeter_h_
+
+#include <SensorDisplay.h>
+
+class QGroupBox;
+class QLCDNumber;
+class QLabel;
+class MultiMeterSettings;
+
+class MultiMeter : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+
+public:
+ MultiMeter(QWidget* parent = 0, const char* name = 0,
+ const QString& = QString::null, double min = 0, double max = 0, bool nf = false, bool isApplet = false);
+ virtual ~MultiMeter()
+ {
+ }
+
+ bool addSensor(const QString& hostName, const QString& sensorName,
+ const QString& sensorType, const QString& sensorDescr);
+ void answerReceived(int id, const QString& answer);
+ void resizeEvent(QResizeEvent*);
+
+ bool restoreSettings(QDomElement& element);
+ bool saveSettings(QDomDocument& doc, QDomElement& element, bool save = true);
+
+ virtual bool hasSettingsDialog() const
+ {
+ return (true);
+ }
+
+ void configureSettings();
+
+public slots:
+ void applySettings();
+ void applyStyle();
+
+private:
+ void setDigitColor(const QColor& col);
+ void setBackgroundColor(const QColor& col);
+
+ QLCDNumber* lcd;
+ QColor normalDigitColor;
+ QColor alarmDigitColor;
+
+ MultiMeterSettings* mms;
+ bool lowerLimitActive;
+ double lowerLimit;
+ bool upperLimitActive;
+ double upperLimit;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/MultiMeterSettings.cc b/ksysguard/gui/SensorDisplayLib/MultiMeterSettings.cc
new file mode 100644
index 000000000..9114c583b
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/MultiMeterSettings.cc
@@ -0,0 +1,127 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "MultiMeterSettings.h"
+#include "MultiMeterSettingsWidget.h"
+
+#include <klocale.h>
+
+MultiMeterSettings::MultiMeterSettings( QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, i18n( "Multimeter Settings" ),
+ Ok|Apply|Cancel, Ok, true )
+{
+ m_settingsWidget = new MultiMeterSettingsWidget( this, "m_settingsWidget" );
+ setMainWidget( m_settingsWidget );
+}
+
+QString MultiMeterSettings::title()
+{
+ return m_settingsWidget->title();
+}
+
+bool MultiMeterSettings::showUnit()
+{
+ return m_settingsWidget->showUnit();
+}
+
+bool MultiMeterSettings::lowerLimitActive()
+{
+ return m_settingsWidget->lowerLimitActive();
+}
+
+bool MultiMeterSettings::upperLimitActive()
+{
+ return m_settingsWidget->upperLimitActive();
+}
+
+double MultiMeterSettings::lowerLimit()
+{
+ return m_settingsWidget->lowerLimit();
+}
+
+double MultiMeterSettings::upperLimit()
+{
+ return m_settingsWidget->upperLimit();
+}
+
+QColor MultiMeterSettings::normalDigitColor()
+{
+ return m_settingsWidget->normalDigitColor();
+}
+
+QColor MultiMeterSettings::alarmDigitColor()
+{
+ return m_settingsWidget->alarmDigitColor();
+}
+
+QColor MultiMeterSettings::meterBackgroundColor()
+{
+ return m_settingsWidget->meterBackgroundColor();
+}
+
+void MultiMeterSettings::setTitle( const QString &title )
+{
+ m_settingsWidget->setTitle( title );
+}
+
+void MultiMeterSettings::setShowUnit( bool b )
+{
+ m_settingsWidget->setShowUnit( b );
+}
+
+void MultiMeterSettings::setLowerLimitActive( bool b )
+{
+ m_settingsWidget->setLowerLimitActive( b );
+}
+
+void MultiMeterSettings::setUpperLimitActive( bool b )
+{
+ m_settingsWidget->setUpperLimitActive( b );
+}
+
+void MultiMeterSettings::setLowerLimit( double limit )
+{
+ m_settingsWidget->setLowerLimit( limit );
+}
+
+void MultiMeterSettings::setUpperLimit( double limit )
+{
+ m_settingsWidget->setUpperLimit( limit );
+}
+
+void MultiMeterSettings::setNormalDigitColor( const QColor &c )
+{
+ m_settingsWidget->setNormalDigitColor( c );
+}
+
+void MultiMeterSettings::setAlarmDigitColor( const QColor &c )
+{
+ m_settingsWidget->setAlarmDigitColor( c );
+}
+
+void MultiMeterSettings::setMeterBackgroundColor( const QColor &c )
+{
+ m_settingsWidget->setMeterBackgroundColor( c );
+}
+
+#include "MultiMeterSettings.moc"
+
+/* vim: et sw=2 ts=2
+*/
+
diff --git a/ksysguard/gui/SensorDisplayLib/MultiMeterSettings.h b/ksysguard/gui/SensorDisplayLib/MultiMeterSettings.h
new file mode 100644
index 000000000..516a02128
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/MultiMeterSettings.h
@@ -0,0 +1,68 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or ( at your option ) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef MULTIMETERSETTINGS_H
+#define MULTIMETERSETTINGS_H
+
+#include <kdialogbase.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+
+class MultiMeterSettingsWidget;
+
+class MultiMeterSettings : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+
+ MultiMeterSettings( QWidget *parent=0, const char *name=0 );
+
+ QString title();
+ bool showUnit();
+ bool lowerLimitActive();
+ bool upperLimitActive();
+ double lowerLimit();
+ double upperLimit();
+ QColor normalDigitColor();
+ QColor alarmDigitColor();
+ QColor meterBackgroundColor();
+
+ void setTitle( const QString & );
+ void setShowUnit( bool );
+ void setLowerLimitActive( bool );
+ void setUpperLimitActive( bool );
+ void setLowerLimit( double );
+ void setUpperLimit( double );
+ void setNormalDigitColor( const QColor & );
+ void setAlarmDigitColor( const QColor & );
+ void setMeterBackgroundColor( const QColor & );
+
+ private:
+
+ MultiMeterSettingsWidget *m_settingsWidget;
+};
+
+#endif // MULTIMETERSETTINGS_H
+
+/* vim: et sw=2 ts=2
+*/
+
diff --git a/ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui b/ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui
new file mode 100644
index 000000000..7ecdef88f
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui
@@ -0,0 +1,475 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>MultiMeterSettingsWidget</class>
+<comment>MultiMeterSettingsWidget</comment>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>MultiMeterSettingsWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>378</width>
+ <height>229</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox7</cstring>
+ </property>
+ <property name="title">
+ <string>Title</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLineEdit" row="0" column="0">
+ <property name="name">
+ <cstring>m_title</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the title of the display here.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="1">
+ <property name="name">
+ <cstring>m_showUnit</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Show unit</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enable this to append the unit to the title of the display.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>TabWidget2</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Alarms</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>GroupBox1_2</cstring>
+ </property>
+ <property name="title">
+ <string>Alarm for Maximum Value</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>m_upperLimitActive</cstring>
+ </property>
+ <property name="text">
+ <string>E&amp;nable alarm</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enable the maximum value alarm.</string>
+ </property>
+ </widget>
+ <spacer row="0" column="1">
+ <property name="name">
+ <cstring>Spacer1_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="0" column="2">
+ <property name="name">
+ <cstring>m_lblUpperLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Upper limit:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="3">
+ <property name="name">
+ <cstring>m_upperLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Alarm for Minimum Value</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>m_lowerLimitActive</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Enable alarm</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enable the minimum value alarm.</string>
+ </property>
+ </widget>
+ <spacer row="0" column="1">
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="0" column="2">
+ <property name="name">
+ <cstring>m_lblLowerLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Lower limit:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="3">
+ <property name="name">
+ <cstring>m_lowerLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Colors</string>
+ </attribute>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Normal digit color:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Alarm digit color:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_normalDigitColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_alarmDigitColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_backgroundColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KColorButton</class>
+ <header location="local">kcolorbutton.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ <signal>destroyed()</signal>
+ <signal>destroyed(QObject*)</signal>
+ <signal>pressed()</signal>
+ <signal>released()</signal>
+ <signal>clicked()</signal>
+ <signal>toggled(bool)</signal>
+ <signal>stateChanged(int)</signal>
+ <signal>changed(const QColor&amp;)</signal>
+ <slot access="public" specifier="">deleteLater()</slot>
+ <slot access="private" specifier="">cleanupEventFilter(QObject*)</slot>
+ <slot access="public" specifier="">setEnabled(bool)</slot>
+ <slot access="public" specifier="">setDisabled(bool)</slot>
+ <slot access="public" specifier="">setCaption(const QString&amp;)</slot>
+ <slot access="public" specifier="">setIcon(const QPixmap&amp;)</slot>
+ <slot access="public" specifier="">setIconText(const QString&amp;)</slot>
+ <slot access="public" specifier="">setMouseTracking(bool)</slot>
+ <slot access="public" specifier="">setFocus()</slot>
+ <slot access="public" specifier="">clearFocus()</slot>
+ <slot access="public" specifier="">setUpdatesEnabled(bool)</slot>
+ <slot access="public" specifier="">update()</slot>
+ <slot access="public" specifier="">update(int,int,int,int)</slot>
+ <slot access="public" specifier="">update(const QRect&amp;)</slot>
+ <slot access="public" specifier="">repaint()</slot>
+ <slot access="public" specifier="">repaint(bool)</slot>
+ <slot access="public" specifier="">repaint(int,int,int,int)</slot>
+ <slot access="public" specifier="">repaint(int,int,int,int,bool)</slot>
+ <slot access="public" specifier="">repaint(const QRect&amp;)</slot>
+ <slot access="public" specifier="">repaint(const QRect&amp;,bool)</slot>
+ <slot access="public" specifier="">repaint(const QRegion&amp;)</slot>
+ <slot access="public" specifier="">repaint(const QRegion&amp;,bool)</slot>
+ <slot access="public" specifier="">show()</slot>
+ <slot access="public" specifier="">hide()</slot>
+ <slot access="public" specifier="">setShown(bool)</slot>
+ <slot access="public" specifier="">setHidden(bool)</slot>
+ <slot access="public" specifier="">iconify()</slot>
+ <slot access="public" specifier="">showMinimized()</slot>
+ <slot access="public" specifier="">showMaximized()</slot>
+ <slot access="public" specifier="">showFullScreen()</slot>
+ <slot access="public" specifier="">showNormal()</slot>
+ <slot access="public" specifier="">polish()</slot>
+ <slot access="public" specifier="">constPolish()</slot>
+ <slot access="public" specifier="">close()</slot>
+ <slot access="public" specifier="">raise()</slot>
+ <slot access="public" specifier="">lower()</slot>
+ <slot access="public" specifier="">stackUnder(QWidget*)</slot>
+ <slot access="public" specifier="">move(int,int)</slot>
+ <slot access="public" specifier="">move(const QPoint&amp;)</slot>
+ <slot access="public" specifier="">resize(int,int)</slot>
+ <slot access="public" specifier="">resize(const QSize&amp;)</slot>
+ <slot access="public" specifier="">setGeometry(int,int,int,int)</slot>
+ <slot access="public" specifier="">setGeometry(const QRect&amp;)</slot>
+ <slot access="public" specifier="">adjustSize()</slot>
+ <slot access="private" specifier="">focusProxyDestroyed()</slot>
+ <slot access="public" specifier="">animateClick()</slot>
+ <slot access="public" specifier="">toggle()</slot>
+ <slot access="private" specifier="">animateTimeout()</slot>
+ <slot access="private" specifier="">autoRepeatTimeout()</slot>
+ <slot access="private" specifier="">emulateClick()</slot>
+ <slot access="public" specifier="">setOn(bool)</slot>
+ <slot access="private" specifier="">popupPressed()</slot>
+ <slot access="protected" specifier="">chooseColor()</slot>
+ <property type="CString">name</property>
+ <property type="Bool">enabled</property>
+ <property type="Rect">geometry</property>
+ <property type="SizePolicy">sizePolicy</property>
+ <property type="Size">minimumSize</property>
+ <property type="Size">maximumSize</property>
+ <property type="Size">sizeIncrement</property>
+ <property type="Size">baseSize</property>
+ <property type="Color">paletteForegroundColor</property>
+ <property type="Color">paletteBackgroundColor</property>
+ <property type="Pixmap">paletteBackgroundPixmap</property>
+ <property type="Palette">palette</property>
+ <property type="BackgroundOrigin">backgroundOrigin</property>
+ <property type="Font">font</property>
+ <property type="Cursor">cursor</property>
+ <property type="String">caption</property>
+ <property type="Pixmap">icon</property>
+ <property type="String">iconText</property>
+ <property type="Bool">mouseTracking</property>
+ <property type="FocusPolicy">focusPolicy</property>
+ <property type="Bool">acceptDrops</property>
+ <property type="String">text</property>
+ <property type="Pixmap">pixmap</property>
+ <property type="KeySequence">accel</property>
+ <property type="Bool">autoRepeat</property>
+ <property type="Bool">autoDefault</property>
+ <property type="Bool">default</property>
+ <property type="IconSet">iconSet</property>
+ <property type="Bool">toggleButton</property>
+ <property type="Bool">on</property>
+ <property type="Bool">flat</property>
+ <property type="Bool">autoMask</property>
+ <property type="Color">color</property>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="827">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000030249444154789cad953188db6614c77f0e1a9ee0029fc10509ae20c30de7d1852e4733f846d30c2e74483aa5812ea54bba35590a693a640e1d0e0e0ae16e282443e1321cd499eca5d4072951e10af26090e00ef40d013d88411d3ed967f91228e4de22f4e97dbff7d7ff7b7a6a9465c9221a8d0657116559d258801ffcf080ce76076b6d996629f99bfc7f41acb524a709e33fc73067a9cc5b287dfaeb53c28f294dbb2042d1b9228b0ccf25fbd5b598afec9ec33401dd13262fb50407f7562a97a65d90d923f23c0114df578ab7423613f2730584660bda6d453640ab02721dc210262b6fb204a7594a8456508bef0baf5f1986bf5be2130b68952944dbc2eec0b0d303e66e5da46ed1129cbfc9d1b92ea1a3211cfc92b94d1b427bdb201ea43365fa8fb2ff73463635dcbe232b45df01765ac0f7e1f52ba9a04aeff380fe40687e0488a21a327a5170b097717498110411fd2f9b80ad81afad9729de0ac3e77609fdea1ba1195a104b7e26fcf13ca73ff0f9fabb00109e1d5aecf9bac4f55b0fb29910ff6d31c6d01f0878163c506bd87facc42796fc0ceede6b323e76b971ec6c7abf62a84e5f09a3eaf52be89347ee104d4bf8e48620a6a0d37527964eb532f23d60d7a72e41c4799aa786278f94f8c4151481f6a6ef9e7b0b985cb2e292e266cb25263345b5c9f8254ea91182c090cd2c0fefa7c49326e9a9eb8630f2d731f53ac5dc357fb4254cff55462f0afab77cf233c3ce0d21dcf479781fb2a9e5a76f135415d312badd8274566fb94b8a6503fa0303c0c15ec6e8b8e0eebd26dd1e44dd9cef7f6c630283b5169d2bbb838070eb92e07567dc67bad3836c66787698b1ff38637c2c743a0202e9698a9eeb72e75f434b723344bcfa87b23a2b2ee0285fdc114c1071f49beb86f8e4a2b86909fd41c46868b1aaa882b5752b96e0e434619a00d72fe0fd81b0d30b8963433a75ebe1a64ff7d382700b766f864ea497134feae04659966ec07b94ddcf8430ac5a6dce7264caa20d6bc629e209d6423c51d24cb16eb434ea6017251f16f541ffae071f1ad7c0fda3ae3a967d7c95f0b22cf90f71e859c3d57176e60000000049454e44ae426082</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>m_lowerLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_lowerLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_upperLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_upperLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_lowerLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_lblLowerLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_upperLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_lblUpperLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="global" impldecl="in implementation">kdialog.h</include>
+ <include location="global" impldecl="in implementation">knumvalidator.h</include>
+ <include location="local" impldecl="in implementation">MultiMeterSettingsWidget.ui.h</include>
+</includes>
+<slots>
+ <slot>setMeterBackgroundColor( const QColor &amp; c )</slot>
+</slots>
+<functions>
+ <function access="private" specifier="non virtual">init()</function>
+ <function specifier="non virtual" returnType="QString">title()</function>
+ <function specifier="non virtual" returnType="bool">showUnit()</function>
+ <function returnType="bool">lowerLimitActive()</function>
+ <function specifier="non virtual" returnType="double">lowerLimit()</function>
+ <function returnType="bool">upperLimitActive()</function>
+ <function returnType="double">upperLimit()</function>
+ <function specifier="non virtual" returnType="QColor">normalDigitColor()</function>
+ <function specifier="non virtual" returnType="QColor">alarmDigitColor()</function>
+ <function returnType="QColor">meterBackgroundColor()</function>
+ <function specifier="non virtual">setTitle( const QString &amp; s )</function>
+ <function specifier="non virtual">setShowUnit( bool b )</function>
+ <function specifier="non virtual">setLowerLimitActive( bool b )</function>
+ <function specifier="non virtual">setLowerLimit( double d )</function>
+ <function specifier="non virtual">setUpperLimitActive( bool b )</function>
+ <function specifier="non virtual">setUpperLimit( double d )</function>
+ <function specifier="non virtual">setNormalDigitColor( const QColor &amp; c )</function>
+ <function specifier="non virtual">setAlarmDigitColor( const QColor &amp; c )</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>kcolorbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui.h b/ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui.h
new file mode 100644
index 000000000..81d6e73f6
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/MultiMeterSettingsWidget.ui.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+void MultiMeterSettingsWidget::init()
+{
+ m_lowerLimit->setValidator(new KDoubleValidator(m_lowerLimit));
+ m_upperLimit->setValidator(new KDoubleValidator(m_upperLimit));
+
+ m_title->setFocus();
+}
+
+QString MultiMeterSettingsWidget::title()
+{
+ return m_title->text();
+}
+
+
+bool MultiMeterSettingsWidget::showUnit()
+{
+ return m_showUnit->isChecked();
+}
+
+
+bool MultiMeterSettingsWidget::lowerLimitActive()
+{
+ return m_lowerLimitActive->isChecked();
+}
+
+
+double MultiMeterSettingsWidget::lowerLimit()
+{
+ return m_lowerLimit->text().toDouble();
+}
+
+
+bool MultiMeterSettingsWidget::upperLimitActive()
+{
+ return m_upperLimitActive->isChecked();
+}
+
+
+double MultiMeterSettingsWidget::upperLimit()
+{
+ return m_upperLimit->text().toDouble();
+}
+
+
+QColor MultiMeterSettingsWidget::normalDigitColor()
+{
+ return m_normalDigitColor->color();
+}
+
+
+QColor MultiMeterSettingsWidget::alarmDigitColor()
+{
+ return m_alarmDigitColor->color();
+}
+
+
+QColor MultiMeterSettingsWidget::meterBackgroundColor()
+{
+ return m_backgroundColor->color();
+}
+
+
+void MultiMeterSettingsWidget::setTitle( const QString &s )
+{
+ m_title->setText(s);
+}
+
+
+void MultiMeterSettingsWidget::setShowUnit( bool b )
+{
+ m_showUnit->setChecked(b);
+}
+
+
+void MultiMeterSettingsWidget::setLowerLimitActive( bool b )
+{
+ m_lowerLimitActive->setChecked(b);
+}
+
+
+void MultiMeterSettingsWidget::setLowerLimit( double d )
+{
+ m_lowerLimit->setText(QString("%1").arg(d));
+}
+
+
+void MultiMeterSettingsWidget::setUpperLimitActive( bool b )
+{
+ m_upperLimitActive->setChecked(b);
+}
+
+
+void MultiMeterSettingsWidget::setUpperLimit( double d )
+{
+ m_upperLimit->setText(QString("%1").arg(d));
+}
+
+
+void MultiMeterSettingsWidget::setNormalDigitColor( const QColor &c )
+{
+ m_normalDigitColor->setColor(c);
+}
+
+
+void MultiMeterSettingsWidget::setAlarmDigitColor( const QColor &c )
+{
+ m_alarmDigitColor->setColor(c);
+}
+
+
+void MultiMeterSettingsWidget::setMeterBackgroundColor( const QColor &c )
+{
+ m_backgroundColor->setColor(c);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/ProcessController.cc b/ksysguard/gui/SensorDisplayLib/ProcessController.cc
new file mode 100644
index 000000000..b9fcd4f06
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ProcessController.cc
@@ -0,0 +1,472 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms version 2 of of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <assert.h>
+
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdialogbase.h>
+#include <klistviewsearchline.h>
+
+#include <ksgrd/SensorManager.h>
+
+#include "ProcessController.moc"
+#include "SignalIDs.h"
+
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qgroupbox.h>
+#include <qlayout.h>
+
+#include <kapplication.h>
+#include <kpushbutton.h>
+
+
+
+ProcessController::ProcessController(QWidget* parent, const char* name, const QString &title, bool nf)
+ : KSGRD::SensorDisplay(parent, name, title, nf)
+{
+ dict.setAutoDelete(true);
+ dict.insert("Name", new QString(i18n("Name")));
+ dict.insert("PID", new QString(i18n("PID")));
+ dict.insert("PPID", new QString(i18n("PPID")));
+ dict.insert("UID", new QString(i18n("UID")));
+ dict.insert("GID", new QString(i18n("GID")));
+ dict.insert("Status", new QString(i18n("Status")));
+ dict.insert("User%", new QString(i18n("User%")));
+ dict.insert("System%", new QString(i18n("System%")));
+ dict.insert("Nice", new QString(i18n("Nice")));
+ dict.insert("VmSize", new QString(i18n("VmSize")));
+ dict.insert("VmRss", new QString(i18n("VmRss")));
+ dict.insert("Login", new QString(i18n("Login")));
+ dict.insert("Command", new QString(i18n("Command")));
+
+ // Setup the geometry management.
+ gm = new QVBoxLayout(this, 10);
+ Q_CHECK_PTR(gm);
+ gm->addSpacing(15);
+
+ gmSearch = new QHBoxLayout();
+ Q_CHECK_PTR(gmSearch);
+ gm->addLayout(gmSearch, 0);
+
+ // Create the table that lists the processes.
+ pList = new ProcessList(this, "pList");
+ Q_CHECK_PTR(pList);
+ pList->setShowSortIndicator(true);
+ pListSearchLine = new KListViewSearchLineWidget(pList, this, "process_list_search_line");
+ gmSearch->addWidget(pListSearchLine, 1);
+
+ connect(pList, SIGNAL(killProcess(int, int)),
+ this, SLOT(killProcess(int, int)));
+ connect(pList, SIGNAL(reniceProcess(const QValueList<int> &, int)),
+ this, SLOT(reniceProcess(const QValueList<int> &, int)));
+ connect(pList, SIGNAL(listModified(bool)),
+ this, SLOT(setModified(bool)));
+
+ /* Create the combo box to configure the process filter. The
+ * cbFilter must be created prior to constructing pList as the
+ * pList constructor sets cbFilter to its start value. */
+ cbFilter = new QComboBox(this, "pList_cbFilter");
+ Q_CHECK_PTR(cbFilter);
+ gmSearch->addWidget(cbFilter,0);
+ cbFilter->insertItem(i18n("All Processes"), 0);
+ cbFilter->insertItem(i18n("System Processes"), 1);
+ cbFilter->insertItem(i18n("User Processes"), 2);
+ cbFilter->insertItem(i18n("Own Processes"), 3);
+ cbFilter->setMinimumSize(cbFilter->sizeHint());
+ // Create the check box to switch between tree view and list view.
+ xbTreeView = new QCheckBox(i18n("&Tree"), this, "xbTreeView");
+ Q_CHECK_PTR(xbTreeView);
+ xbTreeView->setMinimumSize(xbTreeView->sizeHint());
+ connect(xbTreeView, SIGNAL(toggled(bool)),
+ this, SLOT(setTreeView(bool)));
+
+
+ /* When the both cbFilter and pList are constructed we can connect the
+ * missing link. */
+ connect(cbFilter, SIGNAL(activated(int)),
+ this, SLOT(filterModeChanged(int)));
+
+ // Create the 'Refresh' button.
+ bRefresh = new KPushButton( KGuiItem( i18n( "&Refresh" ), "reload" ),
+ this, "bRefresh" );
+ Q_CHECK_PTR(bRefresh);
+ bRefresh->setMinimumSize(bRefresh->sizeHint());
+ connect(bRefresh, SIGNAL(clicked()), this, SLOT(updateList()));
+
+ // Create the 'Kill' button.
+ bKill = new KPushButton(i18n("&Kill"), this, "bKill");
+ Q_CHECK_PTR(bKill);
+ bKill->setMinimumSize(bKill->sizeHint());
+ connect(bKill, SIGNAL(clicked()), this, SLOT(killProcess()));
+ /* Disable the kill button until we know that the daemon supports the
+ * kill command. */
+ bKill->setEnabled(false);
+ killSupported = false;
+
+ gm->addWidget(pList, 1);
+
+ gm1 = new QHBoxLayout();
+ Q_CHECK_PTR(gm1);
+ gm->addLayout(gm1, 0);
+ gm1->addStretch();
+ gm1->addWidget(xbTreeView);
+ gm1->addStretch();
+ gm1->addWidget(bRefresh);
+ gm1->addStretch();
+ gm1->addWidget(bKill);
+ gm1->addStretch();
+ gm->addSpacing(5);
+
+ gm->activate();
+
+ setPlotterWidget(pList);
+
+ setMinimumSize(sizeHint());
+ fixTabOrder();
+}
+
+void ProcessController::setSearchFocus() {
+ //stupid search line widget. See rant in fixTabOrder
+ if(!pListSearchLine->searchLine())
+ QTimer::singleShot(100, this, SLOT(setSearchFocus()));
+ else {
+ pListSearchLine->searchLine()->setFocus();
+ }
+}
+void ProcessController::fixTabOrder() {
+
+ //Wow, I hate this search line widget so much.
+ //It creates the searchline in a singleshot timer. This makes it totally unpredictable when searchLine is actually valid.
+ //So we set up singleshot timer and call ourselves over and over until it's ready.
+ //
+ //Did i mention I hate this?
+ if(!pListSearchLine->searchLine())
+ QTimer::singleShot(100, this, SLOT(fixTabOrder()));
+ else {
+ setTabOrder(pListSearchLine->searchLine(), cbFilter);
+ setTabOrder(cbFilter, pList);
+ setTabOrder(pList, xbTreeView);
+ setTabOrder(xbTreeView, bRefresh);
+ setTabOrder(bRefresh, bKill);
+ }
+}
+
+void
+ProcessController::resizeEvent(QResizeEvent* ev)
+{
+ if(frame())
+ frame()->setGeometry(0, 0, width(), height());
+
+ QWidget::resizeEvent(ev);
+}
+
+bool
+ProcessController::addSensor(const QString& hostName,
+ const QString& sensorName,
+ const QString& sensorType,
+ const QString& title)
+{
+ if (sensorType != "table")
+ return (false);
+
+ registerSensor(new KSGRD::SensorProperties(hostName, sensorName, sensorType, title));
+ /* This just triggers the first communication. The full set of
+ * requests are send whenever the sensor reconnects (detected in
+ * sensorError(). */
+
+ sendRequest(hostName, "test kill", 4);
+
+ if (title.isEmpty())
+ setTitle(i18n("%1: Running Processes").arg(hostName));
+ else
+ setTitle(title);
+
+ return (true);
+}
+
+void
+ProcessController::updateList()
+{
+ sendRequest(sensors().at(0)->hostName(), "ps", 2);
+}
+
+void
+ProcessController::killProcess(int pid, int sig)
+{
+ sendRequest(sensors().at(0)->hostName(),
+ QString("kill %1 %2" ).arg(pid).arg(sig), 3);
+
+ if ( !timerOn() )
+ // give ksysguardd time to update its proccess list
+ QTimer::singleShot(3000, this, SLOT(updateList()));
+ else
+ updateList();
+}
+
+void
+ProcessController::killProcess()
+{
+ const QStringList& selectedAsStrings = pList->getSelectedAsStrings();
+ if (selectedAsStrings.isEmpty())
+ {
+ KMessageBox::sorry(this,
+ i18n("You need to select a process first."));
+ return;
+ }
+ else
+ {
+ QString msg = i18n("Do you want to kill the selected process?",
+ "Do you want to kill the %n selected processes?",
+ selectedAsStrings.count());
+
+ KDialogBase *dlg = new KDialogBase ( i18n ("Kill Process"),
+ KDialogBase::Yes | KDialogBase::Cancel,
+ KDialogBase::Yes, KDialogBase::Cancel, this->parentWidget(),
+ "killconfirmation",
+ true, true, KGuiItem(i18n("Kill")));
+
+ bool dontAgain = false;
+
+ int res = KMessageBox::createKMessageBox(dlg, QMessageBox::Question,
+ msg, selectedAsStrings,
+ i18n("Do not ask again"), &dontAgain,
+ KMessageBox::Notify);
+
+ if (res != KDialogBase::Yes)
+ {
+ return;
+ }
+ }
+
+ const QValueList<int>& selectedPIds = pList->getSelectedPIds();
+
+ // send kill signal to all seleted processes
+ QValueListConstIterator<int> it;
+ for (it = selectedPIds.begin(); it != selectedPIds.end(); ++it)
+ sendRequest(sensors().at(0)->hostName(), QString("kill %1 %2" ).arg(*it)
+ .arg(MENU_ID_SIGKILL), 3);
+
+ if ( !timerOn())
+ // give ksysguardd time to update its proccess list
+ QTimer::singleShot(3000, this, SLOT(updateList()));
+ else
+ updateList();
+}
+
+void
+ProcessController::reniceProcess(const QValueList<int> &pids, int niceValue)
+{
+ for( QValueList<int>::ConstIterator it = pids.constBegin(), end = pids.constEnd(); it != end; ++it )
+ sendRequest(sensors().at(0)->hostName(),
+ QString("setpriority %1 %2" ).arg(*it).arg(niceValue), 5);
+ sendRequest(sensors().at(0)->hostName(), "ps", 2); //update the display afterwards
+}
+
+void
+ProcessController::answerReceived(int id, const QString& answer)
+{
+ /* We received something, so the sensor is probably ok. */
+ sensorError(id, false);
+
+ switch (id)
+ {
+ case 1:
+ {
+ /* We have received the answer to a ps? command that contains
+ * the information about the table headers. */
+ KSGRD::SensorTokenizer lines(answer, '\n');
+ if (lines.count() != 2)
+ {
+ kdDebug (1215) << "ProcessController::answerReceived(1)"
+ "wrong number of lines [" << answer << "]" << endl;
+ sensorError(id, true);
+ return;
+ }
+ KSGRD::SensorTokenizer headers(lines[0], '\t');
+ KSGRD::SensorTokenizer colTypes(lines[1], '\t');
+
+ pList->removeColumns();
+ for (unsigned int i = 0; i < headers.count(); i++)
+ {
+ QString header;
+ if (dict[headers[i]])
+ header = *dict[headers[i]];
+ else
+ header = headers[i];
+ pList->addColumn(header, colTypes[i]);
+ }
+
+ break;
+ }
+ case 2:
+ /* We have received the answer to a ps command that contains a
+ * list of processes with various additional information. */
+ pList->update(answer);
+ pListSearchLine->searchLine()->updateSearch(); //re-apply the filter
+ break;
+ case 3:
+ {
+ // result of kill operation
+ kdDebug(1215) << answer << endl;
+ KSGRD::SensorTokenizer vals(answer, '\t');
+ switch (vals[0].toInt())
+ {
+ case 0: // successful kill operation
+ break;
+ case 1: // unknown error
+ KSGRD::SensorMgr->notify(
+ i18n("Error while attempting to kill process %1.")
+ .arg(vals[1]));
+ break;
+ case 2:
+ KSGRD::SensorMgr->notify(
+ i18n("Insufficient permissions to kill "
+ "process %1.").arg(vals[1]));
+ break;
+ case 3:
+ KSGRD::SensorMgr->notify(
+ i18n("Process %1 has already disappeared.")
+ .arg(vals[1]));
+ break;
+ case 4:
+ KSGRD::SensorMgr->notify(i18n("Invalid Signal."));
+ break;
+ }
+ break;
+ }
+ case 4:
+ killSupported = (answer.toInt() == 1);
+ pList->setKillSupported(killSupported);
+ bKill->setEnabled(killSupported);
+ break;
+ case 5:
+ {
+ // result of renice operation
+ kdDebug(1215) << answer << endl;
+ KSGRD::SensorTokenizer vals(answer, '\t');
+ switch (vals[0].toInt())
+ {
+ case 0: // successful renice operation
+ break;
+ case 1: // unknown error
+ KSGRD::SensorMgr->notify(
+ i18n("Error while attempting to renice process %1.")
+ .arg(vals[1]));
+ break;
+ case 2:
+ KSGRD::SensorMgr->notify(
+ i18n("Insufficient permissions to renice "
+ "process %1.").arg(vals[1]));
+ break;
+ case 3:
+ KSGRD::SensorMgr->notify(
+ i18n("Process %1 has already disappeared.")
+ .arg(vals[1]));
+ break;
+ case 4:
+ KSGRD::SensorMgr->notify(i18n("Invalid argument."));
+ break;
+ }
+ break;
+ }
+ }
+}
+
+void
+ProcessController::sensorError(int, bool err)
+{
+ if (err == sensors().at(0)->isOk())
+ {
+ if (!err)
+ {
+ /* Whenever the communication with the sensor has been
+ * (re-)established we need to requests the full set of
+ * properties again, since the back-end might be a new
+ * one. */
+ sendRequest(sensors().at(0)->hostName(), "test kill", 4);
+ sendRequest(sensors().at(0)->hostName(), "ps?", 1);
+ sendRequest(sensors().at(0)->hostName(), "ps", 2);
+ }
+
+ /* This happens only when the sensorOk status needs to be changed. */
+ sensors().at(0)->setIsOk( !err );
+ }
+ setSensorOk(sensors().at(0)->isOk());
+}
+
+bool
+ProcessController::restoreSettings(QDomElement& element)
+{
+ bool result = addSensor(element.attribute("hostName"),
+ element.attribute("sensorName"), (element.attribute("sensorType").isEmpty() ? "table" : element.attribute("sensorType")),
+ QString::null);
+
+ xbTreeView->setChecked(element.attribute("tree").toInt());
+ setTreeView(element.attribute("tree").toInt());
+
+ uint filter = element.attribute("filter").toUInt();
+ cbFilter->setCurrentItem(filter);
+ filterModeChanged(filter);
+
+ uint col = element.attribute("sortColumn").toUInt();
+ bool inc = element.attribute("incrOrder").toUInt();
+
+ if (!pList->load(element))
+ return (false);
+
+ pList->setSortColumn(col, inc);
+
+ SensorDisplay::restoreSettings(element);
+
+ setModified(false);
+
+ return (result);
+}
+
+bool
+ProcessController::saveSettings(QDomDocument& doc, QDomElement& element, bool save)
+{
+ element.setAttribute("hostName", sensors().at(0)->hostName());
+ element.setAttribute("sensorName", sensors().at(0)->name());
+ element.setAttribute("sensorType", sensors().at(0)->type());
+ element.setAttribute("tree", (uint) xbTreeView->isChecked());
+ element.setAttribute("filter", cbFilter->currentItem());
+ element.setAttribute("sortColumn", pList->getSortColumn());
+ element.setAttribute("incrOrder", pList->getIncreasing());
+
+ if (!pList->save(doc, element))
+ return (false);
+
+ SensorDisplay::saveSettings(doc, element);
+
+ if (save)
+ setModified(false);
+
+ return (true);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/ProcessController.h b/ksysguard/gui/SensorDisplayLib/ProcessController.h
new file mode 100644
index 000000000..f834efbb6
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ProcessController.h
@@ -0,0 +1,154 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef _ProcessController_h_
+#define _ProcessController_h_
+
+#include <qdict.h>
+#include <qwidget.h>
+
+#include <kapplication.h>
+
+#include <SensorDisplay.h>
+
+#include "ProcessList.h"
+
+class QVBoxLayout;
+class QHBoxLayout;
+class QCheckBox;
+class QComboBox;
+class KPushButton;
+class KListViewSearchLineWidget;
+
+extern KApplication* Kapp;
+
+/**
+ * This widget implements a process list page. Besides the process
+ * list which is implemented as a ProcessList, it contains two
+ * comboxes and two buttons. The combo boxes are used to set the
+ * update rate and the process filter. The buttons are used to force
+ * an immediate update and to kill a process.
+ */
+class ProcessController : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+
+public:
+ ProcessController(QWidget* parent = 0, const char* name = 0, const QString &title = QString::null, bool nf = false);
+ virtual ~ProcessController() { }
+
+ void resizeEvent(QResizeEvent*);
+
+ bool restoreSettings(QDomElement& element);
+
+ bool saveSettings(QDomDocument& doc, QDomElement& element, bool save = true);
+
+ void refreshList(void)
+ {
+ updateList();
+ }
+
+ virtual void timerEvent(QTimerEvent*)
+ {
+ updateList();
+ }
+
+ virtual bool addSensor(const QString&, const QString&, const QString&, const QString&);
+
+ virtual void answerReceived(int id, const QString& answer);
+
+ virtual void sensorError(int, bool err);
+
+ void configureSettings() { }
+
+ virtual bool hasSettingsDialog() const
+ {
+ return (false);
+ }
+
+public slots:
+ void setSearchFocus();
+ void fixTabOrder();
+ void filterModeChanged(int filter)
+ {
+ pList->setFilterMode(filter);
+ updateList();
+ setModified(true);
+ }
+
+ void setTreeView(bool tv)
+ {
+ pList->setTreeView(tv);
+ updateList();
+ setModified(true);
+ }
+
+ virtual void setModified(bool mfd)
+ {
+ if (mfd != modified())
+ {
+ SensorDisplay::setModified( mfd );
+ if (!mfd)
+ pList->setModified(0);
+ emit modified(modified());
+ }
+ }
+
+ void killProcess();
+ void killProcess(int pid, int sig);
+
+ void reniceProcess(const QValueList<int> &pids, int niceValue);
+
+ void updateList();
+
+signals:
+ void setFilterMode(int);
+
+private:
+ QVBoxLayout* gm;
+
+ bool killSupported;
+
+ /// The process list.
+ ProcessList* pList;
+ ///Layout for the search line and process filter combo box
+ QHBoxLayout* gmSearch;
+ KListViewSearchLineWidget *pListSearchLine;
+
+ QHBoxLayout* gm1;
+
+ /// Checkbox to switch between tree and list view
+ QCheckBox* xbTreeView;
+
+ /// This combo boxes control the process filter.
+ QComboBox* cbFilter;
+
+ /// These buttons force an immedeate refresh or kill a process.
+ KPushButton* bRefresh;
+ KPushButton* bKill;
+
+ /// Dictionary for header translations.
+ QDict<QString> dict;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/ProcessList.cc b/ksysguard/gui/SensorDisplayLib/ProcessList.cc
new file mode 100644
index 000000000..6d158c872
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ProcessList.cc
@@ -0,0 +1,941 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (C) 1997 Bernd Johannes Wuebben
+ <wuebben@math.cornell.edu>
+
+ Copyright (C) 1998 Nicolas Leclercq <nicknet@planete.net>
+
+ Copyright (c) 1999, 2000, 2001, 2002 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <assert.h>
+#include <config.h>
+#include <ctype.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <qbitmap.h>
+#include <qheader.h>
+#include <qimage.h>
+#include <qpopupmenu.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include "ProcessController.h"
+#include "ProcessList.h"
+#include "ReniceDlg.h"
+#include "SignalIDs.h"
+
+#define NONE -1
+#define INIT_PID 1
+
+//extern const char* intKey(const char* text);
+//extern const char* timeKey(const char* text);
+//extern const char* floatKey(const char* text);
+
+QDict<QString> ProcessList::aliases;
+
+int ProcessLVI::compare( QListViewItem *item, int col, bool ascending ) const
+{
+ int type = ((ProcessList*)listView())->columnType( col );
+
+ if ( type == ProcessList::Int ) {
+ int prev = (int)KGlobal::locale()->readNumber( key( col, ascending ) );
+ int next = (int)KGlobal::locale()->readNumber( item->key( col, ascending ) );
+ if ( prev < next )
+ return -1;
+ else if ( prev == next )
+ return 0;
+ else
+ return 1;
+ }
+
+ if ( type == ProcessList::Float ) {
+ double prev = KGlobal::locale()->readNumber( key( col, ascending ) );
+ double next = KGlobal::locale()->readNumber( item->key( col, ascending ) );
+ if ( prev < next )
+ return -1;
+ else
+ return 1;
+ }
+
+ if ( type == ProcessList::Time ) {
+ int hourPrev, hourNext, minutesPrev, minutesNext;
+ sscanf( key( col, ascending ).latin1(), "%d:%d", &hourPrev, &minutesPrev );
+ sscanf( item->key( col, ascending ).latin1(), "%d:%d", &hourNext, &minutesNext );
+ int prev = hourPrev * 60 + minutesPrev;
+ int next = hourNext * 60 + minutesNext;
+ if ( prev < next )
+ return -1;
+ else if ( prev == next )
+ return 0;
+ else
+ return 1;
+ }
+
+ return key( col, ascending ).localeAwareCompare( item->key( col, ascending ) );
+}
+
+ProcessList::ProcessList(QWidget *parent, const char* name)
+ : KListView(parent, name)
+{
+ iconCache.setAutoDelete(true);
+
+ columnDict.setAutoDelete(true);
+ columnDict.insert("running",
+ new QString(i18n("process status", "running")));
+ columnDict.insert("sleeping",
+ new QString(i18n("process status", "sleeping")));
+ columnDict.insert("disk sleep",
+ new QString(i18n("process status", "disk sleep")));
+ columnDict.insert("zombie", new QString(i18n("process status", "zombie")));
+ columnDict.insert("stopped",
+ new QString(i18n("process status", "stopped")));
+ columnDict.insert("paging", new QString(i18n("process status", "paging")));
+ columnDict.insert("idle", new QString(i18n("process status", "idle")));
+
+ if (aliases.isEmpty())
+ {
+#ifdef Q_OS_LINUX
+ aliases.insert("init", new QString("penguin"));
+#else
+ aliases.insert("init", new QString("system"));
+#endif
+ /* kernel stuff */
+ aliases.insert("bdflush", new QString("kernel"));
+ aliases.insert("dhcpcd", new QString("kernel"));
+ aliases.insert("kapm-idled", new QString("kernel"));
+ aliases.insert("keventd", new QString("kernel"));
+ aliases.insert("khubd", new QString("kernel"));
+ aliases.insert("klogd", new QString("kernel"));
+ aliases.insert("kreclaimd", new QString("kernel"));
+ aliases.insert("kreiserfsd", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU0", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU1", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU2", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU3", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU4", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU5", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU6", new QString("kernel"));
+ aliases.insert("ksoftirqd_CPU7", new QString("kernel"));
+ aliases.insert("kswapd", new QString("kernel"));
+ aliases.insert("kupdated", new QString("kernel"));
+ aliases.insert("mdrecoveryd", new QString("kernel"));
+ aliases.insert("scsi_eh_0", new QString("kernel"));
+ aliases.insert("scsi_eh_1", new QString("kernel"));
+ aliases.insert("scsi_eh_2", new QString("kernel"));
+ aliases.insert("scsi_eh_3", new QString("kernel"));
+ aliases.insert("scsi_eh_4", new QString("kernel"));
+ aliases.insert("scsi_eh_5", new QString("kernel"));
+ aliases.insert("scsi_eh_6", new QString("kernel"));
+ aliases.insert("scsi_eh_7", new QString("kernel"));
+ /* daemon and other service providers */
+ aliases.insert("artsd", new QString("daemon"));
+ aliases.insert("atd", new QString("daemon"));
+ aliases.insert("automount", new QString("daemon"));
+ aliases.insert("cardmgr", new QString("daemon"));
+ aliases.insert("cron", new QString("daemon"));
+ aliases.insert("cupsd", new QString("daemon"));
+ aliases.insert("in.identd", new QString("daemon"));
+ aliases.insert("lpd", new QString("daemon"));
+ aliases.insert("mingetty", new QString("daemon"));
+ aliases.insert("nscd", new QString("daemon"));
+ aliases.insert("portmap", new QString("daemon"));
+ aliases.insert("rpc.statd", new QString("daemon"));
+ aliases.insert("rpciod", new QString("daemon"));
+ aliases.insert("sendmail", new QString("daemon"));
+ aliases.insert("sshd", new QString("daemon"));
+ aliases.insert("syslogd", new QString("daemon"));
+ aliases.insert("usbmgr", new QString("daemon"));
+ aliases.insert("wwwoffled", new QString("daemon"));
+ aliases.insert("xntpd", new QString("daemon"));
+ aliases.insert("ypbind", new QString("daemon"));
+ /* kde applications */
+ aliases.insert("appletproxy", new QString("kdeapp"));
+ aliases.insert("dcopserver", new QString("kdeapp"));
+ aliases.insert("kcookiejar", new QString("kdeapp"));
+ aliases.insert("kde", new QString("kdeapp"));
+ aliases.insert("kded", new QString("kdeapp"));
+ aliases.insert("kdeinit", new QString("kdeapp"));
+ aliases.insert("kdesktop", new QString("kdeapp"));
+ aliases.insert("kdesud", new QString("kdeapp"));
+ aliases.insert("kdm", new QString("kdeapp"));
+ aliases.insert("khotkeys", new QString("kdeapp"));
+ aliases.insert("kio_file", new QString("kdeapp"));
+ aliases.insert("kio_uiserver", new QString("kdeapp"));
+ aliases.insert("klauncher", new QString("kdeapp"));
+ aliases.insert("ksmserver", new QString("kdeapp"));
+ aliases.insert("kwrapper", new QString("kdeapp"));
+ aliases.insert("kwrited", new QString("kdeapp"));
+ aliases.insert("kxmlrpcd", new QString("kdeapp"));
+ aliases.insert("startkde", new QString("kdeapp"));
+ /* other processes */
+ aliases.insert("bash", new QString("shell"));
+ aliases.insert("cat", new QString("tools"));
+ aliases.insert("egrep", new QString("tools"));
+ aliases.insert("emacs", new QString("wordprocessing"));
+ aliases.insert("fgrep", new QString("tools"));
+ aliases.insert("find", new QString("tools"));
+ aliases.insert("grep", new QString("tools"));
+ aliases.insert("ksh", new QString("shell"));
+ aliases.insert("screen", new QString("openterm"));
+ aliases.insert("sh", new QString("shell"));
+ aliases.insert("sort", new QString("tools"));
+ aliases.insert("ssh", new QString("shell"));
+ aliases.insert("su", new QString("tools"));
+ aliases.insert("tcsh", new QString("shell"));
+ aliases.insert("tee", new QString("tools"));
+ aliases.insert("vi", new QString("wordprocessing"));
+ }
+
+ /* The filter mode is controlled by a combo box of the parent. If
+ * the mode is changed we get a signal. */
+ connect(parent, SIGNAL(setFilterMode(int)),
+ this, SLOT(setFilterMode(int)));
+
+ /* We need to catch this signal to show various popup menues. */
+ connect(this,
+ SIGNAL(rightButtonPressed(QListViewItem*, const QPoint&, int)),
+ this,
+ SLOT(handleRMBPressed(QListViewItem*, const QPoint&, int)));
+
+ /* Since Qt does not tell us the sorting details we have to do our
+ * own bookkeping, so we can save and restore the sorting
+ * settings. */
+ connect(header(), SIGNAL(clicked(int)), this, SLOT(sortingChanged(int)));
+
+ treeViewEnabled = false;
+ openAll = true;
+
+ filterMode = FILTER_ALL;
+
+ sortColumn = 1;
+ increasing = false;
+
+ // Elements in the process list may only live in this list.
+ pl.setAutoDelete(true);
+
+ setItemMargin(2);
+ setAllColumnsShowFocus(true);
+ setTreeStepSize(17);
+ setSorting(sortColumn, increasing);
+ setSelectionMode(QListView::Extended);
+
+ // Create popup menu for RMB clicks on table header
+ headerPM = new QPopupMenu();
+ headerPM->insertItem(i18n("Remove Column"), HEADER_REMOVE);
+ headerPM->insertItem(i18n("Add Column"), HEADER_ADD);
+ headerPM->insertItem(i18n("Help on Column"), HEADER_HELP);
+
+ connect(header(), SIGNAL(sizeChange(int, int, int)),
+ this, SLOT(sizeChanged(int, int, int)));
+ connect(header(), SIGNAL(indexChange(int, int, int)),
+ this, SLOT(indexChanged(int, int, int)));
+
+ killSupported = false;
+ setModified(false);
+}
+
+ProcessList::~ProcessList()
+{
+ delete(headerPM);
+}
+
+const QValueList<int>&
+ProcessList::getSelectedPIds()
+{
+ selectedPIds.clear();
+ // iterate through all selected visible items of the listview
+ QListViewItemIterator it(this, QListViewItemIterator::Visible | QListViewItemIterator::Selected );
+ for ( ; it.current(); ++it )
+ selectedPIds.append(it.current()->text(1).toInt());
+
+ return (selectedPIds);
+}
+
+const QStringList&
+ProcessList::getSelectedAsStrings()
+{
+ selectedAsStrings.clear();
+ // iterate through all selected visible items of the listview
+ QListViewItemIterator it(this, QListViewItemIterator::Visible | QListViewItemIterator::Selected );
+ QString spaces;
+ for ( ; it.current(); ++it ) {
+ spaces.fill(QChar(' '), 7 - it.current()->text(1).length());
+ selectedAsStrings.append("(PID: " + it.current()->text(1) + ")" + spaces + " " + it.current()->text(0));
+ }
+
+ return (selectedAsStrings);
+}
+bool
+ProcessList::update(const QString& list)
+{
+ /* Disable painting to avoid flickering effects,
+ * especially when in tree view mode.
+ * Ditto for the scrollbar. */
+ setUpdatesEnabled(false);
+ viewport()->setUpdatesEnabled(false);
+
+ pl.clear();
+
+ // Convert ps answer in a list of tokenized lines
+ KSGRD::SensorTokenizer procs(list, '\n');
+ for (unsigned int i = 0; i < procs.count(); i++)
+ {
+ KSGRD::SensorPSLine* line = new KSGRD::SensorPSLine(procs[i]);
+ if (line->count() != (uint) columns())
+ {
+#if 0
+ // This is needed for debugging only.
+ kdDebug(1215) << list << endl;
+ QString l;
+ for (uint j = 0; j < line->count(); j++)
+ l += (*line)[j] + "|";
+ kdDebug(1215) << "Incomplete ps line:" << l << endl;
+#endif
+ return (false);
+ }
+ else
+ pl.append(line);
+ }
+
+ int currItemPos = itemPos(currentItem());
+ int vpos = verticalScrollBar()->value();
+ int hpos = horizontalScrollBar()->value();
+
+ updateMetaInfo();
+
+ clear();
+
+ if (treeViewEnabled)
+ buildTree();
+ else
+ buildList();
+
+ QListViewItemIterator it( this );
+ while ( it.current() ) {
+ if ( itemPos( it.current() ) == currItemPos ) {
+ setCurrentItem( it.current() );
+ break;
+ }
+ ++it;
+ }
+
+ verticalScrollBar()->setValue(vpos);
+ horizontalScrollBar()->setValue(hpos);
+
+ // Re-enable painting, and force an update.
+ setUpdatesEnabled(true);
+ viewport()->setUpdatesEnabled(true);
+
+ triggerUpdate();
+
+ return (true);
+}
+
+void
+ProcessList::setTreeView(bool tv)
+{
+ if (treeViewEnabled = tv)
+ {
+ savedWidth[0] = columnWidth(0);
+ openAll = true;
+ }
+ else
+ {
+ /* In tree view the first column is wider than in list view mode.
+ * So we shrink it to 1 pixel. The next update will resize it again
+ * appropriately. */
+ setColumnWidth(0, savedWidth[0]);
+ }
+ /* In tree view mode borders are added to the icons. So we have to clear
+ * the cache when we change the tree view mode. */
+ iconCache.clear();
+}
+
+bool
+ProcessList::load(QDomElement& el)
+{
+ QDomNodeList dnList = el.elementsByTagName("column");
+ for (uint i = 0; i < dnList.count(); ++i)
+ {
+ QDomElement lel = dnList.item(i).toElement();
+ if (savedWidth.count() <= i)
+ savedWidth.append(lel.attribute("savedWidth").toInt());
+ else
+ savedWidth[i] = lel.attribute("savedWidth").toInt();
+ if (currentWidth.count() <= i)
+ currentWidth.append(lel.attribute("currentWidth").toInt());
+ else
+ currentWidth[i] = lel.attribute("currentWidth").toInt();
+ if (index.count() <= i)
+ index.append(lel.attribute("index").toInt());
+ else
+ index[i] = lel.attribute("index").toInt();
+ }
+
+ setModified(false);
+
+ return (true);
+}
+
+bool
+ProcessList::save(QDomDocument& doc, QDomElement& display)
+{
+ for (int i = 0; i < columns(); ++i)
+ {
+ QDomElement col = doc.createElement("column");
+ display.appendChild(col);
+ col.setAttribute("currentWidth", columnWidth(i));
+ col.setAttribute("savedWidth", savedWidth[i]);
+ col.setAttribute("index", header()->mapToIndex(i));
+ }
+
+ setModified(false);
+
+ return (true);
+}
+
+void
+ProcessList::sortingChanged(int col)
+{
+ if (col == sortColumn)
+ increasing = !increasing;
+ else
+ {
+ sortColumn = col;
+ increasing = true;
+ }
+ setSorting(sortColumn, increasing);
+ setModified(true);
+}
+
+int ProcessList::columnType( uint pos ) const
+{
+ if ( pos >= mColumnTypes.count() )
+ return 0;
+
+ if ( mColumnTypes[ pos ] == "d" || mColumnTypes[ pos ] == "D" )
+ return Int;
+ else if ( mColumnTypes[ pos ] == "f" || mColumnTypes[ pos ] == "F" )
+ return Float;
+ else if ( mColumnTypes[ pos ] == "t" )
+ return Time;
+ else
+ return Text;
+}
+
+bool
+ProcessList::matchesFilter(KSGRD::SensorPSLine* p) const
+{
+ // This mechanism is likely to change in the future!
+
+ switch (filterMode)
+ {
+ case FILTER_ALL:
+ return (true);
+
+ case FILTER_SYSTEM:
+ return (p->uid() < 100 ? true : false);
+
+ case FILTER_USER:
+ return (p->uid() >= 100 ? true : false);
+
+ case FILTER_OWN:
+ default:
+ return (p->uid() == (long) getuid() ? true : false);
+ }
+}
+
+void
+ProcessList::buildList()
+{
+ /* Get the first process in the list, check whether it matches the
+ * filter and append it to QListView widget if so. */
+ while (!pl.isEmpty())
+ {
+ KSGRD::SensorPSLine* p = pl.first();
+
+ if (matchesFilter(p))
+ {
+ ProcessLVI* pli = new ProcessLVI(this);
+
+ addProcess(p, pli);
+
+ if (selectedPIds.findIndex(p->pid()) != -1)
+ pli->setSelected(true);
+ }
+ pl.removeFirst();
+ }
+}
+
+void
+ProcessList::buildTree()
+{
+ // remove all leaves that do not match the filter
+ deleteLeaves();
+
+ KSGRD::SensorPSLine* ps = pl.first();
+
+ while (ps)
+ {
+ if (ps->pid() == INIT_PID)
+ {
+ // insert root item into the tree widget
+ ProcessLVI* pli = new ProcessLVI(this);
+ addProcess(ps, pli);
+
+ // remove the process from the process list, ps is now invalid
+ int pid = ps->pid();
+ pl.remove();
+
+ if (selectedPIds.findIndex(pid) != -1)
+ pli->setSelected(true);
+
+ // insert all child processes of current process
+ extendTree(&pl, pli, pid);
+ break;
+ }
+ else
+ ps = pl.next();
+ }
+}
+
+void
+ProcessList::deleteLeaves(void)
+{
+ for ( ; ; )
+ {
+ unsigned int i;
+ for (i = 0; i < pl.count() &&
+ (!isLeafProcess(pl.at(i)->pid()) ||
+ matchesFilter(pl.at(i))); i++)
+ ;
+ if (i == pl.count())
+ return;
+
+ pl.remove(i);
+ }
+}
+
+bool
+ProcessList::isLeafProcess(int pid)
+{
+ for (unsigned int i = 0; i < pl.count(); i++)
+ if (pl.at(i)->ppid() == pid)
+ return (false);
+
+ return (true);
+}
+
+void
+ProcessList::extendTree(QPtrList<KSGRD::SensorPSLine>* pl, ProcessLVI* parent, int ppid)
+{
+ KSGRD::SensorPSLine* ps;
+
+ // start at top list
+ ps = pl->first();
+
+ while (ps)
+ {
+ // look for a child process of the current parent
+ if (ps->ppid() == ppid)
+ {
+ ProcessLVI* pli = new ProcessLVI(parent);
+
+ addProcess(ps, pli);
+
+ if (selectedPIds.findIndex(ps->pid()) != -1)
+ pli->setSelected(true);
+
+ if (ps->ppid() != INIT_PID && closedSubTrees.findIndex(ps->ppid()) != -1)
+ parent->setOpen(false);
+ else
+ parent->setOpen(true);
+
+ // remove the process from the process list, ps is now invalid
+ int pid = ps->pid();
+ pl->remove();
+
+ // now look for the childs of the inserted process
+ extendTree(pl, pli, pid);
+
+ /* Since buildTree can remove processes from the list we
+ * can't find a "current" process. So we start searching
+ * at the top again. It's no endless loops since this
+ * branch is only entered when there are children of the
+ * current parent in the list. When we have removed them
+ * all the while loop will exit. */
+ ps = pl->first();
+ }
+ else
+ ps = pl->next();
+ }
+}
+void
+ProcessList::addProcess(KSGRD::SensorPSLine* p, ProcessLVI* pli)
+{
+ QString name = p->name();
+ if (aliases[name])
+ name = *aliases[name];
+
+ /* Get icon from icon list that might be appropriate for a process
+ * with this name. */
+ QPixmap pix;
+ if (!iconCache[name])
+ {
+ pix = KGlobal::iconLoader()->loadIcon(name, KIcon::Small,
+ KIcon::SizeSmall, KIcon::DefaultState,
+ 0L, true);
+ if (pix.isNull() || !pix.mask())
+ pix = KGlobal::iconLoader()->loadIcon("unknownapp", KIcon::User,
+ KIcon::SizeSmall);
+
+ if (pix.width() != 16 || pix.height() != 16)
+ {
+ /* I guess this isn't needed too often. The KIconLoader should
+ * scale the pixmaps already appropriately. Since I got a bug
+ * report claiming that it doesn't work with GNOME apps I've
+ * added this safeguard. */
+ QImage img;
+ img = pix;
+ img.smoothScale(16, 16);
+ pix = img;
+ }
+ /* We copy the icon into a 24x16 pixmap to add a 4 pixel margin on
+ * the left and right side. In tree view mode we use the original
+ * icon. */
+ QPixmap icon(24, 16, pix.depth());
+ if (!treeViewEnabled)
+ {
+ icon.fill();
+ bitBlt(&icon, 4, 0, &pix, 0, 0, pix.width(), pix.height());
+ QBitmap mask(24, 16, true);
+ bitBlt(&mask, 4, 0, pix.mask(), 0, 0, pix.width(), pix.height());
+ icon.setMask(mask);
+ pix = icon;
+ }
+ iconCache.insert(name, new QPixmap(pix));
+ }
+ else
+ pix = *(iconCache[name]);
+
+ // icon + process name
+ pli->setPixmap(0, pix);
+ pli->setText(0, p->name());
+
+ // insert remaining field into table
+ for (unsigned int col = 1; col < p->count(); col++)
+ {
+ if (mColumnTypes[col] == "S" && columnDict[(*p)[col]])
+ pli->setText(col, *columnDict[(*p)[col]]);
+ else if ( mColumnTypes[col] == "f" )
+ pli->setText( col, KGlobal::locale()->formatNumber( (*p)[col].toFloat() ) );
+ else if ( mColumnTypes[col] == "D" )
+ pli->setText( col, KGlobal::locale()->formatNumber( (*p)[col].toInt(), 0 ) );
+ else
+ pli->setText(col, (*p)[col]);
+ }
+}
+
+void
+ProcessList::updateMetaInfo(void)
+{
+ selectedPIds.clear();
+ closedSubTrees.clear();
+
+ QListViewItemIterator it(this);
+
+ // iterate through all items of the listview
+ for ( ; it.current(); ++it )
+ {
+ if (it.current()->isSelected() && it.current()->isVisible())
+ selectedPIds.append(it.current()->text(1).toInt());
+ if (treeViewEnabled && !it.current()->isOpen())
+ closedSubTrees.append(it.current()->text(1).toInt());
+ }
+
+ /* In list view mode all list items are set to closed by QListView.
+ * If the tree view is now selected, all item will be closed. This is
+ * annoying. So we use the openAll flag to force all trees to open when
+ * the treeViewEnbled flag was set to true. */
+ if (openAll)
+ {
+ if (treeViewEnabled)
+ closedSubTrees.clear();
+ openAll = false;
+ }
+}
+
+void
+ProcessList::removeColumns(void)
+{
+ for (int i = columns() - 1; i >= 0; --i)
+ removeColumn(i);
+}
+
+void
+ProcessList::addColumn(const QString& label, const QString& type)
+{
+ QListView::addColumn(label);
+ uint col = columns() - 1;
+ if (type == "s" || type == "S")
+ setColumnAlignment(col, AlignLeft);
+ else if (type == "d" || type == "D")
+ setColumnAlignment(col, AlignRight);
+ else if (type == "t")
+ setColumnAlignment(col, AlignRight);
+ else if (type == "f")
+ setColumnAlignment(col, AlignRight);
+ else
+ {
+ kdDebug(1215) << "Unknown type " << type << " of column " << label
+ << " in ProcessList!" << endl;
+ return;
+ }
+
+ mColumnTypes.append(type);
+
+ /* Just use some sensible default values as initial setting. */
+ QFontMetrics fm = fontMetrics();
+ setColumnWidth(col, fm.width(label) + 10);
+
+ if (currentWidth.count() - 1 == col)
+ {
+ /* Table has been loaded from file. We can restore the settings
+ * when the last column has been added. */
+ for (uint i = 0; i < col; ++i)
+ {
+ /* In case the language has been changed the column width
+ * might need to be increased. */
+ if (currentWidth[i] == 0)
+ {
+ if (fm.width(header()->label(i)) + 10 > savedWidth[i])
+ savedWidth[i] = fm.width(header()->label(i)) + 10;
+ setColumnWidth(i, 0);
+ }
+ else
+ {
+ if (fm.width(header()->label(i)) + 10 > currentWidth[i])
+ setColumnWidth(i, fm.width(header()->label(i)) + 10);
+ else
+ setColumnWidth(i, currentWidth[i]);
+ }
+ setColumnWidthMode(i, currentWidth[i] == 0 ?
+ QListView::Manual : QListView::Maximum);
+ header()->moveSection(i, index[i]);
+ }
+ setSorting(sortColumn, increasing);
+ }
+}
+
+void
+ProcessList::handleRMBPressed(QListViewItem* lvi, const QPoint& p, int col)
+{
+ if (!lvi)
+ return;
+
+ lvi->setSelected( true );
+
+ /* lvi is only valid until the next time we hit the main event
+ * loop. So we need to save the information we need after calling
+ * processPM->exec(). */
+ int currentPId = lvi->text(1).toInt();
+
+ int currentNiceValue = 0;
+ for (int i = 0; i < columns(); ++i)
+ if (QString::compare(header()->label(i), i18n("Nice")) == 0)
+ currentNiceValue = lvi->text(i).toInt();
+
+ QPopupMenu processPM;
+ if (columnWidth(col) != 0)
+ processPM.insertItem(i18n("Hide Column"), 5);
+ QPopupMenu* hiddenPM = new QPopupMenu(&processPM);
+ for (int i = 0; i < columns(); ++i)
+ if (columnWidth(i) == 0)
+ hiddenPM->insertItem(header()->label(i), i + 100);
+ if(columns())
+ processPM.insertItem(i18n("Show Column"), hiddenPM);
+
+ processPM.insertSeparator();
+
+ processPM.insertItem(i18n("Select All Processes"), 1);
+ processPM.insertItem(i18n("Unselect All Processes"), 2);
+
+ QPopupMenu* signalPM = new QPopupMenu(&processPM);
+ if (killSupported && lvi->isSelected())
+ {
+ processPM.insertSeparator();
+ processPM.insertItem(i18n("Select All Child Processes"), 3);
+ processPM.insertItem(i18n("Unselect All Child Processes"), 4);
+
+ signalPM->insertItem(i18n("SIGABRT"), MENU_ID_SIGABRT);
+ signalPM->insertItem(i18n("SIGALRM"), MENU_ID_SIGALRM);
+ signalPM->insertItem(i18n("SIGCHLD"), MENU_ID_SIGCHLD);
+ signalPM->insertItem(i18n("SIGCONT"), MENU_ID_SIGCONT);
+ signalPM->insertItem(i18n("SIGFPE"), MENU_ID_SIGFPE);
+ signalPM->insertItem(i18n("SIGHUP"), MENU_ID_SIGHUP);
+ signalPM->insertItem(i18n("SIGILL"), MENU_ID_SIGILL);
+ signalPM->insertItem(i18n("SIGINT"), MENU_ID_SIGINT);
+ signalPM->insertItem(i18n("SIGKILL"), MENU_ID_SIGKILL);
+ signalPM->insertItem(i18n("SIGPIPE"), MENU_ID_SIGPIPE);
+ signalPM->insertItem(i18n("SIGQUIT"), MENU_ID_SIGQUIT);
+ signalPM->insertItem(i18n("SIGSEGV"), MENU_ID_SIGSEGV);
+ signalPM->insertItem(i18n("SIGSTOP"), MENU_ID_SIGSTOP);
+ signalPM->insertItem(i18n("SIGTERM"), MENU_ID_SIGTERM);
+ signalPM->insertItem(i18n("SIGTSTP"), MENU_ID_SIGTSTP);
+ signalPM->insertItem(i18n("SIGTTIN"), MENU_ID_SIGTTIN);
+ signalPM->insertItem(i18n("SIGTTOU"), MENU_ID_SIGTTOU);
+ signalPM->insertItem(i18n("SIGUSR1"), MENU_ID_SIGUSR1);
+ signalPM->insertItem(i18n("SIGUSR2"), MENU_ID_SIGUSR2);
+
+ processPM.insertSeparator();
+ processPM.insertItem(i18n("Send Signal"), signalPM);
+ }
+
+ /* differ between killSupported and reniceSupported in a future
+ * version. */
+ if (killSupported && lvi->isSelected())
+ {
+ processPM.insertSeparator();
+ processPM.insertItem(i18n("Renice Process..."), 300);
+ }
+
+ int id;
+ switch (id = processPM.exec(p))
+ {
+ case -1:
+ break;
+ case 1:
+ case 2:
+ selectAllItems(id & 1);
+ break;
+ case 3:
+ case 4:
+ selectAllChilds(currentPId, id & 1);
+ break;
+ case 5:
+ setColumnWidthMode(col, QListView::Manual);
+ savedWidth[col] = columnWidth(col);
+ setColumnWidth(col, 0);
+ setModified(true);
+ break;
+ case 300:
+ {
+ ReniceDlg reniceDlg(this, "reniceDlg", currentNiceValue, currentPId);
+
+ int reniceVal;
+ if ((reniceVal = reniceDlg.exec()) != 40) {
+ emit reniceProcess(selectedPIds, reniceVal);
+ }
+ }
+ break;
+ default:
+ /* IDs < 100 are used for signals. */
+ if (id < 100)
+ {
+ /* we go through list to get all task also
+ when update interval is paused */
+ selectedPIds.clear();
+ QListViewItemIterator it(this, QListViewItemIterator::Visible | QListViewItemIterator::Selected);
+
+ // iterate through all selected visible items of the listview
+ for ( ; it.current(); ++it )
+ {
+ selectedPIds.append(it.current()->text(1).toInt());
+ }
+
+ QString msg = i18n("Do you really want to send signal %1 to the selected process?",
+ "Do you really want to send signal %1 to the %n selected processes?",
+ selectedPIds.count())
+ .arg(signalPM->text(id));
+ int answ;
+ switch(answ = KMessageBox::questionYesNo(this, msg, QString::null, i18n("Send"), KStdGuiItem::cancel()))
+ {
+ case KMessageBox::Yes:
+ {
+ QValueList<int>::Iterator it;
+ for (it = selectedPIds.begin(); it != selectedPIds.end(); ++it)
+ emit (killProcess(*it, id));
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else
+ {
+ /* IDs >= 100 are used for hidden columns. */
+ int col = id - 100;
+ setColumnWidthMode(col, QListView::Maximum);
+ setColumnWidth(col, savedWidth[col]);
+ setModified(true);
+ }
+ }
+}
+
+void
+ProcessList::selectAllItems(bool select)
+{
+ selectedPIds.clear();
+
+ QListViewItemIterator it(this, QListViewItemIterator::Visible);
+
+ // iterate through all items of the listview
+ for ( ; it.current(); ++it )
+ {
+ it.current()->setSelected(select);
+ repaintItem(it.current());
+ if (select)
+ selectedPIds.append(it.current()->text(1).toInt());
+ }
+}
+
+void
+ProcessList::selectAllChilds(int pid, bool select)
+{
+ QListViewItemIterator it(this, QListViewItemIterator::Visible );
+
+ // iterate through all items of the listview
+ for ( ; it.current(); ++it )
+ {
+ // Check if PPID matches the pid (current is a child of pid)
+ if (it.current()->text(2).toInt() == pid)
+ {
+ int currPId = it.current()->text(1).toInt();
+ it.current()->setSelected(select);
+ repaintItem(it.current());
+ if (select)
+ selectedPIds.append(currPId);
+ else
+ selectedPIds.remove(currPId);
+ selectAllChilds(currPId, select);
+ }
+ }
+}
+
+#include "ProcessList.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/ProcessList.h b/ksysguard/gui/SensorDisplayLib/ProcessList.h
new file mode 100644
index 000000000..b3f484484
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ProcessList.h
@@ -0,0 +1,270 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me
+ first. Thanks!
+
+ */
+
+#ifndef _ProcessList_h_
+#define _ProcessList_h_
+
+#include <qdict.h>
+#include <qdom.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include <qwidget.h>
+
+#include <kiconloader.h>
+#include <klistview.h>
+
+#include "SensorClient.h"
+
+typedef const char* (*KeyFunc)(const char*);
+
+/**
+ * To support bi-directional sorting, and sorting of text, integers etc. we
+ * need a specialized version of QListViewItem.
+ */
+class ProcessLVI : public KListViewItem
+{
+public:
+ ProcessLVI(QListView* lv) : KListViewItem(lv) { }
+ ProcessLVI(QListViewItem* lvi) : KListViewItem(lvi) { }
+
+ virtual int compare( QListViewItem *item, int column, bool ) const;
+};
+
+class QPopupMenu;
+
+/**
+ * This class implementes a table filled with information about the running
+ * processes. The table is derived from QListView.
+ */
+class ProcessList : public KListView
+{
+ Q_OBJECT
+
+public:
+ // possible values for the filter mode
+ enum
+ {
+ FILTER_ALL = 0,
+ FILTER_SYSTEM,
+ FILTER_USER,
+ FILTER_OWN
+ };
+
+ enum ColumnType { Text, Int, Float, Time };
+
+ /// The constructor.
+ ProcessList(QWidget* parent = 0, const char* name = 0);
+
+ /// The destructor.
+ ~ProcessList();
+
+ void removeColumns();
+
+ void addColumn(const QString& header, const QString& type);
+
+ void setSortColumn(uint col, bool inc)
+ {
+ sortColumn = col;
+ increasing = inc;
+ setSorting(col, inc);
+ }
+
+ uint getSortColumn() const
+ {
+ return sortColumn;
+ }
+
+ bool getIncreasing() const
+ {
+ return increasing;
+ }
+
+ const QValueList<int>& getSelectedPIds();
+ const QStringList& getSelectedAsStrings();
+
+ /**
+ * The udpate function can be used to update the displayed process
+ * list. A current list of processes is requested from the OS. In
+ * case the list contains invalid or corrupted info, FALSE is
+ * returned.
+ */
+ bool update(const QString& list);
+
+ int columnType( uint col ) const;
+
+ void setSensorOk(bool ok);
+
+ void setKillSupported(bool supported)
+ {
+ killSupported = supported;
+ }
+
+ bool load(QDomElement& el);
+ bool save(QDomDocument& doc, QDomElement& display);
+
+public slots:
+ void setTreeView(bool tv);
+
+ /**
+ * This slot allows the filter mode to be set by other
+ * widgets. Possible values are FILTER_ALL, FILTER_SYSTEM,
+ * FILTER_USER and FILTER_OWN. This filter mechanism will be much
+ * more sophisticated in the future.
+ */
+ void setFilterMode(int fm)
+ {
+ filterMode = fm;
+ setModified(true);
+ }
+
+ void sortingChanged(int col);
+
+ void handleRMBPressed(QListViewItem* lvi, const QPoint& p, int col);
+
+ void sizeChanged(int, int, int)
+ {
+ setModified(true);
+ }
+
+ void indexChanged(int, int, int)
+ {
+ setModified(true);
+ }
+
+ virtual void setModified(bool mfd)
+ {
+ if (mfd != modified)
+ {
+ modified = mfd;
+ emit listModified(modified);
+ }
+ }
+
+signals:
+ // This signal is emitted when process pid should receive signal sig.
+ void killProcess(int pid, int sig);
+
+ // This signal is emitted when process pid should be reniced.
+ void reniceProcess(const QValueList<int> &pids, int niceValue);
+
+ void listModified(bool);
+
+private:
+ // items of table header RMB popup menu
+ enum
+ {
+ HEADER_REMOVE = 0,
+ HEADER_ADD,
+ HEADER_HELP
+ };
+
+ /**
+ * This function updates the lists of selected PID und the closed
+ * sub trees.
+ */
+ void updateMetaInfo(void);
+
+ /**
+ * This function determines whether a process matches the current
+ * filter mode or not. If it machtes the criteria it returns true,
+ * false otherwise.
+ */
+ bool matchesFilter(KSGRD::SensorPSLine* p) const;
+
+ /**
+ * This function constructs the list of processes for list
+ * mode. It's a straightforward appending operation to the
+ * QListView widget.
+ */
+ void buildList();
+
+ /**
+ * This function constructs the tree of processes for tree mode. It
+ * filters out leaf-sub-trees that contain no processes that match
+ * the filter criteria.
+ */
+ void buildTree();
+
+ /**
+ * This function deletes the leaf-sub-trees that do not match the
+ * filter criteria.
+ */
+ void deleteLeaves(void);
+
+ /**
+ * This function returns true if the process is a leaf process with
+ * respect to the other processes in the process list. It does not
+ * have to be a leaf process in the overall list of processes.
+ */
+ bool isLeafProcess(int pid);
+
+ /**
+ * This function is used to recursively construct the tree by
+ * removing processes from the process list an inserting them into
+ * the tree.
+ */
+ void extendTree(QPtrList<KSGRD::SensorPSLine>* pl, ProcessLVI* parent, int ppid);
+
+ /**
+ * This function adds a process to the list/tree.
+ */
+ void addProcess(KSGRD::SensorPSLine* p, ProcessLVI* pli);
+
+private:
+ void selectAllItems(bool select);
+ void selectAllChilds(int pid, bool select);
+
+ bool modified;
+ int filterMode;
+ int sortColumn;
+ bool increasing;
+ int refreshRate;
+ int currColumn;
+ bool killSupported;
+ bool treeViewEnabled;
+ bool openAll;
+
+ /* The following lists are primarily used to store table specs between
+ * load() and the actual table creation in addColumn(). */
+ QValueList<int> savedWidth;
+ QValueList<int> currentWidth;
+ QValueList<int> index;
+
+ QPtrList<KSGRD::SensorPSLine> pl;
+
+ QStringList mColumnTypes;
+ QDict<QString> columnDict;
+
+ QValueList<int> selectedPIds;
+ QValueList<int> closedSubTrees;
+ QStringList selectedAsStrings;
+
+ static QDict<QString> aliases;
+
+ QDict<QPixmap> iconCache;
+
+ QPopupMenu* headerPM;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/ReniceDlg.cc b/ksysguard/gui/SensorDisplayLib/ReniceDlg.cc
new file mode 100644
index 000000000..39c05eecf
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ReniceDlg.cc
@@ -0,0 +1,66 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>. Please do
+ not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <klocale.h>
+#include <knuminput.h>
+
+#include "ReniceDlg.moc"
+
+ReniceDlg::ReniceDlg(QWidget* parent, const char* name, int currentPPrio,
+ int pid)
+ : KDialogBase( parent, name, true, i18n("Renice Process"),
+ KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true )
+{
+ QWidget *page = new QWidget( this );
+ setMainWidget(page);
+ vLay = new QVBoxLayout(page, 20, -1, "ReniceLayout");
+
+ QString msg;
+ msg = i18n("You are about to change the scheduling priority of\n"
+ "process %1. Be aware that only the Superuser (root)\n"
+ "can decrease the nice level of a process. The lower\n"
+ "the number is the higher the priority.\n\n"
+ "Please enter the desired nice level:").arg(pid);
+ message = new QLabel(msg, page);
+ message->setMinimumSize(message->sizeHint());
+ vLay->addWidget(message);
+
+ /*
+ * Create a slider with an LCD display to the right using a horizontal
+ * layout. The slider and the LCD are kept in sync through signals
+ */
+ input = new KIntNumInput(currentPPrio, page, 10);
+ input->setRange(-20, 19);
+ vLay->addWidget(input);
+}
+
+void ReniceDlg::slotOk()
+{
+ done(input->value());
+}
+
+void ReniceDlg::slotCancel()
+{
+ done(40);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/ReniceDlg.h b/ksysguard/gui/SensorDisplayLib/ReniceDlg.h
new file mode 100644
index 000000000..d8f0d2685
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/ReniceDlg.h
@@ -0,0 +1,61 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>. Please do
+ not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef _ReniceDlg_h_
+#define _ReniceDlg_h_
+
+#include <kdialogbase.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlcdnumber.h>
+#include <qpushbutton.h>
+#include <qslider.h>
+
+class KIntNumInput;
+
+/**
+ * This class creates and handles a simple dialog to change the scheduling
+ * priority of a process.
+ */
+class ReniceDlg : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ ReniceDlg(QWidget* parent, const char* name, int currentPPrio, int pid);
+
+public slots:
+ void slotOk();
+ void slotCancel();
+
+private:
+ QBoxLayout* vLay;
+ QBoxLayout* butLay;
+ QBoxLayout* sldLay;
+
+ QLabel* message;
+ KIntNumInput* input;
+};
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/SensorDisplay.cc b/ksysguard/gui/SensorDisplayLib/SensorDisplay.cc
new file mode 100644
index 000000000..805c9a492
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorDisplay.cc
@@ -0,0 +1,611 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2002 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <qcheckbox.h>
+#include <qdom.h>
+#include <qpopupmenu.h>
+#include <qspinbox.h>
+#include <qwhatsthis.h>
+#include <qbitmap.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <krun.h>
+#include <kservice.h>
+
+#include "SensorManager.h"
+#include "TimerSettings.h"
+
+#include "SensorDisplay.h"
+
+using namespace KSGRD;
+
+SensorDisplay::SensorDisplay( QWidget *parent, const char *name,
+ const QString &title, bool nf, bool isApplet)
+ : QWidget( parent, name )
+{
+ mIsApplet = isApplet;
+ mSensors.setAutoDelete( true );
+
+ // default interval is 2 seconds.
+ mUpdateInterval = 2;
+ mUseGlobalUpdateInterval = true;
+ mModified = false;
+ mShowUnit = false;
+ mTimerId = NONE;
+ mFrame = 0;
+ mErrorIndicator = 0;
+ mPlotterWdg = 0;
+
+ setTimerOn( true );
+ QWhatsThis::add( this, "dummy" );
+
+ if(!nf) {
+ mFrame = new QGroupBox( 2, Qt::Vertical, "", this, "displayFrame");
+ mFrame->setFlat(true);
+ mFrame->setAlignment(Qt::AlignHCenter);
+ mFrame->setInsideMargin(2);
+
+ setTitle( title );
+ /* All RMB clicks to the box frame will be handled by
+ * SensorDisplay::eventFilter. */
+ mFrame->installEventFilter( this );
+ }
+
+
+ setMinimumSize( 16, 16 );
+ setModified( false );
+ setSensorOk( false );
+
+ /* Let's call updateWhatsThis() in case the derived class does not do
+ * this. */
+ updateWhatsThis();
+}
+
+SensorDisplay::~SensorDisplay()
+{
+ if ( SensorMgr != 0 )
+ SensorMgr->disconnectClient( this );
+
+ killTimer( mTimerId );
+}
+
+void SensorDisplay::registerSensor( SensorProperties *sp )
+{
+ /* Make sure that we have a connection established to the specified
+ * host. When a work sheet has been saved while it had dangling
+ * sensors, the connect info is not saved in the work sheet. In such
+ * a case the user can re-enter the connect information and the
+ * connection will be established. */
+ if ( !SensorMgr->engageHost( sp->hostName() ) ) {
+ QString msg = i18n( "It is impossible to connect to \'%1\'." ).arg( sp->hostName() );
+ KMessageBox::error( this, msg );
+ }
+
+ mSensors.append( sp );
+}
+
+void SensorDisplay::unregisterSensor( uint pos )
+{
+ mSensors.remove( pos );
+}
+
+void SensorDisplay::configureUpdateInterval()
+{
+ TimerSettings dlg( this );
+
+ dlg.setUseGlobalUpdate( mUseGlobalUpdateInterval );
+ dlg.setInterval( mUpdateInterval );
+
+ if ( dlg.exec() ) {
+ if ( dlg.useGlobalUpdate() ) {
+ mUseGlobalUpdateInterval = true;
+
+ SensorBoard* sb = dynamic_cast<SensorBoard*>( parentWidget() );
+ if ( !sb ) {
+ kdDebug(1215) << "dynamic cast lacks" << endl;
+ setUpdateInterval( 2 );
+ } else {
+ setUpdateInterval( sb->updateInterval() );
+ }
+ } else {
+ mUseGlobalUpdateInterval = false;
+ setUpdateInterval( dlg.interval() );
+ }
+
+ setModified( true );
+ }
+}
+
+void SensorDisplay::timerEvent( QTimerEvent* )
+{
+ int i = 0;
+ for ( SensorProperties *s = mSensors.first(); s; s = mSensors.next(), ++i )
+ sendRequest( s->hostName(), s->name(), i );
+}
+
+void SensorDisplay::resizeEvent( QResizeEvent* )
+{
+ if(mFrame)
+ mFrame->setGeometry( rect() );
+}
+
+bool SensorDisplay::eventFilter( QObject *object, QEvent *event )
+{
+ if ( event->type() == QEvent::MouseButtonPress &&
+ ( (QMouseEvent*)event)->button() == RightButton ) {
+ QPopupMenu pm;
+ if ( mIsApplet ) {
+ pm.insertItem( i18n( "Launch &System Guard"), 1 );
+ pm.insertSeparator();
+ }
+ if ( hasSettingsDialog() )
+ pm.insertItem( i18n( "&Properties" ), 2 );
+ pm.insertItem( i18n( "&Remove Display" ), 3 );
+ pm.insertSeparator();
+ pm.insertItem( i18n( "&Setup Update Interval..." ), 4 );
+ if ( !timerOn() )
+ pm.insertItem( i18n( "&Continue Update" ), 5 );
+ else
+ pm.insertItem( i18n( "P&ause Update" ), 6 );
+
+ switch ( pm.exec( QCursor::pos() ) ) {
+ case 1:
+ KRun::run(*KService::serviceByDesktopName("ksysguard"), KURL::List());
+ break;
+ case 2:
+ configureSettings();
+ break;
+ case 3: {
+ QCustomEvent *e = new QCustomEvent( QEvent::User );
+ e->setData( this );
+ kapp->postEvent( parent(), e );
+ }
+ break;
+ case 4:
+ configureUpdateInterval();
+ break;
+ case 5:
+ setTimerOn( true );
+ setModified( true );
+ break;
+ case 6:
+ setTimerOn( false );
+ setModified( true );
+ break;
+ }
+
+ return true;
+ } else if ( event->type() == QEvent::MouseButtonRelease &&
+ ( ( QMouseEvent*)event)->button() == LeftButton ) {
+ setFocus();
+ }
+
+ return QWidget::eventFilter( object, event );
+}
+
+void SensorDisplay::sendRequest( const QString &hostName,
+ const QString &command, int id )
+{
+ if ( !SensorMgr->sendRequest( hostName, command, (SensorClient*)this, id ) )
+ sensorError( id, true );
+}
+
+void SensorDisplay::sensorError( int sensorId, bool err )
+{
+ if ( sensorId >= (int)mSensors.count() || sensorId < 0 )
+ return;
+
+ if ( err == mSensors.at( sensorId )->isOk() ) {
+ // this happens only when the sensorOk status needs to be changed.
+ mSensors.at( sensorId )->setIsOk( !err );
+ }
+
+ bool ok = true;
+ for ( uint i = 0; i < mSensors.count(); ++i )
+ if ( !mSensors.at( i )->isOk() ) {
+ ok = false;
+ break;
+ }
+
+ setSensorOk( ok );
+}
+
+void SensorDisplay::updateWhatsThis()
+{
+ QWhatsThis::add( this, i18n(
+ "<qt><p>This is a sensor display. To customize a sensor display click "
+ "and hold the right mouse button on either the frame or the "
+ "display box and select the <i>Properties</i> entry from the popup "
+ "menu. Select <i>Remove</i> to delete the display from the worksheet."
+ "</p>%1</qt>" ).arg( additionalWhatsThis() ) );
+}
+
+void SensorDisplay::hosts( QStringList& list )
+{
+ for ( SensorProperties *s = mSensors.first(); s; s = mSensors.next() )
+ if ( !list.contains( s->hostName() ) )
+ list.append( s->hostName() );
+}
+
+QColor SensorDisplay::restoreColor( QDomElement &element, const QString &attr,
+ const QColor& fallback )
+{
+ bool ok;
+ uint c = element.attribute( attr ).toUInt( &ok );
+ if ( !ok )
+ return fallback;
+ else
+ return QColor( (c >> 16) & 0xFF, (c >> 8) & 0xFF, c & 0xFF );
+}
+
+void SensorDisplay::saveColor( QDomElement &element, const QString &attr,
+ const QColor &color )
+{
+ int r, g, b;
+ color.rgb( &r, &g, &b );
+ element.setAttribute( attr, (r << 16) | (g << 8) | b );
+}
+
+bool SensorDisplay::addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &description )
+{
+ registerSensor( new SensorProperties( hostName, name, type, description ) );
+ return true;
+}
+
+bool SensorDisplay::removeSensor( uint pos )
+{
+ unregisterSensor( pos );
+ return true;
+}
+
+void SensorDisplay::setUpdateInterval( uint interval )
+{
+ bool timerActive = timerOn();
+
+ if ( timerActive )
+ setTimerOn( false );
+
+ mUpdateInterval = interval;
+
+ if ( timerActive )
+ setTimerOn( true );
+}
+
+bool SensorDisplay::hasSettingsDialog() const
+{
+ return false;
+}
+
+void SensorDisplay::configureSettings()
+{
+}
+
+void SensorDisplay::setUseGlobalUpdateInterval( bool value )
+{
+ mUseGlobalUpdateInterval = value;
+}
+
+bool SensorDisplay::useGlobalUpdateInterval() const
+{
+ return mUseGlobalUpdateInterval;
+}
+
+QString SensorDisplay::additionalWhatsThis()
+{
+ return QString::null;
+}
+
+void SensorDisplay::sensorLost( int reqId )
+{
+ sensorError( reqId, true );
+}
+
+bool SensorDisplay::restoreSettings( QDomElement &element )
+{
+ QString str = element.attribute( "showUnit", "X" );
+ if(!str.isEmpty() && str != "X") {
+ mShowUnit = str.toInt();
+ }
+ str = element.attribute( "unit", QString::null );
+ if(!str.isEmpty())
+ setUnit(str);
+ str = element.attribute( "title", QString::null );
+ if(!str.isEmpty())
+ setTitle(str);
+
+ if ( element.attribute( "updateInterval" ) != QString::null ) {
+ mUseGlobalUpdateInterval = false;
+ setUpdateInterval( element.attribute( "updateInterval", "2" ).toInt() );
+ } else {
+ mUseGlobalUpdateInterval = true;
+
+ SensorBoard* sb = dynamic_cast<SensorBoard*>( parentWidget() );
+ if ( !sb ) {
+ kdDebug(1215) << "dynamic cast lacks" << endl;
+ setUpdateInterval( 2 );
+ } else
+ setUpdateInterval( sb->updateInterval() );
+ }
+
+ if ( element.attribute( "pause", "0" ).toInt() == 0 )
+ setTimerOn( true );
+ else
+ setTimerOn( false );
+
+ return true;
+}
+
+bool SensorDisplay::saveSettings( QDomDocument&, QDomElement &element, bool )
+{
+ element.setAttribute( "title", title() );
+ element.setAttribute( "unit", unit() );
+ element.setAttribute( "showUnit", mShowUnit );
+
+ if ( mUseGlobalUpdateInterval )
+ element.setAttribute( "globalUpdate", "1" );
+ else {
+ element.setAttribute( "globalUpdate", "0" );
+ element.setAttribute( "updateInterval", mUpdateInterval );
+ }
+
+ if ( !timerOn() )
+ element.setAttribute( "pause", 1 );
+ else
+ element.setAttribute( "pause", 0 );
+
+ return true;
+}
+
+void SensorDisplay::setTimerOn( bool on )
+{
+ if ( on ) {
+ if ( mTimerId == NONE )
+ mTimerId = startTimer( mUpdateInterval * 1000 );
+ } else {
+ if ( mTimerId != NONE ) {
+ killTimer( mTimerId );
+ mTimerId = NONE;
+ }
+ }
+}
+
+bool SensorDisplay::timerOn() const
+{
+ return ( mTimerId != NONE );
+}
+
+bool SensorDisplay::modified() const
+{
+ return mModified;
+}
+
+QPtrList<SensorProperties> &SensorDisplay::sensors()
+{
+ return mSensors;
+}
+
+void SensorDisplay::rmbPressed()
+{
+ emit showPopupMenu( this );
+}
+
+void SensorDisplay::applySettings()
+{
+}
+
+void SensorDisplay::applyStyle()
+{
+}
+
+void SensorDisplay::setModified( bool value )
+{
+ if ( value != mModified ) {
+ mModified = value;
+ emit modified( mModified );
+ }
+}
+
+void SensorDisplay::setSensorOk( bool ok )
+{
+ if ( ok ) {
+ delete mErrorIndicator;
+ mErrorIndicator = 0;
+ } else {
+ if ( mErrorIndicator )
+ return;
+
+ QPixmap errorIcon = KGlobal::iconLoader()->loadIcon( "connect_creating", KIcon::Desktop,
+ KIcon::SizeSmall );
+ if ( !mPlotterWdg )
+ return;
+
+ mErrorIndicator = new QWidget( mPlotterWdg );
+ mErrorIndicator->setErasePixmap( errorIcon );
+ mErrorIndicator->resize( errorIcon.size() );
+ if ( errorIcon.mask() )
+ mErrorIndicator->setMask( *errorIcon.mask() );
+ mErrorIndicator->move( 0, 0 );
+ mErrorIndicator->show();
+ }
+}
+
+void SensorDisplay::setTitle( const QString &title )
+{
+ mTitle = title;
+
+ if(!mFrame) {
+ return; //fixme. create a frame and move widget inside it.
+ }
+
+ /* Changing the frame title may increase the width of the frame and
+ * hence breaks the layout. To avoid this, we save the original size
+ * and restore it after we have set the frame title. */
+ QSize s = mFrame->size();
+
+ if ( mShowUnit && !mUnit.isEmpty() )
+ mFrame->setTitle( mTitle + " [" + mUnit + "]" );
+ else
+ mFrame->setTitle( mTitle );
+ mFrame->setGeometry( 0, 0, s.width(), s.height() );
+}
+
+QString SensorDisplay::title() const
+{
+ return mTitle;
+}
+
+void SensorDisplay::setUnit( const QString &unit )
+{
+ mUnit = unit;
+}
+
+QString SensorDisplay::unit() const
+{
+ return mUnit;
+}
+
+void SensorDisplay::setShowUnit( bool value )
+{
+ mShowUnit = value;
+}
+
+bool SensorDisplay::showUnit() const
+{
+ return mShowUnit;
+}
+
+void SensorDisplay::setPlotterWidget( QWidget *wdg )
+{
+ mPlotterWdg = wdg;
+
+}
+
+QWidget *SensorDisplay::frame()
+{
+ return mFrame;
+}
+
+//void SensorDisplay::setNoFrame( bool /*value*/ )
+//{
+ //FIXME - delete or create the frame as needed
+//}
+
+bool SensorDisplay::noFrame() const
+{
+ return !mFrame;
+}
+
+void SensorDisplay::reorderSensors(const QValueList<int> &orderOfSensors)
+{
+ QPtrList<SensorProperties> newSensors;
+ for ( uint i = 0; i < orderOfSensors.count(); ++i ) {
+ newSensors.append( mSensors.at(orderOfSensors[i] ));
+ }
+
+ mSensors.setAutoDelete( false );
+ mSensors = newSensors;
+ mSensors.setAutoDelete( true );
+}
+
+
+SensorProperties::SensorProperties()
+{
+}
+
+SensorProperties::SensorProperties( const QString &hostName, const QString &name,
+ const QString &type, const QString &description )
+ : mHostName( hostName ), mName( name ), mType( type ), mDescription( description )
+{
+ mOk = false;
+}
+
+SensorProperties::~SensorProperties()
+{
+}
+
+void SensorProperties::setHostName( const QString &hostName )
+{
+ mHostName = hostName;
+}
+
+QString SensorProperties::hostName() const
+{
+ return mHostName;
+}
+
+void SensorProperties::setName( const QString &name )
+{
+ mName = name;
+}
+
+QString SensorProperties::name() const
+{
+ return mName;
+}
+
+void SensorProperties::setType( const QString &type )
+{
+ mType = type;
+}
+
+QString SensorProperties::type() const
+{
+ return mType;
+}
+
+void SensorProperties::setDescription( const QString &description )
+{
+ mDescription = description;
+}
+
+QString SensorProperties::description() const
+{
+ return mDescription;
+}
+
+void SensorProperties::setUnit( const QString &unit )
+{
+ mUnit = unit;
+}
+
+QString SensorProperties::unit() const
+{
+ return mUnit;
+}
+
+void SensorProperties::setIsOk( bool value )
+{
+ mOk = value;
+}
+
+bool SensorProperties::isOk() const
+{
+ return mOk;
+}
+
+#include "SensorDisplay.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/SensorDisplay.h b/ksysguard/gui/SensorDisplayLib/SensorDisplay.h
new file mode 100644
index 000000000..e5e867a01
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorDisplay.h
@@ -0,0 +1,331 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_SENSORDISPLAY_H
+#define KSG_SENSORDISPLAY_H
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qvaluelist.h>
+#include <qwidget.h>
+
+#include <knotifyclient.h>
+
+#include <ksgrd/SensorClient.h>
+
+#define NONE -1
+
+class QDomDocument;
+class QDomElement;
+
+namespace KSGRD {
+
+class SensorProperties;
+
+/**
+ This class is the base class for all displays for sensors. A
+ display is any kind of widget that can display the value of one or
+ more sensors in any form. It must be inherited by all displays that
+ should be inserted into the work sheet.
+ */
+class SensorDisplay : public QWidget, public SensorClient
+{
+ Q_OBJECT
+
+ public:
+ /**
+ Constructor.
+ */
+ SensorDisplay( QWidget *parent = 0, const char *name = 0,
+ const QString& title = 0, bool nf = false, bool isApplet = false );
+
+ /**
+ Destructor.
+ */
+ virtual ~SensorDisplay();
+
+ /**
+ Sets the title of the display.
+ */
+ void setTitle( const QString &title );
+
+ /**
+ Returns the title of the display.
+ */
+ QString title() const;
+
+ /**
+ Sets the unit of the display.
+ */
+ void setUnit( const QString &unit );
+
+ /**
+ Returns the unit of the display.
+ */
+ QString unit() const;
+
+ /**
+ Sets whether the unit string should be displayed at the top
+ of the display frame.
+ */
+ void setShowUnit( bool value );
+
+ /**
+ Returns whether the unit string should be displayed at the top
+ of the display frame. @see setShowUnit()
+ */
+ bool showUnit() const;
+
+ /**
+ Sets whether the update interval of the work sheet should be
+ used instead of the one, set by @ref setUpdateInterval().
+ */
+ void setUseGlobalUpdateInterval( bool value );
+
+ /**
+ Returns whether the update interval of the work sheet should be
+ used instead of the one, set by @ref setUpdateInterval().
+ see @ref setUseGlobalUpdateInterval()
+ */
+ bool useGlobalUpdateInterval() const;
+
+ /**
+ Sets the update interval of the timer, which triggers the timer
+ events. The state of the timer can be set with @ref setTimerOn().
+ */
+ void setUpdateInterval( uint interval );
+
+ /**
+ Returns the update interval.
+ */
+ uint updateInterval() const;
+
+ /**
+ This method appends all hosts of the display to @ref list.
+ */
+ void hosts( QStringList& list );
+
+ /**
+ Sets the widget on which the error icon can be drawn.
+ */
+ void setPlotterWidget( QWidget *plotter );
+
+ /**
+ Returns the widget on which the error icon can be drawn.
+ */
+ QWidget *plotterWidget() const;
+
+ /**
+ Add a sensor to the display.
+
+ @param hostName The name of the host, the sensor belongs to.
+ @param name The sensor name.
+ @param type The type of the sensor.
+ @param description A short description of the sensor.
+ */
+ virtual bool addSensor( const QString &hostName, const QString &name,
+ const QString &type, const QString &description );
+
+ /**
+ Removes the sensor from the display, that is at the position
+ @ref pos of the intern sensor list.
+ */
+ virtual bool removeSensor( uint pos );
+
+ /**
+ This function is a wrapper function to SensorManager::sendRequest.
+ It should be used by all SensorDisplay functions that need to send
+ a request to a sensor since it performs an appropriate error
+ handling by removing the display of necessary.
+ */
+ void sendRequest( const QString &hostName, const QString &cmd, int id );
+
+ /**
+ Raises the configure dialog to setup the update interval.
+ */
+ void configureUpdateInterval();
+
+ /**
+ Returns whether the display provides a settings dialog.
+ This method should be reimplemented in the derived class.
+ */
+ virtual bool hasSettingsDialog() const;
+
+ /**
+ This method is called to raise the settings dialog of the
+ display. It should be reimplemented in the derived class.
+ */
+ virtual void configureSettings();
+
+ /**
+ Reimplement this method to setup the display from config data.
+ */
+ virtual bool restoreSettings( QDomElement& );
+
+ /**
+ Reimplement this method to save the displays config data.
+ */
+ virtual bool saveSettings( QDomDocument&, QDomElement&, bool = true );
+
+ /**
+ Reimplement this method to catch error messages from the SensorManager.
+
+ @param sensorId The unique id of the sensor.
+ @param mode The mode: true = error, false = everthing ok
+ */
+ virtual void sensorError( int sensorId, bool mode );
+
+ /**
+ Normaly you shouldn't reimplement this methode
+ */
+ virtual void sensorLost( int reqId );
+
+ public slots:
+ /**
+ If @ref value is true, this method starts the timer that triggers
+ timer events. If @ref value is false, the timer is stopped.
+ */
+ void setTimerOn( bool value );
+
+ /**
+ Calling this method emits the @ref showPopupMenu() with this
+ display as argument.
+ */
+ void rmbPressed();
+
+ /**
+ Sets whether the display is modified of not.
+ */
+ void setModified( bool modified );
+
+ /**
+ This method can be used to apply the new settings. Just connect
+ the applyClicked() signal of your configuration dialog with this
+ slot and reimplement it.
+ */
+ virtual void applySettings();
+
+ /**
+ This methid is called whenever the global style is changed.
+ Reimplement it to apply the new style settings to the display.
+ */
+ virtual void applyStyle();
+
+
+ signals:
+ void showPopupMenu( KSGRD::SensorDisplay *display );
+ void modified( bool modified );
+
+ protected:
+ virtual bool eventFilter( QObject*, QEvent* );
+ virtual void resizeEvent( QResizeEvent* );
+ virtual void timerEvent( QTimerEvent* );
+
+ void registerSensor( SensorProperties *sp );
+ void unregisterSensor( uint pos );
+
+ QColor restoreColor( QDomElement &element, const QString &attr,
+ const QColor& fallback );
+ void saveColor( QDomElement &element, const QString &attr,
+ const QColor &color );
+
+ virtual QString additionalWhatsThis();
+
+ void setSensorOk( bool ok );
+
+ bool modified() const;
+ bool timerOn() const;
+
+ QWidget *frame();
+
+// void setNoFrame( bool value );
+ bool noFrame() const;
+
+ void reorderSensors(const QValueList<int> &orderOfSensors);
+ QPtrList<SensorProperties> &sensors();
+
+ private:
+ void updateWhatsThis();
+
+ bool mShowUnit;
+ bool mUseGlobalUpdateInterval;
+ bool mModified;
+ bool mNoFrame;
+ bool mIsApplet;
+
+ int mTimerId;
+ int mUpdateInterval;
+
+ // The frame around the other widgets.
+ QGroupBox* mFrame;
+
+ QPtrList<SensorProperties> mSensors;
+
+ QString mTitle;
+ QString mUnit;
+
+ QWidget* mErrorIndicator;
+ QWidget* mPlotterWdg;
+};
+
+class SensorProperties
+{
+ public:
+ SensorProperties();
+ SensorProperties( const QString &hostName, const QString &name,
+ const QString &type, const QString &description );
+ ~SensorProperties();
+
+ void setHostName( const QString &hostName );
+ QString hostName() const;
+
+ void setName( const QString &name );
+ QString name() const;
+
+ void setType( const QString &type );
+ QString type() const;
+
+ void setDescription( const QString &description );
+ QString description() const;
+
+ void setUnit( const QString &unit );
+ QString unit() const;
+
+ void setIsOk( bool value );
+ bool isOk() const;
+
+ private:
+ QString mHostName;
+ QString mName;
+ QString mType;
+ QString mDescription;
+ QString mUnit;
+
+ /* This flag indicates whether the communication to the sensor is
+ * ok or not. */
+ bool mOk;
+};
+
+}
+
+#endif
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLogger.cc b/ksysguard/gui/SensorDisplayLib/SensorLogger.cc
new file mode 100644
index 000000000..b51ba67e0
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLogger.cc
@@ -0,0 +1,437 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <klocale.h>
+
+#include <ksgrd/SensorManager.h>
+#include <ksgrd/StyleEngine.h>
+
+#include <qfile.h>
+
+#include "SensorLogger.moc"
+#include "SensorLoggerSettings.h"
+
+SLListViewItem::SLListViewItem(QListView *parent)
+ : QListViewItem(parent)
+{
+}
+
+LogSensor::LogSensor(QListView *parent)
+ : timerID( NONE ), lowerLimitActive( 0 ), upperLimitActive( 0 ),
+ lowerLimit( 0 ), upperLimit( 0 )
+{
+ Q_CHECK_PTR(parent);
+
+ monitor = parent;
+
+ lvi = new SLListViewItem(monitor);
+ Q_CHECK_PTR(lvi);
+
+ pixmap_running = UserIcon( "running" );
+ pixmap_waiting = UserIcon( "waiting" );
+
+ lvi->setPixmap(0, pixmap_waiting);
+ lvi->setTextColor(monitor->colorGroup().text());
+
+ monitor->insertItem(lvi);
+}
+
+LogSensor::~LogSensor(void)
+{
+ if ((lvi) && (monitor))
+ delete lvi;
+}
+
+void
+LogSensor::startLogging(void)
+{
+ lvi->setPixmap(0, pixmap_running);
+ timerOn();
+}
+
+void
+LogSensor::stopLogging(void)
+{
+ lvi->setPixmap(0, pixmap_waiting);
+ lvi->setTextColor(monitor->colorGroup().text());
+ lvi->repaint();
+ timerOff();
+}
+
+void
+LogSensor::timerEvent(QTimerEvent*)
+{
+ KSGRD::SensorMgr->sendRequest(hostName, sensorName, (KSGRD::SensorClient*) this, 42);
+}
+
+void
+LogSensor::answerReceived(int id, const QString& answer)
+{
+ QFile logFile(fileName);
+
+ if (!logFile.open(IO_ReadWrite | IO_Append))
+ {
+ stopLogging();
+ return;
+ }
+
+ switch (id)
+ {
+ case 42: {
+ QTextStream stream(&logFile);
+ double value = answer.toDouble();
+
+ if (lowerLimitActive && value < lowerLimit)
+ {
+ timerOff();
+ lowerLimitActive = false;
+ lvi->setTextColor(monitor->colorGroup().foreground());
+ lvi->repaint();
+ KNotifyClient::event(monitor->winId(), "sensor_alarm", QString("sensor '%1' at '%2' reached lower limit").arg(sensorName).arg(hostName));
+ timerOn();
+ } else if (upperLimitActive && value > upperLimit)
+ {
+ timerOff();
+ upperLimitActive = false;
+ lvi->setTextColor(monitor->colorGroup().foreground());
+ lvi->repaint();
+ KNotifyClient::event(monitor->winId(), "sensor_alarm", QString("sensor '%1' at '%2' reached upper limit").arg(sensorName).arg(hostName));
+ timerOn();
+ }
+ QDate date = QDateTime::currentDateTime().date();
+ QTime time = QDateTime::currentDateTime().time();
+
+ stream << QString("%1 %2 %3 %4 %5: %6\n").arg(date.shortMonthName(date.month())).arg(date.day()).arg(time.toString()).arg(hostName).arg(sensorName).arg(value);
+ }
+ }
+
+ logFile.close();
+}
+
+SensorLogger::SensorLogger(QWidget *parent, const char *name, const QString& title)
+ : KSGRD::SensorDisplay(parent, name, title)
+{
+ monitor = new QListView(this, "monitor");
+ Q_CHECK_PTR(monitor);
+
+ monitor->addColumn(i18n("Logging"));
+ monitor->addColumn(i18n("Timer Interval"));
+ monitor->addColumn(i18n("Sensor Name"));
+ monitor->addColumn(i18n("Host Name"));
+ monitor->addColumn(i18n("Log File"));
+
+ QColorGroup cgroup = monitor->colorGroup();
+ cgroup.setColor(QColorGroup::Text, KSGRD::Style->firstForegroundColor());
+ cgroup.setColor(QColorGroup::Base, KSGRD::Style->backgroundColor());
+ cgroup.setColor(QColorGroup::Foreground, KSGRD::Style->alarmColor());
+ monitor->setPalette(QPalette(cgroup, cgroup, cgroup));
+ monitor->setSelectionMode(QListView::NoSelection);
+
+ connect(monitor, SIGNAL(rightButtonClicked(QListViewItem*, const QPoint&, int)), this, SLOT(RMBClicked(QListViewItem*, const QPoint&, int)));
+
+ setTitle(i18n("Sensor Logger"));
+
+ logSensors.setAutoDelete(true);
+
+ setPlotterWidget(monitor);
+
+ setMinimumSize(50, 25);
+ setModified(false);
+}
+
+SensorLogger::~SensorLogger(void)
+{
+}
+
+bool
+SensorLogger::addSensor(const QString& hostName, const QString& sensorName, const QString& sensorType, const QString&)
+{
+ if (sensorType != "integer" && sensorType != "float")
+ return (false);
+
+ sld = new SensorLoggerDlg(this, "SensorLoggerDlg");
+ Q_CHECK_PTR(sld);
+
+ if (sld->exec()) {
+ if (!sld->fileName().isEmpty()) {
+ LogSensor *sensor = new LogSensor(monitor);
+ Q_CHECK_PTR(sensor);
+
+ sensor->setHostName(hostName);
+ sensor->setSensorName(sensorName);
+ sensor->setFileName(sld->fileName());
+ sensor->setTimerInterval(sld->timerInterval());
+ sensor->setLowerLimitActive(sld->lowerLimitActive());
+ sensor->setUpperLimitActive(sld->upperLimitActive());
+ sensor->setLowerLimit(sld->lowerLimit());
+ sensor->setUpperLimit(sld->upperLimit());
+
+ logSensors.append(sensor);
+
+ setModified(true);
+ }
+ }
+
+ delete sld;
+ sld = 0;
+
+ return (true);
+}
+
+bool
+SensorLogger::editSensor(LogSensor* sensor)
+{
+ sld = new SensorLoggerDlg(this, "SensorLoggerDlg");
+ Q_CHECK_PTR(sld);
+
+ sld->setFileName(sensor->getFileName());
+ sld->setTimerInterval(sensor->getTimerInterval());
+ sld->setLowerLimitActive(sensor->getLowerLimitActive());
+ sld->setLowerLimit(sensor->getLowerLimit());
+ sld->setUpperLimitActive(sensor->getUpperLimitActive());
+ sld->setUpperLimit(sensor->getUpperLimit());
+
+ if (sld->exec()) {
+ if (!sld->fileName().isEmpty()) {
+ sensor->setFileName(sld->fileName());
+ sensor->setTimerInterval(sld->timerInterval());
+ sensor->setLowerLimitActive(sld->lowerLimitActive());
+ sensor->setUpperLimitActive(sld->upperLimitActive());
+ sensor->setLowerLimit(sld->lowerLimit());
+ sensor->setUpperLimit(sld->upperLimit());
+
+ setModified(true);
+ }
+ }
+
+ delete sld;
+ sld = 0;
+
+ return (true);
+}
+
+void
+SensorLogger::configureSettings()
+{
+ QColorGroup cgroup = monitor->colorGroup();
+
+ sls = new SensorLoggerSettings(this, "SensorLoggerSettings");
+ Q_CHECK_PTR(sls);
+
+ connect( sls, SIGNAL( applyClicked() ), SLOT( applySettings() ) );
+
+ sls->setTitle(title());
+ sls->setForegroundColor(cgroup.text());
+ sls->setBackgroundColor(cgroup.base());
+ sls->setAlarmColor(cgroup.foreground());
+
+ if (sls->exec())
+ applySettings();
+
+ delete sls;
+ sls = 0;
+}
+
+void
+SensorLogger::applySettings()
+{
+ QColorGroup cgroup = monitor->colorGroup();
+
+ setTitle(sls->title());
+
+ cgroup.setColor(QColorGroup::Text, sls->foregroundColor());
+ cgroup.setColor(QColorGroup::Base, sls->backgroundColor());
+ cgroup.setColor(QColorGroup::Foreground, sls->alarmColor());
+ monitor->setPalette(QPalette(cgroup, cgroup, cgroup));
+
+ setModified(true);
+}
+
+void
+SensorLogger::applyStyle(void)
+{
+ QColorGroup cgroup = monitor->colorGroup();
+
+ cgroup.setColor(QColorGroup::Text, KSGRD::Style->firstForegroundColor());
+ cgroup.setColor(QColorGroup::Base, KSGRD::Style->backgroundColor());
+ cgroup.setColor(QColorGroup::Foreground, KSGRD::Style->alarmColor());
+ monitor->setPalette(QPalette(cgroup, cgroup, cgroup));
+
+ setModified(true);
+}
+
+bool
+SensorLogger::restoreSettings(QDomElement& element)
+{
+ QColorGroup cgroup = monitor->colorGroup();
+
+ cgroup.setColor(QColorGroup::Text, restoreColor(element, "textColor", Qt::green));
+ cgroup.setColor(QColorGroup::Base, restoreColor(element, "backgroundColor", Qt::black));
+ cgroup.setColor(QColorGroup::Foreground, restoreColor(element, "alarmColor", Qt::red));
+ monitor->setPalette(QPalette(cgroup, cgroup, cgroup));
+
+ logSensors.clear();
+
+ QDomNodeList dnList = element.elementsByTagName("logsensors");
+ for (uint i = 0; i < dnList.count(); i++) {
+ QDomElement element = dnList.item(i).toElement();
+ LogSensor* sensor = new LogSensor(monitor);
+ Q_CHECK_PTR(sensor);
+
+ sensor->setHostName(element.attribute("hostName"));
+ sensor->setSensorName(element.attribute("sensorName"));
+ sensor->setFileName(element.attribute("fileName"));
+ sensor->setTimerInterval(element.attribute("timerInterval").toInt());
+ sensor->setLowerLimitActive(element.attribute("lowerLimitActive").toInt());
+ sensor->setLowerLimit(element.attribute("lowerLimit").toDouble());
+ sensor->setUpperLimitActive(element.attribute("upperLimitActive").toInt());
+ sensor->setUpperLimit(element.attribute("upperLimit").toDouble());
+
+ logSensors.append(sensor);
+ }
+
+ SensorDisplay::restoreSettings(element);
+
+ setModified(false);
+
+ return (true);
+}
+
+bool
+SensorLogger::saveSettings(QDomDocument& doc, QDomElement& element, bool save)
+{
+ saveColor(element, "textColor", monitor->colorGroup().text());
+ saveColor(element, "backgroundColor", monitor->colorGroup().base());
+ saveColor(element, "alarmColor", monitor->colorGroup().foreground());
+
+ for (LogSensor* sensor = logSensors.first(); sensor != 0; sensor = logSensors.next())
+ {
+ QDomElement log = doc.createElement("logsensors");
+ log.setAttribute("sensorName", sensor->getSensorName());
+ log.setAttribute("hostName", sensor->getHostName());
+ log.setAttribute("fileName", sensor->getFileName());
+ log.setAttribute("timerInterval", sensor->getTimerInterval());
+ log.setAttribute("lowerLimitActive", QString("%1").arg(sensor->getLowerLimitActive()));
+ log.setAttribute("lowerLimit", QString("%1").arg(sensor->getLowerLimit()));
+ log.setAttribute("upperLimitActive", QString("%1").arg(sensor->getUpperLimitActive()));
+ log.setAttribute("upperLimit", QString("%1").arg(sensor->getUpperLimit()));
+
+ element.appendChild(log);
+ }
+
+ SensorDisplay::saveSettings(doc, element);
+
+ if (save)
+ setModified(false);
+
+ return (true);
+}
+
+void
+SensorLogger::answerReceived(int, const QString&)
+{
+ // we do not use this, since all answers are received by the LogSensors
+}
+
+void
+SensorLogger::resizeEvent(QResizeEvent*)
+{
+ frame()->setGeometry(0, 0, this->width(), this->height());
+ monitor->setGeometry(10, 20, this->width() - 20, this->height() - 30);
+}
+
+LogSensor*
+SensorLogger::getLogSensor(QListViewItem* item)
+{
+ for (LogSensor* sensor = logSensors.first(); sensor != 0; sensor = logSensors.next())
+ {
+ if (item == sensor->getListViewItem()) {
+ return sensor;
+ }
+ }
+
+ return NULL;
+}
+
+void
+SensorLogger::RMBClicked(QListViewItem* item, const QPoint& point, int)
+{
+ QPopupMenu pm;
+ if (hasSettingsDialog())
+ pm.insertItem(i18n("&Properties"), 1);
+ pm.insertItem(i18n("&Remove Display"), 2);
+ pm.insertSeparator(-1);
+ pm.insertItem(i18n("&Remove Sensor"), 3);
+ pm.insertItem(i18n("&Edit Sensor..."), 4);
+
+ if ( !item )
+ {
+ pm.setItemEnabled( 3, false );
+ pm.setItemEnabled( 4, false );
+ }
+ else
+ {
+ LogSensor* sensor = getLogSensor(item);
+
+ if ( sensor->isLogging() )
+ pm.insertItem(i18n("St&op Logging"), 6);
+ else
+ pm.insertItem(i18n("S&tart Logging"), 5);
+ }
+
+ switch (pm.exec(point))
+ {
+ case 1:
+ configureSettings();
+ break;
+ case 2: {
+ QCustomEvent* ev = new QCustomEvent(QEvent::User);
+ ev->setData(this);
+ kapp->postEvent(parent(), ev);
+ break;
+ }
+ case 3: {
+ LogSensor* sensor = getLogSensor(item);
+ if (sensor)
+ logSensors.remove(sensor);
+ break;
+ }
+ case 4: {
+ LogSensor* sensor = getLogSensor(item);
+ if (sensor)
+ editSensor(sensor);
+ break;
+ }
+ case 5: {
+ LogSensor* sensor = getLogSensor(item);
+ if (sensor)
+ sensor->startLogging();
+ break;
+ }
+ case 6: {
+ LogSensor* sensor = getLogSensor(item);
+ if (sensor)
+ sensor->stopLogging();
+ break;
+ }
+ }
+}
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLogger.h b/ksysguard/gui/SensorDisplayLib/SensorLogger.h
new file mode 100644
index 000000000..835e62401
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLogger.h
@@ -0,0 +1,184 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _SensorLogger_h
+#define _SensorLogger_h
+
+#include <qdom.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qlistview.h>
+#include <qpopupmenu.h>
+#include <qspinbox.h>
+#include <qstring.h>
+
+#include <SensorDisplay.h>
+
+#include "SensorLoggerDlg.h"
+
+#define NONE -1
+
+class SensorLoggerSettings;
+
+class SLListViewItem : public QListViewItem
+{
+public:
+ SLListViewItem(QListView *parent = 0);
+
+ void setTextColor(const QColor& color) { textColor = color; }
+
+ void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) {
+ QColorGroup cgroup(cg);
+ cgroup.setColor(QColorGroup::Text, textColor);
+ QListViewItem::paintCell(p, cgroup, column, width, alignment);
+
+ }
+
+ void paintFocus(QPainter *, const QColorGroup, const QRect) {}
+
+private:
+ QColor textColor;
+};
+
+class LogSensor : public QObject, public KSGRD::SensorClient
+{
+ Q_OBJECT
+public:
+ LogSensor(QListView *parent);
+ ~LogSensor(void);
+
+ void answerReceived(int id, const QString& answer);
+
+ void setHostName(const QString& name) { hostName = name; lvi->setText(3, name); }
+ void setSensorName(const QString& name) { sensorName = name; lvi->setText(2, name); }
+ void setFileName(const QString& name)
+ {
+ fileName = name;
+ lvi->setText(4, name);
+ }
+ void setUpperLimitActive(bool value) { upperLimitActive = value; }
+ void setLowerLimitActive(bool value) { lowerLimitActive = value; }
+ void setUpperLimit(double value) { upperLimit = value; }
+ void setLowerLimit(double value) { lowerLimit = value; }
+
+ void setTimerInterval(int interval) {
+ timerInterval = interval;
+
+ if (timerID != NONE)
+ {
+ timerOff();
+ timerOn();
+ }
+
+ lvi->setText(1, QString("%1").arg(interval));
+ }
+
+ QString getSensorName(void) { return sensorName; }
+ QString getHostName(void) { return hostName; }
+ QString getFileName(void) { return fileName; }
+ int getTimerInterval(void) { return timerInterval; }
+ bool getUpperLimitActive(void) { return upperLimitActive; }
+ bool getLowerLimitActive(void) { return lowerLimitActive; }
+ double getUpperLimit(void) { return upperLimit; }
+ double getLowerLimit(void) { return lowerLimit; }
+ QListViewItem* getListViewItem(void) { return lvi; }
+
+public slots:
+ void timerOff()
+ {
+ killTimer(timerID);
+ timerID = NONE;
+ }
+
+ void timerOn()
+ {
+ timerID = startTimer(timerInterval * 1000);
+ }
+
+ bool isLogging() { return timerID != NONE; }
+
+ void startLogging(void);
+ void stopLogging(void);
+
+protected:
+ virtual void timerEvent(QTimerEvent*);
+
+private:
+ QListView* monitor;
+ SLListViewItem* lvi;
+ QPixmap pixmap_running;
+ QPixmap pixmap_waiting;
+ QString sensorName;
+ QString hostName;
+ QString fileName;
+
+ int timerInterval;
+ int timerID;
+
+ bool lowerLimitActive;
+ bool upperLimitActive;
+
+ double lowerLimit;
+ double upperLimit;
+};
+
+class SensorLogger : public KSGRD::SensorDisplay
+{
+ Q_OBJECT
+public:
+ SensorLogger(QWidget *parent = 0, const char *name = 0, const QString& title = 0);
+ ~SensorLogger(void);
+
+ bool addSensor(const QString& hostName, const QString& sensorName, const QString& sensorType,
+ const QString& sensorDescr);
+
+ bool editSensor(LogSensor*);
+
+ void answerReceived(int id, const QString& answer);
+ void resizeEvent(QResizeEvent*);
+
+ bool restoreSettings(QDomElement& element);
+ bool saveSettings(QDomDocument& doc, QDomElement& element, bool save = true);
+
+ void configureSettings(void);
+
+ virtual bool hasSettingsDialog() const
+ {
+ return (true);
+ }
+
+public slots:
+ void applySettings();
+ void applyStyle();
+ void RMBClicked(QListViewItem*, const QPoint&, int);
+
+protected:
+ LogSensor* getLogSensor(QListViewItem*);
+
+private:
+ QListView* monitor;
+
+ QPtrList<LogSensor> logSensors;
+
+ SensorLoggerDlg *sld;
+ SensorLoggerSettings *sls;
+};
+
+#endif // _SensorLogger_h
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.cc b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.cc
new file mode 100644
index 000000000..f07b55ae4
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.cc
@@ -0,0 +1,106 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "SensorLoggerDlg.h"
+#include "SensorLoggerDlgWidget.h"
+
+#include <qlayout.h>
+
+#include <klocale.h>
+
+SensorLoggerDlg::SensorLoggerDlg( QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, i18n( "Sensor Logger" ),
+ Ok|Cancel, Ok, true )
+{
+ QWidget *main = new QWidget( this );
+
+ QVBoxLayout *topLayout = new QVBoxLayout( main, 0, KDialog::spacingHint() );
+
+ m_loggerWidget = new SensorLoggerDlgWidget( main, "m_loggerWidget" );
+ topLayout->addWidget( m_loggerWidget );
+ topLayout->addStretch();
+
+ setMainWidget( main );
+}
+
+QString SensorLoggerDlg::fileName() const
+{
+ return m_loggerWidget->fileName();
+}
+
+int SensorLoggerDlg::timerInterval() const
+{
+ return m_loggerWidget->timerInterval();
+}
+
+bool SensorLoggerDlg::lowerLimitActive() const
+{
+ return m_loggerWidget->lowerLimitActive();
+}
+
+bool SensorLoggerDlg::upperLimitActive() const
+{
+ return m_loggerWidget->upperLimitActive();
+}
+
+double SensorLoggerDlg::lowerLimit() const
+{
+ return m_loggerWidget->lowerLimit();
+}
+
+double SensorLoggerDlg::upperLimit() const
+{
+ return m_loggerWidget->upperLimit();
+}
+
+void SensorLoggerDlg::setFileName( const QString &url )
+{
+ m_loggerWidget->setFileName( url );
+}
+
+void SensorLoggerDlg::setTimerInterval( int i )
+{
+ m_loggerWidget->setTimerInterval( i );
+}
+
+void SensorLoggerDlg::setLowerLimitActive( bool b )
+{
+ m_loggerWidget->setLowerLimitActive( b );
+}
+
+void SensorLoggerDlg::setUpperLimitActive( bool b )
+{
+ m_loggerWidget->setUpperLimitActive( b );
+}
+
+void SensorLoggerDlg::setLowerLimit( double limit )
+{
+ m_loggerWidget->setLowerLimit( limit );
+}
+
+void SensorLoggerDlg::setUpperLimit( double limit )
+{
+ m_loggerWidget->setUpperLimit( limit );
+}
+
+#include "SensorLoggerDlg.moc"
+
+/* vim: et sw=2 ts=2
+*/
+
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.h b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.h
new file mode 100644
index 000000000..3af8290c8
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlg.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or ( at your option ) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef SENSORLOGGERDLG_H
+#define SENSORLOGGERDLG_H
+
+#include <kdialogbase.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+
+class SensorLoggerDlgWidget;
+
+class SensorLoggerDlg : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+
+ SensorLoggerDlg( QWidget *parent=0, const char *name=0 );
+
+ QString fileName() const;
+ int timerInterval() const;
+ bool lowerLimitActive() const;
+ bool upperLimitActive() const;
+ double lowerLimit() const;
+ double upperLimit() const;
+
+ void setFileName( const QString & );
+ void setTimerInterval( int );
+ void setLowerLimitActive( bool );
+ void setUpperLimitActive( bool );
+ void setLowerLimit( double );
+ void setUpperLimit( double );
+
+ private:
+
+ SensorLoggerDlgWidget *m_loggerWidget;
+};
+
+#endif // SENSORLOGGERDLG_H
+
+/* vim: et sw=2 ts=2
+*/
+
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui
new file mode 100644
index 000000000..26d3b2d49
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui
@@ -0,0 +1,263 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>SensorLoggerDlgWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>SensorLoggerDlgWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>363</width>
+ <height>254</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>fileFrame</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>GroupBoxPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>File</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>m_fileName</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>timerFrame</cstring>
+ </property>
+ <property name="title">
+ <string>Timer Interval</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KIntNumInput">
+ <property name="name">
+ <cstring>m_timerInterval</cstring>
+ </property>
+ <property name="value">
+ <number>2</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="maxValue">
+ <number>99</number>
+ </property>
+ <property name="suffix">
+ <string> sec</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Alarm for Minimum Value</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_lowerLimitActive</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Enable alarm</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enable the minimum value alarm.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_lblLowerLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Lower limit:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_lowerLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox1_2</cstring>
+ </property>
+ <property name="title">
+ <string>Alarm for Maximum Value</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_upperLimitActive</cstring>
+ </property>
+ <property name="text">
+ <string>E&amp;nable alarm</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enable the maximum value alarm.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer1_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>m_lblUpperLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Upper limit:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_upperLimit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>70</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>m_lowerLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_lowerLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_upperLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_upperLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_lowerLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_lblLowerLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_upperLimitActive</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_lblUpperLimit</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="global" impldecl="in implementation">kdialog.h</include>
+ <include location="global" impldecl="in implementation">knumvalidator.h</include>
+ <include location="local" impldecl="in implementation">SensorLoggerDlgWidget.ui.h</include>
+</includes>
+<functions>
+ <function access="private" specifier="non virtual">init()</function>
+ <function specifier="non virtual" returnType="QString">fileName()</function>
+ <function specifier="non virtual" returnType="int">timerInterval()</function>
+ <function specifier="non virtual" returnType="bool">lowerLimitActive()</function>
+ <function specifier="non virtual" returnType="double">lowerLimit()</function>
+ <function returnType="bool">upperLimitActive()</function>
+ <function specifier="non virtual" returnType="double">upperLimit()</function>
+ <function specifier="non virtual">setFileName( const QString &amp; url )</function>
+ <function specifier="non virtual">setTimerInterval( int i )</function>
+ <function specifier="non virtual">setLowerLimitActive( bool b )</function>
+ <function specifier="non virtual">setLowerLimit( double d )</function>
+ <function specifier="non virtual">setUpperLimitActive( bool b )</function>
+ <function specifier="non virtual">setUpperLimit( double d )</function>
+</functions>
+
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui.h b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui.h
new file mode 100644
index 000000000..afe0767e9
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerDlgWidget.ui.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+void SensorLoggerDlgWidget::init()
+{
+ m_lowerLimit->setValidator(new KDoubleValidator(m_lowerLimit));
+ m_upperLimit->setValidator(new KDoubleValidator(m_upperLimit));
+ m_timerInterval->setRange(1, 99, 1, true);
+
+ m_fileName->setFocus();
+}
+
+
+QString SensorLoggerDlgWidget::fileName()
+{
+ return m_fileName->url();
+}
+
+
+int SensorLoggerDlgWidget::timerInterval()
+{
+ return m_timerInterval->value();
+}
+
+
+bool SensorLoggerDlgWidget::lowerLimitActive()
+{
+ return m_lowerLimitActive->isChecked();
+}
+
+
+double SensorLoggerDlgWidget::lowerLimit()
+{
+ return m_lowerLimit->text().toDouble();
+}
+
+
+bool SensorLoggerDlgWidget::upperLimitActive()
+{
+ return m_upperLimitActive->isChecked();
+}
+
+
+double SensorLoggerDlgWidget::upperLimit()
+{
+ return m_upperLimit->text().toDouble();
+}
+
+
+void SensorLoggerDlgWidget::setFileName( const QString &url )
+{
+ m_fileName->setURL(url);
+}
+
+
+void SensorLoggerDlgWidget::setTimerInterval( int i )
+{
+ m_timerInterval->setValue(i);
+}
+
+
+void SensorLoggerDlgWidget::setLowerLimitActive( bool b )
+{
+ m_lowerLimitActive->setChecked(b);
+}
+
+
+void SensorLoggerDlgWidget::setLowerLimit( double d )
+{
+ m_lowerLimit->setText(QString("%1").arg(d));
+}
+
+
+void SensorLoggerDlgWidget::setUpperLimitActive( bool b )
+{
+ m_upperLimitActive->setChecked(b);
+}
+
+
+void SensorLoggerDlgWidget::setUpperLimit( double d )
+{
+ m_upperLimit->setText(QString("%1").arg(d));
+}
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.cc b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.cc
new file mode 100644
index 000000000..568108547
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.cc
@@ -0,0 +1,77 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "SensorLoggerSettings.h"
+#include "SensorLoggerSettingsWidget.h"
+
+#include <klocale.h>
+
+SensorLoggerSettings::SensorLoggerSettings( QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, i18n( "Sensor Logger Settings" ),
+ Ok|Apply|Cancel, Ok, true )
+{
+ m_settingsWidget = new SensorLoggerSettingsWidget( this, "m_settingsWidget" );
+ setMainWidget( m_settingsWidget );
+}
+
+QString SensorLoggerSettings::title()
+{
+ return m_settingsWidget->title();
+}
+
+QColor SensorLoggerSettings::foregroundColor()
+{
+ return m_settingsWidget->foregroundColor();
+}
+
+QColor SensorLoggerSettings::backgroundColor()
+{
+ return m_settingsWidget->backgroundColor();
+}
+
+QColor SensorLoggerSettings::alarmColor()
+{
+ return m_settingsWidget->alarmColor();
+}
+
+void SensorLoggerSettings::setTitle( const QString &title )
+{
+ m_settingsWidget->setTitle( title );
+}
+
+void SensorLoggerSettings::setBackgroundColor( const QColor &c )
+{
+ m_settingsWidget->setBackgroundColor( c );
+}
+
+void SensorLoggerSettings::setForegroundColor( const QColor &c )
+{
+ m_settingsWidget->setForegroundColor( c );
+}
+
+void SensorLoggerSettings::setAlarmColor( const QColor &c )
+{
+ m_settingsWidget->setAlarmColor( c );
+}
+
+#include "SensorLoggerSettings.moc"
+
+/* vim: et sw=2 ts=2
+*/
+
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.h b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.h
new file mode 100644
index 000000000..639f55944
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettings.h
@@ -0,0 +1,57 @@
+/* This file is part of the KDE project
+ Copyright ( C ) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or ( at your option ) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef SENSORLOGGERSETTINGS_H
+#define SENSORLOGGERSETTINGS_H
+
+#include <kdialogbase.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+
+class SensorLoggerSettingsWidget;
+
+class SensorLoggerSettings : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+
+ SensorLoggerSettings( QWidget *parent=0, const char *name=0 );
+
+ QString title();
+ QColor foregroundColor();
+ QColor backgroundColor();
+ QColor alarmColor();
+
+ void setTitle( const QString & );
+ void setForegroundColor( const QColor & );
+ void setBackgroundColor( const QColor & );
+ void setAlarmColor( const QColor & );
+
+ private:
+
+ SensorLoggerSettingsWidget *m_settingsWidget;
+};
+
+#endif // SENSORLOGGERSETTINGS_H
+
+/* vim: et sw=2 ts=2
+*/
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui
new file mode 100644
index 000000000..c86e671b2
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui
@@ -0,0 +1,180 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>SensorLoggerSettingsWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>SensorLoggerSettingsWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>415</width>
+ <height>202</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>titleFrame</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="title">
+ <string>Title</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_title</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>colorFrame</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>Box</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="title">
+ <string>Colors</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter|AlignLeft</set>
+ </property>
+ <property name="vAlign" stdset="0">
+ </property>
+ <property name="wordwrap" stdset="0">
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Text color:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Alarm color:</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_foregroundColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_backgroundColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>m_alarmColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<includes>
+ <include location="global" impldecl="in implementation">kdialog.h</include>
+ <include location="local" impldecl="in implementation">SensorLoggerSettingsWidget.ui.h</include>
+</includes>
+<functions>
+ <function specifier="non virtual" returnType="QString">title()</function>
+ <function specifier="non virtual" returnType="QColor">foregroundColor()</function>
+ <function specifier="non virtual" returnType="QColor">backgroundColor()</function>
+ <function specifier="non virtual" returnType="QColor">alarmColor()</function>
+ <function specifier="non virtual">setTitle( const QString &amp; t )</function>
+ <function specifier="non virtual">setForegroundColor( const QColor &amp; c )</function>
+ <function specifier="non virtual">setBackgroundColor( const QColor &amp; c )</function>
+ <function specifier="non virtual">setAlarmColor( const QColor &amp; c )</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+</UI>
diff --git a/ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui.h b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui.h
new file mode 100644
index 000000000..751366466
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SensorLoggerSettingsWidget.ui.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+
+QString SensorLoggerSettingsWidget::title()
+{
+ return m_title->text();
+}
+
+
+QColor SensorLoggerSettingsWidget::foregroundColor()
+{
+ return m_foregroundColor->color();
+}
+
+
+QColor SensorLoggerSettingsWidget::backgroundColor()
+{
+ return m_backgroundColor->color();
+}
+
+
+QColor SensorLoggerSettingsWidget::alarmColor()
+{
+ return m_alarmColor->color();
+}
+
+
+void SensorLoggerSettingsWidget::setTitle( const QString &t )
+{
+ m_title->setText(t);
+}
+
+
+void SensorLoggerSettingsWidget::setForegroundColor( const QColor &c )
+{
+ m_foregroundColor->setColor(c);
+}
+
+
+void SensorLoggerSettingsWidget::setBackgroundColor( const QColor &c )
+{
+ m_backgroundColor->setColor(c);
+}
+
+
+void SensorLoggerSettingsWidget::setAlarmColor( const QColor &c )
+{
+ m_alarmColor->setColor(c);
+}
diff --git a/ksysguard/gui/SensorDisplayLib/SignalPlotter.cc b/ksysguard/gui/SensorDisplayLib/SignalPlotter.cc
new file mode 100644
index 000000000..f8ad121f1
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SignalPlotter.cc
@@ -0,0 +1,648 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2002 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <math.h>
+#include <string.h>
+
+#include <qpainter.h>
+#include <qpixmap.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+
+#include <ksgrd/StyleEngine.h>
+
+#include "SignalPlotter.h"
+
+SignalPlotter::SignalPlotter( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ // Auto deletion does not work for pointer to arrays.
+ mBeamData.setAutoDelete( false );
+
+ setBackgroundMode( NoBackground );
+ mShowThinFrame = true;
+ mSamples = 0;
+ mMinValue = mMaxValue = 0.0;
+ mUseAutoRange = true;
+
+ mGraphStyle = GRAPH_POLYGON;
+
+ // Anything smaller than this does not make sense.
+ setMinimumSize( 16, 16 );
+ setSizePolicy( QSizePolicy( QSizePolicy::Expanding,
+ QSizePolicy::Expanding, false ) );
+
+ mShowVerticalLines = true;
+ mVerticalLinesColor = KSGRD::Style->firstForegroundColor();
+ mVerticalLinesDistance = 30;
+ mVerticalLinesScroll = true;
+ mVerticalLinesOffset = 0;
+ mHorizontalScale = 1;
+
+ mShowHorizontalLines = true;
+ mHorizontalLinesColor = KSGRD::Style->secondForegroundColor();
+ mHorizontalLinesCount = 5;
+
+ mShowLabels = true;
+ mShowTopBar = false;
+ mFontSize = KSGRD::Style->fontSize();
+
+ mBackgroundColor = KSGRD::Style->backgroundColor();
+}
+
+SignalPlotter::~SignalPlotter()
+{
+ for ( double* p = mBeamData.first(); p; p = mBeamData.next() )
+ delete [] p;
+}
+
+bool SignalPlotter::addBeam( const QColor &color )
+{
+ double* d = new double[ mSamples ];
+ memset( d, 0, sizeof(double) * mSamples );
+ mBeamData.append( d );
+ mBeamColor.append( color );
+
+ return true;
+}
+
+void SignalPlotter::addSample( const QValueList<double>& sampleBuf )
+{
+ if ( mBeamData.count() != sampleBuf.count() )
+ return;
+
+ double* d;
+ if ( mUseAutoRange ) {
+ double sum = 0;
+ for ( d = mBeamData.first(); d; d = mBeamData.next() ) {
+ sum += d[ 0 ];
+ if ( sum < mMinValue )
+ mMinValue = sum;
+ if ( sum > mMaxValue )
+ mMaxValue = sum;
+ }
+ }
+
+ /* If the vertical lines are scrolling, increment the offset
+ * so they move with the data. The vOffset / hScale confusion
+ * is because v refers to Vertical Lines, and h to the horizontal
+ * distance between the vertical lines. */
+ if ( mVerticalLinesScroll ) {
+ mVerticalLinesOffset = ( mVerticalLinesOffset + mHorizontalScale)
+ % mVerticalLinesDistance;
+ }
+
+ // Shift data buffers one sample down and insert new samples.
+ QValueList<double>::ConstIterator s;
+ for ( d = mBeamData.first(), s = sampleBuf.begin(); d; d = mBeamData.next(), ++s ) {
+ memmove( d, d + 1, ( mSamples - 1 ) * sizeof( double ) );
+ d[ mSamples - 1 ] = *s;
+ }
+
+ update();
+}
+
+void SignalPlotter::reorderBeams( const QValueList<int>& newOrder )
+{
+ if(newOrder.count() != mBeamData.count()) {
+ kdDebug() << "Serious problem in move sample" << endl;
+ return;
+ }
+ QPtrList<double> newBeamData;
+ QValueList<QColor> newBeamColor;
+
+ for(uint i = 0; i < newOrder.count(); i++) {
+ int newIndex = newOrder[i];
+ newBeamData.append(mBeamData.at(newIndex));
+ newBeamColor.append(*mBeamColor.at(newIndex));
+ }
+ mBeamData = newBeamData;
+ mBeamColor = newBeamColor;
+
+}
+
+void SignalPlotter::changeRange( int beam, double min, double max )
+{
+ // Only the first beam affects range calculation.
+ if ( beam > 1 )
+ return;
+
+ mMinValue = min;
+ mMaxValue = max;
+}
+
+QValueList<QColor> &SignalPlotter::beamColors()
+{
+ return mBeamColor;
+}
+
+void SignalPlotter::removeBeam( uint pos )
+{
+ mBeamColor.remove( mBeamColor.at( pos ) );
+ double *p = mBeamData.take( pos );
+ delete [] p;
+}
+
+void SignalPlotter::setTitle( const QString &title )
+{
+ mTitle = title;
+}
+
+QString SignalPlotter::title() const
+{
+ return mTitle;
+}
+
+void SignalPlotter::setUseAutoRange( bool value )
+{
+ mUseAutoRange = value;
+}
+
+bool SignalPlotter::useAutoRange() const
+{
+ return mUseAutoRange;
+}
+
+void SignalPlotter::setMinValue( double min )
+{
+ mMinValue = min;
+}
+
+double SignalPlotter::minValue() const
+{
+ return ( mUseAutoRange ? 0 : mMinValue );
+}
+
+void SignalPlotter::setMaxValue( double max )
+{
+ mMaxValue = max;
+}
+
+double SignalPlotter::maxValue() const
+{
+ return ( mUseAutoRange ? 0 : mMaxValue );
+}
+
+void SignalPlotter::setGraphStyle( uint style )
+{
+ mGraphStyle = style;
+}
+
+uint SignalPlotter::graphStyle() const
+{
+ return mGraphStyle;
+}
+
+void SignalPlotter::setHorizontalScale( uint scale )
+{
+ if (scale == mHorizontalScale)
+ return;
+
+ mHorizontalScale = scale;
+ if (isVisible())
+ updateDataBuffers();
+}
+
+int SignalPlotter::horizontalScale() const
+{
+ return mHorizontalScale;
+}
+
+void SignalPlotter::setShowVerticalLines( bool value )
+{
+ mShowVerticalLines = value;
+}
+
+bool SignalPlotter::showVerticalLines() const
+{
+ return mShowVerticalLines;
+}
+
+void SignalPlotter::setVerticalLinesColor( const QColor &color )
+{
+ mVerticalLinesColor = color;
+}
+
+QColor SignalPlotter::verticalLinesColor() const
+{
+ return mVerticalLinesColor;
+}
+
+void SignalPlotter::setVerticalLinesDistance( int distance )
+{
+ mVerticalLinesDistance = distance;
+}
+
+int SignalPlotter::verticalLinesDistance() const
+{
+ return mVerticalLinesDistance;
+}
+
+void SignalPlotter::setVerticalLinesScroll( bool value )
+{
+ mVerticalLinesScroll = value;
+}
+
+bool SignalPlotter::verticalLinesScroll() const
+{
+ return mVerticalLinesScroll;
+}
+
+void SignalPlotter::setShowHorizontalLines( bool value )
+{
+ mShowHorizontalLines = value;
+}
+
+bool SignalPlotter::showHorizontalLines() const
+{
+ return mShowHorizontalLines;
+}
+
+void SignalPlotter::setHorizontalLinesColor( const QColor &color )
+{
+ mHorizontalLinesColor = color;
+}
+
+QColor SignalPlotter::horizontalLinesColor() const
+{
+ return mHorizontalLinesColor;
+}
+
+void SignalPlotter::setHorizontalLinesCount( int count )
+{
+ mHorizontalLinesCount = count;
+}
+
+int SignalPlotter::horizontalLinesCount() const
+{
+ return mHorizontalLinesCount;
+}
+
+void SignalPlotter::setShowLabels( bool value )
+{
+ mShowLabels = value;
+}
+
+bool SignalPlotter::showLabels() const
+{
+ return mShowLabels;
+}
+
+void SignalPlotter::setShowTopBar( bool value )
+{
+ mShowTopBar = value;
+}
+
+bool SignalPlotter::showTopBar() const
+{
+ return mShowTopBar;
+}
+
+void SignalPlotter::setFontSize( int size )
+{
+ mFontSize = size;
+}
+
+int SignalPlotter::fontSize() const
+{
+ return mFontSize;
+}
+
+void SignalPlotter::setBackgroundColor( const QColor &color )
+{
+ mBackgroundColor = color;
+}
+
+QColor SignalPlotter::backgroundColor() const
+{
+ return mBackgroundColor;
+}
+
+void SignalPlotter::resizeEvent( QResizeEvent* )
+{
+ Q_ASSERT( width() > 2 );
+
+ updateDataBuffers();
+}
+
+void SignalPlotter::updateDataBuffers()
+{
+ /* Since the data buffers for the beams are equal in size to the
+ * width of the widget minus 2 we have to enlarge or shrink the
+ * buffers accordingly when a resize occures. To have a nicer
+ * display we try to keep as much data as possible. Data that is
+ * lost due to shrinking the buffers cannot be recovered on
+ * enlarging though. */
+
+ /* Determine new number of samples first.
+ * +0.5 to ensure rounding up
+ * +2 for extra data points so there is
+ * 1) no wasted space and
+ * 2) no loss of precision when drawing the first data point. */
+ uint newSampleNum = static_cast<uint>( ( ( width() - 2 ) /
+ mHorizontalScale ) + 2.5 );
+
+ // overlap between the old and the new buffers.
+ int overlap = kMin( mSamples, newSampleNum );
+
+ for ( uint i = 0; i < mBeamData.count(); ++i ) {
+ double* nd = new double[ newSampleNum ];
+
+ // initialize new part of the new buffer
+ if ( newSampleNum > (uint)overlap )
+ memset( nd, 0, sizeof( double ) * ( newSampleNum - overlap ) );
+
+ // copy overlap from old buffer to new buffer
+ memcpy( nd + ( newSampleNum - overlap ), mBeamData.at( i ) +
+ ( mSamples - overlap ), overlap * sizeof( double ) );
+
+ double *p = mBeamData.take( i );
+ delete [] p;
+ mBeamData.insert( i, nd );
+ }
+
+ mSamples = newSampleNum;
+}
+
+void SignalPlotter::paintEvent( QPaintEvent* )
+{
+ uint w = width();
+ uint h = height();
+
+ /* Do not do repaints when the widget is not yet setup properly. */
+ if ( w <= 2 )
+ return;
+
+ QPixmap pm( w, h );
+ QPainter p;
+ p.begin( &pm, this );
+
+ pm.fill( mBackgroundColor );
+ /* Draw white line along the bottom and the right side of the
+ * widget to create a 3D like look. */
+ p.setPen( QColor( colorGroup().light() ) );
+ if(mShowThinFrame) {
+ p.drawLine( 0, h - 1, w - 1, h - 1 );
+ p.drawLine( w - 1, 0, w - 1, h - 1 );
+
+ h--;
+ w--;
+ p.setClipRect( 0, 0, w, h );
+ }
+ double range = mMaxValue - mMinValue;
+
+ /* If the range is too small we will force it to 1.0 since it
+ * looks a lot nicer. */
+ if ( range < 0.000001 )
+ range = 1.0;
+
+ double minValue = mMinValue;
+ if ( mUseAutoRange ) {
+ if ( mMinValue != 0.0 ) {
+ double dim = pow( 10, floor( log10( fabs( mMinValue ) ) ) ) / 2;
+ if ( mMinValue < 0.0 )
+ minValue = dim * floor( mMinValue / dim );
+ else
+ minValue = dim * ceil( mMinValue / dim );
+ range = mMaxValue - minValue;
+ if ( range < 0.000001 )
+ range = 1.0;
+ }
+ // Massage the range so that the grid shows some nice values.
+ double step = range / (mHorizontalLinesCount+1);
+ double dim = pow( 10, floor( log10( step ) ) ) / 2;
+ range = dim * ceil( step / dim ) * (mHorizontalLinesCount+1);
+ }
+ double maxValue = minValue + range;
+
+ int top = 0;
+ if ( mShowTopBar && h > ( mFontSize/*top bar size*/ + 2/*padding*/ +5/*smallest reasonable size for a graph*/ ) ) {
+ /* Draw horizontal bar with current sensor values at top of display. */
+ p.setPen( mHorizontalLinesColor );
+ int x0 = w / 2;
+ p.setFont( QFont( p.font().family(), mFontSize ) );
+ top = p.fontMetrics().height();
+ h -= top;
+ int h0 = top - 2; // h0 is our new top. It's at least 5 pixels high
+ p.drawText(0, 0, x0, top - 2, Qt::AlignCenter, mTitle );
+
+ p.drawLine( x0 - 1, 1, x0 - 1, h0 );
+ p.drawLine( 0, top - 1, w - 2, top - 1 );
+
+ double bias = -minValue;
+ double scaleFac = ( w - x0 - 2 ) / range;
+ QValueList<QColor>::Iterator col;
+ col = mBeamColor.begin();
+ for ( double* d = mBeamData.first(); d; d = mBeamData.next(), ++col ) {
+ int start = x0 + (int)( bias * scaleFac );
+ int end = x0 + (int)( ( bias += d[ mSamples - 1 ] ) * scaleFac );
+ /* If the rect is wider than 2 pixels we draw only the last
+ * pixels with the bright color. The rest is painted with
+ * a 50% darker color. */
+ if ( end - start > 1 ) {
+ p.setPen( (*col).dark( 150 ) );
+ p.setBrush( (*col).dark( 150 ) );
+ p.drawRect( start, 1, end - start, h0 );
+ p.setPen( *col );
+ p.drawLine( end, 1, end, h0 );
+ } else if ( start - end > 1 ) {
+ p.setPen( (*col).dark( 150 ) );
+ p.setBrush( (*col).dark( 150 ) );
+ p.drawRect( end, 1, start - end, h0 );
+ p.setPen( *col );
+ p.drawLine( end, 1, end, h0 );
+ } else {
+ p.setPen( *col );
+ p.drawLine( start, 1, start, h0 );
+ }
+ }
+ }
+
+ /* Draw scope-like grid vertical lines */
+ if ( mShowVerticalLines && w > 60 ) {
+ p.setPen( mVerticalLinesColor );
+ for ( uint x = mVerticalLinesOffset; x < ( w - 2 ); x += mVerticalLinesDistance )
+ p.drawLine( w - x, top, w - x, h + top - 2 );
+ }
+
+ /* In autoRange mode we determine the range and plot the values in
+ * one go. This is more efficiently than running through the
+ * buffers twice but we do react on recently discarded samples as
+ * well as new samples one plot too late. So the range is not
+ * correct if the recently discarded samples are larger or smaller
+ * than the current extreme values. But we can probably live with
+ * this. */
+ if ( mUseAutoRange )
+ mMinValue = mMaxValue = 0.0;
+
+ /* Plot stacked values */
+ double scaleFac = ( h - 2 ) / range;
+ if ( mGraphStyle == GRAPH_ORIGINAL ) {
+ int xPos = 0;
+ for ( int i = 0; i < mSamples; i++, xPos += mHorizontalScale ) {
+ double bias = -minValue;
+ QValueList<QColor>::Iterator col;
+ col = mBeamColor.begin();
+ double sum = 0.0;
+ for ( double* d = mBeamData.first(); d; d = mBeamData.next(), ++col ) {
+ if ( mUseAutoRange ) {
+ sum += d[ i ];
+ if ( sum < mMinValue )
+ mMinValue = sum;
+ if ( sum > mMaxValue )
+ mMaxValue = sum;
+ }
+ int start = top + h - 2 - (int)( bias * scaleFac );
+ int end = top + h - 2 - (int)( ( bias + d[ i ] ) * scaleFac );
+ bias += d[ i ];
+ /* If the line is longer than 2 pixels we draw only the last
+ * 2 pixels with the bright color. The rest is painted with
+ * a 50% darker color. */
+ if ( end - start > 2 ) {
+ p.fillRect( xPos, start, mHorizontalScale, end - start - 1, (*col).dark( 150 ) );
+ p.fillRect( xPos, end - 1, mHorizontalScale, 2, *col );
+ } else if ( start - end > 2 ) {
+ p.fillRect( xPos, start, mHorizontalScale, end - start + 1, (*col).dark( 150 ) );
+ p.fillRect( xPos, end + 1, mHorizontalScale, 2, *col );
+ } else
+ p.fillRect( xPos, start, mHorizontalScale, end - start, *col );
+
+ }
+ }
+ } else if ( mGraphStyle == GRAPH_POLYGON ) {
+ int *prevVals = new int[ mBeamData.count() ];
+ int hack[ 4 ];
+ hack[ 0 ] = hack[ 1 ] = hack[ 2 ] = hack[ 3 ] = 0;
+ int x1 = w - ( ( mSamples + 1 ) * mHorizontalScale );
+
+ for ( int i = 0; i < mSamples; i++ ) {
+ QValueList<QColor>::Iterator col;
+ col = mBeamColor.begin();
+ double sum = 0.0;
+ int y = top + h - 2;
+ int oldY = top + h;
+ int oldPrevY = oldY;
+ int height = 0;
+ int j = 0;
+ int jMax = mBeamData.count() - 1;
+ x1 += mHorizontalScale;
+ int x2 = x1 + mHorizontalScale;
+
+ for ( double* d = mBeamData.first(); d; d = mBeamData.next(), ++col, j++ ) {
+ if ( mUseAutoRange ) {
+ sum += d[ i ];
+ if ( sum < mMinValue )
+ mMinValue = sum;
+ if ( sum > mMaxValue )
+ mMaxValue = sum;
+ }
+ height = (int)( ( d[ i ] - minValue ) * scaleFac );
+ y -= height;
+
+ /* If the line is longer than 2 pixels we draw only the last
+ * 2 pixels with the bright color. The rest is painted with
+ * a 50% darker color. */
+ QPen lastPen = QPen( p.pen() );
+ p.setPen( (*col).dark( 150 ) );
+ p.setBrush( (*col).dark( 150 ) );
+ QPointArray pa( 4 );
+ int prevY = ( i == 0 ) ? y : prevVals[ j ];
+ pa.putPoints( 0, 1, x1, prevY );
+ pa.putPoints( 1, 1, x2, y );
+ pa.putPoints( 2, 1, x2, oldY );
+ pa.putPoints( 3, 1, x1, oldPrevY );
+ p.drawPolygon( pa );
+ p.setPen( lastPen );
+ if ( jMax == 0 ) {
+ // draw as normal, no deferred drawing req'd.
+ p.setPen( *col );
+ p.drawLine( x1, prevY, x2, y );
+ } else if ( j == jMax ) {
+ // draw previous values and current values
+ p.drawLine( hack[ 0 ], hack[ 1 ], hack[ 2 ], hack[ 3 ] );
+ p.setPen( *col );
+ p.drawLine( x1, prevY, x2, y );
+ } else if ( j == 0 ) {
+ // save values only
+ hack[ 0 ] = x1;
+ hack[ 1 ] = prevY;
+ hack[ 2 ] = x2;
+ hack[ 3 ] = y;
+ p.setPen( *col );
+ } else {
+ p.drawLine( hack[ 0 ], hack[ 1 ], hack[ 2 ], hack[ 3 ] );
+ hack[ 0 ] = x1;
+ hack[ 1 ] = prevY;
+ hack[ 2 ] = x2;
+ hack[ 3 ] = y;
+ p.setPen( *col );
+ }
+
+ prevVals[ j ] = y;
+ oldY = y;
+ oldPrevY = prevY;
+ }
+ }
+
+ delete[] prevVals;
+ }
+
+ /* Draw horizontal lines and values. Lines are always drawn.
+ * Values are only draw when width is greater than 60 */
+ if ( mShowHorizontalLines ) {
+ p.setPen( mHorizontalLinesColor );
+ p.setFont( QFont( p.font().family(), mFontSize ) );
+ QString val;
+
+ /* top = 0 or font.height depending on whether there's a topbar or not
+ * h = graphing area.height - i.e. the actual space we have to draw inside
+ *
+ * Note we are drawing from 0,0 as the top left corner. So we have to add on top to get to the top of where we are drawing
+ * so top+h is the height of the widget
+ */
+ for ( uint y = 1; y <= mHorizontalLinesCount; y++ ) {
+
+ int y_coord = top + (y * h) / (mHorizontalLinesCount+1); //Make sure it's y*h first to avoid rounding bugs
+ p.drawLine( 0, y_coord, w - 2, y_coord );
+
+ if ( mShowLabels && h > ( mFontSize + 1 ) * ( mHorizontalLinesCount + 1 )
+ && w > 60 ) {
+ val = QString::number(maxValue - (y * range) / (mHorizontalLinesCount+1 ) );
+ p.drawText( 6, y_coord - 1, val ); //draw the text one pixel raised above the line
+ }
+ }
+
+ //Draw the bottom most (minimum) number as well
+ if ( mShowLabels && h > ( mFontSize + 1 ) * ( mHorizontalLinesCount + 1 )
+ && w > 60 ) {
+ val = QString::number( minValue );
+ p.drawText( 6, top + h - 2, val );
+ }
+ }
+
+ p.end();
+ bitBlt( this, 0, 0, &pm );
+}
+
+#include "SignalPlotter.moc"
diff --git a/ksysguard/gui/SensorDisplayLib/SignalPlotter.h b/ksysguard/gui/SensorDisplayLib/SignalPlotter.h
new file mode 100644
index 000000000..9a9544b3c
--- /dev/null
+++ b/ksysguard/gui/SensorDisplayLib/SignalPlotter.h
@@ -0,0 +1,147 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_SIGNALPLOTTER_H
+#define KSG_SIGNALPLOTTER_H
+
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <qwidget.h>
+
+#define GRAPH_POLYGON 0
+#define GRAPH_ORIGINAL 1
+
+class QColor;
+
+class SignalPlotter : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ SignalPlotter( QWidget *parent = 0, const char *name = 0 );
+ ~SignalPlotter();
+
+ bool addBeam( const QColor &color );
+ void addSample( const QValueList<double> &samples );
+
+ void removeBeam( uint pos );
+
+ void changeRange( int beam, double min, double max );
+
+ QValueList<QColor> &beamColors();
+
+ void setTitle( const QString &title );
+ QString title() const;
+
+ void setUseAutoRange( bool value );
+ bool useAutoRange() const;
+
+ void setMinValue( double min );
+ double minValue() const;
+
+ void setMaxValue( double max );
+ double maxValue() const;
+
+ void setGraphStyle( uint style );
+ uint graphStyle() const;
+
+ void setHorizontalScale( uint scale );
+ int horizontalScale() const;
+
+ void setShowVerticalLines( bool value );
+ bool showVerticalLines() const;
+
+ void setVerticalLinesColor( const QColor &color );
+ QColor verticalLinesColor() const;
+
+ void setVerticalLinesDistance( int distance );
+ int verticalLinesDistance() const;
+
+ void setVerticalLinesScroll( bool value );
+ bool verticalLinesScroll() const;
+
+ void setShowHorizontalLines( bool value );
+ bool showHorizontalLines() const;
+
+ void setHorizontalLinesColor( const QColor &color );
+ QColor horizontalLinesColor() const;
+
+ void setHorizontalLinesCount( int count );
+ int horizontalLinesCount() const;
+
+ void setShowLabels( bool value );
+ bool showLabels() const;
+
+ void setShowTopBar( bool value );
+ bool showTopBar() const;
+
+ void setFontSize( int size );
+ int fontSize() const;
+
+ void setBackgroundColor( const QColor &color );
+ QColor backgroundColor() const;
+ void reorderBeams( const QValueList<int>& newOrder );
+
+ void setThinFrame(bool set) { mShowThinFrame = set; }
+
+ protected:
+ void updateDataBuffers();
+
+ virtual void resizeEvent( QResizeEvent* );
+ virtual void paintEvent( QPaintEvent* );
+
+ private:
+ double mMinValue;
+ double mMaxValue;
+ bool mUseAutoRange;
+ bool mShowThinFrame;
+
+ uint mGraphStyle;
+
+ bool mShowVerticalLines;
+ QColor mVerticalLinesColor;
+ uint mVerticalLinesDistance;
+ bool mVerticalLinesScroll;
+ uint mVerticalLinesOffset;
+ uint mHorizontalScale;
+
+ bool mShowHorizontalLines;
+ QColor mHorizontalLinesColor;
+ uint mHorizontalLinesCount;
+
+ bool mShowLabels;
+ bool mShowTopBar;
+ uint mFontSize;
+
+ QColor mBackgroundColor;
+
+ QPtrList<double> mBeamData;
+ QValueList<QColor> mBeamColor;
+
+ unsigned int mSamples;
+
+ QString mTitle;
+};
+
+#endif
diff --git a/ksysguard/gui/SignalIDs.h b/ksysguard/gui/SignalIDs.h
new file mode 100644
index 000000000..16df1b1e1
--- /dev/null
+++ b/ksysguard/gui/SignalIDs.h
@@ -0,0 +1,52 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>. Please do
+ not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_SIGNALIDS_H
+#define KSG_SIGNALIDS_H
+
+/* This file is used to correlate the entries of the process popup menu
+ * of the ProcessList class and the value received by the kill command
+ * in ksysguardd. We limit the set of available signals to the POSIX.1
+ * set with job control. */
+
+#define MENU_ID_SIGABRT 11
+#define MENU_ID_SIGALRM 12
+#define MENU_ID_SIGCHLD 13
+#define MENU_ID_SIGCONT 14
+#define MENU_ID_SIGFPE 15
+#define MENU_ID_SIGHUP 16
+#define MENU_ID_SIGILL 17
+#define MENU_ID_SIGINT 18
+#define MENU_ID_SIGKILL 19
+#define MENU_ID_SIGPIPE 20
+#define MENU_ID_SIGQUIT 21
+#define MENU_ID_SIGSEGV 22
+#define MENU_ID_SIGSTOP 23
+#define MENU_ID_SIGTERM 24
+#define MENU_ID_SIGTSTP 25
+#define MENU_ID_SIGTTIN 26
+#define MENU_ID_SIGTTOU 27
+#define MENU_ID_SIGUSR1 28
+#define MENU_ID_SIGUSR2 29
+
+#endif
diff --git a/ksysguard/gui/SystemLoad.sgrd b/ksysguard/gui/SystemLoad.sgrd
new file mode 100644
index 000000000..139187e93
--- /dev/null
+++ b/ksysguard/gui/SystemLoad.sgrd
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE KSysGuardWorkSheet>
+<WorkSheet rows="2" interval="2" columns="2" >
+ <host port="-1" shell="" name="localhost" command="ksysguardd" />
+ <display topBar="0" vColor="326429" title="CPU Load" bColor="3223601" graphStyle="0" class="FancyPlotter" row="0" unit="" hScale="1" column="0" showUnit="0" hLines="1" hCount="5" vLines="1" autoRange="0" min="0" max="100" hColor="326429" globalUpdate="1" pause="0" fontSize="9" labels="1" vScroll="1" vDistance="30" >
+ <beam sensorName="cpu/user" hostName="localhost" color="1608191" sensorType="integer" />
+ <beam sensorName="cpu/sys" hostName="localhost" color="16743688" sensorType="integer" />
+ <beam sensorName="cpu/nice" hostName="localhost" color="16771600" sensorType="integer" />
+ </display>
+ <display topBar="0" vColor="326429" title="Load Average (1 min)" bColor="3223601" graphStyle="0" class="FancyPlotter" row="0" unit="" hScale="1" column="1" showUnit="0" hLines="1" hCount="5" vLines="1" autoRange="1" min="0" max="0" hColor="326429" globalUpdate="1" pause="0" fontSize="9" labels="1" vScroll="1" vDistance="30" >
+ <beam sensorName="cpu/loadavg1" hostName="localhost" color="1608191" sensorType="float" />
+ </display>
+ <display topBar="0" vColor="326429" title="Physical Memory"
+bColor="3223601" graphStyle="0" class="FancyPlotter" row="1" unit=""
+hScale="1" column="0" showUnit="0" hLines="1" hCount="5" vLines="1"
+autoRange="0" min="0" max="0" hColor="326429" globalUpdate="1" pause="0" fontSize="9" labels="1" vScroll="1" vDistance="30" >
+ <beam sensorName="mem/physical/application" hostName="localhost" color="1608191" sensorType="integer" />
+ <beam sensorName="mem/physical/buf" hostName="localhost" color="16743688" sensorType="integer" />
+ <beam sensorName="mem/physical/cached" hostName="localhost" color="16771600" sensorType="integer" />
+ </display>
+ <display topBar="0" vColor="326429" title="Swap Memory"
+bColor="3223601" graphStyle="0" class="FancyPlotter" row="1" unit=""
+hScale="1" column="1" showUnit="0" hLines="1" hCount="5" vLines="1"
+autoRange="0" min="0" max="0" hColor="326429" globalUpdate="1" pause="0" fontSize="9" labels="1" vScroll="1" vDistance="30" >
+ <beam sensorName="mem/swap/used" hostName="localhost" color="1608191" sensorType="integer" />
+ </display>
+</WorkSheet>
diff --git a/ksysguard/gui/Taskmanager.ktop b/ksysguard/gui/Taskmanager.ktop
new file mode 100644
index 000000000..00e5ec5ce
--- /dev/null
+++ b/ksysguard/gui/Taskmanager.ktop
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE KSysGuardWorkSheet >
+<WorkSheet rows="1" columns="1">
+<host name="localhost" shell="" command="ksysguardd"/>
+<display row="0" column="0" class="ProcessController" hostName="localhost" sensorName="ps" sensorType="table" tree="off" pause="off" filter="0">
+</display>
+</WorkSheet>
diff --git a/ksysguard/gui/WorkSheet.cc b/ksysguard/gui/WorkSheet.cc
new file mode 100644
index 000000000..f6555a1c6
--- /dev/null
+++ b/ksysguard/gui/WorkSheet.cc
@@ -0,0 +1,698 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <qclipboard.h>
+#include <qcursor.h>
+#include <qdragobject.h>
+#include <qfile.h>
+#include <qlayout.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kpopupmenu.h>
+
+#include <SensorManager.h>
+
+#include "DancingBars.h"
+#include "DummyDisplay.h"
+#include "FancyPlotter.h"
+#include "ListView.h"
+#include "LogFile.h"
+#include "MultiMeter.h"
+#include "ProcessController.h"
+#include "SensorLogger.h"
+#include "WorkSheet.h"
+#include "WorkSheetSettings.h"
+
+WorkSheet::WorkSheet( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ mGridLayout = 0;
+ mRows = mColumns = 0;
+ mDisplayList = 0;
+ mModified = false;
+ mFileName = "";
+
+ setAcceptDrops( true );
+}
+
+WorkSheet::WorkSheet( uint rows, uint columns, uint interval, QWidget* parent,
+ const char *name )
+ : QWidget( parent, name )
+{
+ mRows = mColumns = 0;
+ mGridLayout = 0;
+ mDisplayList = 0;
+ updateInterval( interval );
+ mModified = false;
+ mFileName = "";
+
+ createGrid( rows, columns );
+
+ // Initialize worksheet with dummy displays.
+ for ( uint r = 0; r < mRows; ++r )
+ for ( uint c = 0; c < mColumns; ++c )
+ replaceDisplay( r, c );
+
+ mGridLayout->activate();
+
+ setAcceptDrops( true );
+}
+
+WorkSheet::~WorkSheet()
+{
+}
+
+bool WorkSheet::load( const QString &fileName )
+{
+ setModified( false );
+
+ mFileName = fileName;
+ QFile file( mFileName );
+ if ( !file.open( IO_ReadOnly ) ) {
+ KMessageBox::sorry( this, i18n( "Cannot open the file %1." ).arg( mFileName ) );
+ return false;
+ }
+
+ QDomDocument doc;
+
+ // Read in file and check for a valid XML header.
+ if ( !doc.setContent( &file) ) {
+ KMessageBox::sorry( this, i18n( "The file %1 does not contain valid XML." )
+ .arg( mFileName ) );
+ return false;
+ }
+
+ // Check for proper document type.
+ if ( doc.doctype().name() != "KSysGuardWorkSheet" ) {
+ KMessageBox::sorry( this, i18n( "The file %1 does not contain a valid worksheet "
+ "definition, which must have a document type 'KSysGuardWorkSheet'.")
+ .arg( mFileName ) );
+ return false;
+ }
+
+ // Check for proper size.
+ QDomElement element = doc.documentElement();
+ updateInterval( element.attribute( "interval" ).toUInt() );
+ if ( updateInterval() < 1 || updateInterval() > 300 )
+ updateInterval( 2 );
+
+ bool rowsOk, columnsOk;
+ uint rows = element.attribute( "rows" ).toUInt( &rowsOk );
+ uint columns = element.attribute( "columns" ).toUInt( &columnsOk );
+ if ( !( rowsOk && columnsOk ) ) {
+ KMessageBox::sorry( this, i18n("The file %1 has an invalid worksheet size.")
+ .arg( mFileName ) );
+ return false;
+ }
+
+ createGrid( rows, columns );
+
+ uint i;
+ /* Load lists of hosts that are needed for the work sheet and try
+ * to establish a connection. */
+ QDomNodeList dnList = element.elementsByTagName( "host" );
+ for ( i = 0; i < dnList.count(); ++i ) {
+ QDomElement element = dnList.item( i ).toElement();
+ bool ok;
+ int port = element.attribute( "port" ).toInt( &ok );
+ if ( !ok )
+ port = -1;
+ KSGRD::SensorMgr->engage( element.attribute( "name" ),
+ element.attribute( "shell" ),
+ element.attribute( "command" ), port );
+ }
+ //if no hosts are specified, at least connect to localhost
+ if(dnList.count() == 0)
+ KSGRD::SensorMgr->engage( "localhost", "", "ksysguardd", -1);
+
+ // Load the displays and place them into the work sheet.
+ dnList = element.elementsByTagName( "display" );
+ for ( i = 0; i < dnList.count(); ++i ) {
+ QDomElement element = dnList.item( i ).toElement();
+ uint row = element.attribute( "row" ).toUInt();
+ uint column = element.attribute( "column" ).toUInt();
+ if ( row >= mRows || column >= mColumns) {
+ kdDebug(1215) << "Row or Column out of range (" << row << ", "
+ << column << ")" << endl;
+ return false;
+ }
+
+ replaceDisplay( row, column, element );
+ }
+
+ // Fill empty cells with dummy displays
+ for ( uint r = 0; r < mRows; ++r )
+ for ( uint c = 0; c < mColumns; ++c )
+ if ( !mDisplayList[ r ][ c ] )
+ replaceDisplay( r, c );
+
+ setModified( false );
+
+ return true;
+}
+
+bool WorkSheet::save( const QString &fileName )
+{
+ mFileName = fileName;
+
+ QDomDocument doc( "KSysGuardWorkSheet" );
+ doc.appendChild( doc.createProcessingInstruction(
+ "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
+
+ // save work sheet information
+ QDomElement ws = doc.createElement( "WorkSheet" );
+ doc.appendChild( ws );
+ ws.setAttribute( "interval", updateInterval() );
+ ws.setAttribute( "rows", mRows );
+ ws.setAttribute( "columns", mColumns );
+
+ QStringList hosts;
+ collectHosts( hosts );
+
+ // save host information (name, shell, etc.)
+ QStringList::Iterator it;
+ for ( it = hosts.begin(); it != hosts.end(); ++it ) {
+ QString shell, command;
+ int port;
+
+ if ( KSGRD::SensorMgr->hostInfo( *it, shell, command, port ) ) {
+ QDomElement host = doc.createElement( "host" );
+ ws.appendChild( host );
+ host.setAttribute( "name", *it );
+ host.setAttribute( "shell", shell );
+ host.setAttribute( "command", command );
+ host.setAttribute( "port", port );
+ }
+ }
+
+ for ( uint r = 0; r < mRows; ++r )
+ for (uint c = 0; c < mColumns; ++c )
+ if ( !mDisplayList[ r ][ c ]->isA( "DummyDisplay" ) ) {
+ KSGRD::SensorDisplay* display = (KSGRD::SensorDisplay*)mDisplayList[ r ][ c ];
+ QDomElement element = doc.createElement( "display" );
+ ws.appendChild( element );
+ element.setAttribute( "row", r );
+ element.setAttribute( "column", c );
+ element.setAttribute( "class", display->className() );
+
+ display->saveSettings( doc, element );
+ }
+
+ QFile file( mFileName );
+ if ( !file.open( IO_WriteOnly ) ) {
+ KMessageBox::sorry( this, i18n( "Cannot save file %1" ).arg( mFileName ) );
+ return false;
+ }
+
+ QTextStream s( &file );
+ s.setEncoding( QTextStream::UnicodeUTF8 );
+ s << doc;
+ file.close();
+
+ setModified( false );
+
+ return true;
+}
+
+void WorkSheet::cut()
+{
+ if ( !currentDisplay() || currentDisplay()->isA( "DummyDisplay" ) )
+ return;
+
+ QClipboard* clip = QApplication::clipboard();
+
+ clip->setText( currentDisplayAsXML() );
+
+ removeDisplay( currentDisplay() );
+}
+
+void WorkSheet::copy()
+{
+ if ( !currentDisplay() || currentDisplay()->isA( "DummyDisplay" ) )
+ return;
+
+ QClipboard* clip = QApplication::clipboard();
+
+ clip->setText( currentDisplayAsXML() );
+}
+
+void WorkSheet::paste()
+{
+ uint row, column;
+ if ( !currentDisplay( &row, &column ) )
+ return;
+
+ QClipboard* clip = QApplication::clipboard();
+
+ QDomDocument doc;
+ /* Get text from clipboard and check for a valid XML header and
+ * proper document type. */
+ if ( !doc.setContent( clip->text() ) || doc.doctype().name() != "KSysGuardDisplay" ) {
+ KMessageBox::sorry( this, i18n("The clipboard does not contain a valid display "
+ "description." ) );
+ return;
+ }
+
+ QDomElement element = doc.documentElement();
+ replaceDisplay( row, column, element );
+}
+
+void WorkSheet::setFileName( const QString &fileName )
+{
+ mFileName = fileName;
+ setModified( true );
+}
+
+const QString& WorkSheet::fileName() const
+{
+ return mFileName;
+}
+
+bool WorkSheet::modified() const
+{
+ return mModified;
+}
+
+void WorkSheet::setTitle( const QString &title )
+{
+ mTitle = title;
+}
+
+QString WorkSheet::title() const
+{
+ return mTitle;
+}
+
+KSGRD::SensorDisplay *WorkSheet::addDisplay( const QString &hostName,
+ const QString &sensorName,
+ const QString &sensorType,
+ const QString& sensorDescr,
+ uint row, uint column )
+{
+ if ( !KSGRD::SensorMgr->engageHost( hostName ) ) {
+ QString msg = i18n( "It is impossible to connect to \'%1\'." ).arg( hostName );
+ KMessageBox::error( this, msg );
+
+ return 0;
+ }
+
+ /* If the by 'row' and 'column' specified display is a QGroupBox dummy
+ * display we replace the widget. Otherwise we just try to add
+ * the new sensor to an existing display. */
+ if ( mDisplayList[ row ][ column ]->isA( "DummyDisplay" ) ) {
+ KSGRD::SensorDisplay* newDisplay = 0;
+ /* If the sensor type is supported by more than one display
+ * type we popup a menu so the user can select what display is
+ * wanted. */
+ if ( sensorType == "integer" || sensorType == "float" ) {
+ KPopupMenu pm;
+ pm.insertTitle( i18n( "Select Display Type" ) );
+ pm.insertItem( i18n( "&Signal Plotter" ), 1 );
+ pm.insertItem( i18n( "&Multimeter" ), 2 );
+ pm.insertItem( i18n( "&BarGraph" ), 3 );
+ pm.insertItem( i18n( "S&ensorLogger" ), 4 );
+ switch ( pm.exec( QCursor::pos() ) ) {
+ case 1:
+ newDisplay = new FancyPlotter( this, "FancyPlotter", sensorDescr );
+ break;
+ case 2:
+ newDisplay = new MultiMeter( this, "MultiMeter", sensorDescr );
+ break;
+ case 3:
+ newDisplay = new DancingBars( this, "DancingBars", sensorDescr );
+ break;
+ case 4:
+ newDisplay = new SensorLogger( this, "SensorLogger", sensorDescr );
+ break;
+ default:
+ return 0;
+ }
+ } else if ( sensorType == "listview" )
+ newDisplay = new ListView( this, "ListView", sensorDescr );
+ else if ( sensorType == "logfile" )
+ newDisplay = new LogFile( this, "LogFile", sensorDescr );
+ else if ( sensorType == "sensorlogger" )
+ newDisplay = new SensorLogger( this, "SensorLogger", sensorDescr );
+ else if ( sensorType == "table" )
+ newDisplay = new ProcessController( this );
+ else {
+ kdDebug(1215) << "Unkown sensor type: " << sensorType << endl;
+ return 0;
+ }
+
+ replaceDisplay( row, column, newDisplay );
+ }
+
+ mDisplayList[ row ][ column ]->addSensor( hostName, sensorName, sensorType, sensorDescr );
+
+ setModified( true );
+
+ return ((KSGRD::SensorDisplay*)mDisplayList[ row ][ column ] );
+}
+
+void WorkSheet::settings()
+{
+ WorkSheetSettings dlg( this );
+
+ /* The sheet name should be changed with the "Save as..." function,
+ * so we don't have to display the display frame. */
+ dlg.setSheetTitle( mTitle );
+ dlg.setRows( mRows );
+ dlg.setColumns( mColumns );
+ dlg.setInterval( updateInterval() );
+
+ if ( dlg.exec() ) {
+ updateInterval( dlg.interval() );
+ for (uint r = 0; r < mRows; ++r)
+ for (uint c = 0; c < mColumns; ++c)
+ if ( mDisplayList[ r ][ c ]->useGlobalUpdateInterval() )
+ mDisplayList[ r ][ c ]->setUpdateInterval( updateInterval() );
+
+ resizeGrid( dlg.rows(), dlg.columns() );
+
+ mTitle = dlg.sheetTitle();
+ emit titleChanged( this );
+
+ setModified( true );
+ }
+}
+
+void WorkSheet::showPopupMenu( KSGRD::SensorDisplay *display )
+{
+ display->configureSettings();
+}
+
+void WorkSheet::setModified( bool modified )
+{
+ if ( modified != mModified ) {
+ mModified = modified;
+ if ( !modified )
+ for ( uint r = 0; r < mRows; ++r )
+ for ( uint c = 0; c < mColumns; ++c )
+ mDisplayList[ r ][ c ]->setModified( false );
+
+ emit sheetModified( this );
+ }
+}
+
+void WorkSheet::applyStyle()
+{
+ for ( uint r = 0; r < mRows; ++r )
+ for (uint c = 0; c < mColumns; ++c )
+ mDisplayList[ r ][ c ]->applyStyle();
+}
+
+void WorkSheet::dragEnterEvent( QDragEnterEvent *e )
+{
+ e->accept( QTextDrag::canDecode( e ) );
+}
+
+void WorkSheet::dropEvent( QDropEvent *e )
+{
+ QString dragObject;
+
+ if ( QTextDrag::decode( e, dragObject) ) {
+ // The host name, sensor name and type are seperated by a ' '.
+ QStringList parts = QStringList::split( ' ', dragObject );
+
+ QString hostName = parts[ 0 ];
+ QString sensorName = parts[ 1 ];
+ QString sensorType = parts[ 2 ];
+ QString sensorDescr = parts[ 3 ];
+
+ if ( hostName.isEmpty() || sensorName.isEmpty() || sensorType.isEmpty() ) {
+ return;
+ }
+
+ /* Find the sensor display that is supposed to get the drop
+ * event and replace or add sensor. */
+ for ( uint r = 0; r < mRows; ++r )
+ for ( uint c = 0; c < mColumns; ++c )
+ if ( mDisplayList[ r ][ c ]->geometry().contains( e->pos() ) ) {
+ addDisplay( hostName, sensorName, sensorType, sensorDescr, r, c );
+ return;
+ }
+ }
+}
+
+QSize WorkSheet::sizeHint() const
+{
+ return QSize( 200,150 );
+}
+
+void WorkSheet::customEvent( QCustomEvent *e )
+{
+ if ( e->type() == QEvent::User ) {
+ // SensorDisplays send out this event if they want to be removed.
+
+ removeDisplay( (KSGRD::SensorDisplay*)e->data() );
+ }
+}
+
+bool WorkSheet::replaceDisplay( uint row, uint column, QDomElement& element )
+{
+ QString classType = element.attribute( "class" );
+ KSGRD::SensorDisplay* newDisplay;
+ if ( classType == "FancyPlotter" )
+ newDisplay = new FancyPlotter( this );
+ else if ( classType == "MultiMeter" )
+ newDisplay = new MultiMeter( this );
+ else if ( classType == "DancingBars" )
+ newDisplay = new DancingBars( this );
+ else if ( classType == "ListView" )
+ newDisplay = new ListView( this );
+ else if ( classType == "LogFile" )
+ newDisplay = new LogFile( this );
+ else if ( classType == "SensorLogger" )
+ newDisplay = new SensorLogger( this );
+ else if ( classType == "ProcessController" )
+ newDisplay = new ProcessController( this );
+ else {
+ kdDebug(1215) << "Unkown class " << classType << endl;
+ return false;
+ }
+
+ if ( newDisplay->useGlobalUpdateInterval() )
+ newDisplay->setUpdateInterval( updateInterval() );
+
+ // load display specific settings
+ if ( !newDisplay->restoreSettings( element ) )
+ return false;
+
+ replaceDisplay( row, column, newDisplay );
+
+ return true;
+}
+
+void WorkSheet::replaceDisplay( uint row, uint column, KSGRD::SensorDisplay* newDisplay )
+{
+ // remove the old display at this location
+ delete mDisplayList[ row ][ column ];
+
+ // insert new display
+ if ( !newDisplay )
+ mDisplayList[ row ][ column ] = new DummyDisplay( this, "DummyDisplay" );
+ else {
+ mDisplayList[ row ][ column ] = newDisplay;
+ if ( mDisplayList[ row ][ column ]->useGlobalUpdateInterval() )
+ mDisplayList[ row ][ column ]->setUpdateInterval( updateInterval() );
+ connect( newDisplay, SIGNAL( showPopupMenu( KSGRD::SensorDisplay* ) ),
+ SLOT( showPopupMenu( KSGRD::SensorDisplay* ) ) );
+ connect( newDisplay, SIGNAL( modified( bool ) ),
+ SLOT( setModified( bool ) ) );
+ }
+
+
+ mGridLayout->addWidget( mDisplayList[ row ][ column ], row, column );
+
+ if ( isVisible() ) {
+ mDisplayList[ row ][ column ]->show();
+ }
+
+ setMinimumSize(sizeHint());
+
+ setModified( true );
+}
+
+void WorkSheet::removeDisplay( KSGRD::SensorDisplay *display )
+{
+ if ( !display )
+ return;
+
+ for ( uint r = 0; r < mRows; ++r )
+ for ( uint c = 0; c < mColumns; ++c )
+ if ( mDisplayList[ r ][ c ] == display ) {
+ replaceDisplay( r, c );
+ setModified( true );
+ return;
+ }
+}
+
+void WorkSheet::collectHosts( QStringList &list )
+{
+ for ( uint r = 0; r < mRows; ++r )
+ for ( uint c = 0; c < mColumns; ++c )
+ if ( !mDisplayList[ r ][ c ]->isA( "DummyDisplay" ) )
+ ((KSGRD::SensorDisplay*)mDisplayList[ r ][ c ])->hosts( list );
+}
+
+void WorkSheet::createGrid( uint rows, uint columns )
+{
+ mRows = rows;
+ mColumns = columns;
+
+ // create grid layout with specified dimentions
+ mGridLayout = new QGridLayout( this, mRows, mColumns, 5 );
+
+ mDisplayList = new KSGRD::SensorDisplay**[ mRows ];
+ for ( uint r = 0; r < mRows; ++r ) {
+ mDisplayList[ r ] = new KSGRD::SensorDisplay*[ mColumns ];
+ for ( uint c = 0; c < mColumns; ++c )
+ mDisplayList[ r ][ c ] = 0;
+ }
+
+ /* set stretch factors for rows and columns */
+ for ( uint r = 0; r < mRows; ++r )
+ mGridLayout->setRowStretch( r, 100 );
+ for ( uint c = 0; c < mColumns; ++c )
+ mGridLayout->setColStretch( c, 100 );
+}
+
+void WorkSheet::resizeGrid( uint newRows, uint newColumns )
+{
+ uint r, c;
+
+ /* Create new array for display pointers */
+ KSGRD::SensorDisplay*** newDisplayList = new KSGRD::SensorDisplay**[ newRows ];
+ for ( r = 0; r < newRows; ++r ) {
+ newDisplayList[ r ] = new KSGRD::SensorDisplay*[ newColumns ];
+ for ( c = 0; c < newColumns; ++c ) {
+ if ( c < mColumns && r < mRows )
+ newDisplayList[ r ][ c ] = mDisplayList[ r ][ c ];
+ else
+ newDisplayList[ r ][ c ] = 0;
+ }
+ }
+
+ /* remove obsolete displays */
+ for ( r = 0; r < mRows; ++r ) {
+ for ( c = 0; c < mColumns; ++c )
+ if ( r >= newRows || c >= newColumns )
+ delete mDisplayList[ r ][ c ];
+ delete mDisplayList[ r ];
+ }
+ delete [] mDisplayList;
+
+ /* now we make the new display the regular one */
+ mDisplayList = newDisplayList;
+
+ /* create new displays */
+ for ( r = 0; r < newRows; ++r )
+ for ( c = 0; c < newColumns; ++c )
+ if ( r >= mRows || c >= mColumns )
+ replaceDisplay( r, c );
+
+ /* set stretch factors for new rows and columns (if any) */
+ for ( r = mRows; r < newRows; ++r )
+ mGridLayout->setRowStretch( r, 100 );
+ for ( c = mColumns; c < newColumns; ++c )
+ mGridLayout->setColStretch( c, 100 );
+
+ /* Obviously Qt does not shrink the size of the QGridLayout
+ * automatically. So we simply force the rows and columns that
+ * are no longer used to have a strech factor of 0 and hence be
+ * invisible. */
+ for ( r = newRows; r < mRows; ++r )
+ mGridLayout->setRowStretch( r, 0 );
+ for ( c = newColumns; c < mColumns; ++c )
+ mGridLayout->setColStretch( c, 0 );
+
+ mRows = newRows;
+ mColumns = newColumns;
+
+ fixTabOrder();
+
+ mGridLayout->activate();
+}
+
+KSGRD::SensorDisplay *WorkSheet::display( uint row, uint column ) {
+ if(row >= mRows || column >= mColumns) return 0;
+ return mDisplayList[row][column];
+}
+KSGRD::SensorDisplay *WorkSheet::currentDisplay( uint *row, uint *column )
+{
+ for ( uint r = 0 ; r < mRows; ++r )
+ for ( uint c = 0 ; c < mColumns; ++c )
+ if ( mDisplayList[ r ][ c ]->hasFocus() ) {
+ if ( row )
+ *row = r;
+ if ( column )
+ *column = c;
+ return ( mDisplayList[ r ][ c ] );
+ }
+
+ return 0;
+}
+
+void WorkSheet::fixTabOrder()
+{
+ for ( uint r = 0; r < mRows; ++r )
+ for ( uint c = 0; c < mColumns; ++c ) {
+ if ( c + 1 < mColumns )
+ setTabOrder( mDisplayList[ r ][ c ], mDisplayList[ r ][ c + 1 ] );
+ else if ( r + 1 < mRows )
+ setTabOrder( mDisplayList[ r ][ c ], mDisplayList[ r + 1 ][ 0 ] );
+ }
+}
+
+QString WorkSheet::currentDisplayAsXML()
+{
+ KSGRD::SensorDisplay* display = currentDisplay();
+ if ( !display )
+ return QString::null;
+
+ /* We create an XML description of the current display. */
+ QDomDocument doc( "KSysGuardDisplay" );
+ doc.appendChild( doc.createProcessingInstruction(
+ "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
+
+ QDomElement element = doc.createElement( "display" );
+ doc.appendChild( element );
+ element.setAttribute( "class", display->className() );
+ display->saveSettings( doc, element );
+
+ return doc.toString();
+}
+
+void WorkSheet::setIsOnTop( bool /* onTop */ )
+{
+/*
+ for ( uint r = 0; r < mRows; ++r )
+ for ( uint c = 0; c < mColumns; ++c )
+ mDisplayList[ r ][ c ]->setIsOnTop( onTop );
+*/
+}
+
+#include "WorkSheet.moc"
diff --git a/ksysguard/gui/WorkSheet.h b/ksysguard/gui/WorkSheet.h
new file mode 100644
index 000000000..f706f36dc
--- /dev/null
+++ b/ksysguard/gui/WorkSheet.h
@@ -0,0 +1,135 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2002 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_WORKSHEET_H
+#define KSG_WORKSHEET_H
+
+#include <qwidget.h>
+
+#include <SensorDisplay.h>
+
+class QDomElement;
+class QDragEnterEvent;
+class QDropEvent;
+class QGridLayout;
+class QString;
+class QStringList;
+
+/**
+ A WorkSheet contains the displays to visualize the sensor results. When
+ creating the WorkSheet you must specify the number of columns. Displays
+ can be added and removed on the fly. The grid layout will handle the
+ layout. The number of columns can not be changed. Displays are added by
+ dragging a sensor from the sensor browser over the WorkSheet.
+ */
+class WorkSheet : public QWidget, public KSGRD::SensorBoard
+{
+ Q_OBJECT
+
+ public:
+ WorkSheet( QWidget* parent, const char *name = 0 );
+ WorkSheet( uint rows, uint columns, uint interval, QWidget* parent,
+ const char *name = 0 );
+ ~WorkSheet();
+
+ bool load( const QString &fileName );
+ bool save( const QString &fileName );
+
+ void cut();
+ void copy();
+ void paste();
+
+ void setFileName( const QString &fileName );
+ const QString& fileName() const;
+
+ bool modified() const;
+
+ void setTitle( const QString &title );
+ QString title() const;
+
+ KSGRD::SensorDisplay* addDisplay( const QString &hostname,
+ const QString &monitor,
+ const QString &sensorType,
+ const QString &sensorDescr,
+ uint rows, uint columns );
+ //Returns the sensor at position row,column.
+ //Return NULL if invalid row or column
+ KSGRD::SensorDisplay *display( uint row, uint column );
+
+ void settings();
+
+ void setIsOnTop( bool onTop );
+
+ public slots:
+ void showPopupMenu( KSGRD::SensorDisplay *display );
+ void setModified( bool mfd );
+ void applyStyle();
+
+ signals:
+ void sheetModified( QWidget *sheet );
+ void titleChanged( QWidget *sheet );
+
+ protected:
+ virtual QSize sizeHint() const;
+ void dragEnterEvent( QDragEnterEvent* );
+ void dropEvent( QDropEvent* );
+ void customEvent( QCustomEvent* );
+
+ private:
+ void removeDisplay( KSGRD::SensorDisplay *display );
+
+ bool replaceDisplay( uint row, uint column, QDomElement& element );
+
+ void replaceDisplay( uint row, uint column,
+ KSGRD::SensorDisplay* display = 0 );
+
+ void collectHosts( QStringList &list );
+
+ void createGrid( uint rows, uint columns );
+
+ void resizeGrid( uint rows, uint columns );
+
+ KSGRD::SensorDisplay* currentDisplay( uint* row = 0, uint* column = 0 );
+
+ void fixTabOrder();
+
+ QString currentDisplayAsXML();
+
+ bool mModified;
+
+ uint mRows;
+ uint mColumns;
+
+ QGridLayout* mGridLayout;
+ QString mFileName;
+ QString mTitle;
+
+ /**
+ This two dimensional array stores the pointers to the sensor displays
+ or if no sensor is present at a position a pointer to a dummy widget.
+ The size of the array corresponds to the size of the grid layout.
+ */
+ KSGRD::SensorDisplay*** mDisplayList;
+};
+
+#endif
diff --git a/ksysguard/gui/WorkSheetSettings.cc b/ksysguard/gui/WorkSheetSettings.cc
new file mode 100644
index 000000000..e9ba0da08
--- /dev/null
+++ b/ksysguard/gui/WorkSheetSettings.cc
@@ -0,0 +1,153 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2002 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <kaccelmanager.h>
+#include <klineedit.h>
+#include <knuminput.h>
+#include <klocale.h>
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qspinbox.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+#include "WorkSheetSettings.h"
+
+WorkSheetSettings::WorkSheetSettings( QWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, QString::null, Ok|Cancel, Ok, true )
+{
+ setCaption( i18n( "Worksheet Properties" ) );
+
+ QWidget *page = new QWidget( this );
+ setMainWidget( page );
+
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+
+ QGroupBox *group = new QGroupBox( 0, Qt::Vertical, i18n( "Title" ), page );
+ group->layout()->setMargin( marginHint() );
+ group->layout()->setSpacing( spacingHint() );
+
+ QGridLayout *groupLayout = new QGridLayout( group->layout(), 1, 1 );
+ groupLayout->setAlignment( Qt::AlignTop );
+
+ mSheetTitle = new KLineEdit( group );
+ groupLayout->addWidget( mSheetTitle, 0, 0 );
+
+ topLayout->addWidget( group );
+
+ group = new QGroupBox( 0, Qt::Vertical, i18n( "Properties" ), page );
+ group->layout()->setMargin( marginHint() );
+ group->layout()->setSpacing( spacingHint() );
+
+ groupLayout = new QGridLayout( group->layout(), 3, 2 );
+ groupLayout->setAlignment( Qt::AlignTop );
+
+ QLabel *label = new QLabel( i18n( "Rows:" ), group );
+ groupLayout->addWidget( label, 0, 0 );
+
+ mRows = new KIntNumInput( 1, group );
+ mRows->setMaxValue( 42 );
+ mRows->setMinValue( 1 );
+ groupLayout->addWidget( mRows, 0, 1 );
+ label->setBuddy( mRows );
+
+ label = new QLabel( i18n( "Columns:" ), group );
+ groupLayout->addWidget( label, 1, 0 );
+
+ mColumns = new KIntNumInput( 1, group );
+ mColumns->setMaxValue( 42 );
+ mColumns->setMinValue( 1 );
+ groupLayout->addWidget( mColumns, 1, 1 );
+ label->setBuddy( mColumns );
+
+ label = new QLabel( i18n( "Update interval:" ), group );
+ groupLayout->addWidget( label, 2, 0 );
+
+ mInterval = new KIntNumInput( 2, group );
+ mInterval->setMaxValue( 300 );
+ mInterval->setMinValue( 1 );
+ mInterval->setSuffix( i18n( " sec" ) );
+ groupLayout->addWidget( mInterval, 2, 1 );
+ label->setBuddy( mInterval );
+
+ topLayout->addWidget( group );
+
+ QWhatsThis::add( mRows, i18n( "Enter the number of rows the sheet should have." ) );
+ QWhatsThis::add( mColumns, i18n( "Enter the number of columns the sheet should have." ) );
+ QWhatsThis::add( mInterval, i18n( "All displays of the sheet are updated at the rate specified here." ) );
+ QToolTip::add( mSheetTitle, i18n( "Enter the title of the worksheet here." ) );
+
+ KAcceleratorManager::manage( page );
+
+ mSheetTitle->setFocus();
+
+ resize( QSize( 250, 230 ).expandedTo( minimumSizeHint() ) );
+}
+
+WorkSheetSettings::~WorkSheetSettings()
+{
+}
+
+void WorkSheetSettings::setRows( int rows )
+{
+ mRows->setValue( rows );
+}
+
+int WorkSheetSettings::rows() const
+{
+ return mRows->value();
+}
+
+void WorkSheetSettings::setColumns( int columns )
+{
+ mColumns->setValue( columns );
+}
+
+int WorkSheetSettings::columns() const
+{
+ return mColumns->value();
+}
+
+void WorkSheetSettings::setInterval( int interval )
+{
+ mInterval->setValue( interval );
+}
+
+int WorkSheetSettings::interval() const
+{
+ return mInterval->value();
+}
+
+void WorkSheetSettings::setSheetTitle( const QString &title )
+{
+ mSheetTitle->setText( title );
+}
+
+QString WorkSheetSettings::sheetTitle() const
+{
+ return mSheetTitle->text();
+}
+
+#include "WorkSheetSettings.moc"
diff --git a/ksysguard/gui/WorkSheetSettings.h b/ksysguard/gui/WorkSheetSettings.h
new file mode 100644
index 000000000..8fe5641a5
--- /dev/null
+++ b/ksysguard/gui/WorkSheetSettings.h
@@ -0,0 +1,60 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2002 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_WORKSHEETSETTINGS_H
+#define KSG_WORKSHEETSETTINGS_H
+
+#include <kdialogbase.h>
+
+class KLineEdit;
+class KIntNumInput;
+
+class WorkSheetSettings : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ WorkSheetSettings( QWidget* parent = 0, const char* name = 0 );
+ ~WorkSheetSettings();
+
+ void setRows( int rows );
+ int rows() const;
+
+ void setColumns( int columns );
+ int columns() const;
+
+ void setInterval( int interval );
+ int interval() const;
+
+ void setSheetTitle( const QString &title );
+ QString sheetTitle() const;
+
+ private:
+ KLineEdit* mSheetTitle;
+
+ KIntNumInput* mColumns;
+ KIntNumInput* mInterval;
+ KIntNumInput* mRows;
+};
+
+#endif
diff --git a/ksysguard/gui/Workspace.cc b/ksysguard/gui/Workspace.cc
new file mode 100644
index 000000000..c179317c0
--- /dev/null
+++ b/ksysguard/gui/Workspace.cc
@@ -0,0 +1,463 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2002 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <qlineedit.h>
+#include <qspinbox.h>
+#include <qwhatsthis.h>
+
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kaccelmanager.h>
+
+#include "WorkSheet.h"
+#include "WorkSheetSettings.h"
+#include "ProcessController.h"
+
+#include "Workspace.h"
+
+Workspace::Workspace( QWidget* parent, const char* name )
+ : QTabWidget( parent, name )
+{
+ KAcceleratorManager::setNoAccel(this);
+
+ mSheetList.setAutoDelete( true );
+ mAutoSave = true;
+
+ connect( this, SIGNAL( currentChanged( QWidget* ) ),
+ SLOT( updateCaption( QWidget* ) ) );
+
+ QWhatsThis::add( this, i18n( "This is your work space. It holds your worksheets. You need "
+ "to create a new worksheet (Menu File->New) before "
+ "you can drag sensors here." ) );
+}
+
+Workspace::~Workspace()
+{
+ /* This workaround is necessary to prevent a crash when the last
+ * page is not the current page. It seems like the the signal/slot
+ * administration data is already deleted but slots are still
+ * being triggered. TODO: I need to ask the Trolls about this. */
+
+ disconnect( this, SIGNAL( currentChanged( QWidget* ) ), this,
+ SLOT( updateCaption( QWidget* ) ) );
+}
+
+void Workspace::saveProperties( KConfig *cfg )
+{
+ cfg->writePathEntry( "WorkDir", mWorkDir );
+ cfg->writeEntry( "CurrentSheet", tabLabel( currentPage() ) );
+
+ QPtrListIterator<WorkSheet> it( mSheetList);
+
+ QStringList list;
+ for ( int i = 0; it.current(); ++it, ++i )
+ if ( !(*it)->fileName().isEmpty() )
+ list.append( (*it)->fileName() );
+
+ cfg->writePathEntry( "Sheets", list );
+}
+
+void Workspace::readProperties( KConfig *cfg )
+{
+ QString currentSheet;
+
+ mWorkDir = cfg->readPathEntry( "WorkDir" );
+
+ if ( mWorkDir.isEmpty() ) {
+ /* If workDir is not specified in the config file, it's
+ * probably the first time the user has started KSysGuard. We
+ * then "restore" a special default configuration. */
+ KStandardDirs* kstd = KGlobal::dirs();
+ kstd->addResourceType( "data", "share/apps/ksysguard" );
+
+ mWorkDir = kstd->saveLocation( "data", "ksysguard" );
+
+ QString origFile = kstd->findResource( "data", "SystemLoad.sgrd" );
+ QString newFile = mWorkDir + "/" + i18n( "System Load" ) + ".sgrd";
+ if ( !origFile.isEmpty() )
+ restoreWorkSheet( origFile, newFile );
+
+ origFile = kstd->findResource( "data", "ProcessTable.sgrd" );
+ newFile = mWorkDir + "/" + i18n( "Process Table" ) + ".sgrd";
+ if ( !origFile.isEmpty() )
+ restoreWorkSheet( origFile, newFile );
+
+ currentSheet = i18n( "System Load" );
+ } else {
+ currentSheet = cfg->readEntry( "CurrentSheet" );
+ QStringList list = cfg->readPathListEntry( "Sheets" );
+ for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
+ restoreWorkSheet( *it );
+ }
+
+ // Determine visible sheet.
+ QPtrListIterator<WorkSheet> it( mSheetList );
+ for ( ; it.current(); ++it )
+ if ( currentSheet == tabLabel(*it) ) {
+ showPage( *it );
+ break;
+ }
+}
+
+void Workspace::newWorkSheet()
+{
+ /* Find a name of the form "Sheet %d" that is not yet used by any
+ * of the existing worksheets. */
+ QString sheetName;
+ bool found;
+
+ int i = 1;
+ do {
+ sheetName = i18n( "Sheet %1" ).arg( i++ );
+ QPtrListIterator<WorkSheet> it( mSheetList );
+ found = false;
+ for ( ; it.current() && !found; ++it )
+ if ( tabLabel(*it) == sheetName )
+ found = true;
+ } while ( found );
+
+ WorkSheetSettings dlg( this );
+ dlg.setSheetTitle( sheetName );
+ if ( dlg.exec() ) {
+ WorkSheet* sheet = new WorkSheet( dlg.rows(), dlg.columns(), dlg.interval(), this );
+ sheet->setTitle( dlg.sheetTitle() );
+ insertTab( sheet, dlg.sheetTitle() );
+ mSheetList.append( sheet );
+ showPage( sheet );
+ connect( sheet, SIGNAL( sheetModified( QWidget* ) ),
+ SLOT( updateCaption( QWidget* ) ) );
+ connect( sheet, SIGNAL( titleChanged( QWidget* ) ),
+ SLOT( updateSheetTitle( QWidget* ) ) );
+ }
+}
+
+bool Workspace::saveOnQuit()
+{
+ QPtrListIterator<WorkSheet> it( mSheetList );
+ for ( ; it.current(); ++it )
+ if ( (*it)->modified() ) {
+ if ( !mAutoSave || (*it)->fileName().isEmpty() ) {
+ int res = KMessageBox::warningYesNoCancel( this,
+ i18n( "The worksheet '%1' contains unsaved data.\n"
+ "Do you want to save the worksheet?")
+ .arg( tabLabel( *it ) ), QString::null, KStdGuiItem::save(), KStdGuiItem::discard() );
+ if ( res == KMessageBox::Yes )
+ saveWorkSheet( *it );
+ else if ( res == KMessageBox::Cancel )
+ return false; // abort quit
+ } else
+ saveWorkSheet(*it);
+ }
+
+ return true;
+}
+
+void Workspace::loadWorkSheet()
+{
+ KFileDialog dlg( 0, i18n( "*.sgrd|Sensor Files" ), this,
+ "LoadFileDialog", true );
+
+ KURL url = dlg.getOpenURL( mWorkDir, "*.sgrd", 0, i18n( "Select Worksheet to Load" ) );
+
+ loadWorkSheet( url );
+}
+
+void Workspace::loadWorkSheet( const KURL &url )
+{
+ if ( url.isEmpty() )
+ return;
+
+ /* It's probably not worth the effort to make this really network
+ * transparent. Unless s/o beats me up I use this pseudo transparent
+ * code. */
+ QString tmpFile;
+ KIO::NetAccess::download( url, tmpFile, this );
+ mWorkDir = tmpFile.left( tmpFile.findRev( '/' ) );
+
+ // Load sheet from file.
+ if ( !restoreWorkSheet( tmpFile ) )
+ return;
+
+ /* If we have loaded a non-local file we clear the file name so that
+ * the users is prompted for a new name for saving the file. */
+ KURL tmpFileUrl;
+ tmpFileUrl.setPath( tmpFile );
+ if ( tmpFileUrl != url.url() )
+ mSheetList.last()->setFileName( QString::null );
+ KIO::NetAccess::removeTempFile( tmpFile );
+
+ emit announceRecentURL( KURL( url ) );
+}
+
+void Workspace::saveWorkSheet()
+{
+ saveWorkSheet( (WorkSheet*)currentPage() );
+}
+
+void Workspace::saveWorkSheetAs()
+{
+ saveWorkSheetAs( (WorkSheet*)currentPage() );
+}
+
+void Workspace::saveWorkSheet( WorkSheet *sheet )
+{
+ if ( !sheet ) {
+ KMessageBox::sorry( this, i18n( "You do not have a worksheet that could be saved." ) );
+ return;
+ }
+
+ QString fileName = sheet->fileName();
+ if ( fileName.isEmpty() ) {
+ KFileDialog dlg( 0, i18n( "*.sgrd|Sensor Files" ), this,
+ "LoadFileDialog", true );
+ fileName = dlg.getSaveFileName( mWorkDir + "/" + tabLabel( sheet ) +
+ ".sgrd", "*.sgrd", 0,
+ i18n( "Save Current Worksheet As" ) );
+ if ( fileName.isEmpty() )
+ return;
+
+ mWorkDir = fileName.left( fileName.findRev( '/' ) );
+
+ // extract filename without path
+ QString baseName = fileName.right( fileName.length() - fileName.findRev( '/' ) - 1 );
+
+ // chop off extension (usually '.sgrd')
+ baseName = baseName.left( baseName.findRev( '.' ) );
+ changeTab( sheet, baseName );
+ }
+
+ /* If we cannot save the file is probably write protected. So we need
+ * to ask the user for a new name. */
+ if ( !sheet->save( fileName ) ) {
+ saveWorkSheetAs( sheet );
+ return;
+ }
+
+ /* Add file to recent documents menue. */
+ KURL url;
+ url.setPath( fileName );
+ emit announceRecentURL( url );
+}
+
+void Workspace::saveWorkSheetAs( WorkSheet *sheet )
+{
+ if ( !sheet ) {
+ KMessageBox::sorry( this, i18n( "You do not have a worksheet that could be saved." ) );
+ return;
+ }
+
+ QString fileName;
+ do {
+ KFileDialog dlg( 0, "*.sgrd", this, "LoadFileDialog", true );
+ fileName = dlg.getSaveFileName( mWorkDir + "/" + tabLabel( currentPage() ) +
+ ".sgrd", "*.sgrd" );
+ if ( fileName.isEmpty() )
+ return;
+
+ mWorkDir = fileName.left( fileName.findRev( '/' ) );
+
+ // extract filename without path
+ QString baseName = fileName.right( fileName.length() - fileName.findRev( '/' ) - 1 );
+
+ // chop off extension (usually '.sgrd')
+ baseName = baseName.left( baseName.findRev( '.' ) );
+ changeTab( sheet, baseName );
+ } while ( !sheet->save( fileName ) );
+
+ /* Add file to recent documents menue. */
+ KURL url;
+ url.setPath( fileName );
+ emit announceRecentURL( url );
+}
+
+void Workspace::deleteWorkSheet()
+{
+ WorkSheet *current = (WorkSheet*)currentPage();
+
+ if ( current ) {
+ if ( current->modified() ) {
+ if ( !mAutoSave || current->fileName().isEmpty() ) {
+ int res = KMessageBox::warningYesNoCancel( this,
+ i18n( "The worksheet '%1' contains unsaved data.\n"
+ "Do you want to save the worksheet?" )
+ .arg( tabLabel( current ) ), QString::null, KStdGuiItem::save(), KStdGuiItem::discard() );
+ if ( res == KMessageBox::Cancel )
+ return;
+
+ if ( res == KMessageBox::Yes )
+ saveWorkSheet( current );
+ } else
+ saveWorkSheet( current );
+ }
+
+ removePage( current );
+ mSheetList.remove( current );
+ } else {
+ QString msg = i18n( "There are no worksheets that could be deleted." );
+ KMessageBox::error( this, msg );
+ }
+}
+
+void Workspace::removeAllWorkSheets()
+{
+ WorkSheet *sheet;
+ while ( ( sheet = (WorkSheet*)currentPage() ) != 0 ) {
+ removePage( sheet );
+ mSheetList.remove( sheet );
+ }
+}
+
+void Workspace::deleteWorkSheet( const QString &fileName )
+{
+ QPtrListIterator<WorkSheet> it( mSheetList );
+ for ( ; it.current(); ++it )
+ if ( (*it)->fileName() == fileName ) {
+ removePage( *it );
+ mSheetList.remove( *it );
+ return;
+ }
+}
+
+WorkSheet *Workspace::restoreWorkSheet( const QString &fileName, const QString &newName )
+{
+ /* We might want to save the worksheet under a different name later. This
+ * name can be specified by newName. If newName is empty we use the
+ * original name to save the work sheet. */
+ QString tmpStr;
+ if ( newName.isEmpty() )
+ tmpStr = fileName;
+ else
+ tmpStr = newName;
+
+ // extract filename without path
+ QString baseName = tmpStr.right( tmpStr.length() - tmpStr.findRev( '/' ) - 1 );
+
+ // chop off extension (usually '.sgrd')
+ baseName = baseName.left( baseName.findRev( '.' ) );
+
+ WorkSheet *sheet = new WorkSheet( this );
+ sheet->setTitle( baseName );
+ insertTab( sheet, baseName );
+ showPage( sheet );
+
+ if ( !sheet->load( fileName ) ) {
+ delete sheet;
+ return NULL;
+ }
+
+ mSheetList.append( sheet );
+ connect( sheet, SIGNAL( sheetModified( QWidget* ) ),
+ SLOT( updateCaption( QWidget* ) ) );
+
+ /* Force the file name to be the new name. This also sets the modified
+ * flag, so that the file will get saved on exit. */
+ if ( !newName.isEmpty() )
+ sheet->setFileName( newName );
+
+ return sheet;
+}
+
+void Workspace::cut()
+{
+ WorkSheet *current = (WorkSheet*)currentPage();
+
+ if ( current )
+ current->cut();
+}
+
+void Workspace::copy()
+{
+ WorkSheet *current = (WorkSheet*)currentPage();
+
+ if ( current )
+ current->copy();
+}
+
+void Workspace::paste()
+{
+ WorkSheet *current = (WorkSheet*)currentPage();
+
+ if ( current )
+ current->paste();
+}
+
+void Workspace::configure()
+{
+ WorkSheet *current = (WorkSheet*)currentPage();
+
+ if ( !current )
+ return;
+
+ current->settings();
+}
+
+void Workspace::updateCaption( QWidget* wdg )
+{
+ if ( wdg )
+ emit setCaption( tabLabel( wdg ), ((WorkSheet*)wdg)->modified() );
+ else
+ emit setCaption( QString::null, false );
+
+ for ( WorkSheet* s = mSheetList.first(); s != 0; s = mSheetList.next() )
+ ((WorkSheet*)s)->setIsOnTop( s == wdg );
+}
+
+void Workspace::updateSheetTitle( QWidget* wdg )
+{
+ if ( wdg )
+ changeTab( wdg, static_cast<WorkSheet*>( wdg )->title() );
+}
+
+void Workspace::applyStyle()
+{
+ if ( currentPage() )
+ ((WorkSheet*)currentPage())->applyStyle();
+}
+
+void Workspace::showProcesses()
+{
+ KStandardDirs* kstd = KGlobal::dirs();
+ kstd->addResourceType( "data", "share/apps/ksysguard" );
+
+ QString file = kstd->findResource( "data", "ProcessTable.sgrd" );
+ if ( file.isEmpty() ) {
+ KMessageBox::error( this, i18n( "Cannot find file ProcessTable.sgrd." ) );
+ return;
+ }
+ WorkSheet *processSheet = restoreWorkSheet( file );
+ if(!processSheet) return;
+
+ //Set the focus of the search line. This is nasty I know, but I don't know how better to do this :(
+ KSGRD::SensorDisplay *processSensor = processSheet->display( 0,0 );
+ if(!processSensor || !processSensor->isA("ProcessController")) return;
+ ProcessController *controller = dynamic_cast<ProcessController *>(processSensor);
+ if(!controller) return;
+ controller->setSearchFocus();
+
+}
+
+#include "Workspace.moc"
diff --git a/ksysguard/gui/Workspace.h b/ksysguard/gui/Workspace.h
new file mode 100644
index 000000000..af27f6303
--- /dev/null
+++ b/ksysguard/gui/Workspace.h
@@ -0,0 +1,84 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>. Please do
+ not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_WORKSPACE_H
+#define KSG_WORKSPACE_H
+
+#include <qptrlist.h>
+#include <qtabwidget.h>
+
+class KConfig;
+class KURL;
+class QString;
+class WorkSheet;
+
+class Workspace : public QTabWidget
+{
+ Q_OBJECT
+
+ public:
+ Workspace( QWidget* parent, const char* name = 0 );
+ ~Workspace();
+
+ void saveProperties( KConfig* );
+ void readProperties( KConfig* );
+
+ bool saveOnQuit();
+
+ void showProcesses();
+
+ WorkSheet *restoreWorkSheet( const QString &fileName,
+ const QString &newName = QString::null );
+ void deleteWorkSheet( const QString &fileName );
+
+ public slots:
+ void newWorkSheet();
+ void loadWorkSheet();
+ void loadWorkSheet( const KURL& );
+ void saveWorkSheet();
+ void saveWorkSheet( WorkSheet *sheet );
+ void saveWorkSheetAs();
+ void saveWorkSheetAs( WorkSheet *sheet );
+ void deleteWorkSheet();
+ void removeAllWorkSheets();
+ void cut();
+ void copy();
+ void paste();
+ void configure();
+ void updateCaption( QWidget* );
+ void updateSheetTitle( QWidget* );
+ void applyStyle();
+
+ signals:
+ void announceRecentURL( const KURL &url );
+ void setCaption( const QString &text, bool modified );
+
+ private:
+ QPtrList<WorkSheet> mSheetList;
+
+ // Directory that was used for the last load/save.
+ QString mWorkDir;
+ bool mAutoSave;
+};
+
+#endif
diff --git a/ksysguard/gui/kpm.c b/ksysguard/gui/kpm.c
new file mode 100644
index 000000000..5ce25516a
--- /dev/null
+++ b/ksysguard/gui/kpm.c
@@ -0,0 +1,8 @@
+/* A small wrapper to call ksysguard --showprocesses */
+
+#include <unistd.h>
+
+int main()
+{
+ return execlp( "ksysguard", "ksysguard", "--showprocesses", 0 );
+}
diff --git a/ksysguard/gui/ksgrd/HostConnector.cc b/ksysguard/gui/ksgrd/HostConnector.cc
new file mode 100644
index 000000000..5762d08b3
--- /dev/null
+++ b/ksysguard/gui/ksgrd/HostConnector.cc
@@ -0,0 +1,217 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <kapplication.h>
+#include <kaccelmanager.h>
+#include <kcombobox.h>
+#include <klocale.h>
+
+#include <qbuttongroup.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qradiobutton.h>
+#include <qspinbox.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+#include "HostConnector.h"
+
+HostConnector::HostConnector( QWidget *parent, const char *name )
+ : KDialogBase( Plain, i18n( "Connect Host" ), Help | Ok | Cancel, Ok,
+ parent, name, true, true )
+{
+ QFrame *page = plainPage();
+ QGridLayout *layout = new QGridLayout( page, 2, 2, 0, spacingHint() );
+ layout->setColStretch( 1, 1 );
+
+ QLabel *label = new QLabel( i18n( "Host:" ), page );
+ layout->addWidget( label, 0, 0 );
+
+ mHostNames = new KComboBox( true, page );
+ mHostNames->setMaxCount( 20 );
+ mHostNames->setInsertionPolicy( QComboBox::AtTop );
+ mHostNames->setAutoCompletion( true );
+ mHostNames->setDuplicatesEnabled( false );
+ layout->addWidget( mHostNames, 0, 1 );
+ label->setBuddy( mHostNames );
+ QWhatsThis::add( mHostNames, i18n( "Enter the name of the host you want to connect to." ) );
+
+ mHostNameLabel = new QLabel( page );
+ mHostNameLabel->hide();
+ layout->addWidget( mHostNameLabel, 0, 1 );
+
+ QButtonGroup *group = new QButtonGroup( 0, Qt::Vertical,
+ i18n( "Connection Type" ), page );
+ QGridLayout *groupLayout = new QGridLayout( group->layout(), 4, 4,
+ spacingHint() );
+ groupLayout->setAlignment( Qt::AlignTop );
+
+ mUseSsh = new QRadioButton( i18n( "ssh" ), group );
+ mUseSsh->setEnabled( true );
+ mUseSsh->setChecked( true );
+ QWhatsThis::add( mUseSsh, i18n( "Select this to use the secure shell to login to the remote host." ) );
+ groupLayout->addWidget( mUseSsh, 0, 0 );
+
+ mUseRsh = new QRadioButton( i18n( "rsh" ), group );
+ QWhatsThis::add( mUseRsh, i18n( "Select this to use the remote shell to login to the remote host." ) );
+ groupLayout->addWidget( mUseRsh, 0, 1 );
+
+ mUseDaemon = new QRadioButton( i18n( "Daemon" ), group );
+ QWhatsThis::add( mUseDaemon, i18n( "Select this if you want to connect to a ksysguard daemon that is running on the machine you want to connect to, and is listening for client requests." ) );
+ groupLayout->addWidget( mUseDaemon, 0, 2 );
+
+ mUseCustom = new QRadioButton( i18n( "Custom command" ), group );
+ QWhatsThis::add( mUseCustom, i18n( "Select this to use the command you entered below to start ksysguardd on the remote host." ) );
+ groupLayout->addWidget( mUseCustom, 0, 3 );
+
+ label = new QLabel( i18n( "Port:" ), group );
+ groupLayout->addWidget( label, 1, 0 );
+
+ mPort = new QSpinBox( 1, 65535, 1, group );
+ mPort->setEnabled( false );
+ mPort->setValue( 3112 );
+ QToolTip::add( mPort, i18n( "Enter the port number on which the ksysguard daemon is listening for connections." ) );
+ groupLayout->addWidget( mPort, 1, 2 );
+
+ label = new QLabel( i18n( "e.g. 3112" ), group );
+ groupLayout->addWidget( label, 1, 3 );
+
+ label = new QLabel( i18n( "Command:" ), group );
+ groupLayout->addWidget( label, 2, 0 );
+
+ mCommands = new KComboBox( true, group );
+ mCommands->setEnabled( false );
+ mCommands->setMaxCount( 20 );
+ mCommands->setInsertionPolicy( QComboBox::AtTop );
+ mCommands->setAutoCompletion( true );
+ mCommands->setDuplicatesEnabled( false );
+ QWhatsThis::add( mCommands, i18n( "Enter the command that runs ksysguardd on the host you want to monitor." ) );
+ groupLayout->addMultiCellWidget( mCommands, 2, 2, 2, 3 );
+ label->setBuddy( mCommands );
+
+ label = new QLabel( i18n( "e.g. ssh -l root remote.host.org ksysguardd" ), group );
+ groupLayout->addMultiCellWidget( label, 3, 3, 2, 3 );
+
+ layout->addMultiCellWidget( group, 1, 1, 0, 1 );
+
+ connect( mUseCustom, SIGNAL( toggled( bool ) ),
+ mCommands, SLOT( setEnabled( bool ) ) );
+ connect( mUseDaemon, SIGNAL( toggled( bool ) ),
+ mPort, SLOT( setEnabled( bool ) ) );
+ connect( mHostNames->lineEdit(), SIGNAL( textChanged ( const QString & ) ),
+ this, SLOT( slotHostNameChanged( const QString & ) ) );
+ enableButtonOK( !mHostNames->lineEdit()->text().isEmpty() );
+ KAcceleratorManager::manage( this );
+}
+
+HostConnector::~HostConnector()
+{
+}
+
+void HostConnector::slotHostNameChanged( const QString &_text )
+{
+ enableButtonOK( !_text.isEmpty() );
+}
+
+void HostConnector::setHostNames( const QStringList &list )
+{
+ mHostNames->insertStringList( list );
+}
+
+QStringList HostConnector::hostNames() const
+{
+ QStringList list;
+
+ for ( int i = 0; i < mHostNames->count(); ++i )
+ list.append( mHostNames->text( i ) );
+
+ return list;
+}
+
+void HostConnector::setCommands( const QStringList &list )
+{
+ mCommands->insertStringList( list );
+}
+
+QStringList HostConnector::commands() const
+{
+ QStringList list;
+
+ for ( int i = 0; i < mCommands->count(); ++i )
+ list.append( mCommands->text( i ) );
+
+ return list;
+}
+
+void HostConnector::setCurrentHostName( const QString &hostName )
+{
+ if ( !hostName.isEmpty() ) {
+ mHostNames->hide();
+ mHostNameLabel->setText( hostName );
+ mHostNameLabel->show();
+ enableButtonOK( true );//enable true when mHostNames is empty and hidden fix #66955
+ } else {
+ mHostNameLabel->hide();
+ mHostNames->show();
+ mHostNames->setFocus();
+ }
+}
+
+QString HostConnector::currentHostName() const
+{
+ return mHostNames->currentText();
+}
+
+QString HostConnector::currentCommand() const
+{
+ return mCommands->currentText();
+}
+
+int HostConnector::port() const
+{
+ return mPort->value();
+}
+
+bool HostConnector::useSsh() const
+{
+ return mUseSsh->isChecked();
+}
+
+bool HostConnector::useRsh() const
+{
+ return mUseRsh->isChecked();
+}
+
+bool HostConnector::useDaemon() const
+{
+ return mUseDaemon->isChecked();
+}
+
+bool HostConnector::useCustom() const
+{
+ return mUseCustom->isChecked();
+}
+
+void HostConnector::slotHelp()
+{
+ kapp->invokeHelp( "CONNECTINGTOOTHERHOSTS", "ksysguard/the-sensor-browser.html" );
+}
+
+#include "HostConnector.moc"
diff --git a/ksysguard/gui/ksgrd/HostConnector.h b/ksysguard/gui/ksgrd/HostConnector.h
new file mode 100644
index 000000000..eadf728cd
--- /dev/null
+++ b/ksysguard/gui/ksgrd/HostConnector.h
@@ -0,0 +1,74 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_HOSTCONNECTOR_H
+#define KSG_HOSTCONNECTOR_H
+
+#include <kdialogbase.h>
+
+class KComboBox;
+
+class QLabel;
+class QRadioButton;
+class QSpinBox;
+
+class HostConnector : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ HostConnector( QWidget *parent, const char *name = 0 );
+ ~HostConnector();
+
+ void setHostNames( const QStringList &list );
+ QStringList hostNames() const;
+
+ void setCommands( const QStringList &list );
+ QStringList commands() const;
+
+ void setCurrentHostName( const QString &hostName );
+
+ QString currentHostName() const;
+ QString currentCommand() const;
+ int port() const;
+
+ bool useSsh() const;
+ bool useRsh() const;
+ bool useDaemon() const;
+ bool useCustom() const;
+
+ protected slots:
+ virtual void slotHelp();
+ void slotHostNameChanged( const QString &_text );
+ private:
+ KComboBox *mCommands;
+ KComboBox *mHostNames;
+
+ QLabel *mHostNameLabel;
+
+ QRadioButton *mUseSsh;
+ QRadioButton *mUseRsh;
+ QRadioButton *mUseDaemon;
+ QRadioButton *mUseCustom;
+
+ QSpinBox *mPort;
+};
+
+#endif
diff --git a/ksysguard/gui/ksgrd/Makefile.am b/ksysguard/gui/ksgrd/Makefile.am
new file mode 100644
index 000000000..ff5f0aa47
--- /dev/null
+++ b/ksysguard/gui/ksgrd/Makefile.am
@@ -0,0 +1,34 @@
+
+# set the include path for X, qt and KDE
+INCLUDES= -I$(srcdir)/../SensorDisplayLib $(all_includes)
+
+lib_LTLIBRARIES = libksgrd.la
+
+libksgrd_la_LDFLAGS = -no-undefined -version-info 3:0:2 $(all_libraries)
+libksgrd_la_LIBADD = $(LIB_KDEUI)
+
+# Which sources should be compiled for ksysguard.
+libksgrd_la_SOURCES = \
+ HostConnector.cc \
+ SensorAgent.cc \
+ SensorManager.cc \
+ SensorShellAgent.cc \
+ SensorSocketAgent.cc \
+ StyleEngine.cc \
+ StyleSettings.cc \
+ TimerSettings.cc
+
+ksgrdincludedir = $(includedir)/ksgrd
+ksgrdinclude_HEADERS = \
+ HostConnector.h \
+ SensorAgent.h \
+ SensorClient.h \
+ SensorManager.h \
+ SensorShellAgent.h \
+ SensorSocketAgent.h \
+ StyleEngine.h \
+ StyleSettings.h \
+ TimerSettings.h
+
+# just to make sure, automake makes them
+libksgrd_la_METASOURCES = AUTO
diff --git a/ksysguard/gui/ksgrd/SensorAgent.cc b/ksysguard/gui/ksgrd/SensorAgent.cc
new file mode 100644
index 000000000..a24bf5594
--- /dev/null
+++ b/ksysguard/gui/ksgrd/SensorAgent.cc
@@ -0,0 +1,260 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdlib.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kpassdlg.h>
+
+#include "SensorClient.h"
+#include "SensorManager.h"
+
+#include "SensorAgent.h"
+
+/**
+ This can be used to debug communication problems with the daemon.
+ Should be set to 0 in any production version.
+*/
+#define SA_TRACE 0
+
+using namespace KSGRD;
+
+SensorAgent::SensorAgent( SensorManager *sm )
+ : mSensorManager( sm )
+{
+ /* SensorRequests migrate from the inputFIFO to the processingFIFO. So
+ * we only have to delete them when they are removed from the
+ * processingFIFO. */
+ mInputFIFO.setAutoDelete( false );
+ mProcessingFIFO.setAutoDelete( true );
+
+ mDaemonOnLine = false;
+ mTransmitting = false;
+ mState = 0;
+}
+
+SensorAgent::~SensorAgent()
+{
+}
+
+bool SensorAgent::sendRequest( const QString &req, SensorClient *client, int id )
+{
+ /* The request is registered with the FIFO so that the answer can be
+ * routed back to the requesting client. */
+ mInputFIFO.prepend( new SensorRequest( req, client, id ) );
+
+#if SA_TRACE
+ kdDebug(1215) << "-> " << req << "(" << mInputFIFO.count() << "/"
+ << mProcessingFIFO.count() << ")" << endl;
+#endif
+ executeCommand();
+
+ return false;
+}
+
+void SensorAgent::processAnswer( const QString &buffer )
+{
+#if SA_TRACE
+ kdDebug(1215) << "<- " << buffer << endl;
+#endif
+
+ for ( uint i = 0; i < buffer.length(); i++ ) {
+ if ( buffer[ i ] == '\033' ) {
+ mState = ( mState + 1 ) & 1;
+ if ( !mErrorBuffer.isEmpty() && mState == 0 ) {
+ if ( mErrorBuffer == "RECONFIGURE\n" )
+ emit reconfigure( this );
+ else {
+ /* We just received the end of an error message, so we
+ * can display it. */
+ SensorMgr->notify( i18n( "Message from %1:\n%2" )
+ .arg( mHostName )
+ .arg( mErrorBuffer ) );
+ }
+ mErrorBuffer = QString::null;
+ }
+ } else if ( mState == 0 ) // receiving to answerBuffer
+ mAnswerBuffer += buffer[ i ];
+ else // receiving to errorBuffer
+ mErrorBuffer += buffer[ i ];
+ }
+
+ int end;
+ // And now the real information
+ while ( ( end = mAnswerBuffer.find( "\nksysguardd> " ) ) >= 0 ) {
+#if SA_TRACE
+ kdDebug(1215) << "<= " << mAnswerBuffer.left( end )
+ << "(" << mInputFIFO.count() << "/"
+ << mProcessingFIFO.count() << ")" << endl;
+#endif
+ if ( !mDaemonOnLine ) {
+ /* First '\nksysguardd> ' signals that the daemon is
+ * ready to serve requests now. */
+ mDaemonOnLine = true;
+#if SA_TRACE
+ kdDebug(1215) << "Daemon now online!" << endl;
+#endif
+ mAnswerBuffer = QString::null;
+ break;
+ }
+
+ // remove pending request from FIFO
+ SensorRequest* req = mProcessingFIFO.last();
+ if ( !req ) {
+ kdDebug(1215) << "ERROR: Received answer but have no pending "
+ << "request! : " << mAnswerBuffer.left( end ) << endl;
+ mAnswerBuffer = QString::null;
+ } else {
+ if ( !req->client() ) {
+ /* The client has disappeared before receiving the answer
+ * to his request. */
+ } else {
+ if ( mAnswerBuffer.left( end ) == "UNKNOWN COMMAND" ) {
+ /* Notify client that the sensor seems to be no longer
+ * available. */
+ req->client()->sensorLost( req->id() );
+ } else {
+ // Notify client of newly arrived answer.
+ req->client()->answerReceived( req->id(), mAnswerBuffer.left( end ) );
+ }
+ }
+ mProcessingFIFO.removeLast();
+ }
+ // chop off the processed part of the answer buffer
+ mAnswerBuffer.remove( 0, end + strlen( "\nksysguardd> " ) );
+ }
+
+ executeCommand();
+}
+
+void SensorAgent::executeCommand()
+{
+ /* This function is called whenever there is a chance that we have a
+ * command to pass to the daemon. But the command many only be send
+ * if the daemon is online and there is no other command currently
+ * being sent. */
+ if ( mDaemonOnLine && txReady() && !mInputFIFO.isEmpty() ) {
+ // take oldest request for input FIFO
+ SensorRequest* req = mInputFIFO.last();
+ mInputFIFO.removeLast();
+
+#if SA_TRACE
+ kdDebug(1215) << ">> " << req->request().ascii() << "(" << mInputFIFO.count()
+ << "/" << mProcessingFIFO.count() << ")" << endl;
+#endif
+ // send request to daemon
+ QString cmdWithNL = req->request() + "\n";
+ if ( writeMsg( cmdWithNL.ascii(), cmdWithNL.length() ) )
+ mTransmitting = true;
+ else
+ kdDebug(1215) << "SensorAgent::writeMsg() failed" << endl;
+
+ // add request to processing FIFO
+ mProcessingFIFO.prepend( req );
+ }
+}
+
+void SensorAgent::disconnectClient( SensorClient *client )
+{
+ for ( SensorRequest *req = mInputFIFO.first(); req; req = mInputFIFO.next() )
+ if ( req->client() == client )
+ req->setClient( 0 );
+ for ( SensorRequest *req = mProcessingFIFO.first(); req; req = mProcessingFIFO.next() )
+ if ( req->client() == client )
+ req->setClient( 0 );
+}
+
+SensorManager *SensorAgent::sensorManager()
+{
+ return mSensorManager;
+}
+
+void SensorAgent::setDaemonOnLine( bool value )
+{
+ mDaemonOnLine = value;
+}
+
+bool SensorAgent::daemonOnLine() const
+{
+ return mDaemonOnLine;
+}
+
+void SensorAgent::setTransmitting( bool value )
+{
+ mTransmitting = value;
+}
+
+bool SensorAgent::transmitting() const
+{
+ return mTransmitting;
+}
+
+void SensorAgent::setHostName( const QString &hostName )
+{
+ mHostName = hostName;
+}
+
+const QString &SensorAgent::hostName() const
+{
+ return mHostName;
+}
+
+
+SensorRequest::SensorRequest( const QString &request, SensorClient *client, int id )
+ : mRequest( request ), mClient( client ), mId( id )
+{
+}
+
+SensorRequest::~SensorRequest()
+{
+}
+
+void SensorRequest::setRequest( const QString &request )
+{
+ mRequest = request;
+}
+
+QString SensorRequest::request() const
+{
+ return mRequest;
+}
+
+void SensorRequest::setClient( SensorClient *client )
+{
+ mClient = client;
+}
+
+SensorClient *SensorRequest::client()
+{
+ return mClient;
+}
+
+void SensorRequest::setId( int id )
+{
+ mId = id;
+}
+
+int SensorRequest::id()
+{
+ return mId;
+}
+
+#include "SensorAgent.moc"
diff --git a/ksysguard/gui/ksgrd/SensorAgent.h b/ksysguard/gui/ksgrd/SensorAgent.h
new file mode 100644
index 000000000..e30deb510
--- /dev/null
+++ b/ksysguard/gui/ksgrd/SensorAgent.h
@@ -0,0 +1,137 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_SENSORAGENT_H
+#define KSG_SENSORAGENT_H
+
+#include <qobject.h>
+#include <qptrlist.h>
+
+class KProcess;
+class KShellProcess;
+
+class QString;
+
+namespace KSGRD {
+
+class SensorClient;
+class SensorManager;
+class SensorRequest;
+
+/**
+ The SensorAgent depending on the type of requested connection
+ starts a ksysguardd process or connects through a tcp connection to
+ a running ksysguardd and handles the asynchronous communication. It
+ keeps a list of pending requests that have not been answered yet by
+ ksysguardd. The current implementation only allowes one pending
+ requests. Incoming requests are queued in an input FIFO.
+*/
+class KDE_EXPORT SensorAgent : public QObject
+{
+ Q_OBJECT
+
+ public:
+ SensorAgent( SensorManager *sm );
+ virtual ~SensorAgent();
+
+ virtual bool start( const QString &host, const QString &shell,
+ const QString &command = "", int port = -1 ) = 0;
+
+ /**
+ This function should only be used by the the SensorManager and
+ never by the SensorClients directly since the pointer returned by
+ engaged is not guaranteed to be valid. Only the SensorManager knows
+ whether a SensorAgent pointer is still valid or not.
+
+ This function sends out a command to the sensor and notifies the
+ agent to return the answer to 'client'. The 'id' can be used by the
+ client to identify the answer. It is only passed through and never
+ used by the SensorAgent. So it can be any value the client suits to
+ use.
+ */
+ bool sendRequest( const QString &req, SensorClient *client, int id = 0 );
+
+ virtual void hostInfo( QString &sh, QString &cmd, int &port ) const = 0;
+
+ void disconnectClient( SensorClient *client );
+
+ const QString &hostName() const;
+
+ signals:
+ void reconfigure( const SensorAgent* );
+
+ protected:
+ void processAnswer( const QString &buffer );
+ void executeCommand();
+
+ SensorManager *sensorManager();
+
+ void setDaemonOnLine( bool value );
+ bool daemonOnLine() const;
+
+ void setTransmitting( bool value );
+ bool transmitting() const;
+
+ void setHostName( const QString &hostName );
+
+ private:
+ virtual bool writeMsg( const char *msg, int len ) = 0;
+ virtual bool txReady() = 0;
+
+ int mState;
+ QPtrList<SensorRequest> mInputFIFO;
+ QPtrList<SensorRequest> mProcessingFIFO;
+ QString mAnswerBuffer;
+ QString mErrorBuffer;
+
+ SensorManager *mSensorManager;
+
+ bool mDaemonOnLine;
+ bool mTransmitting;
+ QString mHostName;
+};
+
+/**
+ This auxilliary class is used to store requests during their processing.
+*/
+class SensorRequest
+{
+ public:
+ SensorRequest( const QString &request, SensorClient *client, int id );
+ ~SensorRequest();
+
+ void setRequest( const QString& );
+ QString request() const;
+
+ void setClient( SensorClient* );
+ SensorClient *client();
+
+ void setId( int );
+ int id();
+
+ private:
+ QString mRequest;
+ SensorClient *mClient;
+ int mId;
+};
+
+}
+
+#endif
diff --git a/ksysguard/gui/ksgrd/SensorClient.h b/ksysguard/gui/ksgrd/SensorClient.h
new file mode 100644
index 000000000..30586a8a2
--- /dev/null
+++ b/ksysguard/gui/ksgrd/SensorClient.h
@@ -0,0 +1,209 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_SENSORCLIENT_H
+#define KSG_SENSORCLIENT_H
+
+#include <qptrlist.h>
+#include <qstring.h>
+
+namespace KSGRD {
+
+/**
+ Every object that should act as a client to a sensor must inherit from
+ this class. A pointer to the client object is passed as SensorClient*
+ to the SensorAgent. When the requested information is available or a
+ problem occurred one of the member functions is called.
+ */
+class SensorClient
+{
+ public:
+ SensorClient() { }
+ virtual ~SensorClient() { }
+
+ /**
+ This function is called whenever the information form the sensor has
+ been received by the sensor agent. This function must be reimplemented
+ by the sensor client to receive and process this information.
+ */
+ virtual void answerReceived( int, const QString& ) { }
+
+ /**
+ In case of an unexpected fatal problem with the sensor the sensor
+ agent will call this function to notify the client about it.
+ */
+ virtual void sensorLost( int ) { }
+};
+
+/**
+ Every object that has a SensorClient as a child must inherit from
+ this class to support the advanced update interval settings.
+ */
+class SensorBoard
+{
+ public:
+ SensorBoard() { }
+ virtual ~SensorBoard() { }
+
+ void updateInterval( int interval ) { mUpdateInterval = interval; }
+
+ int updateInterval() { return mUpdateInterval; }
+
+ private:
+ int mUpdateInterval;
+};
+
+/**
+ The following classes are utility classes that provide a
+ convenient way to retrieve pieces of information from the sensor
+ answers. For each type of answer there is a separate class.
+ */
+class SensorTokenizer
+{
+ public:
+ SensorTokenizer( const QString &info, QChar separator )
+ {
+ mTokens = QStringList::split( separator, info );
+ }
+
+ ~SensorTokenizer() { }
+
+ const QString& operator[]( unsigned idx )
+ {
+ return mTokens[ idx ];
+ }
+
+ uint count()
+ {
+ return mTokens.count();
+ }
+
+ private:
+ QStringList mTokens;
+};
+
+/**
+ An integer info contains 4 fields seperated by TABS, a description
+ (name), the minimum and the maximum values and the unit.
+ e.g. Swap Memory 0 133885952 KB
+ */
+class SensorIntegerInfo : public SensorTokenizer
+{
+ public:
+ SensorIntegerInfo( const QString &info )
+ : SensorTokenizer( info, '\t' ) { }
+
+ ~SensorIntegerInfo() { }
+
+ const QString &name()
+ {
+ return (*this)[ 0 ];
+ }
+
+ long min()
+ {
+ return (*this)[ 1 ].toLong();
+ }
+
+ long max()
+ {
+ return (*this)[ 2 ].toLong();
+ }
+
+ const QString &unit()
+ {
+ return (*this)[ 3 ];
+ }
+};
+
+/**
+ An float info contains 4 fields seperated by TABS, a description
+ (name), the minimum and the maximum values and the unit.
+ e.g. CPU Voltage 0.0 5.0 V
+ */
+class SensorFloatInfo : public SensorTokenizer
+{
+ public:
+ SensorFloatInfo( const QString &info )
+ : SensorTokenizer( info, '\t' ) { }
+
+ ~SensorFloatInfo() { }
+
+ const QString &name()
+ {
+ return (*this)[ 0 ];
+ }
+
+ double min()
+ {
+ return (*this)[ 1 ].toDouble();
+ }
+
+ double max()
+ {
+ return (*this)[ 2 ].toDouble();
+ }
+
+ const QString &unit()
+ {
+ return (*this)[ 3 ];
+ }
+};
+
+/**
+ A PS line consists of information about a process. Each piece of
+ information is seperated by a TAB. The first 4 fields are process name,
+ PID, PPID and real user ID. Those fields are mandatory.
+ */
+class SensorPSLine : public SensorTokenizer
+{
+ public:
+ SensorPSLine( const QString &line )
+ : SensorTokenizer( line, '\t' ) { }
+
+ ~SensorPSLine() { }
+
+ const QString& name()
+ {
+ return (*this)[ 0 ];
+ }
+
+ long pid()
+ {
+ return (*this)[ 1 ].toLong();
+ }
+
+ long ppid()
+ {
+ return (*this)[ 2 ].toLong();
+ }
+
+ long uid()
+ {
+ return (*this)[ 3 ].toLong();
+ }
+};
+
+}
+
+#endif
diff --git a/ksysguard/gui/ksgrd/SensorManager.cc b/ksysguard/gui/ksgrd/SensorManager.cc
new file mode 100644
index 000000000..065da717a
--- /dev/null
+++ b/ksysguard/gui/ksgrd/SensorManager.cc
@@ -0,0 +1,432 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qradiobutton.h>
+#include <qspinbox.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "HostConnector.h"
+#include "SensorShellAgent.h"
+#include "SensorSocketAgent.h"
+
+#include "SensorManager.h"
+
+using namespace KSGRD;
+
+SensorManager* KSGRD::SensorMgr;
+
+SensorManager::SensorManager()
+{
+ mAgents.setAutoDelete( true );
+ mDict.setAutoDelete( true );
+
+ // Fill the sensor description dictionary.
+ mDict.insert( "cpu", new QString( i18n( "CPU Load" ) ) );
+ mDict.insert( "idle", new QString( i18n( "Idle Load" ) ) );
+ mDict.insert( "sys", new QString( i18n( "System Load" ) ) );
+ mDict.insert( "nice", new QString( i18n( "Nice Load" ) ) );
+ mDict.insert( "user", new QString( i18n( "User Load" ) ) );
+ mDict.insert( "mem", new QString( i18n( "Memory" ) ) );
+ mDict.insert( "physical", new QString( i18n( "Physical Memory" ) ) );
+ mDict.insert( "swap", new QString( i18n( "Swap Memory" ) ) );
+ mDict.insert( "cached", new QString( i18n( "Cached Memory" ) ) );
+ mDict.insert( "buf", new QString( i18n( "Buffered Memory" ) ) );
+ mDict.insert( "used", new QString( i18n( "Used Memory" ) ) );
+ mDict.insert( "application", new QString( i18n( "Application Memory" ) ) );
+ mDict.insert( "free", new QString( i18n( "Free Memory" ) ) );
+ mDict.insert( "pscount", new QString( i18n( "Process Count" ) ) );
+ mDict.insert( "ps", new QString( i18n( "Process Controller" ) ) );
+ mDict.insert( "disk", new QString( i18n( "Disk Throughput" ) ) );
+ mDict.insert( "load", new QString( i18n( "CPU Load", "Load" ) ) );
+ mDict.insert( "total", new QString( i18n( "Total Accesses" ) ) );
+ mDict.insert( "rio", new QString( i18n( "Read Accesses" ) ) );
+ mDict.insert( "wio", new QString( i18n( "Write Accesses" ) ) );
+ mDict.insert( "rblk", new QString( i18n( "Read Data" ) ) );
+ mDict.insert( "wblk", new QString( i18n( "Write Data" ) ) );
+ mDict.insert( "pageIn", new QString( i18n( "Pages In" ) ) );
+ mDict.insert( "pageOut", new QString( i18n( "Pages Out" ) ) );
+ mDict.insert( "context", new QString( i18n( "Context Switches" ) ) );
+ mDict.insert( "network", new QString( i18n( "Network" ) ) );
+ mDict.insert( "interfaces", new QString( i18n( "Interfaces" ) ) );
+ mDict.insert( "receiver", new QString( i18n( "Receiver" ) ) );
+ mDict.insert( "transmitter", new QString( i18n( "Transmitter" ) ) );
+ mDict.insert( "data", new QString( i18n( "Data" ) ) );
+ mDict.insert( "compressed", new QString( i18n( "Compressed Packets" ) ) );
+ mDict.insert( "drops", new QString( i18n( "Dropped Packets" ) ) );
+ mDict.insert( "errors", new QString( i18n( "Errors" ) ) );
+ mDict.insert( "fifo", new QString( i18n( "FIFO Overruns" ) ) );
+ mDict.insert( "frame", new QString( i18n( "Frame Errors" ) ) );
+ mDict.insert( "multicast", new QString( i18n( "Multicast" ) ) );
+ mDict.insert( "packets", new QString( i18n( "Packets" ) ) );
+ mDict.insert( "carrier", new QString( i18n( "Carrier" ) ) );
+ mDict.insert( "collisions", new QString( i18n( "Collisions" ) ) );
+ mDict.insert( "sockets", new QString( i18n( "Sockets" ) ) );
+ mDict.insert( "count", new QString( i18n( "Total Number" ) ) );
+ mDict.insert( "list", new QString( i18n( "Table" ) ) );
+ mDict.insert( "apm", new QString( i18n( "Advanced Power Management" ) ) );
+ mDict.insert( "acpi", new QString( i18n( "ACPI" ) ) );
+ mDict.insert( "thermal_zone", new QString( i18n( "Thermal Zone" ) ) );
+ mDict.insert( "temperature", new QString( i18n( "Temperature" ) ) );
+ mDict.insert( "fan", new QString( i18n( "Fan" ) ) );
+ mDict.insert( "state", new QString( i18n( "State" ) ) );
+ mDict.insert( "battery", new QString( i18n( "Battery" ) ) );
+ mDict.insert( "batterycharge", new QString( i18n( "Battery Charge" ) ) );
+ mDict.insert( "batteryusage", new QString( i18n( "Battery Usage" ) ) );
+ mDict.insert( "remainingtime", new QString( i18n( "Remaining Time" ) ) );
+ mDict.insert( "interrupts", new QString( i18n( "Interrupts" ) ) );
+ mDict.insert( "loadavg1", new QString( i18n( "Load Average (1 min)" ) ) );
+ mDict.insert( "loadavg5", new QString( i18n( "Load Average (5 min)" ) ) );
+ mDict.insert( "loadavg15", new QString( i18n( "Load Average (15 min)" ) ) );
+ mDict.insert( "clock", new QString( i18n( "Clock Frequency" ) ) );
+ mDict.insert( "lmsensors", new QString( i18n( "Hardware Sensors" ) ) );
+ mDict.insert( "partitions", new QString( i18n( "Partition Usage" ) ) );
+ mDict.insert( "usedspace", new QString( i18n( "Used Space" ) ) );
+ mDict.insert( "freespace", new QString( i18n( "Free Space" ) ) );
+ mDict.insert( "filllevel", new QString( i18n( "Fill Level" ) ) );
+
+ for ( int i = 0; i < 32; i++ ) {
+ mDict.insert( "cpu" + QString::number( i ),
+ new QString( QString( i18n( "CPU%1" ) ).arg( i ) ) );
+ mDict.insert( "disk" + QString::number( i ),
+ new QString( QString( i18n( "Disk%1" ) ).arg( i ) ) );
+ }
+
+ for ( int i = 0; i < 6; i++) {
+ mDict.insert( "fan" + QString::number( i ),
+ new QString( QString( i18n( "Fan%1" ) ).arg( i ) ) );
+ mDict.insert( "temp" + QString::number( i ),
+ new QString( QString( i18n( "Temperature%1" ) ).arg( i ) ) );
+ }
+
+ mDict.insert( "int00", new QString( i18n( "Total" ) ) );
+
+ QString num;
+ for ( int i = 1; i < 25; i++ ) {
+ num.sprintf( "%.2d", i );
+ mDict.insert( "int" + num,
+ new QString( QString( i18n( "Int%1" ) ).arg( i - 1, 3 ) ) );
+ }
+
+ mDescriptions.setAutoDelete( true );
+ // TODO: translated descriptions not yet implemented.
+
+ mUnits.setAutoDelete( true );
+ mUnits.insert( "1/s", new QString( i18n( "the unit 1 per second", "1/s" ) ) );
+ mUnits.insert( "kBytes", new QString( i18n( "kBytes" ) ) );
+ mUnits.insert( "min", new QString( i18n( "the unit minutes", "min" ) ) );
+ mUnits.insert( "MHz", new QString( i18n( "the frequency unit", "MHz" ) ) );
+
+ mTypes.setAutoDelete( true );
+ mTypes.insert( "integer", new QString( i18n( "Integer Value" ) ) );
+ mTypes.insert( "float", new QString( i18n( "Floating Point Value" ) ) );
+ mTypes.insert( "table", new QString( i18n( "Process Controller" ) ) );
+ mTypes.insert( "listview", new QString( i18n( "Table" ) ) );
+
+ mBroadcaster = 0;
+
+ mHostConnector = new HostConnector( 0 );
+}
+
+SensorManager::~SensorManager()
+{
+ delete mHostConnector;
+}
+
+bool SensorManager::engageHost( const QString &hostName )
+{
+ bool retVal = true;
+
+ if ( hostName.isEmpty() || mAgents.find( hostName ) == 0 ) {
+ if(hostName == "localhost") {
+ //There was a bug where the xml file would end up not specifying to connect to localhost.
+ //This work around makes sure we always connect to localhost
+ return engage( "localhost", "", "ksysguardd", -1);
+ }
+ mHostConnector->setCurrentHostName( hostName );
+
+ if ( mHostConnector->exec() ) {
+ QString shell = "";
+ QString command = "";
+ int port = -1;
+
+ /* Check which radio button is selected and set parameters
+ * appropriately. */
+ if ( mHostConnector->useSsh() )
+ shell = "ssh";
+ else if ( mHostConnector->useRsh() )
+ shell = "rsh";
+ else if ( mHostConnector->useDaemon() )
+ port = mHostConnector->port();
+ else
+ command = mHostConnector->currentCommand();
+
+ if ( hostName.isEmpty() )
+ retVal = engage( mHostConnector->currentHostName(), shell,
+ command, port );
+ else
+ retVal = engage( hostName, shell, command, port );
+ }
+ }
+
+ return retVal;
+}
+
+bool SensorManager::engage( const QString &hostName, const QString &shell,
+ const QString &command, int port )
+{
+ SensorAgent *agent;
+
+ if ( ( agent = mAgents.find( hostName ) ) == 0 ) {
+ if ( port == -1 )
+ agent = new SensorShellAgent( this );
+ else
+ agent = new SensorSocketAgent( this );
+
+ if ( !agent->start( hostName.ascii(), shell, command, port ) ) {
+ delete agent;
+ return false;
+ }
+
+ mAgents.insert( hostName, agent );
+ connect( agent, SIGNAL( reconfigure( const SensorAgent* ) ),
+ SLOT( reconfigure( const SensorAgent* ) ) );
+
+ emit update();
+ return true;
+ }
+
+ return false;
+}
+
+void SensorManager::requestDisengage( const SensorAgent *agent )
+{
+ /* When a sensor agent becomes disfunctional it calls this function
+ * to request that it is being removed from the SensorManager. It must
+ * not call disengage() directly since it would trigger ~SensorAgent()
+ * while we are still in a SensorAgent member function.
+ * So we have to post an event which is later caught by
+ * SensorManger::customEvent(). */
+ QCustomEvent* event = new QCustomEvent( QEvent::User, (void*)agent );
+ kapp->postEvent( this, event );
+}
+
+bool SensorManager::disengage( const SensorAgent *agent )
+{
+ QDictIterator<SensorAgent> it( mAgents );
+
+ for ( ; it.current(); ++it )
+ if ( it.current() == agent ) {
+ mAgents.remove( it.currentKey() );
+ emit update();
+ return true;
+ }
+
+ return false;
+}
+
+bool SensorManager::disengage( const QString &hostName )
+{
+ SensorAgent *agent;
+ if ( ( agent = mAgents.find( hostName ) ) != 0 ) {
+ mAgents.remove( hostName );
+ emit update();
+ return true;
+ }
+
+ return false;
+}
+
+bool SensorManager::resynchronize( const QString &hostName )
+{
+ SensorAgent *agent;
+
+ if ( ( agent = mAgents.find( hostName ) ) == 0 )
+ return false;
+
+ QString shell, command;
+ int port;
+ hostInfo( hostName, shell, command, port );
+
+ disengage( hostName );
+
+ kdDebug (1215) << "Re-synchronizing connection to " << hostName << endl;
+
+ return engage( hostName, shell, command );
+}
+
+void SensorManager::hostLost( const SensorAgent *agent )
+{
+ emit hostConnectionLost( agent->hostName() );
+
+ if ( mBroadcaster ) {
+ QCustomEvent *event = new QCustomEvent( QEvent::User );
+ event->setData( new QString( i18n( "Connection to %1 has been lost." )
+ .arg( agent->hostName() ) ) );
+ kapp->postEvent( mBroadcaster, event );
+ }
+}
+
+void SensorManager::notify( const QString &msg ) const
+{
+ /* This function relays text messages to the toplevel widget that
+ * displays the message in a pop-up box. It must be used for objects
+ * that might have been deleted before the pop-up box is closed. */
+ if ( mBroadcaster ) {
+ QCustomEvent *event = new QCustomEvent( QEvent::User );
+ event->setData( new QString( msg ) );
+ kapp->postEvent( mBroadcaster, event );
+ }
+}
+
+void SensorManager::setBroadcaster( QWidget *wdg )
+{
+ mBroadcaster = wdg;
+}
+
+void SensorManager::reconfigure( const SensorAgent* )
+{
+ emit update();
+}
+
+bool SensorManager::event( QEvent *event )
+{
+ if ( event->type() == QEvent::User ) {
+ disengage( (const SensorAgent*)((QCustomEvent*)event)->data() );
+ return true;
+ }
+
+ return false;
+}
+
+bool SensorManager::sendRequest( const QString &hostName, const QString &req,
+ SensorClient *client, int id )
+{
+ SensorAgent *agent = mAgents.find( hostName );
+ if( !agent && hostName == "localhost") {
+ //we should always be able to reconnect to localhost
+ engage("localhost", "", "ksysguardd", -1);
+ agent = mAgents.find( hostName );
+ }
+ if ( agent ) {
+ agent->sendRequest( req, client, id );
+ return true;
+ }
+
+ return false;
+}
+
+const QString SensorManager::hostName( const SensorAgent *agent) const
+{
+ QDictIterator<SensorAgent> it( mAgents );
+
+ while ( it.current() ) {
+ if ( it.current() == agent )
+ return it.currentKey();
+ ++it;
+ }
+
+ return QString::null;
+}
+
+bool SensorManager::hostInfo( const QString &hostName, QString &shell,
+ QString &command, int &port )
+{
+ SensorAgent *agent;
+ if ( ( agent = mAgents.find( hostName ) ) != 0 ) {
+ agent->hostInfo( shell, command, port );
+ return true;
+ }
+
+ return false;
+}
+
+const QString &SensorManager::translateUnit( const QString &unit ) const
+{
+ if ( !unit.isEmpty() && mUnits[ unit ] )
+ return *mUnits[ unit ];
+ else
+ return unit;
+}
+
+const QString &SensorManager::translateSensorPath( const QString &path ) const
+{
+ if ( !path.isEmpty() && mDict[ path ] )
+ return *mDict[ path ];
+ else
+ return path;
+}
+
+const QString &SensorManager::translateSensorType( const QString &type ) const
+{
+ if ( !type.isEmpty() && mTypes[ type ] )
+ return *mTypes[ type ];
+ else
+ return type;
+}
+
+QString SensorManager::translateSensor( const QString &sensor ) const
+{
+ QString token, out;
+ int start = 0, end = 0;
+ for ( ; ; ) {
+ end = sensor.find( '/', start );
+ if ( end > 0 )
+ out += translateSensorPath( sensor.mid( start, end - start ) ) + "/";
+ else {
+ out += translateSensorPath( sensor.right( sensor.length() - start ) );
+ break;
+ }
+ start = end + 1;
+ }
+
+ return out;
+}
+
+void SensorManager::readProperties( KConfig *cfg )
+{
+ mHostConnector->setHostNames( cfg->readListEntry( "HostList" ) );
+ mHostConnector->setCommands( cfg->readListEntry( "CommandList" ) );
+}
+
+void
+SensorManager::saveProperties( KConfig *cfg )
+{
+ cfg->writeEntry( "HostList", mHostConnector->hostNames() );
+ cfg->writeEntry( "CommandList", mHostConnector->commands() );
+}
+
+void SensorManager::disconnectClient( SensorClient *client )
+{
+ QDictIterator<SensorAgent> it( mAgents );
+
+ for ( ; it.current(); ++it)
+ it.current()->disconnectClient( client );
+}
+
+#include "SensorManager.moc"
diff --git a/ksysguard/gui/ksgrd/SensorManager.h b/ksysguard/gui/ksgrd/SensorManager.h
new file mode 100644
index 000000000..8eb778009
--- /dev/null
+++ b/ksysguard/gui/ksgrd/SensorManager.h
@@ -0,0 +1,126 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_SENSORMANAGER_H
+#define KSG_SENSORMANAGER_H
+
+#include <kconfig.h>
+
+#include <qdict.h>
+#include <qobject.h>
+
+#include <SensorAgent.h>
+
+class HostConnector;
+
+namespace KSGRD {
+
+class SensorManagerIterator;
+
+/**
+ The SensorManager handles all interaction with the connected
+ hosts. Connections to a specific hosts are handled by
+ SensorAgents. Use engage() to establish a connection and
+ disengage() to terminate the connection. If you don't know if a
+ certain host is already connected use engageHost(). If there is no
+ connection yet or the hostname is empty, a dialog will be shown to
+ enter the connections details.
+ */
+class KDE_EXPORT SensorManager : public QObject
+{
+ Q_OBJECT
+
+ friend class SensorManagerIterator;
+
+ public:
+ SensorManager();
+ ~SensorManager();
+
+ bool engageHost( const QString &hostName );
+ bool engage( const QString &hostName, const QString &shell = "ssh",
+ const QString &command = "", int port = -1 );
+
+ void requestDisengage( const SensorAgent *agent );
+ bool disengage( const SensorAgent *agent );
+ bool disengage( const QString &hostName );
+ bool resynchronize( const QString &hostName );
+ void hostLost( const SensorAgent *agent );
+ void notify( const QString &msg ) const;
+
+ void setBroadcaster( QWidget *wdg );
+
+ virtual bool event( QEvent *event );
+
+ bool sendRequest( const QString &hostName, const QString &request,
+ SensorClient *client, int id = 0 );
+
+ const QString hostName( const SensorAgent *sensor ) const;
+ bool hostInfo( const QString &host, QString &shell,
+ QString &command, int &port );
+
+ const QString& translateUnit( const QString &unit ) const;
+ const QString& translateSensorPath( const QString &path ) const;
+ const QString& translateSensorType( const QString &type ) const;
+ QString translateSensor(const QString& u) const;
+
+ void readProperties( KConfig *cfg );
+ void saveProperties( KConfig *cfg );
+
+ void disconnectClient( SensorClient *client );
+
+ public slots:
+ void reconfigure( const SensorAgent *agent );
+
+ signals:
+ void update();
+ void hostConnectionLost( const QString &hostName );
+
+ protected:
+ QDict<SensorAgent> mAgents;
+
+ private:
+ /**
+ These dictionary stores the localized versions of the sensor
+ descriptions and units.
+ */
+ QDict<QString> mDescriptions;
+ QDict<QString> mUnits;
+ QDict<QString> mDict;
+ QDict<QString> mTypes;
+
+ QWidget* mBroadcaster;
+
+ HostConnector* mHostConnector;
+};
+
+KDE_EXPORT extern SensorManager* SensorMgr;
+
+class KDE_EXPORT SensorManagerIterator : public QDictIterator<SensorAgent>
+{
+ public:
+ SensorManagerIterator( const SensorManager *sm )
+ : QDictIterator<SensorAgent>( sm->mAgents ) { }
+
+ ~SensorManagerIterator() { }
+};
+
+}
+
+#endif
diff --git a/ksysguard/gui/ksgrd/SensorShellAgent.cc b/ksysguard/gui/ksgrd/SensorShellAgent.cc
new file mode 100644
index 000000000..0f06e88fe
--- /dev/null
+++ b/ksysguard/gui/ksgrd/SensorShellAgent.cc
@@ -0,0 +1,141 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdlib.h>
+
+#include <kdebug.h>
+#include <kpassdlg.h>
+#include <kprocess.h>
+
+#include "SensorClient.h"
+#include "SensorManager.h"
+
+#include "SensorShellAgent.h"
+
+using namespace KSGRD;
+
+SensorShellAgent::SensorShellAgent( SensorManager *sm )
+ : SensorAgent( sm ), mDaemon( 0 )
+{
+}
+
+SensorShellAgent::~SensorShellAgent()
+{
+ if ( mDaemon ) {
+ mDaemon->writeStdin( "quit\n", strlen( "quit\n" ) );
+ delete mDaemon;
+ mDaemon = 0;
+ }
+}
+
+bool SensorShellAgent::start( const QString &host, const QString &shell,
+ const QString &command, int )
+{
+ mRetryCount = 3;
+ mDaemon = new KProcess;
+ mDaemon->setUseShell(true);
+ setHostName( host );
+ mShell = shell;
+ mCommand = command;
+
+ connect( mDaemon, SIGNAL( processExited( KProcess* ) ),
+ SLOT( daemonExited( KProcess* ) ) );
+ connect( mDaemon, SIGNAL( receivedStdout( KProcess*, char*, int ) ),
+ SLOT( msgRcvd( KProcess*, char*, int ) ) );
+ connect( mDaemon, SIGNAL( receivedStderr( KProcess*, char*, int ) ),
+ SLOT( errMsgRcvd( KProcess*, char*, int ) ) );
+ connect( mDaemon, SIGNAL( wroteStdin( KProcess* ) ),
+ SLOT( msgSent( KProcess* ) ) );
+
+ QString cmd;
+ if ( !command.isEmpty() )
+ cmd = command;
+ else
+ cmd = mShell + " " + hostName() + " ksysguardd";
+ *mDaemon << cmd;
+
+ if ( !mDaemon->start( KProcess::NotifyOnExit, KProcess::All ) ) {
+ sensorManager()->hostLost( this );
+ kdDebug (1215) << "Command '" << cmd << "' failed" << endl;
+ return false;
+ }
+
+ return true;
+}
+
+void SensorShellAgent::hostInfo( QString &shell, QString &command,
+ int &port) const
+{
+ shell = mShell;
+ command = mCommand;
+ port = -1;
+}
+
+void SensorShellAgent::msgSent( KProcess* )
+{
+ setTransmitting( false );
+
+ // Try to send next request if available.
+ executeCommand();
+}
+
+void SensorShellAgent::msgRcvd( KProcess*, char *buffer, int buflen )
+{
+ if ( !buffer || buflen == 0 )
+ return;
+ mRetryCount = 3; //we recieved an answer, so reset our retry count back to 3
+ QString aux = QString::fromLocal8Bit( buffer, buflen );
+
+ processAnswer( aux );
+}
+
+void SensorShellAgent::errMsgRcvd( KProcess*, char *buffer, int buflen )
+{
+ if ( !buffer || buflen == 0 )
+ return;
+
+ QString buf = QString::fromLocal8Bit( buffer, buflen );
+
+ kdDebug(1215) << "SensorShellAgent: Warning, received text over stderr!"
+ << endl << buf << endl;
+}
+
+void SensorShellAgent::daemonExited( KProcess *process )
+{
+ kdDebug() << "daemonExited" << endl;
+ if ( mRetryCount-- <= 0 || !mDaemon->start( KProcess::NotifyOnExit, KProcess::All ) ) {
+ kdDebug() << "daemon could not be restart" << endl;
+ setDaemonOnLine( false );
+ sensorManager()->hostLost( this );
+ sensorManager()->requestDisengage( this );
+ }
+}
+
+bool SensorShellAgent::writeMsg( const char *msg, int len )
+{
+ return mDaemon->writeStdin( msg, len );
+}
+
+bool SensorShellAgent::txReady()
+{
+ return !transmitting();
+}
+
+#include "SensorShellAgent.moc"
diff --git a/ksysguard/gui/ksgrd/SensorShellAgent.h b/ksysguard/gui/ksgrd/SensorShellAgent.h
new file mode 100644
index 000000000..e13413d55
--- /dev/null
+++ b/ksysguard/gui/ksgrd/SensorShellAgent.h
@@ -0,0 +1,77 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_SENSORSHELLAGENT_H
+#define KSG_SENSORSHELLAGENT_H
+
+#include <qobject.h>
+#include <qptrlist.h>
+#include <qguardedptr.h>
+
+#include <SensorAgent.h>
+
+class QString;
+
+class KProcess;
+
+namespace KSGRD {
+
+class SensorClient;
+class SensorManager;
+
+/**
+ The SensorShellAgent starts a ksysguardd process and handles the
+ asynchronous communication. It keeps a list of pending requests
+ that have not been answered yet by ksysguard. The current
+ implementation only allowes one pending requests. Incoming requests
+ are queued in an input FIFO.
+ */
+class SensorShellAgent : public SensorAgent
+{
+ Q_OBJECT
+
+ public:
+ SensorShellAgent( SensorManager *sm );
+ ~SensorShellAgent();
+
+ bool start( const QString &host, const QString &shell,
+ const QString &command = "", int port = -1 );
+
+ void hostInfo( QString &shell, QString &command, int &port) const;
+
+ private slots:
+ void msgSent( KProcess* );
+ void msgRcvd( KProcess*, char *buffer, int buflen );
+ void errMsgRcvd( KProcess*, char *buffer, int buflen );
+ void daemonExited( KProcess* );
+
+ private:
+ bool writeMsg( const char *msg, int len );
+ bool txReady();
+
+ QGuardedPtr<KProcess> mDaemon;
+ QString mShell;
+ QString mCommand;
+ int mRetryCount;
+};
+
+}
+
+#endif
diff --git a/ksysguard/gui/ksgrd/SensorSocketAgent.cc b/ksysguard/gui/ksgrd/SensorSocketAgent.cc
new file mode 100644
index 000000000..dcb5b7f3b
--- /dev/null
+++ b/ksysguard/gui/ksgrd/SensorSocketAgent.cc
@@ -0,0 +1,137 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdlib.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kpassdlg.h>
+
+#include "SensorClient.h"
+#include "SensorManager.h"
+
+#include "SensorSocketAgent.h"
+
+using namespace KSGRD;
+
+SensorSocketAgent::SensorSocketAgent( SensorManager *sm )
+ : SensorAgent( sm )
+{
+ connect( &mSocket, SIGNAL( gotError( int ) ), SLOT( error( int ) ) );
+ connect( &mSocket, SIGNAL( bytesWritten( int ) ), SLOT( msgSent( int ) ) );
+ connect( &mSocket, SIGNAL( readyRead() ), SLOT( msgRcvd() ) );
+ connect( &mSocket, SIGNAL( closed() ), SLOT( connectionClosed() ) );
+}
+
+SensorSocketAgent::~SensorSocketAgent()
+{
+ mSocket.writeBlock( "quit\n", strlen( "quit\n" ) );
+ mSocket.flush();
+}
+
+bool SensorSocketAgent::start( const QString &host, const QString&,
+ const QString&, int port )
+{
+ if ( port <= 0 )
+ kdDebug(1215) << "SensorSocketAgent::start: Illegal port " << port << endl;
+
+ setHostName( host );
+ mPort = port;
+
+ mSocket.connect( hostName(), QString::number(mPort) );
+
+ return true;
+}
+
+void SensorSocketAgent::hostInfo( QString &shell, QString &command, int &port ) const
+{
+ shell = QString::null;
+ command = QString::null;
+ port = mPort;
+}
+
+void SensorSocketAgent::msgSent( int )
+{
+ if ( mSocket.bytesToWrite() != 0 )
+ return;
+
+ setTransmitting( false );
+
+ // Try to send next request if available.
+ executeCommand();
+}
+
+void SensorSocketAgent::msgRcvd()
+{
+ int buflen = mSocket.bytesAvailable();
+ char* buffer = new char[ buflen ];
+
+ mSocket.readBlock( buffer, buflen );
+ QString buf = QString::fromLocal8Bit( buffer, buflen );
+ delete [] buffer;
+
+ processAnswer( buf );
+}
+
+void SensorSocketAgent::connectionClosed()
+{
+ setDaemonOnLine( false );
+ sensorManager()->hostLost( this );
+ sensorManager()->requestDisengage( this );
+}
+
+void SensorSocketAgent::error( int id )
+{
+ switch ( id ) {
+ case KNetwork::KSocketBase::ConnectionRefused:
+ SensorMgr->notify( i18n( "Connection to %1 refused" )
+ .arg( hostName() ) );
+ break;
+ case KNetwork::KSocketBase::LookupFailure:
+ SensorMgr->notify( i18n( "Host %1 not found" )
+ .arg( hostName() ) );
+ break;
+ case KNetwork::KSocketBase::Timeout:
+ SensorMgr->notify( i18n( "Timeout at host %1")
+ .arg( hostName() ) );
+ break;
+ case KNetwork::KSocketBase::NetFailure:
+ SensorMgr->notify( i18n( "Network failure host %1")
+ .arg( hostName() ) );
+ break;
+ default:
+ kdDebug(1215) << "SensorSocketAgent::error() unknown error " << id << endl;
+ }
+
+ setDaemonOnLine( false );
+ sensorManager()->requestDisengage( this );
+}
+
+bool SensorSocketAgent::writeMsg( const char *msg, int len )
+{
+ return ( mSocket.writeBlock( msg, len ) == len );
+}
+
+bool SensorSocketAgent::txReady()
+{
+ return !transmitting();
+}
+
+#include "SensorSocketAgent.moc"
diff --git a/ksysguard/gui/ksgrd/SensorSocketAgent.h b/ksysguard/gui/ksgrd/SensorSocketAgent.h
new file mode 100644
index 000000000..b422d3a9b
--- /dev/null
+++ b/ksysguard/gui/ksgrd/SensorSocketAgent.h
@@ -0,0 +1,71 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_SENSORSOCKETAGENT_H
+#define KSG_SENSORSOCKETAGENT_H
+
+#include <qptrlist.h>
+#include <kbufferedsocket.h>
+
+#include <SensorAgent.h>
+
+class QString;
+
+namespace KSGRD {
+
+class SensorClient;
+
+/**
+ The SensorSocketAgent connects to a ksysguardd via a TCP
+ connection. It keeps a list of pending requests that have not been
+ answered yet by ksysguard. The current implementation only allowes
+ one pending requests. Incoming requests are queued in an input
+ FIFO.
+ */
+class SensorSocketAgent : public SensorAgent
+{
+ Q_OBJECT
+
+ public:
+ SensorSocketAgent( SensorManager *sm );
+ ~SensorSocketAgent();
+
+ bool start( const QString &host, const QString &shell,
+ const QString &command = "", int port = -1 );
+
+ void hostInfo( QString &shell, QString &command, int &port ) const;
+
+ private slots:
+ void connectionClosed();
+ void msgSent( int );
+ void msgRcvd();
+ void error( int );
+
+ private:
+ bool writeMsg( const char *msg, int len );
+ bool txReady();
+
+ KNetwork::KBufferedSocket mSocket;
+ int mPort;
+};
+
+}
+
+#endif
diff --git a/ksysguard/gui/ksgrd/StyleEngine.cc b/ksysguard/gui/ksgrd/StyleEngine.cc
new file mode 100644
index 000000000..ccea0a7c2
--- /dev/null
+++ b/ksysguard/gui/ksgrd/StyleEngine.cc
@@ -0,0 +1,176 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <qimage.h>
+#include <qpushbutton.h>
+#include <qspinbox.h>
+
+#include <kconfig.h>
+#include <klocale.h>
+
+#include "StyleSettings.h"
+
+#include "StyleEngine.h"
+
+using namespace KSGRD;
+
+StyleEngine* KSGRD::Style;
+
+StyleEngine::StyleEngine()
+{
+ mFirstForegroundColor = QColor( 0x6894c9 ); // light blue
+ mSecondForegroundColor = QColor( 0x6894c9 ); // light blue
+ mAlarmColor = QColor( 255, 0, 0 );
+ mBackgroundColor = QColor( 0x313031 ); // almost black
+ mFontSize = 9;
+
+ mSensorColors.append( QColor( 0x1889ff ) ); // soft blue
+ mSensorColors.append( QColor( 0xff7f08 ) ); // reddish
+ mSensorColors.append( QColor( 0xffeb14 ) ); // bright yellow
+
+ uint v = 0x00ff00;
+ for ( uint i = mSensorColors.count(); i < 32; ++i ) {
+ v = ( ( ( v + 82 ) & 0xff ) << 23 ) | ( v >> 8 );
+ mSensorColors.append( QColor( v & 0xff, ( v >> 16 ) & 0xff, ( v >> 8 ) & 0xff ) );
+ }
+}
+
+StyleEngine::~StyleEngine()
+{
+}
+
+void StyleEngine::readProperties( KConfig *cfg )
+{
+ mFirstForegroundColor = cfg->readColorEntry( "fgColor1", &mFirstForegroundColor );
+ mSecondForegroundColor = cfg->readColorEntry( "fgColor2", &mSecondForegroundColor );
+ mAlarmColor = cfg->readColorEntry( "alarmColor", &mAlarmColor );
+ mBackgroundColor = cfg->readColorEntry( "backgroundColor", &mBackgroundColor );
+ mFontSize = cfg->readNumEntry( "fontSize", mFontSize );
+
+ QStringList list = cfg->readListEntry( "sensorColors" );
+ if ( !list.isEmpty() ) {
+ mSensorColors.clear();
+ QStringList::Iterator it;
+ for ( it = list.begin(); it != list.end(); ++it )
+ mSensorColors.append( QColor( *it ) );
+ }
+}
+
+void StyleEngine::saveProperties( KConfig *cfg )
+{
+ cfg->writeEntry( "fgColor1", mFirstForegroundColor );
+ cfg->writeEntry( "fgColor2", mSecondForegroundColor );
+ cfg->writeEntry( "alarmColor", mAlarmColor );
+ cfg->writeEntry( "backgroundColor", mBackgroundColor );
+ cfg->writeEntry( "fontSize", mFontSize );
+
+ QStringList list;
+ QValueList<QColor>::Iterator it;
+ for ( it = mSensorColors.begin(); it != mSensorColors.end(); ++it )
+ list.append( (*it).name() );
+
+ cfg->writeEntry( "sensorColors", list );
+}
+
+const QColor &StyleEngine::firstForegroundColor() const
+{
+ return mFirstForegroundColor;
+}
+
+const QColor &StyleEngine::secondForegroundColor() const
+{
+ return mSecondForegroundColor;
+}
+
+const QColor &StyleEngine::alarmColor() const
+{
+ return mAlarmColor;
+}
+
+const QColor &StyleEngine::backgroundColor() const
+{
+ return mBackgroundColor;
+}
+
+uint StyleEngine::fontSize() const
+{
+ return mFontSize;
+}
+
+const QColor& StyleEngine::sensorColor( uint pos )
+{
+ static QColor dummy;
+
+ if ( pos < mSensorColors.count() )
+ return *mSensorColors.at( pos );
+ else
+ return dummy;
+}
+
+uint StyleEngine::numSensorColors() const
+{
+ return mSensorColors.count();
+}
+
+void StyleEngine::configure()
+{
+ mSettingsDialog = new StyleSettings( 0 );
+
+ mSettingsDialog->setFirstForegroundColor( mFirstForegroundColor );
+ mSettingsDialog->setSecondForegroundColor( mSecondForegroundColor );
+ mSettingsDialog->setAlarmColor( mAlarmColor );
+ mSettingsDialog->setBackgroundColor( mBackgroundColor );
+ mSettingsDialog->setFontSize( mFontSize );
+ mSettingsDialog->setSensorColors( mSensorColors );
+
+ connect( mSettingsDialog, SIGNAL( applyClicked() ),
+ this, SLOT( applyToWorksheet() ) );
+
+ if ( mSettingsDialog->exec() )
+ apply();
+
+ delete mSettingsDialog;
+ mSettingsDialog = 0;
+}
+
+void StyleEngine::applyToWorksheet()
+{
+ apply();
+ emit applyStyleToWorksheet();
+}
+
+void StyleEngine::apply()
+{
+ if ( !mSettingsDialog )
+ return;
+
+ mFirstForegroundColor = mSettingsDialog->firstForegroundColor();
+ mSecondForegroundColor = mSettingsDialog->secondForegroundColor();
+ mAlarmColor = mSettingsDialog->alarmColor();
+ mBackgroundColor = mSettingsDialog->backgroundColor();
+ mFontSize = mSettingsDialog->fontSize();
+
+ mSensorColors = mSettingsDialog->sensorColors();
+}
+
+#include "StyleEngine.moc"
diff --git a/ksysguard/gui/ksgrd/StyleEngine.h b/ksysguard/gui/ksgrd/StyleEngine.h
new file mode 100644
index 000000000..d896a2422
--- /dev/null
+++ b/ksysguard/gui/ksgrd/StyleEngine.h
@@ -0,0 +1,86 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_STYLEENGINE_H
+#define KSG_STYLEENGINE_H
+
+#include <qcolor.h>
+#include <qobject.h>
+#include <qptrlist.h>
+
+#include <kdemacros.h>
+
+class KConfig;
+
+class QListBoxItem;
+
+class StyleSettings;
+
+namespace KSGRD {
+
+class KDE_EXPORT StyleEngine : public QObject
+{
+ Q_OBJECT
+
+ public:
+ StyleEngine();
+ ~StyleEngine();
+
+ void readProperties( KConfig* );
+ void saveProperties( KConfig* );
+
+ const QColor& firstForegroundColor() const;
+ const QColor& secondForegroundColor() const;
+ const QColor& alarmColor() const;
+ const QColor& backgroundColor() const;
+
+ uint fontSize() const;
+
+ const QColor& sensorColor( uint pos );
+ uint numSensorColors() const;
+
+ public slots:
+ void configure();
+ void applyToWorksheet();
+
+ signals:
+ void applyStyleToWorksheet();
+
+ private:
+ void apply();
+
+ QColor mFirstForegroundColor;
+ QColor mSecondForegroundColor;
+ QColor mAlarmColor;
+ QColor mBackgroundColor;
+ uint mFontSize;
+ QValueList<QColor> mSensorColors;
+
+ StyleSettings *mSettingsDialog;
+};
+
+KDE_EXPORT extern StyleEngine* Style;
+
+}
+
+#endif
diff --git a/ksysguard/gui/ksgrd/StyleSettings.cc b/ksysguard/gui/ksgrd/StyleSettings.cc
new file mode 100644
index 000000000..19a924cbe
--- /dev/null
+++ b/ksysguard/gui/ksgrd/StyleSettings.cc
@@ -0,0 +1,201 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <qimage.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlistbox.h>
+#include <qpixmap.h>
+#include <qpushbutton.h>
+#include <qspinbox.h>
+#include <qtabwidget.h>
+
+#include <kaccelmanager.h>
+#include <kcolorbutton.h>
+#include <kcolordialog.h>
+#include <klocale.h>
+
+#include "StyleSettings.h"
+
+StyleSettings::StyleSettings( QWidget *parent, const char *name )
+ : KDialogBase( Tabbed, i18n( "Global Style Settings" ), Help | Ok | Apply |
+ Cancel, Ok, parent, name, true, true )
+{
+ QFrame *page = addPage( i18n( "Display Style" ) );
+ QGridLayout *layout = new QGridLayout( page, 6, 2, 0, spacingHint() );
+
+ QLabel *label = new QLabel( i18n( "First foreground color:" ), page );
+ layout->addWidget( label, 0, 0 );
+
+ mFirstForegroundColor = new KColorButton( page );
+ layout->addWidget( mFirstForegroundColor, 0, 1 );
+ label->setBuddy( mFirstForegroundColor );
+
+ label = new QLabel( i18n( "Second foreground color:" ), page );
+ layout->addWidget( label, 1, 0 );
+
+ mSecondForegroundColor = new KColorButton( page );
+ layout->addWidget( mSecondForegroundColor, 1, 1 );
+ label->setBuddy( mSecondForegroundColor );
+
+ label = new QLabel( i18n( "Alarm color:" ), page );
+ layout->addWidget( label, 2, 0 );
+
+ mAlarmColor = new KColorButton( page );
+ layout->addWidget( mAlarmColor, 2, 1 );
+ label->setBuddy( mAlarmColor );
+
+ label = new QLabel( i18n( "Background color:" ), page );
+ layout->addWidget( label, 3, 0 );
+
+ mBackgroundColor = new KColorButton( page );
+ layout->addWidget( mBackgroundColor, 3, 1 );
+ label->setBuddy( mBackgroundColor );
+
+ label = new QLabel( i18n( "Font size:" ), page );
+ layout->addWidget( label, 4, 0 );
+
+ mFontSize = new QSpinBox( 7, 48, 1, page );
+ mFontSize->setValue( 8 );
+ layout->addWidget( mFontSize, 4, 1 );
+ label->setBuddy( mFontSize );
+
+ layout->setRowStretch( 5, 1 );
+
+ page = addPage( i18n( "Sensor Colors" ) );
+ layout = new QGridLayout( page, 1, 2, 0, spacingHint() );
+
+ mColorListBox = new QListBox( page );
+ layout->addWidget( mColorListBox, 0, 0 );
+
+ mEditColorButton = new QPushButton( i18n( "Change Color..." ), page );
+ mEditColorButton->setEnabled( false );
+ layout->addWidget( mEditColorButton, 0, 1, Qt::AlignTop );
+
+ connect( mColorListBox, SIGNAL( selectionChanged( QListBoxItem* ) ),
+ SLOT( selectionChanged( QListBoxItem* ) ) );
+ connect( mColorListBox, SIGNAL( doubleClicked( QListBoxItem* ) ),
+ SLOT( editSensorColor() ) );
+ connect( mEditColorButton, SIGNAL( clicked() ),
+ SLOT( editSensorColor() ) );
+
+ KAcceleratorManager::manage( this );
+}
+
+StyleSettings::~StyleSettings()
+{
+}
+
+void StyleSettings::setFirstForegroundColor( const QColor &color )
+{
+ mFirstForegroundColor->setColor( color );
+}
+
+QColor StyleSettings::firstForegroundColor() const
+{
+ return mFirstForegroundColor->color();
+}
+
+void StyleSettings::setSecondForegroundColor( const QColor &color )
+{
+ mSecondForegroundColor->setColor( color );
+}
+
+QColor StyleSettings::secondForegroundColor() const
+{
+ return mSecondForegroundColor->color();
+}
+
+void StyleSettings::setAlarmColor( const QColor &color )
+{
+ mAlarmColor->setColor( color );
+}
+
+QColor StyleSettings::alarmColor() const
+{
+ return mAlarmColor->color();
+}
+
+void StyleSettings::setBackgroundColor( const QColor &color )
+{
+ mBackgroundColor->setColor( color );
+}
+
+QColor StyleSettings::backgroundColor() const
+{
+ return mBackgroundColor->color();
+}
+
+void StyleSettings::setFontSize( uint size )
+{
+ mFontSize->setValue( size );
+}
+
+uint StyleSettings::fontSize() const
+{
+ return mFontSize->value();
+}
+
+void StyleSettings::setSensorColors( const QValueList<QColor> &list )
+{
+ mColorListBox->clear();
+
+ for ( uint i = 0; i < list.count(); ++i ) {
+ QPixmap pm( 12, 12 );
+ pm.fill( *list.at( i ) );
+ mColorListBox->insertItem( pm, i18n( "Color %1" ).arg( i ) );
+ }
+}
+
+QValueList<QColor> StyleSettings::sensorColors()
+{
+ QValueList<QColor> list;
+
+ for ( uint i = 0; i < mColorListBox->count(); ++i )
+ list.append( QColor( mColorListBox->pixmap( i )->convertToImage().pixel( 1, 1 ) ) );
+
+ return list;
+}
+
+void StyleSettings::editSensorColor()
+{
+ int pos = mColorListBox->currentItem();
+
+ if ( pos < 0 )
+ return;
+
+ QColor color = mColorListBox->pixmap( pos )->convertToImage().pixel( 1, 1 );
+
+ if ( KColorDialog::getColor( color ) == KColorDialog::Accepted ) {
+ QPixmap pm( 12, 12 );
+ pm.fill( color );
+ mColorListBox->changeItem( pm, mColorListBox->text( pos ), pos );
+ }
+}
+
+void StyleSettings::selectionChanged( QListBoxItem *item )
+{
+ mEditColorButton->setEnabled( item != 0 );
+}
+
+#include "StyleSettings.moc"
diff --git a/ksysguard/gui/ksgrd/StyleSettings.h b/ksysguard/gui/ksgrd/StyleSettings.h
new file mode 100644
index 000000000..d16b5e723
--- /dev/null
+++ b/ksysguard/gui/ksgrd/StyleSettings.h
@@ -0,0 +1,78 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_STYLESETTINGS_H
+#define KSG_STYLESETTINGS_H
+
+#include <kdialogbase.h>
+
+#include <qcolor.h>
+
+class KColorButton;
+
+class QListBoxItem;
+class QPushButton;
+
+class StyleSettings : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ StyleSettings( QWidget *parent = 0, const char *name = 0 );
+ ~StyleSettings();
+
+ void setFirstForegroundColor( const QColor &color );
+ QColor firstForegroundColor() const;
+
+ void setSecondForegroundColor( const QColor &color );
+ QColor secondForegroundColor() const;
+
+ void setAlarmColor( const QColor &color );
+ QColor alarmColor() const;
+
+ void setBackgroundColor( const QColor &color );
+ QColor backgroundColor() const;
+
+ void setFontSize( uint size );
+ uint fontSize() const;
+
+ void setSensorColors( const QValueList<QColor> &list );
+ QValueList<QColor> sensorColors();
+
+ private slots:
+ void editSensorColor();
+ void selectionChanged( QListBoxItem* );
+
+ private:
+ KColorButton *mFirstForegroundColor;
+ KColorButton *mSecondForegroundColor;
+ KColorButton *mAlarmColor;
+ KColorButton *mBackgroundColor;
+
+ QSpinBox *mFontSize;
+
+ QListBox *mColorListBox;
+ QPushButton *mEditColorButton;
+};
+
+#endif
diff --git a/ksysguard/gui/ksgrd/TimerSettings.cc b/ksysguard/gui/ksgrd/TimerSettings.cc
new file mode 100644
index 000000000..4806f7d8a
--- /dev/null
+++ b/ksysguard/gui/ksgrd/TimerSettings.cc
@@ -0,0 +1,94 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#include <kaccelmanager.h>
+#include <klocale.h>
+
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qspinbox.h>
+#include <qwhatsthis.h>
+
+#include "TimerSettings.h"
+
+TimerSettings::TimerSettings( QWidget *parent, const char *name )
+ : KDialogBase( Plain, i18n( "Timer Settings" ), Ok | Cancel,
+ Ok, parent, name, true, true )
+{
+ QFrame *page = plainPage();
+
+ QGridLayout *layout = new QGridLayout( page, 2, 2, 0, spacingHint() );
+
+ mUseGlobalUpdate = new QCheckBox( i18n( "Use update interval of worksheet" ), page );
+ layout->addMultiCellWidget( mUseGlobalUpdate, 0, 0, 0, 1 );
+
+ mLabel = new QLabel( i18n( "Update interval:" ), page );
+ layout->addWidget( mLabel, 1, 0 );
+
+ mInterval = new QSpinBox( 1, 300, 1, page );
+ mInterval->setValue( 2 );
+ mInterval->setSuffix( i18n( " sec" ) );
+ layout->addWidget( mInterval, 1, 1 );
+ mLabel->setBuddy( mInterval );
+ QWhatsThis::add( mInterval, i18n( "All displays of the sheet are updated at the rate specified here." ) );
+
+ connect( mUseGlobalUpdate, SIGNAL( toggled( bool ) ),
+ SLOT( globalUpdateChanged( bool ) ) );
+
+ mUseGlobalUpdate->setChecked( true );
+
+ KAcceleratorManager::manage( this );
+}
+
+TimerSettings::~TimerSettings()
+{
+}
+
+void TimerSettings::setUseGlobalUpdate( bool value )
+{
+ mUseGlobalUpdate->setChecked( value );
+}
+
+bool TimerSettings::useGlobalUpdate() const
+{
+ return mUseGlobalUpdate->isChecked();
+}
+
+void TimerSettings::setInterval( int interval )
+{
+ mInterval->setValue( interval );
+}
+
+int TimerSettings::interval() const
+{
+ return mInterval->value();
+}
+
+void TimerSettings::globalUpdateChanged( bool value )
+{
+ mInterval->setEnabled( !value );
+ mLabel->setEnabled( !value );
+}
+
+#include "TimerSettings.moc"
diff --git a/ksysguard/gui/ksgrd/TimerSettings.h b/ksysguard/gui/ksgrd/TimerSettings.h
new file mode 100644
index 000000000..daf2eda6f
--- /dev/null
+++ b/ksysguard/gui/ksgrd/TimerSettings.h
@@ -0,0 +1,56 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>.
+ Please do not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_TIMERSETTINGS_H
+#define KSG_TIMERSETTINGS_H
+
+#include <kdialogbase.h>
+
+class QCheckBox;
+class QLabel;
+class QSpinBox;
+
+class KDE_EXPORT TimerSettings : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ TimerSettings( QWidget *parent, const char *name = 0 );
+ ~TimerSettings();
+
+ void setUseGlobalUpdate( bool value );
+ bool useGlobalUpdate() const;
+
+ void setInterval( int interval );
+ int interval() const;
+
+ private slots:
+ void globalUpdateChanged( bool );
+
+ private:
+ QCheckBox* mUseGlobalUpdate;
+ QLabel* mLabel;
+ QSpinBox* mInterval;
+};
+
+#endif
diff --git a/ksysguard/gui/ksysguard.cc b/ksysguard/gui/ksysguard.cc
new file mode 100644
index 000000000..4750a380f
--- /dev/null
+++ b/ksysguard/gui/ksysguard.cc
@@ -0,0 +1,650 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger
+ <cs@kde.org>. Please do not commit any changes without consulting
+ me first. Thanks!
+
+ KSysGuard has been written with some source code and ideas from
+ ktop (<1.0). Early versions of ktop have been written by Bernd
+ Johannes Wuebben <wuebben@math.cornell.edu> and Nicolas Leclercq
+ <nicknet@planete.net>.
+
+*/
+
+#include <assert.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <kaboutdata.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kdebug.h>
+#include <kedittoolbar.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ksgrd/SensorAgent.h>
+#include <ksgrd/SensorManager.h>
+#include <ksgrd/StyleEngine.h>
+#include <kstandarddirs.h>
+#include <kstatusbar.h>
+#include <kstdaction.h>
+#include <kwin.h>
+#include <kwinmodule.h>
+#include <dnssd/remoteservice.h>
+
+
+#include "../version.h"
+#include "SensorBrowser.h"
+#include "Workspace.h"
+
+#include "ksysguard.h"
+
+static const char Description[] = I18N_NOOP( "KDE system guard" );
+TopLevel* topLevel;
+
+/**
+ This is the constructor for the main widget. It sets up the menu and the
+ TaskMan widget.
+ */
+TopLevel::TopLevel( const char *name )
+ : KMainWindow( 0, name ), DCOPObject( "KSysGuardIface" )
+{
+ setPlainCaption( i18n( "KDE System Guard" ) );
+ mDontSaveSession = false;
+ mTimerId = -1;
+
+ mSplitter = new QSplitter( this );
+ mSplitter->setOrientation( Horizontal );
+ mSplitter->setOpaqueResize( KGlobalSettings::opaqueResize() );
+ setCentralWidget( mSplitter );
+
+ mSensorBrowser = new SensorBrowser( mSplitter, KSGRD::SensorMgr );
+
+ mServiceBrowser = new DNSSD::ServiceBrowser("_ksysguard._tcp", 0, true);
+ connect(mServiceBrowser,SIGNAL(serviceAdded(DNSSD::RemoteService::Ptr)),this,
+ SLOT(serviceAdded(DNSSD::RemoteService::Ptr)));
+
+ mWorkSpace = new Workspace( mSplitter );
+ connect( mWorkSpace, SIGNAL( announceRecentURL( const KURL& ) ),
+ SLOT( registerRecentURL( const KURL& ) ) );
+ connect( mWorkSpace, SIGNAL( setCaption( const QString&, bool ) ),
+ SLOT( setCaption( const QString&, bool ) ) );
+ connect( KSGRD::Style, SIGNAL( applyStyleToWorksheet() ), mWorkSpace,
+ SLOT( applyStyle() ) );
+
+ /* Create the status bar. It displays some information about the
+ * number of processes and the memory consumption of the local
+ * host. */
+ statusBar()->insertFixedItem( i18n( "88888 Processes" ), 0 );
+ statusBar()->insertFixedItem( i18n( "Memory: 88888888888 kB used, "
+ "88888888888 kB free" ), 1 );
+ statusBar()->insertFixedItem( i18n( "Swap: 888888888 kB used, "
+ "888888888 kB free" ), 2 );
+ statusBar()->hide();
+
+ // create actions for menue entries
+ new KAction( i18n( "&New Worksheet..." ), "tab_new", 0, mWorkSpace,
+ SLOT( newWorkSheet() ), actionCollection(), "new_worksheet" );
+
+ new KAction( i18n( "Import Worksheet..." ), "fileopen", 0, mWorkSpace,
+ SLOT( loadWorkSheet() ), actionCollection(), "import_worksheet" );
+
+ mActionOpenRecent = new KRecentFilesAction( i18n( "&Import Recent Worksheet" ),"fileopen", 0,
+ mWorkSpace, SLOT( loadWorkSheet( const KURL& ) ), actionCollection(), "recent_import_worksheet" );
+
+ new KAction( i18n( "&Remove Worksheet" ), "tab_remove", 0, mWorkSpace,
+ SLOT( deleteWorkSheet() ), actionCollection(), "remove_worksheet" );
+
+ new KAction( i18n( "&Export Worksheet..." ), "filesaveas", 0, mWorkSpace,
+ SLOT( saveWorkSheetAs() ), actionCollection(), "export_worksheet" );
+
+ KStdAction::quit( this, SLOT( close() ), actionCollection() );
+
+ new KAction( i18n( "C&onnect Host..." ), "connect_established", 0, this,
+ SLOT( connectHost() ), actionCollection(), "connect_host" );
+ new KAction( i18n( "D&isconnect Host" ), "connect_no", 0, this,
+ SLOT( disconnectHost() ), actionCollection(), "disconnect_host" );
+
+// KStdAction::cut( mWorkSpace, SLOT( cut() ), actionCollection() );
+// KStdAction::copy( mWorkSpace, SLOT( copy() ), actionCollection() );
+// KStdAction::paste( mWorkSpace, SLOT( paste() ), actionCollection() );
+ new KAction( i18n( "&Worksheet Properties" ), "configure", 0, mWorkSpace,
+ SLOT( configure() ), actionCollection(), "configure_sheet" );
+
+ new KAction( i18n( "Load Standard Sheets" ), "revert",
+ 0, this, SLOT( resetWorkSheets() ),
+ actionCollection(), "revert_all_worksheets" );
+
+ new KAction( i18n( "Configure &Style..." ), "colorize", 0, this,
+ SLOT( editStyle() ), actionCollection(), "configure_style" );
+
+ // TODO remove resize and fix so sizeHints() determines default size.
+ if (!initialGeometrySet())
+ resize( 640, 480 );
+ setupGUI(ToolBar | Keys | StatusBar | Create);
+ setAutoSaveSettings();
+}
+
+
+/*
+ * DCOP Interface functions
+ */
+void TopLevel::resetWorkSheets()
+{
+ if ( KMessageBox::warningContinueCancel( this,
+ i18n( "Do you really want to restore the default worksheets?" ),
+ i18n( "Reset All Worksheets" ),
+ i18n("Reset"),
+ "AskResetWorkSheets") == KMessageBox::Cancel )
+ return;
+
+ mWorkSpace->removeAllWorkSheets();
+
+ KStandardDirs* kstd = KGlobal::dirs();
+ kstd->addResourceType( "data", "share/apps/ksysguard" );
+
+ QString workDir = kstd->saveLocation( "data", "ksysguard" );
+
+ QString file = kstd->findResource( "data", "SystemLoad.sgrd" );
+ QString newFile = workDir + "/" + i18n( "System Load" ) + ".sgrd";
+ if ( !file.isEmpty() )
+ mWorkSpace->restoreWorkSheet( file, newFile );
+
+ file = kstd->findResource( "data", "ProcessTable.sgrd" );
+ newFile = workDir + "/" + i18n( "Process Table" ) + ".sgrd";
+ if ( !file.isEmpty() )
+ mWorkSpace->restoreWorkSheet( file, newFile );
+}
+
+void TopLevel::showProcesses()
+{
+ mWorkSpace->showProcesses();
+}
+
+void TopLevel::showOnCurrentDesktop()
+{
+ KWin::setOnDesktop( winId(), KWin::currentDesktop() );
+ kapp->updateUserTimestamp();
+ KWin::forceActiveWindow( winId() );
+}
+
+void TopLevel::loadWorkSheet( const QString &fileName )
+{
+ mWorkSpace->loadWorkSheet( KURL( fileName ) );
+}
+
+void TopLevel::removeWorkSheet( const QString &fileName )
+{
+ mWorkSpace->deleteWorkSheet( fileName );
+}
+
+QStringList TopLevel::listSensors( const QString &hostName )
+{
+ return mSensorBrowser->listSensors( hostName );
+}
+
+QStringList TopLevel::listHosts()
+{
+ return mSensorBrowser->listHosts();
+}
+
+QString TopLevel::readIntegerSensor( const QString &sensorLocator )
+{
+ QString host = sensorLocator.left( sensorLocator.find( ':' ) );
+ QString sensor = sensorLocator.right( sensorLocator.length() -
+ sensorLocator.find( ':' ) - 1 );
+
+ DCOPClientTransaction *dcopTransaction = kapp->dcopClient()->beginTransaction();
+ mDCopFIFO.prepend( dcopTransaction );
+
+ KSGRD::SensorMgr->engage( host, "", "ksysguardd" );
+ KSGRD::SensorMgr->sendRequest( host, sensor, (KSGRD::SensorClient*)this, 133 );
+
+ return QString::null;
+}
+
+QStringList TopLevel::readListSensor( const QString& sensorLocator )
+{
+ QStringList retval;
+
+ QString host = sensorLocator.left( sensorLocator.find( ':' ) );
+ QString sensor = sensorLocator.right( sensorLocator.length() -
+ sensorLocator.find( ':' ) - 1 );
+
+ DCOPClientTransaction *dcopTransaction = kapp->dcopClient()->beginTransaction();
+ mDCopFIFO.prepend( dcopTransaction );
+
+ KSGRD::SensorMgr->engage( host, "", "ksysguardd" );
+ KSGRD::SensorMgr->sendRequest( host, sensor, (KSGRD::SensorClient*)this, 134 );
+
+ return retval;
+}
+/*
+ * End of DCOP Interface section
+ */
+
+void TopLevel::serviceAdded(DNSSD::RemoteService::Ptr srv)
+{
+ KSGRD::SensorMgr->engage( srv->hostName(), "", "", srv->port() );
+}
+
+void TopLevel::registerRecentURL( const KURL &url )
+{
+ mActionOpenRecent->addURL( url );
+}
+
+void TopLevel::beATaskManager()
+{
+ mWorkSpace->showProcesses();
+
+ // Avoid displaying splitter widget
+ mSensorBrowser->hide();
+
+ // No toolbar and status bar in taskmanager mode.
+ toolBar( "mainToolBar" )->hide();
+
+ mDontSaveSession = true;
+
+ stateChanged( "showProcessState" );
+}
+
+void TopLevel::showRequestedSheets()
+{
+ toolBar( "mainToolBar" )->hide();
+
+ QValueList<int> sizes;
+ sizes.append( 0 );
+ sizes.append( 100 );
+ mSplitter->setSizes( sizes );
+}
+
+void TopLevel::initStatusBar()
+{
+ KSGRD::SensorMgr->engage( "localhost", "", "ksysguardd" );
+ /* Request info about the swap space size and the units it is
+ * measured in. The requested info will be received by
+ * answerReceived(). */
+ KSGRD::SensorMgr->sendRequest( "localhost", "mem/swap/used?",
+ (KSGRD::SensorClient*)this, 5 );
+ updateStatusBar();
+ mServiceBrowser->startBrowse();
+
+ KToggleAction *sb = dynamic_cast<KToggleAction*>(action("options_show_statusbar"));
+ if (sb)
+ connect(sb, SIGNAL(toggled(bool)), this, SLOT(updateStatusBar()));
+}
+
+void TopLevel::updateStatusBar()
+{
+ if ( mTimerId == -1 )
+ mTimerId = startTimer( 2000 );
+
+ // call timerEvent to fill the status bar with real values
+ timerEvent( 0 );
+}
+
+void TopLevel::connectHost()
+{
+ KSGRD::SensorMgr->engageHost( "" );
+}
+
+void TopLevel::disconnectHost()
+{
+ mSensorBrowser->disconnect();
+}
+
+void TopLevel::editToolbars()
+{
+ saveMainWindowSettings( kapp->config() );
+ KEditToolbar dlg( actionCollection() );
+ connect( &dlg, SIGNAL( newToolbarConfig() ), this,
+ SLOT( slotNewToolbarConfig() ) );
+
+ dlg.exec();
+}
+
+void TopLevel::slotNewToolbarConfig()
+{
+ createGUI();
+ applyMainWindowSettings( kapp->config() );
+}
+
+void TopLevel::editStyle()
+{
+ KSGRD::Style->configure();
+}
+
+void TopLevel::customEvent( QCustomEvent *e )
+{
+ if ( e->type() == QEvent::User ) {
+ /* Due to the asynchronous communication between ksysguard and its
+ * back-ends, we sometimes need to show message boxes that were
+ * triggered by objects that have died already. */
+ KMessageBox::error( this, *((QString*)e->data()) );
+ delete (QString*)e->data();
+ }
+}
+
+void TopLevel::timerEvent( QTimerEvent* )
+{
+ if ( statusBar()->isVisibleTo( this ) ) {
+ /* Request some info about the memory status. The requested
+ * information will be received by answerReceived(). */
+ KSGRD::SensorMgr->sendRequest( "localhost", "pscount",
+ (KSGRD::SensorClient*)this, 0 );
+ KSGRD::SensorMgr->sendRequest( "localhost", "mem/physical/free",
+ (KSGRD::SensorClient*)this, 1 );
+ KSGRD::SensorMgr->sendRequest( "localhost", "mem/physical/used",
+ (KSGRD::SensorClient*)this, 2 );
+ KSGRD::SensorMgr->sendRequest( "localhost", "mem/swap/free",
+ (KSGRD::SensorClient*)this, 3 );
+ KSGRD::SensorMgr->sendRequest( "localhost", "mem/swap/used",
+ (KSGRD::SensorClient*)this, 4 );
+ }
+}
+
+bool TopLevel::queryClose()
+{
+ if ( !mDontSaveSession ) {
+ if ( !mWorkSpace->saveOnQuit() )
+ return false;
+
+ saveProperties( kapp->config() );
+ kapp->config()->sync();
+ }
+
+ return true;
+}
+
+void TopLevel::readProperties( KConfig *cfg )
+{
+ /* we can ignore 'isMaximized' because we can't set the window
+ maximized, so we save the coordinates instead */
+ if ( cfg->readBoolEntry( "isMinimized" ) == true )
+ showMinimized();
+
+ QValueList<int> sizes = cfg->readIntListEntry( "SplitterSizeList" );
+ if ( sizes.isEmpty() ) {
+ // start with a 30/70 ratio
+ sizes.append( 30 );
+ sizes.append( 70 );
+ }
+ mSplitter->setSizes( sizes );
+
+ KSGRD::SensorMgr->readProperties( cfg );
+ KSGRD::Style->readProperties( cfg );
+
+ mWorkSpace->readProperties( cfg );
+
+ mActionOpenRecent->loadEntries( cfg );
+
+ applyMainWindowSettings( cfg );
+}
+
+void TopLevel::saveProperties( KConfig *cfg )
+{
+ mActionOpenRecent->saveEntries( cfg );
+
+ cfg->writeEntry( "isMinimized", isMinimized() );
+ cfg->writeEntry( "SplitterSizeList", mSplitter->sizes() );
+
+ KSGRD::Style->saveProperties( cfg );
+ KSGRD::SensorMgr->saveProperties( cfg );
+
+ saveMainWindowSettings( cfg );
+ mWorkSpace->saveProperties( cfg );
+}
+
+void TopLevel::answerReceived( int id, const QString &answer )
+{
+ QString s;
+ static QString unit;
+ static long mUsed = 0;
+ static long mFree = 0;
+ static long sUsed = 0;
+ static long sFree = 0;
+
+ switch ( id ) {
+ case 0:
+ // yes, I know there is never 1 process, but that's the way
+ // singular vs. plural works :/
+ //
+ // To use pluralForms, though, you need to convert to
+ // an integer, not use the QString straight.
+ s = i18n( "1 Process", "%n Processes", answer.toInt() );
+ statusBar()->changeItem( s, 0 );
+ break;
+
+ case 1:
+ mFree = answer.toLong();
+ break;
+
+ case 2:
+ mUsed = answer.toLong();
+ s = i18n( "Memory: %1 %2 used, %3 %4 free" )
+ .arg( KGlobal::locale()->formatNumber( mUsed, 0 ) ).arg( unit )
+ .arg( KGlobal::locale()->formatNumber( mFree, 0 ) ).arg( unit );
+ statusBar()->changeItem( s, 1 );
+ break;
+
+ case 3:
+ sFree = answer.toLong();
+ setSwapInfo( sUsed, sFree, unit );
+ break;
+
+ case 4:
+ sUsed = answer.toLong();
+ setSwapInfo( sUsed, sFree, unit );
+ break;
+
+ case 5: {
+ KSGRD::SensorIntegerInfo info( answer );
+ unit = KSGRD::SensorMgr->translateUnit( info.unit() );
+ }
+
+ case 133: {
+ QCString replyType = "QString";
+ QByteArray replyData;
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << answer;
+
+ DCOPClientTransaction *dcopTransaction = mDCopFIFO.last();
+ kapp->dcopClient()->endTransaction( dcopTransaction, replyType, replyData );
+ mDCopFIFO.removeLast();
+ break;
+ }
+
+ case 134: {
+ QStringList resultList;
+ QCString replyType = "QStringList";
+ QByteArray replyData;
+ QDataStream reply( replyData, IO_WriteOnly );
+
+ KSGRD::SensorTokenizer lines( answer, '\n' );
+
+ for ( unsigned int i = 0; i < lines.count(); i++ )
+ resultList.append( lines[ i ] );
+
+ reply << resultList;
+
+ DCOPClientTransaction *dcopTransaction = mDCopFIFO.last();
+ kapp->dcopClient()->endTransaction( dcopTransaction, replyType, replyData );
+ mDCopFIFO.removeLast();
+ break;
+ }
+ }
+}
+
+void TopLevel::setSwapInfo( long used, long free, const QString &unit )
+{
+ QString msg;
+ if ( used == 0 && free == 0 ) // no swap available
+ msg = i18n( "No swap space available" );
+ else {
+ msg = i18n( "Swap: %1 %2 used, %3 %4 free" )
+ .arg( KGlobal::locale()->formatNumber( used, 0 ) ).arg( unit )
+ .arg( KGlobal::locale()->formatNumber( free, 0 ) ).arg( unit );
+ }
+
+ statusBar()->changeItem( msg, 2 );
+}
+
+static const KCmdLineOptions options[] = {
+ { "showprocesses", I18N_NOOP( "Show only process list of local host" ), 0 },
+ { "+[worksheet]", I18N_NOOP( "Optional worksheet files to load" ), 0 },
+ KCmdLineLastOption
+};
+
+/*
+ * Once upon a time...
+ */
+int main( int argc, char** argv )
+{
+ // initpipe is used to keep the parent process around till the child
+ // has registered with dcop.
+ int initpipe[ 2 ];
+ pipe( initpipe );
+
+ /* This forking will put ksysguard in it's on session not having a
+ * controlling terminal attached to it. This prevents ssh from
+ * using this terminal for password requests. Unfortunately you
+ * now need a ssh with ssh-askpass support to popup an X dialog to
+ * enter the password. Currently only the original ssh provides this
+ * but not open-ssh. */
+
+ pid_t pid;
+ if ( ( pid = fork() ) < 0 )
+ return -1;
+ else
+ if ( pid != 0 ) {
+ close( initpipe[ 1 ] );
+
+ // wait till init is complete
+ char c;
+ while( read( initpipe[ 0 ], &c, 1 ) < 0 );
+
+ // then exit
+ close( initpipe[ 0 ] );
+ exit( 0 );
+ }
+
+ close( initpipe[ 0 ] );
+ setsid();
+
+ KAboutData aboutData( "ksysguard", I18N_NOOP( "KDE System Guard" ),
+ KSYSGUARD_VERSION, Description, KAboutData::License_GPL,
+ I18N_NOOP( "(c) 1996-2002 The KSysGuard Developers" ) );
+ aboutData.addAuthor( "Chris Schlaeger", "Current Maintainer", "cs@kde.org" );
+ aboutData.addAuthor( "Tobias Koenig", 0, "tokoe@kde.org" );
+ aboutData.addAuthor( "Nicolas Leclercq", 0, "nicknet@planete.net" );
+ aboutData.addAuthor( "Alex Sanda", 0, "alex@darkstart.ping.at" );
+ aboutData.addAuthor( "Bernd Johannes Wuebben", 0, "wuebben@math.cornell.edu" );
+ aboutData.addAuthor( "Ralf Mueller", 0, "rlaf@bj-ig.de" );
+ aboutData.addAuthor( "Hamish Rodda", 0, "rodda@kde.org" );
+ aboutData.addAuthor( "Torsten Kasch", I18N_NOOP( "Solaris Support\n"
+ "Parts derived (by permission) from the sunos5\n"
+ "module of William LeFebvre's \"top\" utility." ),
+ "tk@Genetik.Uni-Bielefeld.DE" );
+
+ KCmdLineArgs::init( argc, argv, &aboutData );
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KApplication::disableAutoDcopRegistration();
+ // initialize KDE application
+ KApplication *app = new KApplication;
+
+ KSGRD::SensorMgr = new KSGRD::SensorManager();
+ KSGRD::Style = new KSGRD::StyleEngine();
+
+ KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
+
+ int result = 0;
+
+ if ( args->isSet( "showprocesses" ) ) {
+ /* To avoid having multiple instances of ksysguard in
+ * taskmanager mode we check if another taskmanager is running
+ * already. If so, we terminate this one immediately. */
+ if ( app->dcopClient()->registerAs( "ksysguard_taskmanager", false ) ==
+ "ksysguard_taskmanager" ) {
+ // We have registered with DCOP, our parent can exit now.
+ char c = 0;
+ write( initpipe[ 1 ], &c, 1 );
+ close( initpipe[ 1 ] );
+
+ topLevel = new TopLevel( "KSysGuard" );
+ topLevel->beATaskManager();
+ topLevel->initStatusBar();
+ topLevel->show();
+ KSGRD::SensorMgr->setBroadcaster( topLevel );
+
+ // run the application
+ result = app->exec();
+ } else {
+ QByteArray data;
+ app->dcopClient()->send( "ksysguard_taskmanager", "KSysGuardIface",
+ "showOnCurrentDesktop()", data );
+ }
+ } else {
+ app->dcopClient()->registerAs( "ksysguard" );
+ app->dcopClient()->setDefaultObject( "KSysGuardIface" );
+
+ // We have registered with DCOP, our parent can exit now.
+ char c = 0;
+ write( initpipe[ 1 ], &c, 1 );
+ close( initpipe[ 1 ] );
+
+ topLevel = new TopLevel( "KSysGuard" );
+
+ // create top-level widget
+ if ( args->count() > 0 ) {
+ /* The user has specified a list of worksheets to load. In this
+ * case we do not restore any previous settings but load all the
+ * requested worksheets. */
+ topLevel->showRequestedSheets();
+ for ( int i = 0; i < args->count(); ++i )
+ topLevel->loadWorkSheet( args->arg( i ) );
+ } else {
+ if ( app->isRestored() )
+ topLevel->restore( 1 );
+ else
+ topLevel->readProperties( app->config() );
+ }
+
+ topLevel->initStatusBar();
+ topLevel->show();
+ KSGRD::SensorMgr->setBroadcaster( topLevel );
+
+ // run the application
+ result = app->exec();
+ }
+
+ delete KSGRD::Style;
+ delete KSGRD::SensorMgr;
+ delete app;
+
+ return result;
+}
+
+#include "ksysguard.moc"
diff --git a/ksysguard/gui/ksysguard.desktop b/ksysguard/gui/ksysguard.desktop
new file mode 100644
index 000000000..76a960ec4
--- /dev/null
+++ b/ksysguard/gui/ksysguard.desktop
@@ -0,0 +1,102 @@
+[Desktop Entry]
+Name=KSysGuard
+Name[af]=Ksysguard
+Name[ar]=حارس النظام
+Name[bg]=Системна защита
+Name[csb]=KDE Wachtôrz Systemë
+Name[de]=Systemüberwachung
+Name[eo]=KSistemGardilo
+Name[et]=Süsteemi valvur
+Name[fr]=Surveillance du système
+Name[he]=משמר המערכת
+Name[hi]=के-सिस-गार्ड
+Name[hr]=KDE zaštitnik sustava
+Name[is]=KDE álagsmælir
+Name[ja]=KDE システムガード
+Name[lo]=ກວດສອບແລະປ້ອງກັນລະບົບ - K
+Name[mn]=Системийн хяналт
+Name[nb]=KDE Systemvakt
+Name[ne]=KSys रक्षक
+Name[nn]=KDE Systemvakt
+Name[nso]=Thlokomelo ya KSys
+Name[pl]=KDE Strażnik Systemu
+Name[sk]=KDE Strážca systému
+Name[sv]=Systemövervakare
+Name[tg]=Муҳофизати системаи-K
+Name[th]=ตรวจสอบและป้องกันระบบ
+Name[uz]=KDE tizim nazoratchisi
+Name[uz@cyrillic]=KDE тизим назоратчиси
+Name[vi]=Bảo vệ Hệ thống KDE
+Name[wa]=KSisGåde
+GenericName=Performance Monitor
+GenericName[af]=Werkverrigting Monitor
+GenericName[ar]=مراقب الإداء
+GenericName[be]=Сістэмны назіральнік
+GenericName[bg]=Мониторинг на системата
+GenericName[bs]=Monitor performansi
+GenericName[ca]=Monitor de rendiment
+GenericName[cs]=Monitor výkonu
+GenericName[csb]=Mònitor spòroscë
+GenericName[da]=Overvågning af ydelse
+GenericName[de]=Performancemonitor
+GenericName[el]=Επόπτης συστήματος
+GenericName[eo]=Rendimento Monitoro
+GenericName[es]=Monitor de rendimiento
+GenericName[et]=Jõudluse monitor
+GenericName[eu]=Sistemaren errendimenduaren monitorea
+GenericName[fa]=نمایشگر کارایی
+GenericName[fi]=Järjestelmän suorituskyvyn monitori
+GenericName[fr]=Indicateurs de performance
+GenericName[fy]=Prestaasjemonitor
+GenericName[gl]=Monitor de Rendemento
+GenericName[he]=צג מערכת
+GenericName[hr]=Nadzor performansi
+GenericName[hu]=Teljesítményfigyelő
+GenericName[is]=Afkasta eftirlit
+GenericName[it]=Monitor delle prestazioni
+GenericName[ja]=パフォーマンスモニター
+GenericName[ka]=წარმადობის მონიტორი
+GenericName[kk]=Жылдамдылық бақылаушысы
+GenericName[km]=កម្មវិធី​ត្រួតពិនិត្យ​ដំណើរការ
+GenericName[lt]=Veiksenos monitorius
+GenericName[mk]=Монитор на перформанси
+GenericName[ms]=Pemantau Prestasi
+GenericName[nb]=Ytelsesovervåker
+GenericName[nds]=Leisten-Kieker
+GenericName[ne]=सम्पादन मनिटर
+GenericName[nl]=Prestatiemonitor
+GenericName[nn]=Ytelsesovervakar
+GenericName[pa]=ਪਰਦਰਸ਼ਨ ਨਿਗਰਾਨ
+GenericName[pl]=Monitor wydajności
+GenericName[pt]=Monitor de Performance
+GenericName[pt_BR]=Monitor de Performance
+GenericName[ro]=Monitor de performanță
+GenericName[ru]=Монитор производительности
+GenericName[rw]=Mugaragaza y'Imikorere
+GenericName[se]=Buvttogoziheaddji
+GenericName[sk]=Sledovač výkonu
+GenericName[sl]=Nadzor delovanja
+GenericName[sr]=Монитор перформанси
+GenericName[sr@Latn]=Monitor performansi
+GenericName[sv]=Prestandaövervakare
+GenericName[ta]=செயல்திறன் திரை
+GenericName[th]=สอดส่องประสิทธิภาพการทำงานของระบบ
+GenericName[tr]=Sistem İzleyici
+GenericName[tt]=Citezlek Küzätüçese
+GenericName[uk]=Монітор швидкодії
+GenericName[uz]=Tizimni nazorat qilish
+GenericName[uz@cyrillic]=Тизимни назорат қилиш
+GenericName[vi]=Theo dõi Hiệu năng
+GenericName[wa]=Corwaitoe di ç' ki va bén
+GenericName[zh_CN]=性能监视器
+GenericName[zh_TW]=效能監視器
+Exec=ksysguard %U
+Icon=ksysguard
+Type=Application
+MimeType=application/x-ksysguard;
+DocPath=ksysguard/index.html
+Terminal=false
+Path=
+X-KDE-StartupNotify=true
+X-DCOP-ServiceType=Multi
+Categories=Qt;KDE;System;
diff --git a/ksysguard/gui/ksysguard.h b/ksysguard/gui/ksysguard.h
new file mode 100644
index 000000000..8d2ef15d9
--- /dev/null
+++ b/ksysguard/gui/ksysguard.h
@@ -0,0 +1,124 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ KSysGuard is currently maintained by Chris Schlaeger <cs@kde.org>. Please do
+ not commit any changes without consulting me first. Thanks!
+
+*/
+
+#ifndef KSG_KSYSGUARD_H
+#define KSG_KSYSGUARD_H
+
+#include <qevent.h>
+
+#include <dcopclient.h>
+#include <dcopobject.h>
+#include <kapplication.h>
+#include <kmainwindow.h>
+#include <dnssd/servicebrowser.h>
+
+#include <ksgrd/SensorClient.h>
+
+class KRecentFilesAction;
+class KToggleAction;
+
+class QSplitter;
+class SensorBrowser;
+class Workspace;
+
+class TopLevel : public KMainWindow, public KSGRD::SensorClient, public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+
+ public:
+ TopLevel( const char *name = 0 );
+
+ virtual void saveProperties( KConfig* );
+ virtual void readProperties( KConfig* );
+
+ virtual void answerReceived( int id, const QString& );
+
+ void beATaskManager();
+ void showRequestedSheets();
+ void initStatusBar();
+
+ k_dcop:
+ // calling ksysguard with kwin/kicker hot-key
+ ASYNC showProcesses();
+ ASYNC showOnCurrentDesktop();
+ ASYNC loadWorkSheet( const QString &fileName );
+ ASYNC removeWorkSheet( const QString &fileName );
+ QStringList listHosts();
+ QStringList listSensors( const QString &hostName );
+ QString readIntegerSensor( const QString &sensorLocator );
+ QStringList readListSensor( const QString &sensorLocator );
+
+ public slots:
+ void registerRecentURL( const KURL &url );
+ void resetWorkSheets();
+
+ protected:
+ virtual void customEvent( QCustomEvent* );
+ virtual void timerEvent( QTimerEvent* );
+ virtual bool queryClose();
+
+ protected slots:
+ void connectHost();
+ void disconnectHost();
+ void updateStatusBar();
+ void editToolbars();
+ void editStyle();
+ void slotNewToolbarConfig();
+ void serviceAdded(DNSSD::RemoteService::Ptr srv);
+
+ private:
+ void setSwapInfo( long, long, const QString& );
+
+ QPtrList<DCOPClientTransaction> mDCopFIFO;
+
+ QSplitter* mSplitter;
+ KRecentFilesAction* mActionOpenRecent;
+
+ SensorBrowser* mSensorBrowser;
+ Workspace* mWorkSpace;
+
+ DNSSD::ServiceBrowser* mServiceBrowser;
+
+ bool mDontSaveSession;
+ int mTimerId;
+};
+
+extern TopLevel* Toplevel;
+
+/*
+ since there is only a forward declaration of DCOPClientTransaction
+ in dcopclient.h we have to redefine it here, otherwise QPtrList
+ causes errors
+*/
+typedef unsigned long CARD32;
+
+class DCOPClientTransaction
+{
+ public:
+ Q_INT32 id;
+ CARD32 key;
+ QCString senderId;
+};
+
+#endif
diff --git a/ksysguard/gui/ksysguardapplet.desktop b/ksysguard/gui/ksysguardapplet.desktop
new file mode 100644
index 000000000..08441fe64
--- /dev/null
+++ b/ksysguard/gui/ksysguardapplet.desktop
@@ -0,0 +1,120 @@
+[Desktop Entry]
+Type=Plugin
+Name=System Guard
+Name[af]=Stelsel Wag
+Name[ar]=حارس النظام
+Name[be]=Сістэмны ахоўнік
+Name[bg]=Системен монитор
+Name[bn]=সিস্টেম প্রহরী
+Name[br]=Gward Reizhiad
+Name[bs]=Nadzor sistema
+Name[ca]=Vigilant del sistema
+Name[cs]=Strážce systému
+Name[csb]=Wachtôrz Systemë
+Name[da]=Systemvagt
+Name[de]=Systemüberwachung
+Name[el]=Φρουρός συστήματος
+Name[eo]=Sistemo Gardilo
+Name[es]=Guardián del sistema
+Name[et]=Süsteemi valvur
+Name[eu]=Sistemaren zaintzailea
+Name[fa]=محافظ سیستم
+Name[fi]=Järjestelmän valvonta
+Name[fr]=Surveillance du système
+Name[fy]=Systeemwarder
+Name[gl]=Vixiante do Sistema
+Name[he]=משמר המערכת
+Name[hr]=Zaštitnik sustava
+Name[hu]=Rendszermonitor
+Name[is]=Kerfiseftirlit
+Name[it]=Controllo del sistema
+Name[ja]=システムガード
+Name[ka]=სისტემის მცველი
+Name[kk]=Жүйе бақылаушысы
+Name[km]=ឆ្មាំ​ប្រព័ន្ធ
+Name[ko]=KDE 시스템 지킴이
+Name[lt]=Sistemos apsauga
+Name[mk]=Чувар на системот
+Name[nb]=Systemvakt
+Name[nds]=Systeemwachter
+Name[ne]=प्रणाली रक्षक
+Name[nl]=Systeembewaking
+Name[nn]=Systemvakt
+Name[pa]=ਸਿਸਟਮ ਗਾਰਡ
+Name[pl]=Strażnik Systemu
+Name[pt]=Vigilante do Sistema
+Name[pt_BR]=Guarda do Sistema
+Name[ro]=Sistem de gardă
+Name[ru]=Системный монитор
+Name[se]=Vuogádatfákta
+Name[sk]=Strážca systému
+Name[sl]=Sistemski varuh
+Name[sr]=Заштита система
+Name[sr@Latn]=Zaštita sistema
+Name[sv]=Systemövervakare
+Name[th]=ป้องกันระบบ
+Name[tr]=Sistem İzleyici
+Name[uk]=Системний вартовий
+Name[uz]=Kengaytirilgan tizim nazoratchisi
+Name[uz@cyrillic]=Кенгайтирилган тизим назоратчиси
+Name[vi]=Bảo vệ Hệ thống
+Name[wa]=Gåde do sistinme
+Name[zh_CN]=系统卫士
+Name[zh_TW]=系統守衛
+Comment=An advanced system monitor which swallows KDE system guard displays
+Comment[af]='n Gevorderde stelsel monitor wat KDE se stelsel wag skerms insluit
+Comment[be]=Адмысловы сістэмны назіральнік, які "праглынае" дысплеі сістэмнага ахоўніка KDE
+Comment[bg]=Системен монитор, който следи за състоянието на системата
+Comment[bs]=Napredni program za nadzor sistema koji obuhvata više drugih prozora
+Comment[ca]=Un monitor del sistema avançat que inclou pantalles del vigilant del sistema KDE
+Comment[cs]=Pokročilý monitor systému, který pohlcuje displeje strážce KDE
+Comment[csb]=Awansowóny mònitor systemë jaczi pòkazywô wskôzywôcze KDE Wachtôrza Systemë
+Comment[da]=En avanceret systemovervåger som svælger skærme fra KDE's systemovervågning
+Comment[de]=Erweiterte Systemüberwachung für die Kontrollleiste
+Comment[el]=Ένας προχωρημένος επόπτης του συστήματος ο οποίος ενσωματώνει προβολές του φρουρού συστήματος του KDE
+Comment[eo]=Malbaza sistemomonitoro kiu glutas KDE-sistemogardilo-ekranojn.
+Comment[es]=Un monitor avanzado del sistema que integra los gráficos del guardián del sistema de KDE
+Comment[et]=Võimas süsteemi monitor KDE süsteemi valvuri sensoritele
+Comment[eu]=Sistema monitore aurreratua, KDE sistemaren zaintzailearen pantailak bistaratzen dituena
+Comment[fa]=یک نمایشگر پیشرفتۀ سیستم که نمایشهای محافظ سیستم KDE را از بین می‌برد
+Comment[fi]=Edistynyt järjestelmän valvonta, johon sisältyy KDE järjestelmänvalvonnan näytöt
+Comment[fr]=Un surveillant avancé affichant l'état du système
+Comment[fy]=In avansearre systeemmonitor mei systeemwardings werjefte
+Comment[gl]=Un monitor do sistema que incorpora os resultados do vixiante do sistema de KDE
+Comment[he]=מנטר מערכת מתקדם המאפשר המטעה של תצוגות של משמר המערכת של KDE
+Comment[hr]=Napredan sistemski nadzor koji "guta" prikaze KDE zaštitnika sustava
+Comment[hu]=Rendszermonitor kijelzőkkel
+Comment[is]=Þróað kerfiseftirlit sem gleypir KDE álagsmæla
+Comment[it]=Un sistema di controllo del sistema avanzato che ingloba i controlli di sistema di KDE
+Comment[ja]=KDE システムガードを表示する高度なシステムモニター
+Comment[kk]=Жетілдірілген жүйе бақылаушысы
+Comment[km]=កម្មវិធី​ត្រួតពិនិត្យ​ប្រព័ន្ធកម្រិត​ខ្ពស់​ដែល​អនុញ្ញាត​ឲ្យ​ប្រព័ន្ធ​ KDE ​ត្រួត​ពិនិត្យ​ការ​បង្ហាញ
+Comment[lt]=Sudėtingesnė sistemos stebėjimo priemonė, įtraukianti KDE sistemos apsaugos stebėjimo priemones
+Comment[mk]=Напреден монитор на системот кој ги врамува приказите на чуварите на системот на KDE
+Comment[nb]=En avansert systemovervåker som svelger visninger av KDEs systemovervåker
+Comment[nds]=En verwiedert Systeemkieker, mit inbett Diagrammen vun KDE System Guard
+Comment[ne]=उन्नत प्रणाली मनिटर जसले अन्त्य गर्ने KDE प्रणाली रक्षक प्रदर्शन गर्छ
+Comment[nl]=Een geavanceerde systeemmonitor met systeembewakingsdisplays
+Comment[nn]=Ein avansert systemovervakar som svelgjer visingar av KDE-systemovervakaren
+Comment[pl]=Zaawansowany monitor systemu pokazujący wskaźniki Strażnika systemu KDE
+Comment[pt]=Um monitor de sistema avançado que engloba folhas de monitorização do sistema KDE
+Comment[pt_BR]=Um monitor avançado de sistema que permite monitorar o que a guarda do sistema do KDE exibe
+Comment[ro]=Un monitor de sistem avansat care înghite ecranele sistemului de gardă KDE
+Comment[ru]=Системный монитор
+Comment[sk]=Sledovač systému, ktorý obsahuje systémových strážcov KDE
+Comment[sl]=Napreden nadzor sistema, ki uporablja prikazovalnike iz Sistemskega varuha KDE
+Comment[sr]=Напредни монитор који гута приказе KDE-ове заштите система
+Comment[sr@Latn]=Napredni monitor koji guta prikaze KDE-ove zaštite sistema
+Comment[sv]=En avancerad systemövervakare som sväljer skärmar från KDE:s systemövervakare
+Comment[th]=ตัวเฝ้าตรวจสอบระบบขั้นก้าวหน้า ซึ่งกลืนหน้าจอของตัวป้องกันระบบ KDE
+Comment[tr]=Gelişmiş bir sistem izleyici
+Comment[uk]=Додатковий системний монітор, який поглинає показ системного вартового KDE
+Comment[uz]=Tizimning protsessor, xotira, tarmoq kabi qisimlarini kuzatib turadigan kengaytirilgan tizim nazoratchisi
+Comment[uz@cyrillic]=Тизимнинг процессор, хотира, тармоқ каби қисимларини кузатиб турадиган кенгайтирилган тизим назоратчиси
+Comment[vi]=Một trình theo dõi hệ thống nâng cao thế chỗ cho hiển thị bảo vệ hệ thống KDE
+Comment[wa]=On corwaitoe po les spepieus k' avale li håynaedje so gåde do sistinme di KDE
+Comment[zh_CN]=可显示 KDE 系统卫士效果的高级系统监视器
+Comment[zh_TW]=包含 KDE 系統守衛顯示的進階系統監視器
+Icon=ksysguard
+X-KDE-Library=sysguard_panelapplet
+X-KDE-UniqueApplet=true
diff --git a/ksysguard/gui/ksysguardui.rc b/ksysguard/gui/ksysguardui.rc
new file mode 100644
index 000000000..912894ed3
--- /dev/null
+++ b/ksysguard/gui/ksysguardui.rc
@@ -0,0 +1,50 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="ksysguard" version="5">
+<State name="showProcessState">
+ <Disable>
+ <Action name="new_worksheet"/>
+ <Action name="import_worksheet"/>
+ <Action name="recent_import_worksheet"/>
+ <Action name="export_worksheet"/>
+ <Action name="remove_worksheet"/>
+ <Action name="revert_all_worksheets"/>
+ <Action name="connect_host"/>
+ <Action name="disconnect_host"/>
+ <Action name="configure_sheet"/>
+ <Action name="configure_style"/>
+ </Disable>
+</State>
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name="new_worksheet"/>
+ <Action name="recent_import_worksheet"/>
+ <Action name="import_worksheet"/>
+ <Separator/>
+ <Action name="export_worksheet"/>
+ <Separator/>
+ <Action name="remove_worksheet"/>
+ <Action name="revert_all_worksheets"/>
+ <Separator/>
+ <Action name="connect_host"/>
+ <Action name="disconnect_host"/>
+ </Menu>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="configure_sheet"/>
+ </Menu>
+ <Menu name="settings"><text>&amp;Settings</text>
+ <Action name="configure_style"/>
+ </Menu>
+</MenuBar>
+<ToolBar name="mainToolBar" noMerge="1"><text>Main Toolbar</text>
+ <Action name="new_worksheet"/>
+ <Action name="import_worksheet"/>
+ <Action name="export_worksheet"/>
+ <Separator/>
+ <Action name="connect_host"/>
+ <Action name="disconnect_host"/>
+ <Separator/>
+ <Action name="configure_sheet"/>
+ <Action name="configure_style"/>
+</ToolBar>
+</kpartgui>
+
diff --git a/ksysguard/gui/x-ksysguard.desktop b/ksysguard/gui/x-ksysguard.desktop
new file mode 100644
index 000000000..78a0a15c9
--- /dev/null
+++ b/ksysguard/gui/x-ksysguard.desktop
@@ -0,0 +1,86 @@
+# KDE Config File
+[Desktop Entry]
+NotShowIn=GNOME;
+MimeType=application/x-ksysguard
+Comment=KDE System Guard
+Comment[af]=KDE Stelsel Wag
+Comment[ar]=حارس النظام KDE
+Comment[az]=KDE Sistem Cangüdəni
+Comment[be]=Ахоўнік сістэмы KDE
+Comment[bg]=Системна защита
+Comment[bn]=কে.ডি.ই. সিস্টেম গার্ড
+Comment[br]=Gward Reizhiad KDE
+Comment[bs]=KDE zaštita sistema
+Comment[ca]=Vigilant del sistema KDE
+Comment[cs]=Správce systému KDE
+Comment[csb]=KDE Wachtôrz Systemë
+Comment[cy]=Gwarchodwr Cysawd KDE
+Comment[da]=KDE Systemvagt
+Comment[de]=KDE-Systemüberwachung
+Comment[el]=Φρουρός συστήματος του KDE
+Comment[eo]=KDE-Sistemobservilo
+Comment[es]=Guardián del sistema de KDE
+Comment[et]=KDE süsteemi valvur
+Comment[eu]=KDEren sistemaren kontrola
+Comment[fa]=محافظ سیستم KDE
+Comment[fi]=KDE:n järjestelmänvalvonta
+Comment[fr]=Surveillance du système
+Comment[fy]=KDE systeembefeiliging
+Comment[ga]=Garda an Chórais KDE
+Comment[gl]=Vixiante do Sistema de KDE
+Comment[he]=משמר המערכת של KDE
+Comment[hi]=केडीई तंत्र गार्ड
+Comment[hr]=KDE zaštitnik sustava
+Comment[hu]=KDE rendszermonitor
+Comment[is]=KDE kerfisvörður
+Comment[it]=Controllo di sistema di KDE
+Comment[ja]=KDE システムガード
+Comment[ka]=KDE სისტემური მონიტორი
+Comment[kk]=KDE жүйелік бақылаушысы
+Comment[km]=ការពារ​ប្រព័ន្ធ KDE
+Comment[ko]=KDE 시스템 지킴이
+Comment[lo]=ເຄື່ອງມືຶປ້ອງກັນລະບົບຂອງ KDE
+Comment[lt]=KDE sistemos apsauga
+Comment[lv]=KDE Sistēmas Sargs
+Comment[mk]=KDE Системски чувар
+Comment[mn]=КДЭ-Системийн хяналт
+Comment[ms]=Pengawas Sistem KDE
+Comment[mt]=Gwardja tas-Sistema KDE
+Comment[nb]=KDE Systemovervåker
+Comment[nds]=KDE-Systeemwachter
+Comment[ne]=KDE प्रणाली रक्षक
+Comment[nl]=KDE systeembewaking
+Comment[nn]=KDE Systemvakt
+Comment[nso]=Thlokomelo ya System ya KDE
+Comment[pa]=KDE ਸਿਸਟਮ ਗਾਰਡ
+Comment[pl]=KDE Strażnik Systemu
+Comment[pt]=Vigilante do sistema do KDE
+Comment[pt_BR]=Sistema de Guarda do KDE
+Comment[ro]=Sistem de gardă KDE
+Comment[ru]=Системный монитор
+Comment[rw]=Umurinzi Sisitemu KDE
+Comment[se]=KDE vuogádatfákta
+Comment[sk]=KDE Strážca systému
+Comment[sl]=Sistemski varuh KDE
+Comment[sr]=KDE чувар система
+Comment[sr@Latn]=KDE čuvar sistema
+Comment[sv]=KDE:s systemövervakare
+Comment[ta]=KDE கணினி காவலன்
+Comment[tg]=Муҳофизи системаи KDE
+Comment[th]=เครื่องมือป้องกันระบบ KDE
+Comment[tr]=KDE Sistem Koruyucu
+Comment[tt]=KDE'nıñ Sistem Saqçısı
+Comment[uk]=Системний вартовий KDE
+Comment[uz]=KDE tizim nazoratchisi
+Comment[uz@cyrillic]=KDE тизим назоратчиси
+Comment[ven]=Mulindi wa maitele a KDE
+Comment[vi]=Trình bảo vệ Hệ thống KDE
+Comment[wa]=Gåre sistinme KDE
+Comment[xh]=KDE Ukhuselo lendlela yokusebenza
+Comment[zh_CN]=KDE 系统卫士
+Comment[zh_TW]=KDE 系統守衛
+Comment[zu]=Unogada Wesistimu ye-KDE
+Icon=ksysguard
+Type=MimeType
+Patterns=*.sgrd;
+X-KDE-AutoEmbed=false
diff --git a/ksysguard/ksysguardd/Command.c b/ksysguard/ksysguardd/Command.c
new file mode 100644
index 000000000..17abffb92
--- /dev/null
+++ b/ksysguard/ksysguardd/Command.c
@@ -0,0 +1,261 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include "ccont.h"
+#include "ksysguardd.h"
+
+#include "Command.h"
+
+typedef struct {
+ char* command;
+ cmdExecutor ex;
+ char* type;
+ int isMonitor;
+ struct SensorModul* sm;
+} Command;
+
+static CONTAINER CommandList;
+static sigset_t SignalSet;
+
+void command_cleanup( void* v );
+
+void command_cleanup( void* v )
+{
+ if ( v ) {
+ Command* c = v;
+ if ( c->command )
+ free ( c->command );
+ if ( c->type )
+ free ( c->type );
+ free ( v );
+ }
+}
+
+/*
+================================ public part =================================
+*/
+
+int ReconfigureFlag = 0;
+int CheckSetupFlag = 0;
+
+void print_error( const char *fmt, ... )
+{
+ char errmsg[ 1024 ];
+ va_list az;
+
+ va_start( az, fmt );
+ vsnprintf( errmsg, sizeof( errmsg ) - 1, fmt, az );
+ errmsg[ sizeof( errmsg ) - 1 ] = '\0';
+ va_end( az );
+
+ if ( CurrentClient )
+ fprintf( CurrentClient, "\033%s\033", errmsg );
+}
+
+void log_error( const char *fmt, ... )
+{
+ char errmsg[ 1024 ];
+ va_list az;
+
+ va_start( az, fmt );
+ vsnprintf( errmsg, sizeof( errmsg ) - 1, fmt, az );
+ errmsg[ sizeof( errmsg ) - 1 ] = '\0';
+ va_end( az );
+
+ openlog( "ksysguardd", LOG_PID, LOG_DAEMON );
+ syslog( LOG_ERR, "%s", errmsg );
+ closelog();
+}
+
+void initCommand( void )
+{
+ CommandList = new_ctnr();
+ sigemptyset( &SignalSet );
+ sigaddset( &SignalSet, SIGALRM );
+
+ registerCommand( "monitors", printMonitors );
+ registerCommand( "test", printTest );
+
+ if ( RunAsDaemon == 0 )
+ registerCommand( "quit", exQuit );
+}
+
+void exitCommand( void )
+{
+ destr_ctnr( CommandList, command_cleanup );
+}
+
+void registerCommand( const char* command, cmdExecutor ex )
+{
+ Command* cmd = (Command*)malloc( sizeof( Command ) );
+ cmd->command = (char*)malloc( strlen( command ) + 1 );
+ strcpy( cmd->command, command );
+ cmd->type = 0;
+ cmd->ex = ex;
+ cmd->isMonitor = 0;
+ push_ctnr( CommandList, cmd );
+ ReconfigureFlag = 1;
+}
+
+void removeCommand( const char* command )
+{
+ Command* cmd;
+
+ for ( cmd = first_ctnr( CommandList ); cmd; cmd = next_ctnr( CommandList ) ) {
+ if ( strcmp( cmd->command, command ) == 0 ) {
+ remove_ctnr( CommandList );
+ if ( cmd->command )
+ free( cmd->command );
+ if ( cmd->type )
+ free( cmd->type );
+ free( cmd );
+ }
+ }
+
+ ReconfigureFlag = 1;
+}
+
+void registerMonitor( const char* command, const char* type, cmdExecutor ex,
+ cmdExecutor iq, struct SensorModul* sm )
+{
+ /* Monitors are similar to regular commands except that every monitor
+ * registers two commands. The first is the value request command and
+ * the second is the info request command. The info request command is
+ * identical to the value request but with an '?' appended. The value
+ * command prints a single value. The info request command prints
+ * a description of the monitor, the mininum value, the maximum value
+ * and the unit. */
+ Command* cmd = (Command*)malloc( sizeof( Command ) );
+ cmd->command = (char*)malloc( strlen( command ) + 1 );
+ strcpy( cmd->command, command );
+ cmd->ex = ex;
+ cmd->type = (char*)malloc( strlen( type ) + 1 );
+ strcpy( cmd->type, type );
+ cmd->isMonitor = 1;
+ cmd->sm = sm;
+ push_ctnr( CommandList, cmd );
+
+ cmd = (Command*)malloc( sizeof( Command ) );
+ cmd->command = (char*)malloc( strlen( command ) + 2 );
+ strcpy( cmd->command, command );
+ cmd->command[ strlen( command ) ] = '?';
+ cmd->command[ strlen( command ) + 1 ] = '\0';
+ cmd->ex = iq;
+ cmd->isMonitor = 0;
+ cmd->sm = sm;
+ cmd->type = 0;
+ push_ctnr( CommandList, cmd );
+}
+
+void removeMonitor( const char* command )
+{
+ char* buf;
+
+ removeCommand( command );
+ buf = (char*)malloc( strlen( command ) + 2 );
+ strcpy( buf, command );
+ strcat( buf, "?" );
+ removeCommand( buf );
+ free( buf );
+}
+
+void executeCommand( const char* command )
+{
+ Command* cmd;
+ char tokenFormat[ 64 ];
+ char token[ 64 ];
+
+ sprintf( tokenFormat, "%%%ds", (int)sizeof( token ) - 1 );
+ sscanf( command, tokenFormat, token );
+
+ for ( cmd = first_ctnr( CommandList ); cmd; cmd = next_ctnr( CommandList ) ) {
+ if ( strcmp( cmd->command, token ) == 0 ) {
+ if ( cmd->isMonitor ) {
+ if ( ( time( NULL ) - cmd->sm->time ) >= UPDATEINTERVAL ) {
+ cmd->sm->time = time( NULL );
+
+ if ( cmd->sm->updateCommand != NULL )
+ cmd->sm->updateCommand();
+ }
+ }
+
+ (*(cmd->ex))( command );
+
+ if ( ReconfigureFlag ) {
+ ReconfigureFlag = 0;
+ print_error( "RECONFIGURE\n" );
+ }
+
+ fflush( CurrentClient );
+ return;
+ }
+ }
+
+ if ( CurrentClient ) {
+ fprintf( CurrentClient, "UNKNOWN COMMAND\n" );
+ fflush( CurrentClient );
+ }
+}
+
+void printMonitors( const char *c )
+{
+ Command* cmd;
+ ReconfigureFlag = 0;
+
+ (void)c;
+
+ for ( cmd = first_ctnr( CommandList ); cmd; cmd = next_ctnr( CommandList ) ) {
+ if ( cmd->isMonitor )
+ fprintf(CurrentClient, "%s\t%s\n", cmd->command, cmd->type);
+ }
+
+ fflush( CurrentClient );
+}
+
+void printTest( const char* c )
+{
+ Command* cmd;
+
+ for ( cmd = first_ctnr( CommandList ); cmd; cmd = next_ctnr( CommandList ) ) {
+ if ( strcmp( cmd->command, c + strlen( "test " ) ) == 0 ) {
+ fprintf( CurrentClient, "1\n" );
+ fflush( CurrentClient );
+ return;
+ }
+ }
+
+ fprintf( CurrentClient, "0\n" );
+ fflush( CurrentClient );
+}
+
+void exQuit( const char* cmd )
+{
+ (void)cmd;
+
+ QuitApp = 1;
+}
diff --git a/ksysguard/ksysguardd/Command.h b/ksysguard/ksysguardd/Command.h
new file mode 100644
index 000000000..d3645d905
--- /dev/null
+++ b/ksysguard/ksysguardd/Command.h
@@ -0,0 +1,103 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include "ksysguardd.h"
+
+#ifndef KSG_COMMAND_H
+#define KSG_COMMAND_H
+
+typedef void (*cmdExecutor)(const char*);
+
+/**
+ Set this flag to '1' to request a rescan of the available sensors
+ in the front end.
+ */
+extern int ReconfigureFlag;
+
+/**
+ Has nearly the same meaning like the above flag ;)
+ */
+extern int CheckSetupFlag;
+
+/**
+ Delivers the error message to the front end.
+ */
+void print_error( const char*, ... )
+#ifdef __GNUC__
+ __attribute__ ( ( format ( printf, 1, 2 ) ) )
+#endif
+ ;
+
+/**
+ Writes the error message to the syslog daemon.
+ */
+void log_error( const char*, ... )
+ #ifdef __GNUC__
+ __attribute__ ( ( format ( printf, 1, 2 ) ) )
+#endif
+ ;
+
+
+
+/**
+ Use this function to register a command with the name
+ @ref command and the function pointer @ref ex.
+ */
+void registerCommand( const char* command, cmdExecutor ex );
+
+/**
+ Use this function to remove a command with the name
+ @ref command.
+ */
+void removeCommand( const char* command );
+
+/**
+ Use this function to add a new montior with the name @ref monitor
+ from the type @ref type.
+ @ref ex is a pointer to the function that is called to get a value
+ and @ref iq is a pointer to the function that returns informations
+ about this monitor.
+ @ref sm is a parameter to the sensor modul object that is passed by
+ the initXXX method.
+ */
+void registerMonitor( const char* monitor, const char* type, cmdExecutor ex,
+ cmdExecutor iq, struct SensorModul* sm );
+
+/**
+ Use this function to add the montior with the name @ref monitor.
+ */
+void removeMonitor( const char* monitor );
+
+
+/**
+ Internal usage.
+ */
+void executeCommand( const char* command );
+
+void initCommand( void );
+void exitCommand( void );
+
+void printMonitors( const char* cmd );
+void printTest( const char* cmd );
+
+void exQuit( const char* cmd );
+
+#endif
diff --git a/ksysguard/ksysguardd/FreeBSD/CPU.c b/ksysguard/ksysguardd/FreeBSD/CPU.c
new file mode 100644
index 000000000..90d0c4721
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/CPU.c
@@ -0,0 +1,263 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <osreldate.h>
+
+#include <sys/types.h>
+#if defined(__DragonFly__)
+#include <sys/param.h>
+#include <kinfo.h>
+#elif __FreeBSD_version < 500101
+ #include <sys/dkstat.h>
+#else
+ #include <sys/resource.h>
+#endif
+#include <sys/sysctl.h>
+
+#include <devstat.h>
+#include <fcntl.h>
+#include <nlist.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "CPU.h"
+#include "Command.h"
+#include "ksysguardd.h"
+
+#if defined(__DragonFly__)
+static void cputime_percentages(int[4], struct kinfo_cputime *,
+ struct kinfo_cputime *);
+static struct kinfo_cputime cp_time, cp_old;
+
+#define CPUSTATES 4
+#define CP_USER 0
+#define CP_NICE 1
+#define CP_SYS 2
+#define CP_IDLE 3
+
+#else
+long percentages(int cnt, int *out, long *new, long *old, long *diffs);
+
+unsigned long cp_time_offset;
+
+long cp_time[CPUSTATES];
+long cp_old[CPUSTATES];
+long cp_diff[CPUSTATES];
+#endif
+
+int cpu_states[CPUSTATES];
+
+void
+initCpuInfo(struct SensorModul* sm)
+{
+ /* Total CPU load */
+ registerMonitor("cpu/user", "integer", printCPUUser,
+ printCPUUserInfo, sm);
+ registerMonitor("cpu/nice", "integer", printCPUNice,
+ printCPUNiceInfo, sm);
+ registerMonitor("cpu/sys", "integer", printCPUSys,
+ printCPUSysInfo, sm);
+ registerMonitor("cpu/idle", "integer", printCPUIdle,
+ printCPUIdleInfo, sm);
+
+ updateCpuInfo();
+}
+
+void
+exitCpuInfo(void)
+{
+}
+
+int
+updateCpuInfo(void)
+{
+#if defined(__DragonFly__)
+ kinfo_get_sched_cputime(&cp_time);
+ cputime_percentages(cpu_states, &cp_time, &cp_old);
+#else
+ size_t len = sizeof(cp_time);
+ sysctlbyname("kern.cp_time", &cp_time, &len, NULL, 0);
+ percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
+#endif
+ return (0);
+}
+
+void
+printCPUUser(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CP_USER]/10);
+}
+
+void
+printCPUUserInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU User Load\t0\t100\t%%\n");
+}
+
+void
+printCPUNice(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CP_NICE]/10);
+}
+
+void
+printCPUNiceInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU Nice Load\t0\t100\t%%\n");
+}
+
+void
+printCPUSys(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CP_SYS]/10);
+}
+
+void
+printCPUSysInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU System Load\t0\t100\t%%\n");
+}
+
+void
+printCPUIdle(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CP_IDLE]/10);
+}
+
+void
+printCPUIdleInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU Idle Load\t0\t100\t%%\n");
+}
+
+
+/* The part ripped from top... */
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ */
+
+/*
+ * percentages(cnt, out, new, old, diffs) - calculate percentage change
+ * between array "old" and "new", putting the percentages i "out".
+ * "cnt" is size of each array and "diffs" is used for scratch space.
+ * The array "old" is updated on each call.
+ * The routine assumes modulo arithmetic. This function is especially
+ * useful on BSD mchines for calculating cpu state percentages.
+ */
+#if defined(__DragonFly__)
+static void
+cputime_percentages(int out[4], struct kinfo_cputime *new, struct kinfo_cputime * old)
+{
+ struct kinfo_cputime diffs;
+ int i;
+ uint64_t total_change, half_total;
+
+ /* initialization */
+ total_change = 0;
+
+ diffs.cp_user = new->cp_user - old->cp_user;
+ diffs.cp_nice = new->cp_nice - old->cp_nice;
+ diffs.cp_sys = new->cp_sys - old->cp_sys;
+ diffs.cp_intr = new->cp_intr - old->cp_intr;
+ diffs.cp_idle = new->cp_idle - old->cp_idle;
+ total_change = diffs.cp_user + diffs.cp_nice + diffs.cp_sys +
+ diffs.cp_intr + diffs.cp_idle;
+ old->cp_user = new->cp_user;
+ old->cp_nice = new->cp_nice;
+ old->cp_sys = new->cp_sys;
+ old->cp_intr = new->cp_intr;
+ old->cp_idle = new->cp_idle;
+
+ /* avoid divide by zero potential */
+ if (total_change == 0)
+ total_change = 1;
+
+ /* calculate percentages based on overall change, rounding up */
+ half_total = total_change >> 1;
+
+ out[0] = ((diffs.cp_user * 1000LL + half_total) / total_change);
+ out[1] = ((diffs.cp_nice * 1000LL + half_total) / total_change);
+ out[2] = (((diffs.cp_sys + diffs.cp_intr) * 1000LL + half_total) / total_change);
+ out[4] = ((diffs.cp_idle * 1000LL + half_total) / total_change);
+}
+
+#else
+long percentages(cnt, out, new, old, diffs)
+
+int cnt;
+int *out;
+register long *new;
+register long *old;
+long *diffs;
+
+{
+ register int i;
+ register long change;
+ register long total_change;
+ register long *dp;
+ long half_total;
+
+ /* initialization */
+ total_change = 0;
+ dp = diffs;
+
+ /* calculate changes for each state and the overall change */
+ for (i = 0; i < cnt; i++)
+ {
+ if ((change = *new - *old) < 0)
+ {
+ /* this only happens when the counter wraps */
+ change = (int)
+ ((unsigned long)*new-(unsigned long)*old);
+ }
+ total_change += (*dp++ = change);
+ *old++ = *new++;
+ }
+
+ /* avoid divide by zero potential */
+ if (total_change == 0)
+ {
+ total_change = 1;
+ }
+
+ /* calculate percentages based on overall change, rounding up */
+ half_total = total_change / 2l;
+
+ /* Do not divide by 0. Causes Floating point exception */
+ if(total_change) {
+ for (i = 0; i < cnt; i++)
+ {
+ *out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
+ }
+ }
+
+ /* return the total in case the caller wants to use it */
+ return(total_change);
+}
+#endif
diff --git a/ksysguard/ksysguardd/FreeBSD/CPU.h b/ksysguard/ksysguardd/FreeBSD/CPU.h
new file mode 100644
index 000000000..c35932ac8
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/CPU.h
@@ -0,0 +1,49 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _cpuinfo_h_
+#define _cpuinfo_h_
+
+struct SensorModul;
+
+void initCpuInfo(struct SensorModul* sm);
+void exitCpuInfo(void);
+
+int updateCpuInfo(void);
+
+void printCPUUser(const char* cmd);
+void printCPUUserInfo(const char* cmd);
+void printCPUNice(const char* cmd);
+void printCPUNiceInfo(const char* cmd);
+void printCPUSys(const char* cmd);
+void printCPUSysInfo(const char* cmd);
+void printCPUIdle(const char* cmd);
+void printCPUIdleInfo(const char* cmd);
+void printCPUxUser(const char* cmd);
+void printCPUxUserInfo(const char* cmd);
+void printCPUxNice(const char* cmd);
+void printCPUxNiceInfo(const char* cmd);
+void printCPUxSys(const char* cmd);
+void printCPUxSysInfo(const char* cmd);
+void printCPUxIdle(const char* cmd);
+void printCPUxIdleInfo(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/FreeBSD/Makefile.am b/ksysguard/ksysguardd/FreeBSD/Makefile.am
new file mode 100644
index 000000000..29860a407
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/Makefile.am
@@ -0,0 +1,8 @@
+#
+#
+
+INCLUDES = -I$(srcdir)/../../CContLib -I$(srcdir)/..
+
+noinst_LIBRARIES = libksysguardd.a
+libksysguardd_a_SOURCES = CPU.c Memory.c ProcessList.c apm.c diskstat.c \
+ loadavg.c logfile.c netdev.c
diff --git a/ksysguard/ksysguardd/FreeBSD/Memory.c b/ksysguard/ksysguardd/FreeBSD/Memory.c
new file mode 100644
index 000000000..9e3db646c
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/Memory.c
@@ -0,0 +1,209 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999-2000 Hans Petter Bieker <bieker@kde.org>
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/vmmeter.h>
+
+#include <vm/vm_param.h>
+
+#include <fcntl.h>
+#include <kvm.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "Command.h"
+#include "Memory.h"
+#include "ksysguardd.h"
+
+static size_t Total = 0;
+static size_t MFree = 0;
+static size_t Used = 0;
+static size_t Buffers = 0;
+static size_t Cached = 0;
+static size_t Application = 0;
+static size_t STotal = 0;
+static size_t SFree = 0;
+static size_t SUsed = 0;
+static kvm_t *kd;
+
+void
+initMemory(struct SensorModul* sm)
+{
+ char *nlistf = NULL;
+ char *memf = NULL;
+ char buf[_POSIX2_LINE_MAX];
+
+ if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) {
+ log_error("kvm_openfiles()");
+ return;
+ }
+
+ registerMonitor("mem/physical/free", "integer", printMFree, printMFreeInfo, sm);
+ registerMonitor("mem/physical/used", "integer", printUsed, printUsedInfo, sm);
+ registerMonitor("mem/physical/buf", "integer", printBuffers, printBuffersInfo, sm);
+ registerMonitor("mem/physical/cached", "integer", printCached, printCachedInfo, sm);
+ registerMonitor("mem/physical/application", "integer", printApplication, printApplicationInfo, sm);
+ registerMonitor("mem/swap/free", "integer", printSwapFree, printSwapFreeInfo, sm);
+ registerMonitor("mem/swap/used", "integer", printSwapUsed, printSwapUsedInfo, sm);
+}
+
+void
+exitMemory(void)
+{
+ kvm_close(kd);
+}
+
+int
+updateMemory(void)
+{
+ size_t len;
+ FILE *file;
+ char buf[256];
+ struct kvm_swap kswap[16];
+ int i, swap_count, hlen, pagesize = getpagesize();
+ long blocksize;
+
+ len = sizeof (Total);
+ sysctlbyname("hw.physmem", &Total, &len, NULL, 0);
+ Total /= 1024;
+
+ /* Borrowed from pstat */
+ swap_count = kvm_getswapinfo(kd, kswap, 16, SWIF_DEV_PREFIX);
+ getbsize(&hlen, &blocksize);
+
+#define CONVERT(v) ((int)((quad_t)(v) * pagesize / blocksize))
+
+ if (swap_count > 0) {
+ STotal = CONVERT(kswap[0].ksw_total);
+ SUsed = CONVERT(kswap[0].ksw_used);
+ SFree = CONVERT(kswap[0].ksw_total - kswap[0].ksw_used);
+ }
+
+ len = sizeof (Buffers);
+ if ((sysctlbyname("vfs.bufspace", &Buffers, &len, NULL, 0) == -1) || !len)
+ Buffers = 0; /* Doesn't work under FreeBSD v2.2.x */
+ Buffers /= 1024;
+
+ len = sizeof (Cached);
+ if ((sysctlbyname("vm.stats.vm.v_cache_count", &Cached, &len, NULL, 0) == -1) || !len)
+ Cached = 0; /* Doesn't work under FreeBSD v2.2.x */
+ Cached *= pagesize / 1024;
+
+ len = sizeof (MFree);
+ if ((sysctlbyname("vm.stats.vm.v_free_count", &MFree, &len, NULL, 0) == -1) || !len)
+ MFree = 0; /* Doesn't work under FreeBSD v2.2.x */
+ MFree *= pagesize / 1024;
+
+ Used = Total - MFree;
+ Application = Used - Buffers - Cached;
+
+ return 0;
+}
+
+void
+printMFree(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", MFree);
+}
+
+void
+printMFreeInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Free Memory\t0\t%d\tKB\n", Total);
+}
+
+void
+printUsed(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", Used);
+}
+
+void
+printUsedInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Used Memory\t0\t%d\tKB\n", Total);
+}
+
+void
+printBuffers(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", Buffers);
+}
+
+void
+printBuffersInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Buffer Memory\t0\t%d\tKB\n", Total);
+}
+
+void
+printCached(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", Cached);
+}
+
+void
+printCachedInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Cached Memory\t0\t%d\tKB\n", Total);
+}
+
+void
+printApplication(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", Application);
+}
+
+void
+printApplicationInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Application Memory\t0\t%ld\tKB\n", Total);
+}
+
+void
+printSwapUsed(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", SUsed);
+}
+
+void
+printSwapUsedInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Used Swap Memory\t0\t%d\tKB\n", STotal);
+}
+
+void
+printSwapFree(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", SFree);
+}
+
+void
+printSwapFreeInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Free Swap Memory\t0\t%d\tKB\n", STotal);
+}
diff --git a/ksysguard/ksysguardd/FreeBSD/Memory.h b/ksysguard/ksysguardd/FreeBSD/Memory.h
new file mode 100644
index 000000000..66b521617
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/Memory.h
@@ -0,0 +1,45 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _memory_h_
+#define _memory_h_
+
+void initMemory(struct SensorModul* sm);
+void exitMemory(void);
+
+int updateMemory(void);
+
+void printMFree(const char* cmd);
+void printMFreeInfo(const char* cmd);
+void printUsed(const char* cmd);
+void printUsedInfo(const char* cmd);
+void printBuffers(const char* cmd);
+void printBuffersInfo(const char* cmd);
+void printCached(const char* cmd);
+void printCachedInfo(const char* cmd);
+void printApplication(const char* cmd);
+void printApplicationInfo(const char* cmd);
+void printSwapUsed(const char* cmd);
+void printSwapUsedInfo(const char* cmd);
+void printSwapFree(const char* cmd);
+void printSwapFreeInfo(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/FreeBSD/ProcessList.c b/ksysguard/ksysguardd/FreeBSD/ProcessList.c
new file mode 100644
index 000000000..f8d2c3ba6
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/ProcessList.c
@@ -0,0 +1,556 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999-2000 Hans Petter Bieker<bieker@kde.org>
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+#if defined(__DragonFly__)
+#include <sys/user.h>
+#include <sys/resourcevar.h>
+#endif
+
+#if __FreeBSD_version > 500015
+#include <sys/priority.h>
+#endif
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/user.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "../../gui/SignalIDs.h"
+#include "Command.h"
+#include "ProcessList.h"
+#include "ccont.h"
+#include "ksysguardd.h"
+
+CONTAINER ProcessList = 0;
+
+int fscale;
+
+#define BUFSIZE 1024
+
+typedef struct
+{
+ /* This flag is set for all found processes at the beginning of the
+ * process list update. Processes that do not have this flag set will
+ * be assumed dead and removed from the list. The flag is cleared after
+ * each list update. */
+ int alive;
+
+ /* the process ID */
+ pid_t pid;
+
+ /* the parent process ID */
+ pid_t ppid;
+
+ /* the real user ID */
+ uid_t uid;
+
+ /* the real group ID */
+ gid_t gid;
+
+ /* a character description of the process status */
+ char status[16];
+
+ /* the number of the tty the process owns */
+ int ttyNo;
+
+ /*
+ * The nice level. The range should be -20 to 20. I'm not sure
+ * whether this is true for all platforms.
+ */
+ int niceLevel;
+
+ /*
+ * The scheduling priority.
+ */
+ int priority;
+
+ /*
+ * The total amount of memory the process uses. This includes shared and
+ * swapped memory.
+ */
+ unsigned int vmSize;
+
+ /*
+ * The amount of physical memory the process currently uses.
+ */
+ unsigned int vmRss;
+
+ /*
+ * The amount of memory (shared/swapped/etc) the process shares with
+ * other processes.
+ */
+ unsigned int vmLib;
+
+ /*
+ * The number of 1/100 of a second the process has spend in user space.
+ * If a machine has an uptime of 1 1/2 years or longer this is not a
+ * good idea. I never thought that the stability of UNIX could get me
+ * into trouble! ;)
+ */
+#if !defined(__DragonFly__)
+ unsigned int userTime;
+#else
+ long userTime;
+#endif
+
+ /*
+ * The number of 1/100 of a second the process has spend in system space.
+ * If a machine has an uptime of 1 1/2 years or longer this is not a
+ * good idea. I never thought that the stability of UNIX could get me
+ * into trouble! ;)
+ */
+ unsigned int sysTime;
+
+ /* system time as multime of 100ms */
+ int centStamp;
+
+ /* the current CPU load (in %) from user space */
+ double userLoad;
+
+ /* the current CPU load (in %) from system space */
+ double sysLoad;
+
+ /* the name of the process */
+ char name[64];
+
+ /* the command used to start the process */
+ char cmdline[256];
+
+ /* the login name of the user that owns this process */
+ char userName[32];
+} ProcessInfo;
+
+static unsigned ProcessCount;
+
+static int
+processCmp(void* p1, void* p2)
+{
+ return (((ProcessInfo*) p1)->pid - ((ProcessInfo*) p2)->pid);
+}
+
+static ProcessInfo*
+findProcessInList(int pid)
+{
+ ProcessInfo key;
+ long index;
+
+ key.pid = pid;
+ if ((index = search_ctnr(ProcessList, processCmp, &key)) < 0)
+ return (0);
+
+ return (get_ctnr(ProcessList, index));
+}
+
+static int
+updateProcess(int pid)
+{
+ static char *statuses[] = { "idle","run","sleep","stop","zombie" };
+
+ ProcessInfo* ps;
+ struct passwd* pwent;
+ int mib[4];
+ struct kinfo_proc p;
+ struct rusage pru;
+ size_t len;
+ size_t buflen = 256;
+ char buf[256];
+
+ if ((ps = findProcessInList(pid)) == 0)
+ {
+ ps = (ProcessInfo*) malloc(sizeof(ProcessInfo));
+ ps->pid = pid;
+ ps->centStamp = 0;
+ push_ctnr(ProcessList, ps);
+ bsort_ctnr(ProcessList, processCmp);
+ }
+
+ ps->alive = 1;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = pid;
+
+ len = sizeof (p);
+ if (sysctl(mib, 4, &p, &len, NULL, 0) == -1 || !len)
+ return -1;
+
+#if __FreeBSD_version >= 500015
+ ps->pid = p.ki_pid;
+ ps->ppid = p.ki_ppid;
+ ps->uid = p.ki_uid;
+ ps->gid = p.ki_pgid;
+ ps->priority = p.ki_pri.pri_user;
+ ps->niceLevel = p.ki_nice;
+#elif defined(__DragonFly__) && __DragonFly_version >= 190000
+ ps->pid = p.kp_pid;
+ ps->ppid = p.kp_ppid;
+ ps->uid = p.kp_uid;
+ ps->gid = p.kp_pgid;
+ ps->priority = p.kp_lwp.kl_tdprio;
+#else
+ ps->pid = p.kp_proc.p_pid;
+ ps->ppid = p.kp_eproc.e_ppid;
+ ps->uid = p.kp_eproc.e_ucred.cr_uid;
+ ps->gid = p.kp_eproc.e_pgid;
+#if defined(__DragonFly__)
+ ps->priority = p.kp_thread.td_pri;
+#else
+ ps->priority = p.kp_proc.p_priority;
+#endif
+ ps->niceLevel = p.kp_proc.p_nice;
+#endif
+
+ /* this isn't usertime -- it's total time (??) */
+#if __FreeBSD_version >= 500015
+ ps->userTime = p.ki_runtime / 10000;
+#elif defined(__DragonFly__)
+#if __DragonFly_version >= 190000
+ if (!getrusage(p.kp_pid, &pru))
+#else
+ if (!getrusage(p.kp_proc.p_pid, &pru))
+#endif
+ {
+ errx(1, "failed to get rusage info");
+ }
+ ps->userTime = pru.ru_utime.tv_usec / 1000; /*p_runtime / 1000*/
+#elif __FreeBSD_version >= 300000
+ ps->userTime = p.kp_proc.p_runtime / 10000;
+#else
+ ps->userTime = p.kp_proc.p_rtime.tv_sec*100+p.kp_proc.p_rtime.tv_usec/100;
+#endif
+ ps->sysTime = 0;
+ ps->sysLoad = 0;
+
+ /* memory, process name, process uid */
+ /* find out user name with process uid */
+ pwent = getpwuid(ps->uid);
+ strncpy(ps->userName,pwent&&pwent->pw_name? pwent->pw_name:"????",sizeof(ps->userName));
+ ps->userName[sizeof(ps->userName)-1]='\0';
+
+ if (fscale == 0)
+ ps->userLoad = 0;
+ else
+#if __FreeBSD_version >= 500015
+ ps->userLoad = 100.0 * (double) p.ki_pctcpu / fscale;
+ ps->vmSize = p.ki_size;
+ ps->vmRss = p.ki_rssize * getpagesize();
+ strlcpy(ps->name,p.ki_comm? p.ki_comm:"????",sizeof(ps->name));
+ strcpy(ps->status,(p.ki_stat>=1)&&(p.ki_stat<=5)? statuses[p.ki_stat-1]:"????");
+#elif defined (__DragonFly__) && __DragonFly_version >= 190000
+ ps->userLoad = 100.0 * (double) p.kp_lwp.kl_pctcpu / fscale;
+ ps->vmSize = p.kp_vm_map_size;
+ ps->vmRss = p.kp_vm_rssize * getpagesize();
+ strlcpy(ps->name,p.kp_comm ? p.kp_comm : "????",
+ sizeof(ps->name));
+ strcpy(ps->status,(p.kp_stat>=1)&&(p.kp_stat<=5)? statuses[p.kp_stat-1]:"????");
+#else
+ ps->userLoad = 100.0 * (double) p.kp_proc.p_pctcpu / fscale;
+ ps->vmSize = p.kp_eproc.e_vm.vm_map.size;
+ ps->vmRss = p.kp_eproc.e_vm.vm_rssize * getpagesize();
+#if defined (__DragonFly__)
+ strlcpy(ps->name,p.kp_thread.td_comm ? p.kp_thread.td_comm : "????",
+ sizeof(ps->name));
+#else
+ strlcpy(ps->name,p.kp_proc.p_comm ? p.kp_proc.p_comm : "????", sizeof(ps->name));
+ strcpy(ps->status,(p.kp_proc.p_stat>=1)&&(p.kp_proc.p_stat<=5)? statuses[p.kp_proc.p_stat-1]:"????");
+#endif
+#endif
+
+ /* process command line */
+ /* do a sysctl to get the command line args. */
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_ARGS;
+ mib[3] = pid;
+
+ if ((sysctl(mib, 4, buf, &buflen, 0, 0) == -1) || !buflen)
+ strcpy(ps->cmdline, "????");
+ else
+ strncpy(ps->cmdline, buf, buflen);
+
+ return (0);
+}
+
+static void
+cleanupProcessList(void)
+{
+ ProcessInfo* ps;
+
+ ProcessCount = 0;
+ /* All processes that do not have the active flag set are assumed dead
+ * and will be removed from the list. The alive flag is cleared. */
+ for (ps = first_ctnr(ProcessList); ps; ps = next_ctnr(ProcessList))
+ {
+ if (ps->alive)
+ {
+ /* Process is still alive. Just clear flag. */
+ ps->alive = 0;
+ ProcessCount++;
+ }
+ else
+ {
+ /* Process has probably died. We remove it from the list and
+ * destruct the data structure. i needs to be decremented so
+ * that after i++ the next list element will be inspected. */
+ free(remove_ctnr(ProcessList));
+ }
+ }
+}
+
+/*
+================================ public part ==================================
+*/
+
+void
+initProcessList(struct SensorModul* sm)
+{
+ size_t fscalelen;
+ ProcessList = new_ctnr();
+
+ registerMonitor("ps", "table", printProcessList, printProcessListInfo, sm);
+ registerMonitor("pscount", "integer", printProcessCount, printProcessCountInfo, sm);
+
+ if (!RunAsDaemon)
+ {
+ registerCommand("kill", killProcess);
+ registerCommand("setpriority", setPriority);
+ }
+
+ fscalelen = sizeof(fscale);
+ if (sysctlbyname("kern.fscale", &fscale, &fscalelen, NULL, 0) == -1)
+ fscale = 0;
+
+ updateProcessList();
+}
+
+void
+exitProcessList(void)
+{
+ removeMonitor("ps");
+ removeMonitor("pscount");
+
+ if (ProcessList)
+ free (ProcessList);
+}
+
+int
+updateProcessList(void)
+{
+ int mib[3];
+ size_t len;
+ size_t num;
+ struct kinfo_proc *p;
+
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_ALL;
+ sysctl(mib, 3, NULL, &len, NULL, 0);
+ p = malloc(len);
+ sysctl(mib, 3, p, &len, NULL, 0);
+
+ for (num = 0; num < len / sizeof(struct kinfo_proc); num++)
+#if __FreeBSD_version >= 500015
+ updateProcess(p[num].ki_pid);
+#elif __DragonFly_version >= 190000
+ /* Skip kernel threads with pid -1. Swapper with pid 0 also
+ * causing problems is skipped in printProcessList() as 'kernel'
+ * entry. */
+ if (p[num].kp_pid >= 0)
+ updateProcess(p[num].kp_pid);
+#elif defined(__DragonFly__)
+ if (p[num].kp_proc.p_pid >= 0)
+ updateProcess(p[num].kp_proc.p_pid);
+#else
+ updateProcess(p[num].kp_proc.p_pid);
+#endif
+ free(p);
+ cleanupProcessList();
+
+ return (0);
+}
+
+void
+printProcessListInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Name\tPID\tPPID\tUID\tGID\tStatus\tUser%%\tSystem%%\tNice\tVmSize\tVmRss\tLogin\tCommand\n");
+ fprintf(CurrentClient, "s\td\td\td\td\tS\tf\tf\td\tD\tD\ts\ts\n");
+}
+
+void
+printProcessList(const char* cmd)
+{
+ ProcessInfo* ps;
+
+ ps = first_ctnr(ProcessList); /* skip 'kernel' entry */
+ for (ps = next_ctnr(ProcessList); ps; ps = next_ctnr(ProcessList))
+ {
+ fprintf(CurrentClient, "%s\t%ld\t%ld\t%ld\t%ld\t%s\t%.2f\t%.2f\t%d\t%d\t%d\t%s\t%s\n",
+ ps->name, (long)ps->pid, (long)ps->ppid,
+ (long)ps->uid, (long)ps->gid, ps->status,
+ ps->userLoad, ps->sysLoad, ps->niceLevel,
+ ps->vmSize / 1024, ps->vmRss / 1024, ps->userName, ps->cmdline);
+ }
+}
+
+void
+printProcessCount(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", ProcessCount);
+}
+
+void
+printProcessCountInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Number of Processes\t1\t65535\t\n");
+}
+
+void
+killProcess(const char* cmd)
+{
+ int sig, pid;
+
+ sscanf(cmd, "%*s %d %d", &pid, &sig);
+ switch(sig)
+ {
+ case MENU_ID_SIGABRT:
+ sig = SIGABRT;
+ break;
+ case MENU_ID_SIGALRM:
+ sig = SIGALRM;
+ break;
+ case MENU_ID_SIGCHLD:
+ sig = SIGCHLD;
+ break;
+ case MENU_ID_SIGCONT:
+ sig = SIGCONT;
+ break;
+ case MENU_ID_SIGFPE:
+ sig = SIGFPE;
+ break;
+ case MENU_ID_SIGHUP:
+ sig = SIGHUP;
+ break;
+ case MENU_ID_SIGILL:
+ sig = SIGILL;
+ break;
+ case MENU_ID_SIGINT:
+ sig = SIGINT;
+ break;
+ case MENU_ID_SIGKILL:
+ sig = SIGKILL;
+ break;
+ case MENU_ID_SIGPIPE:
+ sig = SIGPIPE;
+ break;
+ case MENU_ID_SIGQUIT:
+ sig = SIGQUIT;
+ break;
+ case MENU_ID_SIGSEGV:
+ sig = SIGSEGV;
+ break;
+ case MENU_ID_SIGSTOP:
+ sig = SIGSTOP;
+ break;
+ case MENU_ID_SIGTERM:
+ sig = SIGTERM;
+ break;
+ case MENU_ID_SIGTSTP:
+ sig = SIGTSTP;
+ break;
+ case MENU_ID_SIGTTIN:
+ sig = SIGTTIN;
+ break;
+ case MENU_ID_SIGTTOU:
+ sig = SIGTTOU;
+ break;
+ case MENU_ID_SIGUSR1:
+ sig = SIGUSR1;
+ break;
+ case MENU_ID_SIGUSR2:
+ sig = SIGUSR2;
+ break;
+ }
+ if (kill((pid_t) pid, sig))
+ {
+ switch(errno)
+ {
+ case EINVAL:
+ fprintf(CurrentClient, "4\t%d\n", pid);
+ break;
+ case ESRCH:
+ fprintf(CurrentClient, "3\t%d\n", pid);
+ break;
+ case EPERM:
+ fprintf(CurrentClient, "2\t%d\n", pid);
+ break;
+ default:
+ fprintf(CurrentClient, "1\t%d\n", pid); /* unknown error */
+ break;
+ }
+
+ }
+ else
+ fprintf(CurrentClient, "0\t%d\n", pid);
+}
+
+void
+setPriority(const char* cmd)
+{
+ int pid, prio;
+
+ sscanf(cmd, "%*s %d %d", &pid, &prio);
+ if (setpriority(PRIO_PROCESS, pid, prio))
+ {
+ switch(errno)
+ {
+ case EINVAL:
+ fprintf(CurrentClient, "4\n");
+ break;
+ case ESRCH:
+ fprintf(CurrentClient, "3\n");
+ break;
+ case EPERM:
+ case EACCES:
+ fprintf(CurrentClient, "2\n");
+ break;
+ default:
+ fprintf(CurrentClient, "1\n"); /* unknown error */
+ break;
+ }
+ }
+ else
+ fprintf(CurrentClient, "0\n");
+}
diff --git a/ksysguard/ksysguardd/FreeBSD/ProcessList.h b/ksysguard/ksysguardd/FreeBSD/ProcessList.h
new file mode 100644
index 000000000..925c55f5a
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/ProcessList.h
@@ -0,0 +1,38 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _process_list_h_
+#define _process_list_h_
+
+void initProcessList(struct SensorModul* sm);
+void exitProcessList(void);
+
+int updateProcessList(void);
+
+void printProcessList(const char*);
+void printProcessListInfo(const char*);
+void printProcessCount(const char* cmd);
+void printProcessCountInfo(const char* cmd);
+
+void killProcess(const char* cmd);
+void setPriority(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/FreeBSD/apm.c b/ksysguard/ksysguardd/FreeBSD/apm.c
new file mode 100644
index 000000000..95efec792
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/apm.c
@@ -0,0 +1,102 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifdef __i386__
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <machine/apm_bios.h>
+#include <stdio.h>
+
+#include "Command.h"
+#include "apm.h"
+#include "ksysguardd.h"
+
+static int ApmFD, BattFill, BattTime;
+
+#define APMDEV "/dev/apm"
+
+/*
+================================ public part =================================
+*/
+
+void
+initApm(struct SensorModul* sm)
+{
+ if ((ApmFD = open(APMDEV, O_RDONLY)) < 0)
+ return;
+
+ if (updateApm() < 0)
+ return;
+
+ registerMonitor("apm/batterycharge", "integer", printApmBatFill,
+ printApmBatFillInfo, sm);
+ registerMonitor("apm/remainingtime", "integer", printApmBatTime,
+ printApmBatTimeInfo, sm);
+}
+
+void
+exitApm(void)
+{
+ removeMonitor("apm/batterycharge");
+ removeMonitor("apm/remainingtime");
+
+ close(ApmFD);
+}
+
+int
+updateApm(void)
+{
+ struct apm_info info;
+ int retval;
+
+ retval = ioctl(ApmFD, APMIO_GETINFO, &info);
+
+ BattFill = info.ai_batt_life;
+ BattTime = info.ai_batt_time;
+
+ return retval;
+}
+
+void
+printApmBatFill(const char* c)
+{
+ fprintf(CurrentClient, "%d\n", BattFill);
+}
+
+void
+printApmBatFillInfo(const char* c)
+{
+ fprintf(CurrentClient, "Battery charge\t0\t100\t%%\n");
+}
+
+void
+printApmBatTime(const char* c)
+{
+ fprintf(CurrentClient, "%d\n", BattTime);
+}
+
+void
+printApmBatTimeInfo(const char* c)
+{
+ fprintf(CurrentClient, "Remaining battery time\t0\t0\tmin\n");
+}
+
+#endif
diff --git a/ksysguard/ksysguardd/FreeBSD/apm.h b/ksysguard/ksysguardd/FreeBSD/apm.h
new file mode 100644
index 000000000..4e3c0c0d3
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/apm.h
@@ -0,0 +1,34 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _apm_h_
+#define _apm_h_
+
+void initApm(struct SensorModul* sm);
+void exitApm(void);
+
+int updateApm(void);
+
+void printApmBatFill(const char*);
+void printApmBatFillInfo(const char*);
+void printApmBatTime(const char*);
+void printApmBatTimeInfo(const char*);
+
+#endif
diff --git a/ksysguard/ksysguardd/FreeBSD/diskstat.c b/ksysguard/ksysguardd/FreeBSD/diskstat.c
new file mode 100644
index 000000000..04f64a706
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/diskstat.c
@@ -0,0 +1,256 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "Command.h"
+#include "ccont.h"
+#include "diskstat.h"
+#include "ksysguardd.h"
+
+typedef struct {
+ char device[256];
+ char mntpnt[256];
+ long blocks;
+ long bfree;
+ long bused;
+ int bused_percent;
+} DiskInfo;
+
+static CONTAINER DiskStatList = 0;
+static struct SensorModul* DiskStatSM;
+
+char *getMntPnt(const char *cmd)
+{
+ static char device[1025];
+ char *ptr;
+
+ memset(device, 0, sizeof(device));
+ sscanf(cmd, "partitions%1024s", device);
+
+ ptr = (char *)rindex(device, '/');
+ *ptr = '\0';
+
+ return (char *)device;
+}
+
+int numMntPnt(void)
+{
+ struct statfs *fs_info;
+ int i, n, counter = 0;
+
+ n = getmntinfo(&fs_info, MNT_WAIT);
+ for (i = 0; i < n; i++)
+ if (strcmp(fs_info[i].f_fstypename, "procfs") && strcmp(fs_info[i].f_fstypename, "swap") && strcmp(fs_info[i].f_fstypename, "devfs"))
+ counter++;
+
+ return counter;
+}
+
+/* ------------------------------ public part --------------------------- */
+
+void initDiskStat(struct SensorModul* sm)
+{
+ char monitor[1024];
+ DiskInfo* disk_info;
+
+ DiskStatList = new_ctnr();
+ DiskStatSM = sm;
+
+ updateDiskStat();
+
+ registerMonitor("partitions/list", "listview", printDiskStat, printDiskStatInfo, DiskStatSM);
+
+ for (disk_info = first_ctnr(DiskStatList); disk_info; disk_info = next_ctnr(DiskStatList)) {
+ snprintf(monitor, sizeof(monitor), "partitions%s/usedspace", disk_info->mntpnt);
+ registerMonitor(monitor, "integer", printDiskStatUsed, printDiskStatUsedInfo, DiskStatSM);
+ snprintf(monitor, sizeof(monitor), "partitions%s/freespace", disk_info->mntpnt);
+ registerMonitor(monitor, "integer", printDiskStatFree, printDiskStatFreeInfo, DiskStatSM);
+ snprintf(monitor, sizeof(monitor), "partitions%s/filllevel", disk_info->mntpnt);
+ registerMonitor(monitor, "integer", printDiskStatPercent, printDiskStatPercentInfo, DiskStatSM);
+ }
+}
+
+void checkDiskStat(void)
+{
+ if (numMntPnt() != level_ctnr(DiskStatList)) {
+ /* a filesystem was mounted or unmounted
+ so we do a reset */
+ exitDiskStat();
+ initDiskStat(DiskStatSM);
+ }
+}
+
+void exitDiskStat(void)
+{
+ DiskInfo *disk_info;
+ char monitor[1024];
+
+ removeMonitor("partitions/list");
+
+ for (disk_info = first_ctnr(DiskStatList); disk_info; disk_info = next_ctnr(DiskStatList)) {
+ snprintf(monitor, sizeof(monitor), "partitions%s/usedspace", disk_info->mntpnt);
+ removeMonitor(monitor);
+ snprintf(monitor, sizeof(monitor), "partitions%s/freespace", disk_info->mntpnt);
+ removeMonitor(monitor);
+ snprintf(monitor, sizeof(monitor), "partitions%s/filllevel", disk_info->mntpnt);
+ removeMonitor(monitor);
+ }
+
+ destr_ctnr(DiskStatList, free);
+}
+
+int updateDiskStat(void)
+{
+ struct statfs *fs_info;
+ struct statfs fs;
+ float percent;
+ int i, mntcount;
+ DiskInfo *disk_info;
+
+ /* let's hope there is no difference between the DiskStatList and
+ the number of mounted filesystems */
+ for (i = level_ctnr(DiskStatList); i >= 0; --i)
+ free(pop_ctnr(DiskStatList));
+
+ mntcount = getmntinfo(&fs_info, MNT_WAIT);
+
+ for (i = 0; i < mntcount; i++) {
+ fs = fs_info[i];
+ if (strcmp(fs.f_fstypename, "procfs") && strcmp(fs.f_fstypename, "devfs") && strcmp(fs.f_fstypename, "devfs")) {
+
+ if ( fs.f_blocks != 0 )
+ {
+ percent = (((float)fs.f_blocks - (float)fs.f_bfree)/(float)fs.f_blocks);
+ percent = percent * 100;
+ }
+ else
+ percent = 0;
+
+ if ((disk_info = (DiskInfo *)malloc(sizeof(DiskInfo))) == NULL) {
+ continue;
+ }
+ memset(disk_info, 0, sizeof(DiskInfo));
+ strlcpy(disk_info->device, fs.f_mntfromname, sizeof(disk_info->device));
+ if (!strcmp(fs.f_mntonname, "/")) {
+ strncpy(disk_info->mntpnt, "/root", 6);
+ } else {
+ strlcpy(disk_info->mntpnt, fs.f_mntonname, sizeof(disk_info->mntpnt));
+ }
+ disk_info->blocks = fs.f_blocks;
+ disk_info->bfree = fs.f_bfree;
+ disk_info->bused = (fs.f_blocks - fs.f_bfree);
+ disk_info->bused_percent = (int)percent;
+
+ push_ctnr(DiskStatList, disk_info);
+ }
+ }
+
+ return 0;
+}
+
+void printDiskStat(const char* cmd)
+{
+ DiskInfo* disk_info;
+
+ for (disk_info = first_ctnr(DiskStatList); disk_info; disk_info = next_ctnr(DiskStatList)) {
+ fprintf(CurrentClient, "%s\t%ld\t%ld\t%ld\t%d\t%s\n",
+ disk_info->device,
+ disk_info->blocks,
+ disk_info->bused,
+ disk_info->bfree,
+ disk_info->bused_percent,
+ disk_info->mntpnt);
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printDiskStatInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Device\tBlocks\tUsed\tAvailable\tUsed %%\tMountPoint\nM\tD\tD\tD\td\ts\n");
+}
+
+void printDiskStatUsed(const char* cmd)
+{
+ DiskInfo* disk_info;
+ char *mntpnt = (char *)getMntPnt(cmd);
+
+ for (disk_info = first_ctnr(DiskStatList); disk_info; disk_info = next_ctnr(DiskStatList)) {
+ if (!strcmp(mntpnt, disk_info->mntpnt)) {
+ fprintf(CurrentClient, "%ld\n", disk_info->bused);
+ }
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printDiskStatUsedInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Used Blocks\t0\t-\tBlocks\n");
+}
+
+void printDiskStatFree(const char* cmd)
+{
+ DiskInfo* disk_info;
+ char *mntpnt = (char *)getMntPnt(cmd);
+
+ for (disk_info = first_ctnr(DiskStatList); disk_info; disk_info = next_ctnr(DiskStatList)) {
+ if (!strcmp(mntpnt, disk_info->mntpnt)) {
+ fprintf(CurrentClient, "%ld\n", disk_info->bfree);
+ }
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printDiskStatFreeInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Free Blocks\t0\t-\tBlocks\n");
+}
+
+void printDiskStatPercent(const char* cmd)
+{
+ DiskInfo* disk_info;
+ char *mntpnt = (char *)getMntPnt(cmd);
+
+ for (disk_info = first_ctnr(DiskStatList); disk_info; disk_info = next_ctnr(DiskStatList)) {
+ if (!strcmp(mntpnt, disk_info->mntpnt)) {
+ fprintf(CurrentClient, "%d\n", disk_info->bused_percent);
+ }
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printDiskStatPercentInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Used Blocks\t0\t100\t%%\n");
+}
diff --git a/ksysguard/ksysguardd/FreeBSD/diskstat.h b/ksysguard/ksysguardd/FreeBSD/diskstat.h
new file mode 100644
index 000000000..06f247837
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/diskstat.h
@@ -0,0 +1,40 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _diskstat_h_
+#define _diskstat_h_
+
+void initDiskStat(struct SensorModul* sm);
+void exitDiskStat(void);
+
+int updateDiskStat(void);
+void checkDiskStat(void);
+
+void printDiskStat(const char* cmd);
+void printDiskStatInfo(const char* cmd);
+
+void printDiskStatUsed(const char* cmd);
+void printDiskStatUsedInfo(const char* cmd);
+void printDiskStatFree(const char* cmd);
+void printDiskStatFreeInfo(const char* cmd);
+void printDiskStatPercent(const char* cmd);
+void printDiskStatPercentInfo(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/FreeBSD/loadavg.c b/ksysguard/ksysguardd/FreeBSD/loadavg.c
new file mode 100644
index 000000000..53eb9fc4e
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/loadavg.c
@@ -0,0 +1,96 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "Command.h"
+#include "ksysguardd.h"
+#include "loadavg.h"
+
+static double LoadAvg[3];
+
+/*
+================================ public part =================================
+*/
+
+void
+initLoadAvg(struct SensorModul* sm)
+{
+ if (updateLoadAvg() < 0)
+ return;
+
+ registerMonitor("cpu/loadavg1", "float", printLoadAvg1,
+ printLoadAvg1Info, sm);
+ registerMonitor("cpu/loadavg5", "float", printLoadAvg5,
+ printLoadAvg5Info, sm);
+ registerMonitor("cpu/loadavg15", "float", printLoadAvg15,
+ printLoadAvg15Info, sm);
+}
+
+void
+exitLoadAvg(void)
+{
+ removeMonitor("cpu/loadavg1");
+ removeMonitor("cpu/loadavg5");
+ removeMonitor("cpu/loadavg15");
+}
+
+int
+updateLoadAvg(void)
+{
+ return getloadavg(LoadAvg, 3);
+}
+
+void
+printLoadAvg1(const char* c)
+{
+ fprintf(CurrentClient, "%f\n", LoadAvg[0]);
+}
+
+void
+printLoadAvg1Info(const char* c)
+{
+ fprintf(CurrentClient, "Load average 1 min\t0\t0\t\n");
+}
+
+void
+printLoadAvg5(const char* c)
+{
+ fprintf(CurrentClient, "%f\n", LoadAvg[1]);
+}
+
+void
+printLoadAvg5Info(const char* c)
+{
+ fprintf(CurrentClient, "Load average 5 min\t0\t0\t\n");
+}
+
+void
+printLoadAvg15(const char* c)
+{
+ fprintf(CurrentClient, "%f\n", LoadAvg[2]);
+}
+
+void
+printLoadAvg15Info(const char* c)
+{
+ fprintf(CurrentClient, "Load average 15 min\t0\t0\t\n");
+}
diff --git a/ksysguard/ksysguardd/FreeBSD/loadavg.h b/ksysguard/ksysguardd/FreeBSD/loadavg.h
new file mode 100644
index 000000000..801e4ef8d
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/loadavg.h
@@ -0,0 +1,36 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _loadavg_h_
+#define _loadavg_h_
+
+void initLoadAvg(struct SensorModul* sm);
+void exitLoadAvg(void);
+
+int updateLoadAvg(void);
+
+void printLoadAvg1(const char*);
+void printLoadAvg1Info(const char*);
+void printLoadAvg5(const char*);
+void printLoadAvg5Info(const char*);
+void printLoadAvg15(const char*);
+void printLoadAvg15Info(const char*);
+
+#endif
diff --git a/ksysguard/ksysguardd/FreeBSD/logfile.c b/ksysguard/ksysguardd/FreeBSD/logfile.c
new file mode 100644
index 000000000..3b07ad8ac
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/logfile.c
@@ -0,0 +1,175 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "Command.h"
+#include "ccont.h"
+#include "conf.h"
+#include "ksysguardd.h"
+#include "logfile.h"
+
+static CONTAINER LogFiles = 0;
+static unsigned long counter = 1;
+
+typedef struct {
+ char name[256];
+ FILE* fh;
+ unsigned long id;
+} LogFileEntry;
+
+extern CONTAINER LogFileList;
+
+/*
+================================ public part =================================
+*/
+
+void initLogFile(struct SensorModul* sm)
+{
+ char monitor[1024];
+ ConfigLogFile *entry;
+
+ registerCommand("logfile_register", registerLogFile);
+ registerCommand("logfile_unregister", unregisterLogFile);
+ registerCommand("logfile_registered", printRegistered);
+
+ for (entry = first_ctnr(LogFileList); entry; entry = next_ctnr(LogFileList))
+ {
+ FILE* fp;
+
+ /* register the log file if we can actually read the file. */
+ if ((fp = fopen(entry->path, "r")) != NULL)
+ {
+ fclose(fp);
+ snprintf(monitor, 1024, "logfiles/%s", entry->name);
+ registerMonitor(monitor, "logfile", printLogFile,
+ printLogFileInfo, sm);
+ }
+ }
+
+ LogFiles = new_ctnr();
+}
+
+void exitLogFile(void)
+{
+ destr_ctnr(LogFiles, free);
+}
+
+void printLogFile(const char* cmd)
+{
+ char line[1024];
+ unsigned long id;
+ int i;
+ char ch;
+ LogFileEntry *entry;
+
+ sscanf(cmd, "%*s %lu", &id);
+
+ for (entry = first_ctnr(LogFiles); entry; entry = next_ctnr(LogFiles)) {
+ if (entry->id == id) {
+ while (fgets(line, sizeof(line), entry->fh) != NULL) {
+ fprintf(CurrentClient, "%s", line);
+ }
+ clearerr(entry->fh);
+ }
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printLogFileInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "LogFile\n");
+}
+
+void registerLogFile(const char* cmd)
+{
+ char name[257];
+ FILE* file;
+ LogFileEntry *entry;
+ ConfigLogFile *conf;
+
+ memset(name, 0, sizeof(name));
+ sscanf(cmd, "%*s %256s", name);
+
+ for (conf = first_ctnr(LogFileList); conf; conf = next_ctnr(LogFileList)) {
+ if (!strcmp(conf->name, name)) {
+ if ((file = fopen(conf->path, "r")) == NULL) {
+ print_error("fopen()");
+ fprintf(CurrentClient, "0\n");
+ return;
+ }
+
+ fseek(file, 0, SEEK_END);
+
+ if ((entry = (LogFileEntry *)malloc(sizeof(LogFileEntry))) == NULL) {
+ print_error("malloc()");
+ fprintf(CurrentClient, "0\n");
+ return;
+ }
+
+ entry->fh = file;
+ strlcpy(entry->name, conf->name, sizeof(entry->name));
+ entry->id = counter;
+
+ push_ctnr(LogFiles, entry);
+
+ fprintf(CurrentClient, "%lu\n", counter);
+ counter++;
+
+ return;
+ }
+ }
+
+ fprintf(CurrentClient, "0\n");
+}
+
+void unregisterLogFile(const char* cmd)
+{
+ unsigned long id;
+ LogFileEntry *entry;
+
+ sscanf(cmd, "%*s %lu", &id);
+
+ for (entry = first_ctnr(LogFiles); entry; entry = next_ctnr(LogFiles)) {
+ if (entry->id == id) {
+ fclose(entry->fh);
+ free(remove_ctnr(LogFiles));
+ fprintf(CurrentClient, "\n");
+ return;
+ }
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printRegistered(const char* cmd)
+{
+ LogFileEntry *entry;
+
+ for (entry = first_ctnr(LogFiles); entry; entry = next_ctnr(LogFiles))
+ fprintf(CurrentClient, "%s:%lu\n", entry->name, entry->id);
+
+ fprintf(CurrentClient, "\n");
+}
diff --git a/ksysguard/ksysguardd/FreeBSD/logfile.h b/ksysguard/ksysguardd/FreeBSD/logfile.h
new file mode 100644
index 000000000..45ade9013
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/logfile.h
@@ -0,0 +1,36 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _logfile_h_
+#define _logfile_h_
+
+void initLogFile(struct SensorModul* sm);
+void exitLogFile(void);
+
+void printLogFile(const char* cmd);
+void printLogFileInfo(const char* cmd);
+
+void registerLogFile(const char* cmd);
+void unregisterLogFile(const char* cmd);
+
+/* debug command */
+void printRegistered(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/FreeBSD/netdev.c b/ksysguard/ksysguardd/FreeBSD/netdev.c
new file mode 100644
index 000000000..cec8be590
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/netdev.c
@@ -0,0 +1,353 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/if_mib.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "Command.h"
+#include "ksysguardd.h"
+#include "netdev.h"
+
+
+typedef struct {
+ char name[32];
+ u_long recBytes;
+ u_long recPacks;
+ u_long recErrs;
+ u_long recDrop;
+ u_long recMulticast;
+ u_long sentBytes;
+ u_long sentPacks;
+ u_long sentErrs;
+ u_long sentMulticast;
+ u_long sentColls;
+} NetDevInfo;
+
+#define MAXNETDEVS 64
+static NetDevInfo NetDevs[MAXNETDEVS];
+static NetDevInfo NetDevsOld[MAXNETDEVS];
+static int NetDevCnt = 0;
+static struct SensorModul* NetDevSM;
+
+static float elapsed = 0.0;
+static struct timeval old_tv;
+
+char **parseCommand(const char *cmd)
+{
+ char *tmp_cmd = strdup(cmd);
+ char *begin;
+ char **retval = malloc(sizeof(char *)*2);
+
+ begin = rindex(tmp_cmd, '/');
+ *begin = '\0';
+ begin++;
+ retval[1] = strdup((const char *)begin); /* sensor */
+
+ begin = rindex(tmp_cmd, '/');
+ *begin = '\0';
+ begin = rindex(tmp_cmd, '/');
+ begin++;
+ retval[0] = strdup((const char *)begin); /* interface */
+ free(tmp_cmd);
+
+ return retval;
+}
+
+int numActivIfaces(void)
+{
+ int counter = 0;
+ int name[6];
+ int num_iface, i;
+ size_t len;
+ struct ifmibdata ifmd;
+
+ len = sizeof(num_iface);
+ sysctlbyname("net.link.generic.system.ifcount", &num_iface, &len, NULL, 0);
+
+ for (i = 1; i < num_iface + 1; i++) {
+ name[0] = CTL_NET;
+ name[1] = PF_LINK;
+ name[2] = NETLINK_GENERIC;
+ name[3] = IFMIB_IFDATA;
+ name[4] = i;
+ name[5] = IFDATA_GENERAL;
+
+ len = sizeof(ifmd);
+ sysctl(name, 6, &ifmd, &len, NULL, 0);
+ if (ifmd.ifmd_flags & IFF_UP)
+ counter++;
+ }
+
+ return counter;
+}
+
+/* ------------------------------ public part --------------------------- */
+
+void initNetDev(struct SensorModul* sm)
+{
+ int i;
+ char monitor[1024];
+ gettimeofday(&old_tv, (struct timezone *)0);
+
+ NetDevSM = sm;
+
+ updateNetDev();
+
+ for (i = 0; i < NetDevCnt; i++) {
+ /* init data */
+ NetDevsOld[i] = NetDevs[i];
+
+ /* register monitors */
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/receiver/data", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevRecBytes, printNetDevRecBytesInfo, NetDevSM);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/receiver/packets", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevRecBytes, printNetDevRecBytesInfo, NetDevSM);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/receiver/errors", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevRecBytes, printNetDevRecBytesInfo, NetDevSM);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/receiver/drops", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevRecBytes, printNetDevRecBytesInfo, NetDevSM);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/receiver/multicast", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevRecBytes, printNetDevRecBytesInfo, NetDevSM);
+
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/transmitter/data", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevSentBytes, printNetDevSentBytesInfo, NetDevSM);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/transmitter/packets", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevSentBytes, printNetDevSentBytesInfo, NetDevSM);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/transmitter/errors", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevSentBytes, printNetDevSentBytesInfo, NetDevSM);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/transmitter/multicast", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevSentBytes, printNetDevSentBytesInfo, NetDevSM);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/transmitter/collisions", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevSentBytes, printNetDevSentBytesInfo, NetDevSM);
+ }
+}
+
+void exitNetDev(void)
+{
+ int i;
+ char monitor[1024];
+
+ for (i = 0; i < NetDevCnt; i++) {
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/receiver/data", NetDevs[i].name);
+ removeMonitor(monitor);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/receiver/packets", NetDevs[i].name);
+ removeMonitor(monitor);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/receiver/errors", NetDevs[i].name);
+ removeMonitor(monitor);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/receiver/drops", NetDevs[i].name);
+ removeMonitor(monitor);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/receiver/multicast", NetDevs[i].name);
+ removeMonitor(monitor);
+
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/transmitter/data", NetDevs[i].name);
+ removeMonitor(monitor);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/transmitter/packets", NetDevs[i].name);
+ removeMonitor(monitor);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/transmitter/errors", NetDevs[i].name);
+ removeMonitor(monitor);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/transmitter/multicast", NetDevs[i].name);
+ removeMonitor(monitor);
+ snprintf(monitor, sizeof(monitor), "network/interfaces/%s/transmitter/collisions", NetDevs[i].name);
+ removeMonitor(monitor);
+ }
+}
+
+int updateNetDev(void)
+{
+ int name[6];
+ int num_iface, i;
+ size_t len;
+ struct ifmibdata ifmd;
+ struct timeval new_tv, tv;
+
+ len = sizeof(num_iface);
+ sysctlbyname("net.link.generic.system.ifcount", &num_iface, &len, NULL, 0);
+
+ NetDevCnt = 0;
+ for (i = 1; i < num_iface + 1; i++) {
+ name[0] = CTL_NET;
+ name[1] = PF_LINK;
+ name[2] = NETLINK_GENERIC;
+ name[3] = IFMIB_IFDATA;
+ name[4] = i;
+ name[5] = IFDATA_GENERAL;
+
+ len = sizeof(ifmd);
+ sysctl(name, 6, &ifmd, &len, NULL, 0);
+ if (ifmd.ifmd_flags & IFF_UP) {
+ NetDevsOld[NetDevCnt] = NetDevs[NetDevCnt];
+
+ strlcpy(NetDevs[NetDevCnt].name, ifmd.ifmd_name, sizeof(NetDevs[NetDevCnt].name));
+ NetDevs[NetDevCnt].recBytes = ifmd.ifmd_data.ifi_ibytes;
+ NetDevs[NetDevCnt].recPacks = ifmd.ifmd_data.ifi_ipackets;
+ NetDevs[NetDevCnt].recErrs = ifmd.ifmd_data.ifi_ierrors;
+ NetDevs[NetDevCnt].recDrop = ifmd.ifmd_data.ifi_iqdrops;
+ NetDevs[NetDevCnt].recMulticast = ifmd.ifmd_data.ifi_imcasts;
+ NetDevs[NetDevCnt].sentBytes = ifmd.ifmd_data.ifi_obytes;
+ NetDevs[NetDevCnt].sentPacks = ifmd.ifmd_data.ifi_opackets;
+ NetDevs[NetDevCnt].sentErrs = ifmd.ifmd_data.ifi_oerrors;
+ NetDevs[NetDevCnt].sentMulticast = ifmd.ifmd_data.ifi_omcasts;
+ NetDevs[NetDevCnt].sentColls = ifmd.ifmd_data.ifi_collisions;
+ NetDevCnt++;
+ }
+ }
+
+ gettimeofday(&new_tv, (struct timezone *)0);
+ timersub(&new_tv, &old_tv, &tv);
+ elapsed = tv.tv_sec + (tv.tv_usec * 1e-6);
+ old_tv = new_tv;
+
+ return 0;
+}
+
+void checkNetDev(void)
+{
+ if (numActivIfaces() != NetDevCnt) {
+ /* interface has been added or removed
+ so we do a reset */
+ exitNetDev();
+ initNetDev(NetDevSM);
+ }
+}
+
+void printNetDevRecBytes(const char *cmd)
+{
+ int i;
+ char **retval;
+
+ retval = parseCommand(cmd);
+
+ if (retval == NULL)
+ return;
+
+ for (i = 0; i < NetDevCnt; i++) {
+ if (!strcmp(NetDevs[i].name, retval[0])) {
+ if (!strncmp(retval[1], "data", 4))
+ fprintf(CurrentClient, "%lu", (u_long)((NetDevs[i].recBytes - NetDevsOld[i].recBytes) / (1024 * elapsed)));
+ if (!strncmp(retval[1], "packets", 7))
+ fprintf(CurrentClient, "%lu", (u_long)((NetDevs[i].recPacks - NetDevsOld[i].recPacks) / elapsed));
+ if (!strncmp(retval[1], "errors", 6))
+ fprintf(CurrentClient, "%lu", (u_long)((NetDevs[i].recErrs - NetDevsOld[i].recErrs) / elapsed));
+ if (!strncmp(retval[1], "drops", 5))
+ fprintf(CurrentClient, "%lu", (u_long)((NetDevs[i].recDrop - NetDevsOld[i].recDrop) / elapsed));
+ if (!strncmp(retval[1], "multicast", 9))
+ fprintf(CurrentClient, "%lu", (u_long)((NetDevs[i].recMulticast - NetDevsOld[i].recMulticast) / elapsed));
+ }
+ }
+ free(retval[0]);
+ free(retval[1]);
+ free(retval);
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printNetDevRecBytesInfo(const char *cmd)
+{
+ char **retval;
+
+ retval = parseCommand(cmd);
+
+ if (retval == NULL)
+ return;
+
+ if (!strncmp(retval[1], "data", 4))
+ fprintf(CurrentClient, "Received Data\t0\t0\tkBytes/s\n");
+ if (!strncmp(retval[1], "packets", 7))
+ fprintf(CurrentClient, "Received Packets\t0\t0\t1/s\n");
+ if (!strncmp(retval[1], "errors", 6))
+ fprintf(CurrentClient, "Receiver Errors\t0\t0\t1/s\n");
+ if (!strncmp(retval[1], "drops", 5))
+ fprintf(CurrentClient, "Receiver Drops\t0\t0\t1/s\n");
+ if (!strncmp(retval[1], "multicast", 9))
+ fprintf(CurrentClient, "Received Multicast Packets\t0\t0\t1/s\n");
+
+ free(retval[0]);
+ free(retval[1]);
+ free(retval);
+}
+
+void printNetDevSentBytes(const char *cmd)
+{
+ int i;
+ char **retval;
+
+ retval = parseCommand(cmd);
+
+ if (retval == NULL)
+ return;
+
+ for (i = 0; i < NetDevCnt; i++) {
+ if (!strcmp(NetDevs[i].name, retval[0])) {
+ if (!strncmp(retval[1], "data", 4))
+ fprintf(CurrentClient, "%lu", (u_long)((NetDevs[i].sentBytes - NetDevsOld[i].sentBytes) / (1024 * elapsed)));
+ if (!strncmp(retval[1], "packets", 7))
+ fprintf(CurrentClient, "%lu", (u_long)((NetDevs[i].sentPacks - NetDevsOld[i].sentPacks) / elapsed));
+ if (!strncmp(retval[1], "errors", 6))
+ fprintf(CurrentClient, "%lu", (u_long)((NetDevs[i].sentErrs - NetDevsOld[i].sentErrs) / elapsed));
+ if (!strncmp(retval[1], "multicast", 9))
+ fprintf(CurrentClient, "%lu", (u_long)((NetDevs[i].sentMulticast - NetDevsOld[i].sentMulticast) / elapsed));
+ if (!strncmp(retval[1], "collisions", 10))
+ fprintf(CurrentClient, "%lu", (u_long)((NetDevs[i].sentColls - NetDevsOld[i].sentColls) / elapsed));
+ }
+ }
+ free(retval[0]);
+ free(retval[1]);
+ free(retval);
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printNetDevSentBytesInfo(const char *cmd)
+{
+ char **retval;
+
+ retval = parseCommand(cmd);
+
+ if (retval == NULL)
+ return;
+
+ if (!strncmp(retval[1], "data", 4))
+ fprintf(CurrentClient, "Sent Data\t0\t0\tkBytes/s\n");
+ if (!strncmp(retval[1], "packets", 7))
+ fprintf(CurrentClient, "Sent Packets\t0\t0\t1/s\n");
+ if (!strncmp(retval[1], "errors", 6))
+ fprintf(CurrentClient, "Transmitter Errors\t0\t0\t1/s\n");
+ if (!strncmp(retval[1], "multicast", 9))
+ fprintf(CurrentClient, "Sent Multicast Packets\t0\t0\t1/s\n");
+ if (!strncmp(retval[1], "collisions", 10))
+ fprintf(CurrentClient, "Transmitter Collisions\t0\t0\t1/s\n");
+
+ free(retval[0]);
+ free(retval[1]);
+ free(retval);
+}
diff --git a/ksysguard/ksysguardd/FreeBSD/netdev.h b/ksysguard/ksysguardd/FreeBSD/netdev.h
new file mode 100644
index 000000000..17d9c89e9
--- /dev/null
+++ b/ksysguard/ksysguardd/FreeBSD/netdev.h
@@ -0,0 +1,35 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _netdev_h_
+#define _netdev_h_
+
+void initNetDev(struct SensorModul* sm);
+void exitNetDev(void);
+
+int updateNetDev(void);
+void checkNetDev(void);
+
+void printNetDevRecBytes(const char* cmd);
+void printNetDevRecBytesInfo(const char* cmd);
+void printNetDevSentBytes(const char* cmd);
+void printNetDevSentBytesInfo(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/Irix/LoadAvg.c b/ksysguard/ksysguardd/Irix/LoadAvg.c
new file mode 100644
index 000000000..92d284756
--- /dev/null
+++ b/ksysguard/ksysguardd/Irix/LoadAvg.c
@@ -0,0 +1,78 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ Irix support by Carsten Kroll <CKroll@pinnaclesys.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/swap.h>
+
+#include "config.h"
+
+#include "ksysguardd.h"
+#include "Command.h"
+#include "LoadAvg.h"
+
+double loadavg1 = 0.0;
+double loadavg5 = 0.0;
+double loadavg15 = 0.0;
+
+void initLoadAvg(struct SensorModul* sm ) {
+ registerMonitor( "cpu/loadavg1", "float",
+ printLoadAvg1, printLoadAvg1Info, sm );
+ registerMonitor( "cpu/loadavg5", "float",
+ printLoadAvg5, printLoadAvg5Info, sm );
+ registerMonitor( "cpu/loadavg15", "float",
+ printLoadAvg15, printLoadAvg15Info, sm );
+}
+
+void exitLoadAvg( void ) {
+}
+
+int updateLoadAvg( void ) {
+
+ return( 0 );
+}
+
+void printLoadAvg1Info( const char *cmd ) {
+ fprintf(CurrentClient, "avnrun 1min\t0\t0\n" );
+}
+
+void printLoadAvg1( const char *cmd ) {
+ fprintf(CurrentClient, "%f\n", loadavg1 );
+}
+
+void printLoadAvg5Info( const char *cmd ) {
+ fprintf(CurrentClient, "avnrun 5min\t0\t0\n" );
+}
+
+void printLoadAvg5( const char *cmd ) {
+ fprintf(CurrentClient, "%f\n", loadavg5 );
+}
+
+void printLoadAvg15Info( const char *cmd ) {
+ fprintf(CurrentClient, "avnrun 15min\t0\t0\n" );
+}
+
+void printLoadAvg15( const char *cmd ) {
+ fprintf(CurrentClient, "%f\n", loadavg15 );
+}
diff --git a/ksysguard/ksysguardd/Irix/LoadAvg.h b/ksysguard/ksysguardd/Irix/LoadAvg.h
new file mode 100644
index 000000000..eea8ad82e
--- /dev/null
+++ b/ksysguard/ksysguardd/Irix/LoadAvg.h
@@ -0,0 +1,41 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _LoadAvg_h_
+#define _LoadAvg_h_
+
+#define LOAD(a) ((double)(a) / (1 << 8 ))
+
+void initLoadAvg(struct SensorModul* sm);
+void exitLoadAvg(void);
+
+int updateLoadAvg(void);
+
+void printLoadAvg1( const char *cmd );
+void printLoadAvg1Info( const char *cmd );
+void printLoadAvg5( const char *cmd );
+void printLoadAvg5Info( const char *cmd );
+void printLoadAvg15( const char *cmd );
+void printLoadAvg15Info( const char *cmd );
+
+#endif /* _LoadAvg_h_ */
diff --git a/ksysguard/ksysguardd/Irix/Makefile.am b/ksysguard/ksysguardd/Irix/Makefile.am
new file mode 100644
index 000000000..3c1997924
--- /dev/null
+++ b/ksysguard/ksysguardd/Irix/Makefile.am
@@ -0,0 +1,4 @@
+INCLUDES = -I$(srcdir)/../../CContLib -I..
+
+noinst_LIBRARIES = libksysguardd.a
+libksysguardd_a_SOURCES = Memory.c LoadAvg.c ProcessList.c NetDev.c cpu.c
diff --git a/ksysguard/ksysguardd/Irix/Memory.c b/ksysguard/ksysguardd/Irix/Memory.c
new file mode 100644
index 000000000..e88123ddd
--- /dev/null
+++ b/ksysguard/ksysguardd/Irix/Memory.c
@@ -0,0 +1,128 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ Irix support by Carsten Kroll <ckroll@pinnaclesys.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/statfs.h>
+#include <sys/swap.h>
+#include <sys/sysmp.h>
+
+#include "config.h"
+
+#include "ksysguardd.h"
+#include "Command.h"
+#include "Memory.h"
+
+static int Dirty = 1;
+static t_memsize totalmem = (t_memsize) 0;
+static t_memsize freemem = (t_memsize) 0;
+static unsigned long totalswap = 0L,vswap = 0L;
+static unsigned long freeswap = 0L,bufmem = 0L ;
+
+void initMemory( struct SensorModul* sm ) {
+
+ registerMonitor( "mem/physical/free", "integer",
+ printMemFree, printMemFreeInfo, sm );
+ registerMonitor( "mem/physical/used", "integer",
+ printMemUsed, printMemUsedInfo, sm );
+ registerMonitor( "mem/swap/free", "integer",
+ printSwapFree, printSwapFreeInfo, sm );
+ registerMonitor( "mem/swap/used", "integer",
+ printSwapUsed, printSwapUsedInfo, sm );
+}
+
+void exitMemory( void ) {
+}
+
+int updateMemory( void ) {
+ struct statfs sf;
+ off_t val;
+ int pagesize = getpagesize();
+ struct rminfo rmi;
+ if( sysmp(MP_SAGET, MPSA_RMINFO, &rmi, sizeof(rmi)) == -1 )
+ return( -1 );
+ totalmem = rmi.physmem*pagesize/1024; // total physical memory (without swaps)
+ freemem = rmi.freemem*pagesize/1024; // total free physical memory (without swaps)
+ bufmem = rmi.bufmem *pagesize/1024;
+
+ statfs ("/proc", &sf,sizeof(sf),0);
+
+ swapctl(SC_GETSWAPVIRT,&val);
+ vswap = val >> 1;
+ swapctl(SC_GETSWAPTOT,&val);
+ totalswap = val >> 1;
+ swapctl(SC_GETFREESWAP,&val);
+ freeswap = val >> 1;
+
+ Dirty = 1;
+
+ return( 0 );
+}
+
+void printMemFreeInfo( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "Free Memory\t0\t%ld\tKB\n", freemem );
+}
+
+void printMemFree( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "%ld\n", freemem );
+}
+
+void printMemUsedInfo( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "Used Memory\t0\t%ld\tKB\n", totalmem - freemem );
+}
+
+void printMemUsed( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "%ld\n", totalmem - freemem );
+}
+
+void printSwapFreeInfo( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "Free Swap\t0\t%ld\tKB\n", freeswap );
+}
+
+void printSwapFree( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "%ld\n", freeswap );
+}
+void printSwapUsedInfo( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "Used Swap\t0\t%ld\tKB\n", totalswap - freeswap );
+}
+
+void printSwapUsed( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "%ld\n", totalswap - freeswap );
+}
diff --git a/ksysguard/ksysguardd/Irix/Memory.h b/ksysguard/ksysguardd/Irix/Memory.h
new file mode 100644
index 000000000..ac3677b13
--- /dev/null
+++ b/ksysguard/ksysguardd/Irix/Memory.h
@@ -0,0 +1,46 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ Irix support by Carsten Kroll <ckroll@pinnaclesys.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _Memory_h_
+#define _Memory_h_
+
+typedef unsigned long t_memsize;
+
+void initMemory(struct SensorModul* sm);
+void exitMemory(void);
+
+int updateMemory(void);
+
+void printMemFree( const char *cmd );
+void printMemFreeInfo( const char *cmd );
+void printMemUsed( const char *cmd );
+void printMemUsedInfo( const char *cmd );
+void printMemBuff( const char *cmd);
+void printMemBuffInfo( const char *cmd);
+
+void printSwapFree( const char *cmd );
+void printSwapFreeInfo( const char *cmd );
+void printSwapUsed( const char *cmd );
+void printSwapUsedInfo( const char *cmd );
+
+#endif /* _Memory_h */
diff --git a/ksysguard/ksysguardd/Irix/NetDev.c b/ksysguard/ksysguardd/Irix/NetDev.c
new file mode 100644
index 000000000..80bc2b310
--- /dev/null
+++ b/ksysguard/ksysguardd/Irix/NetDev.c
@@ -0,0 +1,343 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+ Irix Support by Carsten Kroll <ckroll@pinnaclesys.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/soioctl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <invent.h>
+#include <strings.h>
+
+
+#include "Command.h"
+#include "ksysguardd.h"
+#include "NetDev.h"
+
+#ifdef __GNUC__
+#define LONGLONG long long
+#endif
+
+typedef struct {
+ char name[IFNAMSIZ];
+ u_long recBytes;
+ u_long recPacks;
+ u_long recErrs;
+ u_long recDrop;
+ u_long recMulticast;
+ u_long sentBytes;
+ u_long sentPacks;
+ u_long sentErrs;
+ u_long sentMulticast;
+ u_long sentColls;
+} NetDevInfo;
+
+#define MAXNETDEVS 32
+static NetDevInfo NetDevs[MAXNETDEVS];
+static NetDevInfo oNetDevs[MAXNETDEVS];
+static int NetDevCnt = 0;
+
+char **parseCommand(const char *cmd)
+{
+ char *tmp_cmd = strdup(cmd);
+ char *begin;
+ char *retval = malloc(sizeof(char *)*2);
+
+ begin = rindex(tmp_cmd, '/');
+ *begin = '\0';
+ begin++;
+ retval[1] = strdup(begin); // sensor
+
+ begin = rindex(tmp_cmd, '/');
+ *begin = '\0';
+ begin = rindex(tmp_cmd, '/');
+ begin++;
+ retval[0] = strdup(begin); // interface
+ free(tmp_cmd);
+
+ return retval;
+}
+
+/* ------------------------------ public part --------------------------- */
+
+void initNetDev(struct SensorModul* sm)
+{
+ int i;
+ char monitor[1024];
+
+ memset(NetDevs,0,sizeof(NetDevInfo)*MAXNETDEVS);
+ memset(oNetDevs,0,sizeof(NetDevInfo)*MAXNETDEVS);
+
+ updateNetDev();
+
+ for (i = 0; i < NetDevCnt; i++) {
+
+ sprintf(monitor,"network/interfaces/%s/receiver/packets", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevRecBytes, printNetDevRecBytesInfo, sm);
+ sprintf(monitor ,"network/interfaces/%s/receiver/errors", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevRecBytes, printNetDevRecBytesInfo, sm);
+ /*
+ [CK] I don't know how to get Bytes sent/received, if someone does please drop me a note.
+ sprintf(monitor,"network/interfaces/%s/receiver/data", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevRecBytes, printNetDevRecBytesInfo, sm);
+ sprintf(monitor,"network/interfaces/%s/receiver/drops", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevRecBytes, printNetDevRecBytesInfo, sm);
+ sprintf(monitor ,"network/interfaces/%s/receiver/multicast", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevRecBytes, printNetDevRecBytesInfo, sm);
+ */
+
+ sprintf(monitor,"network/interfaces/%s/transmitter/packets", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevSentBytes, printNetDevSentBytesInfo, sm);
+ sprintf(monitor,"network/interfaces/%s/transmitter/errors", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevSentBytes, printNetDevSentBytesInfo, sm);
+ /*
+ sprintf(monitor,"network/interfaces/%s/transmitter/data", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevSentBytes, printNetDevSentBytesInfo, sm);
+ sprintf(monitor,"network/interfaces/%s/transmitter/multicast", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevSentBytes, printNetDevSentBytesInfo, sm);
+ */
+ sprintf(monitor,"network/interfaces/%s/transmitter/collisions", NetDevs[i].name);
+ registerMonitor(monitor, "integer", printNetDevSentBytes, printNetDevSentBytesInfo, sm);
+ }
+}
+
+void exitNetDev(void)
+{
+ int i;
+ char monitor[1024];
+
+ for (i = 0; i < NetDevCnt; i++) {
+ sprintf(monitor,"network/interfaces/%s/receiver/packets", NetDevs[i].name);
+ removeMonitor(monitor);
+ sprintf(monitor,"network/interfaces/%s/receiver/errors", NetDevs[i].name);
+ removeMonitor(monitor);
+/*
+ sprintf(monitor,"network/interfaces/%s/receiver/drops", NetDevs[i].name);
+ removeMonitor(monitor);
+ sprintf(monitor,"network/interfaces/%s/receiver/multicast", NetDevs[i].name);
+ removeMonitor(monitor);
+ sprintf(monitor,"network/interfaces/%s/receiver/data", NetDevs[i].name);
+ removeMonitor(monitor);
+*/
+
+ sprintf(monitor,"network/interfaces/%s/transmitter/packets", NetDevs[i].name);
+ removeMonitor(monitor);
+ sprintf(monitor,"network/interfaces/%s/transmitter/errors", NetDevs[i].name);
+ removeMonitor(monitor);
+/*
+ sprintf(monitor,"network/interfaces/%s/transmitter/data", NetDevs[i].name);
+ removeMonitor(monitor);
+ sprintf(monitor,"network/interfaces/%s/transmitter/multicast", NetDevs[i].name);
+ removeMonitor(monitor);
+*/
+ sprintf(monitor,"network/interfaces/%s/transmitter/collisions", NetDevs[i].name);
+ removeMonitor(monitor);
+
+ }
+}
+
+int updateNetDev(void)
+{
+ int name[6];
+ int num_iface=0, i;
+ char buf[MAXNETDEVS*sizeof(struct ifreq)];
+ size_t len;
+ int s;
+ struct ifconf ifc;
+ struct ifstats *istat;
+ struct timeval tv;
+ static LONGLONG timestamp=0;
+ register LONGLONG cts,elapsed;
+ //struct ipstat ips;
+
+ if ((s=socket(PF_INET,SOCK_DGRAM,0)) < 0){
+ print_error("socket creation failed");
+ return(-1);
+ }
+
+ ifc.ifc_len = sizeof (buf);
+ ifc.ifc_buf = buf;
+ if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
+ print_error("cannot get interface configuration");
+ return(-1);
+ }
+
+ gettimeofday(&tv, 0);
+ cts = ((LONGLONG)tv.tv_sec * 100 + (LONGLONG) tv.tv_usec / 10000);/* in 10 ms unit*/
+ elapsed = cts - timestamp;
+ timestamp=cts;
+
+ NetDevCnt=0;
+
+ for (i = 0; i < MAXNETDEVS; i++) {
+ if ( *ifc.ifc_req[i].ifr_name == 0) break;
+ if (ioctl(s, SIOCGIFSTATS, &ifc.ifc_req[i]) < 0) {
+ print_error("cannot get interface statistics");
+ return (-1);
+ }
+ istat=&ifc.ifc_req[i].ifr_stats;
+ //if ( ifc.ifc_req[i].ifr_flags & IFF_UP) {
+ strncpy(NetDevs[i].name,ifc.ifc_req[i].ifr_name, IFNAMSIZ);
+ NetDevs[i].name[IFNAMSIZ-1]='\0';
+ NetDevs[i].recBytes = (istat->ifs_ipackets - oNetDevs[i].recBytes) * 100 / elapsed;
+ NetDevs[i].recPacks = (istat->ifs_ipackets - oNetDevs[i].recPacks) * 100 / elapsed;
+ NetDevs[i].recErrs = istat->ifs_ierrors - oNetDevs[i].recErrs;
+ //NetDevs[i].recDrop = istat - oNetDevs[i].recDrop;
+ //NetDevs[i].recMulticast = istat - oNetDevs[i].recMulticast;
+ NetDevs[i].sentBytes = istat->ifs_opackets - oNetDevs[i].sentBytes;
+ NetDevs[i].sentPacks = (istat->ifs_opackets - oNetDevs[i].sentPacks) * 100 / elapsed;
+ NetDevs[i].sentErrs = (istat->ifs_oerrors - oNetDevs[i].sentErrs) * 100 / elapsed;
+ //NetDevs[i].sentMulticast = istat - NetDevs[i].sentMulticast;
+ NetDevs[i].sentColls = (istat->ifs_collisions - oNetDevs[i].sentColls) *100/elapsed;
+ /* save it for the next round */
+ oNetDevs[i].recBytes = istat->ifs_ipackets;
+ oNetDevs[i].recPacks = istat->ifs_ipackets;
+ oNetDevs[i].recErrs = istat->ifs_ierrors;
+ //oNetDevs[i].recDrop =
+ //oNetDevs[i].recMulticast =
+ oNetDevs[i].sentBytes = istat->ifs_opackets;
+ oNetDevs[i].sentPacks = istat->ifs_opackets;
+ oNetDevs[i].sentErrs = istat->ifs_oerrors;
+ //oNetDevs[i].sentMulticast =
+ oNetDevs[i].sentColls = istat->ifs_collisions;
+ //}
+ NetDevCnt++;
+ }
+ close(s);
+ return (0);
+}
+
+void printNetDevRecBytes(const char *cmd)
+{
+ int i;
+ char **retval;
+
+ retval = parseCommand(cmd);
+
+ if (retval == NULL)
+ return;
+
+ for (i = 0; i < NetDevCnt; i++) {
+ if (!strcmp(NetDevs[i].name, retval[0])) {
+ if (!strncmp(retval[1], "data", 4))
+ fprintf(CurrentClient, "%lu", NetDevs[i].recBytes);
+ if (!strncmp(retval[1], "packets", 7))
+ fprintf(CurrentClient, "%lu", NetDevs[i].recPacks);
+ if (!strncmp(retval[1], "errors", 6))
+ fprintf(CurrentClient, "%lu", NetDevs[i].recErrs);
+ if (!strncmp(retval[1], "drops", 5))
+ fprintf(CurrentClient, "%lu", NetDevs[i].recDrop);
+ if (!strncmp(retval[1], "multicast", 9))
+ fprintf(CurrentClient, "%lu", NetDevs[i].recMulticast);
+ }
+ }
+ free(retval[0]);
+ free(retval[1]);
+ free(retval);
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printNetDevRecBytesInfo(const char *cmd)
+{
+ char **retval;
+
+ retval = parseCommand(cmd);
+
+ if (retval == NULL)
+ return;
+
+ if (!strncmp(retval[1], "data", 4))
+ fprintf(CurrentClient, "Received Data\t0\t0\tkBytes/s\n");
+ if (!strncmp(retval[1], "packets", 7))
+ fprintf(CurrentClient, "Received Packets\t0\t0\t1/s\n");
+ if (!strncmp(retval[1], "errors", 6))
+ fprintf(CurrentClient, "Receiver Errors\t0\t0\t1/s\n");
+ if (!strncmp(retval[1], "drops", 5))
+ fprintf(CurrentClient, "Receiver Drops\t0\t0\t1/s\n");
+ if (!strncmp(retval[1], "multicast", 9))
+ fprintf(CurrentClient, "Received Multicast Packets\t0\t0\t1/s\n");
+
+ free(retval[0]);
+ free(retval[1]);
+ free(retval);
+}
+
+void printNetDevSentBytes(const char *cmd)
+{
+ int i;
+ char **retval;
+
+ retval = parseCommand(cmd);
+
+ if (retval == NULL)
+ return;
+
+ for (i = 0; i < NetDevCnt; i++) {
+ if (!strcmp(NetDevs[i].name, retval[0])) {
+ if (!strncmp(retval[1], "data", 4))
+ fprintf(CurrentClient, "%lu", NetDevs[i].sentBytes);
+ if (!strncmp(retval[1], "packets", 7))
+ fprintf(CurrentClient, "%lu", NetDevs[i].sentPacks);
+ if (!strncmp(retval[1], "errors", 6))
+ fprintf(CurrentClient, "%lu", NetDevs[i].sentErrs);
+ if (!strncmp(retval[1], "multicast", 9))
+ fprintf(CurrentClient, "%lu", NetDevs[i].sentMulticast);
+ if (!strncmp(retval[1], "collisions", 10))
+ fprintf(CurrentClient, "%lu", NetDevs[i].sentColls);
+ }
+ }
+ free(retval[0]);
+ free(retval[1]);
+ free(retval);
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printNetDevSentBytesInfo(const char *cmd)
+{
+ char **retval;
+
+ retval = parseCommand(cmd);
+
+ if (retval == NULL)
+ return;
+
+ if (!strncmp(retval[1], "data", 4))
+ fprintf(CurrentClient, "Sent Data\t0\t0\tkBytes/s\n");
+ if (!strncmp(retval[1], "packets", 7))
+ fprintf(CurrentClient, "Sent Packets\t0\t0\t1/s\n");
+ if (!strncmp(retval[1], "errors", 6))
+ fprintf(CurrentClient, "Transmitter Errors\t0\t0\t1/s\n");
+ if (!strncmp(retval[1], "multicast", 9))
+ fprintf(CurrentClient, "Sent Multicast Packets\t0\t0\t1/s\n");
+ if (!strncmp(retval[1], "collisions", 10))
+ fprintf(CurrentClient, "Transmitter Collisions\t0\t0\t1/s\n");
+
+ free(retval[0]);
+ free(retval[1]);
+ free(retval);
+}
diff --git a/ksysguard/ksysguardd/Irix/NetDev.h b/ksysguard/ksysguardd/Irix/NetDev.h
new file mode 100644
index 000000000..aa30166e9
--- /dev/null
+++ b/ksysguard/ksysguardd/Irix/NetDev.h
@@ -0,0 +1,35 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+ Irix support by Carsten Kroll <ckroll@pinnaclesys.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _netdev_h_
+#define _netdev_h_
+
+void initNetDev(struct SensorModul* sm);
+void exitNetDev(void);
+
+int updateNetDev(void);
+
+void printNetDevRecBytes(const char* cmd);
+void printNetDevRecBytesInfo(const char* cmd);
+void printNetDevSentBytes(const char* cmd);
+void printNetDevSentBytesInfo(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/Irix/ProcessList.c b/ksysguard/ksysguardd/Irix/ProcessList.c
new file mode 100644
index 000000000..523d87d26
--- /dev/null
+++ b/ksysguard/ksysguardd/Irix/ProcessList.c
@@ -0,0 +1,462 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ Irix support by Carsten Kroll <ckroll@pinnaclesys.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <sys/resource.h>
+#include <sys/procfs.h>
+#include <sys/statfs.h>
+#include <sys/sysmp.h>
+#include <sys/sysinfo.h>
+
+#include "ccont.h"
+#include "../../gui/SignalIDs.h"
+#include "ksysguardd.h"
+
+#include "Command.h"
+#include "ProcessList.h"
+
+#define BUFSIZE 1024
+#define KDEINITLEN strlen("kdeinit: ")
+
+typedef struct {
+ int alive; /* for "garbage collection" */
+ pid_t pid; /* process ID */
+ pid_t ppid; /* parent process ID */
+ uid_t uid; /* process owner (real UID) */
+ gid_t gid; /* process group (real GID) */
+ char *userName; /* process owner (name) */
+ int nThreads; /* # of threads in this process */
+ int Prio; /* scheduling priority */
+ size_t Size; /* total size of process image */
+ size_t RSSize; /* resident set size */
+ char State[8]; /* process state */
+ double Time; /* CPU time for the process in 100ms */
+ double Load; /* CPU load in % */
+ char Command[PRCOMSIZ];/* command name */
+ char CmdLine[PRARGSZ];/* command line */
+ double centStamp; /* timestamp for CPU load */
+} ProcessInfo;
+
+static CONTAINER ProcessList = 0;
+static unsigned ProcessCount = 0; /* # of processes */
+static DIR *procdir; /* handle for /proc */
+static int pagesz;
+
+#define KBYTES 1024
+
+/*
+ * lwpStateName() -- return string representation of process state
+ */
+char *lwpStateName( prpsinfo_t lwpinfo ) {
+
+ static char result[8];
+
+ switch( lwpinfo.pr_sname ) {
+ case 'S':
+ sprintf( result, "%s", "sleep" );
+ break;
+ case 'R':
+ sprintf( result, "%s", "run" );
+ break;
+ case 'Z':
+ sprintf( result, "%s", "zombie" );
+ break;
+ case 'T':
+ sprintf( result, "%s", "stop" );
+ break;
+ case 'I':
+ sprintf( result, "%s", "start" );
+ break;
+ case 'X':
+ sprintf( result, "%s", "wmem" );
+ case '0':
+ sprintf( result, "%s/%d", "cpu", (int) lwpinfo.pr_sonproc );
+ break;
+ default:
+ sprintf( result, "%s", "???" );
+ break;
+ }
+
+ return( result );
+}
+
+static void validateStr( char *string ) {
+
+ char *ptr = string;
+
+ /*
+ * remove all chars that might screw up communication
+ */
+ while( *ptr != '\0' ) {
+ if( *ptr == '\t' || *ptr == '\n' || *ptr == '\r' )
+ *ptr = ' ';
+ ptr++;
+ }
+ /*
+ * make sure there's at least one char
+ */
+ if( string[0] == '\0' )
+ strcpy( string, " " );
+}
+
+static int processCmp( void *p1, void *p2 ) {
+
+ return( ((ProcessInfo *) p1)->pid - ((ProcessInfo *) p2)->pid );
+}
+
+static ProcessInfo *findProcessInList( pid_t pid ) {
+
+ ProcessInfo key;
+ long index;
+
+ key.pid = pid;
+ if( (index = search_ctnr( ProcessList, processCmp, &key )) < 0 )
+ return( NULL );
+
+ return( get_ctnr( ProcessList, index ));
+}
+
+static int updateProcess( pid_t pid ) {
+ ProcessInfo *ps;
+ int fd;
+ char buf[BUFSIZE];
+ prpsinfo_t psinfo;
+ struct passwd *pw;
+ register double newCentStamp,timeDiff, usDiff,usTime;
+ struct timeval tv;
+
+ if( (ps = findProcessInList( pid )) == NULL ) {
+ if( (ps = (ProcessInfo *) malloc( sizeof( ProcessInfo )))
+ == NULL ) {
+ print_error( "cannot malloc()\n" );
+ return( -1 );
+ }
+ ps->pid = pid;
+ ps->userName = NULL;
+ ps->alive = 0;
+
+ gettimeofday(&tv, 0);
+ ps->centStamp = (double)tv.tv_sec * 100.0 + (double)tv.tv_usec / 10000.0;
+
+ push_ctnr( ProcessList, ps );
+ bsort_ctnr( ProcessList, processCmp );
+ }
+
+ sprintf( buf, "%s/pinfo/%ld", PROCDIR, pid );
+ if( (fd = open( buf, O_RDONLY )) < 0 ) {
+ /* process terminated */
+ return( -1 );
+ }
+
+
+
+ if( ioctl(fd,PIOCPSINFO,&psinfo) < 0) {
+ print_error( "cannot read psinfo from \"%s\"\n", buf );
+ close( fd );
+ return( -1 );
+ }
+ close( fd );
+
+ ps->ppid = psinfo.pr_ppid;
+ ps->uid = psinfo.pr_uid;
+ ps->gid = psinfo.pr_gid;
+
+ pw = getpwuid( psinfo.pr_uid );
+ if( ps->userName != NULL )
+ free( ps->userName );
+ ps->userName = strdup( pw->pw_name );
+
+ strncpy (ps->State,lwpStateName( psinfo ),8);
+ ps->State[7]='\0';
+
+
+ ps->Prio = psinfo.pr_pri;
+
+ gettimeofday(&tv, 0);
+ newCentStamp = (double)tv.tv_sec * 100.0 + (double) tv.tv_usec / 10000.0;
+ usTime = (double) psinfo.pr_time.tv_sec * 100.0 + (double)psinfo.pr_time.tv_nsec / 10000000.0;
+
+ timeDiff = newCentStamp - ps->centStamp;
+ usDiff = usTime - ps->Time;
+
+ if ((timeDiff > 0.0) && (usDiff >= 0.0))
+ {
+ ps->Load = (usDiff / timeDiff) * 100.0;
+ /* During startup we get bigger loads since the time diff
+ * cannot be correct. So we force it to 0. */
+ ps->Load = (ps->Load > 100.0) ? 0.0 : ps->Load;
+ }
+ else
+ ps->Load = 0.0;
+
+ ps->centStamp = newCentStamp;
+ ps->Time = usTime;
+
+ ps->Size = (psinfo.pr_size * pagesz)/KBYTES;
+ ps->RSSize = (psinfo.pr_rssize * pagesz)/KBYTES;
+
+ strncpy(ps->Command,psinfo.pr_fname,PRCOMSIZ);
+ ps->Command[PRCOMSIZ-1]='\0';
+
+ strncpy(ps->CmdLine,psinfo.pr_psargs,PRARGSZ);
+ ps->CmdLine[PRARGSZ-1]='\0';
+
+ validateStr( ps->Command );
+ validateStr( ps->CmdLine );
+
+ ps->alive = 1;
+ return( 0 );
+}
+
+static void cleanupProcessList( void ) {
+
+ ProcessInfo *ps;
+
+ ProcessCount = 0;
+ for( ps = first_ctnr( ProcessList ); ps; ps = next_ctnr( ProcessList )) {
+ if( ps->alive ) {
+ ps->alive = 0;
+ ProcessCount++;
+ } else {
+ free( remove_ctnr( ProcessList ));
+ }
+ }
+}
+
+void initProcessList( struct SensorModul* sm ) {
+
+ if( (procdir = opendir( PROCDIR )) == NULL ) {
+ print_error( "cannot open \"%s\" for reading\n", PROCDIR );
+ return;
+ }
+ pagesz=getpagesize();
+ ProcessList = new_ctnr();
+ updateProcessList();
+
+ /*
+ * register the supported monitors & commands
+ */
+ registerMonitor( "pscount", "integer",
+ printProcessCount, printProcessCountInfo, sm );
+ registerMonitor( "ps", "table",
+ printProcessList, printProcessListInfo, sm );
+
+ if (!RunAsDaemon)
+ {
+ registerCommand("kill", killProcess);
+ registerCommand("setpriority", setPriority);
+ }
+}
+
+void exitProcessList( void ) {
+
+ removeMonitor("ps");
+ removeMonitor("pscount");
+
+ if (!RunAsDaemon)
+ {
+ removeCommand("kill");
+ removeCommand("setpriority");
+ }
+
+ destr_ctnr( ProcessList, free );
+}
+
+int updateProcessList( void ) {
+
+ struct dirent *de;
+ struct statfs sf;
+
+ statfs("/proc/pinfo",&sf,sizeof(sf),0);
+ ProcessCount = sf.f_files;
+
+ rewinddir( procdir );
+ while( (de = readdir( procdir )) != NULL ) {
+ /*
+ * skip '.' and '..'
+ */
+ if( de->d_name[0] == '.' )
+ continue;
+
+ /*
+ * fetch the process info and insert it into the info table
+ */
+ updateProcess( (pid_t) atol( de->d_name ));
+ }
+ cleanupProcessList();
+
+ return( 0 );
+}
+
+void printProcessListInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Name\tPID\tPPID\tGID\tStatus\tUser"
+ "\tSize\tResident\t%% CPU\tPriority\tCommand\n" );
+ fprintf(CurrentClient, "s\td\td\td\ts\ts\tD\tD\tf\td\ts\n" );
+}
+
+void printProcessList( const char *cmd ) {
+
+ ProcessInfo *ps;
+
+ for( ps = first_ctnr( ProcessList ); ps; ps = next_ctnr( ProcessList )) {
+ fprintf(CurrentClient,
+ "%s\t%ld\t%ld\t%ld\t%s\t%s\t%d\t%d\t%.2f\t%d\t%s\n",
+ ps->Command,
+ (long) ps->pid,
+ (long) ps->ppid,
+ (long) ps->gid,
+ ps->State,
+ ps->userName,
+ ps->Size,
+ ps->RSSize,
+ ps->Load,
+ ps->Prio,
+ ps->CmdLine);
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printProcessCount( const char *cmd ) {
+ fprintf(CurrentClient, "%d\n", ProcessCount );
+}
+
+void printProcessCountInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Number of Processes\t0\t0\t\n" );
+}
+
+void killProcess( const char *cmd ) {
+
+ int sig, pid;
+
+ sscanf( cmd, "%*s %d %d", &pid, &sig );
+
+ switch( sig ) {
+ case MENU_ID_SIGABRT:
+ sig = SIGABRT;
+ break;
+ case MENU_ID_SIGALRM:
+ sig = SIGALRM;
+ break;
+ case MENU_ID_SIGCHLD:
+ sig = SIGCHLD;
+ break;
+ case MENU_ID_SIGCONT:
+ sig = SIGCONT;
+ break;
+ case MENU_ID_SIGFPE:
+ sig = SIGFPE;
+ break;
+ case MENU_ID_SIGHUP:
+ sig = SIGHUP;
+ break;
+ case MENU_ID_SIGILL:
+ sig = SIGILL;
+ break;
+ case MENU_ID_SIGINT:
+ sig = SIGINT;
+ break;
+ case MENU_ID_SIGKILL:
+ sig = SIGKILL;
+ break;
+ case MENU_ID_SIGPIPE:
+ sig = SIGPIPE;
+ break;
+ case MENU_ID_SIGQUIT:
+ sig = SIGQUIT;
+ break;
+ case MENU_ID_SIGSEGV:
+ sig = SIGSEGV;
+ break;
+ case MENU_ID_SIGSTOP:
+ sig = SIGSTOP;
+ break;
+ case MENU_ID_SIGTERM:
+ sig = SIGTERM;
+ break;
+ case MENU_ID_SIGTSTP:
+ sig = SIGTSTP;
+ break;
+ case MENU_ID_SIGTTIN:
+ sig = SIGTTIN;
+ break;
+ case MENU_ID_SIGTTOU:
+ sig = SIGTTOU;
+ break;
+ case MENU_ID_SIGUSR1:
+ sig = SIGUSR1;
+ break;
+ case MENU_ID_SIGUSR2:
+ sig = SIGUSR2;
+ break;
+ }
+ if( kill( (pid_t) pid, sig )) {
+ switch( errno ) {
+ case EINVAL:
+ fprintf(CurrentClient, "4\n" );
+ break;
+ case ESRCH:
+ fprintf(CurrentClient, "3\n" );
+ break;
+ case EPERM:
+ fprintf(CurrentClient, "2\n" );
+ break;
+ default:
+ fprintf(CurrentClient, "1\n" ); /* unknown error */
+ break;
+ }
+ } else
+ fprintf(CurrentClient, "0\n");
+}
+
+void setPriority( const char *cmd ) {
+ int pid, prio;
+
+ sscanf( cmd, "%*s %d %d", &pid, &prio );
+ if( setpriority( PRIO_PROCESS, pid, prio )) {
+ switch( errno ) {
+ case EINVAL:
+ fprintf(CurrentClient, "4\n" );
+ break;
+ case ESRCH:
+ fprintf(CurrentClient, "3\n" );
+ break;
+ case EPERM:
+ case EACCES:
+ fprintf(CurrentClient, "2\n" );
+ break;
+ default:
+ fprintf(CurrentClient, "1\n" ); /* unknown error */
+ break;
+ }
+ } else
+ fprintf(CurrentClient, "0\n");
+}
diff --git a/ksysguard/ksysguardd/Irix/ProcessList.h b/ksysguard/ksysguardd/Irix/ProcessList.h
new file mode 100644
index 000000000..5d949279e
--- /dev/null
+++ b/ksysguard/ksysguardd/Irix/ProcessList.h
@@ -0,0 +1,43 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ Irix support by Carsten Kroll <ckroll@pinnaclesys.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _ProcessList_H_
+#define _ProcessList_H_
+
+#define PROCDIR "/proc"
+
+void initProcessList(struct SensorModul* sm);
+void exitProcessList(void);
+
+int updateProcessList(void);
+
+void printProcessList(const char*);
+void printProcessListInfo(const char*);
+
+void printProcessCount(const char* cmd);
+void printProcessCountInfo(const char* cmd);
+
+void killProcess(const char* cmd);
+void setPriority(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/Irix/cpu.c b/ksysguard/ksysguardd/Irix/cpu.c
new file mode 100644
index 000000000..9fdd25ab7
--- /dev/null
+++ b/ksysguard/ksysguardd/Irix/cpu.c
@@ -0,0 +1,262 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ Irix support by Carsten Kroll <ckroll@pinnaclesys.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/sysmp.h>
+#include <sys/sysinfo.h>
+
+#include "cpu.h"
+#include "Command.h"
+#include "ksysguardd.h"
+
+#define CPUSTATES 6
+
+long percentages(int cnt, int *out, long *new, long *old, long *diffs);
+
+static int nCPUs=0;
+
+
+long cp_time[CPUSTATES];
+long cp_old[CPUSTATES];
+long cp_diff[CPUSTATES];
+int cpu_states[CPUSTATES];
+
+struct cpu_info{
+ long cp_time[CPUSTATES];
+ long cp_old[CPUSTATES];
+ long cp_diff[CPUSTATES];
+ int cpu_states[CPUSTATES];
+};
+
+static struct cpu_info *g_ci;
+
+/* returns the requested cpu number starting at 0*/
+int getID(const char *cmd){
+ int id;
+ sscanf(cmd + 7, "%d", &id);
+ return id-1;
+}
+
+void
+initCpuInfo(struct SensorModul* sm)
+{
+ char mname[50];
+ int i;
+ if (sysmp(MP_NPROCS,&nCPUs) < 0) nCPUs=0;
+ nCPUs++;
+ g_ci = malloc(sizeof(struct cpu_info) * nCPUs);
+ memset(g_ci,0,sizeof(struct cpu_info) * nCPUs);
+
+ registerMonitor("cpu/user", "integer", printCPUUser,
+ printCPUUserInfo, sm);
+ registerMonitor("cpu/sys", "integer", printCPUSys,
+ printCPUSysInfo, sm);
+ registerMonitor("cpu/idle", "integer", printCPUIdle,
+ printCPUIdleInfo, sm);
+
+ if (nCPUs > 1) for (i=0;i<nCPUs;i++){
+ /* indidividual CPU load */
+ sprintf(mname,"cpu/cpu%d/user",i+1);
+ registerMonitor(mname, "integer", printCPUxUser,
+ printCPUUserInfo, sm);
+ sprintf(mname,"cpu/cpu%d/sys",i+1);
+ registerMonitor(mname, "integer", printCPUxSys,
+ printCPUSysInfo, sm);
+ sprintf(mname,"cpu/cpu%d/idle",i+1);
+ registerMonitor(mname, "integer", printCPUxIdle,
+ printCPUIdleInfo, sm);
+ }
+
+ updateCpuInfo();
+}
+
+void
+exitCpuInfo(void)
+{
+ free(g_ci);
+}
+
+int
+updateCpuInfo(void)
+{
+ struct sysinfo si;
+ int rv=0;
+ int i;
+ /* overall summary */
+ if (sysmp(MP_SAGET,MPSA_SINFO,&si,sizeof(struct sysinfo)) >=0){
+ cp_time[CPU_IDLE] =si.cpu[CPU_IDLE];
+ cp_time[CPU_USER] =si.cpu[CPU_USER];
+ cp_time[CPU_KERNEL]=si.cpu[CPU_KERNEL];
+ cp_time[CPU_SXBRK] =si.cpu[CPU_SXBRK];
+ cp_time[CPU_INTR] =si.cpu[CPU_INTR];
+ cp_time[CPU_WAIT] =si.cpu[CPU_WAIT];
+ percentages(CPUSTATES,cpu_states,cp_time,cp_old,cp_diff);
+ }
+ /* individual CPU statistics*/
+ if (nCPUs > 1) for (i=0;i<nCPUs;i++){
+ if (sysmp(MP_SAGET1,MPSA_SINFO,&si,sizeof(struct sysinfo),i) >=0){
+ g_ci[i].cp_time[CPU_IDLE] =si.cpu[CPU_IDLE];
+ g_ci[i].cp_time[CPU_USER] =si.cpu[CPU_USER];
+ g_ci[i].cp_time[CPU_KERNEL]=si.cpu[CPU_KERNEL];
+ g_ci[i].cp_time[CPU_SXBRK] =si.cpu[CPU_SXBRK];
+ g_ci[i].cp_time[CPU_INTR] =si.cpu[CPU_INTR];
+ g_ci[i].cp_time[CPU_WAIT] =si.cpu[CPU_WAIT];
+ percentages(CPUSTATES, g_ci[i].cpu_states, g_ci[i].cp_time, g_ci[i].cp_old,g_ci[i].cp_diff);
+ }else{
+ rv =-1;
+ }
+ }
+ return (rv);
+}
+
+void
+printCPUUser(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CPU_USER]/10);
+}
+
+void
+printCPUUserInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU User Load\t0\t100\t%%\n");
+}
+
+void
+printCPUSys(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CPU_KERNEL]/10);
+}
+
+void
+printCPUSysInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU System Load\t0\t100\t%%\n");
+}
+
+void
+printCPUIdle(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CPU_IDLE]/10);
+}
+
+void
+printCPUIdleInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU Idle Load\t0\t100\t%%\n");
+}
+/* same as above but for individual CPUs */
+void
+printCPUxUser(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", g_ci[getID(cmd)].cpu_states[CPU_USER]/10);
+}
+
+void
+printCPUxSys(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", g_ci[getID(cmd)].cpu_states[CPU_KERNEL]/10);
+}
+
+void
+printCPUxIdle(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", g_ci[getID(cmd)].cpu_states[CPU_IDLE]/10);
+}
+
+
+/* The part ripped from top... */
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ */
+
+/*
+ * percentages(cnt, out, new, old, diffs) - calculate percentage change
+ * between array "old" and "new", putting the percentages in "out".
+ * "cnt" is size of each array and "diffs" is used for scratch space.
+ * The array "old" is updated on each call.
+ * The routine assumes modulo arithmetic. This function is especially
+ * useful on BSD mchines for calculating cpu state percentages.
+ */
+
+long percentages(cnt, out, new, old, diffs)
+
+int cnt;
+int *out;
+register long *new;
+register long *old;
+long *diffs;
+
+{
+ register int i;
+ register long change;
+ register long total_change;
+ register long *dp;
+ long half_total;
+
+ /* initialization */
+ total_change = 0;
+ dp = diffs;
+
+ /* calculate changes for each state and the overall change */
+ for (i = 0; i < cnt; i++)
+ {
+ if ((change = *new - *old) < 0)
+ {
+ /* this only happens when the counter wraps */
+ change = (int)
+ ((unsigned long)*new-(unsigned long)*old);
+ }
+ total_change += (*dp++ = change);
+ *old++ = *new++;
+ }
+
+ /* avoid divide by zero potential */
+ if (total_change == 0)
+ {
+ total_change = 1;
+ }
+
+ /* calculate percentages based on overall change, rounding up */
+ half_total = total_change / 2l;
+
+ /* Do not divide by 0. Causes Floating point exception */
+ if(total_change) {
+ for (i = 0; i < cnt; i++)
+ {
+ *out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
+ }
+ }
+
+ /* return the total in case the caller wants to use it */
+ return(total_change);
+}
diff --git a/ksysguard/ksysguardd/Irix/cpu.h b/ksysguard/ksysguardd/Irix/cpu.h
new file mode 100644
index 000000000..f61d12505
--- /dev/null
+++ b/ksysguard/ksysguardd/Irix/cpu.h
@@ -0,0 +1,43 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _cpuinfo_h_
+#define _cpuinfo_h_
+
+void initCpuInfo(struct SensorModul* sm);
+void exitCpuInfo(void);
+
+int updateCpuInfo(void);
+
+void printCPUUser(const char* cmd);
+void printCPUUserInfo(const char* cmd);
+void printCPUSys(const char* cmd);
+void printCPUSysInfo(const char* cmd);
+void printCPUIdle(const char* cmd);
+void printCPUIdleInfo(const char* cmd);
+void printCPUxUser(const char* cmd);
+void printCPUxUserInfo(const char* cmd);
+void printCPUxSys(const char* cmd);
+void printCPUxSysInfo(const char* cmd);
+void printCPUxIdle(const char* cmd);
+void printCPUxIdleInfo(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/Linux/Makefile.am b/ksysguard/ksysguardd/Linux/Makefile.am
new file mode 100644
index 000000000..928b4b66a
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/Makefile.am
@@ -0,0 +1,14 @@
+AM_CPPFLAGS = -D_GNU_SOURCE
+AM_CFLAGS = -Wall
+
+# add all supported modules
+if supports_i8k
+KSGRD_SUPPORTS = -DHAVE_I8K_SUPPORT
+endif
+
+
+INCLUDES = -I$(srcdir)/../../CContLib -I$(srcdir)/.. $(KSGRD_SUPPORTS) $(all_includes)
+
+noinst_LIBRARIES = libksysguardd.a
+libksysguardd_a_SOURCES = ProcessList.c Memory.c stat.c netdev.c apm.c acpi.c \
+ loadavg.c cpuinfo.c lmsensors.c netstat.c diskstat.c logfile.c i8k.c
diff --git a/ksysguard/ksysguardd/Linux/Memory.c b/ksysguard/ksysguardd/Linux/Memory.c
new file mode 100644
index 000000000..93c8d9edb
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/Memory.c
@@ -0,0 +1,293 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "Command.h"
+#include "ksysguardd.h"
+
+#include "Memory.h"
+
+#define MEMINFOBUFSIZE (2 * 1024)
+
+static char MemInfoBuf[ MEMINFOBUFSIZE ];
+static int Dirty = 1;
+
+static unsigned long Total = 0;
+static unsigned long MFree = 0;
+static unsigned long Appl = 0;
+static unsigned long Used = 0;
+static unsigned long Buffers = 0;
+static unsigned long Cached = 0;
+static unsigned long STotal = 0;
+static unsigned long SFree = 0;
+static unsigned long SUsed = 0;
+
+static void scan_one( const char* buff, const char *key, unsigned long int* val )
+{
+ int o;
+ char *b = strstr( buff, key );
+ if ( b )
+ o = sscanf( b + strlen( key ), ": %lu", val );
+}
+
+static void processMemInfo()
+{
+ scan_one( MemInfoBuf, "MemTotal", &Total );
+ scan_one( MemInfoBuf, "MemFree", &MFree );
+ scan_one( MemInfoBuf, "Buffers", &Buffers );
+ scan_one( MemInfoBuf, "Cached", &Cached );
+ scan_one( MemInfoBuf, "SwapTotal", &STotal );
+ scan_one( MemInfoBuf, "SwapFree", &SFree );
+ Used = Total - MFree;
+ Appl = ( Used - ( Buffers + Cached ) );
+
+ if ( STotal == 0 ) /* no swap activated */
+ SUsed = 0;
+ else
+ SUsed = STotal - SFree;
+
+ Dirty = 0;
+}
+
+/*
+================================ public part =================================
+*/
+
+void initMemory( struct SensorModul* sm )
+{
+ /**
+ Make sure that /proc/meminfo exists and is readable. If not we do
+ not register any monitors for memory.
+ */
+ if ( updateMemory() < 0 )
+ return;
+
+ registerMonitor( "mem/physical/free", "integer", printMFree, printMFreeInfo, sm );
+ registerMonitor( "mem/physical/used", "integer", printUsed, printUsedInfo, sm );
+ registerMonitor( "mem/physical/application", "integer", printAppl, printApplInfo, sm );
+ registerMonitor( "mem/physical/buf", "integer", printBuffers, printBuffersInfo, sm );
+ registerMonitor( "mem/physical/cached", "integer", printCached, printCachedInfo, sm );
+ registerMonitor( "mem/swap/used", "integer", printSwapUsed, printSwapUsedInfo, sm );
+ registerMonitor( "mem/swap/free", "integer", printSwapFree, printSwapFreeInfo, sm );
+}
+
+void exitMemory( void )
+{
+}
+
+int updateMemory( void )
+{
+ /**
+ The amount of total and used memory is read from the /proc/meminfo.
+ It also contains the information about the swap space.
+ The 'file' looks like this:
+
+ MemTotal: 516560 kB
+ MemFree: 7812 kB
+ MemShared: 0 kB
+ Buffers: 80312 kB
+ Cached: 236432 kB
+ SwapCached: 468 kB
+ Active: 291992 kB
+ Inactive: 133556 kB
+ HighTotal: 0 kB
+ HighFree: 0 kB
+ LowTotal: 516560 kB
+ LowFree: 7812 kB
+ SwapTotal: 899632 kB
+ SwapFree: 898932 kB
+ Dirty: 2736 kB
+ Writeback: 0 kB
+ Mapped: 155996 kB
+ Slab: 73920 kB
+ Committed_AS: 315588 kB
+ PageTables: 1764 kB
+ ReverseMaps: 103458
+ */
+
+ int fd;
+ size_t n;
+
+ if ( ( fd = open( "/proc/meminfo", O_RDONLY ) ) < 0 ) {
+ print_error( "Cannot open \'/proc/meminfo\'!\n"
+ "The kernel needs to be compiled with support\n"
+ "for /proc filesystem enabled!\n" );
+ return -1;
+ }
+
+ if ( ( n = read( fd, MemInfoBuf, MEMINFOBUFSIZE - 1 ) ) == MEMINFOBUFSIZE - 1 ) {
+ log_error( "Internal buffer too small to read \'/proc/mem\'" );
+ close( fd );
+ return -1;
+ }
+
+ close( fd );
+ MemInfoBuf[ n ] = '\0';
+ Dirty = 1;
+
+ return 0;
+}
+
+void printMFree( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processMemInfo();
+
+ fprintf( CurrentClient, "%ld\n", MFree );
+}
+
+void printMFreeInfo( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processMemInfo();
+
+ fprintf( CurrentClient, "Free Memory\t0\t%ld\tKB\n", Total );
+}
+
+void printUsed( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processMemInfo();
+
+ fprintf( CurrentClient, "%ld\n", Used );
+}
+
+void printUsedInfo( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processMemInfo();
+
+ fprintf( CurrentClient, "Used Memory\t0\t%ld\tKB\n", Total );
+}
+
+void printAppl( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processMemInfo();
+
+ fprintf( CurrentClient, "%ld\n", Appl );
+}
+
+void printApplInfo( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processMemInfo();
+
+ fprintf( CurrentClient, "Application Memory\t0\t%ld\tKB\n", Total );
+}
+
+void printBuffers( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processMemInfo();
+
+ fprintf( CurrentClient, "%ld\n", Buffers );
+}
+
+void printBuffersInfo( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processMemInfo();
+
+ fprintf( CurrentClient, "Buffer Memory\t0\t%ld\tKB\n", Total );
+}
+
+void printCached( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processMemInfo();
+
+ fprintf( CurrentClient, "%ld\n", Cached );
+}
+
+void printCachedInfo( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processMemInfo();
+
+ fprintf( CurrentClient, "Cached Memory\t0\t%ld\tKB\n", Total );
+}
+
+void printSwapUsed( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processMemInfo();
+
+ fprintf( CurrentClient, "%ld\n", SUsed );
+}
+
+void printSwapUsedInfo( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processMemInfo();
+
+ fprintf( CurrentClient, "Used Swap Memory\t0\t%ld\tKB\n", STotal );
+}
+
+void printSwapFree( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processMemInfo();
+
+ fprintf( CurrentClient, "%ld\n", SFree );
+}
+
+void printSwapFreeInfo( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processMemInfo();
+
+ fprintf( CurrentClient, "Free Swap Memory\t0\t%ld\tKB\n", STotal );
+}
diff --git a/ksysguard/ksysguardd/Linux/Memory.h b/ksysguard/ksysguardd/Linux/Memory.h
new file mode 100644
index 000000000..2dbd6f2dc
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/Memory.h
@@ -0,0 +1,45 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_MEMORY_H
+#define KSG_MEMORY_H
+
+void initMemory( struct SensorModul* );
+void exitMemory( void );
+
+int updateMemory( void );
+
+void printMFree( const char* );
+void printMFreeInfo( const char* );
+void printUsed( const char* );
+void printUsedInfo( const char* );
+void printAppl( const char* );
+void printApplInfo( const char* );
+void printBuffers( const char* );
+void printBuffersInfo( const char* );
+void printCached( const char* );
+void printCachedInfo( const char* );
+void printSwapUsed( const char* );
+void printSwapUsedInfo( const char* );
+void printSwapFree( const char* );
+void printSwapFreeInfo( const char* );
+
+#endif
diff --git a/ksysguard/ksysguardd/Linux/ProcessList.c b/ksysguard/ksysguardd/Linux/ProcessList.c
new file mode 100644
index 000000000..b267c7005
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/ProcessList.c
@@ -0,0 +1,554 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "../../gui/SignalIDs.h"
+#include "Command.h"
+#include "PWUIDCache.h"
+#include "ccont.h"
+#include "ksysguardd.h"
+
+#include "ProcessList.h"
+
+#define BUFSIZE 1024
+#define TAGSIZE 32
+#define KDEINITLEN strlen( "kdeinit: " )
+
+static CONTAINER ProcessList = 0;
+
+typedef struct {
+ /**
+ This flag is set for all found processes at the beginning of the
+ process list update. Processes that do not have this flag set will
+ be assumed dead and removed from the list. The flag is cleared after
+ each list update.
+ */
+ int alive;
+
+ /* The process ID */
+ pid_t pid;
+
+ /* The parent process ID */
+ pid_t ppid;
+
+ /* The real user ID */
+ uid_t uid;
+
+ /* The real group ID */
+ gid_t gid;
+
+ /* A character description of the process status */
+ char status[ 16 ];
+
+ /* The number of the tty the process owns */
+ int ttyNo;
+
+ /**
+ The nice level. The range should be -20 to 20. I'm not sure
+ whether this is true for all platforms.
+ */
+ int niceLevel;
+
+ /* The scheduling priority. */
+ int priority;
+
+ /**
+ The total amount of memory the process uses. This includes shared and
+ swapped memory.
+ */
+ unsigned int vmSize;
+
+ /* The amount of physical memory the process currently uses. */
+ unsigned int vmRss;
+
+ /**
+ The number of 1/100 of a second the process has spend in user space.
+ If a machine has an uptime of 1 1/2 years or longer this is not a
+ good idea. I never thought that the stability of UNIX could get me
+ into trouble! ;)
+ */
+ unsigned int userTime;
+
+ /**
+ The number of 1/100 of a second the process has spend in system space.
+ If a machine has an uptime of 1 1/2 years or longer this is not a
+ good idea. I never thought that the stability of UNIX could get me
+ into trouble! ;)
+ */
+ unsigned int sysTime;
+
+ /* The system time as multime of 100ms */
+ int centStamp;
+
+ /* The current CPU load (in %) from user space */
+ double userLoad;
+
+ /* The current CPU load (in %) from system space */
+ double sysLoad;
+
+ /* The name of the process */
+ char name[ 64 ];
+
+ /* The command used to start the process */
+ char cmdline[ 256 ];
+
+ /* The login name of the user that owns this process */
+ char userName[ 32 ];
+} ProcessInfo;
+
+static unsigned ProcessCount;
+
+static void validateStr( char* str )
+{
+ char* s = str;
+
+ /* All characters that could screw up the communication will be removed. */
+ while ( *s ) {
+ if ( *s == '\t' || *s == '\n' || *s == '\r' )
+ *s = ' ';
+ ++s;
+ }
+
+ /* Make sure that string contains at least one character (blank). */
+ if ( str[ 0 ] == '\0' )
+ strcpy( str, " " );
+}
+
+static int processCmp( void* p1, void* p2 )
+{
+ return ( ((ProcessInfo*)p1)->pid - ((ProcessInfo*)p2)->pid );
+}
+
+static ProcessInfo* findProcessInList( int pid )
+{
+ ProcessInfo key;
+ long idx;
+
+ key.pid = pid;
+ if ( ( idx = search_ctnr( ProcessList, processCmp, &key ) ) < 0 )
+ return 0;
+
+ return get_ctnr( ProcessList, idx );
+}
+
+static int updateProcess( int pid )
+{
+ ProcessInfo* ps;
+ FILE* fd;
+ char buf[ BUFSIZE ];
+ char tag[ TAGSIZE ];
+ char format[ 32 ];
+ char tagformat[ 32 ];
+ int userTime, sysTime;
+ const char* uName;
+ char status;
+
+ if ( ( ps = findProcessInList( pid ) ) == 0 ) {
+ struct timeval tv;
+
+ ps = (ProcessInfo*)malloc( sizeof( ProcessInfo ) );
+ ps->pid = pid;
+ ps->alive = 0;
+
+ gettimeofday( &tv, 0 );
+ ps->centStamp = tv.tv_sec * 100 + tv.tv_usec / 10000;
+
+ push_ctnr( ProcessList, ps );
+ bsort_ctnr( ProcessList, processCmp );
+ }
+
+ snprintf( buf, BUFSIZE - 1, "/proc/%d/status", pid );
+ if ( ( fd = fopen( buf, "r" ) ) == 0 ) {
+ /* process has terminated in the mean time */
+ return -1;
+ }
+
+ sprintf( format, "%%%d[^\n]\n", (int)sizeof( buf ) - 1 );
+ sprintf( tagformat, "%%%ds", (int)sizeof( tag ) - 1 );
+ for ( ;; ) {
+ if ( fscanf( fd, format, buf ) != 1 )
+ break;
+ buf[ sizeof( buf ) - 1 ] = '\0';
+ sscanf( buf, tagformat, tag );
+ tag[ sizeof( tag ) - 1 ] = '\0';
+ if ( strcmp( tag, "Name:" ) == 0 ) {
+ sscanf( buf, "%*s %63s", ps->name );
+ validateStr( ps->name );
+ } else if ( strcmp( tag, "Uid:" ) == 0 )
+ sscanf( buf, "%*s %d %*d %*d %*d", (int*)&ps->uid );
+ }
+
+ if ( fclose( fd ) )
+ return -1;
+
+ snprintf( buf, BUFSIZE - 1, "/proc/%d/stat", pid );
+ buf[ BUFSIZE - 1 ] = '\0';
+ if ( ( fd = fopen( buf, "r" ) ) == 0 )
+ return -1;
+
+ if ( fscanf( fd, "%*d %*s %c %d %d %*d %d %*d %*u %*u %*u %*u %*u %d %d"
+ "%*d %*d %*d %d %*u %*u %*d %u %u",
+ &status, (int*)&ps->ppid, (int*)&ps->gid, &ps->ttyNo,
+ &userTime, &sysTime, &ps->niceLevel, &ps->vmSize,
+ &ps->vmRss) != 9 ) {
+ fclose( fd );
+ return -1;
+ }
+
+ if ( fclose( fd ) )
+ return -1;
+
+ /* status decoding as taken from fs/proc/array.c */
+ if ( status == 'R' )
+ strcpy( ps->status, "running" );
+ else if ( status == 'S' )
+ strcpy( ps->status, "sleeping" );
+ else if ( status == 'D' )
+ strcpy( ps->status, "disk sleep" );
+ else if ( status == 'Z' )
+ strcpy( ps->status, "zombie" );
+ else if ( status == 'T' )
+ strcpy( ps->status, "stopped" );
+ else if ( status == 'W' )
+ strcpy( ps->status, "paging" );
+ else
+ sprintf( ps->status, "Unknown: %c", status );
+
+ ps->vmRss = ( ps->vmRss + 3 ) * sysconf(_SC_PAGESIZE);
+
+ {
+ int newCentStamp;
+ int timeDiff, userDiff, sysDiff;
+ struct timeval tv;
+
+ gettimeofday( &tv, 0 );
+ newCentStamp = tv.tv_sec * 100 + tv.tv_usec / 10000;
+
+ timeDiff = newCentStamp - ps->centStamp;
+ userDiff = userTime - ps->userTime;
+ sysDiff = sysTime - ps->sysTime;
+
+ if ( ( timeDiff > 0 ) && ( userDiff >= 0 ) && ( sysDiff >= 0 ) ) {
+ ps->userLoad = ( (double)userDiff / timeDiff ) * 100.0;
+ ps->sysLoad = ( (double)sysDiff / timeDiff ) * 100.0;
+ /**
+ During startup we get bigger loads since the time diff
+ cannot be correct. So we force it to 0.
+ */
+ if ( ps->userLoad > 100.0 )
+ ps->userLoad = 0.0;
+ if ( ps->sysLoad > 100.0 )
+ ps->sysLoad = 0.0;
+ } else
+ ps->sysLoad = ps->userLoad = 0.0;
+
+ ps->centStamp = newCentStamp;
+ ps->userTime = userTime;
+ ps->sysTime = sysTime;
+ }
+
+ snprintf( buf, BUFSIZE - 1, "/proc/%d/cmdline", pid );
+ if ( ( fd = fopen( buf, "r" ) ) == 0 )
+ return -1;
+
+ ps->cmdline[ 0 ] = '\0';
+ sprintf( buf, "%%%d[^\n]", (int)sizeof( ps->cmdline ) - 1 );
+ fscanf( fd, buf, ps->cmdline );
+ ps->cmdline[ sizeof( ps->cmdline ) - 1 ] = '\0';
+ validateStr( ps->cmdline );
+ if ( fclose( fd ) )
+ return -1;
+
+ /* Ugly hack to "fix" program name for kdeinit launched programs. */
+ if ( strcmp( ps->name, "kdeinit" ) == 0 &&
+ strncmp( ps->cmdline, "kdeinit: ", KDEINITLEN ) == 0 &&
+ strcmp( ps->cmdline + KDEINITLEN, "Running..." ) != 0 ) {
+ size_t len;
+ char* end = strchr( ps->cmdline + KDEINITLEN, ' ' );
+ if ( end )
+ len = ( end - ps->cmdline ) - KDEINITLEN;
+ else
+ len = strlen( ps->cmdline + KDEINITLEN );
+ if ( len > 0 ) {
+ if ( len > sizeof( ps->name ) - 1 )
+ len = sizeof( ps->name ) - 1;
+ strncpy( ps->name, ps->cmdline + KDEINITLEN, len );
+ ps->name[ len ] = '\0';
+ }
+ }
+
+ /* find out user name with the process uid */
+ uName = getCachedPWUID( ps->uid );
+ strncpy( ps->userName, uName, sizeof( ps->userName ) - 1 );
+ ps->userName[ sizeof( ps->userName ) - 1 ] = '\0';
+ validateStr( ps->userName );
+
+ ps->alive = 1;
+
+ return 0;
+}
+
+static void cleanupProcessList( void )
+{
+ ProcessInfo* ps;
+
+ ProcessCount = 0;
+ /**
+ All processes that do not have the active flag set are assumed dead
+ and will be removed from the list. The alive flag is cleared.
+ */
+ for ( ps = first_ctnr( ProcessList ); ps; ps = next_ctnr( ProcessList ) ) {
+ if ( ps->alive ) {
+ /* Process is still alive. Just clear flag. */
+ ps->alive = 0;
+ ProcessCount++;
+ } else {
+ /**
+ Process has probably died. We remove it from the list and
+ destruct the data structure. i needs to be decremented so
+ that after i++ the next list element will be inspected.
+ */
+ free( remove_ctnr( ProcessList ) );
+ }
+ }
+}
+
+int updateProcessList( void )
+{
+ DIR* dir;
+ struct dirent* entry;
+
+ /* read in current process list via the /proc filesystem entry */
+ if ( ( dir = opendir( "/proc" ) ) == NULL ) {
+ print_error( "Cannot open directory \'/proc\'!\n"
+ "The kernel needs to be compiled with support\n"
+ "for /proc filesystem enabled!\n" );
+ return 0;
+ }
+
+ while ( ( entry = readdir( dir ) ) ) {
+ if ( isdigit( entry->d_name[ 0 ] ) ) {
+ int pid;
+
+ pid = atoi( entry->d_name );
+ updateProcess( pid );
+ }
+ }
+ closedir( dir );
+
+ cleanupProcessList();
+ return 0;
+}
+
+/*
+================================ public part =================================
+*/
+
+void initProcessList( struct SensorModul* sm )
+{
+ initPWUIDCache();
+
+ ProcessList = new_ctnr();
+
+ registerMonitor( "pscount", "integer", printProcessCount, printProcessCountInfo, sm );
+ registerMonitor( "ps", "table", printProcessList, printProcessListInfo, sm );
+
+ if ( !RunAsDaemon ) {
+ registerCommand( "kill", killProcess );
+ registerCommand( "setpriority", setPriority );
+ }
+
+ updateProcessList();
+}
+
+void exitProcessList( void )
+{
+ removeMonitor( "ps" );
+ removeMonitor( "pscount" );
+
+ if ( !RunAsDaemon ) {
+ removeCommand( "kill" );
+ removeCommand( "setpriority" );
+ }
+
+ destr_ctnr( ProcessList, free );
+
+ exitPWUIDCache();
+}
+
+void printProcessListInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Name\tPID\tPPID\tUID\tGID\tStatus\tUser%%\tSystem%%\tNice\tVmSize"
+ "\tVmRss\tLogin\tCommand\n" );
+ fprintf( CurrentClient, "s\td\td\td\td\tS\tf\tf\td\tD\tD\ts\ts\n" );
+}
+
+void printProcessList( const char* cmd )
+{
+ ProcessInfo* ps;
+
+ (void)cmd;
+
+ for ( ps = first_ctnr( ProcessList ); ps; ps = next_ctnr( ProcessList ) ) {
+ fprintf( CurrentClient, "%s\t%ld\t%ld\t%ld\t%ld\t%s\t%.2f\t%.2f\t%d\t%d\t%d"
+ "\t%s\t%s\n", ps->name, (long)ps->pid, (long)ps->ppid,
+ (long)ps->uid, (long)ps->gid, ps->status, ps->userLoad,
+ ps->sysLoad, ps->niceLevel, ps->vmSize / 1024, ps->vmRss / 1024,
+ ps->userName, ps->cmdline );
+ }
+
+ fprintf( CurrentClient, "\n" );
+}
+
+void printProcessCount( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "%d\n", ProcessCount );
+}
+
+void printProcessCountInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Number of Processes\t0\t0\t\n" );
+}
+
+void killProcess( const char* cmd )
+{
+ int sig, pid;
+
+ sscanf( cmd, "%*s %d %d", &pid, &sig );
+ switch( sig ) {
+ case MENU_ID_SIGABRT:
+ sig = SIGABRT;
+ break;
+ case MENU_ID_SIGALRM:
+ sig = SIGALRM;
+ break;
+ case MENU_ID_SIGCHLD:
+ sig = SIGCHLD;
+ break;
+ case MENU_ID_SIGCONT:
+ sig = SIGCONT;
+ break;
+ case MENU_ID_SIGFPE:
+ sig = SIGFPE;
+ break;
+ case MENU_ID_SIGHUP:
+ sig = SIGHUP;
+ break;
+ case MENU_ID_SIGILL:
+ sig = SIGILL;
+ break;
+ case MENU_ID_SIGINT:
+ sig = SIGINT;
+ break;
+ case MENU_ID_SIGKILL:
+ sig = SIGKILL;
+ break;
+ case MENU_ID_SIGPIPE:
+ sig = SIGPIPE;
+ break;
+ case MENU_ID_SIGQUIT:
+ sig = SIGQUIT;
+ break;
+ case MENU_ID_SIGSEGV:
+ sig = SIGSEGV;
+ break;
+ case MENU_ID_SIGSTOP:
+ sig = SIGSTOP;
+ break;
+ case MENU_ID_SIGTERM:
+ sig = SIGTERM;
+ break;
+ case MENU_ID_SIGTSTP:
+ sig = SIGTSTP;
+ break;
+ case MENU_ID_SIGTTIN:
+ sig = SIGTTIN;
+ break;
+ case MENU_ID_SIGTTOU:
+ sig = SIGTTOU;
+ break;
+ case MENU_ID_SIGUSR1:
+ sig = SIGUSR1;
+ break;
+ case MENU_ID_SIGUSR2:
+ sig = SIGUSR2;
+ break;
+ }
+
+ if ( kill( (pid_t)pid, sig ) ) {
+ switch ( errno ) {
+ case EINVAL:
+ fprintf( CurrentClient, "4\t%d\n", pid );
+ break;
+ case ESRCH:
+ fprintf( CurrentClient, "3\t%d\n", pid );
+ break;
+ case EPERM:
+ if(vfork() == 0) {
+ exit(0);/* Won't execute unless execve fails. Need this for the parent process to continue */
+ }
+ fprintf( CurrentClient, "2\t%d\n", pid );
+ break;
+ default: /* unknown error */
+ fprintf( CurrentClient, "1\t%d\n", pid );
+ break;
+ }
+ } else
+ fprintf( CurrentClient, "0\t%d\n", pid );
+}
+
+void setPriority( const char* cmd )
+{
+ int pid, prio;
+
+ sscanf( cmd, "%*s %d %d", &pid, &prio );
+ if ( setpriority( PRIO_PROCESS, pid, prio ) ) {
+ switch ( errno ) {
+ case EINVAL:
+ fprintf( CurrentClient, "4\n" );
+ break;
+ case ESRCH:
+ fprintf( CurrentClient, "3\n" );
+ break;
+ case EPERM:
+ case EACCES:
+ fprintf( CurrentClient, "2\n" );
+ break;
+ default: /* unknown error */
+ fprintf( CurrentClient, "1\n" );
+ break;
+ }
+ } else
+ fprintf( CurrentClient, "0\n" );
+}
diff --git a/ksysguard/ksysguardd/Linux/ProcessList.h b/ksysguard/ksysguardd/Linux/ProcessList.h
new file mode 100644
index 000000000..709994a29
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/ProcessList.h
@@ -0,0 +1,38 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_PROCESSLIST_H
+#define KSG_PROCESSLIST_H
+
+void initProcessList( struct SensorModul* );
+void exitProcessList( void );
+
+int updateProcessList( void );
+
+void printProcessList( const char* );
+void printProcessListInfo( const char* );
+void printProcessCount( const char* );
+void printProcessCountInfo( const char* );
+
+void killProcess( const char* );
+void setPriority( const char* );
+
+#endif
diff --git a/ksysguard/ksysguardd/Linux/acpi.c b/ksysguard/ksysguardd/Linux/acpi.c
new file mode 100644
index 000000000..b3100c363
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/acpi.c
@@ -0,0 +1,418 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2003 Stephan Uhlmann <su@su2.info>
+ Copyright (c) 2005 Sirtaj Singh Kang <taj@kde.org> -- Battery fixes and Thermal
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "Command.h"
+#include "ksysguardd.h"
+
+#include "acpi.h"
+
+#define ACPIFILENAMELENGTHMAX 64
+#define ACPIBATTERYNUMMAX 6
+#define ACPIBATTERYINFOBUFSIZE 1024
+#define ACPIBATTERYSTATEBUFSIZE 512
+
+static int AcpiBatteryNum = 0;
+static char AcpiBatteryNames[ ACPIBATTERYNUMMAX ][ 8 ];
+static int AcpiBatteryCharge[ ACPIBATTERYNUMMAX ];
+static int AcpiBatteryUsage[ ACPIBATTERYNUMMAX ];
+
+static int AcpiThermalZones = -1;
+static int AcpiFans = -1;
+/*
+================================ public part =================================
+*/
+
+void initAcpi(struct SensorModul* sm)
+{
+ initAcpiBattery(sm);
+ initAcpiFan(sm);
+ initAcpiThermal(sm);
+}
+
+int updateAcpi( void )
+{
+ if (AcpiBatteryNum > 0) updateAcpiBattery();
+ if (AcpiFans > 0) updateAcpiFan();
+ if (AcpiThermalZones > 0) updateAcpiThermal();
+ return 0;
+}
+
+void exitAcpi( void )
+{
+ AcpiBatteryNum = -1;
+ AcpiFans = -1;
+ AcpiThermalZones = -1;
+}
+
+
+/************ ACPI Battery **********/
+
+void initAcpiBattery( struct SensorModul* sm )
+{
+ DIR *d;
+ struct dirent *de;
+ char s[ ACPIFILENAMELENGTHMAX ];
+
+ if ( ( d = opendir( "/proc/acpi/battery" ) ) == NULL ) {
+ AcpiBatteryNum = -1;
+ return;
+ } else {
+ AcpiBatteryNum = 0;
+ while ( ( de = readdir( d ) ) )
+ if ( ( strcmp( de->d_name, "." ) != 0 ) && ( strcmp( de->d_name, ".." ) != 0 ) ) {
+ strncpy( AcpiBatteryNames[ AcpiBatteryNum ], de->d_name, 8 );
+ snprintf( s, sizeof( s ), "acpi/battery/%d/batterycharge", AcpiBatteryNum );
+ registerMonitor( s, "integer", printAcpiBatFill, printAcpiBatFillInfo, sm );
+ snprintf( s, sizeof( s ), "acpi/battery/%d/batteryusage", AcpiBatteryNum );
+ registerMonitor( s, "integer", printAcpiBatUsage, printAcpiBatUsageInfo, sm);
+ AcpiBatteryCharge[ AcpiBatteryNum ] = 0;
+ AcpiBatteryNum++;
+ }
+ }
+}
+
+
+int updateAcpiBattery( void )
+{
+ int i, fd;
+ char s[ ACPIFILENAMELENGTHMAX ];
+ size_t n;
+ char AcpiBatInfoBuf[ ACPIBATTERYINFOBUFSIZE ];
+ char AcpiBatStateBuf[ ACPIBATTERYSTATEBUFSIZE ];
+ char *p;
+ int AcpiBatCapacity = 1;
+ int AcpiBatRemainingCapacity = 0;
+
+ if ( AcpiBatteryNum <= 0 )
+ return -1;
+
+ for ( i = 0; i < AcpiBatteryNum; i++ ) {
+ /* get total capacity */
+ snprintf( s, sizeof( s ), "/proc/acpi/battery/%s/info", AcpiBatteryNames[ i ] );
+ if ( ( fd = open( s, O_RDONLY ) ) < 0 ) {
+ print_error( "Cannot open file \'%s\'!\n"
+ "Load the battery ACPI kernel module or\n"
+ "compile it into your kernel.\n", s );
+ return -1;
+ }
+ if ( ( n = read( fd, AcpiBatInfoBuf, ACPIBATTERYINFOBUFSIZE - 1 ) ) ==
+ ACPIBATTERYINFOBUFSIZE - 1 ) {
+ log_error( "Internal buffer too small to read \'%s\'", s );
+ close( fd );
+ return -1;
+ }
+ close( fd );
+ p = AcpiBatInfoBuf;
+ while ( ( p!= NULL ) && ( sscanf( p, "last full capacity: %d ",
+ &AcpiBatCapacity ) != 1 ) ) {
+ p = strchr( p, '\n' );
+ if ( p )
+ p++;
+ }
+ /* get remaining capacity */
+ snprintf( s, sizeof( s ), "/proc/acpi/battery/%s/state", AcpiBatteryNames[ i ] );
+ if ( ( fd = open( s, O_RDONLY ) ) < 0 ) {
+ print_error( "Cannot open file \'%s\'!\n"
+ "Load the battery ACPI kernel module or\n"
+ "compile it into your kernel.\n", s );
+ return -1;
+ }
+ if ( ( n = read( fd, AcpiBatStateBuf, ACPIBATTERYSTATEBUFSIZE - 1 ) ) ==
+ ACPIBATTERYSTATEBUFSIZE - 1 ) {
+ log_error( "Internal buffer too small to read \'%s\'", s);
+ close( fd );
+ return -1;
+ }
+ close( fd );
+ p = AcpiBatStateBuf;
+ while ( ( p!= NULL ) && ( sscanf( p, "remaining capacity: %d ",
+ &AcpiBatRemainingCapacity ) != 1 ) ) {
+ p = strchr( p, '\n' );
+ if ( p )
+ p++;
+ }
+
+ /* get current battery usage, (current Current) */
+ p = AcpiBatStateBuf;
+ while ( ( p!= NULL ) && ( sscanf( p, "present rate: %d ",
+ &AcpiBatteryUsage[i] ) != 1 ) ) {
+ p = strchr( p, '\n' );
+ if ( p )
+ p++;
+ }
+
+
+ /* calculate charge rate */
+ if ( AcpiBatCapacity > 0 )
+ AcpiBatteryCharge[ i ] = AcpiBatRemainingCapacity * 100 / AcpiBatCapacity;
+ else
+ AcpiBatteryCharge[ i ] = 0;
+ }
+
+ return 0;
+}
+
+void printAcpiBatFill( const char* cmd )
+{
+ int i;
+
+ sscanf( cmd + 13, "%d", &i );
+ fprintf( CurrentClient, "%d\n", AcpiBatteryCharge[ i ] );
+}
+
+void printAcpiBatFillInfo( const char* cmd )
+{
+ int i;
+
+ sscanf( cmd + 13, "%d", &i );
+ fprintf( CurrentClient, "Battery %d charge\t0\t100\t%%\n", i );
+}
+
+void printAcpiBatUsage( const char* cmd)
+{
+ int i;
+
+ sscanf( cmd + 13, "%d", &i );
+ fprintf(CurrentClient, "%d\n", AcpiBatteryUsage[ i ] );
+}
+
+void printAcpiBatUsageInfo( const char* cmd)
+{
+
+ int i;
+
+ sscanf(cmd+13, "%d", &i);
+
+ fprintf(CurrentClient, "Battery %d usage\t0\t2500\tmA\n", i );
+}
+
+/************** ACPI Thermal *****************/
+
+#define THERMAL_ZONE_DIR "/proc/acpi/thermal_zone"
+#define TEMPERATURE_FILE "temperature"
+#define TEMPERATURE_FILE_MAXLEN 255
+
+
+/*static char **zone_names = NULL;*/
+
+/** Find the thermal zone name from the command.
+ * Assumes the command is of the form acpi/thermal_zone/<zone name>/...
+ * @p startidx is set to the start of the zone name. May be set to an
+ * undefined value if zone name is not found.
+ * @return length of found name, or 0 if nothing found.
+ */
+static int extract_zone_name(char **startidx, const char *cmd)
+{
+ char *idx = NULL;
+ idx = strchr(cmd, '/');
+ if (idx == NULL) return 0;
+ idx = strchr(idx+1, '/');
+ if (idx == NULL) return 0;
+ *startidx = idx+1;
+ idx = strchr(*startidx, '/');
+ if (idx == NULL) return 0;
+ return idx - *startidx;
+}
+
+void initAcpiThermal(struct SensorModul *sm)
+{
+
+ char th_ref[ ACPIFILENAMELENGTHMAX ];
+ DIR *d = NULL;
+ struct dirent *de;
+
+ d = opendir(THERMAL_ZONE_DIR);
+ if (d == NULL) {
+/* print_error( "Directory \'" THERMAL_ZONE_DIR
+ "\' does not exist or is not readable.\n"
+ "Load the ACPI thermal kernel module or compile it into your kernel.\n" );
+*/
+ AcpiThermalZones = -1;
+ return;
+ }
+
+ AcpiThermalZones = 0;
+ while ( (de = readdir(d)) != NULL ) {
+ if ( ( strcmp( de->d_name, "." ) == 0 )
+ || ( strcmp( de->d_name, ".." ) == 0 ) ) {
+ continue;
+ }
+
+ AcpiThermalZones++;
+ snprintf(th_ref, sizeof(th_ref),
+ "acpi/thermal_zone/%s/temperature", de->d_name);
+ registerMonitor(th_ref, "integer", printThermalZoneTemperature,
+ printThermalZoneTemperatureInfo, sm);
+ }
+
+ return;
+}
+
+int updateAcpiThermal()
+{
+ /* TODO: stub */
+ return 0;
+}
+
+static int getCurrentTemperature(const char *cmd)
+{
+ char th_file[ ACPIFILENAMELENGTHMAX ];
+ char input_buf[ TEMPERATURE_FILE_MAXLEN ];
+ char *zone_name = NULL;
+ int read_bytes = 0, fd = 0, len_zone_name = 0;
+ int temperature=0;
+
+ len_zone_name = extract_zone_name(&zone_name, cmd);
+ if (len_zone_name <= 0) return -1;
+
+ snprintf(th_file, sizeof(th_file),
+ THERMAL_ZONE_DIR "/%.*s/" TEMPERATURE_FILE,
+ len_zone_name, zone_name);
+
+ fd = open(th_file, O_RDONLY);
+ if (fd < 0) {
+ print_error( "Cannot open file \'%s\'!\n"
+ "Load the thermal ACPI kernel module or\n"
+ "compile it into your kernel.\n", th_file );
+ return -1;
+ }
+
+ read_bytes = read( fd, input_buf, sizeof(input_buf) - 1 );
+ if ( read_bytes == sizeof(input_buf) - 1 ) {
+ log_error( "Internal buffer too small to read \'%s\'", th_file );
+ close( fd );
+ return -1;
+ }
+ close(fd);
+
+ sscanf(input_buf, "temperature: %d C", &temperature);
+ return temperature;
+}
+
+void printThermalZoneTemperature(const char *cmd) {
+ int temperature = getCurrentTemperature(cmd);
+ fprintf(CurrentClient, "%d\n", temperature);
+}
+
+void printThermalZoneTemperatureInfo(const char *cmd)
+{
+ fprintf(CurrentClient, "Current temperature\t0\t0\tC\n");
+}
+
+/********** ACPI Fan State***************/
+
+#define FAN_DIR "/proc/acpi/fan"
+#define FAN_STATE_FILE "state"
+#define FAN_STATE_FILE_MAXLEN 255
+
+void initAcpiFan(struct SensorModul *sm)
+{
+
+ char th_ref[ ACPIFILENAMELENGTHMAX ];
+ DIR *d = NULL;
+ struct dirent *de;
+
+ d = opendir(FAN_DIR);
+ if (d == NULL) {
+/* print_error( "Directory \'" THERMAL_ZONE_DIR
+ "\' does not exist or is not readable.\n"
+ "Load the ACPI thermal kernel module or compile it into your kernel.\n" );
+*/
+ AcpiFans = -1;
+ return;
+ }
+
+ AcpiFans = 0;
+ while ( (de = readdir(d)) != NULL ) {
+ if ( ( strcmp( de->d_name, "." ) == 0 )
+ || ( strcmp( de->d_name, ".." ) == 0 ) ) {
+ continue;
+ }
+
+ AcpiFans++;
+ snprintf(th_ref, sizeof(th_ref),
+ "acpi/fan/%s/state", de->d_name);
+ registerMonitor(th_ref, "integer", printFanState,
+ printFanStateInfo, sm);
+ }
+
+ return;
+}
+
+int updateAcpiFan()
+{
+ /* TODO: stub */
+ return 0;
+}
+
+static int getFanState(const char *cmd)
+{
+ char fan_state_file[ ACPIFILENAMELENGTHMAX ];
+ char input_buf[ FAN_STATE_FILE_MAXLEN ];
+ char *fan_name = NULL;
+ int read_bytes = 0, fd = 0, len_fan_name = 0;
+ char fan_state[4];
+
+ len_fan_name = extract_zone_name(&fan_name, cmd);
+ if (len_fan_name <= 0) return -1;
+
+ snprintf(fan_state_file, sizeof(fan_state_file),
+ FAN_DIR "/%.*s/" FAN_STATE_FILE,
+ len_fan_name, fan_name);
+
+ fd = open(fan_state_file, O_RDONLY);
+ if (fd < 0) {
+ print_error( "Cannot open file \'%s\'!\n"
+ "Load the fan ACPI kernel module or\n"
+ "compile it into your kernel.\n", fan_state_file );
+ return -1;
+ }
+
+ read_bytes = read( fd, input_buf, sizeof(input_buf) - 1 );
+ if ( read_bytes == sizeof(input_buf) - 1 ) {
+ log_error( "Internal buffer too small to read \'%s\'", fan_state_file );
+ close( fd );
+ return -1;
+ }
+ close(fd);
+
+ sscanf(input_buf, "status: %2s", fan_state);
+ return (fan_state[1] == 'n') ? 1 : 0;
+}
+
+void printFanState(const char *cmd) {
+ int fan_state = getFanState(cmd);
+ fprintf(CurrentClient, "%d\n", fan_state);
+}
+
+void printFanStateInfo(const char *cmd)
+{
+ fprintf(CurrentClient, "Fan status\t0\t1\tboolean\n");
+}
+
+
diff --git a/ksysguard/ksysguardd/Linux/acpi.h b/ksysguard/ksysguardd/Linux/acpi.h
new file mode 100644
index 000000000..ae01ecad1
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/acpi.h
@@ -0,0 +1,45 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2003 Stephan Uhlmann <su@su2.info>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KSG_ACPI_H
+#define KSG_ACPI_H
+
+void initAcpi( struct SensorModul* );
+void exitAcpi( void );
+
+int updateAcpi( void );
+
+void initAcpiBattery( struct SensorModul* );
+int updateAcpiBattery(void);
+void printAcpiBatFill( const char* );
+void printAcpiBatFillInfo( const char* );
+void printAcpiBatUsage( const char* );
+void printAcpiBatUsageInfo( const char* );
+
+void initAcpiThermal( struct SensorModul * );
+int updateAcpiThermal(void);
+void printThermalZoneTemperature(const char *cmd);
+void printThermalZoneTemperatureInfo(const char *cmd);
+
+void initAcpiFan( struct SensorModul * );
+int updateAcpiFan(void);
+void printFanState(const char *cmd);
+void printFanStateInfo(const char *cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/Linux/apm.c b/ksysguard/ksysguardd/Linux/apm.c
new file mode 100644
index 000000000..0c1d00bcb
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/apm.c
@@ -0,0 +1,126 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "Command.h"
+#include "ksysguardd.h"
+
+#include "apm.h"
+
+static int ApmOK = 0;
+static int BatFill, BatTime;
+
+#define APMBUFSIZE 128
+static char ApmBuf[ APMBUFSIZE ];
+static int Dirty = 0;
+
+static void processApm( void )
+{
+ sscanf( ApmBuf, "%*f %*f %*x %*x %*x %*x %d%% %d min",
+ &BatFill, &BatTime );
+ Dirty = 0;
+}
+
+/*
+================================ public part =================================
+*/
+
+void initApm( struct SensorModul* sm )
+{
+ if ( updateApm() < 0 ) {
+ ApmOK = -1;
+ return;
+ } else
+ ApmOK = 1;
+
+ registerMonitor( "apm/batterycharge", "integer", printApmBatFill, printApmBatFillInfo, sm );
+ registerMonitor( "apm/remainingtime", "integer", printApmBatTime, printApmBatTimeInfo, sm );
+}
+
+void exitApm( void )
+{
+ ApmOK = -1;
+}
+
+int updateApm( void )
+{
+ size_t n;
+ int fd;
+
+ if ( ApmOK < 0 )
+ return -1;
+
+ if ( ( fd = open( "/proc/apm", O_RDONLY ) ) < 0 ) {
+ if ( ApmOK != 0 )
+ print_error( "Cannot open file \'/proc/apm\'!\n"
+ "The kernel needs to be compiled with support\n"
+ "for /proc filesystem enabled!\n" );
+ return -1;
+ }
+
+ if ( ( n = read( fd, ApmBuf, APMBUFSIZE - 1 ) ) == APMBUFSIZE - 1 ) {
+ log_error( "Internal buffer too small to read \'/proc/apm\'" );
+ close( fd );
+ return -1;
+ }
+
+ close( fd );
+ ApmBuf[ n ] = '\0';
+ Dirty = 1;
+
+ return 0;
+}
+
+void printApmBatFill( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processApm();
+
+ fprintf( CurrentClient, "%d\n", BatFill );
+}
+
+void printApmBatFillInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Battery charge\t0\t100\t%%\n" );
+}
+
+void printApmBatTime( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processApm();
+
+ fprintf( CurrentClient, "%d\n", BatTime );
+}
+
+void printApmBatTimeInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Remaining battery time\t0\t0\tmin\n" );
+}
diff --git a/ksysguard/ksysguardd/Linux/apm.h b/ksysguard/ksysguardd/Linux/apm.h
new file mode 100644
index 000000000..982c77f7c
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/apm.h
@@ -0,0 +1,34 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_APM_H
+#define KSG_APM_H
+
+void initApm( struct SensorModul* );
+void exitApm( void );
+
+int updateApm( void );
+
+void printApmBatFill( const char* );
+void printApmBatFillInfo( const char* );
+void printApmBatTime( const char* );
+void printApmBatTimeInfo( const char* );
+
+#endif
diff --git a/ksysguard/ksysguardd/Linux/cpuinfo.c b/ksysguard/ksysguardd/Linux/cpuinfo.c
new file mode 100644
index 000000000..de5deb80f
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/cpuinfo.c
@@ -0,0 +1,179 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2000-2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "Command.h"
+#include "ksysguardd.h"
+
+#include "cpuinfo.h"
+
+static int CpuInfoOK = 0;
+static float* Clocks = 0;
+static int CPUs = 0;
+
+#define CPUINFOBUFSIZE (32 * 1024)
+static char CpuInfoBuf[ CPUINFOBUFSIZE ];
+static int Dirty = 0;
+static struct SensorModul *CpuInfoSM;
+
+static void processCpuInfo( void )
+{
+ char format[ 32 ];
+ char tag[ 32 ];
+ char value[ 256 ];
+ char* cibp = CpuInfoBuf;
+ int cpuId = 0;
+
+ if ( !CpuInfoOK )
+ return;
+
+ sprintf( format, "%%%d[^:]: %%%d[^\n]\n", (int)sizeof( tag ) - 1,
+ (int)sizeof( value ) - 1 );
+
+ while ( sscanf( cibp, format, tag, value ) == 2 ) {
+ char* p;
+ tag[ sizeof( tag ) - 1 ] = '\0';
+ value[ sizeof( value ) - 1 ] = '\0';
+ /* remove trailing whitespaces */
+ p = tag + strlen( tag ) - 1;
+ /* remove trailing whitespaces */
+ while ( ( *p == ' ' || *p == '\t' ) && p > tag )
+ *p-- = '\0';
+
+ if ( strcmp( tag, "processor" ) == 0 ) {
+ if ( sscanf( value, "%d", &cpuId ) == 1 ) {
+ if ( cpuId >= CPUs ) {
+ char cmdName[ 24 ];
+ if ( Clocks )
+ free( Clocks );
+ CPUs = cpuId + 1;
+ Clocks = malloc( CPUs * sizeof( float ) );
+ snprintf( cmdName, sizeof( cmdName ) - 1, "cpu%d/clock", cpuId );
+ registerMonitor( cmdName, "float", printCPUxClock, printCPUxClockInfo,
+ CpuInfoSM );
+ }
+ }
+ } else if ( strcmp( tag, "cpu MHz" ) == 0 )
+ sscanf( value, "%f", &Clocks[ cpuId ] );
+
+ /* Move cibp to begining of next line, if there is one. */
+ cibp = strchr( cibp, '\n' );
+ if ( cibp )
+ cibp++;
+ else
+ cibp = CpuInfoBuf + strlen( CpuInfoBuf );
+ }
+
+ Dirty = 0;
+}
+
+/*
+================================ public part =================================
+*/
+
+void initCpuInfo( struct SensorModul* sm )
+{
+ CpuInfoSM = sm;
+
+ if ( updateCpuInfo() < 0 )
+ return;
+
+ processCpuInfo();
+}
+
+void exitCpuInfo( void )
+{
+ CpuInfoOK = -1;
+
+ free( Clocks );
+}
+
+int updateCpuInfo( void )
+{
+ size_t n;
+ int fd;
+
+ if ( CpuInfoOK < 0 )
+ return -1;
+
+ if ( ( fd = open( "/proc/cpuinfo", O_RDONLY ) ) < 0 ) {
+ if ( CpuInfoOK != 0 )
+ print_error( "Cannot open file \'/proc/cpuinfo\'!\n"
+ "The kernel needs to be compiled with support\n"
+ "for /proc filesystem enabled!\n" );
+ CpuInfoOK = -1;
+ return -1;
+ }
+
+ n = 0;
+ for(;;) {
+ ssize_t len = read( fd, CpuInfoBuf + n, CPUINFOBUFSIZE - 1 - n );
+ if( len < 0 ) {
+ print_error( "Failed to read file \'/proc/cpuinfo\'!\n" );
+ CpuInfoOK = -1;
+ close( fd );
+ return -1;
+ }
+ n += len;
+ if( len == 0 ) /* reading finished */
+ break;
+ if( n == CPUINFOBUFSIZE - 1 ) {
+ log_error( "Internal buffer too small to read \'/proc/cpuinfo\'" );
+ CpuInfoOK = 0;
+ close( fd );
+ return -1;
+ }
+ }
+
+ close( fd );
+ CpuInfoOK = 1;
+ CpuInfoBuf[ n ] = '\0';
+ Dirty = 1;
+
+ return 0;
+}
+
+void printCPUxClock( const char* cmd )
+{
+ int id;
+
+ if ( Dirty )
+ processCpuInfo();
+
+ sscanf( cmd + 3, "%d", &id );
+ fprintf( CurrentClient, "%f\n", Clocks[ id ] );
+}
+
+void printCPUxClockInfo( const char* cmd )
+{
+ int id;
+
+ sscanf( cmd + 3, "%d", &id );
+ fprintf( CurrentClient, "CPU%d Clock Frequency\t0\t0\tMHz\n", id );
+}
diff --git a/ksysguard/ksysguardd/Linux/cpuinfo.h b/ksysguard/ksysguardd/Linux/cpuinfo.h
new file mode 100644
index 000000000..f2380cce7
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/cpuinfo.h
@@ -0,0 +1,32 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2000-2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_CPUINFO_H
+#define KSG_CPUINFO_H
+
+void initCpuInfo( struct SensorModul* );
+void exitCpuInfo( void );
+
+int updateCpuInfo( void );
+
+void printCPUxClock( const char* );
+void printCPUxClockInfo( const char* );
+
+#endif
diff --git a/ksysguard/ksysguardd/Linux/diskstat.c b/ksysguard/ksysguardd/Linux/diskstat.c
new file mode 100644
index 000000000..012ed5a8e
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/diskstat.c
@@ -0,0 +1,265 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <mntent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "Command.h"
+#include "ccont.h"
+#include "diskstat.h"
+#include "ksysguardd.h"
+
+typedef struct {
+ char device[ 256 ];
+ char mntpnt[ 256 ];
+ long blocks;
+ long bfree;
+ long bused;
+ int bused_percent;
+} DiskInfo;
+
+static CONTAINER DiskStatList = 0;
+static struct SensorModul* DiskStatSM;
+char *getMntPnt( const char* cmd );
+
+char *getMntPnt( const char* cmd )
+{
+ static char device[ 1025 ];
+ char* ptr;
+
+ memset( device, 0, sizeof( device ) );
+ sscanf( cmd, "partitions%1024s", device );
+
+ ptr = (char*)rindex( device, '/' );
+ *ptr = '\0';
+
+ return (char*)device;
+}
+
+/* ----------------------------- public part ------------------------------- */
+
+void initDiskStat( struct SensorModul* sm )
+{
+ char monitor[ 1024 ];
+ DiskInfo* disk_info;
+
+ DiskStatList = new_ctnr();
+ DiskStatSM = sm;
+
+ if ( updateDiskStat() < 0 )
+ return;
+
+ registerMonitor( "partitions/list", "listview", printDiskStat, printDiskStatInfo, sm );
+
+ for ( disk_info = first_ctnr( DiskStatList ); disk_info; disk_info = next_ctnr( DiskStatList ) ) {
+ snprintf( monitor, sizeof( monitor ), "partitions%s/usedspace", disk_info->mntpnt );
+ registerMonitor( monitor, "integer", printDiskStatUsed, printDiskStatUsedInfo, DiskStatSM );
+ snprintf( monitor, sizeof( monitor ), "partitions%s/freespace", disk_info->mntpnt );
+ registerMonitor( monitor, "integer", printDiskStatFree, printDiskStatFreeInfo, DiskStatSM );
+ snprintf( monitor, sizeof( monitor ), "partitions%s/filllevel", disk_info->mntpnt );
+ registerMonitor( monitor, "integer", printDiskStatPercent, printDiskStatPercentInfo, DiskStatSM );
+ }
+}
+
+void exitDiskStat( void )
+{
+ char monitor[ 1024 ];
+ DiskInfo* disk_info;
+
+ removeMonitor( "partitions/list" );
+
+ for ( disk_info = first_ctnr( DiskStatList ); disk_info; disk_info = next_ctnr( DiskStatList ) ) {
+ snprintf( monitor, sizeof( monitor ), "partitions%s/usedspace", disk_info->mntpnt );
+ removeMonitor( monitor );
+ snprintf( monitor, sizeof( monitor ), "partitions%s/freespace", disk_info->mntpnt );
+ removeMonitor( monitor );
+ snprintf( monitor, sizeof( monitor ), "partitions%s/filllevel", disk_info->mntpnt );
+ removeMonitor( monitor );
+ }
+
+ destr_ctnr( DiskStatList, free );
+}
+
+void checkDiskStat( void )
+{
+ struct stat mtab_info;
+ static off_t mtab_size = 0;
+
+ stat( "/etc/mtab", &mtab_info );
+ if ( !mtab_size )
+ mtab_size = mtab_info.st_size;
+
+ if ( mtab_info.st_size != mtab_size ) {
+ exitDiskStat();
+ initDiskStat( DiskStatSM );
+ mtab_size = mtab_info.st_size;
+ }
+}
+
+int updateDiskStat( void )
+{
+ DiskInfo *disk_info;
+ FILE *fh;
+ struct mntent *mnt_info;
+ float percent;
+ int i;
+ struct statfs fs_info;
+
+ if ( ( fh = setmntent( "/etc/mtab", "r" ) ) == NULL ) {
+ print_error( "Cannot open \'/etc/mtab\'!\n" );
+ return -1;
+ }
+
+ for ( i = level_ctnr( DiskStatList ); i >= 0; --i )
+ free( pop_ctnr( DiskStatList ) );
+
+ while ( ( mnt_info = getmntent( fh ) ) != NULL ) {
+ if ( statfs( mnt_info->mnt_dir, &fs_info ) < 0 )
+ continue;
+
+ if ( strcmp( mnt_info->mnt_type, "proc" ) &&
+ strcmp( mnt_info->mnt_type, "devfs" ) &&
+ strcmp( mnt_info->mnt_type, "usbfs" ) &&
+ strcmp( mnt_info->mnt_type, "sysfs" ) &&
+ strcmp( mnt_info->mnt_type, "tmpfs" ) &&
+ strcmp( mnt_info->mnt_type, "devpts" ) ) {
+ if ( fs_info.f_blocks != 0 )
+ {
+ percent = ( ( (float)fs_info.f_blocks - (float)fs_info.f_bfree ) /
+ (float)fs_info.f_blocks );
+ percent = percent * 100;
+ }
+ else
+ {
+ percent = 0;
+ }
+
+ if ( ( disk_info = (DiskInfo *)malloc( sizeof( DiskInfo ) ) ) == NULL )
+ continue;
+
+ memset( disk_info, 0, sizeof( DiskInfo ) );
+ strlcpy( disk_info->device, mnt_info->mnt_fsname, sizeof( disk_info->device ) );
+ if ( !strcmp( mnt_info->mnt_dir, "/" ) )
+ strlcpy( disk_info->mntpnt, "/root", sizeof( disk_info->mntpnt ) );
+ else
+ strlcpy( disk_info->mntpnt, mnt_info->mnt_dir, sizeof( disk_info->mntpnt ) );
+
+ disk_info->blocks = fs_info.f_blocks;
+ disk_info->bfree = fs_info.f_bfree;
+ disk_info->bused = fs_info.f_blocks - fs_info.f_bfree;
+ disk_info->bused_percent = (int)percent;
+
+ push_ctnr( DiskStatList, disk_info );
+ }
+ }
+
+ endmntent( fh );
+
+ return 0;
+}
+
+void printDiskStat( const char* cmd )
+{
+ DiskInfo* disk_info;
+
+ (void)cmd;
+ for ( disk_info = first_ctnr( DiskStatList ); disk_info; disk_info = next_ctnr( DiskStatList ) ) {
+ fprintf( CurrentClient, "%s\t%ld\t%ld\t%ld\t%d\t%s\n",
+ disk_info->device,
+ disk_info->blocks,
+ disk_info->bused,
+ disk_info->bfree,
+ disk_info->bused_percent,
+ disk_info->mntpnt );
+ }
+
+ fprintf( CurrentClient, "\n" );
+}
+
+void printDiskStatInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Device\tBlocks\tUsed\tAvailable\tUsed %%\tMountPoint\nM\tD\tD\tD\td\ts\n" );
+}
+
+void printDiskStatUsed( const char* cmd )
+{
+ char *mntpnt = (char*)getMntPnt( cmd );
+ DiskInfo* disk_info;
+
+ for ( disk_info = first_ctnr( DiskStatList ); disk_info; disk_info = next_ctnr( DiskStatList ) ) {
+ if ( !strcmp( mntpnt, disk_info->mntpnt ) )
+ fprintf( CurrentClient, "%ld\n", disk_info->bused );
+ }
+
+ fprintf( CurrentClient, "\n" );
+}
+
+void printDiskStatUsedInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Used Blocks\t0\t-\tBlocks\n" );
+}
+
+void printDiskStatFree( const char* cmd )
+{
+ char *mntpnt = (char*)getMntPnt( cmd );
+ DiskInfo* disk_info;
+
+ for ( disk_info = first_ctnr( DiskStatList ); disk_info; disk_info = next_ctnr( DiskStatList ) ) {
+ if ( !strcmp( mntpnt, disk_info->mntpnt ) )
+ fprintf( CurrentClient, "%ld\n", disk_info->bfree );
+ }
+
+ fprintf( CurrentClient, "\n" );
+}
+
+void printDiskStatFreeInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Free Blocks\t0\t-\tBlocks\n" );
+}
+
+void printDiskStatPercent( const char* cmd )
+{
+ char *mntpnt = (char*)getMntPnt( cmd );
+ DiskInfo* disk_info;
+
+ for ( disk_info = first_ctnr( DiskStatList ); disk_info; disk_info = next_ctnr( DiskStatList ) ) {
+ if ( !strcmp( mntpnt, disk_info->mntpnt ) )
+ fprintf( CurrentClient, "%d\n", disk_info->bused_percent );
+ }
+
+ fprintf( CurrentClient, "\n" );
+}
+
+void printDiskStatPercentInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Used Blocks\t0\t100\t%%\n" );
+}
diff --git a/ksysguard/ksysguardd/Linux/diskstat.h b/ksysguard/ksysguardd/Linux/diskstat.h
new file mode 100644
index 000000000..6a23e6148
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/diskstat.h
@@ -0,0 +1,40 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_DISKSTAT_H
+#define KSG_DISKSTAT_H
+
+void initDiskStat( struct SensorModul* );
+void exitDiskStat( void );
+
+int updateDiskStat( void );
+void checkDiskStat( void );
+
+void printDiskStat( const char* );
+void printDiskStatInfo( const char* );
+
+void printDiskStatUsed( const char* );
+void printDiskStatUsedInfo( const char* );
+void printDiskStatFree( const char* );
+void printDiskStatFreeInfo( const char* );
+void printDiskStatPercent( const char* );
+void printDiskStatPercentInfo( const char* );
+
+#endif
diff --git a/ksysguard/ksysguardd/Linux/i8k.c b/ksysguard/ksysguardd/Linux/i8k.c
new file mode 100644
index 000000000..c6bbe7d72
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/i8k.c
@@ -0,0 +1,150 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "Command.h"
+#include "ksysguardd.h"
+
+#include "i8k.h"
+
+#ifdef HAVE_I8K_SUPPORT
+
+static int I8kOK = 0;
+static int cpuTemp, fan0Speed, fan1Speed;
+
+#define I8KBUFSIZE 128
+static char I8kBuf[ I8KBUFSIZE ];
+
+/*
+================================ public part =================================
+*/
+
+void initI8k( struct SensorModul* sm )
+{
+ if ( updateI8k() < 0 ) {
+ I8kOK = -1;
+ return;
+ } else
+ I8kOK = 1;
+
+ registerMonitor( "dell/cputemp", "integer", printI8kCPUTemperature,
+ printI8kCPUTemperatureInfo, sm );
+ registerMonitor( "dell/fan0", "integer", printI8kFan0Speed,
+ printI8kFan0SpeedInfo, sm );
+ registerMonitor( "dell/fan1", "integer", printI8kFan1Speed,
+ printI8kFan1SpeedInfo, sm );
+}
+
+void exitI8k( void )
+{
+ I8kOK = -1;
+}
+
+int updateI8k( void )
+{
+ size_t n;
+ int fd;
+
+ if ( I8kOK < 0 )
+ return -1;
+
+ if ( ( fd = open( "/proc/i8k", O_RDONLY ) ) < 0 ) {
+ print_error( "Cannot open file \'/proc/i8k\'!\n"
+ "The kernel needs to be compiled with support\n"
+ "for /proc filesystem enabled!\n" );
+ return -1;
+ }
+
+ if ( ( n = read( fd, I8kBuf, I8KBUFSIZE - 1 ) ) == I8KBUFSIZE - 1 ) {
+ log_error( "Internal buffer too small to read \'/proc/i8k\'" );
+
+ close( fd );
+ return -1;
+ }
+
+ close( fd );
+ I8kBuf[ n ] = '\0';
+
+ sscanf( I8kBuf, "%*f %*s %*s %d %*d %*d %d %d %*d %*d",
+ &cpuTemp, &fan0Speed, &fan1Speed );
+
+ return 0;
+}
+
+void printI8kCPUTemperature( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "%d\n", cpuTemp );
+}
+
+void printI8kCPUTemperatureInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "CPU Temperature\t0\t0\tC\n" );
+}
+
+void printI8kFan0Speed( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "%d\n", fan0Speed );
+}
+
+void printI8kFan0SpeedInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Left fan\t0\t0\trpm\n" );
+}
+
+void printI8kFan1Speed( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "%d\n", fan1Speed );
+}
+
+void printI8kFan1SpeedInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Right fan\t0\t0\trpm\n" );
+}
+
+#else /* HAVE_I8K_SUPPORT */
+
+/* dummy version for systems that have no i8k support */
+
+void initI8k( struct SensorModul* sm )
+{
+ (void)sm;
+}
+
+void exitI8k( void )
+{
+}
+
+int updateI8k( void )
+{
+ return 0;
+}
+
+#endif
diff --git a/ksysguard/ksysguardd/Linux/i8k.h b/ksysguard/ksysguardd/Linux/i8k.h
new file mode 100644
index 000000000..40c2a886d
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/i8k.h
@@ -0,0 +1,36 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_I8K_H
+#define KSG_I8K_H
+
+void initI8k( struct SensorModul* );
+void exitI8k( void );
+
+int updateI8k( void );
+
+void printI8kCPUTemperature( const char* );
+void printI8kCPUTemperatureInfo( const char* );
+void printI8kFan0Speed( const char* );
+void printI8kFan0SpeedInfo( const char* );
+void printI8kFan1Speed( const char* );
+void printI8kFan1SpeedInfo( const char* );
+
+#endif
diff --git a/ksysguard/ksysguardd/Linux/lmsensors.c b/ksysguard/ksysguardd/Linux/lmsensors.c
new file mode 100644
index 000000000..37e41d2a1
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/lmsensors.c
@@ -0,0 +1,309 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "Command.h"
+#include "ccont.h"
+#include "ksysguardd.h"
+
+#include "lmsensors.h"
+
+#ifdef HAVE_SENSORS_SENSORS_H
+#include <sensors/sensors.h>
+
+#ifndef SENSORS_API_VERSION
+#define SENSORS_API_VERSION 0x000
+#endif
+#ifndef SENSORS_CHIP_NAME_BUS_PCI
+#define SENSORS_CHIP_NAME_BUS_PCI -5
+#endif
+#ifndef SENSORS_CHIP_NAME_BUS_ISA
+#define SENSORS_CHIP_NAME_BUS_ISA -1
+#endif
+
+#define BUFFER_SIZE_LMSEN 300
+typedef struct
+{
+ char* fullName;
+ const sensors_chip_name* scn;
+#if SENSORS_API_VERSION & 0x400
+ const sensors_feature *sf;
+ const sensors_subfeature *sfd;
+#else
+ const sensors_feature_data* sfd;
+#endif
+} LMSENSOR;
+
+static CONTAINER LmSensors;
+static int LmSensorsOk = -1;
+
+static int sensorCmp( void* s1, void* s2 )
+{
+ return strcmp( ((LMSENSOR*)s1)->fullName, ((LMSENSOR*)s2)->fullName );
+}
+
+static LMSENSOR* findMatchingSensor( const char* name )
+{
+ INDEX idx;
+ LMSENSOR key;
+ LMSENSOR* s;
+
+ if(name == NULL || name[0] == '\0') return 0;
+ key.fullName = strdup( name );
+ int end = strlen(key.fullName)-1;
+ if(key.fullName[end] == '?')
+ key.fullName[end] = '\0';
+ if ( ( idx = search_ctnr( LmSensors, sensorCmp, &key ) ) < 0 ) {
+ free( key.fullName );
+ return 0;
+ }
+
+ free( key.fullName );
+ s = get_ctnr( LmSensors, idx );
+
+ return s;
+}
+
+static const char *chipName(const sensors_chip_name *chip) {
+ static char buffer[256];
+#if SENSORS_API_VERSION & 0x400
+ sensors_snprintf_chip_name(buffer, sizeof(buffer), chip);
+#else /* SENSORS_API_VERSION & 0x400 */
+ if (chip->bus == SENSORS_CHIP_NAME_BUS_ISA)
+ snprintf (buffer, sizeof(buffer), "%s-isa-%04x", chip->prefix, chip->addr);
+ else if (chip->bus == SENSORS_CHIP_NAME_BUS_PCI)
+ snprintf (buffer, sizeof(buffer), "%s-pci-%04x", chip->prefix, chip->addr);
+ else
+ snprintf (buffer, sizeof(buffer), "%s-i2c-%d-%02x", chip->prefix, chip->bus, chip->addr);
+#endif /* SENSORS_API_VERSION & 0x400 */
+ return buffer;
+}
+
+#if SENSORS_API_VERSION & 0x400
+void initLmSensors( struct SensorModul* sm )
+{
+ const sensors_chip_name* scn;
+ int nr = 0;
+
+ if ( sensors_init( NULL ) ) {
+ LmSensorsOk = -1;
+ return;
+ }
+
+ LmSensors = new_ctnr();
+ while ( ( scn = sensors_get_detected_chips( NULL, &nr ) ) != NULL ) {
+ int nr1 = 0;
+ const sensors_feature* sf;
+
+ while ( ( sf = sensors_get_features( scn, &nr1 ) ) != 0 ) {
+ const sensors_subfeature *ssubf;
+ LMSENSOR *p;
+ char *s, *label;
+
+ switch( sf->type )
+ {
+ case SENSORS_FEATURE_IN:
+ ssubf = sensors_get_subfeature( scn, sf,
+ SENSORS_SUBFEATURE_IN_INPUT );
+ break;
+
+ case SENSORS_FEATURE_FAN:
+ ssubf = sensors_get_subfeature( scn, sf,
+ SENSORS_SUBFEATURE_FAN_INPUT );
+ break;
+
+ case SENSORS_FEATURE_TEMP:
+ ssubf = sensors_get_subfeature( scn, sf,
+ SENSORS_SUBFEATURE_TEMP_INPUT );
+ break;
+ default:
+ ssubf = NULL;
+ }
+
+ if ( !ssubf )
+ continue;
+
+ label = sensors_get_label( scn, sf );
+ p = (LMSENSOR*)malloc( sizeof( LMSENSOR ) );
+ p->fullName = (char*)malloc( strlen( "lmsensors/" ) +
+ strlen( scn->prefix ) + 1 +
+ strlen( label ) + 1 );
+ snprintf( p->fullName, BUFFER_SIZE_LMSEN, "lmsensors/%s/%s", scn->prefix, label );
+
+ /* Make sure that name contains only proper characters. */
+ for ( s = p->fullName; *s; s++ )
+ if ( *s == ' ' )
+ *s = '_';
+
+ p->scn = scn;
+ p->sf = sf;
+ p->sfd = ssubf;
+
+ /* Note a name collision should never happen with the lm_sensors-3x code,
+ but it does in the case of k8temp, when there are 2 identical labeled
+ sensors per CPU. This are really 2 distinct sensors measuring the
+ same thing, but fullName must be unique so we just drop the second
+ sensor */
+ if ( search_ctnr( LmSensors, sensorCmp, p ) < 0 ) {
+ push_ctnr( LmSensors, p );
+ registerMonitor( p->fullName, "float", printLmSensor, printLmSensorInfo, sm );
+ } else {
+ free( p->fullName );
+ free( p );
+ }
+ free( label );
+ }
+ }
+ bsort_ctnr( LmSensors, sensorCmp );
+}
+#else /* SENSORS_API_VERSION & 0x400 */
+void initLmSensors( struct SensorModul* sm )
+{
+ const sensors_chip_name* scn;
+ char buffer[BUFFER_SIZE_LMSEN];
+ int nr = 0;
+
+ FILE* input;
+ if ( ( input = fopen( "/etc/sensors.conf", "r" ) ) == NULL ) {
+ LmSensorsOk = -1;
+ return;
+ }
+
+ if ( sensors_init( input ) ) {
+ LmSensorsOk = -1;
+ fclose( input );
+ return;
+ }
+
+ fclose( input );
+
+ LmSensors = new_ctnr();
+ while ( ( scn = sensors_get_detected_chips( &nr ) ) != NULL ) {
+ int nr1, nr2;
+ const sensors_feature_data* sfd;
+ nr1 = nr2 = 0;
+ while ( ( sfd = sensors_get_all_features( *scn, &nr1, &nr2 ) ) != 0 ) {
+ if ( sfd->mapping == SENSORS_NO_MAPPING && sfd->mode & SENSORS_MODE_R /* readable feature */) {
+ LMSENSOR* p;
+ char* label=NULL;
+
+ if(sensors_get_label( *scn, sfd->number, &label ) != 0)
+ continue; /*error*/
+ else
+ free( label );
+ if(sensors_get_ignored( *scn, sfd->number) != 1 )
+ continue; /* 1 for not ignored, 0 for ignore, <0 for error */
+ double result;
+ if(sensors_get_feature( *scn, sfd->number, &result) != 0 )
+ continue; /* Make sure this feature actually works. 0 for success, <0 for fail */
+
+ p = (LMSENSOR*)malloc( sizeof( LMSENSOR ) );
+
+ snprintf( buffer, BUFFER_SIZE_LMSEN, "lmsensors/%s/%s", chipName(scn), sfd->name );
+
+ p->fullName = strndup(buffer, BUFFER_SIZE_LMSEN);
+
+ p->scn = scn;
+ p->sfd = sfd;
+ if ( search_ctnr( LmSensors, sensorCmp, p ) < 0 ) {
+ push_ctnr( LmSensors, p );
+ registerMonitor( p->fullName, "float", printLmSensor, printLmSensorInfo, sm );
+ } else {
+ free( p->fullName );
+ free( p );
+ }
+ }
+ }
+ }
+ bsort_ctnr( LmSensors, sensorCmp );
+}
+#endif /* SENSORS_API_VERSION & 0x400 */
+
+void exitLmSensors( void )
+{
+ destr_ctnr( LmSensors, free );
+}
+
+void printLmSensor( const char* cmd )
+{
+ double value;
+ LMSENSOR* s;
+
+ if ( ( s = findMatchingSensor( cmd ) ) == 0 ) { /* should never happen */
+ fprintf( CurrentClient, "0\n" );
+ return;
+ }
+#if SENSORS_API_VERSION & 0x400
+ sensors_get_value( s->scn, s->sfd->number, &value );
+#else
+ sensors_get_feature( *(s->scn), s->sfd->number, &value );
+#endif
+ fprintf( CurrentClient, "%f\n", value );
+}
+
+void printLmSensorInfo( const char* cmd )
+{
+ LMSENSOR* s;
+
+ if ( ( s = findMatchingSensor( cmd ) ) == 0 ) { /* should never happen */
+ fprintf( CurrentClient, "0\n" );
+ return;
+ }
+
+ /* TODO: print real name here */
+ char *label;
+#if SENSORS_API_VERSION & 0x400
+ label = sensors_get_label( s->scn, s->sf );
+ if (label == NULL) {
+#else
+ if(sensors_get_label( *s->scn, s->sfd->number, &label ) != 0) { /*error*/
+#endif
+ fprintf( CurrentClient, "0\n" );
+ return;
+ }
+ if( strncmp(s->sfd->name, "temp", sizeof("temp")-1) == 0)
+ fprintf( CurrentClient, "%s\t0\t0\t°C\n", label );
+ else if( strncmp(s->sfd->name, "fan", sizeof("fan")-1) == 0)
+ fprintf( CurrentClient, "%s\t0\t0\trpm\n", label );
+ else
+ fprintf( CurrentClient, "%s\t0\t0\tV\n", label ); /* For everything else, say it's in volts. */
+#if SENSORS_API_VERSION & 0x400
+ free(label);
+#endif
+}
+
+#else /* HAVE_SENSORS_SENSORS_H */
+
+/* dummy version for systems that have no lmsensors support */
+
+void initLmSensors( struct SensorModul* sm )
+{
+ (void)sm;
+}
+
+void exitLmSensors( void )
+{
+}
+
+#endif
diff --git a/ksysguard/ksysguardd/Linux/lmsensors.h b/ksysguard/ksysguardd/Linux/lmsensors.h
new file mode 100644
index 000000000..29f514d4a
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/lmsensors.h
@@ -0,0 +1,30 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_LMSENSORS_H
+#define KSG_LMSENSORS_H
+
+void initLmSensors( struct SensorModul* );
+void exitLmSensors( void );
+
+void printLmSensor( const char* );
+void printLmSensorInfo( const char* );
+
+#endif
diff --git a/ksysguard/ksysguardd/Linux/loadavg.c b/ksysguard/ksysguardd/Linux/loadavg.c
new file mode 100644
index 000000000..788e32793
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/loadavg.c
@@ -0,0 +1,143 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include "ksysguardd.h"
+#include "Command.h"
+
+#include "loadavg.h"
+
+static int LoadAvgOK = 0;
+static double LoadAvg1, LoadAvg5, LoadAvg15;
+
+#define LOADAVGBUFSIZE 128
+static char LoadAvgBuf[ LOADAVGBUFSIZE ];
+static int Dirty = 0;
+
+static void processLoadAvg( void )
+{
+ sscanf( LoadAvgBuf, "%lf %lf %lf", &LoadAvg1, &LoadAvg5, &LoadAvg15 );
+ Dirty = 0;
+}
+
+/*
+================================ public part =================================
+*/
+
+void initLoadAvg( struct SensorModul* sm )
+{
+ if ( updateLoadAvg() < 0 ) {
+ LoadAvgOK = -1;
+ return;
+ } else
+ LoadAvgOK = 1;
+
+ registerMonitor( "cpu/loadavg1", "float", printLoadAvg1, printLoadAvg1Info, sm );
+ registerMonitor( "cpu/loadavg5", "float", printLoadAvg5, printLoadAvg5Info, sm );
+ registerMonitor( "cpu/loadavg15", "float", printLoadAvg15, printLoadAvg15Info, sm );
+}
+
+void exitLoadAvg( void )
+{
+ LoadAvgOK = -1;
+}
+
+int updateLoadAvg( void )
+{
+ size_t n;
+ int fd;
+
+ if ( LoadAvgOK < 0 )
+ return -1;
+
+ if ( ( fd = open( "/proc/loadavg", O_RDONLY ) ) < 0 ) {
+ if ( LoadAvgOK != 0 )
+ print_error( "Cannot open file \'/proc/loadavg\'!\n"
+ "The kernel needs to be compiled with support\n"
+ "for /proc filesystem enabled!\n" );
+ return -1;
+ }
+
+ if ( ( n = read( fd, LoadAvgBuf, LOADAVGBUFSIZE - 1 ) ) == LOADAVGBUFSIZE - 1 ) {
+ log_error( "Internal buffer too small to read \'/proc/loadavg\'" );
+
+ close( fd );
+ return -1;
+ }
+
+ close( fd );
+ LoadAvgBuf[ n ] = '\0';
+ Dirty = 1;
+
+ return 0;
+}
+
+void printLoadAvg1( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processLoadAvg();
+
+ fprintf( CurrentClient, "%f\n", LoadAvg1 );
+}
+
+void printLoadAvg1Info( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Load average 1 min\t0\t0\t\n" );
+}
+
+void printLoadAvg5( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processLoadAvg();
+
+ fprintf( CurrentClient, "%f\n", LoadAvg5 );
+}
+
+void printLoadAvg5Info( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Load average 5 min\t0\t0\t\n" );
+}
+
+void printLoadAvg15( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processLoadAvg();
+
+ fprintf( CurrentClient, "%f\n", LoadAvg15 );
+}
+
+void printLoadAvg15Info( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Load average 15 min\t0\t0\t\n" );
+}
diff --git a/ksysguard/ksysguardd/Linux/loadavg.h b/ksysguard/ksysguardd/Linux/loadavg.h
new file mode 100644
index 000000000..31628ac96
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/loadavg.h
@@ -0,0 +1,36 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_LOADAVG_H
+#define KSG_LOADAVG_H
+
+void initLoadAvg( struct SensorModul* );
+void exitLoadAvg( void );
+
+int updateLoadAvg( void );
+
+void printLoadAvg1( const char* );
+void printLoadAvg1Info( const char* );
+void printLoadAvg5( const char* );
+void printLoadAvg5Info( const char* );
+void printLoadAvg15( const char* );
+void printLoadAvg15Info( const char* );
+
+#endif
diff --git a/ksysguard/ksysguardd/Linux/logfile.c b/ksysguard/ksysguardd/Linux/logfile.c
new file mode 100644
index 000000000..58915a207
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/logfile.c
@@ -0,0 +1,172 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "Command.h"
+#include "ccont.h"
+#include "conf.h"
+#include "ksysguardd.h"
+
+#include "logfile.h"
+
+static CONTAINER LogFiles = 0;
+static unsigned long counter = 1;
+
+typedef struct {
+ char name[ 256 ];
+ FILE* fh;
+ unsigned long id;
+} LogFileEntry;
+
+extern CONTAINER LogFileList;
+
+/*
+================================ public part =================================
+*/
+
+void initLogFile( struct SensorModul* sm )
+{
+ char monitor[ 1024 ];
+ ConfigLogFile *entry;
+
+ registerCommand( "logfile_register", registerLogFile );
+ registerCommand( "logfile_unregister", unregisterLogFile );
+ registerCommand( "logfile_registered", printRegistered );
+
+ for ( entry = first_ctnr( LogFileList ); entry; entry = next_ctnr( LogFileList ) ) {
+ FILE* fp;
+ /* Register the log file only if we can actually read the file. */
+ if ( ( fp = fopen( entry->path, "r" ) ) != NULL ) {
+ snprintf( monitor, 1024, "logfiles/%s", entry->name );
+ registerMonitor( monitor, "logfile", printLogFile, printLogFileInfo, sm );
+ fclose( fp );
+ }
+ }
+
+ LogFiles = new_ctnr();
+}
+
+void exitLogFile( void )
+{
+ destr_ctnr( LogFiles, free );
+}
+
+void printLogFile( const char* cmd )
+{
+ char line[ 1024 ];
+ unsigned long id;
+ LogFileEntry *entry;
+
+ sscanf( cmd, "%*s %lu", &id );
+
+ for ( entry = first_ctnr( LogFiles ); entry; entry = next_ctnr( LogFiles ) ) {
+ if ( entry->id == id ) {
+ while ( fgets( line, 1024, entry->fh ) != NULL )
+ fprintf( CurrentClient, "%s", line );
+
+ /* delete the EOF */
+ clearerr( entry->fh );
+ }
+ }
+
+ fprintf( CurrentClient, "\n" );
+}
+
+void printLogFileInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "LogFile\n" );
+}
+
+void registerLogFile( const char* cmd )
+{
+ char name[ 257 ];
+ FILE* file;
+ LogFileEntry *entry;
+ int i;
+
+ memset( name, 0, sizeof( name ) );
+ sscanf( cmd, "%*s %256s", name );
+
+ for ( i = 0; i < level_ctnr( LogFileList ); i++ ) {
+ ConfigLogFile *conf = get_ctnr( LogFileList, i );
+ if ( !strcmp( conf->name, name ) ) {
+ if ( ( file = fopen( conf->path, "r" ) ) == NULL ) {
+ print_error( "fopen()" );
+ fprintf( CurrentClient, "0\n" );
+ return;
+ }
+
+ fseek( file, 0, SEEK_END );
+
+ if ( ( entry = (LogFileEntry*)malloc( sizeof( LogFileEntry ) ) ) == NULL ) {
+ print_error( "malloc()" );
+ fprintf( CurrentClient, "0\n" );
+ return;
+ }
+
+ entry->fh = file;
+ strncpy( entry->name, conf->name, 256 );
+ entry->id = counter;
+
+ push_ctnr( LogFiles, entry );
+
+ fprintf( CurrentClient, "%lu\n", counter );
+ counter++;
+
+ return;
+ }
+ }
+
+ fprintf( CurrentClient, "\n" );
+}
+
+void unregisterLogFile( const char* cmd )
+{
+ unsigned long id;
+ LogFileEntry *entry;
+
+ sscanf( cmd, "%*s %lu", &id );
+
+ for ( entry = first_ctnr( LogFiles ); entry; entry = next_ctnr( LogFiles ) ) {
+ if ( entry->id == id ) {
+ fclose( entry->fh );
+ free( remove_ctnr( LogFiles ) );
+ fprintf( CurrentClient, "\n" );
+ return;
+ }
+ }
+
+ fprintf( CurrentClient, "\n" );
+}
+
+void printRegistered( const char* cmd )
+{
+ LogFileEntry *entry;
+
+ (void)cmd;
+ for ( entry = first_ctnr( LogFiles ); entry; entry = next_ctnr( LogFiles ) )
+ fprintf( CurrentClient, "%s:%lu\n", entry->name, entry->id );
+
+ fprintf( CurrentClient, "\n" );
+}
diff --git a/ksysguard/ksysguardd/Linux/logfile.h b/ksysguard/ksysguardd/Linux/logfile.h
new file mode 100644
index 000000000..5eecb2f70
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/logfile.h
@@ -0,0 +1,36 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_LOGFILE_H
+#define KSG_LOGFILE_H
+
+void initLogFile( struct SensorModul* );
+void exitLogFile( void );
+
+void printLogFile( const char* );
+void printLogFileInfo( const char* );
+
+void registerLogFile( const char* );
+void unregisterLogFile( const char* );
+
+/* debug command */
+void printRegistered( const char* );
+
+#endif
diff --git a/ksysguard/ksysguardd/Linux/netdev.c b/ksysguard/ksysguardd/Linux/netdev.c
new file mode 100644
index 000000000..55e812807
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/netdev.c
@@ -0,0 +1,367 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "Command.h"
+#include "ksysguardd.h"
+
+#include "netdev.h"
+
+#define MON_SIZE 128
+
+#define CALC( a, b, c, d, e ) \
+{ \
+ NetDevs[ i ].a = a - NetDevs[ i ].Old##a; \
+ NetDevs[ i ].Old##a = a; \
+}
+
+#define REGISTERSENSOR( a, b, c, d, e ) \
+{ \
+ snprintf( mon, MON_SIZE, "network/interfaces/%s/%s", tag, b ); \
+ registerMonitor( mon, "integer", printNetDev##a, printNetDev##a##Info, NetDevSM ); \
+}
+
+#define UNREGISTERSENSOR( a, b, c, d, e ) \
+{ \
+ snprintf( mon, MON_SIZE, "network/interfaces/%s/%s", NetDevs[ i ].name, b ); \
+ removeMonitor( mon ); \
+}
+
+#define DEFMEMBERS( a, b, c, d, e ) \
+unsigned long long Old##a; \
+unsigned long long a; \
+unsigned long a##Scale;
+
+#define DEFVARS( a, b, c, d, e ) \
+unsigned long long a;
+
+#define FORALL( a ) \
+ a( recBytes, "receiver/data", "Received Data", "kBytes/s", 1024 ) \
+ a( recPacks, "receiver/packets", "Received Packets", "1/s", 1 ) \
+ a( recErrs, "receiver/errors", "Receiver Errors", "1/s", 1 ) \
+ a( recDrop, "receiver/drops", "Receiver Drops", "1/s", 1 ) \
+ a( recFifo, "receiver/fifo", "Receiver FIFO Overruns", "1/s", 1 ) \
+ a( recFrame, "receiver/frame", "Receiver Frame Errors", "1/s", 1 ) \
+ a( recCompressed, "receiver/compressed", "Received Compressed Packets", "1/s", 1 ) \
+ a( recMulticast, "receiver/multicast", "Received Multicast Packets", "1/s", 1 ) \
+ a( sentBytes, "transmitter/data", "Sent Data", "kBytes/s", 1024 ) \
+ a( sentPacks, "transmitter/packets", "Sent Packets", "1/s", 1 ) \
+ a( sentErrs, "transmitter/errors", "Transmitter Errors", "1/s", 1 ) \
+ a( sentDrop, "transmitter/drops", "Transmitter Drops", "1/s", 1 ) \
+ a( sentFifo, "transmitter/fifo", "Transmitter FIFO overruns", "1/s", 1 ) \
+ a( sentColls, "transmitter/collisions", "Transmitter Collisions", "1/s", 1 ) \
+ a( sentCarrier, "transmitter/carrier", "Transmitter Carrier losses", "1/s", 1 ) \
+ a( sentCompressed, "transmitter/compressed", "Transmitter Compressed Packets", "1/s", 1 )
+
+#define SETZERO( a, b, c, d, e ) \
+a = 0;
+
+#define SETMEMBERZERO( a, b, c, d, e ) \
+NetDevs[ i ].a = 0; \
+NetDevs[ i ].a##Scale = e;
+
+#define DECLAREFUNC( a, b, c, d, e ) \
+void printNetDev##a( const char* cmd ); \
+void printNetDev##a##Info( const char* cmd );
+
+typedef struct
+{
+ FORALL( DEFMEMBERS )
+ char name[ 32 ];
+} NetDevInfo;
+
+/* We have observed deviations of up to 5% in the accuracy of the timer
+ * interrupts. So we try to measure the interrupt interval and use this
+ * value to calculate timing dependant values. */
+static float timeInterval = 0;
+static struct timeval lastSampling;
+static struct timeval currSampling;
+static struct SensorModul* NetDevSM;
+
+#define NETDEVBUFSIZE 4096
+static char NetDevBuf[ NETDEVBUFSIZE ];
+static int NetDevCnt = 0;
+static int Dirty = 0;
+static int NetDevOk = 0;
+static long OldHash = 0;
+
+#define MAXNETDEVS 64
+static NetDevInfo NetDevs[ MAXNETDEVS ];
+
+void processNetDev( void );
+
+FORALL( DECLAREFUNC )
+
+static int processNetDev_( void )
+{
+ int i;
+ char format[ 32 ];
+ char devFormat[ 16 ];
+ char buf[ 1024 ];
+ char tag[ 64 ];
+ char* netDevBufP = NetDevBuf;
+
+ sprintf( format, "%%%d[^\n]\n", (int)sizeof( buf ) - 1 );
+ sprintf( devFormat, "%%%ds", (int)sizeof( tag ) - 1 );
+
+ /* skip 2 first lines */
+ for ( i = 0; i < 2; i++ ) {
+ sscanf( netDevBufP, format, buf );
+ buf[ sizeof( buf ) - 1 ] = '\0';
+ netDevBufP += strlen( buf ) + 1; /* move netDevBufP to next line */
+ }
+
+ for ( i = 0; sscanf( netDevBufP, format, buf ) == 1; ++i ) {
+ buf[ sizeof( buf ) - 1 ] = '\0';
+ netDevBufP += strlen( buf ) + 1; /* move netDevBufP to next line */
+
+ if ( sscanf( buf, devFormat, tag ) ) {
+ char* pos = strchr( tag, ':' );
+ if ( pos ) {
+ FORALL( DEFVARS );
+ *pos = '\0';
+ FORALL( SETZERO );
+ sscanf( buf + 7, "%llu %llu %llu %llu %llu %llu %llu %llu "
+ "%llu %llu %llu %llu %llu %llu %llu %llu",
+ &recBytes, &recPacks, &recErrs, &recDrop, &recFifo,
+ &recFrame, &recCompressed, &recMulticast,
+ &sentBytes, &sentPacks, &sentErrs, &sentDrop,
+ &sentFifo, &sentColls, &sentCarrier, &sentCompressed );
+
+ if ( i >= NetDevCnt || strcmp( NetDevs[ i ].name, tag ) != 0 ) {
+ /* The network device configuration has changed. We
+ * need to reconfigure the netdev module. */
+ return -1;
+ } else {
+ FORALL( CALC );
+ }
+ }
+ }
+ }
+
+ if ( i != NetDevCnt )
+ return -1;
+
+ /* save exact time inverval between this and the last read of
+ * /proc/net/dev */
+ timeInterval = currSampling.tv_sec - lastSampling.tv_sec +
+ ( currSampling.tv_usec - lastSampling.tv_usec ) / 1000000.0;
+ lastSampling = currSampling;
+ Dirty = 0;
+
+ return 0;
+}
+
+void processNetDev( void )
+{
+ int i;
+
+ if ( NetDevCnt == 0 )
+ return;
+
+ for ( i = 0; i < 5 && processNetDev_() < 0; ++i )
+ checkNetDev();
+
+ /* If 5 reconfiguration attemts failed, something is very wrong and
+ * we close the netdev module for further use. */
+ if ( i == 5 )
+ exitNetDev();
+}
+
+/*
+================================ public part =================================
+*/
+
+void initNetDev( struct SensorModul* sm )
+{
+ int i;
+ char format[ 32 ];
+ char devFormat[ 16 ];
+ char buf[ 1024 ];
+ char tag[ 64 ];
+ char* netDevBufP = NetDevBuf;
+
+ NetDevSM = sm;
+
+ if ( updateNetDev() < 0 )
+ return;
+
+ sprintf( format, "%%%d[^\n]\n", (int)sizeof( buf ) - 1 );
+ sprintf( devFormat, "%%%ds", (int)sizeof( tag ) - 1 );
+
+ /* skip 2 first lines */
+ for ( i = 0; i < 2; i++ ) {
+ sscanf( netDevBufP, format, buf );
+ buf[ sizeof( buf ) - 1 ] = '\0';
+ netDevBufP += strlen( buf ) + 1; /* move netDevBufP to next line */
+ }
+
+ for ( i = 0; sscanf( netDevBufP, format, buf ) == 1; ++i ) {
+ buf[ sizeof( buf ) - 1 ] = '\0';
+ netDevBufP += strlen( buf ) + 1; /* move netDevBufP to next line */
+
+ if ( sscanf( buf, devFormat, tag ) ) {
+ char* pos = strchr( tag, ':' );
+ if ( pos ) {
+ char mon[ MON_SIZE ];
+ *pos = '\0';
+ strlcpy( NetDevs[ i ].name, tag, sizeof( NetDevs[ i ].name ) );
+ FORALL( REGISTERSENSOR );
+ sscanf( pos + 1, "%llu %llu %llu %llu %llu %llu %llu %llu"
+ "%llu %llu %llu %llu %llu %llu %llu %llu",
+ &NetDevs[ i ].recBytes, &NetDevs[ i ].recPacks,
+ &NetDevs[ i ].recErrs, &NetDevs[ i ].recDrop,
+ &NetDevs[ i ].recFifo, &NetDevs[ i ].recFrame,
+ &NetDevs[ i ].recCompressed, &NetDevs[ i ].recMulticast,
+ &NetDevs[ i ].sentBytes, &NetDevs[ i ].sentPacks,
+ &NetDevs[ i ].sentErrs, &NetDevs[ i ].sentDrop,
+ &NetDevs[ i ].sentFifo, &NetDevs[ i ].sentColls,
+ &NetDevs[ i ].sentCarrier, &NetDevs[ i ].sentCompressed );
+ NetDevCnt++;
+ }
+ FORALL( SETMEMBERZERO );
+ }
+ }
+
+ /* Call processNetDev to elimitate initial peek values. */
+ processNetDev();
+}
+
+void exitNetDev( void )
+{
+ int i;
+
+ for ( i = 0; i < NetDevCnt; ++i ) {
+ char mon[ MON_SIZE ];
+ FORALL( UNREGISTERSENSOR );
+ }
+ NetDevCnt = 0;
+}
+
+int updateNetDev( void )
+{
+ /* We read the information about the network interfaces from
+ /proc/net/dev. The file should look like this:
+
+ Inter-| Receive | Transmit
+ face | bytes packets errs drop fifo frame compressed multicast| bytes packets errs drop fifo colls carrier compressed
+ lo:275135772 1437448 0 0 0 0 0 0 275135772 1437448 0 0 0 0 0 0
+ eth0:123648812 655251 0 0 0 0 0 0 246847871 889636 0 0 0 0 0 0 Inter-| Receive | Transmit
+ face | bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
+ lo:275135772 1437448 0 0 0 0 0 0 275135772 1437448 0 0 0 0 0 0
+ eth0:123648812 655251 0 0 0 0 0 0 246847871 889636 0 0 0 0 0 0
+ */
+
+ size_t n;
+ int fd;
+ long hash;
+ char* p;
+
+ if ( NetDevOk < 0 )
+ return 0;
+
+ if ( ( fd = open( "/proc/net/dev", O_RDONLY ) ) < 0 ) {
+ /* /proc/net/dev may not exist on some machines. */
+ NetDevOk = -1;
+ return 0;
+ }
+
+ if ( ( n = read( fd, NetDevBuf, NETDEVBUFSIZE - 1 ) ) == NETDEVBUFSIZE - 1 ) {
+ log_error( "Internal buffer too small to read \'/proc/net/dev\'" );
+ NetDevOk = -1;
+
+ close( fd );
+ return -1;
+ }
+
+ gettimeofday( &currSampling, 0 );
+ close( fd );
+ NetDevOk = 1;
+ NetDevBuf[ n ] = '\0';
+
+ /* Calculate hash over the first 7 characters of each line starting
+ * after the first newline. */
+ for ( p = NetDevBuf, hash = 0; *p; ++p )
+ if ( *p == '\n' )
+ for ( ++p; *p && *p != ':' && *p != '|'; ++p )
+ hash = ( ( hash << 6 ) + *p ) % 390389;
+
+ if ( OldHash != 0 && OldHash != hash ) {
+ print_error( "RECONFIGURE\n" );
+ CheckSetupFlag = 1;
+ }
+ OldHash = hash;
+
+ Dirty = 1;
+
+ return 0;
+}
+
+void checkNetDev( void )
+{
+ /* Values for other network devices are lost, but it is still better
+ * than not detecting any new devices. TODO: Fix after 2.1 is out. */
+ exitNetDev();
+ initNetDev( NetDevSM );
+}
+
+#define PRINTFUNC( a, b, c, d, e ) \
+void printNetDev##a( const char* cmd ) \
+{ \
+ int i; \
+ char* beg; \
+ char* end; \
+ char dev[ 64 ]; \
+ \
+ beg = strchr( cmd, '/' ); \
+ beg = strchr( beg + 1, '/' ); \
+ end = strchr( beg + 1, '/' ); \
+ strncpy( dev, beg + 1, end - beg - 1 ); \
+ dev[ end - beg - 1 ] = '\0'; \
+ \
+ if ( Dirty ) \
+ processNetDev(); \
+ \
+ for ( i = 0; i < MAXNETDEVS; ++i ) \
+ if ( strcmp( NetDevs[ i ].name, dev ) == 0) { \
+ fprintf( CurrentClient, "%lu\n", (unsigned long) \
+ ( NetDevs[ i ].a / ( NetDevs[ i ].a##Scale * timeInterval ) ) ); \
+ return; \
+ } \
+ \
+ fprintf( CurrentClient, "0\n" ); \
+} \
+ \
+void printNetDev##a##Info( const char* cmd ) \
+{ \
+ (void)cmd; \
+ fprintf( CurrentClient, "%s\t0\t0\t%s\n", c, d ); \
+}
+
+FORALL( PRINTFUNC )
diff --git a/ksysguard/ksysguardd/Linux/netdev.h b/ksysguard/ksysguardd/Linux/netdev.h
new file mode 100644
index 000000000..d470adfae
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/netdev.h
@@ -0,0 +1,35 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_NETDEV_H
+#define KSG_NETDEV_H
+
+void initNetDev( struct SensorModul* );
+void exitNetDev( void );
+
+int updateNetDev( void );
+void checkNetDev( void );
+
+void printNetDevRecBytes( const char* );
+void printNetDevRecBytesInfo( const char* );
+void printNetDevSentBytes( const char* );
+void printNetDevSentBytesInfo( const char* );
+
+#endif
diff --git a/ksysguard/ksysguardd/Linux/netstat.c b/ksysguard/ksysguardd/Linux/netstat.c
new file mode 100644
index 000000000..c8570f617
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/netstat.c
@@ -0,0 +1,495 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "ksysguardd.h"
+#include "Command.h"
+#include "ccont.h"
+#include "netstat.h"
+
+static CONTAINER TcpSocketList = 0;
+static CONTAINER UdpSocketList = 0;
+static CONTAINER UnixSocketList = 0;
+static CONTAINER RawSocketList = 0;
+
+static int num_tcp = 0;
+static int num_udp = 0;
+static int num_unix = 0;
+static int num_raw = 0;
+
+typedef struct {
+ char local_addr[128];
+ char local_port[128];
+ char remote_addr[128];
+ char remote_port[128];
+ char state[128];
+ int uid;
+} SocketInfo;
+
+typedef struct {
+ int refcount;
+ char type[128];
+ char state[128];
+ int inode;
+ char path[256];
+} UnixInfo;
+
+char *get_serv_name(int port, const char *proto);
+char *get_host_name(int addr);
+char *get_proto_name(int number);
+int get_num_sockets(FILE *netstat);
+void printSocketInfo(SocketInfo* socket_info);
+
+static time_t TcpUdpRaw_timeStamp = 0;
+static time_t Unix_timeStamp = 0;
+static time_t NetStat_timeStamp = 0;
+
+static const char *raw_type[] =
+{
+ "",
+ "stream",
+ "dgram",
+ "raw",
+ "rdm",
+ "seqpacket",
+ "packet"
+};
+
+static const char *raw_state[] =
+{
+ "free",
+ "unconnected",
+ "connecting",
+ "connected",
+ "disconnecting"
+};
+
+static const char *conn_state[] =
+{
+ "",
+ "established",
+ "syn_sent",
+ "syn_recv",
+ "fin_wait1",
+ "fin_wait2",
+ "time_wait",
+ "close",
+ "close_wait",
+ "last_ack",
+ "listen",
+ "closing"
+};
+
+char *get_serv_name(int port, const char *proto)
+{
+ static char buffer[1024];
+ struct servent *service;
+
+ if (port == 0) {
+ return (char *)"*";
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+
+ if ((service = getservbyport(ntohs(port), proto)) == NULL) {
+ snprintf(buffer, sizeof(buffer), "%d", port);
+ } else {
+ strlcpy(buffer, service->s_name, sizeof(buffer));
+ }
+
+ return (char *)buffer;
+}
+
+char *get_host_name(int addr)
+{
+ static char buffer[1024];
+ struct hostent *host;
+ struct in_addr a_addr;
+
+ if (addr == 0) {
+ return (char *)"*";
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+
+ if ((host = gethostbyaddr((char *)&addr, 4, AF_INET)) == NULL) {
+ a_addr.s_addr = addr;
+ return inet_ntoa(a_addr);
+ } else {
+ strlcpy(buffer, host->h_name, sizeof(buffer));
+ return (char *)buffer;
+ }
+}
+
+char *get_proto_name(int number)
+{
+ static char buffer[1024];
+ struct protoent *protocol;
+
+ if (number == 0) {
+ return (char *)"*";
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+
+ if ((protocol = getprotobynumber(number)) == NULL) {
+ snprintf(buffer, sizeof(buffer), "%d", number);
+ } else {
+ strlcpy(buffer, protocol->p_name, sizeof(buffer));
+ }
+
+ return (char *)buffer;
+}
+
+int get_num_sockets(FILE *netstat)
+{
+ char line[1024];
+ int line_count = 0;
+
+ while (fgets(line, 1024, netstat) != NULL)
+ line_count++;
+
+ return line_count - 1;
+}
+
+void printSocketInfo(SocketInfo* socket_info)
+{
+ fprintf(CurrentClient, "%s\t%s\t%s\t%s\t%s\t%d\n",
+ socket_info->local_addr,
+ socket_info->local_port,
+ socket_info->remote_addr,
+ socket_info->remote_port,
+ socket_info->state,
+ socket_info->uid);
+}
+
+/*
+================================ public part =================================
+*/
+
+void
+initNetStat(struct SensorModul* sm)
+{
+ FILE *netstat;
+
+ if ((netstat = fopen("/proc/net/tcp", "r")) != NULL) {
+ registerMonitor("network/sockets/tcp/count", "integer", printNetStat, printNetStatInfo, sm);
+ registerMonitor("network/sockets/tcp/list", "listview", printNetStatTcpUdpRaw, printNetStatTcpUdpRawInfo, sm);
+ fclose(netstat);
+ }
+ if ((netstat = fopen("/proc/net/udp", "r")) != NULL) {
+ registerMonitor("network/sockets/udp/count", "integer", printNetStat, printNetStatInfo, sm);
+ registerMonitor("network/sockets/udp/list", "listview", printNetStatTcpUdpRaw, printNetStatTcpUdpRawInfo, sm);
+ fclose(netstat);
+ }
+ if ((netstat = fopen("/proc/net/unix", "r")) != NULL) {
+ registerMonitor("network/sockets/unix/count", "integer", printNetStat, printNetStatInfo, sm);
+ registerMonitor("network/sockets/unix/list", "listview", printNetStatUnix, printNetStatUnixInfo, sm);
+ fclose(netstat);
+ }
+ if ((netstat = fopen("/proc/net/raw", "r")) != NULL) {
+ registerMonitor("network/sockets/raw/count", "integer", printNetStat, printNetStatInfo, sm);
+ registerMonitor("network/sockets/raw/list", "listview", printNetStatTcpUdpRaw, printNetStatTcpUdpRawInfo, sm);
+ fclose(netstat);
+ }
+
+ TcpSocketList = new_ctnr();
+ UdpSocketList = new_ctnr();
+ RawSocketList = new_ctnr();
+ UnixSocketList = new_ctnr();
+}
+
+void
+exitNetStat(void)
+{
+ destr_ctnr(TcpSocketList, free);
+ destr_ctnr(UdpSocketList, free);
+ destr_ctnr(RawSocketList, free);
+ destr_ctnr(UnixSocketList, free);
+}
+
+int
+updateNetStat(void)
+{
+ FILE *netstat;
+
+ if ((netstat = fopen("/proc/net/tcp", "r")) != NULL) {
+ num_tcp = get_num_sockets(netstat);
+ fclose(netstat);
+ }
+
+ if ((netstat = fopen("/proc/net/udp", "r")) != NULL) {
+ num_udp = get_num_sockets(netstat);
+ fclose(netstat);
+ }
+
+ if ((netstat = fopen("/proc/net/unix", "r")) != NULL) {
+ num_unix = get_num_sockets(netstat);
+ fclose(netstat);
+ }
+ if ((netstat = fopen("/proc/net/raw", "r")) != NULL) {
+ num_raw = get_num_sockets(netstat);
+ fclose(netstat);
+ }
+
+ NetStat_timeStamp = time(0);
+ return 0;
+}
+
+int
+updateNetStatTcpUdpRaw(const char *cmd)
+{
+ FILE *netstat;
+ char buffer[1024];
+ uint local_addr, local_port;
+ uint remote_addr, remote_port;
+ int uid, i;
+ uint state;
+ SocketInfo *socket_info;
+
+ if (strstr(cmd, "tcp")) {
+ snprintf(buffer, sizeof(buffer), "/proc/net/tcp");
+ for (i = level_ctnr(TcpSocketList); i >= 0; --i)
+ free(pop_ctnr(TcpSocketList));
+ }
+
+ if (strstr(cmd, "udp")) {
+ snprintf(buffer, sizeof(buffer), "/proc/net/udp");
+ for (i = level_ctnr(UdpSocketList); i >= 0; --i)
+ free(pop_ctnr(UdpSocketList));
+ }
+
+ if (strstr(cmd, "raw")) {
+ snprintf(buffer, sizeof(buffer), "/proc/net/raw");
+ for (i = level_ctnr(RawSocketList); i >= 0; --i)
+ free(pop_ctnr(RawSocketList));
+ }
+
+ if ((netstat = fopen(buffer, "r")) == NULL) {
+ print_error("Cannot open \'%s\'!\n"
+ "The kernel needs to be compiled with support\n"
+ "for /proc filesystem enabled!\n", buffer);
+ return -1;
+ }
+
+ fgets(buffer, sizeof(buffer), netstat);
+
+ while (fgets(buffer, sizeof(buffer), netstat) != NULL) {
+ if (strcmp(buffer, "")) {
+ sscanf(buffer, "%*d: %x:%x %x:%x %x %*x:%*x %*x:%*x %d",
+ &local_addr, &local_port,
+ &remote_addr, &remote_port,
+ &state,
+ &uid);
+
+ if ((socket_info = (SocketInfo *)malloc(sizeof(SocketInfo))) == NULL) {
+ continue;
+ }
+ strlcpy(socket_info->local_addr, get_host_name(local_addr), sizeof(socket_info->local_addr));
+ strlcpy(socket_info->remote_addr, get_host_name(remote_addr), sizeof(socket_info->remote_addr));
+
+ if (strstr(cmd, "tcp")) {
+ strlcpy(socket_info->local_port, get_serv_name(local_port, "tcp"), sizeof(socket_info->local_port));
+ strlcpy(socket_info->remote_port, get_serv_name(remote_port, "tcp"), sizeof(socket_info->remote_port));
+ strlcpy(socket_info->state, conn_state[state], sizeof(socket_info->state));
+ socket_info->uid = uid;
+
+ push_ctnr(TcpSocketList, socket_info);
+ }
+
+ if (strstr(cmd, "udp")) {
+ strlcpy(socket_info->local_port, get_serv_name(local_port, "udp"), sizeof(socket_info->local_port));
+ strlcpy(socket_info->remote_port, get_serv_name(remote_port, "udp"), sizeof(socket_info->remote_port));
+ strlcpy(socket_info->state, conn_state[state], sizeof(socket_info->state));
+ socket_info->uid = uid;
+
+ push_ctnr(UdpSocketList, socket_info);
+ }
+
+ if (strstr(cmd, "raw")) {
+ strlcpy(socket_info->local_port, get_proto_name(local_port), sizeof(socket_info->local_port));
+ strlcpy(socket_info->remote_port, get_proto_name(remote_port), sizeof(socket_info->remote_port));
+ snprintf(socket_info->state, sizeof(socket_info->state)-1, "%d", state);
+ socket_info->uid = uid;
+
+ push_ctnr(RawSocketList, socket_info);
+ }
+ }
+ }
+ fclose(netstat);
+ TcpUdpRaw_timeStamp = time(0);
+
+ return 0;
+}
+
+int
+updateNetStatUnix(void)
+{
+ FILE *file;
+ char buffer[1024];
+ char path[256];
+ int ref_count, type, state, inode, i;
+ UnixInfo *unix_info;
+
+ if ((file = fopen("/proc/net/unix", "r")) == NULL) {
+ print_error("Cannot open \'/proc/net/unix\'!\n"
+ "The kernel needs to be compiled with support\n"
+ "for /proc filesystem enabled!\n");
+ return -1;
+ }
+
+ for (i = level_ctnr(UnixSocketList); i >= 0; --i)
+ free(pop_ctnr(UnixSocketList));
+
+ fgets(buffer, sizeof(buffer), file);
+
+ while (fgets(buffer, sizeof(buffer), file) != NULL) {
+ if (strcmp(buffer, "")) {
+ sscanf(buffer, "%*x: %d %*d %*d %d %d %d %255s",
+ &ref_count, &type, &state, &inode, path);
+
+ if ((unix_info = (UnixInfo *)malloc(sizeof(UnixInfo))) == NULL) {
+ continue;
+ }
+
+ unix_info->refcount = ref_count;
+ strlcpy(unix_info->type, raw_type[type], sizeof(unix_info->type));
+ strlcpy(unix_info->state, raw_state[state], sizeof(unix_info->state));
+ unix_info->inode = inode;
+ strlcpy(unix_info->path, path, sizeof(unix_info->path));
+
+ push_ctnr(UnixSocketList, unix_info);
+ }
+ }
+ fclose(file);
+ Unix_timeStamp = time(0);
+
+ return 0;
+}
+
+void
+printNetStat(const char* cmd)
+{
+ if ((time(0) - NetStat_timeStamp) >= UPDATEINTERVAL)
+ updateNetStat();
+
+ if (strstr(cmd, "tcp") != NULL)
+ fprintf(CurrentClient, "%d\n", num_tcp);
+ if (strstr(cmd, "udp") != NULL)
+ fprintf(CurrentClient, "%d\n", num_udp);
+ if (strstr(cmd, "unix") != NULL)
+ fprintf(CurrentClient, "%d\n", num_unix);
+ if (strstr(cmd, "raw") != NULL)
+ fprintf(CurrentClient, "%d\n", num_raw);
+}
+
+void
+printNetStatInfo(const char* cmd)
+{
+ if (strstr(cmd, "tcp") != NULL)
+ fprintf(CurrentClient, "Number of TCP-Sockets\t0\t0\tSockets\n");
+ if (strstr(cmd, "udp") != NULL)
+ fprintf(CurrentClient, "Number of UDP-Sockets\t0\t0\tSockets\n");
+ if (strstr(cmd, "unix") != NULL)
+ fprintf(CurrentClient, "Number of UnixDomain-Sockets\t0\t0\tSockets\n");
+ if (strstr(cmd, "raw") != NULL)
+ fprintf(CurrentClient, "Number of Raw-Sockets\t0\t0\tSockets\n");
+}
+
+void
+printNetStatTcpUdpRaw(const char *cmd)
+{
+ SocketInfo* socket_info;
+
+ if (strstr(cmd, "tcp")) {
+ if ((time(0) - TcpUdpRaw_timeStamp) >= UPDATEINTERVAL)
+ updateNetStatTcpUdpRaw("tcp");
+
+ for (socket_info = first_ctnr(TcpSocketList); socket_info; socket_info = next_ctnr(TcpSocketList))
+ printSocketInfo(socket_info);
+
+ if (level_ctnr(TcpSocketList) == 0)
+ fprintf(CurrentClient, "\n");
+ }
+
+ if (strstr(cmd, "udp")) {
+ if ((time(0) - TcpUdpRaw_timeStamp) >= UPDATEINTERVAL)
+ updateNetStatTcpUdpRaw("udp");
+
+ for (socket_info = first_ctnr(UdpSocketList); socket_info; socket_info = next_ctnr(UdpSocketList))
+ printSocketInfo(socket_info);
+
+ if (level_ctnr(UdpSocketList) == 0)
+ fprintf(CurrentClient, "\n");
+ }
+
+ if (strstr(cmd, "raw")) {
+ if ((time(0) - TcpUdpRaw_timeStamp) >= UPDATEINTERVAL)
+ updateNetStatTcpUdpRaw("raw");
+
+ for (socket_info = first_ctnr(RawSocketList); socket_info; socket_info = next_ctnr(RawSocketList))
+ printSocketInfo(socket_info);
+
+ if (level_ctnr(RawSocketList) == 0)
+ fprintf(CurrentClient, "\n");
+ }
+}
+
+void
+printNetStatTcpUdpRawInfo(const char *cmd)
+{
+ (void) cmd;
+ fprintf(CurrentClient, "Local Address\tPort\tForeign Address\tPort\tState\tUID\ns\ts\ts\ts\ts\td\n");
+}
+
+void printNetStatUnix(const char *cmd)
+{
+ UnixInfo* unix_info;
+
+ (void) cmd;
+ if ((time(0) - Unix_timeStamp) >= UPDATEINTERVAL)
+ updateNetStatUnix();
+
+ for (unix_info = first_ctnr(UnixSocketList); unix_info; unix_info = next_ctnr(UnixSocketList)) {
+ fprintf(CurrentClient, "%d\t%s\t%s\t%d\t%s\n",
+ unix_info->refcount,
+ unix_info->type,
+ unix_info->state,
+ unix_info->inode,
+ unix_info->path);
+ }
+
+ if (level_ctnr(UnixSocketList) == 0)
+ fprintf(CurrentClient, "\n");
+}
+
+void printNetStatUnixInfo(const char *cmd)
+{
+ (void) cmd;
+ fprintf(CurrentClient, "RefCount\tType\tState\tInode\tPath\nd\ts\ts\td\ts\n");
+}
diff --git a/ksysguard/ksysguardd/Linux/netstat.h b/ksysguard/ksysguardd/Linux/netstat.h
new file mode 100644
index 000000000..be0c3a850
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/netstat.h
@@ -0,0 +1,39 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _netstat_h_
+#define _netstat_h_
+
+void initNetStat(struct SensorModul* sm);
+void exitNetStat(void);
+
+int updateNetStat(void);
+int updateNetStatTcpUdpRaw(const char* cmd);
+int updateNetStatUnix(void);
+
+void printNetStat(const char* cmd);
+void printNetStatInfo(const char* cmd);
+
+void printNetStatTcpUdpRaw(const char *cmd);
+void printNetStatTcpUdpRawInfo(const char *cmd);
+
+void printNetStatUnix(const char *cmd);
+void printNetStatUnixInfo(const char *cmd);
+#endif
diff --git a/ksysguard/ksysguardd/Linux/stat.c b/ksysguard/ksysguardd/Linux/stat.c
new file mode 100644
index 000000000..0e03e4d53
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/stat.c
@@ -0,0 +1,1184 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "Command.h"
+#include "ksysguardd.h"
+
+#include "stat.h"
+
+typedef struct
+{
+ /* A CPU can be loaded with user processes, reniced processes and
+ * system processes. Unused processing time is called idle load.
+ * These variable store the percentage of each load type. */
+ int userLoad;
+ int niceLoad;
+ int sysLoad;
+ int idleLoad;
+
+ /* To calculate the loads we need to remember the tick values for each
+ * load type. */
+ unsigned long userTicks;
+ unsigned long niceTicks;
+ unsigned long sysTicks;
+ unsigned long idleTicks;
+} CPULoadInfo;
+
+typedef struct
+{
+ unsigned long delta;
+ unsigned long old;
+} DiskLoadSample;
+
+typedef struct
+{
+ /* 5 types of samples are taken:
+ total, rio, wio, rBlk, wBlk */
+ DiskLoadSample s[ 5 ];
+} DiskLoadInfo;
+
+typedef struct DiskIOInfo
+{
+ int major;
+ int minor;
+ int alive;
+ DiskLoadSample total;
+ DiskLoadSample rio;
+ DiskLoadSample wio;
+ DiskLoadSample rblk;
+ DiskLoadSample wblk;
+ struct DiskIOInfo* next;
+} DiskIOInfo;
+
+#define STATBUFSIZE (32 * 1024)
+
+static char StatBuf[ STATBUFSIZE ];
+static char VmStatBuf[ STATBUFSIZE ];
+static char IOStatBuf[ STATBUFSIZE ]; /* Buffer for /proc/diskstats */
+static int Dirty = 0;
+
+/* We have observed deviations of up to 5% in the accuracy of the timer
+ * interrupts. So we try to measure the interrupt interval and use this
+ * value to calculate timing dependant values. */
+static float timeInterval = 0;
+static struct timeval lastSampling;
+static struct timeval currSampling;
+static struct SensorModul* StatSM;
+
+static CPULoadInfo CPULoad;
+static CPULoadInfo* SMPLoad = 0;
+static unsigned CPUCount = 0;
+static DiskLoadInfo* DiskLoad = 0;
+static unsigned DiskCount = 0;
+static DiskIOInfo* DiskIO = 0;
+static unsigned long PageIn = 0;
+static unsigned long OldPageIn = 0;
+static unsigned long PageOut = 0;
+static unsigned long OldPageOut = 0;
+static unsigned long Ctxt = 0;
+static unsigned long OldCtxt = 0;
+static unsigned int NumOfInts = 0;
+static unsigned long* OldIntr = 0;
+static unsigned long* Intr = 0;
+
+static int initStatDisk( char* tag, char* buf, const char* label, const char* shortLabel,
+ int idx, cmdExecutor ex, cmdExecutor iq );
+static void updateCPULoad( const char* line, CPULoadInfo* load );
+static int processDisk( char* tag, char* buf, const char* label, int idx );
+static void processStat( void );
+static int processDiskIO( const char* buf );
+static int process26DiskIO( const char* buf );
+static void cleanupDiskList( void );
+
+static int initStatDisk( char* tag, char* buf, const char* label,
+ const char* shortLabel, int idx, cmdExecutor ex, cmdExecutor iq )
+{
+ char sensorName[ 128 ];
+
+ gettimeofday( &lastSampling, 0 );
+
+ if ( strcmp( label, tag ) == 0 ) {
+ unsigned int i;
+ buf = buf + strlen( label ) + 1;
+
+ for ( i = 0; i < DiskCount; ++i ) {
+ sscanf( buf, "%lu", &DiskLoad[ i ].s[ idx ].old );
+ while ( *buf && isblank( *buf++ ) );
+ while ( *buf && isdigit( *buf++ ) );
+ sprintf( sensorName, "disk/disk%d/%s", i, shortLabel );
+ registerMonitor( sensorName, "integer", ex, iq, StatSM );
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static void updateCPULoad( const char* line, CPULoadInfo* load )
+{
+ unsigned long currUserTicks, currSysTicks, currNiceTicks, currIdleTicks;
+ unsigned long totalTicks;
+
+ sscanf( line, "%*s %lu %lu %lu %lu", &currUserTicks, &currNiceTicks,
+ &currSysTicks, &currIdleTicks );
+
+ totalTicks = ( currUserTicks - load->userTicks ) +
+ ( currSysTicks - load->sysTicks ) +
+ ( currNiceTicks - load->niceTicks ) +
+ ( currIdleTicks - load->idleTicks );
+
+ if ( totalTicks > 10 ) {
+ load->userLoad = ( 100 * ( currUserTicks - load->userTicks ) ) / totalTicks;
+ load->sysLoad = ( 100 * ( currSysTicks - load->sysTicks ) ) / totalTicks;
+ load->niceLoad = ( 100 * ( currNiceTicks - load->niceTicks ) ) / totalTicks;
+ load->idleLoad = ( 100 - ( load->userLoad + load->sysLoad + load->niceLoad ) );
+ } else
+ load->userLoad = load->sysLoad = load->niceLoad = load->idleLoad = 0;
+
+ load->userTicks = currUserTicks;
+ load->sysTicks = currSysTicks;
+ load->niceTicks = currNiceTicks;
+ load->idleTicks = currIdleTicks;
+}
+
+static int processDisk( char* tag, char* buf, const char* label, int idx )
+{
+ if ( strcmp( label, tag ) == 0 ) {
+ unsigned long val;
+ unsigned int i;
+ buf = buf + strlen( label ) + 1;
+
+ for ( i = 0; i < DiskCount; ++i ) {
+ sscanf( buf, "%lu", &val );
+ while ( *buf && isblank( *buf++ ) );
+ while ( *buf && isdigit( *buf++ ) );
+ DiskLoad[ i ].s[ idx ].delta = val - DiskLoad[ i ].s[ idx ].old;
+ DiskLoad[ i ].s[ idx ].old = val;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int processDiskIO( const char* buf )
+{
+ /* Process disk_io lines as provided by 2.4.x kernels.
+ * disk_io: (2,0):(3,3,6,0,0) (3,0):(1413012,511622,12155382,901390,26486215) */
+ int major, minor;
+ unsigned long total, rblk, rio, wblk, wio;
+ DiskIOInfo* ptr = DiskIO;
+ DiskIOInfo* last = 0;
+ char sensorName[ 128 ];
+ const char* p;
+
+ p = buf + strlen( "disk_io: " );
+ while ( p && *p ) {
+ if ( sscanf( p, "(%d,%d):(%lu,%lu,%lu,%lu,%lu)", &major, &minor,
+ &total, &rio, &rblk, &wio, &wblk ) != 7 )
+ return -1;
+
+ last = 0;
+ ptr = DiskIO;
+ while ( ptr ) {
+ if ( ptr->major == major && ptr->minor == minor ) {
+ /* The IO device has already been registered. */
+ ptr->total.delta = total - ptr->total.old;
+ ptr->total.old = total;
+ ptr->rio.delta = rio - ptr->rio.old;
+ ptr->rio.old = rio;
+ ptr->wio.delta = wio - ptr->wio.old;
+ ptr->wio.old = wio;
+ ptr->rblk.delta = rblk - ptr->rblk.old;
+ ptr->rblk.old = rblk;
+ ptr->wblk.delta = wblk - ptr->wblk.old;
+ ptr->wblk.old = wblk;
+ ptr->alive = 1;
+ break;
+ }
+ last = ptr;
+ ptr = ptr->next;
+ }
+
+ if ( !ptr ) {
+ /* The IO device has not been registered yet. We need to add it. */
+ ptr = (DiskIOInfo*)malloc( sizeof( DiskIOInfo ) );
+ ptr->major = major;
+ ptr->minor = minor;
+ ptr->total.delta = 0;
+ ptr->total.old = total;
+ ptr->rio.delta = 0;
+ ptr->rio.old = rio;
+ ptr->wio.delta = 0;
+ ptr->wio.old = wio;
+ ptr->rblk.delta = 0;
+ ptr->rblk.old = rblk;
+ ptr->wblk.delta = 0;
+ ptr->wblk.old = wblk;
+ ptr->alive = 1;
+ ptr->next = 0;
+ if ( last ) {
+ /* Append new entry at end of list. */
+ last->next = ptr;
+ } else {
+ /* List is empty, so we insert the fist element into the list. */
+ DiskIO = ptr;
+ }
+
+ sprintf( sensorName, "disk/%d:%d/total", major, minor );
+ registerMonitor( sensorName, "integer", printDiskIO, printDiskIOInfo, StatSM );
+ sprintf( sensorName, "disk/%d:%d/rio", major, minor );
+ registerMonitor( sensorName, "integer", printDiskIO, printDiskIOInfo, StatSM );
+ sprintf( sensorName, "disk/%d:%d/wio", major, minor );
+ registerMonitor( sensorName, "integer", printDiskIO, printDiskIOInfo, StatSM );
+ sprintf( sensorName, "disk/%d:%d/rblk", major, minor );
+ registerMonitor( sensorName, "integer", printDiskIO, printDiskIOInfo, StatSM );
+ sprintf( sensorName, "disk/%d:%d/wblk", major, minor );
+ registerMonitor( sensorName, "integer", printDiskIO, printDiskIOInfo, StatSM );
+ }
+ /* Move p after the sencond ')'. We can safely assume that
+ * those two ')' exist. */
+ p = strchr( p, ')' ) + 1;
+ p = strchr( p, ')' ) + 1;
+ if ( p && *p )
+ p = strchr( p, '(' );
+ }
+
+ return 0;
+}
+
+static int process26DiskIO( const char* buf )
+{
+ /* Process values from /proc/diskstats (Linux >= 2.6.x) */
+
+ /* For each disk /proc/diskstats includes lines as follows:
+ * 3 0 hda 1314558 74053 26451438 14776742 1971172 4607401 52658448 202855090 0 9597019 217637839
+ * 3 1 hda1 178 360 0 0
+ * 3 2 hda2 354 360 0 0
+ * 3 3 hda3 354 360 0 0
+ * 3 4 hda4 0 0 0 0
+ * 3 5 hda5 529506 9616000 4745856 37966848
+ *
+ * - See Documentation/iostats.txt for details on the changes
+ */
+ int major, minor;
+ char devname[16];
+ unsigned long total,
+ rio, rmrg, rblk, rtim,
+ wio, wmrg, wblk, wtim,
+ ioprog, iotim, iotimw;
+ DiskIOInfo *ptr = DiskIO;
+ DiskIOInfo *last = 0;
+ char sensorName[128];
+
+ switch (sscanf(buf, "%d %d %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
+ &major, &minor, devname,
+ &rio, &rmrg, &rblk, &rtim,
+ &wio, &wmrg, &wblk, &wtim,
+ &ioprog, &iotim, &iotimw))
+ {
+ case 7:
+ /* Partition stats entry */
+ /* Adjust read fields rio rmrg rblk rtim -> rio rblk wio wblk */
+ wblk = rtim;
+ wio = rblk;
+ rblk = rmrg;
+
+ total = rio + wio;
+
+ break;
+ case 14:
+ /* Disk stats entry */
+ total = rio + wio;
+
+ break;
+ default:
+ /* Something unexepected */
+ return -1;
+ }
+
+ last = 0;
+ ptr = DiskIO;
+ while (ptr)
+ {
+ if (ptr->major == major && ptr->minor == minor)
+ {
+ /* The IO device has already been registered. */
+ ptr->total.delta = total - ptr->total.old;
+ ptr->total.old = total;
+ ptr->rio.delta = rio - ptr->rio.old;
+ ptr->rio.old = rio;
+ ptr->wio.delta = wio - ptr->wio.old;
+ ptr->wio.old = wio;
+ ptr->rblk.delta = rblk - ptr->rblk.old;
+ ptr->rblk.old = rblk;
+ ptr->wblk.delta = wblk - ptr->wblk.old;
+ ptr->wblk.old = wblk;
+ ptr->alive = 1;
+ break;
+ }
+
+ last = ptr;
+ ptr = ptr->next;
+ }
+
+ if (!ptr)
+ {
+ /* The IO device has not been registered yet. We need to add it. */
+ ptr = (DiskIOInfo*)malloc( sizeof( DiskIOInfo ) );
+ ptr->major = major;
+ ptr->minor = minor;
+ ptr->total.delta = 0;
+ ptr->total.old = total;
+ ptr->rio.delta = 0;
+ ptr->rio.old = rio;
+ ptr->wio.delta = 0;
+ ptr->wio.old = wio;
+ ptr->rblk.delta = 0;
+ ptr->rblk.old = rblk;
+ ptr->wblk.delta = 0;
+ ptr->wblk.old = wblk;
+ ptr->alive = 1;
+ ptr->next = 0;
+ if (last)
+ {
+ /* Append new entry at end of list. */
+ last->next = ptr;
+ }
+ else
+ {
+ /* List is empty, so we insert the fist element into the list. */
+ DiskIO = ptr;
+ }
+
+ sprintf(sensorName, "disk/%d:%d/total", major, minor);
+ registerMonitor(sensorName, "integer", printDiskIO, printDiskIOInfo,
+ StatSM);
+ sprintf(sensorName, "disk/%d:%d/rio", major, minor);
+ registerMonitor(sensorName, "integer", printDiskIO, printDiskIOInfo,
+ StatSM);
+ sprintf(sensorName, "disk/%d:%d/wio", major, minor);
+ registerMonitor(sensorName, "integer", printDiskIO, printDiskIOInfo,
+ StatSM);
+ sprintf(sensorName, "disk/%d:%d/rblk", major, minor);
+ registerMonitor(sensorName, "integer", printDiskIO, printDiskIOInfo,
+ StatSM);
+ sprintf(sensorName, "disk/%d:%d/wblk", major, minor);
+ registerMonitor(sensorName, "integer", printDiskIO, printDiskIOInfo,
+ StatSM);
+ }
+
+ return 0;
+}
+
+static void cleanupDiskList( void )
+{
+ DiskIOInfo* ptr = DiskIO;
+ DiskIOInfo* last = 0;
+
+ while ( ptr ) {
+ if ( ptr->alive == 0 ) {
+ DiskIOInfo* newPtr;
+ char sensorName[ 128 ];
+
+ /* Disk device has disappeared. We have to remove it from
+ * the list and unregister the monitors. */
+ sprintf( sensorName, "disk/%d:%d/total", ptr->major, ptr->minor );
+ removeMonitor( sensorName );
+ sprintf( sensorName, "disk/%d:%d/rio", ptr->major, ptr->minor );
+ removeMonitor( sensorName );
+ sprintf( sensorName, "disk/%d:%d/wio", ptr->major, ptr->minor );
+ removeMonitor( sensorName );
+ sprintf( sensorName, "disk/%d:%d/rblk", ptr->major, ptr->minor );
+ removeMonitor( sensorName );
+ sprintf( sensorName, "disk/%d:%d/wblk", ptr->major, ptr->minor );
+ removeMonitor( sensorName );
+ if ( last ) {
+ last->next = ptr->next;
+ newPtr = ptr->next;
+ } else {
+ DiskIO = ptr->next;
+ newPtr = DiskIO;
+ last = 0;
+ }
+
+ free ( ptr );
+ ptr = newPtr;
+ } else {
+ ptr->alive = 0;
+ last = ptr;
+ ptr = ptr->next;
+ }
+ }
+}
+
+static void processStat( void )
+{
+ char format[ 32 ];
+ char tagFormat[ 16 ];
+ char buf[ 1024 ];
+ char tag[ 32 ];
+ char* statBufP = StatBuf;
+ char* vmstatBufP = VmStatBuf;
+ char* iostatBufP = IOStatBuf;
+
+ sprintf( format, "%%%d[^\n]\n", (int)sizeof( buf ) - 1 );
+ sprintf( tagFormat, "%%%ds", (int)sizeof( tag ) - 1 );
+
+ while ( sscanf( statBufP, format, buf ) == 1 ) {
+ buf[ sizeof( buf ) - 1 ] = '\0';
+ statBufP += strlen( buf ) + 1; /* move statBufP to next line */
+ sscanf( buf, tagFormat, tag );
+
+ if ( strcmp( "cpu", tag ) == 0 ) {
+ /* Total CPU load */
+ updateCPULoad( buf, &CPULoad );
+ } else if ( strncmp( "cpu", tag, 3 ) == 0 ) {
+ /* Load for each SMP CPU */
+ int id;
+ sscanf( tag + 3, "%d", &id );
+ updateCPULoad( buf, &SMPLoad[ id ] );
+ } else if ( processDisk( tag, buf, "disk", 0 ) ) {
+ } else if ( processDisk( tag, buf, "disk_rio", 1 ) ) {
+ } else if ( processDisk( tag, buf, "disk_wio", 2 ) ) {
+ } else if ( processDisk( tag, buf, "disk_rblk", 3 ) ) {
+ } else if ( processDisk( tag, buf, "disk_wblk", 4 ) ) {
+ } else if ( strcmp( "disk_io:", tag ) == 0 ) {
+ processDiskIO( buf );
+ } else if ( strcmp( "page", tag ) == 0 ) {
+ unsigned long v1, v2;
+ sscanf( buf + 5, "%lu %lu", &v1, &v2 );
+ PageIn = v1 - OldPageIn;
+ OldPageIn = v1;
+ PageOut = v2 - OldPageOut;
+ OldPageOut = v2;
+ } else if ( strcmp( "intr", tag ) == 0 ) {
+ unsigned int i = 0;
+ char* p = buf + 5;
+
+ for ( i = 0; i < NumOfInts; i++ ) {
+ unsigned long val;
+
+ sscanf( p, "%lu", &val );
+ Intr[ i ] = val - OldIntr[ i ];
+ OldIntr[ i ] = val;
+ while ( *p && *p != ' ' )
+ p++;
+ while ( *p && *p == ' ' )
+ p++;
+ }
+ } else if ( strcmp( "ctxt", tag ) == 0 ) {
+ unsigned long val;
+
+ sscanf( buf + 5, "%lu", &val );
+ Ctxt = val - OldCtxt;
+ OldCtxt = val;
+ }
+ }
+
+ /* Read Linux 2.5.x /proc/vmstat */
+ while ( sscanf( vmstatBufP, format, buf ) == 1 ) {
+ buf[ sizeof( buf ) - 1 ] = '\0';
+ vmstatBufP += strlen( buf ) + 1; /* move vmstatBufP to next line */
+ sscanf( buf, tagFormat, tag );
+
+ if ( strcmp( "pgpgin", tag ) == 0 ) {
+ unsigned long v1;
+ sscanf( buf + 7, "%lu", &v1 );
+ PageIn = v1 - OldPageIn;
+ OldPageIn = v1;
+ } else if ( strcmp( "pgpgout", tag ) == 0 ) {
+ unsigned long v1;
+ sscanf( buf + 7, "%lu", &v1 );
+ PageOut = v1 - OldPageOut;
+ OldPageOut = v1;
+ }
+ }
+
+ /* Process values from /proc/diskstats (Linux >= 2.6.x) */
+ while (sscanf(iostatBufP, format, buf) == 1)
+ {
+ buf[sizeof(buf) - 1] = '\0';
+ iostatBufP += strlen(buf) + 1; /* move IOstatBufP to next line */
+
+ process26DiskIO(buf);
+ }
+
+ /* save exact time inverval between this and the last read of /proc/stat */
+ timeInterval = currSampling.tv_sec - lastSampling.tv_sec +
+ ( currSampling.tv_usec - lastSampling.tv_usec ) / 1000000.0;
+ lastSampling = currSampling;
+
+ cleanupDiskList();
+
+ Dirty = 0;
+}
+
+/*
+================================ public part =================================
+*/
+
+void initStat( struct SensorModul* sm )
+{
+ /* The CPU load is calculated from the values in /proc/stat. The cpu
+ * entry contains 4 counters. These counters count the number of ticks
+ * the system has spend on user processes, system processes, nice
+ * processes and idle time.
+ *
+ * SMP systems will have cpu1 to cpuN lines right after the cpu info. The
+ * format is identical to cpu and reports the information for each cpu.
+ * Linux kernels <= 2.0 do not provide this information!
+ *
+ * The /proc/stat file looks like this:
+ *
+ * cpu 1586 4 808 36274
+ * disk 7797 0 0 0
+ * disk_rio 6889 0 0 0
+ * disk_wio 908 0 0 0
+ * disk_rblk 13775 0 0 0
+ * disk_wblk 1816 0 0 0
+ * page 27575 1330
+ * swap 1 0
+ * intr 50444 38672 2557 0 0 0 0 2 0 2 0 0 3 1429 1 7778 0
+ * ctxt 54155
+ * btime 917379184
+ * processes 347
+ *
+ * Linux kernel >= 2.4.0 have one or more disk_io: lines instead of
+ * the disk_* lines.
+ *
+ * Linux kernel >= 2.6.x(?) have disk I/O stats in /proc/diskstats
+ * and no disk relevant lines are found in /proc/stat
+ */
+
+ char format[ 32 ];
+ char tagFormat[ 16 ];
+ char buf[ 1024 ];
+ char tag[ 32 ];
+ char* statBufP = StatBuf;
+ char* vmstatBufP = VmStatBuf;
+ char* iostatBufP = IOStatBuf;
+
+ StatSM = sm;
+
+ updateStat();
+
+ sprintf( format, "%%%d[^\n]\n", (int)sizeof( buf ) - 1 );
+ sprintf( tagFormat, "%%%ds", (int)sizeof( tag ) - 1 );
+
+ while ( sscanf( statBufP, format, buf ) == 1 ) {
+ buf[ sizeof( buf ) - 1 ] = '\0';
+ statBufP += strlen( buf ) + 1; /* move statBufP to next line */
+ sscanf( buf, tagFormat, tag );
+
+ if ( strcmp( "cpu", tag ) == 0 ) {
+ /* Total CPU load */
+ registerMonitor( "cpu/user", "integer", printCPUUser, printCPUUserInfo, StatSM );
+ registerMonitor( "cpu/nice", "integer", printCPUNice, printCPUNiceInfo, StatSM );
+ registerMonitor( "cpu/sys", "integer", printCPUSys, printCPUSysInfo, StatSM );
+ registerMonitor( "cpu/idle", "integer", printCPUIdle, printCPUIdleInfo, StatSM );
+ } else if ( strncmp( "cpu", tag, 3 ) == 0 ) {
+ char cmdName[ 24 ];
+ /* Load for each SMP CPU */
+ int id;
+
+ sscanf( tag + 3, "%d", &id );
+ CPUCount++;
+ sprintf( cmdName, "cpu%d/user", id );
+ registerMonitor( cmdName, "integer", printCPUxUser, printCPUxUserInfo, StatSM );
+ sprintf( cmdName, "cpu%d/nice", id );
+ registerMonitor( cmdName, "integer", printCPUxNice, printCPUxNiceInfo, StatSM );
+ sprintf( cmdName, "cpu%d/sys", id );
+ registerMonitor( cmdName, "integer", printCPUxSys, printCPUxSysInfo, StatSM );
+ sprintf( cmdName, "cpu%d/idle", id );
+ registerMonitor( cmdName, "integer", printCPUxIdle, printCPUxIdleInfo, StatSM );
+ } else if ( strcmp( "disk", tag ) == 0 ) {
+ unsigned long val;
+ char* b = buf + 5;
+
+ /* Count the number of registered disks */
+ for ( DiskCount = 0; *b && sscanf( b, "%lu", &val ) == 1; DiskCount++ ) {
+ while ( *b && isblank( *b++ ) );
+ while ( *b && isdigit( *b++ ) );
+ }
+
+ if ( DiskCount > 0 )
+ DiskLoad = (DiskLoadInfo*)malloc( sizeof( DiskLoadInfo ) * DiskCount );
+ initStatDisk( tag, buf, "disk", "disk", 0, printDiskTotal, printDiskTotalInfo );
+ } else if ( initStatDisk( tag, buf, "disk_rio", "rio", 1, printDiskRIO,
+ printDiskRIOInfo ) );
+ else if ( initStatDisk( tag, buf, "disk_wio", "wio", 2, printDiskWIO,
+ printDiskWIOInfo ) );
+ else if ( initStatDisk( tag, buf, "disk_rblk", "rblk", 3, printDiskRBlk,
+ printDiskRBlkInfo ) );
+ else if ( initStatDisk( tag, buf, "disk_wblk", "wblk", 4, printDiskWBlk,
+ printDiskWBlkInfo ) );
+ else if ( strcmp( "disk_io:", tag ) == 0 )
+ processDiskIO( buf );
+ else if ( strcmp( "page", tag ) == 0 ) {
+ sscanf( buf + 5, "%lu %lu", &OldPageIn, &OldPageOut );
+ registerMonitor( "cpu/pageIn", "integer", printPageIn,
+ printPageInInfo, StatSM );
+ registerMonitor( "cpu/pageOut", "integer", printPageOut,
+ printPageOutInfo, StatSM );
+ } else if ( strcmp( "intr", tag ) == 0 ) {
+ unsigned int i;
+ char cmdName[ 32 ];
+ char* p = buf + 5;
+
+ /* Count the number of listed values in the intr line. */
+ NumOfInts = 0;
+ while ( *p )
+ if ( *p++ == ' ' )
+ NumOfInts++;
+
+ /* It looks like anything above 24 is always 0. So let's just
+ * ignore this for the time being. */
+ if ( NumOfInts > 25 )
+ NumOfInts = 25;
+ OldIntr = (unsigned long*)malloc( NumOfInts * sizeof( unsigned long ) );
+ Intr = (unsigned long*)malloc( NumOfInts * sizeof( unsigned long ) );
+ i = 0;
+ p = buf + 5;
+ for ( i = 0; p && i < NumOfInts; i++ ) {
+ sscanf( p, "%lu", &OldIntr[ i ] );
+ while ( *p && *p != ' ' )
+ p++;
+ while ( *p && *p == ' ' )
+ p++;
+ sprintf( cmdName, "cpu/interrupts/int%02d", i );
+ registerMonitor( cmdName, "integer", printInterruptx,
+ printInterruptxInfo, StatSM );
+ }
+ } else if ( strcmp( "ctxt", tag ) == 0 ) {
+ sscanf( buf + 5, "%lu", &OldCtxt );
+ registerMonitor( "cpu/context", "integer", printCtxt,
+ printCtxtInfo, StatSM );
+ }
+ }
+
+ while ( sscanf( vmstatBufP, format, buf ) == 1 ) {
+ buf[ sizeof( buf ) - 1 ] = '\0';
+ vmstatBufP += strlen( buf ) + 1; /* move vmstatBufP to next line */
+ sscanf( buf, tagFormat, tag );
+
+ if ( strcmp( "pgpgin", tag ) == 0 ) {
+ sscanf( buf + 7, "%lu", &OldPageIn );
+ registerMonitor( "cpu/pageIn", "integer", printPageIn,
+ printPageInInfo, StatSM );
+ } else if ( strcmp( "pgpgout", tag ) == 0 ) {
+ sscanf( buf + 7, "%lu", &OldPageOut );
+ registerMonitor( "cpu/pageOut", "integer", printPageOut,
+ printPageOutInfo, StatSM );
+ }
+ }
+
+ /* Process values from /proc/diskstats (Linux >= 2.6.x) */
+ while (sscanf(iostatBufP, format, buf) == 1)
+ {
+ buf[sizeof(buf) - 1] = '\0';
+ iostatBufP += strlen(buf) + 1; /* move IOstatBufP to next line */
+
+ process26DiskIO(buf);
+ }
+
+ if ( CPUCount > 0 )
+ SMPLoad = (CPULoadInfo*)malloc( sizeof( CPULoadInfo ) * CPUCount );
+
+ /* Call processStat to eliminate initial peek values. */
+ processStat();
+}
+
+void exitStat( void )
+{
+ free( DiskLoad );
+ DiskLoad = 0;
+
+ free( SMPLoad );
+ SMPLoad = 0;
+
+ free( OldIntr );
+ OldIntr = 0;
+
+ free( Intr );
+ Intr = 0;
+}
+
+int updateStat( void )
+{
+ size_t n;
+ int fd;
+
+ if ( ( fd = open( "/proc/stat", O_RDONLY ) ) < 0 ) {
+ print_error( "Cannot open file \'/proc/stat\'!\n"
+ "The kernel needs to be compiled with support\n"
+ "for /proc filesystem enabled!\n" );
+ return -1;
+ }
+
+ if ( ( n = read( fd, StatBuf, STATBUFSIZE - 1 ) ) == STATBUFSIZE - 1 ) {
+ log_error( "Internal buffer too small to read \'/proc/stat\'" );
+
+ close( fd );
+ return -1;
+ }
+
+ gettimeofday( &currSampling, 0 );
+ close( fd );
+ StatBuf[ n ] = '\0';
+ Dirty = 1;
+
+ VmStatBuf[ 0 ] = '\0';
+ if ( ( fd = open( "/proc/vmstat", O_RDONLY ) ) < 0 )
+ return 0; /* failure is okay, only exists for Linux >= 2.5.x */
+
+ if ( ( n = read( fd, VmStatBuf, STATBUFSIZE - 1 ) ) == STATBUFSIZE - 1 ) {
+ log_error( "Internal buffer too small to read \'/proc/vmstat\'" );
+
+ close( fd );
+ return -1;
+ }
+
+ close( fd );
+ VmStatBuf[ n ] = '\0';
+
+ /* Linux >= 2.6.x has disk I/O stats in /proc/diskstats */
+ IOStatBuf[ 0 ] = '\0';
+ if ( ( fd = open( "/proc/diskstats", O_RDONLY ) ) < 0 )
+ return 0; /* failure is okay, only exists for Linux >= 2.6.x */
+
+ if ( ( n = read( fd, IOStatBuf, STATBUFSIZE - 1 ) ) == STATBUFSIZE - 1 ) {
+ log_error( "Internal buffer too small to read \'/proc/diskstats\'" );
+
+ close( fd );
+ return -1;
+ }
+
+ close( fd );
+ IOStatBuf[ n ] = '\0';
+
+ return 0;
+}
+
+void printCPUUser( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processStat();
+
+ fprintf( CurrentClient, "%d\n", CPULoad.userLoad );
+}
+
+void printCPUUserInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "CPU User Load\t0\t100\t%%\n" );
+}
+
+void printCPUNice( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processStat();
+
+ fprintf( CurrentClient, "%d\n", CPULoad.niceLoad );
+}
+
+void printCPUNiceInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "CPU Nice Load\t0\t100\t%%\n" );
+}
+
+void printCPUSys( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processStat();
+
+ fprintf( CurrentClient, "%d\n", CPULoad.sysLoad );
+}
+
+void printCPUSysInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "CPU System Load\t0\t100\t%%\n" );
+}
+
+void printCPUIdle( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processStat();
+
+ fprintf( CurrentClient, "%d\n", CPULoad.idleLoad );
+}
+
+void printCPUIdleInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "CPU Idle Load\t0\t100\t%%\n" );
+}
+
+void printCPUxUser( const char* cmd )
+{
+ int id;
+
+ if ( Dirty )
+ processStat();
+
+ sscanf( cmd + 3, "%d", &id );
+ fprintf( CurrentClient, "%d\n", SMPLoad[ id ].userLoad );
+}
+
+void printCPUxUserInfo( const char* cmd )
+{
+ int id;
+
+ sscanf( cmd + 3, "%d", &id );
+ fprintf( CurrentClient, "CPU%d User Load\t0\t100\t%%\n", id );
+}
+
+void printCPUxNice( const char* cmd )
+{
+ int id;
+
+ if ( Dirty )
+ processStat();
+
+ sscanf( cmd + 3, "%d", &id );
+ fprintf( CurrentClient, "%d\n", SMPLoad[ id ].niceLoad );
+}
+
+void printCPUxNiceInfo( const char* cmd )
+{
+ int id;
+
+ sscanf( cmd + 3, "%d", &id );
+ fprintf( CurrentClient, "CPU%d Nice Load\t0\t100\t%%\n", id );
+}
+
+void printCPUxSys( const char* cmd )
+{
+ int id;
+
+ if ( Dirty )
+ processStat();
+
+ sscanf( cmd + 3, "%d", &id );
+ fprintf( CurrentClient, "%d\n", SMPLoad[ id ].sysLoad );
+}
+
+void printCPUxSysInfo( const char* cmd )
+{
+ int id;
+
+ sscanf( cmd + 3, "%d", &id );
+ fprintf( CurrentClient, "CPU%d System Load\t0\t100\t%%\n", id );
+}
+
+void printCPUxIdle( const char* cmd )
+{
+ int id;
+
+ if ( Dirty )
+ processStat();
+
+ sscanf( cmd + 3, "%d", &id );
+ fprintf( CurrentClient, "%d\n", SMPLoad[ id ].idleLoad );
+}
+
+void printCPUxIdleInfo( const char* cmd )
+{
+ int id;
+
+ sscanf( cmd + 3, "%d", &id );
+ fprintf( CurrentClient, "CPU%d Idle Load\t0\t100\t%%\n", id );
+}
+
+void printDiskTotal( const char* cmd )
+{
+ int id;
+
+ if ( Dirty )
+ processStat();
+
+ sscanf( cmd + 9, "%d", &id );
+ fprintf( CurrentClient, "%lu\n", (unsigned long)( DiskLoad[ id ].s[ 0 ].delta
+ / timeInterval ) );
+}
+
+void printDiskTotalInfo( const char* cmd )
+{
+ int id;
+
+ sscanf( cmd + 9, "%d", &id );
+ fprintf( CurrentClient, "Disk%d Total Load\t0\t0\tkBytes/s\n", id );
+}
+
+void printDiskRIO( const char* cmd )
+{
+ int id;
+
+ if ( Dirty )
+ processStat();
+
+ sscanf( cmd + 9, "%d", &id );
+ fprintf( CurrentClient, "%lu\n", (unsigned long)( DiskLoad[ id ].s[ 1 ].delta
+ / timeInterval ) );
+}
+
+void printDiskRIOInfo( const char* cmd )
+{
+ int id;
+
+ sscanf( cmd + 9, "%d", &id );
+ fprintf( CurrentClient, "Disk%d Read\t0\t0\tkBytes/s\n", id );
+}
+
+void printDiskWIO( const char* cmd )
+{
+ int id;
+
+ if ( Dirty )
+ processStat();
+
+ sscanf( cmd + 9, "%d", &id );
+ fprintf( CurrentClient, "%lu\n", (unsigned long)( DiskLoad[ id ].s[ 2 ].delta
+ / timeInterval ) );
+}
+
+void printDiskWIOInfo( const char* cmd )
+{
+ int id;
+
+ sscanf( cmd + 9, "%d", &id );
+ fprintf( CurrentClient, "Disk%d Write\t0\t0\tkBytes/s\n", id );
+}
+
+void printDiskRBlk( const char* cmd )
+{
+ int id;
+
+ if ( Dirty )
+ processStat();
+
+ sscanf( cmd + 9, "%d", &id );
+ /* a block is 512 bytes or 1/2 kBytes */
+ fprintf( CurrentClient, "%lu\n", (unsigned long)( DiskLoad[ id ].s[ 3 ].delta
+ / timeInterval * 2 ) );
+}
+
+void printDiskRBlkInfo( const char* cmd )
+{
+ int id;
+
+ sscanf( cmd + 9, "%d", &id );
+ fprintf( CurrentClient, "Disk%d Read Data\t0\t0\tkBytes/s\n", id );
+}
+
+void printDiskWBlk( const char* cmd )
+{
+ int id;
+
+ if ( Dirty )
+ processStat();
+
+ sscanf( cmd + 9, "%d", &id );
+ /* a block is 512 bytes or 1/2 kBytes */
+ fprintf( CurrentClient, "%lu\n", (unsigned long)( DiskLoad[ id ].s[ 4 ].delta
+ / timeInterval * 2 ) );
+}
+
+void printDiskWBlkInfo( const char* cmd )
+{
+ int id;
+
+ sscanf( cmd + 9, "%d", &id );
+ fprintf( CurrentClient, "Disk%d Write Data\t0\t0\tkBytes/s\n", id );
+}
+
+void printPageIn( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processStat();
+
+ fprintf( CurrentClient, "%lu\n", (unsigned long)( PageIn / timeInterval ) );
+}
+
+void printPageInInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Paged in Pages\t0\t0\t1/s\n" );
+}
+
+void printPageOut( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processStat();
+
+ fprintf( CurrentClient, "%lu\n", (unsigned long)( PageOut / timeInterval ) );
+}
+
+void printPageOutInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Paged out Pages\t0\t0\t1/s\n" );
+}
+
+void printInterruptx( const char* cmd )
+{
+ int id;
+
+ if ( Dirty )
+ processStat();
+
+ sscanf( cmd + strlen( "cpu/interrupts/int" ), "%d", &id );
+ fprintf( CurrentClient, "%lu\n", (unsigned long)( Intr[ id ] / timeInterval ) );
+}
+
+void printInterruptxInfo( const char* cmd )
+{
+ int id;
+
+ sscanf( cmd + strlen( "cpu/interrupt/int" ), "%d", &id );
+ fprintf( CurrentClient, "Interrupt %d\t0\t0\t1/s\n", id );
+}
+
+void printCtxt( const char* cmd )
+{
+ (void)cmd;
+
+ if ( Dirty )
+ processStat();
+
+ fprintf( CurrentClient, "%lu\n", (unsigned long)( Ctxt / timeInterval ) );
+}
+
+void printCtxtInfo( const char* cmd )
+{
+ (void)cmd;
+ fprintf( CurrentClient, "Context switches\t0\t0\t1/s\n" );
+}
+
+void printDiskIO( const char* cmd )
+{
+ int major, minor;
+ char name[ 17 ];
+ DiskIOInfo* ptr;
+
+ sscanf( cmd, "disk/%d:%d/%16s", &major, &minor, name );
+
+ if ( Dirty )
+ processStat();
+
+ ptr = DiskIO;
+ while ( ptr && ( ptr->major != major || ptr->minor != minor ) )
+ ptr = ptr->next;
+
+ if ( !ptr ) {
+ print_error( "RECONFIGURE" );
+ fprintf( CurrentClient, "0\n" );
+
+ log_error( "Disk device disappeared" );
+ return;
+ }
+
+ if ( strcmp( name, "total" ) == 0 )
+ fprintf( CurrentClient, "%lu\n", (unsigned long)( ptr->total.delta
+ / timeInterval ) );
+ else if ( strcmp( name, "rio" ) == 0 )
+ fprintf( CurrentClient, "%lu\n", (unsigned long)( ptr->rio.delta
+ / timeInterval ) );
+ else if ( strcmp( name, "wio" ) == 0 )
+ fprintf( CurrentClient, "%lu\n", (unsigned long)( ptr->wio.delta
+ / timeInterval ) );
+ else if ( strcmp( name, "rblk" ) == 0 )
+ fprintf( CurrentClient, "%lu\n", (unsigned long)( ptr->rblk.delta
+ / ( timeInterval * 2 ) ) );
+ else if ( strcmp( name, "wblk" ) == 0 )
+ fprintf( CurrentClient, "%lu\n", (unsigned long)( ptr->wblk.delta
+ / ( timeInterval * 2 ) ) );
+ else {
+ fprintf( CurrentClient, "0\n" );
+ log_error( "Unknown disk device property \'%s\'", name );
+ }
+}
+
+void printDiskIOInfo( const char* cmd )
+{
+ int major, minor;
+ char name[ 17 ];
+ DiskIOInfo* ptr = DiskIO;
+
+ sscanf( cmd, "disk/%d:%d/%16s", &major, &minor, name );
+
+ while ( ptr && ( ptr->major != major || ptr->minor != minor ) )
+ ptr = ptr->next;
+
+ if ( !ptr ) {
+ /* Disk device has disappeared. Print a dummy answer. */
+ fprintf( CurrentClient, "Dummy\t0\t0\t\n" );
+ return;
+ }
+
+ /* remove trailing '?' */
+ name[ strlen( name ) - 1 ] = '\0';
+
+ if ( strcmp( name, "total" ) == 0 )
+ fprintf( CurrentClient, "Total accesses device %d, %d\t0\t0\t1/s\n",
+ major, minor );
+ else if ( strcmp( name, "rio" ) == 0 )
+ fprintf( CurrentClient, "Read data device %d, %d\t0\t0\t1/s\n",
+ major, minor );
+ else if ( strcmp( name, "wio" ) == 0 )
+ fprintf( CurrentClient, "Write data device %d, %d\t0\t0\t1/s\n",
+ major, minor );
+ else if ( strcmp( name, "rblk" ) == 0 )
+ fprintf( CurrentClient, "Read accesses device %d, %d\t0\t0\tkBytes/s\n",
+ major, minor );
+ else if ( strcmp( name, "wblk" ) == 0 )
+ fprintf( CurrentClient, "Write accesses device %d, %d\t0\t0\tkBytes/s\n",
+ major, minor );
+ else {
+ fprintf( CurrentClient, "Dummy\t0\t0\t\n" );
+ log_error( "Request for unknown device property \'%s\'", name );
+ }
+}
diff --git a/ksysguard/ksysguardd/Linux/stat.h b/ksysguard/ksysguardd/Linux/stat.h
new file mode 100644
index 000000000..9107d3aa3
--- /dev/null
+++ b/ksysguard/ksysguardd/Linux/stat.h
@@ -0,0 +1,66 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_STAT_H
+#define KSG_STAT_H
+
+void initStat( struct SensorModul* );
+void exitStat( void );
+
+int updateStat( void );
+
+void printCPUUser( const char* );
+void printCPUUserInfo( const char* );
+void printCPUNice( const char* );
+void printCPUNiceInfo( const char* );
+void printCPUSys( const char* );
+void printCPUSysInfo( const char* );
+void printCPUIdle( const char* );
+void printCPUIdleInfo( const char* );
+void printCPUxUser( const char* );
+void printCPUxUserInfo( const char* );
+void printCPUxNice( const char* );
+void printCPUxNiceInfo( const char* );
+void printCPUxSys( const char* );
+void printCPUxSysInfo( const char* );
+void printCPUxIdle( const char* );
+void printCPUxIdleInfo( const char* );
+void printDiskTotal( const char* );
+void printDiskTotalInfo( const char* );
+void printDiskRIO( const char* );
+void printDiskRIOInfo( const char* );
+void printDiskWIO( const char* );
+void printDiskWIOInfo( const char* );
+void printDiskRBlk( const char* );
+void printDiskRBlkInfo( const char* );
+void printDiskWBlk( const char* );
+void printDiskWBlkInfo( const char* );
+void printPageIn( const char* );
+void printPageInInfo( const char* );
+void printPageOut( const char* );
+void printPageOutInfo( const char* );
+void printInterruptx( const char* );
+void printInterruptxInfo( const char* );
+void printCtxt( const char* );
+void printCtxtInfo( const char* );
+void printDiskIO( const char* );
+void printDiskIOInfo( const char* );
+
+#endif
diff --git a/ksysguard/ksysguardd/Makefile.am b/ksysguard/ksysguardd/Makefile.am
new file mode 100644
index 000000000..485700780
--- /dev/null
+++ b/ksysguard/ksysguardd/Makefile.am
@@ -0,0 +1,35 @@
+AUTOMAKE_OPTIONS = foreign
+
+if include_ksysguardd_linux
+linux_SUBDIR = Linux
+endif
+if include_ksysguardd_freebsd
+freebsd_SUBDIR = FreeBSD
+endif
+if include_ksysguardd_netbsd
+netbsd_SUBDIR = NetBSD
+endif
+if include_ksysguardd_solaris
+solaris_SUBDIR = Solaris
+endif
+if include_ksysguardd_tru64
+tru64_SUBDIR = Tru64
+endif
+if include_ksysguardd_irix
+irix_SUBDIR = Irix
+endif
+if include_ksysguardd_openbsd
+openbsd_SUBDIR = OpenBSD
+endif
+
+SUBDIRS = $(linux_SUBDIR) $(freebsd_SUBDIR) $(netbsd_SUBDIR)\
+ $(solaris_SUBDIR) $(tru64_SUBDIR) $(irix_SUBDIR) $(openbsd_SUBDIR)
+
+KSYSGUARDDRCFILE=$(sysconfdir)/ksysguarddrc
+INCLUDES = -DKSYSGUARDDRCFILE="\"$(KSYSGUARDDRCFILE)\"" -DOSTYPE_$(UNAME) -I$(srcdir)/../CContLib -I$(srcdir)/$(UNAME) $(all_includes)
+
+bin_PROGRAMS = ksysguardd
+
+ksysguardd_SOURCES = Command.c conf.c ksysguardd.c PWUIDCache.c
+ksysguardd_LDFLAGS = $(all_libraries)
+ksysguardd_LDADD = $(top_builddir)/ksysguard/ksysguardd/$(UNAME)/libksysguardd.a ../CContLib/libccont.a -lkdefakes_nonpic $(LIBHOSTS) $(LIB_DNSSD) $(LIB_KINFO)
diff --git a/ksysguard/ksysguardd/NetBSD/CPU.c b/ksysguard/ksysguardd/NetBSD/CPU.c
new file mode 100644
index 000000000..959924087
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/CPU.c
@@ -0,0 +1,206 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <sys/dkstat.h>
+#include <sys/sched.h> /* CPUSTATES */
+#include <fcntl.h>
+#include <kvm.h>
+#include <nlist.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "CPU.h"
+#include "Command.h"
+#include "ksysguardd.h"
+
+long percentages(int cnt, int *out, long *new, long *old, long *diffs);
+
+struct nlist my_nlist[] = {
+ {"_cp_time"},
+ { 0 }
+};
+
+kvm_t *kd;
+
+unsigned long cp_time_offset;
+
+long cp_time[CPUSTATES];
+long cp_old[CPUSTATES];
+long cp_diff[CPUSTATES];
+int cpu_states[CPUSTATES];
+
+void
+initCpuInfo(struct SensorModul* sm)
+{
+ /* Total CPU load */
+ registerMonitor("cpu/user", "integer", printCPUUser,
+ printCPUUserInfo, sm);
+ registerMonitor("cpu/nice", "integer", printCPUNice,
+ printCPUNiceInfo, sm);
+ registerMonitor("cpu/sys", "integer", printCPUSys,
+ printCPUSysInfo, sm);
+ registerMonitor("cpu/idle", "integer", printCPUIdle,
+ printCPUIdleInfo, sm);
+ kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open");
+ kvm_nlist(kd, my_nlist);
+ cp_time_offset = my_nlist[0].n_value;
+
+ updateCpuInfo();
+}
+
+void
+exitCpuInfo(void)
+{
+ kvm_close(kd);
+}
+
+int
+updateCpuInfo(void)
+{
+ kvm_read(kd, cp_time_offset, (char *)cp_time, sizeof(cp_time));
+ percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
+ return (0);
+}
+
+void
+printCPUUser(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CP_USER]/10);
+}
+
+void
+printCPUUserInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU User Load\t0\t100\t%%\n");
+}
+
+void
+printCPUNice(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CP_NICE]/10);
+}
+
+void
+printCPUNiceInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU Nice Load\t0\t100\t%%\n");
+}
+
+void
+printCPUSys(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CP_SYS]/10);
+}
+
+void
+printCPUSysInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU System Load\t0\t100\t%%\n");
+}
+
+void
+printCPUIdle(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CP_IDLE]/10);
+}
+
+void
+printCPUIdleInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU Idle Load\t0\t100\t%%\n");
+}
+
+
+/* The part ripped from top... */
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ */
+
+/*
+ * percentages(cnt, out, new, old, diffs) - calculate percentage change
+ * between array "old" and "new", putting the percentages i "out".
+ * "cnt" is size of each array and "diffs" is used for scratch space.
+ * The array "old" is updated on each call.
+ * The routine assumes modulo arithmetic. This function is especially
+ * useful on BSD mchines for calculating cpu state percentages.
+ */
+
+long percentages(cnt, out, new, old, diffs)
+
+int cnt;
+int *out;
+register long *new;
+register long *old;
+long *diffs;
+
+{
+ register int i;
+ register long change;
+ register long total_change;
+ register long *dp;
+ long half_total;
+
+ /* initialization */
+ total_change = 0;
+ dp = diffs;
+
+ /* calculate changes for each state and the overall change */
+ for (i = 0; i < cnt; i++)
+ {
+ if ((change = *new - *old) < 0)
+ {
+ /* this only happens when the counter wraps */
+ change = (int)
+ ((unsigned long)*new-(unsigned long)*old);
+ }
+ total_change += (*dp++ = change);
+ *old++ = *new++;
+ }
+
+ /* avoid divide by zero potential */
+ if (total_change == 0)
+ {
+ total_change = 1;
+ }
+
+ /* calculate percentages based on overall change, rounding up */
+ half_total = total_change / 2l;
+
+ /* Do not divide by 0. Causes Floating point exception */
+ if(total_change) {
+ for (i = 0; i < cnt; i++)
+ {
+ *out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
+ }
+ }
+
+ /* return the total in case the caller wants to use it */
+ return(total_change);
+}
diff --git a/ksysguard/ksysguardd/NetBSD/CPU.h b/ksysguard/ksysguardd/NetBSD/CPU.h
new file mode 100644
index 000000000..c35932ac8
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/CPU.h
@@ -0,0 +1,49 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _cpuinfo_h_
+#define _cpuinfo_h_
+
+struct SensorModul;
+
+void initCpuInfo(struct SensorModul* sm);
+void exitCpuInfo(void);
+
+int updateCpuInfo(void);
+
+void printCPUUser(const char* cmd);
+void printCPUUserInfo(const char* cmd);
+void printCPUNice(const char* cmd);
+void printCPUNiceInfo(const char* cmd);
+void printCPUSys(const char* cmd);
+void printCPUSysInfo(const char* cmd);
+void printCPUIdle(const char* cmd);
+void printCPUIdleInfo(const char* cmd);
+void printCPUxUser(const char* cmd);
+void printCPUxUserInfo(const char* cmd);
+void printCPUxNice(const char* cmd);
+void printCPUxNiceInfo(const char* cmd);
+void printCPUxSys(const char* cmd);
+void printCPUxSysInfo(const char* cmd);
+void printCPUxIdle(const char* cmd);
+void printCPUxIdleInfo(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/NetBSD/Makefile.am b/ksysguard/ksysguardd/NetBSD/Makefile.am
new file mode 100644
index 000000000..29860a407
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/Makefile.am
@@ -0,0 +1,8 @@
+#
+#
+
+INCLUDES = -I$(srcdir)/../../CContLib -I$(srcdir)/..
+
+noinst_LIBRARIES = libksysguardd.a
+libksysguardd_a_SOURCES = CPU.c Memory.c ProcessList.c apm.c diskstat.c \
+ loadavg.c logfile.c netdev.c
diff --git a/ksysguard/ksysguardd/NetBSD/Memory.c b/ksysguard/ksysguardd/NetBSD/Memory.c
new file mode 100644
index 000000000..8e9779506
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/Memory.c
@@ -0,0 +1,202 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999-2000 Hans Petter Bieker <bieker@kde.org>
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <fcntl.h>
+#include <kvm.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#include <sys/vmmeter.h>
+#include <unistd.h>
+/* Everything post 1.5.x uses uvm/uvm_* includes */
+#if __NetBSD_Version__ >= 105010000
+#include <uvm/uvm_param.h>
+#else
+#include <vm/vm_param.h>
+#endif
+
+#include "Command.h"
+#include "Memory.h"
+#include "ksysguardd.h"
+
+static size_t Total = 0;
+static size_t MFree = 0;
+static size_t Used = 0;
+static size_t Buffers = 0;
+static size_t Cached = 0;
+static size_t STotal = 0;
+static size_t SFree = 0;
+static size_t SUsed = 0;
+static kvm_t *kd;
+
+void
+initMemory(struct SensorModul* sm)
+{
+ char *nlistf = NULL;
+ char *memf = NULL;
+ char buf[_POSIX2_LINE_MAX];
+
+ if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) {
+ log_error("kvm_openfiles()");
+ return;
+ }
+
+ registerMonitor("mem/physical/free", "integer", printMFree, printMFreeInfo, sm);
+ registerMonitor("mem/physical/used", "integer", printUsed, printUsedInfo, sm);
+ registerMonitor("mem/physical/buf", "integer", printBuffers, printBuffersInfo, sm);
+ registerMonitor("mem/physical/cached", "integer", printCached, printCachedInfo, sm);
+ registerMonitor("mem/swap/free", "integer", printSwapFree, printSwapFreeInfo, sm);
+ registerMonitor("mem/swap/used", "integer", printSwapUsed, printSwapUsedInfo, sm);
+}
+
+void
+exitMemory(void)
+{
+ kvm_close(kd);
+}
+
+int
+updateMemory(void)
+{
+
+#define ARRLEN(X) (sizeof(X)/sizeof(X[0]))
+ long pagesize; /* using a long promotes the arithmetic */
+ size_t len;
+
+ {
+ static int mib[]={ CTL_HW, HW_PHYSMEM };
+
+ len = sizeof(Total);
+ sysctl(mib, ARRLEN(mib), &Total, &len, NULL, 0);
+ Total >>= 10;
+ }
+
+ {
+ struct uvmexp x;
+ static int mib[] = { CTL_VM, VM_UVMEXP };
+
+ len = sizeof(x);
+ STotal = SUsed = SFree = -1;
+ pagesize = 1;
+ if (-1 < sysctl(mib, ARRLEN(mib), &x, &len, NULL, 0)) {
+ pagesize = x.pagesize;
+ STotal = (pagesize*x.swpages) >> 10;
+ SUsed = (pagesize*x.swpginuse) >> 10;
+ SFree = STotal - SUsed;
+ }
+ }
+
+ /* can't find NetBSD filesystem buffer info */
+ Buffers = -1;
+
+ /* NetBSD doesn't know about vm.stats */
+ Cached = -1;
+
+ {
+ static int mib[]={ CTL_VM, VM_METER };
+ struct vmtotal x;
+
+ len = sizeof(x);
+ MFree = Used = -1;
+ if (sysctl(mib, ARRLEN(mib), &x, &len, NULL, 0) > -1) {
+ MFree = (x.t_free * pagesize) >> 10;
+ Used = (x.t_rm * pagesize) >> 10;
+ }
+ }
+ return 0;
+}
+
+void
+printMFree(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", MFree);
+}
+
+void
+printMFreeInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Free Memory\t0\t%d\tKB\n", Total);
+}
+
+void
+printUsed(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", Used);
+}
+
+void
+printUsedInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Used Memory\t0\t%d\tKB\n", Total);
+}
+
+void
+printBuffers(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", Buffers);
+}
+
+void
+printBuffersInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Buffer Memory\t0\t%d\tKB\n", Total);
+}
+
+void
+printCached(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", Cached);
+}
+
+void
+printCachedInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Cached Memory\t0\t%d\tKB\n", Total);
+}
+
+void
+printSwapUsed(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", SUsed);
+}
+
+void
+printSwapUsedInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Used Swap Memory\t0\t%d\tKB\n", STotal);
+}
+
+void
+printSwapFree(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", SFree);
+}
+
+void
+printSwapFreeInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Free Swap Memory\t0\t%d\tKB\n", STotal);
+}
diff --git a/ksysguard/ksysguardd/NetBSD/Memory.h b/ksysguard/ksysguardd/NetBSD/Memory.h
new file mode 100644
index 000000000..57abb73a2
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/Memory.h
@@ -0,0 +1,43 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _memory_h_
+#define _memory_h_
+
+void initMemory(struct SensorModul* sm);
+void exitMemory(void);
+
+int updateMemory(void);
+
+void printMFree(const char* cmd);
+void printMFreeInfo(const char* cmd);
+void printUsed(const char* cmd);
+void printUsedInfo(const char* cmd);
+void printBuffers(const char* cmd);
+void printBuffersInfo(const char* cmd);
+void printCached(const char* cmd);
+void printCachedInfo(const char* cmd);
+void printSwapUsed(const char* cmd);
+void printSwapUsedInfo(const char* cmd);
+void printSwapFree(const char* cmd);
+void printSwapFreeInfo(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/NetBSD/ProcessList.c b/ksysguard/ksysguardd/NetBSD/ProcessList.c
new file mode 100644
index 000000000..54ab65513
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/ProcessList.c
@@ -0,0 +1,457 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999-2000 Hans Petter Bieker<bieker@kde.org>
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/user.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "../../gui/SignalIDs.h"
+#include "Command.h"
+#include "ProcessList.h"
+#include "ccont.h"
+#include "ksysguardd.h"
+
+CONTAINER ProcessList = 0;
+
+#define BUFSIZE 1024
+
+typedef struct
+{
+ /* This flag is set for all found processes at the beginning of the
+ * process list update. Processes that do not have this flag set will
+ * be assumed dead and removed from the list. The flag is cleared after
+ * each list update. */
+ int alive;
+
+ /* the process ID */
+ pid_t pid;
+
+ /* the parent process ID */
+ pid_t ppid;
+
+ /* the real user ID */
+ uid_t uid;
+
+ /* the real group ID */
+ gid_t gid;
+
+ /* a character description of the process status */
+ char status[16];
+
+ /* the number of the tty the process owns */
+ int ttyNo;
+
+ /*
+ * The nice level. The range should be -20 to 20. I'm not sure
+ * whether this is true for all platforms.
+ */
+ int niceLevel;
+
+ /*
+ * The scheduling priority.
+ */
+ int priority;
+
+ /*
+ * The total amount of memory the process uses. This includes shared and
+ * swapped memory.
+ */
+ unsigned int vmSize;
+
+ /*
+ * The amount of physical memory the process currently uses.
+ */
+ unsigned int vmRss;
+
+ /*
+ * The amount of memory (shared/swapped/etc) the process shares with
+ * other processes.
+ */
+ unsigned int vmLib;
+
+ /*
+ * The number of 1/100 of a second the process has spend in user space.
+ * If a machine has an uptime of 1 1/2 years or longer this is not a
+ * good idea. I never thought that the stability of UNIX could get me
+ * into trouble! ;)
+ */
+ unsigned int userTime;
+
+ /*
+ * The number of 1/100 of a second the process has spend in system space.
+ * If a machine has an uptime of 1 1/2 years or longer this is not a
+ * good idea. I never thought that the stability of UNIX could get me
+ * into trouble! ;)
+ */
+ unsigned int sysTime;
+
+ /* system time as multime of 100ms */
+ int centStamp;
+
+ /* the current CPU load (in %) from user space */
+ double userLoad;
+
+ /* the current CPU load (in %) from system space */
+ double sysLoad;
+
+ /* the name of the process */
+ char name[64];
+
+ /* the command used to start the process */
+ char cmdline[256];
+
+ /* the login name of the user that owns this process */
+ char userName[32];
+} ProcessInfo;
+
+static unsigned ProcessCount;
+
+static int
+processCmp(void* p1, void* p2)
+{
+ return (((ProcessInfo*) p1)->pid - ((ProcessInfo*) p2)->pid);
+}
+
+static ProcessInfo*
+findProcessInList(int pid)
+{
+ ProcessInfo key;
+ long index;
+
+ key.pid = pid;
+ if ((index = search_ctnr(ProcessList, processCmp, &key)) < 0)
+ return (0);
+
+ return (get_ctnr(ProcessList, index));
+}
+
+static int
+updateProcess(int pid)
+{
+ static char *statuses[] = { "idle","run","sleep","stop","zombie" };
+
+ ProcessInfo* ps;
+ struct passwd* pwent;
+ int mib[4];
+ struct kinfo_proc p;
+ size_t len;
+
+ if ((ps = findProcessInList(pid)) == 0)
+ {
+ ps = (ProcessInfo*) malloc(sizeof(ProcessInfo));
+ ps->pid = pid;
+ ps->centStamp = 0;
+ push_ctnr(ProcessList, ps);
+ bsort_ctnr(ProcessList, processCmp);
+ }
+
+ ps->alive = 1;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = pid;
+
+ len = sizeof (p);
+ if (sysctl(mib, 4, &p, &len, NULL, 0) == -1 || !len)
+ return -1;
+
+ ps->pid = p.kp_proc.p_pid;
+ ps->ppid = p.kp_eproc.e_ppid;
+ ps->uid = p.kp_eproc.e_ucred.cr_uid;
+ ps->gid = p.kp_eproc.e_pgid;
+ ps->priority = p.kp_proc.p_priority;
+ ps->niceLevel = p.kp_proc.p_nice;
+
+ /* this isn't usertime -- it's total time (??) */
+ ps->userTime = p.kp_proc.p_rtime.tv_sec*100+p.kp_proc.p_rtime.tv_usec/100;
+ ps->sysTime = 0;
+ ps->sysLoad = 0;
+
+ /* memory, process name, process uid */
+ /* find out user name with process uid */
+ pwent = getpwuid(ps->uid);
+ strlcpy(ps->userName,pwent&&pwent->pw_name? pwent->pw_name:"????",sizeof(ps->userName));
+ ps->userName[sizeof(ps->userName)-1]='\0';
+
+ ps->userLoad = p.kp_proc.p_pctcpu / 100;
+ ps->vmSize = (p.kp_eproc.e_vm.vm_tsize +
+ p.kp_eproc.e_vm.vm_dsize +
+ p.kp_eproc.e_vm.vm_ssize) * getpagesize();
+ ps->vmRss = p.kp_eproc.e_vm.vm_rssize * getpagesize();
+ strlcpy(ps->name,p.kp_proc.p_comm ? p.kp_proc.p_comm : "????", sizeof(ps->name));
+ strlcpy(ps->status,(p.kp_proc.p_stat>=1)&&(p.kp_proc.p_stat<=5)? statuses[p.kp_proc.p_stat-1]:"????", sizeof(ps->status));
+
+ /* process command line */
+ /* the following line causes segfaults on some FreeBSD systems... why?
+ strncpy(ps->cmdline, p.kp_proc.p_args->ar_args, sizeof(ps->cmdline) - 1);
+ */
+ strcpy(ps->cmdline, "????");
+
+ return (0);
+}
+
+static void
+cleanupProcessList(void)
+{
+ ProcessInfo* ps;
+
+ ProcessCount = 0;
+ /* All processes that do not have the active flag set are assumed dead
+ * and will be removed from the list. The alive flag is cleared. */
+ for (ps = first_ctnr(ProcessList); ps; ps = next_ctnr(ProcessList))
+ {
+ if (ps->alive)
+ {
+ /* Process is still alive. Just clear flag. */
+ ps->alive = 0;
+ ProcessCount++;
+ }
+ else
+ {
+ /* Process has probably died. We remove it from the list and
+ * destruct the data structure. i needs to be decremented so
+ * that after i++ the next list element will be inspected. */
+ free(remove_ctnr(ProcessList));
+ }
+ }
+}
+
+/*
+================================ public part ==================================
+*/
+
+void
+initProcessList(struct SensorModul* sm)
+{
+ ProcessList = new_ctnr();
+
+ registerMonitor("ps", "table", printProcessList, printProcessListInfo, sm);
+ registerMonitor("pscount", "integer", printProcessCount, printProcessCountInfo, sm);
+
+ if (!RunAsDaemon)
+ {
+ registerCommand("kill", killProcess);
+ registerCommand("setpriority", setPriority);
+ }
+
+ updateProcessList();
+}
+
+void
+exitProcessList(void)
+{
+ removeMonitor("ps");
+ removeMonitor("pscount");
+
+ if (ProcessList)
+ free (ProcessList);
+}
+
+int
+updateProcessList(void)
+{
+ int mib[3];
+ size_t len;
+ size_t num;
+ struct kinfo_proc *p;
+
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_ALL;
+ sysctl(mib, 3, NULL, &len, NULL, 0);
+ p = malloc(len);
+ sysctl(mib, 3, p, &len, NULL, 0);
+
+ for (num = 0; num < len / sizeof(struct kinfo_proc); num++)
+ updateProcess(p[num].kp_proc.p_pid);
+ free(p);
+ cleanupProcessList();
+
+ return (0);
+}
+
+void
+printProcessListInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Name\tPID\tPPID\tUID\tGID\tStatus\tUser%%\tSystem%%\tNice\tVmSize\tVmRss\tLogin\tCommand\n");
+ fprintf(CurrentClient, "s\td\td\td\td\tS\tf\tf\td\tD\tD\ts\ts\n");
+}
+
+void
+printProcessList(const char* cmd)
+{
+ ProcessInfo* ps;
+
+ ps = first_ctnr(ProcessList); /* skip 'kernel' entry */
+ for (ps = next_ctnr(ProcessList); ps; ps = next_ctnr(ProcessList))
+ {
+ fprintf(CurrentClient, "%s\t%ld\t%ld\t%ld\t%ld\t%s\t%.2f\t%.2f\t%d\t%d\t%d\t%s\t%s\n",
+ ps->name, (long)ps->pid, (long)ps->ppid,
+ (long)ps->uid, (long)ps->gid, ps->status,
+ ps->userLoad, ps->sysLoad, ps->niceLevel,
+ ps->vmSize / 1024, ps->vmRss / 1024, ps->userName, ps->cmdline);
+ }
+}
+
+void
+printProcessCount(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", ProcessCount);
+}
+
+void
+printProcessCountInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Number of Processes\t1\t65535\t\n");
+}
+
+void
+killProcess(const char* cmd)
+{
+ int sig, pid;
+
+ sscanf(cmd, "%*s %d %d", &pid, &sig);
+ switch(sig)
+ {
+ case MENU_ID_SIGABRT:
+ sig = SIGABRT;
+ break;
+ case MENU_ID_SIGALRM:
+ sig = SIGALRM;
+ break;
+ case MENU_ID_SIGCHLD:
+ sig = SIGCHLD;
+ break;
+ case MENU_ID_SIGCONT:
+ sig = SIGCONT;
+ break;
+ case MENU_ID_SIGFPE:
+ sig = SIGFPE;
+ break;
+ case MENU_ID_SIGHUP:
+ sig = SIGHUP;
+ break;
+ case MENU_ID_SIGILL:
+ sig = SIGILL;
+ break;
+ case MENU_ID_SIGINT:
+ sig = SIGINT;
+ break;
+ case MENU_ID_SIGKILL:
+ sig = SIGKILL;
+ break;
+ case MENU_ID_SIGPIPE:
+ sig = SIGPIPE;
+ break;
+ case MENU_ID_SIGQUIT:
+ sig = SIGQUIT;
+ break;
+ case MENU_ID_SIGSEGV:
+ sig = SIGSEGV;
+ break;
+ case MENU_ID_SIGSTOP:
+ sig = SIGSTOP;
+ break;
+ case MENU_ID_SIGTERM:
+ sig = SIGTERM;
+ break;
+ case MENU_ID_SIGTSTP:
+ sig = SIGTSTP;
+ break;
+ case MENU_ID_SIGTTIN:
+ sig = SIGTTIN;
+ break;
+ case MENU_ID_SIGTTOU:
+ sig = SIGTTOU;
+ break;
+ case MENU_ID_SIGUSR1:
+ sig = SIGUSR1;
+ break;
+ case MENU_ID_SIGUSR2:
+ sig = SIGUSR2;
+ break;
+ }
+ if (kill((pid_t) pid, sig))
+ {
+ switch(errno)
+ {
+ case EINVAL:
+ fprintf(CurrentClient, "4\t%d\n", pid);
+ break;
+ case ESRCH:
+ fprintf(CurrentClient, "3\t%d\n", pid);
+ break;
+ case EPERM:
+ fprintf(CurrentClient, "2\t%d\n", pid);
+ break;
+ default:
+ fprintf(CurrentClient, "1\t%d\n", pid); /* unknown error */
+ break;
+ }
+
+ }
+ else
+ fprintf(CurrentClient, "0\t%d\n", pid);
+}
+
+void
+setPriority(const char* cmd)
+{
+ int pid, prio;
+
+ sscanf(cmd, "%*s %d %d", &pid, &prio);
+ if (setpriority(PRIO_PROCESS, pid, prio))
+ {
+ switch(errno)
+ {
+ case EINVAL:
+ fprintf(CurrentClient, "4\n");
+ break;
+ case ESRCH:
+ fprintf(CurrentClient, "3\n");
+ break;
+ case EPERM:
+ case EACCES:
+ fprintf(CurrentClient, "2\n");
+ break;
+ default:
+ fprintf(CurrentClient, "1\n"); /* unknown error */
+ break;
+ }
+ }
+ else
+ fprintf(CurrentClient, "0\n");
+}
diff --git a/ksysguard/ksysguardd/NetBSD/ProcessList.h b/ksysguard/ksysguardd/NetBSD/ProcessList.h
new file mode 100644
index 000000000..925c55f5a
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/ProcessList.h
@@ -0,0 +1,38 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _process_list_h_
+#define _process_list_h_
+
+void initProcessList(struct SensorModul* sm);
+void exitProcessList(void);
+
+int updateProcessList(void);
+
+void printProcessList(const char*);
+void printProcessListInfo(const char*);
+void printProcessCount(const char* cmd);
+void printProcessCountInfo(const char* cmd);
+
+void killProcess(const char* cmd);
+void setPriority(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/NetBSD/apm.c b/ksysguard/ksysguardd/NetBSD/apm.c
new file mode 100644
index 000000000..f24887483
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/apm.c
@@ -0,0 +1,100 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+
+#include <fcntl.h>
+#include <machine/apmvar.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include "Command.h"
+#include "apm.h"
+#include "ksysguardd.h"
+
+static int ApmFD, BattFill, BattTime;
+
+#define APMDEV "/dev/apm"
+
+/*
+================================ public part =================================
+*/
+
+void
+initApm(struct SensorModul* sm)
+{
+ if ((ApmFD = open(APMDEV, O_RDONLY)) < 0)
+ return;
+
+ if (updateApm() < 0)
+ return;
+
+ registerMonitor("apm/batterycharge", "integer", printApmBatFill,
+ printApmBatFillInfo, sm);
+ registerMonitor("apm/remainingtime", "integer", printApmBatTime,
+ printApmBatTimeInfo, sm);
+}
+
+void
+exitApm(void)
+{
+ removeMonitor("apm/batterycharge");
+ removeMonitor("apm/remainingtime");
+
+ close(ApmFD);
+}
+
+int
+updateApm(void)
+{
+ int retval;
+ struct apm_power_info info;
+ retval = ioctl(ApmFD, APM_IOC_GETPOWER, &info);
+
+ BattFill = info.battery_life;
+ BattTime = info.minutes_left;
+
+ return retval;
+}
+
+void
+printApmBatFill(const char* c)
+{
+ fprintf(CurrentClient, "%d\n", BattFill);
+}
+
+void
+printApmBatFillInfo(const char* c)
+{
+ fprintf(CurrentClient, "Battery charge\t0\t100\t%%\n");
+}
+
+void
+printApmBatTime(const char* c)
+{
+ fprintf(CurrentClient, "%d\n", BattTime);
+}
+
+void
+printApmBatTimeInfo(const char* c)
+{
+ fprintf(CurrentClient, "Remaining battery time\t0\t0\tmin\n");
+}
+
diff --git a/ksysguard/ksysguardd/NetBSD/apm.h b/ksysguard/ksysguardd/NetBSD/apm.h
new file mode 100644
index 000000000..4e3c0c0d3
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/apm.h
@@ -0,0 +1,34 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _apm_h_
+#define _apm_h_
+
+void initApm(struct SensorModul* sm);
+void exitApm(void);
+
+int updateApm(void);
+
+void printApmBatFill(const char*);
+void printApmBatFillInfo(const char*);
+void printApmBatTime(const char*);
+void printApmBatTimeInfo(const char*);
+
+#endif
diff --git a/ksysguard/ksysguardd/NetBSD/diskstat.c b/ksysguard/ksysguardd/NetBSD/diskstat.c
new file mode 100644
index 000000000..818eee1d4
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/diskstat.c
@@ -0,0 +1,249 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "Command.h"
+#include "ccont.h"
+#include "diskstat.h"
+#include "ksysguardd.h"
+
+typedef struct {
+ char device[256];
+ char mntpnt[256];
+ long blocks;
+ long bfree;
+ long bused;
+ int bused_percent;
+} DiskInfo;
+
+static CONTAINER DiskStatList = 0;
+static struct SensorModul* DiskStatSM;
+
+char *getMntPnt(const char *cmd)
+{
+ static char device[1025];
+ char *ptr;
+
+ memset(device, 0, sizeof(device));
+ sscanf(cmd, "partitions%1024s", device);
+
+ ptr = (char *)rindex(device, '/');
+ *ptr = '\0';
+
+ return (char *)device;
+}
+
+int numMntPnt(void)
+{
+ struct statfs *fs_info;
+ int i, n, counter = 0;
+
+ n = getmntinfo(&fs_info, MNT_WAIT);
+ for (i = 0; i < n; i++)
+ if (strcmp(fs_info[i].f_fstypename, "procfs") && strcmp(fs_info[i].f_fstypename, "swap") && strcmp(fs_info[i].f_fstypename, "devfs"))
+ counter++;
+
+ return counter;
+}
+
+/* ------------------------------ public part --------------------------- */
+
+void initDiskStat(struct SensorModul* sm)
+{
+ char monitor[1024];
+ DiskInfo* disk_info;
+
+ DiskStatList = new_ctnr();
+ DiskStatSM = sm;
+
+ updateDiskStat();
+
+ registerMonitor("partitions/list", "listview", printDiskStat, printDiskStatInfo, DiskStatSM);
+
+ for (disk_info = first_ctnr(DiskStatList); disk_info; disk_info = next_ctnr(DiskStatList)) {
+ snprintf(monitor, sizeof(monitor), "partitions%s/usedspace", disk_info->mntpnt);
+ registerMonitor(monitor, "integer", printDiskStatUsed, printDiskStatUsedInfo, DiskStatSM);
+ snprintf(monitor, sizeof(monitor), "partitions%s/freespace", disk_info->mntpnt);
+ registerMonitor(monitor, "integer", printDiskStatFree, printDiskStatFreeInfo, DiskStatSM);
+ snprintf(monitor, sizeof(monitor), "partitions%s/filllevel", disk_info->mntpnt);
+ registerMonitor(monitor, "integer", printDiskStatPercent, printDiskStatPercentInfo, DiskStatSM);
+ }
+}
+
+void checkDiskStat(void)
+{
+ if (numMntPnt() != level_ctnr(DiskStatList)) {
+ /* a filesystem was mounted or unmounted
+ so we do a reset */
+ exitDiskStat();
+ initDiskStat(DiskStatSM);
+ }
+}
+
+void exitDiskStat(void)
+{
+ DiskInfo *disk_info;
+ char monitor[1024];
+
+ removeMonitor("partitions/list");
+
+ for (disk_info = first_ctnr(DiskStatList); disk_info; disk_info = next_ctnr(DiskStatList)) {
+ snprintf(monitor, sizeof(monitor), "partitions%s/usedspace", disk_info->mntpnt);
+ removeMonitor(monitor);
+ snprintf(monitor, sizeof(monitor), "partitions%s/freespace", disk_info->mntpnt);
+ removeMonitor(monitor);
+ snprintf(monitor, sizeof(monitor), "partitions%s/filllevel", disk_info->mntpnt);
+ removeMonitor(monitor);
+ }
+
+ destr_ctnr(DiskStatList, free);
+}
+
+int updateDiskStat(void)
+{
+ struct statfs *fs_info;
+ struct statfs fs;
+ float percent;
+ int i, mntcount;
+ DiskInfo *disk_info;
+
+ /* let's hope there is no difference between the DiskStatList and
+ the number of mounted filesystems */
+ for (i = level_ctnr(DiskStatList); i >= 0; --i)
+ free(pop_ctnr(DiskStatList));
+
+ mntcount = getmntinfo(&fs_info, MNT_WAIT);
+
+ for (i = 0; i < mntcount; i++) {
+ fs = fs_info[i];
+ if (strcmp(fs.f_fstypename, "procfs") && strcmp(fs.f_fstypename, "devfs") && strcmp(fs.f_fstypename, "devfs")) {
+ percent = (((float)fs.f_blocks - (float)fs.f_bfree)/(float)fs.f_blocks);
+ percent = percent * 100;
+ if ((disk_info = (DiskInfo *)malloc(sizeof(DiskInfo))) == NULL) {
+ continue;
+ }
+ memset(disk_info, 0, sizeof(DiskInfo));
+ strlcpy(disk_info->device, fs.f_mntfromname, sizeof(disk_info->device));
+ if (!strcmp(fs.f_mntonname, "/")) {
+ strncpy(disk_info->mntpnt, "/root", 6);
+ } else {
+ strlcpy(disk_info->mntpnt, fs.f_mntonname, sizeof(disk_info->mntpnt));
+ }
+ disk_info->blocks = fs.f_blocks;
+ disk_info->bfree = fs.f_bfree;
+ disk_info->bused = (fs.f_blocks - fs.f_bfree);
+ disk_info->bused_percent = (int)percent;
+
+ push_ctnr(DiskStatList, disk_info);
+ }
+ }
+
+ return 0;
+}
+
+void printDiskStat(const char* cmd)
+{
+ DiskInfo* disk_info;
+
+ for (disk_info = first_ctnr(DiskStatList); disk_info; disk_info = next_ctnr(DiskStatList)) {
+ fprintf(CurrentClient, "%s\t%ld\t%ld\t%ld\t%d\t%s\n",
+ disk_info->device,
+ disk_info->blocks,
+ disk_info->bused,
+ disk_info->bfree,
+ disk_info->bused_percent,
+ disk_info->mntpnt);
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printDiskStatInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Device\tBlocks\tUsed\tAvailable\tUsed %%\tMountPoint\nM\tD\tD\tD\td\ts\n");
+}
+
+void printDiskStatUsed(const char* cmd)
+{
+ DiskInfo* disk_info;
+ char *mntpnt = (char *)getMntPnt(cmd);
+
+ for (disk_info = first_ctnr(DiskStatList); disk_info; disk_info = next_ctnr(DiskStatList)) {
+ if (!strcmp(mntpnt, disk_info->mntpnt)) {
+ fprintf(CurrentClient, "%ld\n", disk_info->bused);
+ }
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printDiskStatUsedInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Used Blocks\t0\t-\tBlocks\n");
+}
+
+void printDiskStatFree(const char* cmd)
+{
+ DiskInfo* disk_info;
+ char *mntpnt = (char *)getMntPnt(cmd);
+
+ for (disk_info = first_ctnr(DiskStatList); disk_info; disk_info = next_ctnr(DiskStatList)) {
+ if (!strcmp(mntpnt, disk_info->mntpnt)) {
+ fprintf(CurrentClient, "%ld\n", disk_info->bfree);
+ }
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printDiskStatFreeInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Free Blocks\t0\t-\tBlocks\n");
+}
+
+void printDiskStatPercent(const char* cmd)
+{
+ DiskInfo* disk_info;
+ char *mntpnt = (char *)getMntPnt(cmd);
+
+ for (disk_info = first_ctnr(DiskStatList); disk_info; disk_info = next_ctnr(DiskStatList)) {
+ if (!strcmp(mntpnt, disk_info->mntpnt)) {
+ fprintf(CurrentClient, "%d\n", disk_info->bused_percent);
+ }
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printDiskStatPercentInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Used Blocks\t0\t100\t%%\n");
+}
diff --git a/ksysguard/ksysguardd/NetBSD/diskstat.h b/ksysguard/ksysguardd/NetBSD/diskstat.h
new file mode 100644
index 000000000..06f247837
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/diskstat.h
@@ -0,0 +1,40 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _diskstat_h_
+#define _diskstat_h_
+
+void initDiskStat(struct SensorModul* sm);
+void exitDiskStat(void);
+
+int updateDiskStat(void);
+void checkDiskStat(void);
+
+void printDiskStat(const char* cmd);
+void printDiskStatInfo(const char* cmd);
+
+void printDiskStatUsed(const char* cmd);
+void printDiskStatUsedInfo(const char* cmd);
+void printDiskStatFree(const char* cmd);
+void printDiskStatFreeInfo(const char* cmd);
+void printDiskStatPercent(const char* cmd);
+void printDiskStatPercentInfo(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/NetBSD/loadavg.c b/ksysguard/ksysguardd/NetBSD/loadavg.c
new file mode 100644
index 000000000..53eb9fc4e
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/loadavg.c
@@ -0,0 +1,96 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "Command.h"
+#include "ksysguardd.h"
+#include "loadavg.h"
+
+static double LoadAvg[3];
+
+/*
+================================ public part =================================
+*/
+
+void
+initLoadAvg(struct SensorModul* sm)
+{
+ if (updateLoadAvg() < 0)
+ return;
+
+ registerMonitor("cpu/loadavg1", "float", printLoadAvg1,
+ printLoadAvg1Info, sm);
+ registerMonitor("cpu/loadavg5", "float", printLoadAvg5,
+ printLoadAvg5Info, sm);
+ registerMonitor("cpu/loadavg15", "float", printLoadAvg15,
+ printLoadAvg15Info, sm);
+}
+
+void
+exitLoadAvg(void)
+{
+ removeMonitor("cpu/loadavg1");
+ removeMonitor("cpu/loadavg5");
+ removeMonitor("cpu/loadavg15");
+}
+
+int
+updateLoadAvg(void)
+{
+ return getloadavg(LoadAvg, 3);
+}
+
+void
+printLoadAvg1(const char* c)
+{
+ fprintf(CurrentClient, "%f\n", LoadAvg[0]);
+}
+
+void
+printLoadAvg1Info(const char* c)
+{
+ fprintf(CurrentClient, "Load average 1 min\t0\t0\t\n");
+}
+
+void
+printLoadAvg5(const char* c)
+{
+ fprintf(CurrentClient, "%f\n", LoadAvg[1]);
+}
+
+void
+printLoadAvg5Info(const char* c)
+{
+ fprintf(CurrentClient, "Load average 5 min\t0\t0\t\n");
+}
+
+void
+printLoadAvg15(const char* c)
+{
+ fprintf(CurrentClient, "%f\n", LoadAvg[2]);
+}
+
+void
+printLoadAvg15Info(const char* c)
+{
+ fprintf(CurrentClient, "Load average 15 min\t0\t0\t\n");
+}
diff --git a/ksysguard/ksysguardd/NetBSD/loadavg.h b/ksysguard/ksysguardd/NetBSD/loadavg.h
new file mode 100644
index 000000000..801e4ef8d
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/loadavg.h
@@ -0,0 +1,36 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _loadavg_h_
+#define _loadavg_h_
+
+void initLoadAvg(struct SensorModul* sm);
+void exitLoadAvg(void);
+
+int updateLoadAvg(void);
+
+void printLoadAvg1(const char*);
+void printLoadAvg1Info(const char*);
+void printLoadAvg5(const char*);
+void printLoadAvg5Info(const char*);
+void printLoadAvg15(const char*);
+void printLoadAvg15Info(const char*);
+
+#endif
diff --git a/ksysguard/ksysguardd/NetBSD/logfile.c b/ksysguard/ksysguardd/NetBSD/logfile.c
new file mode 100644
index 000000000..3b07ad8ac
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/logfile.c
@@ -0,0 +1,175 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "Command.h"
+#include "ccont.h"
+#include "conf.h"
+#include "ksysguardd.h"
+#include "logfile.h"
+
+static CONTAINER LogFiles = 0;
+static unsigned long counter = 1;
+
+typedef struct {
+ char name[256];
+ FILE* fh;
+ unsigned long id;
+} LogFileEntry;
+
+extern CONTAINER LogFileList;
+
+/*
+================================ public part =================================
+*/
+
+void initLogFile(struct SensorModul* sm)
+{
+ char monitor[1024];
+ ConfigLogFile *entry;
+
+ registerCommand("logfile_register", registerLogFile);
+ registerCommand("logfile_unregister", unregisterLogFile);
+ registerCommand("logfile_registered", printRegistered);
+
+ for (entry = first_ctnr(LogFileList); entry; entry = next_ctnr(LogFileList))
+ {
+ FILE* fp;
+
+ /* register the log file if we can actually read the file. */
+ if ((fp = fopen(entry->path, "r")) != NULL)
+ {
+ fclose(fp);
+ snprintf(monitor, 1024, "logfiles/%s", entry->name);
+ registerMonitor(monitor, "logfile", printLogFile,
+ printLogFileInfo, sm);
+ }
+ }
+
+ LogFiles = new_ctnr();
+}
+
+void exitLogFile(void)
+{
+ destr_ctnr(LogFiles, free);
+}
+
+void printLogFile(const char* cmd)
+{
+ char line[1024];
+ unsigned long id;
+ int i;
+ char ch;
+ LogFileEntry *entry;
+
+ sscanf(cmd, "%*s %lu", &id);
+
+ for (entry = first_ctnr(LogFiles); entry; entry = next_ctnr(LogFiles)) {
+ if (entry->id == id) {
+ while (fgets(line, sizeof(line), entry->fh) != NULL) {
+ fprintf(CurrentClient, "%s", line);
+ }
+ clearerr(entry->fh);
+ }
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printLogFileInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "LogFile\n");
+}
+
+void registerLogFile(const char* cmd)
+{
+ char name[257];
+ FILE* file;
+ LogFileEntry *entry;
+ ConfigLogFile *conf;
+
+ memset(name, 0, sizeof(name));
+ sscanf(cmd, "%*s %256s", name);
+
+ for (conf = first_ctnr(LogFileList); conf; conf = next_ctnr(LogFileList)) {
+ if (!strcmp(conf->name, name)) {
+ if ((file = fopen(conf->path, "r")) == NULL) {
+ print_error("fopen()");
+ fprintf(CurrentClient, "0\n");
+ return;
+ }
+
+ fseek(file, 0, SEEK_END);
+
+ if ((entry = (LogFileEntry *)malloc(sizeof(LogFileEntry))) == NULL) {
+ print_error("malloc()");
+ fprintf(CurrentClient, "0\n");
+ return;
+ }
+
+ entry->fh = file;
+ strlcpy(entry->name, conf->name, sizeof(entry->name));
+ entry->id = counter;
+
+ push_ctnr(LogFiles, entry);
+
+ fprintf(CurrentClient, "%lu\n", counter);
+ counter++;
+
+ return;
+ }
+ }
+
+ fprintf(CurrentClient, "0\n");
+}
+
+void unregisterLogFile(const char* cmd)
+{
+ unsigned long id;
+ LogFileEntry *entry;
+
+ sscanf(cmd, "%*s %lu", &id);
+
+ for (entry = first_ctnr(LogFiles); entry; entry = next_ctnr(LogFiles)) {
+ if (entry->id == id) {
+ fclose(entry->fh);
+ free(remove_ctnr(LogFiles));
+ fprintf(CurrentClient, "\n");
+ return;
+ }
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printRegistered(const char* cmd)
+{
+ LogFileEntry *entry;
+
+ for (entry = first_ctnr(LogFiles); entry; entry = next_ctnr(LogFiles))
+ fprintf(CurrentClient, "%s:%lu\n", entry->name, entry->id);
+
+ fprintf(CurrentClient, "\n");
+}
diff --git a/ksysguard/ksysguardd/NetBSD/logfile.h b/ksysguard/ksysguardd/NetBSD/logfile.h
new file mode 100644
index 000000000..45ade9013
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/logfile.h
@@ -0,0 +1,36 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _logfile_h_
+#define _logfile_h_
+
+void initLogFile(struct SensorModul* sm);
+void exitLogFile(void);
+
+void printLogFile(const char* cmd);
+void printLogFileInfo(const char* cmd);
+
+void registerLogFile(const char* cmd);
+void unregisterLogFile(const char* cmd);
+
+/* debug command */
+void printRegistered(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/NetBSD/netdev.c b/ksysguard/ksysguardd/NetBSD/netdev.c
new file mode 100644
index 000000000..477acc40e
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/netdev.c
@@ -0,0 +1,304 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+
+#include <net/route.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "Command.h"
+#include "ksysguardd.h"
+#include "netdev.h"
+
+
+#define I_bytes 0
+#define I_packs 1
+#define I_errs 2
+#define I_mcasts 3
+#define I_lost 4
+
+typedef struct {
+ char name[32];
+ u_long recv[5], Drecv[5], sent[5], Dsent[5];
+} NetDevInfo;
+
+#define LEN(X) (sizeof(X)/sizeof(X[0]))
+
+#define MAXNETDEVS 64
+static NetDevInfo NetDevs[MAXNETDEVS], newval[MAXNETDEVS];
+static int NetDevCnt = 0;
+static struct SensorModul *NetDevSM;
+
+/* Read the system's traffic registers.
+ * Merely count the IFs if countp nonzero.
+ * Returns count of IFs read, or -1; the data are written into newval.
+ * Based on getifaddrs source; getifaddrs itself seems to
+ * compile incorrectly, omitting the traffic data. (It also
+ * does things this doesn't need, thus this is slightly more efficient.)
+ */
+static int readSys(int countp)
+{
+ size_t len;
+ char *bfr, *ptr;
+ struct rt_msghdr *rtm;
+ NetDevInfo *nv;
+ static int mib[] = {
+ /* see sysctl(3): */
+ CTL_NET,
+ PF_ROUTE,
+ 0, /* `currently always 0' */
+ 0, /* `may be set to 0 to select all address families' */
+ NET_RT_IFLIST,
+ 0 /* ignored but six levels are needed */
+ };
+
+ if (-1==sysctl(mib, LEN(mib), NULL, &len, NULL, 0))
+ return -1;
+ if (!(bfr = malloc(len)))
+ return -1;
+ if (-1==sysctl(mib, LEN(mib), bfr, &len, NULL, 0)) {
+ free(bfr);
+ return -1;
+ }
+ nv = newval;
+ for (ptr=bfr; ptr<bfr+len; ptr+=rtm->rtm_msglen) {
+ struct if_msghdr *ifm;
+
+ rtm = (void*)ptr; /* chg ptr type to router msg */
+
+ if (rtm->rtm_version != RTM_VERSION) {
+ continue;
+ }
+
+ if (rtm->rtm_type != RTM_IFINFO) {
+ continue;
+ }
+
+ ifm = (void*)rtm; /* chg ptr type to interface msg */
+ if (!(ifm->ifm_flags & IFF_UP)) {
+ continue;
+ }
+
+ if (!countp) {
+ /* a sdl is concat'd to the if msg */
+ struct sockaddr_dl *sdl = (void*)(ifm+1);
+
+ /* copy and terminate the name */
+ /*fixme: check for overruns */
+ memcpy(nv->name, sdl->sdl_data, sdl->sdl_nlen);
+ nv->name[sdl->sdl_nlen] = 0;
+
+ /* copy the data */
+ nv->recv[I_bytes] = ifm->ifm_data.ifi_ibytes;
+ nv->recv[I_packs] = ifm->ifm_data.ifi_ipackets;
+ nv->recv[I_errs] = ifm->ifm_data.ifi_ierrors;
+ nv->recv[I_mcasts] = ifm->ifm_data.ifi_imcasts;
+ nv->recv[I_lost] = ifm->ifm_data.ifi_iqdrops;
+ nv->sent[I_bytes] = ifm->ifm_data.ifi_obytes;
+ nv->sent[I_packs] = ifm->ifm_data.ifi_opackets;
+ nv->sent[I_errs] = ifm->ifm_data.ifi_oerrors;
+ nv->sent[I_mcasts] = ifm->ifm_data.ifi_omcasts;
+ nv->sent[I_lost] = ifm->ifm_data.ifi_collisions;
+ }
+
+ /*fixme: guard against buffer overrun */
+ nv++;
+ }
+ free(bfr);
+ return nv-newval;
+}
+
+
+/* ------------------------------ public part --------------------------- */
+
+static void prVal(const char*, int);
+void printNetDevRecv(const char *cmd) { prVal(cmd,0); }
+void printNetDevSent(const char *cmd) { prVal(cmd,1); }
+
+static void prInfo(const char*, int);
+void printNetDevRecvInfo(const char *cmd) { prInfo(cmd,0); }
+void printNetDevSentInfo(const char *cmd) { prInfo(cmd,1); }
+
+static struct {
+ char *label;
+ cmdExecutor read, inform;
+ struct {
+ char *label, *info;
+ int index;
+ } op[5];
+} opTable[] = {
+ {"receiver",
+ printNetDevRecv, printNetDevRecvInfo,
+ {{"data", "Received Data\t0\t0\tB/s\n", I_bytes},
+ {"packets", "Received Packets\t0\t0\tHz\n", I_packs},
+ {"errors", "Receiver Errors\t0\t0\tHz\n", I_errs},
+ {"multicast", "Received Multicast Packets\t0\t0\tHz\n", I_mcasts},
+ {"drops", "Receiver Drops\t0\t0\tHz\n", I_lost}}},
+ {"transmitter",
+ printNetDevSent, printNetDevSentInfo,
+ {{"data", "Sent Data\t0\t0\tB/s\n", I_bytes},
+ {"packets", "Sent Packets\t0\t0\tHz\n", I_packs},
+ {"errors", "Transmitter Errors\t0\t0\tHz\n", I_errs},
+ {"multicast", "Sent Multicast Packets\t0\t0\tHz\n", I_mcasts},
+ {"collisions", "Transmitter Collisions\t0\t0\tHz\n", I_lost}}}
+};
+
+
+static void prVal(const char *cmd, int N) {
+ char *p, *q, *r;
+ int i, d;
+
+ if (!(p=rindex(cmd, '/')))
+ return;
+ *p=0;
+ q=rindex(cmd, '/');
+ *q=0;
+ r=rindex(cmd, '/');
+ r++;
+ for (d=NetDevCnt; d--; )
+ if (!strcmp(r, NetDevs[d].name))
+ break;
+ *q=*p='/';
+
+ if (-1 == d) return;
+
+ p++;
+ for (i=0; i<LEN(opTable[0].op); i++)
+ if (!strcmp(p, opTable[N].op[i].label))
+ fprintf(CurrentClient, "%lu",
+ /*fixme: ugly and presumptuous */
+ (N?NetDevs[d].Dsent:NetDevs[d].Drecv)[opTable[N].op[i].index]);
+ fprintf(CurrentClient, "\n");
+}
+
+
+static void prInfo(const char *cmd, int N) {
+ char *p, *q;
+ int i;
+
+ if (!(p=rindex(cmd, '/'))) return;
+ p++;
+
+ q = p+strlen(p)-1;
+ if ('?' != *q) return;
+ *q=0;
+
+ for (i=0; i<LEN(opTable[0].op); i++)
+ if (!strcmp(p, opTable[N].op[i].label))
+ fputs(opTable[N].op[i].info, CurrentClient);
+ *q='?';
+}
+
+
+
+static void NDreg (int setp)
+{
+ int i;
+
+ for (i = 0; i<NetDevCnt; i++) {
+ int j;
+
+ for (j=0; j<LEN(opTable); j++) {
+ int k;
+
+ for (k=0; k<LEN(opTable[0].op); k++) {
+ char buffer[1024];
+
+ snprintf(buffer, sizeof(buffer),
+ "network/interfaces/%s/%s/%s",
+ NetDevs[i].name,
+ opTable[j].label,
+ opTable[j].op[k].label);
+
+ /* printf("%d %d %d %s\n",i,j,k,buffer); */
+
+ if (setp)
+ registerMonitor(buffer,
+ "integer",
+ opTable[j].read,
+ opTable[j].inform, NetDevSM);
+ else
+ removeMonitor(buffer);
+ }
+
+ }
+ }
+}
+
+void initNetDev(struct SensorModul* sm) {
+ int i;
+
+ NetDevSM = sm;
+
+ updateNetDev();
+
+ for (i=LEN(NetDevs); i--;) {
+ strcpy(NetDevs[i].name, newval[i].name);
+ }
+
+ NDreg(!0);
+}
+
+
+void exitNetDev(void) {
+ NDreg(0);
+}
+
+void updateNetDev(void) {
+ NetDevInfo *p, *q;
+ int n;
+
+ if (-1==(n = readSys(0)))
+ return;
+
+ NetDevCnt = n;
+ /*fixme: assumes the interfaces are in the same order each time */
+ for (p=NetDevs, q=newval; n--; p++, q++) {
+ int i;
+ /* calculate deltas */
+ for (i=0; i<5; i++) {
+ p->Drecv[i] = q->recv[i]-p->recv[i];
+ p->recv[i] = q->recv[i];
+ p->Dsent[i] = q->sent[i]-p->sent[i];
+ p->sent[i] = q->sent[i];
+
+ }
+ }
+}
+
+void checkNetDev(void) {
+ if (readSys(!0) != NetDevCnt) {
+ /* interface has been added or removed
+ so we do a reset */
+ exitNetDev();
+ initNetDev(NetDevSM);
+ }
+}
+
+
+/* eof */
diff --git a/ksysguard/ksysguardd/NetBSD/netdev.h b/ksysguard/ksysguardd/NetBSD/netdev.h
new file mode 100644
index 000000000..4287c9203
--- /dev/null
+++ b/ksysguard/ksysguardd/NetBSD/netdev.h
@@ -0,0 +1,35 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _netdev_h_
+#define _netdev_h_
+
+void initNetDev(struct SensorModul* sm);
+void exitNetDev(void);
+
+void updateNetDev(void);
+void checkNetDev(void);
+
+void printNetDevRecBytes(const char* cmd);
+void printNetDevRecBytesInfo(const char* cmd);
+void printNetDevSentBytes(const char* cmd);
+void printNetDevSentBytesInfo(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/OpenBSD/Makefile.am b/ksysguard/ksysguardd/OpenBSD/Makefile.am
new file mode 100644
index 000000000..78d97e293
--- /dev/null
+++ b/ksysguard/ksysguardd/OpenBSD/Makefile.am
@@ -0,0 +1,6 @@
+AM_CFLAGS = -Wall
+
+INCLUDES = -I$(srcdir)/../../CContLib -I$(srcdir)/..
+
+noinst_LIBRARIES = libksysguardd.a
+libksysguardd_a_SOURCES = cpu.c memory.c
diff --git a/ksysguard/ksysguardd/OpenBSD/cpu.c b/ksysguard/ksysguardd/OpenBSD/cpu.c
new file mode 100644
index 000000000..3d1535ffe
--- /dev/null
+++ b/ksysguard/ksysguardd/OpenBSD/cpu.c
@@ -0,0 +1,209 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/dkstat.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "cpu.h"
+#include "Command.h"
+#include "ksysguardd.h"
+
+long percentages(int cnt, int *out, long *new, long *old, long *diffs);
+
+unsigned long cp_time_offset;
+
+long cp_time[CPUSTATES];
+long cp_old[CPUSTATES];
+long cp_diff[CPUSTATES];
+int cpu_states[CPUSTATES];
+
+void
+initCpuInfo(struct SensorModul* sm)
+{
+ /* Total CPU load */
+ registerMonitor("cpu/user", "integer", printCPUUser,
+ printCPUUserInfo, sm);
+ registerMonitor("cpu/nice", "integer", printCPUNice,
+ printCPUNiceInfo, sm);
+ registerMonitor("cpu/sys", "integer", printCPUSys,
+ printCPUSysInfo, sm);
+ registerMonitor("cpu/idle", "integer", printCPUIdle,
+ printCPUIdleInfo, sm);
+ registerMonitor("cpu/interrupt", "integer", printCPUInterrupt,
+ printCPUInterruptInfo, sm);
+
+ updateCpuInfo();
+}
+
+void
+exitCpuInfo(void)
+{
+}
+
+int
+updateCpuInfo(void)
+{
+ static int cp_time_mib[] = {CTL_KERN, KERN_CPTIME};
+ size_t size;
+ size=sizeof(cp_time);
+ sysctl(cp_time_mib, 2, &cp_time, &size, NULL, 0);
+ percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
+ return (0);
+}
+
+void
+printCPUUser(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CP_USER]/10);
+}
+
+void
+printCPUUserInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU User Load\t0\t100\t%%\n");
+}
+
+void
+printCPUNice(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CP_NICE]/10);
+}
+
+void
+printCPUNiceInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU Nice Load\t0\t100\t%%\n");
+}
+
+void
+printCPUSys(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CP_SYS]/10);
+}
+
+void
+printCPUSysInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU System Load\t0\t100\t%%\n");
+}
+
+void
+printCPUIdle(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CP_IDLE]/10);
+}
+
+void
+printCPUIdleInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU Idle Load\t0\t100\t%%\n");
+}
+
+void
+printCPUInterrupt(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", cpu_states[CP_INTR]/10);
+}
+
+void
+printCPUInterruptInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "CPU Interrupt Load\t0\t100\t%%\n");
+}
+
+/* The part ripped from top... */
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ */
+
+/*
+ * percentages(cnt, out, new, old, diffs) - calculate percentage change
+ * between array "old" and "new", putting the percentages i "out".
+ * "cnt" is size of each array and "diffs" is used for scratch space.
+ * The array "old" is updated on each call.
+ * The routine assumes modulo arithmetic. This function is especially
+ * useful on BSD mchines for calculating cpu state percentages.
+ */
+
+long percentages(cnt, out, new, old, diffs)
+
+int cnt;
+int *out;
+register long *new;
+register long *old;
+long *diffs;
+
+{
+ register int i;
+ register long change;
+ register long total_change;
+ register long *dp;
+ long half_total;
+
+ /* initialization */
+ total_change = 0;
+ dp = diffs;
+
+ /* calculate changes for each state and the overall change */
+ for (i = 0; i < cnt; i++)
+ {
+ if ((change = *new - *old) < 0)
+ {
+ /* this only happens when the counter wraps */
+ change = (int)
+ ((unsigned long)*new-(unsigned long)*old);
+ }
+ total_change += (*dp++ = change);
+ *old++ = *new++;
+ }
+
+ /* avoid divide by zero potential */
+ if (total_change == 0)
+ {
+ total_change = 1;
+ }
+
+ /* calculate percentages based on overall change, rounding up */
+ half_total = total_change / 2l;
+
+ /* Do not divide by 0. Causes Floating point exception */
+ if(total_change) {
+ for (i = 0; i < cnt; i++)
+ {
+ *out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
+ }
+ }
+
+ /* return the total in case the caller wants to use it */
+ return(total_change);
+}
diff --git a/ksysguard/ksysguardd/OpenBSD/cpu.h b/ksysguard/ksysguardd/OpenBSD/cpu.h
new file mode 100644
index 000000000..a1188cd82
--- /dev/null
+++ b/ksysguard/ksysguardd/OpenBSD/cpu.h
@@ -0,0 +1,51 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _cpuinfo_h_
+#define _cpuinfo_h_
+
+struct SensorModul;
+
+void initCpuInfo(struct SensorModul* sm);
+void exitCpuInfo(void);
+
+int updateCpuInfo(void);
+
+void printCPUUser(const char* cmd);
+void printCPUUserInfo(const char* cmd);
+void printCPUNice(const char* cmd);
+void printCPUNiceInfo(const char* cmd);
+void printCPUSys(const char* cmd);
+void printCPUSysInfo(const char* cmd);
+void printCPUIdle(const char* cmd);
+void printCPUIdleInfo(const char* cmd);
+void printCPUInterrupt(const char* cmd);
+void printCPUInterruptInfo(const char* cmd);
+void printCPUxUser(const char* cmd);
+void printCPUxUserInfo(const char* cmd);
+void printCPUxNice(const char* cmd);
+void printCPUxNiceInfo(const char* cmd);
+void printCPUxSys(const char* cmd);
+void printCPUxSysInfo(const char* cmd);
+void printCPUxIdle(const char* cmd);
+void printCPUxIdleInfo(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/OpenBSD/memory.c b/ksysguard/ksysguardd/OpenBSD/memory.c
new file mode 100644
index 000000000..aaf893268
--- /dev/null
+++ b/ksysguard/ksysguardd/OpenBSD/memory.c
@@ -0,0 +1,207 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+ Copyright (c) 1999-2000 Hans Petter Bieker <bieker@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/dkstat.h>
+#include <sys/swap.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "Command.h"
+#include "memory.h"
+#include "ksysguardd.h"
+
+static size_t Total = 0;
+static size_t MFree = 0;
+static size_t Active = 0;
+static size_t InActive = 0;
+static size_t STotal = 0;
+static size_t SFree = 0;
+static size_t SUsed = 0;
+static int pageshift = 0;
+
+/* define pagetok in terms of pageshift */
+#define pagetok(size) ((size) << pageshift)
+
+void swapmode(int *used, int *total);
+
+void
+initMemory(struct SensorModul* sm)
+{
+ int pagesize;
+ static int physmem_mib[] = { CTL_HW, HW_PHYSMEM };
+ size_t size;
+ /* get the page size with "getpagesize" and calculate pageshift from
+ * it */
+ pagesize = getpagesize();
+ pageshift = 0;
+ while (pagesize > 1) {
+ pageshift++;
+ pagesize >>= 1;
+ }
+ size = sizeof(Total);
+ sysctl(physmem_mib, 2, &Total, &size, NULL, 0);
+ Total /= 1024;
+ swapmode(&SUsed, &STotal);
+
+ registerMonitor("mem/physical/free", "integer", printMFree, printMFreeInfo, sm);
+ registerMonitor("mem/physical/active", "integer", printActive, printActiveInfo, sm);
+ registerMonitor("mem/physical/inactive", "integer", printInActive, printInActiveInfo, sm);
+ registerMonitor("mem/swap/free", "integer", printSwapFree, printSwapFreeInfo, sm);
+ registerMonitor("mem/swap/used", "integer", printSwapUsed, printSwapUsedInfo, sm);
+}
+
+void
+exitMemory(void)
+{
+}
+
+int
+updateMemory(void)
+{
+ static int vmtotal_mib[] = {CTL_VM, VM_METER};
+ size_t size;
+ struct vmtotal vmtotal;
+ size = sizeof(vmtotal);
+
+ if (sysctl(vmtotal_mib, 2, &vmtotal, &size, NULL, 0) < 0)
+ return -1;
+
+ MFree = pagetok(vmtotal.t_free);
+ MFree /= 1024;
+ Active = pagetok(vmtotal.t_arm);
+ Active /= 1024;
+ InActive = pagetok(vmtotal.t_rm);
+ InActive /= 1024;
+ InActive -= Active;
+
+ swapmode(&SUsed, &STotal);
+ SFree = STotal - SUsed;
+ return 0;
+}
+
+void
+printMFree(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", MFree);
+}
+
+void
+printMFreeInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Free Memory\t0\t%d\tKB\n", Total);
+}
+
+void
+printActive(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", Active);
+}
+
+void
+printActiveInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Active Memory\t0\t%d\tKB\n", Total);
+}
+
+void
+printInActive(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", InActive);
+}
+
+void
+printInActiveInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "InActive Memory\t0\t%d\tKB\n", Total);
+}
+
+void
+printSwapUsed(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", SUsed);
+}
+
+void
+printSwapUsedInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Used Swap Memory\t0\t%d\tKB\n", STotal);
+}
+
+void
+printSwapFree(const char* cmd)
+{
+ fprintf(CurrentClient, "%d\n", SFree);
+}
+
+void
+printSwapFreeInfo(const char* cmd)
+{
+ fprintf(CurrentClient, "Free Swap Memory\t0\t%d\tKB\n", STotal);
+}
+
+/*
+This function swapmode was originally written by Tobias
+Weingartner <weingart@openbsd.org>
+
+Taken from OpenBSD top command
+*/
+void
+swapmode (int *used, int *total)
+{
+ int nswap, rnswap, i;
+ struct swapent *swdev;
+
+ *total = *used = 0;
+
+ /* Number of swap devices */
+ nswap = swapctl(SWAP_NSWAP, 0, 0);
+ if (nswap == 0)
+ return;
+
+ swdev = (struct swapent *) malloc(nswap * sizeof(*swdev));
+ if (swdev == NULL)
+ return;
+
+ rnswap = swapctl(SWAP_STATS, swdev, nswap);
+ if (rnswap == -1) {
+ free(swdev);
+ return;
+ }
+
+ /* if rnswap != nswap, then what? */
+
+ /* Total things up */
+ for (i = 0; i < nswap; i++) {
+ if (swdev[i].se_flags & SWF_ENABLE) {
+ *used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
+ *total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
+ }
+ }
+
+ free(swdev);
+}
diff --git a/ksysguard/ksysguardd/OpenBSD/memory.h b/ksysguard/ksysguardd/OpenBSD/memory.h
new file mode 100644
index 000000000..9cb11373a
--- /dev/null
+++ b/ksysguard/ksysguardd/OpenBSD/memory.h
@@ -0,0 +1,43 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _memory_h_
+#define _memory_h_
+
+struct SensorModul;
+
+void initMemory(struct SensorModul* sm);
+void exitMemory(void);
+
+int updateMemory(void);
+
+void printMFree(const char* cmd);
+void printMFreeInfo(const char* cmd);
+void printActive(const char* cmd);
+void printActiveInfo(const char* cmd);
+void printInActive(const char* cmd);
+void printInActiveInfo(const char* cmd);
+void printSwapUsed(const char* cmd);
+void printSwapUsedInfo(const char* cmd);
+void printSwapFree(const char* cmd);
+void printSwapFreeInfo(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/PWUIDCache.c b/ksysguard/ksysguardd/PWUIDCache.c
new file mode 100644
index 000000000..b0140e0a7
--- /dev/null
+++ b/ksysguard/ksysguardd/PWUIDCache.c
@@ -0,0 +1,114 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include "ccont.h"
+
+#include "PWUIDCache.h"
+
+/* Cached values become invalid after 5 minutes */
+#define TIMEOUT 300
+
+typedef struct {
+ uid_t uid;
+ char* uName;
+ time_t tStamp;
+} CachedPWUID;
+
+static CONTAINER UIDCache = 0;
+static time_t lastCleanup = 0;
+
+void PWUIDCache_cleanup( void* c );
+
+static int uidCmp( void* p1, void* p2 )
+{
+ return ( ((CachedPWUID*)p1)->uid - ((CachedPWUID*)p2)->uid );
+}
+
+void PWUIDCache_cleanup( void* c )
+{
+ if ( c ) {
+ if ( ((CachedPWUID*)c)->uName )
+ free ( ((CachedPWUID*)c)->uName );
+ free ( c );
+ }
+}
+
+void initPWUIDCache()
+{
+ UIDCache = new_ctnr();
+}
+
+void exitPWUIDCache()
+{
+ destr_ctnr( UIDCache, PWUIDCache_cleanup );
+}
+
+const char* getCachedPWUID( uid_t uid )
+{
+ CachedPWUID key;
+ CachedPWUID* entry = 0;
+ long idx;
+ time_t stamp;
+
+ stamp = time( 0 );
+ if ( stamp - lastCleanup > TIMEOUT ) {
+ /* Cleanup cache entries every TIMEOUT seconds so that we
+ * don't pile tons of unused entries, and to make sure that
+ * our entries are not outdated. */
+ for ( entry = first_ctnr( UIDCache ); entry; entry = next_ctnr( UIDCache ) ) {
+ /* If a cache entry has not been updated for TIMEOUT
+ * seconds the entry is removed. */
+ if ( stamp - entry->tStamp > TIMEOUT )
+ PWUIDCache_cleanup( remove_ctnr( UIDCache ) );
+ }
+
+ lastCleanup = stamp;
+ }
+
+ key.uid = uid;
+ if ( ( idx = search_ctnr( UIDCache, uidCmp, &key ) ) < 0 ) {
+ struct passwd* pwent;
+
+ /* User id is not yet known */
+ entry = (CachedPWUID*)malloc( sizeof( CachedPWUID ) );
+ entry->tStamp = stamp;
+ entry->uid = uid;
+
+ pwent = getpwuid( uid );
+ if ( pwent )
+ entry->uName = strdup( pwent->pw_name );
+ else
+ entry->uName = strdup( "?" );
+
+ push_ctnr( UIDCache, entry );
+ bsort_ctnr( UIDCache, uidCmp );
+ } else {
+ /* User is is already known */
+ entry = get_ctnr( UIDCache, idx );
+ }
+
+ return entry->uName;
+}
diff --git a/ksysguard/ksysguardd/PWUIDCache.h b/ksysguard/ksysguardd/PWUIDCache.h
new file mode 100644
index 000000000..ce28df0fc
--- /dev/null
+++ b/ksysguard/ksysguardd/PWUIDCache.h
@@ -0,0 +1,36 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2000 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <sys/types.h>
+
+#ifndef KSG_PWUIDCACHE_H
+#define KSG_PWUIDCACHE_H
+
+/**
+ getpwuid() can be fairly expensive on NIS or LDAP systems that do not
+ use chaching. This module implements a cache for uid to user name
+ mappings.
+ */
+void initPWUIDCache( void );
+void exitPWUIDCache( void );
+
+const char* getCachedPWUID( uid_t uid );
+
+#endif
diff --git a/ksysguard/ksysguardd/Porting-HOWTO b/ksysguard/ksysguardd/Porting-HOWTO
new file mode 100644
index 000000000..4576783bc
--- /dev/null
+++ b/ksysguard/ksysguardd/Porting-HOWTO
@@ -0,0 +1,133 @@
+This document describes the interface between ksysguard and
+ksysguardd. ksysguardd is started as a child of ksysguard, either
+directly or via a shell. Alternatively a ksysguardd can listen on a
+port and a single instance can then be used by multiple instances of
+ksysguard.
+
+This client/server design was chosen, because on some operating
+systems the back-end needs elevated permissions. Since C++ programs
+should NEVER have setgid/setuid permissions, a plain C back-end was
+needed. It also allowed for an easy network support using existing
+security mechanisms (ssh).
+
+ksysguard sends commands and ksysguardd answers to them. Each answer
+ends with the string "\nksysguardd> ". Error messages are enclosed in
+ESC '\033' characters. Therefor regular messages may never contain
+ESC. The set of commands that each ksysguardd implementation supports
+can be very different. There are only a very few mandatory command and
+a few recommended commands.
+
+The mandatory commands are 'monitors', 'test' and 'quit'.
+The recommended commands are:
+
+cpu/idle
+cpu/sys
+cpu/nice
+cpu/user
+mem/swap/free
+mem/swap/used
+mem/physical/cached
+mem/physical/buf
+mem/physical/application
+mem/physical/used
+mem/physical/free
+ps
+pscount
+
+Without these commands KSysGuard is not very helpful.
+
+The 'monitors' command returns the list of available sensors. The
+output looks like this:
+
+--------
+mem/physical/free integer
+ps table
+pscount integer
+ksysguardd>
+--------
+
+Sensor names can be hierarchical. Each level is separated by a
+/. ksysguard uses a tree widget in the SensorBrowser to display the
+commands in a tree. Every sensor name must be followed by the type of
+the sensor separated by a tab. Currently 4 different types of sensors
+are supported, integer, float, listview and table. The table sensor
+returns the information for the ProcessController widget. listview
+sensors use a generic table to display information. To find out more
+about a sensor an additional command must be implemented for each
+sensor that has a questionmark appended to the sensor name. It can be
+used to find out more about the sensor.
+
+--------
+ksysguardd> mem/physical/free?
+Free Memory 0 260708 KB
+ksysguardd>
+--------
+
+integer and float sensor return a short description, the minimum and
+maximum value and the unit. All fields are again separated by
+tabs. The minimum and maximum values can both be 0 to trigger the
+auto-range feature of the display.
+
+--------
+ksysguardd> ps?
+Name PID PPID UID GID Status User% System% Nice VmSize VmRss VmLib Login Command
+s d d d d S f f d d sksysguardd>
+--------
+
+This is the output of the ps? inquiry command. The ps command is the
+only recommended command. The answer to ps? consists of 2 lines. Both
+lines have the same number of fields each separated by a tab. The
+first line specifies the name of the columns and the second the type
+of the values in the column.
+
+d: integer value
+D: integer value that should be localized in the frontend
+f: floating point value
+s: string value
+S: string value that needs to be translated
+ Strings must be added to the ProcessList::columnDict dictionary.
+
+For the ProcessController to function properly the Name and PID
+columns are mandatory. All other columns are optional and their
+content may be implementation dependant. It is highly recommended not
+to deviate from the Linux implementation unless absolutely
+unavoidable, in order to provide a consistent interface across all
+platforms.
+
+The 'test' command can be used by the front-end to find out if a
+certain other command is supported by this version of ksysguardd. The
+command returns "1\n" if the command is supported and "0\n" if the
+command is not supported.
+
+The 'quit' command terminates ksysguardd.
+
+ksysguardd may support dynamic monitor sets. If a CPU is added or an
+interface disabled, monitors may be added or removed. To notify the
+front-end about this, you need to send the string "RECONFIGURE\n" over
+stderr. This causes the front-end to request the list of monitors
+again and adapt it's layout accordingly. If ksysguardd receives a
+command it doesn't know it has to reply with "UNKNOWN
+COMMAND\nksysguardd> ".
+
+ksysguardd does not handle native language support. In order to have a
+minimum installation (only a single file) on the monitored machine,
+all translation are handled by the front-end. Please see the files
+gui/ksgrd/SensorManger.cc and gui/SensorDisplayLib/ProcessTable.cc
+if you add new strings.
+
+/**
+ * Since I'm very much a C++ guy I've written some functions which
+ * provide a similar functionality as template classes for lists and
+ * arrays. The Linux implementation uses them. Feel free to use them for
+ * the ports as well if you like. The interface is described in
+ * CContLib/ccont.h. Unfortunately I still haven't found time to document
+ * it properly, but the use should be fairly obvious.
+ */
+
+Chris <cs@kde.org>
+
+Since the above mentioned CContLib was a little slow I reimplement it and
+wrote some docu stuff in the header file. If you need an example for use
+look at ksysguardd/Linux/diskstat.(h|c).
+
+Tobias <tokoe@kde.org>
diff --git a/ksysguard/ksysguardd/Solaris/LoadAvg.c b/ksysguard/ksysguardd/Solaris/LoadAvg.c
new file mode 100644
index 000000000..aea38a212
--- /dev/null
+++ b/ksysguard/ksysguardd/Solaris/LoadAvg.c
@@ -0,0 +1,120 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "config.h"
+
+#ifdef HAVE_KSTAT
+#include <kstat.h>
+#endif
+
+#include "ksysguardd.h"
+#include "Command.h"
+#include "LoadAvg.h"
+
+double loadavg1 = 0.0;
+double loadavg5 = 0.0;
+double loadavg15 = 0.0;
+
+void initLoadAvg( struct SensorModul* sm ) {
+#ifdef HAVE_KSTAT
+ registerMonitor( "cpu/loadavg1", "float",
+ printLoadAvg1, printLoadAvg1Info, sm );
+ registerMonitor( "cpu/loadavg5", "float",
+ printLoadAvg5, printLoadAvg5Info, sm );
+ registerMonitor( "cpu/loadavg15", "float",
+ printLoadAvg15, printLoadAvg15Info, sm );
+#endif
+}
+
+void exitLoadAvg( void ) {
+}
+
+int updateLoadAvg( void ) {
+
+#ifdef HAVE_KSTAT
+ kstat_ctl_t *kctl;
+ kstat_t *ksp;
+ kstat_named_t *kdata;
+
+ /*
+ * get a kstat handle and update the user's kstat chain
+ */
+ if( (kctl = kstat_open()) == NULL )
+ return( 0 );
+ while( kstat_chain_update( kctl ) != 0 )
+ ;
+
+ /*
+ * traverse the kstat chain to find the appropriate statistics
+ */
+ if( (ksp = kstat_lookup( kctl, "unix", 0, "system_misc" )) == NULL )
+ return( 0 );
+ if( kstat_read( kctl, ksp, NULL ) == -1 )
+ return( 0 );
+
+ /*
+ * lookup the data
+ */
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "avenrun_1min" );
+ if( kdata != NULL )
+ loadavg1 = LOAD( kdata->value.ui32 );
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "avenrun_5min" );
+ if( kdata != NULL )
+ loadavg5 = LOAD( kdata->value.ui32 );
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "avenrun_15min" );
+ if( kdata != NULL )
+ loadavg15 = LOAD( kdata->value.ui32 );
+
+ kstat_close( kctl );
+#endif /* ! HAVE_KSTAT */
+
+ return( 0 );
+}
+
+void printLoadAvg1Info( const char *cmd ) {
+ fprintf(CurrentClient, "avnrun 1min\t0\t0\n" );
+}
+
+void printLoadAvg1( const char *cmd ) {
+ fprintf(CurrentClient, "%f\n", loadavg1 );
+}
+
+void printLoadAvg5Info( const char *cmd ) {
+ fprintf(CurrentClient, "avnrun 5min\t0\t0\n" );
+}
+
+void printLoadAvg5( const char *cmd ) {
+ fprintf(CurrentClient, "%f\n", loadavg5 );
+}
+
+void printLoadAvg15Info( const char *cmd ) {
+ fprintf(CurrentClient, "avnrun 15min\t0\t0\n" );
+}
+
+void printLoadAvg15( const char *cmd ) {
+ fprintf(CurrentClient, "%f\n", loadavg15 );
+}
diff --git a/ksysguard/ksysguardd/Solaris/LoadAvg.h b/ksysguard/ksysguardd/Solaris/LoadAvg.h
new file mode 100644
index 000000000..eea8ad82e
--- /dev/null
+++ b/ksysguard/ksysguardd/Solaris/LoadAvg.h
@@ -0,0 +1,41 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _LoadAvg_h_
+#define _LoadAvg_h_
+
+#define LOAD(a) ((double)(a) / (1 << 8 ))
+
+void initLoadAvg(struct SensorModul* sm);
+void exitLoadAvg(void);
+
+int updateLoadAvg(void);
+
+void printLoadAvg1( const char *cmd );
+void printLoadAvg1Info( const char *cmd );
+void printLoadAvg5( const char *cmd );
+void printLoadAvg5Info( const char *cmd );
+void printLoadAvg15( const char *cmd );
+void printLoadAvg15Info( const char *cmd );
+
+#endif /* _LoadAvg_h_ */
diff --git a/ksysguard/ksysguardd/Solaris/Makefile.am b/ksysguard/ksysguardd/Solaris/Makefile.am
new file mode 100644
index 000000000..f5dd51c96
--- /dev/null
+++ b/ksysguard/ksysguardd/Solaris/Makefile.am
@@ -0,0 +1,10 @@
+#
+#
+
+# Sun's C++ compiler doesn't support -Wall
+#AM_CFLAGS = -Wall
+
+INCLUDES = -I$(srcdir)/../../CContLib -I$(srcdir)/..
+
+noinst_LIBRARIES = libksysguardd.a
+libksysguardd_a_SOURCES = Memory.c LoadAvg.c ProcessList.c NetDev.c
diff --git a/ksysguard/ksysguardd/Solaris/Memory.c b/ksysguard/ksysguardd/Solaris/Memory.c
new file mode 100644
index 000000000..efc2f18ac
--- /dev/null
+++ b/ksysguard/ksysguardd/Solaris/Memory.c
@@ -0,0 +1,223 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "config.h"
+
+/* Stop <sys/swap.h> from crapping out on 32-bit architectures. */
+
+#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
+# undef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 32
+#endif
+
+#include <sys/stat.h>
+#include <sys/swap.h>
+#include <vm/anon.h>
+
+#ifdef HAVE_KSTAT
+#include <kstat.h>
+#endif
+
+#include "ksysguardd.h"
+#include "Command.h"
+#include "Memory.h"
+
+static int Dirty = 1;
+static t_memsize totalmem = (t_memsize) 0;
+static t_memsize freemem = (t_memsize) 0;
+static long totalswap = 0L;
+static long freeswap = 0L;
+static struct anoninfo am_swap;
+
+/*
+ * this is borrowed from top's m_sunos5 module
+ * used by permission from William LeFebvre
+ */
+static int pageshift;
+static long (*p_pagetok) ();
+#define pagetok(size) ((*p_pagetok)(size))
+
+long pagetok_none( long size ) {
+ return( size );
+}
+
+long pagetok_left( long size ) {
+ return( size << pageshift );
+}
+
+long pagetok_right( long size ) {
+ return( size >> pageshift );
+}
+
+void initMemory( struct SensorModul* sm ) {
+
+ long i = sysconf( _SC_PAGESIZE );
+
+ pageshift = 0;
+ while( (i >>= 1) > 0 )
+ pageshift++;
+
+ /* calculate an amount to shift to K values */
+ /* remember that log base 2 of 1024 is 10 (i.e.: 2^10 = 1024) */
+ pageshift -= 10;
+
+ /* now determine which pageshift function is appropriate for the
+ result (have to because x << y is undefined for y < 0) */
+ if( pageshift > 0 ) {
+ /* this is the most likely */
+ p_pagetok = pagetok_left;
+ } else if( pageshift == 0 ) {
+ p_pagetok = pagetok_none;
+ } else {
+ p_pagetok = pagetok_right;
+ pageshift = -pageshift;
+ }
+
+#ifdef HAVE_KSTAT
+ registerMonitor( "mem/physical/free", "integer",
+ printMemFree, printMemFreeInfo, sm );
+ registerMonitor( "mem/physical/used", "integer",
+ printMemUsed, printMemUsedInfo, sm );
+#endif
+ registerMonitor( "mem/swap/free", "integer",
+ printSwapFree, printSwapFreeInfo, sm );
+ registerMonitor( "mem/swap/used", "integer",
+ printSwapUsed, printSwapUsedInfo, sm );
+}
+
+void exitMemory( void ) {
+}
+
+int updateMemory( void ) {
+
+ long swaptotal;
+ long swapfree;
+ long swapused;
+#ifdef HAVE_KSTAT
+ kstat_ctl_t *kctl;
+ kstat_t *ksp;
+ kstat_named_t *kdata;
+#endif /* HAVE_KSTAT */
+ swaptotal = swapused = swapfree = 0L;
+
+ /*
+ * Retrieve overall swap information from anonymous memory structure -
+ * which is the same way "swap -s" retrieves it's statistics.
+ *
+ * swapctl(SC_LIST, void *arg) does not return what we are looking for.
+ */
+
+ if (swapctl(SC_AINFO, &am_swap) == -1)
+ return(0);
+
+ swaptotal = am_swap.ani_max;
+ swapused = am_swap.ani_resv;
+ swapfree = swaptotal - swapused;
+
+ totalswap = pagetok(swaptotal);
+ freeswap = pagetok(swapfree);
+
+#ifdef HAVE_KSTAT
+ /*
+ * get a kstat handle and update the user's kstat chain
+ */
+ if( (kctl = kstat_open()) == NULL )
+ return( 0 );
+ while( kstat_chain_update( kctl ) != 0 )
+ ;
+
+ totalmem = pagetok( sysconf( _SC_PHYS_PAGES ));
+
+ /*
+ * traverse the kstat chain to find the appropriate statistics
+ */
+ if( (ksp = kstat_lookup( kctl, "unix", 0, "system_pages" )) == NULL )
+ return( 0 );
+ if( kstat_read( kctl, ksp, NULL ) == -1 )
+ return( 0 );
+
+ /*
+ * lookup the data
+ */
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "freemem" );
+ if( kdata != NULL )
+ freemem = pagetok( kdata->value.ui32 );
+
+ kstat_close( kctl );
+#endif /* ! HAVE_KSTAT */
+
+ Dirty = 0;
+
+ return( 0 );
+}
+
+void printMemFreeInfo( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "Free Memory\t0\t%ld\tKB\n", totalmem );
+}
+
+void printMemFree( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "%ld\n", freemem );
+}
+
+void printMemUsedInfo( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "Used Memory\t0\t%ld\tKB\n", totalmem );
+}
+
+void printMemUsed( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "%ld\n", totalmem - freemem );
+}
+
+void printSwapFreeInfo( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "Free Swap\t0\t%ld\tKB\n", totalswap );
+}
+
+void printSwapFree( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "%ld\n", freeswap );
+}
+
+void printSwapUsedInfo( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "Used Swap\t0\t%ld\tKB\n", totalswap );
+}
+
+void printSwapUsed( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "%ld\n", totalswap - freeswap );
+}
diff --git a/ksysguard/ksysguardd/Solaris/Memory.h b/ksysguard/ksysguardd/Solaris/Memory.h
new file mode 100644
index 000000000..7df6eb033
--- /dev/null
+++ b/ksysguard/ksysguardd/Solaris/Memory.h
@@ -0,0 +1,46 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _Memory_h_
+#define _Memory_h_
+
+typedef unsigned long t_memsize;
+
+#define PAGETOK(a) ((( (t_memsize) sysconf( _SC_PAGESIZE )) / (t_memsize) 1024) * (t_memsize) (a))
+
+void initMemory(struct SensorModul* sm);
+void exitMemory(void);
+
+int updateMemory(void);
+
+void printMemFree( const char *cmd );
+void printMemFreeInfo( const char *cmd );
+void printMemUsed( const char *cmd );
+void printMemUsedInfo( const char *cmd );
+
+void printSwapFree( const char *cmd );
+void printSwapFreeInfo( const char *cmd );
+void printSwapUsed( const char *cmd );
+void printSwapUsedInfo( const char *cmd );
+
+#endif /* _Memory_h */
diff --git a/ksysguard/ksysguardd/Solaris/NetDev.c b/ksysguard/ksysguardd/Solaris/NetDev.c
new file mode 100644
index 000000000..89db266cb
--- /dev/null
+++ b/ksysguard/ksysguardd/Solaris/NetDev.c
@@ -0,0 +1,679 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stropts.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <net/if.h>
+
+#include "config.h"
+
+#ifdef HAVE_KSTAT
+#include <kstat.h>
+#endif
+
+#include "ksysguardd.h"
+#include "Command.h"
+#include "NetDev.h"
+
+/*
+ * available network interface statistics through kstat(3):
+ *
+ * kstat name value
+ * ----------------------------------------------------------------------
+ * for the loopback interface(s) we can get
+ * ipackets # packets received
+ * opackets # packets sent
+ * in addition to those, for "real" interfaces:
+ * oerrors # xmit errors
+ * ierrors # recv errors
+ * macxmt_errors # xmit errors reported by hardware?
+ * macrcv_errors # recv errors reported by hardware?
+ * opackets64 same as opackets (64bit)
+ * ipackets64 same as ipackets (64bit)
+ * obytes # bytes sent
+ * rbytes # bytes received
+ * obytes64 same as obytes (64bit)
+ * rbytes64 same as ibytes (64bit)
+ * collisions # collisions
+ * multixmt # multicasts sent?
+ * multircv # multicasts received?
+ * brdcstxmt # broadcasts transmitted
+ * brdcstrcv # broadcasts received
+ * unknowns
+ * blocked
+ * ex_collisions
+ * defer_xmts
+ * align_errors
+ * fcs_errors
+ * oflo # overflow errors
+ * uflo # underflow errors
+ * runt_errors
+ * missed
+ * tx_late_collisions
+ * carrier_errors
+ * noxmtbuf
+ * norcvbuf
+ * xmt_badinterp
+ * rcv_badinterp
+ * intr # interrupts?
+ * xmtretry # xmit retries?
+ * ifspeed interface speed: 10000000 for 10BaseT
+ * duplex "half" or "full"
+ * media e.g. "PHY/MII"
+ * promisc promiscuous mode (e.g. "off")
+ * first_collisions
+ * multi_collisions
+ * sqe_errors
+ * toolong_errors
+ */
+
+typedef struct {
+ char *Name;
+ short flags;
+ unsigned long ipackets;
+ unsigned long OLDipackets;
+ unsigned long opackets;
+ unsigned long OLDopackets;
+ unsigned long ierrors;
+ unsigned long OLDierrors;
+ unsigned long oerrors;
+ unsigned long OLDoerrors;
+ unsigned long collisions;
+ unsigned long OLDcollisions;
+ unsigned long multixmt;
+ unsigned long OLDmultixmt;
+ unsigned long multircv;
+ unsigned long OLDmultircv;
+ unsigned long brdcstxmt;
+ unsigned long OLDbrdcstxmt;
+ unsigned long brdcstrcv;
+ unsigned long OLDbrdcstrcv;
+} NetDevInfo;
+
+
+#define NBUFFERS 64
+#define MAXNETDEVS 64
+static NetDevInfo IfInfo[MAXNETDEVS];
+
+static int NetDevCount;
+
+/*
+ * insertnetdev() -- insert device name & flags into our list
+ */
+int insertnetdev( const char *name, const short flags ) {
+
+ int i = 0;
+
+ /*
+ * interface "aliases" don't seem to have
+ * separate kstat statistics, so we skip them
+ */
+ if( strchr( name, (int) ':' ) != NULL )
+ return( 0 );
+
+ while( (i < NetDevCount) && (strcmp( IfInfo[i].Name, name ) != 0) ) {
+ if( strcmp( IfInfo[i].Name, name ) == 0 )
+ return( 0 );
+ i++;
+ }
+
+ /*
+ * init new slot
+ */
+ IfInfo[i].Name = strdup( name );
+ IfInfo[i].flags = flags;
+ IfInfo[i].ipackets = 0L;
+ IfInfo[i].OLDipackets = 0L;
+ IfInfo[i].opackets = 0L;
+ IfInfo[i].OLDopackets = 0L;
+ IfInfo[i].ierrors = 0L;
+ IfInfo[i].OLDierrors = 0L;
+ IfInfo[i].oerrors = 0L;
+ IfInfo[i].OLDoerrors = 0L;
+ IfInfo[i].collisions = 0L;
+ IfInfo[i].OLDcollisions = 0L;
+ IfInfo[i].multixmt = 0L;
+ IfInfo[i].OLDmultixmt = 0L;
+ IfInfo[i].multircv = 0L;
+ IfInfo[i].OLDmultircv = 0L;
+ IfInfo[i].brdcstxmt = 0L;
+ IfInfo[i].OLDbrdcstxmt = 0L;
+ IfInfo[i].brdcstrcv = 0L;
+ IfInfo[i].OLDbrdcstrcv = 0L;
+ NetDevCount = ++i;
+
+ /* XXX: need sanity checks! */
+ return( 0 );
+}
+
+/*
+ * getnetdevlist() -- get a list of all "up" interfaces
+ */
+int getnetdevlist( void ) {
+
+ int fd;
+ int buffsize;
+ int prevsize;
+ int prevCount;
+ struct ifconf ifc;
+ struct ifreq *ifr;
+
+ if( (fd = socket( PF_INET, SOCK_DGRAM, 0 )) < 0 ) {
+ return( -1 );
+ }
+
+ /*
+ * get the interface list via iotl( SIOCGIFCONF )
+ * the following algorithm based on ideas from W.R. Stevens'
+ * "UNIX Network Programming", Vol. 1:
+ * Since the ioctl may return 0, indicating success, even if the
+ * ifreq buffer was too small, we have to make sure, it didn't
+ * get truncated by comparing our initial size guess with the
+ * actual returned size.
+ */
+ prevsize = 0;
+ buffsize = NBUFFERS * sizeof( struct ifreq );
+ while( 1 ) {
+ if( (ifc.ifc_buf = malloc( buffsize )) == NULL )
+ return( -1 );
+
+ ifc.ifc_len = buffsize;
+ if( ioctl( fd, SIOCGIFCONF, &ifc ) < 0 ) {
+ if( errno != EINVAL || prevsize != 0 ) {
+ free( ifc.ifc_buf );
+ return( -1 );
+ }
+ } else {
+ if( ifc.ifc_len == prevsize )
+ /* success */
+ break;
+ prevsize = ifc.ifc_len;
+ }
+ /*
+ * initial buffer guessed too small, allocate a bigger one
+ */
+ free( ifc.ifc_buf );
+ buffsize = (NBUFFERS + 10) * sizeof( struct ifreq );
+ }
+
+ /*
+ * get the names for all interfaces which are configured "up"
+ * we're not interested in the ifc data (address), so we reuse the
+ * same structure (with ifc.len set) for the next ioctl()
+ */
+ prevCount = NetDevCount;
+ for( ifr = (struct ifreq *) ifc.ifc_buf;
+ ifr < (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+ ifr++ ) {
+ if( ioctl( fd, SIOCGIFFLAGS, ifr ) < 0 ) {
+ free( ifc.ifc_buf );
+ return( -1 );
+ }
+ if( ifr->ifr_flags & IFF_UP )
+ insertnetdev( ifr->ifr_name, ifr->ifr_flags );
+ }
+ free( ifc.ifc_buf );
+ close( fd );
+
+ if( (prevCount > 0) && (prevCount != NetDevCount) ) {
+ print_error( "RECONFIGURE\n" );
+ prevCount = NetDevCount;
+ }
+
+ return( NetDevCount );
+}
+
+void initNetDev( struct SensorModul* sm ) {
+#ifdef HAVE_KSTAT
+ char mon[128];
+ int i;
+
+ getnetdevlist();
+ for( i = 0; i < NetDevCount; i++ ) {
+ sprintf( mon, "network/%s/ipackets", IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printIPackets, printIPacketsInfo, sm );
+ sprintf( mon, "network/%s/opackets", IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printOPackets, printOPacketsInfo, sm );
+ /*
+ * if this isn't a loopback interface,
+ * register additional monitors
+ */
+ if( ! (IfInfo[i].flags & IFF_LOOPBACK) ) {
+ /*
+ * recv errors
+ */
+ sprintf( mon, "network/%s/ierrors",
+ IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printIErrors, printIErrorsInfo, sm );
+ /*
+ * xmit errors
+ */
+ sprintf( mon, "network/%s/oerrors",
+ IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printOErrors, printOErrorsInfo, sm );
+ /*
+ * collisions
+ */
+ sprintf( mon, "network/%s/collisions",
+ IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printCollisions, printCollisionsInfo, sm );
+ /*
+ * multicast xmits
+ */
+ sprintf( mon, "network/%s/multixmt",
+ IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printMultiXmits, printMultiXmitsInfo, sm );
+ /*
+ * multicast recvs
+ */
+ sprintf( mon, "network/%s/multircv",
+ IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printMultiRecvs, printMultiRecvsInfo, sm );
+ /*
+ * broadcast xmits
+ */
+ sprintf( mon, "network/%s/brdcstxmt",
+ IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printBcastXmits, printBcastXmitsInfo, sm );
+ /*
+ * broadcast recvs
+ */
+ sprintf( mon, "network/%s/brdcstrcv",
+ IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printBcastRecvs, printBcastRecvsInfo, sm );
+ }
+ }
+#endif
+}
+
+void exitNetDev( void ) {
+}
+
+int updateNetDev( void ) {
+
+#ifdef HAVE_KSTAT
+ kstat_ctl_t *kctl;
+ kstat_t *ksp;
+ kstat_named_t *kdata;
+ int i;
+
+ /*
+ * get a kstat handle and update the user's kstat chain
+ */
+ if( (kctl = kstat_open()) == NULL )
+ return( 0 );
+ while( kstat_chain_update( kctl ) != 0 )
+ ;
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ char *name;
+ char *ptr;
+
+ /*
+ * chop off the trailing interface no
+ */
+ name = strdup( IfInfo[i].Name );
+ ptr = name + strlen( name ) - 1;
+ while( (ptr > name) && isdigit( (int) *ptr ) ) {
+ *ptr = '\0';
+ ptr--;
+ }
+
+ /*
+ * traverse the kstat chain
+ * to find the appropriate statistics
+ */
+ if( (ksp = kstat_lookup( kctl,
+ name, 0, IfInfo[i].Name )) == NULL ) {
+ free( name );
+ return( 0 );
+ }
+ if( kstat_read( kctl, ksp, NULL ) == -1 ) {
+ free( name );
+ return( 0 );
+ }
+ free( name );
+
+ /*
+ * lookup & store the data
+ */
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "ipackets" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDipackets = IfInfo[i].ipackets;
+ IfInfo[i].ipackets = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "opackets" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDopackets = IfInfo[i].opackets;
+ IfInfo[i].opackets = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "ierrors" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDierrors = IfInfo[i].ierrors;
+ IfInfo[i].ierrors = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "oerrors" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDoerrors = IfInfo[i].oerrors;
+ IfInfo[i].oerrors = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "collisions" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDcollisions = IfInfo[i].collisions;
+ IfInfo[i].collisions = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "multixmt" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDmultixmt = IfInfo[i].multixmt;
+ IfInfo[i].multixmt = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "multircv" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDmultircv = IfInfo[i].multircv;
+ IfInfo[i].multircv = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "brdcstxmt" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDbrdcstxmt = IfInfo[i].brdcstxmt;
+ IfInfo[i].brdcstxmt = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "brdcstrcv" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDbrdcstrcv = IfInfo[i].brdcstrcv;
+ IfInfo[i].brdcstrcv = kdata->value.ul;
+ }
+ }
+
+ kstat_close( kctl );
+#endif /* ! HAVE_KSTAT */
+
+ return( 0 );
+}
+
+void printIPacketsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Received Packets\t0\t0\tPackets\n" );
+}
+
+void printIPackets( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDipackets > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].ipackets - IfInfo[i].OLDipackets);
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printOPacketsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Transmitted Packets\t0\t0\tPackets\n" );
+}
+
+void printOPackets( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDopackets > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].opackets - IfInfo[i].OLDopackets );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printIErrorsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Input Errors\t0\t0\tPackets\n" );
+}
+
+void printIErrors( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDierrors > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].ierrors - IfInfo[i].OLDierrors );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printOErrorsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Output Errors\t0\t0\tPackets\n" );
+}
+
+void printOErrors( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDoerrors > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].oerrors - IfInfo[i].OLDoerrors );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printCollisionsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Collisions\t0\t0\tPackets\n" );
+}
+
+void printCollisions( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDcollisions > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].collisions - IfInfo[i].OLDcollisions );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printMultiXmitsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Multicasts Sent\t0\t0\tPackets\n" );
+}
+
+void printMultiXmits( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDmultixmt > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].multixmt - IfInfo[i].OLDmultixmt );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printMultiRecvsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Multicasts Received\t0\t0\tPackets\n" );
+}
+
+void printMultiRecvs( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDmultircv > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].multircv - IfInfo[i].OLDmultircv );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printBcastXmitsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Broadcasts Sent\t0\t0\tPackets\n" );
+}
+
+void printBcastXmits( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDbrdcstxmt > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].brdcstxmt - IfInfo[i].OLDbrdcstxmt );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printBcastRecvsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Broadcasts Received\t0\t0\tPackets\n" );
+}
+
+void printBcastRecvs( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDbrdcstrcv > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].brdcstrcv - IfInfo[i].OLDbrdcstrcv );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
diff --git a/ksysguard/ksysguardd/Solaris/NetDev.h b/ksysguard/ksysguardd/Solaris/NetDev.h
new file mode 100644
index 000000000..b6ff54448
--- /dev/null
+++ b/ksysguard/ksysguardd/Solaris/NetDev.h
@@ -0,0 +1,59 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _NetDev_h_
+#define _NetDev_h_
+
+void initNetDev(struct SensorModul* sm);
+void exitNetDev(void);
+
+int updateNetDev(void);
+
+void printIPacketsInfo( const char *cmd );
+void printIPackets( const char *cmd );
+
+void printOPacketsInfo( const char *cmd );
+void printOPackets( const char *cmd );
+
+void printIErrorsInfo( const char *cmd );
+void printIErrors( const char *cmd );
+
+void printOErrorsInfo( const char *cmd );
+void printOErrors( const char *cmd );
+
+void printCollisionsInfo( const char *cmd );
+void printCollisions( const char *cmd );
+
+void printMultiXmitsInfo( const char *cmd );
+void printMultiXmits( const char *cmd );
+
+void printMultiRecvsInfo( const char *cmd );
+void printMultiRecvs( const char *cmd );
+
+void printBcastXmitsInfo( const char *cmd );
+void printBcastXmits( const char *cmd );
+
+void printBcastRecvsInfo( const char *cmd );
+void printBcastRecvs( const char *cmd );
+
+#endif /* _NetDev_h */
diff --git a/ksysguard/ksysguardd/Solaris/ProcessList.c b/ksysguard/ksysguardd/Solaris/ProcessList.c
new file mode 100644
index 000000000..771371b76
--- /dev/null
+++ b/ksysguard/ksysguardd/Solaris/ProcessList.c
@@ -0,0 +1,436 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+/* Stop <sys/procfs.h> from crapping out on 32-bit architectures. */
+
+#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
+# undef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 32
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <procfs.h>
+#include <sys/proc.h>
+#include <sys/resource.h>
+
+#include "ccont.h"
+#include "../../gui/SignalIDs.h"
+#include "ksysguardd.h"
+
+#include "Command.h"
+#include "ProcessList.h"
+
+#define BUFSIZE 1024
+
+typedef struct {
+ int alive; /* for "garbage collection" */
+ pid_t pid; /* process ID */
+ pid_t ppid; /* parent process ID */
+ uid_t uid; /* process owner (real UID) */
+ gid_t gid; /* process group (real GID) */
+ char *userName; /* process owner (name) */
+ int nThreads; /* # of threads in this process */
+ int Prio; /* scheduling priority */
+ size_t Size; /* total size of process image */
+ size_t RSSize; /* resident set size */
+ char *State; /* process state */
+ int Time; /* CPU time for the process */
+ double Load; /* CPU load in % */
+ char *Command; /* command name */
+ char *CmdLine; /* command line */
+} ProcessInfo;
+
+static CONTAINER ProcessList = 0;
+static unsigned ProcessCount = 0; /* # of processes */
+static DIR *procdir; /* handle for /proc */
+
+/*
+ * lwpStateName() -- return string representation of process state
+ */
+char *lwpStateName( lwpsinfo_t lwpinfo ) {
+
+ char result[8];
+ int processor;
+
+ switch( (int) lwpinfo.pr_state ) {
+ case SSLEEP:
+ sprintf( result, "%s", "sleep" );
+ break;
+ case SRUN:
+ sprintf( result, "%s", "run" );
+ break;
+ case SZOMB:
+ sprintf( result, "%s", "zombie" );
+ break;
+ case SSTOP:
+ sprintf( result, "%s", "stop" );
+ break;
+ case SIDL:
+ sprintf( result, "%s", "start" );
+ break;
+ case SONPROC:
+ processor = (int) lwpinfo.pr_onpro;
+ sprintf( result, "%s/%d", "cpu", processor );
+ break;
+ default:
+ sprintf( result, "%s", "???" );
+ break;
+ }
+
+ return( strdup( result ));
+}
+
+static void validateStr( char *string ) {
+
+ char *ptr = string;
+
+ /*
+ * remove all chars that might screw up communication
+ */
+ while( *ptr != '\0' ) {
+ if( *ptr == '\t' || *ptr == '\n' || *ptr == '\r' )
+ *ptr = ' ';
+ ptr++;
+ }
+ /*
+ * make sure there's at least one char
+ */
+ if( string[0] == '\0' )
+ strcpy( string, " " );
+}
+
+static int processCmp( void *p1, void *p2 ) {
+
+ return( ((ProcessInfo *) p1)->pid - ((ProcessInfo *) p2)->pid );
+}
+
+static ProcessInfo *findProcessInList( pid_t pid ) {
+
+ ProcessInfo key;
+ long index;
+
+ key.pid = pid;
+ if( (index = search_ctnr( ProcessList, processCmp, &key )) < 0 )
+ return( NULL );
+
+ return( get_ctnr( ProcessList, index ));
+}
+
+static int updateProcess( pid_t pid ) {
+
+ ProcessInfo *ps;
+ int fd;
+ char buf[BUFSIZE];
+ psinfo_t psinfo;
+ struct passwd *pw;
+
+ if( (ps = findProcessInList( pid )) == NULL ) {
+ if( (ps = (ProcessInfo *) malloc( sizeof( ProcessInfo )))
+ == NULL ) {
+ print_error( "cannot malloc()\n" );
+ return( -1 );
+ }
+ ps->pid = pid;
+ ps->userName = NULL;
+ ps->State = NULL;
+ ps->Command = NULL;
+ ps->CmdLine = NULL;
+ ps->alive = 0;
+
+ push_ctnr( ProcessList, ps );
+ bsort_ctnr( ProcessList, processCmp );
+ }
+
+ snprintf( buf, BUFSIZE - 1, "%s/%ld/psinfo", PROCDIR, pid );
+ if( (fd = open( buf, O_RDONLY )) < 0 ) {
+ return( -1 );
+ }
+
+ if( read( fd, &psinfo, sizeof( psinfo_t )) != sizeof( psinfo_t )) {
+ close( fd );
+ return( -1 );
+ }
+ close( fd );
+
+ ps->ppid = psinfo.pr_ppid;
+ ps->uid = psinfo.pr_uid;
+ ps->gid = psinfo.pr_gid;
+
+ pw = getpwuid( psinfo.pr_uid );
+ if( ps->userName != NULL )
+ free( ps->userName );
+ ps->userName = strdup( pw->pw_name );
+
+ if( ps->State != NULL )
+ free( ps->State );
+ ps->State = lwpStateName( psinfo.pr_lwp );
+
+ /*
+ * the following data is invalid for zombies, so...
+ */
+ if( (ps->nThreads = psinfo.pr_nlwp ) != 0 ) {
+ ps->Prio = psinfo.pr_lwp.pr_pri;
+ ps->Time = psinfo.pr_lwp.pr_time.tv_sec * 100
+ + psinfo.pr_lwp.pr_time.tv_nsec * 10000000;
+ ps->Load = (double) psinfo.pr_lwp.pr_pctcpu
+ / (double) 0x8000 * 100.0;
+ } else {
+ ps->Prio = 0;
+ ps->Time = 0;
+ ps->Load = 0.0;
+ }
+
+ ps->Size = psinfo.pr_size;
+ ps->RSSize = psinfo.pr_rssize;
+
+ if( ps->Command != NULL )
+ free( ps->Command );
+ ps->Command = strdup( psinfo.pr_fname );
+ if( ps->CmdLine != NULL )
+ free( ps->CmdLine );
+ ps->CmdLine = strdup( psinfo.pr_psargs );
+
+ validateStr( ps->Command );
+ validateStr( ps->CmdLine );
+
+ ps->alive = 1;
+
+ return( 0 );
+}
+
+static void cleanupProcessList( void ) {
+
+ ProcessInfo *ps;
+
+ ProcessCount = 0;
+ for( ps = first_ctnr( ProcessList ); ps; ps = next_ctnr( ProcessList )) {
+ if( ps->alive ) {
+ ps->alive = 0;
+ ProcessCount++;
+ } else {
+ free( remove_ctnr( ProcessList ));
+ }
+ }
+}
+
+void initProcessList( struct SensorModul* sm ) {
+
+ if( (procdir = opendir( PROCDIR )) == NULL ) {
+ print_error( "cannot open \"%s\" for reading\n", PROCDIR );
+ return;
+ }
+
+ ProcessList = new_ctnr();
+
+ /*
+ * register the supported monitors & commands
+ */
+ registerMonitor( "pscount", "integer",
+ printProcessCount, printProcessCountInfo, sm );
+ registerMonitor( "ps", "table",
+ printProcessList, printProcessListInfo, sm );
+
+ registerCommand( "kill", killProcess );
+ registerCommand( "setpriority", setPriority );
+}
+
+void exitProcessList( void ) {
+
+ destr_ctnr( ProcessList, free );
+}
+
+int updateProcessList( void ) {
+
+ struct dirent *de;
+
+ rewinddir( procdir );
+ while( (de = readdir( procdir )) != NULL ) {
+ /*
+ * skip '.' and '..'
+ */
+ if( de->d_name[0] == '.' )
+ continue;
+
+ /*
+ * fetch the process info and insert it into the info table
+ */
+ updateProcess( (pid_t) atol( de->d_name ));
+ }
+ cleanupProcessList();
+
+ return( 0 );
+}
+
+void printProcessListInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Name\tPID\tPPID\tGID\tStatus\tUser\tThreads"
+ "\tSize\tResident\t%% CPU\tPriority\tCommand\n" );
+ fprintf(CurrentClient, "s\td\td\td\ts\ts\td\tD\tD\tf\td\ts\n" );
+}
+
+void printProcessList( const char *cmd ) {
+
+ ProcessInfo *ps;
+
+ for( ps = first_ctnr( ProcessList ); ps; ps = next_ctnr( ProcessList )) {
+ fprintf(CurrentClient,
+ "%s\t%ld\t%ld\t%ld\t%s\t%s\t%d\t%d\t%d\t%.2f\t%d\t%s\n",
+ ps->Command,
+ (long) ps->pid,
+ (long) ps->ppid,
+ (long) ps->gid,
+ ps->State,
+ ps->userName,
+ ps->nThreads,
+ ps->Size,
+ ps->RSSize,
+ ps->Load,
+ ps->Prio,
+ ps->CmdLine);
+ }
+
+ fprintf(CurrentClient, "\n");
+}
+
+void printProcessCount( const char *cmd ) {
+ fprintf(CurrentClient, "%d\n", ProcessCount );
+}
+
+void printProcessCountInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Number of Processes\t0\t0\t\n" );
+}
+
+void killProcess( const char *cmd ) {
+
+ int sig, pid;
+
+ sscanf( cmd, "%*s %d %d", &pid, &sig );
+
+ switch( sig ) {
+ case MENU_ID_SIGABRT:
+ sig = SIGABRT;
+ break;
+ case MENU_ID_SIGALRM:
+ sig = SIGALRM;
+ break;
+ case MENU_ID_SIGCHLD:
+ sig = SIGCHLD;
+ break;
+ case MENU_ID_SIGCONT:
+ sig = SIGCONT;
+ break;
+ case MENU_ID_SIGFPE:
+ sig = SIGFPE;
+ break;
+ case MENU_ID_SIGHUP:
+ sig = SIGHUP;
+ break;
+ case MENU_ID_SIGILL:
+ sig = SIGILL;
+ break;
+ case MENU_ID_SIGINT:
+ sig = SIGINT;
+ break;
+ case MENU_ID_SIGKILL:
+ sig = SIGKILL;
+ break;
+ case MENU_ID_SIGPIPE:
+ sig = SIGPIPE;
+ break;
+ case MENU_ID_SIGQUIT:
+ sig = SIGQUIT;
+ break;
+ case MENU_ID_SIGSEGV:
+ sig = SIGSEGV;
+ break;
+ case MENU_ID_SIGSTOP:
+ sig = SIGSTOP;
+ break;
+ case MENU_ID_SIGTERM:
+ sig = SIGTERM;
+ break;
+ case MENU_ID_SIGTSTP:
+ sig = SIGTSTP;
+ break;
+ case MENU_ID_SIGTTIN:
+ sig = SIGTTIN;
+ break;
+ case MENU_ID_SIGTTOU:
+ sig = SIGTTOU;
+ break;
+ case MENU_ID_SIGUSR1:
+ sig = SIGUSR1;
+ break;
+ case MENU_ID_SIGUSR2:
+ sig = SIGUSR2;
+ break;
+ }
+ if( kill( (pid_t) pid, sig )) {
+ switch( errno ) {
+ case EINVAL:
+ fprintf(CurrentClient, "4\n" );
+ break;
+ case ESRCH:
+ fprintf(CurrentClient, "3\n" );
+ break;
+ case EPERM:
+ fprintf(CurrentClient, "2\n" );
+ break;
+ default:
+ fprintf(CurrentClient, "1\n" ); /* unknown error */
+ break;
+ }
+ } else
+ fprintf(CurrentClient, "0\n");
+}
+
+void setPriority( const char *cmd ) {
+ int pid, prio;
+
+ sscanf( cmd, "%*s %d %d", &pid, &prio );
+ if( setpriority( PRIO_PROCESS, pid, prio )) {
+ switch( errno ) {
+ case EINVAL:
+ fprintf(CurrentClient, "4\n" );
+ break;
+ case ESRCH:
+ fprintf(CurrentClient, "3\n" );
+ break;
+ case EPERM:
+ case EACCES:
+ fprintf(CurrentClient, "2\n" );
+ break;
+ default:
+ fprintf(CurrentClient, "1\n" ); /* unknown error */
+ break;
+ }
+ } else
+ fprintf(CurrentClient, "0\n");
+}
diff --git a/ksysguard/ksysguardd/Solaris/ProcessList.h b/ksysguard/ksysguardd/Solaris/ProcessList.h
new file mode 100644
index 000000000..90333f5b8
--- /dev/null
+++ b/ksysguard/ksysguardd/Solaris/ProcessList.h
@@ -0,0 +1,43 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _ProcessList_H_
+#define _ProcessList_H_
+
+#define PROCDIR "/proc"
+
+void initProcessList(struct SensorModul* sm);
+void exitProcessList(void);
+
+int updateProcessList(void);
+
+void printProcessList(const char*);
+void printProcessListInfo(const char*);
+
+void printProcessCount(const char* cmd);
+void printProcessCountInfo(const char* cmd);
+
+void killProcess(const char* cmd);
+void setPriority(const char* cmd);
+
+#endif
diff --git a/ksysguard/ksysguardd/Tru64/LoadAvg.c b/ksysguard/ksysguardd/Tru64/LoadAvg.c
new file mode 100644
index 000000000..ddbe68e2d
--- /dev/null
+++ b/ksysguard/ksysguardd/Tru64/LoadAvg.c
@@ -0,0 +1,121 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/swap.h>
+
+#include "config.h"
+
+#ifdef HAVE_KSTAT
+#include <kstat.h>
+#endif
+
+#include "ksysguardd.h"
+#include "Command.h"
+#include "LoadAvg.h"
+
+double loadavg1 = 0.0;
+double loadavg5 = 0.0;
+double loadavg15 = 0.0;
+
+void initLoadAvg( struct SensorModul* sm ) {
+#ifdef HAVE_KSTAT
+ registerMonitor( "cpu/loadavg1", "float",
+ printLoadAvg1, printLoadAvg1Info, sm );
+ registerMonitor( "cpu/loadavg5", "float",
+ printLoadAvg5, printLoadAvg5Info, sm );
+ registerMonitor( "cpu/loadavg15", "float",
+ printLoadAvg15, printLoadAvg15Info, sm );
+#endif
+}
+
+void exitLoadAvg( void ) {
+}
+
+int updateLoadAvg( void ) {
+
+#ifdef HAVE_KSTAT
+ kstat_ctl_t *kctl;
+ kstat_t *ksp;
+ kstat_named_t *kdata;
+
+ /*
+ * get a kstat handle and update the user's kstat chain
+ */
+ if( (kctl = kstat_open()) == NULL )
+ return( 0 );
+ while( kstat_chain_update( kctl ) != 0 )
+ ;
+
+ /*
+ * traverse the kstat chain to find the appropriate statistics
+ */
+ if( (ksp = kstat_lookup( kctl, "unix", 0, "system_misc" )) == NULL )
+ return( 0 );
+ if( kstat_read( kctl, ksp, NULL ) == -1 )
+ return( 0 );
+
+ /*
+ * lookup the data
+ */
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "avenrun_1min" );
+ if( kdata != NULL )
+ loadavg1 = LOAD( kdata->value.ui32 );
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "avenrun_5min" );
+ if( kdata != NULL )
+ loadavg5 = LOAD( kdata->value.ui32 );
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "avenrun_15min" );
+ if( kdata != NULL )
+ loadavg15 = LOAD( kdata->value.ui32 );
+
+ kstat_close( kctl );
+#endif /* ! HAVE_KSTAT */
+
+ return( 0 );
+}
+
+void printLoadAvg1Info( const char *cmd ) {
+ fprintf(CurrentClient, "avnrun 1min\t0\t0\n" );
+}
+
+void printLoadAvg1( const char *cmd ) {
+ fprintf(CurrentClient, "%f\n", loadavg1 );
+}
+
+void printLoadAvg5Info( const char *cmd ) {
+ fprintf(CurrentClient, "avnrun 5min\t0\t0\n" );
+}
+
+void printLoadAvg5( const char *cmd ) {
+ fprintf(CurrentClient, "%f\n", loadavg5 );
+}
+
+void printLoadAvg15Info( const char *cmd ) {
+ fprintf(CurrentClient, "avnrun 15min\t0\t0\n" );
+}
+
+void printLoadAvg15( const char *cmd ) {
+ fprintf(CurrentClient, "%f\n", loadavg15 );
+}
diff --git a/ksysguard/ksysguardd/Tru64/LoadAvg.h b/ksysguard/ksysguardd/Tru64/LoadAvg.h
new file mode 100644
index 000000000..eea8ad82e
--- /dev/null
+++ b/ksysguard/ksysguardd/Tru64/LoadAvg.h
@@ -0,0 +1,41 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _LoadAvg_h_
+#define _LoadAvg_h_
+
+#define LOAD(a) ((double)(a) / (1 << 8 ))
+
+void initLoadAvg(struct SensorModul* sm);
+void exitLoadAvg(void);
+
+int updateLoadAvg(void);
+
+void printLoadAvg1( const char *cmd );
+void printLoadAvg1Info( const char *cmd );
+void printLoadAvg5( const char *cmd );
+void printLoadAvg5Info( const char *cmd );
+void printLoadAvg15( const char *cmd );
+void printLoadAvg15Info( const char *cmd );
+
+#endif /* _LoadAvg_h_ */
diff --git a/ksysguard/ksysguardd/Tru64/Makefile.am b/ksysguard/ksysguardd/Tru64/Makefile.am
new file mode 100644
index 000000000..95be0247b
--- /dev/null
+++ b/ksysguard/ksysguardd/Tru64/Makefile.am
@@ -0,0 +1,8 @@
+#
+#
+AM_CFLAGS = -Wall
+
+INCLUDES = -I$(srcdir)/../../CContLib -I..
+
+lib_LIBRARIES = libksysguardd.a
+libksysguardd_a_SOURCES = Memory.c LoadAvg.c NetDev.c
diff --git a/ksysguard/ksysguardd/Tru64/Memory.c b/ksysguard/ksysguardd/Tru64/Memory.c
new file mode 100644
index 000000000..3a9332064
--- /dev/null
+++ b/ksysguard/ksysguardd/Tru64/Memory.c
@@ -0,0 +1,237 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/swap.h>
+
+#include "config.h"
+
+#ifdef HAVE_KSTAT
+#include <kstat.h>
+#endif
+
+#include "ksysguardd.h"
+#include "Command.h"
+#include "Memory.h"
+
+static int Dirty = 1;
+static t_memsize totalmem = (t_memsize) 0;
+static t_memsize freemem = (t_memsize) 0;
+static long totalswap = 0L;
+static long freeswap = 0L;
+
+/*
+ * this is borrowed from top's m_sunos5 module
+ * used by permission from William LeFebvre
+ */
+static int pageshift;
+static long (*p_pagetok) ();
+#define pagetok(size) ((*p_pagetok)(size))
+
+long pagetok_none( long size ) {
+ return( size );
+}
+
+long pagetok_left( long size ) {
+ return( size << pageshift );
+}
+
+long pagetok_right( long size ) {
+ return( size >> pageshift );
+}
+
+void initMemory( struct SensorModul* sm ) {
+
+ long i = sysconf( _SC_PAGESIZE );
+
+ pageshift = 0;
+ while( (i >>= 1) > 0 )
+ pageshift++;
+
+ /* calculate an amount to shift to K values */
+ /* remember that log base 2 of 1024 is 10 (i.e.: 2^10 = 1024) */
+ pageshift -= 10;
+
+ /* now determine which pageshift function is appropriate for the
+ result (have to because x << y is undefined for y < 0) */
+ if( pageshift > 0 ) {
+ /* this is the most likely */
+ p_pagetok = pagetok_left;
+ } else if( pageshift == 0 ) {
+ p_pagetok = pagetok_none;
+ } else {
+ p_pagetok = pagetok_right;
+ pageshift = -pageshift;
+ }
+
+#ifdef HAVE_KSTAT
+ registerMonitor( "mem/physical/free", "integer",
+ printMemFree, printMemFreeInfo, sm );
+ registerMonitor( "mem/physical/used", "integer",
+ printMemUsed, printMemUsedInfo, sm );
+#endif
+ registerMonitor( "mem/swap/free", "integer",
+ printSwapFree, printSwapFreeInfo, sm );
+ registerMonitor( "mem/swap/used", "integer",
+ printSwapUsed, printSwapUsedInfo, sm );
+}
+
+void exitMemory( void ) {
+}
+
+int updateMemory( void ) {
+
+ struct swaptable *swt;
+ struct swapent *ste;
+ int i;
+ int ndevs;
+ long swaptotal;
+ long swapfree;
+ char dummy[128];
+#ifdef HAVE_KSTAT
+ kstat_ctl_t *kctl;
+ kstat_t *ksp;
+ kstat_named_t *kdata;
+#endif /* HAVE_KSTAT */
+
+ if( (ndevs = swapctl( SC_GETNSWP, NULL )) < 1 )
+ return( 0 );
+ if( (swt = (struct swaptable *) malloc(
+ sizeof( int )
+ + ndevs * sizeof( struct swapent ))) == NULL )
+ return( 0 );
+
+ /*
+ * fill in the required fields and retrieve the info thru swapctl()
+ */
+ swt->swt_n = ndevs;
+ ste = &(swt->swt_ent[0]);
+ for( i = 0; i < ndevs; i++ ) {
+ /*
+ * since we'renot interested in the path(s),
+ * we'll re-use the same buffer
+ */
+ ste->ste_path = dummy;
+ ste++;
+ }
+ swapctl( SC_LIST, swt );
+
+ swaptotal = swapfree = 0L;
+
+ ste = &(swt->swt_ent[0]);
+ for( i = 0; i < ndevs; i++ ) {
+ if( (! (ste->ste_flags & ST_INDEL))
+ && (! (ste->ste_flags & ST_DOINGDEL)) ) {
+ swaptotal += ste->ste_pages;
+ swapfree += ste->ste_free;
+ }
+ ste++;
+ }
+ free( swt );
+
+ totalswap = pagetok( swaptotal );
+ freeswap = pagetok( swapfree );
+
+#ifdef HAVE_KSTAT
+ /*
+ * get a kstat handle and update the user's kstat chain
+ */
+ if( (kctl = kstat_open()) == NULL )
+ return( 0 );
+ while( kstat_chain_update( kctl ) != 0 )
+ ;
+
+ totalmem = pagetok( sysconf( _SC_PHYS_PAGES ));
+
+ /*
+ * traverse the kstat chain to find the appropriate statistics
+ */
+ if( (ksp = kstat_lookup( kctl, "unix", 0, "system_pages" )) == NULL )
+ return( 0 );
+ if( kstat_read( kctl, ksp, NULL ) == -1 )
+ return( 0 );
+
+ /*
+ * lookup the data
+ */
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "freemem" );
+ if( kdata != NULL )
+ freemem = pagetok( kdata->value.ui32 );
+
+ kstat_close( kctl );
+#endif /* ! HAVE_KSTAT */
+
+ Dirty = 0;
+
+ return( 0 );
+}
+
+void printMemFreeInfo( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "Free Memory\t0\t%ld\tKB\n", totalmem );
+}
+
+void printMemFree( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "%ld\n", freemem );
+}
+
+void printMemUsedInfo( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "Used Memory\t0\t%ld\tKB\n", totalmem );
+}
+
+void printMemUsed( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "%ld\n", totalmem - freemem );
+}
+
+void printSwapFreeInfo( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "Free Swap\t0\t%ld\tKB\n", totalswap );
+}
+
+void printSwapFree( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "%ld\n", freeswap );
+}
+
+void printSwapUsedInfo( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "Used Swap\t0\t%ld\tKB\n", totalswap );
+}
+
+void printSwapUsed( const char *cmd ) {
+ if( Dirty )
+ updateMemory();
+ fprintf(CurrentClient, "%ld\n", totalswap - freeswap );
+}
diff --git a/ksysguard/ksysguardd/Tru64/Memory.h b/ksysguard/ksysguardd/Tru64/Memory.h
new file mode 100644
index 000000000..7df6eb033
--- /dev/null
+++ b/ksysguard/ksysguardd/Tru64/Memory.h
@@ -0,0 +1,46 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _Memory_h_
+#define _Memory_h_
+
+typedef unsigned long t_memsize;
+
+#define PAGETOK(a) ((( (t_memsize) sysconf( _SC_PAGESIZE )) / (t_memsize) 1024) * (t_memsize) (a))
+
+void initMemory(struct SensorModul* sm);
+void exitMemory(void);
+
+int updateMemory(void);
+
+void printMemFree( const char *cmd );
+void printMemFreeInfo( const char *cmd );
+void printMemUsed( const char *cmd );
+void printMemUsedInfo( const char *cmd );
+
+void printSwapFree( const char *cmd );
+void printSwapFreeInfo( const char *cmd );
+void printSwapUsed( const char *cmd );
+void printSwapUsedInfo( const char *cmd );
+
+#endif /* _Memory_h */
diff --git a/ksysguard/ksysguardd/Tru64/NetDev.c b/ksysguard/ksysguardd/Tru64/NetDev.c
new file mode 100644
index 000000000..0699b929a
--- /dev/null
+++ b/ksysguard/ksysguardd/Tru64/NetDev.c
@@ -0,0 +1,678 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stropts.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include "config.h"
+
+#ifdef HAVE_KSTAT
+#include <kstat.h>
+#endif
+
+#include "ksysguardd.h"
+#include "Command.h"
+#include "NetDev.h"
+
+/*
+ * available network interface statistics through kstat(3):
+ *
+ * kstat name value
+ * ----------------------------------------------------------------------
+ * for the loopback interface(s) we can get
+ * ipackets # packets received
+ * opackets # packets sent
+ * in addition to those, for "real" interfaces:
+ * oerrors # xmit errors
+ * ierrors # recv errors
+ * macxmt_errors # xmit errors reported by hardware?
+ * macrcv_errors # recv errors reported by hardware?
+ * opackets64 same as opackets (64bit)
+ * ipackets64 same as ipackets (64bit)
+ * obytes # bytes sent
+ * rbytes # bytes received
+ * obytes64 same as obytes (64bit)
+ * rbytes64 same as ibytes (64bit)
+ * collisions # collisions
+ * multixmt # multicasts sent?
+ * multircv # multicasts received?
+ * brdcstxmt # broadcasts transmitted
+ * brdcstrcv # broadcasts received
+ * unknowns
+ * blocked
+ * ex_collisions
+ * defer_xmts
+ * align_errors
+ * fcs_errors
+ * oflo # overflow errors
+ * uflo # underflow errors
+ * runt_errors
+ * missed
+ * tx_late_collisions
+ * carrier_errors
+ * noxmtbuf
+ * norcvbuf
+ * xmt_badinterp
+ * rcv_badinterp
+ * intr # interrupts?
+ * xmtretry # xmit retries?
+ * ifspeed interface speed: 10000000 for 10BaseT
+ * duplex "half" or "full"
+ * media e.g. "PHY/MII"
+ * promisc promiscuous mode (e.g. "off")
+ * first_collisions
+ * multi_collisions
+ * sqe_errors
+ * toolong_errors
+ */
+
+typedef struct {
+ char *Name;
+ short flags;
+ unsigned long ipackets;
+ unsigned long OLDipackets;
+ unsigned long opackets;
+ unsigned long OLDopackets;
+ unsigned long ierrors;
+ unsigned long OLDierrors;
+ unsigned long oerrors;
+ unsigned long OLDoerrors;
+ unsigned long collisions;
+ unsigned long OLDcollisions;
+ unsigned long multixmt;
+ unsigned long OLDmultixmt;
+ unsigned long multircv;
+ unsigned long OLDmultircv;
+ unsigned long brdcstxmt;
+ unsigned long OLDbrdcstxmt;
+ unsigned long brdcstrcv;
+ unsigned long OLDbrdcstrcv;
+} NetDevInfo;
+
+
+#define NBUFFERS 64
+#define MAXNETDEVS 64
+static NetDevInfo IfInfo[MAXNETDEVS];
+
+static int NetDevCount;
+
+/*
+ * insertnetdev() -- insert device name & flags into our list
+ */
+int insertnetdev( const char *name, const short flags ) {
+
+ int i = 0;
+
+ /*
+ * interface "aliases" don't seem to have
+ * separate kstat statistics, so we skip them
+ */
+ if( strchr( name, (int) ':' ) != NULL )
+ return( 0 );
+
+ while( (i < NetDevCount) && (strcmp( IfInfo[i].Name, name ) != 0) ) {
+ if( strcmp( IfInfo[i].Name, name ) == 0 )
+ return( 0 );
+ i++;
+ }
+
+ /*
+ * init new slot
+ */
+ IfInfo[i].Name = strdup( name );
+ IfInfo[i].flags = flags;
+ IfInfo[i].ipackets = 0L;
+ IfInfo[i].OLDipackets = 0L;
+ IfInfo[i].opackets = 0L;
+ IfInfo[i].OLDopackets = 0L;
+ IfInfo[i].ierrors = 0L;
+ IfInfo[i].OLDierrors = 0L;
+ IfInfo[i].oerrors = 0L;
+ IfInfo[i].OLDoerrors = 0L;
+ IfInfo[i].collisions = 0L;
+ IfInfo[i].OLDcollisions = 0L;
+ IfInfo[i].multixmt = 0L;
+ IfInfo[i].OLDmultixmt = 0L;
+ IfInfo[i].multircv = 0L;
+ IfInfo[i].OLDmultircv = 0L;
+ IfInfo[i].brdcstxmt = 0L;
+ IfInfo[i].OLDbrdcstxmt = 0L;
+ IfInfo[i].brdcstrcv = 0L;
+ IfInfo[i].OLDbrdcstrcv = 0L;
+ NetDevCount = ++i;
+
+ /* XXX: need sanity checks! */
+ return( 0 );
+}
+
+/*
+ * getnetdevlist() -- get a list of all "up" interfaces
+ */
+int getnetdevlist( void ) {
+
+ int fd;
+ int buffsize;
+ int prevsize;
+ int prevCount;
+ struct ifconf ifc;
+ struct ifreq *ifr;
+
+ if( (fd = socket( PF_INET, SOCK_DGRAM, 0 )) < 0 ) {
+ return( -1 );
+ }
+
+ /*
+ * get the interface list via iotl( SIOCGIFCONF )
+ * the following algorithm based on ideas from W.R. Stevens'
+ * "UNIX Network Programming", Vol. 1:
+ * Since the ioctl may return 0, indicating success, even if the
+ * ifreq buffer was too small, we have to make sure, it didn't
+ * get truncated by comparing our initial size guess with the
+ * actual returned size.
+ */
+ prevsize = 0;
+ buffsize = NBUFFERS * sizeof( struct ifreq );
+ while( 1 ) {
+ if( (ifc.ifc_buf = malloc( buffsize )) == NULL )
+ return( -1 );
+
+ ifc.ifc_len = buffsize;
+ if( ioctl( fd, SIOCGIFCONF, &ifc ) < 0 ) {
+ if( errno != EINVAL || prevsize != 0 ) {
+ free( ifc.ifc_buf );
+ return( -1 );
+ }
+ } else {
+ if( ifc.ifc_len == prevsize )
+ /* success */
+ break;
+ prevsize = ifc.ifc_len;
+ }
+ /*
+ * initial buffer guessed too small, allocate a bigger one
+ */
+ free( ifc.ifc_buf );
+ buffsize = (NBUFFERS + 10) * sizeof( struct ifreq );
+ }
+
+ /*
+ * get the names for all interfaces which are configured "up"
+ * we're not interested in the ifc data (address), so we reuse the
+ * same structure (with ifc.len set) for the next ioctl()
+ */
+ prevCount = NetDevCount;
+ for( ifr = (struct ifreq *) ifc.ifc_buf;
+ ifr < (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+ ifr++ ) {
+ if( ioctl( fd, SIOCGIFFLAGS, ifr ) < 0 ) {
+ free( ifc.ifc_buf );
+ return( -1 );
+ }
+ if( ifr->ifr_flags & IFF_UP )
+ insertnetdev( ifr->ifr_name, ifr->ifr_flags );
+ }
+ free( ifc.ifc_buf );
+ close( fd );
+
+ if( (prevCount > 0) && (prevCount != NetDevCount) ) {
+ print_error( "RECONFIGURE\n" );
+ prevCount = NetDevCount;
+ }
+
+ return( NetDevCount );
+}
+
+void initNetDev( struct SensorModul* sm ) {
+#ifdef HAVE_KSTAT
+ char mon[128];
+ int i;
+
+ getnetdevlist();
+ for( i = 0; i < NetDevCount; i++ ) {
+ sprintf( mon, "network/%s/ipackets", IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printIPackets, printIPacketsInfo, sm );
+ sprintf( mon, "network/%s/opackets", IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printOPackets, printOPacketsInfo, sm );
+ /*
+ * if this isn't a loopback interface,
+ * register additional monitors
+ */
+ if( ! (IfInfo[i].flags & IFF_LOOPBACK) ) {
+ /*
+ * recv errors
+ */
+ sprintf( mon, "network/%s/ierrors",
+ IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printIErrors, printIErrorsInfo, sm );
+ /*
+ * xmit errors
+ */
+ sprintf( mon, "network/%s/oerrors",
+ IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printOErrors, printOErrorsInfo, sm );
+ /*
+ * collisions
+ */
+ sprintf( mon, "network/%s/collisions",
+ IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printCollisions, printCollisionsInfo, sm );
+ /*
+ * multicast xmits
+ */
+ sprintf( mon, "network/%s/multixmt",
+ IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printMultiXmits, printMultiXmitsInfo, sm );
+ /*
+ * multicast recvs
+ */
+ sprintf( mon, "network/%s/multircv",
+ IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printMultiRecvs, printMultiRecvsInfo, sm );
+ /*
+ * broadcast xmits
+ */
+ sprintf( mon, "network/%s/brdcstxmt",
+ IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printBcastXmits, printBcastXmitsInfo, sm );
+ /*
+ * broadcast recvs
+ */
+ sprintf( mon, "network/%s/brdcstrcv",
+ IfInfo[i].Name );
+ registerMonitor( mon, "integer",
+ printBcastRecvs, printBcastRecvsInfo, sm );
+ }
+ }
+#endif
+}
+
+void exitNetDev( void ) {
+}
+
+int updateNetDev( void ) {
+
+#ifdef HAVE_KSTAT
+ kstat_ctl_t *kctl;
+ kstat_t *ksp;
+ kstat_named_t *kdata;
+ int i;
+
+ /*
+ * get a kstat handle and update the user's kstat chain
+ */
+ if( (kctl = kstat_open()) == NULL )
+ return( 0 );
+ while( kstat_chain_update( kctl ) != 0 )
+ ;
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ char *name;
+ char *ptr;
+
+ /*
+ * chop off the trailing interface no
+ */
+ name = strdup( IfInfo[i].Name );
+ ptr = name + strlen( name ) - 1;
+ while( (ptr > name) && isdigit( (int) *ptr ) ) {
+ *ptr = '\0';
+ ptr--;
+ }
+
+ /*
+ * traverse the kstat chain
+ * to find the appropriate statistics
+ */
+ if( (ksp = kstat_lookup( kctl,
+ name, 0, IfInfo[i].Name )) == NULL ) {
+ free( name );
+ return( 0 );
+ }
+ if( kstat_read( kctl, ksp, NULL ) == -1 ) {
+ free( name );
+ return( 0 );
+ }
+ free( name );
+
+ /*
+ * lookup & store the data
+ */
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "ipackets" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDipackets = IfInfo[i].ipackets;
+ IfInfo[i].ipackets = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "opackets" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDopackets = IfInfo[i].opackets;
+ IfInfo[i].opackets = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "ierrors" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDierrors = IfInfo[i].ierrors;
+ IfInfo[i].ierrors = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "oerrors" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDoerrors = IfInfo[i].oerrors;
+ IfInfo[i].oerrors = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "collisions" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDcollisions = IfInfo[i].collisions;
+ IfInfo[i].collisions = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "multixmt" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDmultixmt = IfInfo[i].multixmt;
+ IfInfo[i].multixmt = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "multircv" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDmultircv = IfInfo[i].multircv;
+ IfInfo[i].multircv = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "brdcstxmt" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDbrdcstxmt = IfInfo[i].brdcstxmt;
+ IfInfo[i].brdcstxmt = kdata->value.ul;
+ }
+ kdata = (kstat_named_t *) kstat_data_lookup( ksp, "brdcstrcv" );
+ if( kdata != NULL ) {
+ IfInfo[i].OLDbrdcstrcv = IfInfo[i].brdcstrcv;
+ IfInfo[i].brdcstrcv = kdata->value.ul;
+ }
+ }
+
+ kstat_close( kctl );
+#endif /* ! HAVE_KSTAT */
+
+ return( 0 );
+}
+
+void printIPacketsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Received Packets\t0\t0\tPackets\n" );
+}
+
+void printIPackets( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDipackets > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].ipackets - IfInfo[i].OLDipackets);
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printOPacketsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Transmitted Packets\t0\t0\tPackets\n" );
+}
+
+void printOPackets( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDopackets > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].opackets - IfInfo[i].OLDopackets );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printIErrorsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Input Errors\t0\t0\tPackets\n" );
+}
+
+void printIErrors( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDierrors > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].ierrors - IfInfo[i].OLDierrors );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printOErrorsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Output Errors\t0\t0\tPackets\n" );
+}
+
+void printOErrors( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDoerrors > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].oerrors - IfInfo[i].OLDoerrors );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printCollisionsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Collisions\t0\t0\tPackets\n" );
+}
+
+void printCollisions( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDcollisions > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].collisions - IfInfo[i].OLDcollisions );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printMultiXmitsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Multicasts Sent\t0\t0\tPackets\n" );
+}
+
+void printMultiXmits( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDmultixmt > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].multixmt - IfInfo[i].OLDmultixmt );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printMultiRecvsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Multicasts Received\t0\t0\tPackets\n" );
+}
+
+void printMultiRecvs( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDmultircv > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].multircv - IfInfo[i].OLDmultircv );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printBcastXmitsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Broadcasts Sent\t0\t0\tPackets\n" );
+}
+
+void printBcastXmits( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDbrdcstxmt > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].brdcstxmt - IfInfo[i].OLDbrdcstxmt );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
+
+void printBcastRecvsInfo( const char *cmd ) {
+ fprintf(CurrentClient, "Broadcasts Received\t0\t0\tPackets\n" );
+}
+
+void printBcastRecvs( const char *cmd ) {
+
+ char *cmdcopy = strdup( cmd );
+ char *name, *ptr;
+ int i;
+
+ ptr = strchr( cmdcopy, (int) '/' );
+ name = ++ptr;
+ ptr = strchr( name, (int) '/' );
+ *ptr = '\0';
+
+ for( i = 0; i < NetDevCount; i++ ) {
+ if( (IfInfo[i].OLDbrdcstrcv > 0)
+ && (strcmp( IfInfo[i].Name, name ) == 0) ) {
+ fprintf(CurrentClient, "%ld\n",
+ IfInfo[i].brdcstrcv - IfInfo[i].OLDbrdcstrcv );
+ free( cmdcopy );
+ return;
+ }
+ }
+ free( cmdcopy );
+ fprintf(CurrentClient, "0\n" );
+}
diff --git a/ksysguard/ksysguardd/Tru64/NetDev.h b/ksysguard/ksysguardd/Tru64/NetDev.h
new file mode 100644
index 000000000..b6ff54448
--- /dev/null
+++ b/ksysguard/ksysguardd/Tru64/NetDev.h
@@ -0,0 +1,59 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 Chris Schlaeger <cs@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef _NetDev_h_
+#define _NetDev_h_
+
+void initNetDev(struct SensorModul* sm);
+void exitNetDev(void);
+
+int updateNetDev(void);
+
+void printIPacketsInfo( const char *cmd );
+void printIPackets( const char *cmd );
+
+void printOPacketsInfo( const char *cmd );
+void printOPackets( const char *cmd );
+
+void printIErrorsInfo( const char *cmd );
+void printIErrors( const char *cmd );
+
+void printOErrorsInfo( const char *cmd );
+void printOErrors( const char *cmd );
+
+void printCollisionsInfo( const char *cmd );
+void printCollisions( const char *cmd );
+
+void printMultiXmitsInfo( const char *cmd );
+void printMultiXmits( const char *cmd );
+
+void printMultiRecvsInfo( const char *cmd );
+void printMultiRecvs( const char *cmd );
+
+void printBcastXmitsInfo( const char *cmd );
+void printBcastXmits( const char *cmd );
+
+void printBcastRecvsInfo( const char *cmd );
+void printBcastRecvs( const char *cmd );
+
+#endif /* _NetDev_h */
diff --git a/ksysguard/ksysguardd/conf.c b/ksysguard/ksysguardd/conf.c
new file mode 100644
index 000000000..1d857137b
--- /dev/null
+++ b/ksysguard/ksysguardd/conf.c
@@ -0,0 +1,137 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "Command.h"
+
+#include "conf.h"
+
+CONTAINER LogFileList = 0;
+CONTAINER SensorList = 0;
+char* RegisterDomain = 0;
+
+void LogFileList_cleanup( void *ptr );
+void freeConfigFile( void );
+
+void LogFileList_cleanup( void *ptr )
+{
+ if ( ptr ) {
+ if ( ((ConfigLogFile*)ptr)->name )
+ free( ((ConfigLogFile*)ptr)->name );
+
+ free( ptr );
+ }
+}
+
+void freeConfigFile( void )
+{
+ destr_ctnr( LogFileList, LogFileList_cleanup );
+ destr_ctnr( SensorList, free );
+}
+
+void parseConfigFile( const char *filename )
+{
+ FILE* config;
+ char line[ 2048 ];
+ char *begin, *token, *tmp;
+ ConfigLogFile *confLog;
+
+ LogFileList = new_ctnr();
+ SensorList = new_ctnr();
+
+ if ( ( config = fopen( filename, "r" ) ) == NULL ) {
+ log_error( "can't open config file '%s'", filename );
+
+ /**
+ If we can't open a config file we have to add the
+ available sensors manually
+ */
+ push_ctnr( SensorList, strdup( "ProcessList" ) );
+ push_ctnr( SensorList, strdup( "Memory" ) );
+ push_ctnr( SensorList, strdup( "Stat" ) );
+ push_ctnr( SensorList, strdup( "NetDev" ) );
+ push_ctnr( SensorList, strdup( "NetStat" ) );
+ push_ctnr( SensorList, strdup( "Apm" ) );
+ push_ctnr( SensorList, strdup( "Acpi" ) );
+ push_ctnr( SensorList, strdup( "CpuInfo" ) );
+ push_ctnr( SensorList, strdup( "LoadAvg" ) );
+ push_ctnr( SensorList, strdup( "LmSensors" ) );
+ push_ctnr( SensorList, strdup( "DiskStat" ) );
+ push_ctnr( SensorList, strdup( "LogFile" ) );
+ push_ctnr( SensorList, strdup( "DellLaptop" ) );
+
+ return;
+ }
+
+ while ( fgets( line, sizeof( line ), config ) != NULL ) {
+ if ( ( line[ 0 ] == '#') || ( strlen( line ) == 0 ) )
+ continue;
+
+ if ( strchr( line, '#' ) )
+ *( strchr( line, '#' ) ) = '\0';
+
+ if ( line[ strlen( line ) - 1 ] == '\n' )
+ line[ strlen( line ) - 1 ] = '\0';
+
+ if ( !strncmp( line, "RegisterDomain",14) && (begin = strchr( line, '=' )) ) RegisterDomain=strdup(begin+1);
+
+ if ( !strncmp( line, "LogFiles", 8 ) && (begin = strchr( line, '=' )) ) {
+ begin++;
+
+ for ( token = strtok( begin, "," ); token; token = strtok( NULL, "," ) ) {
+ if ( ( confLog = (ConfigLogFile *)malloc( sizeof( ConfigLogFile ) ) ) == NULL ) {
+ log_error( "malloc() no free memory avail" );
+ continue;
+ }
+ confLog->name = strdup( token );
+ tmp = strchr( confLog->name, ':' );
+ *tmp = '\0';
+ confLog->path = tmp;
+ confLog->path++;
+
+ push_ctnr( LogFileList, confLog );
+ }
+ }
+
+ if ( !strncmp( line, "Sensors", 7 ) && (begin = strchr( line, '=' )) ) {
+ begin++;
+
+ for ( token = strtok( begin, ","); token; token = strtok( NULL, "," ) )
+ push_ctnr( SensorList, strdup( token ) );
+ }
+ }
+
+ fclose( config );
+}
+
+int sensorAvailable( const char *sensor )
+{
+ char* name;
+
+ for ( name = first_ctnr( SensorList ); name; name = next_ctnr( SensorList ) ) {
+ if ( !strcmp( name, sensor ) )
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/ksysguard/ksysguardd/conf.h b/ksysguard/ksysguardd/conf.h
new file mode 100644
index 000000000..40be01ea8
--- /dev/null
+++ b/ksysguard/ksysguardd/conf.h
@@ -0,0 +1,38 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include "ccont.h"
+
+#ifndef KSG_CONF_H
+#define KSG_CONF_H
+
+typedef struct {
+ char *name;
+ char *path;
+} ConfigLogFile;
+
+extern char* RegisterDomain;
+
+void parseConfigFile( const char *filename );
+void freeConfigFile();
+
+int sensorAvailable( const char* sensor );
+
+#endif
diff --git a/ksysguard/ksysguardd/configure.in.in b/ksysguard/ksysguardd/configure.in.in
new file mode 100644
index 000000000..9a2f748a1
--- /dev/null
+++ b/ksysguard/ksysguardd/configure.in.in
@@ -0,0 +1,45 @@
+#MIN_CONFIG
+
+AC_ARG_ENABLE(dnssd, [ --disable-dnssd don't require libdns_sd (browsing and publishing DNS-SD services will not be possible) ], with_dnssd=$enableval, with_dnssd=yes)
+if test "$with_dnssd" = "yes"; then
+AC_MSG_CHECKING(for DNS-SD support)
+save_dnssdtest_LIBS="$LIBS"
+save_dnssdtest_LDFLAGS="$LDFLAGS"
+save_dnssdtest_CPPFLAGS="$CPPFLAGS"
+LDFLAGS="$all_libraries $LDFLAGS"
+CPPFLAGS="$CPPFLAGS $all_includes"
+case $host_os in
+ darwin*) LIBS="" ;;
+ *) LIBS="-ldns_sd" ;;
+esac
+have_libdns_sd="no"
+AC_TRY_LINK( [
+ #include <dns_sd.h>
+ ],[
+ DNSServiceRefDeallocate( (DNSServiceRef) 0);
+ TXTRecordDeallocate( (TXTRecordRef*) 0);
+ ],[
+ AC_DEFINE(HAVE_DNSSD,1,[Define if dns-sd is available])
+ case $host_os in
+ darwin*) LIB_DNSSD="" ;;
+ *) LIB_DNSSD="-ldns_sd" ;;
+ esac
+ have_libdns_sd="yes"
+ AC_MSG_RESULT(yes)
+ ],[
+ AC_MSG_RESULT(no)
+ LIB_DNSSD=""
+])
+CPPFLAGS=$save_dnssdtest_CPPFLAGS
+LDFLAGS=$save_dnssdtest_LDFLAGS
+LIBS=$save_dnssdtest_LIBS
+fi
+
+case $host_os in
+ dragonfly*) LIB_KINFO="-lkinfo" ;;
+ *) LIB_KINFO="" ;;
+esac
+
+AC_SUBST(LIB_DNSSD)
+AC_SUBST(LIB_KINFO)
+AM_CONDITIONAL(HAVE_DNSSD, test "$have_libdns_sd" = "yes")
diff --git a/ksysguard/ksysguardd/ksysguardd.c b/ksysguard/ksysguardd/ksysguardd.c
new file mode 100644
index 000000000..faea19492
--- /dev/null
+++ b/ksysguard/ksysguardd/ksysguardd.c
@@ -0,0 +1,633 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999 - 2003 Chris Schlaeger <cs@kde.org>
+ Tobias Koenig <tokoe@kde.org>
+
+ Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#include <config.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+#include <../version.h>
+#ifdef HAVE_DNSSD
+#include <dns_sd.h>
+#endif
+#include "modules.h"
+
+#include "ksysguardd.h"
+
+#define CMDBUFSIZE 128
+#define MAX_CLIENTS 100
+
+typedef struct {
+ int socket;
+ FILE* out;
+} ClientInfo;
+
+static int ServerSocket;
+static ClientInfo ClientList[ MAX_CLIENTS ];
+static int SocketPort = -1;
+static unsigned char BindToAllInterfaces = 0;
+static int CurrentSocket;
+static const char *LockFile = "/var/run/ksysguardd.pid";
+static const char *ConfigFile = KSYSGUARDDRCFILE;
+#ifdef HAVE_DNSSD
+static int ServiceSocket = -1;
+static DNSServiceRef Ref;
+#endif
+
+void signalHandler( int sig );
+void makeDaemon( void );
+void resetClientList( void );
+int addClient( int client );
+int delClient( int client );
+int createServerSocket( void );
+#ifdef HAVE_DNSSD
+void publish_callback (DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name,
+ const char*, const char*, void *context);
+#endif
+
+/**
+ This variable is set to 1 if a module requests that the daemon should
+ be terminated.
+ */
+int QuitApp = 0;
+
+/**
+ This variable indicates whether we are running as daemon or (1) or if
+ we were have a controlling shell.
+ */
+int RunAsDaemon = 0;
+
+/**
+ This pointer is used by all modules. It contains the file pointer of
+ the currently served client. This is stdout for non-daemon mode.
+ */
+FILE* CurrentClient = 0;
+
+static int processArguments( int argc, char* argv[] )
+{
+ int option;
+
+ opterr = 0;
+ while ( ( option = getopt( argc, argv, "-p:f:dih" ) ) != EOF ) {
+ switch ( tolower( option ) ) {
+ case 'p':
+ SocketPort = atoi( optarg );
+ break;
+ case 'f':
+ ConfigFile = strdup( optarg );
+ break;
+ case 'd':
+ RunAsDaemon = 1;
+ break;
+ case 'i':
+ BindToAllInterfaces = 1;
+ break;
+ case '?':
+ case 'h':
+ default:
+ fprintf(stderr, "Usage: %s [-d] [-i] [-p port]\n", argv[ 0 ] );
+ return -1;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static void printWelcome( FILE* out )
+{
+ fprintf( out, "ksysguardd %s\n"
+ "(c) 1999, 2000, 2001, 2002 Chris Schlaeger <cs@kde.org> and\n"
+ "(c) 2001 Tobias Koenig <tokoe@kde.org>\n"
+ "This program is part of the KDE Project and licensed under\n"
+ "the GNU GPL version 2. See http://www.kde.org for details.\n",
+ KSYSGUARD_VERSION );
+
+ fflush( out );
+}
+
+static int createLockFile()
+{
+ FILE *file;
+
+ if ( ( file = fopen( LockFile, "w+" ) ) != NULL ) {
+ struct flock lock;
+ lock.l_type = F_WRLCK;
+ lock.l_whence = 0;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ lock.l_pid = -1;
+ if ( fcntl( fileno( file ), F_SETLK, &lock ) < 0 ) {
+ if ( ( errno == EACCES ) || ( errno == EAGAIN ) ) {
+ log_error( "ksysguardd is running already" );
+ fprintf( stderr, "ksysguardd is running already\n" );
+ fclose( file );
+ return -1;
+ }
+ }
+
+ fseek( file, 0, SEEK_SET );
+ fprintf( file, "%d\n", getpid() );
+ fflush( file );
+ ftruncate( fileno( file ), ftell( file ) );
+ } else {
+ log_error( "Cannot create lockfile '%s'", LockFile );
+ fprintf( stderr, "Cannot create lockfile '%s'\n", LockFile );
+ return -2;
+ }
+
+ /**
+ We abandon 'file' here on purpose. It's needed nowhere else, but we
+ have to keep the file open and locked. The kernel will remove the
+ lock when the process terminates and the runlevel scripts has to
+ remove the pid file.
+ */
+ return 0;
+}
+
+void signalHandler( int sig )
+{
+ switch ( sig ) {
+ case SIGQUIT:
+ case SIGTERM:
+#ifdef HAVE_DNSSD
+ if ( ServiceSocket != -1 ) DNSServiceRefDeallocate(Ref);
+#endif
+ exit( 0 );
+ break;
+ }
+}
+
+static void installSignalHandler( void )
+{
+ struct sigaction Action;
+
+ Action.sa_handler = signalHandler;
+ sigemptyset( &Action.sa_mask );
+ /* make sure that interrupted system calls are restarted. */
+ Action.sa_flags = SA_RESTART;
+ sigaction( SIGTERM, &Action, 0 );
+ sigaction( SIGQUIT, &Action, 0 );
+}
+
+static void dropPrivileges( void )
+{
+ struct passwd *pwd;
+
+ if ( ( pwd = getpwnam( "nobody" ) ) != NULL ) {
+ if ( !setgid(pwd->pw_gid) )
+ setuid(pwd->pw_uid);
+ if (!geteuid() && getuid() != pwd->pw_uid)
+ _exit(1);
+ }
+ else {
+ log_error( "User 'nobody' does not exist." );
+ /**
+ We exit here to avoid becoming vulnerable just because
+ user nobody does not exist.
+ */
+ _exit(1);
+ }
+}
+
+void makeDaemon( void )
+{
+ int fd = -1;
+ switch ( fork() ) {
+ case -1:
+ log_error( "fork() failed" );
+ break;
+ case 0:
+ setsid();
+ chdir( "/" );
+ umask( 0 );
+ if ( createLockFile() < 0 )
+ _exit( 1 );
+
+ dropPrivileges();
+ installSignalHandler();
+
+ fd = open("/dev/null", O_RDWR, 0);
+ if (fd != -1) {
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ close (fd);
+ }
+ break;
+ default:
+ exit( 0 );
+ }
+}
+
+static int readCommand( int fd, char* cmdBuf, size_t len )
+{
+ unsigned int i;
+ char c;
+ for ( i = 0; i < len; ++i )
+ {
+ int result = read( fd, &c, 1 );
+ if (result < 0)
+ return -1; /* Error */
+
+ if (result == 0) {
+ if (i == 0)
+ return -1; /* Connection lost */
+
+ break; /* End of data */
+ }
+
+ if (c == '\n')
+ break; /* End of line */
+
+ cmdBuf[ i ] = c;
+ }
+ cmdBuf[i] = '\0';
+
+ return i;
+}
+
+void resetClientList( void )
+{
+ int i;
+
+ for ( i = 0; i < MAX_CLIENTS; i++ ) {
+ ClientList[ i ].socket = -1;
+ ClientList[ i ].out = 0;
+ }
+}
+
+/**
+ addClient adds a new client to the ClientList.
+ */
+int addClient( int client )
+{
+ int i;
+ FILE* out;
+
+ for ( i = 0; i < MAX_CLIENTS; i++ ) {
+ if ( ClientList[ i ].socket == -1 ) {
+ ClientList[ i ].socket = client;
+ if ( ( out = fdopen( client, "w+" ) ) == NULL ) {
+ log_error( "fdopen()" );
+ return -1;
+ }
+ /* We use unbuffered IO */
+ fcntl( fileno( out ), F_SETFL, O_NDELAY );
+ ClientList[ i ].out = out;
+ printWelcome( out );
+ fprintf( out, "ksysguardd> " );
+ fflush( out );
+
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/**
+ delClient removes a client from the ClientList.
+ */
+int delClient( int client )
+{
+ int i;
+
+ for ( i = 0; i < MAX_CLIENTS; i++ ) {
+ if ( ClientList[i].socket == client ) {
+ fclose( ClientList[ i ].out );
+ ClientList[ i ].out = 0;
+ close( ClientList[ i ].socket );
+ ClientList[ i ].socket = -1;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+#ifdef HAVE_DNSSD
+void publish_callback (DNSServiceRef ref, DNSServiceFlags f, DNSServiceErrorType errorCode, const char *name,
+ const char* type, const char* domain, void *context)
+{
+ if (errorCode != kDNSServiceErr_NoError) log_error("Publishing DNS-SD service failed with error %i",errorCode);
+}
+#endif
+
+
+int createServerSocket()
+{
+ int i = 1;
+ int newSocket;
+ struct sockaddr_in s_in;
+ struct servent *service;
+
+ if ( ( newSocket = socket( PF_INET, SOCK_STREAM, 0 ) ) < 0 ) {
+ log_error( "socket()" );
+ return -1;
+ }
+
+ setsockopt( newSocket, SOL_SOCKET, SO_REUSEADDR, &i, sizeof( i ) );
+
+ /**
+ The -p command line option always overrides the default or the
+ service entry.
+ */
+ if ( SocketPort == -1 ) {
+ if ( ( service = getservbyname( "ksysguardd", "tcp" ) ) == NULL ) {
+ /**
+ No entry in service directory and no command line request,
+ so we take the build-in default (the offical IANA port).
+ */
+ SocketPort = PORT_NUMBER;
+ } else
+ SocketPort = htons( service->s_port );
+ }
+
+ memset( &s_in, 0, sizeof( struct sockaddr_in ) );
+ s_in.sin_family = AF_INET;
+ if ( BindToAllInterfaces )
+ s_in.sin_addr.s_addr = htonl( INADDR_ANY );
+ else
+ s_in.sin_addr.s_addr = htonl( INADDR_LOOPBACK );
+ s_in.sin_port = htons( SocketPort );
+
+ if ( bind( newSocket, (struct sockaddr*)&s_in, sizeof( s_in ) ) < 0 ) {
+ log_error( "Cannot bind to port %d", SocketPort );
+ return -1;
+ }
+
+ if ( listen( newSocket, 5 ) < 0 ) {
+ log_error( "listen()" );
+ return -1;
+ }
+
+#ifdef HAVE_DNSSD
+ if ( BindToAllInterfaces )
+ if (DNSServiceRegister(&Ref, 0, 0, 0, "_ksysguard._tcp", RegisterDomain ?
+ RegisterDomain : "local.",NULL, htons(SocketPort), 0, 0, publish_callback, 0) == kDNSServiceErr_NoError)
+ ServiceSocket = DNSServiceRefSockFD(Ref);
+#endif
+
+ return newSocket;
+}
+
+static int setupSelect( fd_set* fds )
+{
+ int highestFD = ServerSocket;
+ FD_ZERO( fds );
+ /**
+ Fill the filedescriptor array with all relevant descriptors. If we
+ not in daemon mode we only need to watch stdin.
+ */
+ if ( RunAsDaemon ) {
+ int i;
+ FD_SET( ServerSocket, fds );
+#ifdef HAVE_DNSSD
+ if ( ServiceSocket != -1 ) {
+ FD_SET( ServiceSocket, fds );
+ if ( highestFD < ServiceSocket) highestFD = ServiceSocket;
+ }
+#endif
+
+ for ( i = 0; i < MAX_CLIENTS; i++ ) {
+ if ( ClientList[ i ].socket != -1 ) {
+ FD_SET( ClientList[ i ].socket, fds );
+ if ( highestFD < ClientList[ i ].socket )
+ highestFD = ClientList[ i ].socket;
+ }
+ }
+ } else {
+ FD_SET( STDIN_FILENO, fds );
+ if ( highestFD < STDIN_FILENO )
+ highestFD = STDIN_FILENO;
+ }
+
+ return highestFD;
+}
+
+static void checkModules()
+{
+ struct SensorModul *entry;
+
+ for ( entry = SensorModulList; entry->configName != NULL; entry++ )
+ if ( entry->checkCommand != NULL && entry->available )
+ entry->checkCommand();
+}
+
+static void handleTimerEvent( struct timeval* tv, struct timeval* last )
+{
+ struct timeval now;
+ gettimeofday( &now, NULL );
+ /* Check if the last event was really TIMERINTERVAL seconds ago */
+ if ( now.tv_sec - last->tv_sec >= TIMERINTERVAL ) {
+ /* If so, update all sensors and save current time to last. */
+ checkModules();
+ *last = now;
+ }
+ /**
+ Set tv so that the next timer event will be generated in
+ TIMERINTERVAL seconds.
+ */
+ tv->tv_usec = last->tv_usec - now.tv_usec;
+ if ( tv->tv_usec < 0 ) {
+ tv->tv_usec += 1000000;
+ tv->tv_sec = last->tv_sec + TIMERINTERVAL - 1 - now.tv_sec;
+ } else
+ tv->tv_sec = last->tv_sec + TIMERINTERVAL - now.tv_sec;
+}
+
+static void handleSocketTraffic( int socketNo, const fd_set* fds )
+{
+ char cmdBuf[ CMDBUFSIZE ];
+
+ if ( RunAsDaemon ) {
+ int i;
+
+ if ( FD_ISSET( socketNo, fds ) ) {
+ int clientsocket;
+ struct sockaddr addr;
+ kde_socklen_t addr_len = sizeof( struct sockaddr );
+
+ /* a new connection */
+ if ( ( clientsocket = accept( socketNo, &addr, &addr_len ) ) < 0 ) {
+ log_error( "accept()" );
+ exit( 1 );
+ } else
+ addClient( clientsocket );
+ }
+
+#ifdef HAVE_DNSSD
+ if ( ServiceSocket != -1 && FD_ISSET( ServiceSocket, fds )) DNSServiceProcessResult(Ref);
+#endif
+
+ for ( i = 0; i < MAX_CLIENTS; i++ ) {
+ if ( ClientList[ i ].socket != -1 ) {
+ CurrentSocket = ClientList[ i ].socket;
+ if ( FD_ISSET( ClientList[ i ].socket, fds ) ) {
+ ssize_t cnt;
+ if ( ( cnt = readCommand( CurrentSocket, cmdBuf, sizeof( cmdBuf ) - 1 ) ) <= 0 )
+ delClient( CurrentSocket );
+ else {
+ cmdBuf[ cnt ] = '\0';
+ if ( strncmp( cmdBuf, "quit", 4 ) == 0 )
+ delClient( CurrentSocket );
+ else {
+ CurrentClient = ClientList[ i ].out;
+ fflush( stdout );
+ executeCommand( cmdBuf );
+ fprintf( CurrentClient, "ksysguardd> " );
+ fflush( CurrentClient );
+ }
+ }
+ }
+ }
+ }
+ } else if ( FD_ISSET( STDIN_FILENO, fds ) ) {
+ if (readCommand( STDIN_FILENO, cmdBuf, sizeof( cmdBuf ) ) < 0) {
+ exit(0);
+ }
+ executeCommand( cmdBuf );
+ printf( "ksysguardd> " );
+ fflush( stdout );
+ }
+}
+
+static void initModules()
+{
+ struct SensorModul *entry;
+
+ /* initialize all sensors */
+ initCommand();
+
+ for ( entry = SensorModulList; entry->configName != NULL; entry++ ) {
+ if ( entry->initCommand != NULL && sensorAvailable( entry->configName ) ) {
+ entry->available = 1;
+ entry->initCommand( entry );
+ }
+ }
+
+ ReconfigureFlag = 0;
+}
+
+static void exitModules()
+{
+ struct SensorModul *entry;
+
+ for ( entry = SensorModulList; entry->configName != NULL; entry++ ) {
+ if ( entry->exitCommand != NULL && entry->available )
+ entry->exitCommand();
+ }
+
+ exitCommand();
+}
+
+/*
+================================ public part =================================
+*/
+
+int main( int argc, char* argv[] )
+{
+ fd_set fds;
+ struct timeval tv;
+ struct timeval last;
+
+#ifdef OSTYPE_FreeBSD
+ /**
+ If we are not root or the executable does not belong to the
+ kmem group, ksysguardd will crash because of permission problems
+ for opening /dev/kmem
+ */
+ struct group* grentry = NULL;
+
+ if ( geteuid() != 0 ) {
+ grentry = getgrnam( "kmem" );
+ if ( grentry == NULL ) {
+ fprintf( stderr, "the group kmem is missing on your system\n" );
+ return -1;
+ }
+
+ if ( getegid() != grentry->gr_gid ) {
+ fprintf( stderr, "ksysguardd can't be started because of permission conflicts!\n"
+ "Start the program as user 'root' or change its group to 'kmem' and set the sgid-bit\n" );
+ return -1;
+ }
+
+ endgrent();
+ }
+#endif
+
+ printWelcome( stdout );
+
+ if ( processArguments( argc, argv ) < 0 )
+ return -1;
+
+ parseConfigFile( ConfigFile );
+
+ initModules();
+
+ if ( RunAsDaemon ) {
+ makeDaemon();
+
+ if ( ( ServerSocket = createServerSocket() ) < 0 )
+ return -1;
+ resetClientList();
+ } else {
+ fprintf( stdout, "ksysguardd> " );
+ fflush( stdout );
+ CurrentClient = stdout;
+ ServerSocket = 0;
+ }
+
+ tv.tv_sec = TIMERINTERVAL;
+ tv.tv_usec = 0;
+ gettimeofday( &last, NULL );
+
+ while ( !QuitApp ) {
+ int highestFD = setupSelect( &fds );
+ /* wait for communication or timeouts */
+ if ( select( highestFD + 1, &fds, NULL, NULL, &tv ) >= 0 ) {
+ handleTimerEvent( &tv, &last );
+ handleSocketTraffic( ServerSocket, &fds );
+ }
+ }
+
+ exitModules();
+
+ freeConfigFile();
+
+ return 0;
+}
diff --git a/ksysguard/ksysguardd/ksysguardd.h b/ksysguard/ksysguardd/ksysguardd.h
new file mode 100644
index 000000000..10184acd0
--- /dev/null
+++ b/ksysguard/ksysguardd/ksysguardd.h
@@ -0,0 +1,52 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 1999-2001 Chris Schlaeger <cs@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_KSYSGUARDD_H
+#define KSG_KSYSGUARDD_H
+
+#include <stdio.h>
+#include <time.h>
+
+/* This is the official ksysguardd port assigned by IANA. */
+#define PORT_NUMBER 3112
+
+/* Timer interval for checking modules */
+#define TIMERINTERVAL 1
+
+/* Timer interval for update modules */
+#define UPDATEINTERVAL 1
+
+extern int RunAsDaemon;
+extern int QuitApp;
+
+/* This pointer give you access to the client which made the request */
+extern FILE* CurrentClient;
+
+struct SensorModul {
+ const char *configName;
+ void (*initCommand)( struct SensorModul* );
+ void (*exitCommand)( void );
+ int (*updateCommand)( void );
+ void (*checkCommand)( void );
+ int available;
+ time_t time;
+};
+
+#endif
diff --git a/ksysguard/ksysguardd/modules.h b/ksysguard/ksysguardd/modules.h
new file mode 100644
index 000000000..5c214c7f0
--- /dev/null
+++ b/ksysguard/ksysguardd/modules.h
@@ -0,0 +1,151 @@
+/*
+ KSysGuard, the KDE System Guard
+
+ Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of version 2 of the GNU General Public
+ License as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KSG_MODULES_H
+#define KSG_MODULES_H
+
+#include "Command.h"
+#include "conf.h"
+#include "ksysguardd.h"
+
+#ifdef OSTYPE_Linux
+#include "Memory.h"
+#include "ProcessList.h"
+#include "acpi.h"
+#include "apm.h"
+#include "cpuinfo.h"
+#include "diskstat.h"
+#include "i8k.h"
+#include "lmsensors.h"
+#include "loadavg.h"
+#include "logfile.h"
+#include "netdev.h"
+#include "netstat.h"
+#include "stat.h"
+#endif /* OSTYPE_Linux */
+
+#ifdef OSTYPE_FreeBSD
+#include <grp.h>
+#include "CPU.h"
+#include "Memory.h"
+#include "ProcessList.h"
+#ifdef __i386__
+#include "apm.h"
+#endif
+#include "diskstat.h"
+#include "loadavg.h"
+#include "logfile.h"
+#include "netdev.h"
+#endif /* OSTYPE_FreeBSD */
+
+#ifdef OSTYPE_Solaris
+#include "LoadAvg.h"
+#include "Memory.h"
+#include "NetDev.h"
+#include "ProcessList.h"
+#endif /* OSTYPE_Solaris */
+
+#ifdef OSTYPE_Irix
+#include "LoadAvg.h"
+#include "Memory.h"
+#include "NetDev.h"
+#include "ProcessList.h"
+#include "cpu.h"
+#endif /* OSTYPE_Irix */
+
+#ifdef OSTYPE_Tru64
+#include "LoadAvg.h"
+#include "Memory.h"
+#include "NetDev.h"
+#endif /* OSTYPE_Tru64 */
+
+#ifdef OSTYPE_OpenBSD
+#include "cpu.h"
+#include "memory.h"
+#endif /* OSTYPE_OpenBSD */
+
+typedef void (*VSFunc)( struct SensorModul* );
+#define NULLVSFUNC ((VSFunc) 0)
+typedef void (*VVFunc)( void );
+#define NULLVVFUNC ((VVFunc) 0)
+typedef int (*IVFunc)( void );
+#define NULLIVFUNC ((IVFunc) 0)
+#define NULLTIME ((time_t) 0)
+
+struct SensorModul SensorModulList[] = {
+#ifdef OSTYPE_Linux
+ { "ProcessList", initProcessList, exitProcessList, updateProcessList, NULLVVFUNC, 0, NULLTIME },
+ { "Memory", initMemory, exitMemory, updateMemory, NULLVVFUNC, 0, NULLTIME },
+ { "Stat", initStat, exitStat, updateStat, NULLVVFUNC, 0, NULLTIME },
+ { "NetDev", initNetDev, exitNetDev, updateNetDev, NULLVVFUNC, 0, NULLTIME },
+ { "NetStat", initNetStat, exitNetStat, NULLIVFUNC, NULLVVFUNC, 0, NULLTIME },
+ { "Apm", initApm, exitApm, updateApm, NULLVVFUNC, 0, NULLTIME },
+ { "Acpi", initAcpi, exitAcpi, updateAcpi, NULLVVFUNC, 0, NULLTIME },
+ { "CpuInfo", initCpuInfo, exitCpuInfo, updateCpuInfo, NULLVVFUNC, 0, NULLTIME },
+ { "LoadAvg", initLoadAvg, exitLoadAvg, updateLoadAvg, NULLVVFUNC, 0, NULLTIME },
+ { "LmSensors", initLmSensors, exitLmSensors, NULLIVFUNC, NULLVVFUNC, 0, NULLTIME },
+ { "DiskStat", initDiskStat, exitDiskStat, updateDiskStat, checkDiskStat, 0, NULLTIME },
+ { "LogFile", initLogFile, exitLogFile, NULLIVFUNC, NULLVVFUNC, 0, NULLTIME },
+ { "DellLaptop", initI8k, exitI8k, updateI8k, NULLVVFUNC, 0, NULLTIME },
+#endif /* OSTYPE_Linux */
+
+#ifdef OSTYPE_FreeBSD
+ { "CpuInfo", initCpuInfo, exitCpuInfo, updateCpuInfo, NULLVVFUNC, 0, NULLTIME },
+ { "Memory", initMemory, exitMemory, updateMemory, NULLVVFUNC, 0, NULLTIME },
+ { "ProcessList", initProcessList, exitProcessList, updateProcessList, NULLVVFUNC, 0, NULLTIME },
+#ifdef __i386__
+ { "Apm", initApm, exitApm, updateApm, NULLVVFUNC, 0, NULLTIME },
+#endif
+ { "DiskStat", initDiskStat, exitDiskStat, updateDiskStat, checkDiskStat, 0, NULLTIME },
+ { "LoadAvg", initLoadAvg, exitLoadAvg, updateLoadAvg, NULLVVFUNC, 0, NULLTIME },
+ { "LogFile", initLogFile, exitLogFile, NULLIVFUNC, NULLVVFUNC, 0, NULLTIME },
+ { "NetDev", initNetDev, exitNetDev, updateNetDev, checkNetDev, 0, NULLTIME },
+#endif /* OSTYPE_FreeBSD */
+
+#ifdef OSTYPE_Solaris
+ { "LoadAvg", initLoadAvg, exitLoadAvg, updateLoadAvg, NULLVVFUNC, 0, NULLTIME },
+ { "Memory", initMemory, exitMemory, updateMemory, NULLVVFUNC, 0, NULLTIME },
+ { "NetDev", initNetDev, exitNetDev, updateNetDev, NULLVVFUNC, 0, NULLTIME },
+ { "ProcessList", initProcessList, exitProcessList, updateProcessList, NULLVVFUNC, 0, NULLTIME },
+#endif /* OSTYPE_Solaris */
+
+#ifdef OSTYPE_Irix
+ { "CpuInfo", initCpuInfo, exitCpuInfo, updateCpuInfo, NULLVVFUNC, 0, NULLTIME },
+ { "LoadAvg", initLoadAvg, exitLoadAvg, updateLoadAvg, NULLVVFUNC, 0, NULLTIME },
+ { "Memory", initMemory, exitMemory, updateMemory, NULLVVFUNC, 0, NULLTIME },
+ { "NetDev", initNetDev, exitNetDev, updateNetDev, NULLVVFUNC, 0, NULLTIME },
+ { "ProcessList", initProcessList, exitProcessList, updateProcessList, NULLVVFUNC, 0, NULLTIME },
+#endif /* OSTYPE_Irix */
+
+#ifdef OSTYPE_Tru64
+ { "LoadAvg", initLoadAvg, exitLoadAvg, updateLoadAvg, NULLVVFUNC, 0, NULLTIME },
+ { "Memory", initMemory, exitMemory, updateMemory, NULLVVFUNC, 0, NULLTIME },
+ { "NetDev", initNetDev, exitNetDev, updateNetDev, NULLVVFUNC, 0, NULLTIME },
+#endif /* OSTYPE_Tru64 */
+
+#ifdef OSTYPE_OpenBSD
+ { "CpuInfo", initCpuInfo, exitCpuInfo, updateCpuInfo, NULLVVFUNC, 0, NULLTIME },
+ { "Memory", initMemory, exitMemory, updateMemory, NULLVVFUNC, 0, NULLTIME },
+#endif /* OSTYPE_OpenBSD */
+
+ { NULL, NULLVSFUNC, NULLVVFUNC, NULLIVFUNC, NULLVVFUNC, 0, NULLTIME }
+};
+
+#endif
diff --git a/ksysguard/pics/Makefile.am b/ksysguard/pics/Makefile.am
new file mode 100644
index 000000000..040498488
--- /dev/null
+++ b/ksysguard/pics/Makefile.am
@@ -0,0 +1,5 @@
+#! /usr/bin/tail +2
+ksysguard_pics_datadir = $(kde_datadir)/ksysguard/pics
+
+ksysguard_pics_data_DATA = unknownapp.png ksysguardd.png computer.png daemon.png shell.png \
+kernel.png kdeapp.png X.png tools.png waiting.png running.png
diff --git a/ksysguard/pics/X.png b/ksysguard/pics/X.png
new file mode 100644
index 000000000..5b0742f87
--- /dev/null
+++ b/ksysguard/pics/X.png
Binary files differ
diff --git a/ksysguard/pics/computer.png b/ksysguard/pics/computer.png
new file mode 100644
index 000000000..85a078c13
--- /dev/null
+++ b/ksysguard/pics/computer.png
Binary files differ
diff --git a/ksysguard/pics/daemon.png b/ksysguard/pics/daemon.png
new file mode 100644
index 000000000..f21b3abfc
--- /dev/null
+++ b/ksysguard/pics/daemon.png
Binary files differ
diff --git a/ksysguard/pics/kdeapp.png b/ksysguard/pics/kdeapp.png
new file mode 100644
index 000000000..629bfbc80
--- /dev/null
+++ b/ksysguard/pics/kdeapp.png
Binary files differ
diff --git a/ksysguard/pics/kernel.png b/ksysguard/pics/kernel.png
new file mode 100644
index 000000000..9e8c0d8dc
--- /dev/null
+++ b/ksysguard/pics/kernel.png
Binary files differ
diff --git a/ksysguard/pics/ksysguardd.png b/ksysguard/pics/ksysguardd.png
new file mode 100644
index 000000000..ee4c6377d
--- /dev/null
+++ b/ksysguard/pics/ksysguardd.png
Binary files differ
diff --git a/ksysguard/pics/running.png b/ksysguard/pics/running.png
new file mode 100644
index 000000000..543710fb7
--- /dev/null
+++ b/ksysguard/pics/running.png
Binary files differ
diff --git a/ksysguard/pics/shell.png b/ksysguard/pics/shell.png
new file mode 100644
index 000000000..d7c7bc271
--- /dev/null
+++ b/ksysguard/pics/shell.png
Binary files differ
diff --git a/ksysguard/pics/tools.png b/ksysguard/pics/tools.png
new file mode 100644
index 000000000..95bd319ce
--- /dev/null
+++ b/ksysguard/pics/tools.png
Binary files differ
diff --git a/ksysguard/pics/unknownapp.png b/ksysguard/pics/unknownapp.png
new file mode 100644
index 000000000..2206448e4
--- /dev/null
+++ b/ksysguard/pics/unknownapp.png
Binary files differ
diff --git a/ksysguard/pics/waiting.png b/ksysguard/pics/waiting.png
new file mode 100644
index 000000000..2415dfc78
--- /dev/null
+++ b/ksysguard/pics/waiting.png
Binary files differ
diff --git a/ksysguard/version.h b/ksysguard/version.h
new file mode 100644
index 000000000..253a02fc7
--- /dev/null
+++ b/ksysguard/version.h
@@ -0,0 +1 @@
+#define KSYSGUARD_VERSION "1.2.0"