diff options
Diffstat (limited to 'ksysguard/ksysguardd')
108 files changed, 16423 insertions, 0 deletions
diff --git a/ksysguard/ksysguardd/CMakeLists.txt b/ksysguard/ksysguardd/CMakeLists.txt new file mode 100644 index 000000000..9ec73cc93 --- /dev/null +++ b/ksysguard/ksysguardd/CMakeLists.txt @@ -0,0 +1,45 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +# FIXME there is only Linux support + +include( ConfigureChecks.cmake ) + +if( ${CMAKE_SYSTEM_NAME} MATCHES "Linux" ) + set( OS_SPECIFIC_DIR Linux ) +else() + tde_message_fatal( "Your operating system (${CMAKE_SYSTEM_NAME}) is not supported yet." ) +endif() + +add_subdirectory( ${OS_SPECIFIC_DIR} ) + + +add_definitions( + -DKSYSGUARDDRCFILE=\"${SYSCONF_INSTALL_DIR}/ksysguarddrc\" + -DOSTYPE_${CMAKE_SYSTEM_NAME} +) + + +include_directories( + ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/${OS_SPECIFIC_DIR} + ${CMAKE_SOURCE_DIR}/ksysguard/CContLib +) + + +##### ksysguardd (executable) ################### + +tde_add_executable( ksysguardd AUTOMOC + SOURCES Command.c conf.c ksysguardd.c PWUIDCache.c + LINK ccont-static ksysguardd-static ${TDE_LIB_DIR}/libtdefakes_nonpic.a + ${SENSORS_LIBRARIES} + DESTINATION ${BIN_INSTALL_DIR} +) 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/ConfigureChecks.cmake b/ksysguard/ksysguardd/ConfigureChecks.cmake new file mode 100644 index 000000000..529a89fbe --- /dev/null +++ b/ksysguard/ksysguardd/ConfigureChecks.cmake @@ -0,0 +1,21 @@ +################################################# +# +# (C) 2013 Alexander Golubev +# fatzer2 (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +# lm_sensors +if( WITH_SENSORS ) + check_include_file( "sensors/sensors.h" HAVE_SENSORS_SENSORS_H ) + check_library_exists( sensors sensors_init "" HAVE_SENSORS_LIB ) + if( HAVE_SENSORS_SENSORS_H AND HAVE_SENSORS_LIB ) + set( SENSORS_LIBRARIES sensors ) + else( ) + tde_message_fatal( "lm_sensors are required, but not found on your system" ) + endif( ) +endif( WITH_SENSORS ) 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..5bc2230b0 --- /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 TDEINITLEN strlen("tdeinit: ") + +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/CMakeLists.txt b/ksysguard/ksysguardd/Linux/CMakeLists.txt new file mode 100644 index 000000000..f1b02080c --- /dev/null +++ b/ksysguard/ksysguardd/Linux/CMakeLists.txt @@ -0,0 +1,36 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( -D_GNU_SOURCE ) + +if( WITH_I8K ) + add_definitions( -DHAVE_I8K_SUPPORT ) +endif() + +if( WITH_SENSORS ) + add_definitions( -DHAVE_SENSORS_SENSORS_H ) +endif() + +include_directories( + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/ksysguard/CContLib + ${CMAKE_SOURCE_DIR}/ksysguard/ksysguardd +) + + +##### ksysguardd (static) ####################### + +tde_add_library( ksysguardd STATIC + 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/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..2708664bd --- /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 TDEINITLEN strlen( "tdeinit: " ) + +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 tdeinit launched programs. */ + if ( strcmp( ps->name, "tdeinit" ) == 0 && + strncmp( ps->cmdline, "tdeinit: ", TDEINITLEN ) == 0 && + strcmp( ps->cmdline + TDEINITLEN, "Running..." ) != 0 ) { + size_t len; + char* end = strchr( ps->cmdline + TDEINITLEN, ' ' ); + if ( end ) + len = ( end - ps->cmdline ) - TDEINITLEN; + else + len = strlen( ps->cmdline + TDEINITLEN ); + if ( len > 0 ) { + if ( len > sizeof( ps->name ) - 1 ) + len = sizeof( ps->name ) - 1; + strncpy( ps->name, ps->cmdline + TDEINITLEN, 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..c2ef2d16f --- /dev/null +++ b/ksysguard/ksysguardd/Linux/netdev.c @@ -0,0 +1,482 @@ +/* + 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, f ) \ +{ \ + if (f){ \ + NetDevs[ i ].a = a - NetDevs[ i ].Old##a; \ + NetDevs[ i ].Old##a = a; \ + } \ + else{ \ + NetDevs[ i ].a = a; \ + } \ +} + +#define REGISTERSENSOR( a, b, c, d, e, f ) \ +{ \ + 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, f ) \ +{ \ + snprintf( mon, MON_SIZE, "network/interfaces/%s/%s", NetDevs[ i ].name, b ); \ + removeMonitor( mon ); \ +} + +#define DEFMEMBERS( a, b, c, d, e, f ) \ +signed long long Old##a; \ +signed long long a; \ +signed long a##Scale; + +#define DEFVARS( a, b, c, d, e, f ) \ +signed long long a; + + +/*The sixth variable is 1 if the quantity variation must be provided, 0 if the absolute value must be provided */ +#define FORALL( a ) \ + a( recBytes, "receiver/data", "Received Data", "kBytes/s", 1024, 1) \ + a( recPacks, "receiver/packets", "Received Packets", "1/s", 1, 1 ) \ + a( recErrs, "receiver/errors", "Receiver Errors", "1/s", 1, 1 ) \ + a( recDrop, "receiver/drops", "Receiver Drops", "1/s", 1, 1 ) \ + a( recFifo, "receiver/fifo", "Receiver FIFO Overruns", "1/s", 1, 1 ) \ + a( recFrame, "receiver/frame", "Receiver Frame Errors", "1/s", 1, 1 ) \ + a( recCompressed, "receiver/compressed", "Received Compressed Packets", "1/s", 1, 1 ) \ + a( recMulticast, "receiver/multicast", "Received Multicast Packets", "1/s", 1, 1 ) \ + a( sentBytes, "transmitter/data", "Sent Data", "kBytes/s", 1024, 1 ) \ + a( sentPacks, "transmitter/packets", "Sent Packets", "1/s", 1, 1 ) \ + a( sentErrs, "transmitter/errors", "Transmitter Errors", "1/s", 1, 1 ) \ + a( sentDrop, "transmitter/drops", "Transmitter Drops", "1/s", 1, 1 ) \ + a( sentFifo, "transmitter/fifo", "Transmitter FIFO overruns", "1/s", 1, 1 ) \ + a( sentColls, "transmitter/collisions", "Transmitter Collisions", "1/s", 1, 1 ) \ + a( sentCarrier, "transmitter/carrier", "Transmitter Carrier losses", "1/s", 1, 1 ) \ + a( sentCompressed, "transmitter/compressed", "Transmitter Compressed Packets", "1/s", 1, 1 ) + +#define FORALLWIFI( a ) \ + a( linkQuality, "wifi/quality", "Link Quality", "", 1, 0) \ + a( signalLevel, "wifi/signal", "Signal Level", "dBm", 1, 0) \ + a( noiseLevel, "wifi/noise", "Noise Level", "dBm", 1, 0) \ + a( nwid, "wifi/nwid", "Rx Invalid Nwid Packets", "1/s", 1, 1) \ + a( RxCrypt, "wifi/crypt", "Rx Invalid Crypt Packets", "1/s", 1, 1) \ + a( frag, "wifi/frag", "Rx Invalid Frag Packets", "1/s", 1, 1) \ + a( retry, "wifi/retry", "Tx Excessive Retries Packets", "1/s", 1, 1) \ + a( misc, "wifi/misc", "Invalid Misc Packets", "1/s", 1, 1) \ + a( beacon, "wifi/beacon", "Missed Beacon", "1/s", 1, 1) + +#define SETZERO( a, b, c, d, e, f ) \ +a = 0; + +#define SETMEMBERZERO( a, b, c, d, e, f ) \ +NetDevs[ i ].a = 0; \ +NetDevs[ i ].a##Scale = e; + +#define DECLAREFUNC( a, b, c, d, e, f ) \ +void printNetDev##a( const char* cmd ); \ +void printNetDev##a##Info( const char* cmd ); + +typedef struct +{ + FORALL( DEFMEMBERS ) + FORALLWIFI( DEFMEMBERS ) + char name[ 32 ]; + int wifi; +} 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 char NetDevWifiBuf[ 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 ) +FORALLWIFI( DECLAREFUNC ) + +static int processNetDev_( void ) +{ + int i,j; + char format[ 32 ]; + char devFormat[ 16 ]; + char buf[ 1024 ]; + char tag[ 64 ]; + char* netDevBufP = NetDevBuf; + char* netDevWifiBufP = NetDevWifiBuf; + + 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, "%lli %lli %lli %lli %lli %lli %lli %lli " + "%lli %lli %lli %lli %lli %lli %lli %lli", + &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; + + /*Update the values for the wifi interfaces*/ + if ( *netDevWifiBufP=='\0') /*there is no /proc/net/wireless file*/ + return 0; + + /* skip 2 first lines */ + for ( i = 0; i < 2; i++ ) { + sscanf( netDevWifiBufP, format, buf ); + buf[ sizeof( buf ) - 1 ] = '\0'; + netDevWifiBufP += strlen( buf ) + 1; /* move netDevWifiBufP to next line */ + } + + for ( j = 0; sscanf( netDevWifiBufP, format, buf ) == 1; ++j ) { + buf[ sizeof( buf ) - 1 ] = '\0'; + netDevWifiBufP += strlen( buf ) + 1; /* move netDevWifiBufP to next line */ + + if ( sscanf( buf, devFormat, tag ) ) { + char* pos = strchr( tag, ':' ); + if ( pos ) { + FORALLWIFI( DEFVARS ); + *pos = '\0'; + + for (i = 0 ; i < NetDevCnt ; ++i){ /*find the corresponding interface*/ + if ( strcmp(tag,NetDevs[ i ].name)==0){ + break; + } + } + sscanf( buf + 12, " %lli. %lli. %lli. %lli %lli %lli %lli %lli %lli", + &linkQuality, &signalLevel, &noiseLevel, &nwid, + &RxCrypt, &frag, &retry, &misc, &beacon ); + signalLevel -= 256; /*the units are dBm*/ + noiseLevel -= 256; + FORALLWIFI( CALC ); + } + } + } + + + + /* 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,j; + char format[ 32 ]; + char devFormat[ 16 ]; + char buf[ 1024 ]; + char tag[ 64 ]; + char* netDevBufP = NetDevBuf; + char* netDevWifiBufP = NetDevWifiBuf; + + 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, "%lli %lli %lli %lli %lli %lli %lli %lli" + "%lli %lli %lli %lli %lli %lli %lli %lli", + &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 ); + } + + } + + /* detect the wifi interfaces*/ + /* skip 2 first lines */ + for ( i = 0; i < 2; i++ ) { + sscanf( netDevWifiBufP, format, buf ); + buf[ sizeof( buf ) - 1 ] = '\0'; + netDevWifiBufP += strlen( buf ) + 1; /* move netDevWifiBufP to next line */ + } + + for ( j = 0; sscanf( netDevWifiBufP, format, buf ) == 1; ++j ) { + buf[ sizeof( buf ) - 1 ] = '\0'; + netDevWifiBufP += strlen( buf ) + 1; /* move netDevWifiBufP to next line */ + + if ( sscanf( buf, devFormat, tag ) ) { + char * pos = strchr( tag, ':' ); + if ( pos ) { + char mon[ MON_SIZE ]; + *pos = '\0'; + /*find and tag the corresponding NetDev as wifi enabled. + At the end of the loop, i is the index of the device. + This variable i is used in some macro */ + for (i = 0 ; i < NetDevCnt ; ++i){ + if ( strcmp(tag,NetDevs[ i ].name)==0){ + NetDevs[ i ].wifi = 1; + break; + } + } + FORALLWIFI( REGISTERSENSOR ); + } + FORALLWIFI( SETMEMBERZERO ); /* the variable i must point to the corrrect NetDevs[i]*/ + } + } + + /* 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 ); + if (NetDevs[ i ].wifi) + FORALLWIFI( 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; + + /* We read the informations about the wifi from /proc/net/wireless and store it into NetDevWifiBuf */ + if ( ( fd = open( "/proc/net/wireless", O_RDONLY ) ) < 0 ) { + /* /proc/net/wireless may not exist on some machines. */ + NetDevWifiBuf[0]='\0'; + } + + if ( ( n = read( fd, NetDevWifiBuf, NETDEVBUFSIZE - 1 ) ) == NETDEVBUFSIZE - 1 ) { + log_error( "Internal buffer too small to read \'/proc/net/wireless\'" ); + close( fd ); + return -1; + } + close( fd ); + NetDevWifiBuf[ n ] = '\0'; + + 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, f ) \ +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) { \ + if (f) \ + fprintf( CurrentClient, "%li\n", (long) \ + ( NetDevs[ i ].a / ( NetDevs[ i ].a##Scale * timeInterval ) ) ); \ + else \ + fprintf( CurrentClient, "%li\n", (long) NetDevs[ i ].a ); \ + 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 ) +FORALLWIFI( 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..0e6da33ad --- /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 -ltdefakes_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 |