/* KSysGuard, the KDE System Guard Copyright (c) 1999 - 2001 Chris Schlaeger 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 #include #include #include #include "Command.h" #include "ccont.h" #include "ksysguardd.h" #include "lmsensors.h" #ifdef HAVE_SENSORS_SENSORS_H #include #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