2
0
mirror of https://github.com/lm-sensors/lm-sensors synced 2025-09-05 08:45:26 +00:00
Files
lm-sensors/prog/sensors/main.c
Mark M. Hoffman f854a231b2 Add asb100 to lists of special (subclient) cases for kernel 2.6. This
stops short of full "support" for sensors, for now.  I.e. all the
	info is displayed, it's just not as pretty.


git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@2206 7894878c-1315-0410-8ee3-d5d059ff63e0
2004-01-06 05:19:25 +00:00

437 lines
12 KiB
C

/*
main.c - Part of sensors, a user-space program for hardware monitoring
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <errno.h>
#include "lib/sensors.h"
#include "lib/error.h"
#include "chips.h"
#include "version.h"
#define PROGRAM "sensors"
#define VERSION LM_VERSION
#define DEFAULT_CONFIG_FILE_NAME "sensors.conf"
static char *config_file_name = NULL;
FILE *config_file;
static const char *config_file_path[] =
{ "/etc", "/usr/local/etc", "/usr/lib/sensors", "/usr/local/lib/sensors",
"/usr/lib", "/usr/local/lib", ".", 0 };
extern int main(int argc, char *arv[]);
static void print_short_help(void);
static void print_long_help(void);
static void print_version(void);
static void open_config_file(void);
static int open_this_config_file(char *filename);
static void do_a_print(sensors_chip_name name);
static int do_a_set(sensors_chip_name name);
static int do_the_real_work(int *error);
static const char *sprintf_chip_name(sensors_chip_name name);
#define CHIPS_MAX 20
sensors_chip_name chips[CHIPS_MAX];
int chips_count=0;
int do_sets, do_unknown, fahrenheit, hide_adapter, hide_unknown;
void print_short_help(void)
{
printf("Try `%s -h' for more information\n",PROGRAM);
}
void print_long_help(void)
{
printf("Usage: %s [OPTION]... [CHIP]...\n",PROGRAM);
printf(" -c, --config-file Specify a config file\n");
printf(" -h, --help Display this help text\n");
printf(" -s, --set Execute `set' statements too (root only)\n");
printf(" -f, --fahrenheit Show temperatures in degrees fahrenheit\n");
printf(" -A, --no-adapter Do not show adapter and algorithm for each chip\n");
printf(" -U, --no-unknown Do not show unknown chips\n");
printf(" -u, --unknown Treat chips as unknown ones (testing only)\n");
printf(" -v, --version Display the program version\n");
printf("\n");
printf("By default, a list of directories is examined for config file `sensors.conf'.\n");
printf("Use `-' after `-c' to read the config file from stdin.\n");
printf("If no chips are specified, all chip info will be printed.\n");
printf("Example chip names:\n");
printf("\tlm78-i2c-0-2d\t*-i2c-0-2d\n");
printf("\tlm78-i2c-0-*\t*-i2c-0-*\n");
printf("\tlm78-i2c-*-2d\t*-i2c-*-2d\n");
printf("\tlm78-i2c-*-*\t*-i2c-*-*\n");
printf("\tlm78-isa-0290\t*-isa-0290\n");
printf("\tlm78-isa-*\t*-isa-*\n");
printf("\tlm78-*\n");
}
void print_version(void)
{
printf("%s version %s\n", PROGRAM, VERSION);
}
/* This examines global var config_file, and leaves the name there too.
It also opens config_file. */
void open_config_file(void)
{
#define MAX_FILENAME_LEN 1024
char *filename;
char buffer[MAX_FILENAME_LEN];
int res,i;
if (config_file_name && !strcmp(config_file_name,"-")) {
config_file = stdin;
return;
} else if (config_file_name && index(config_file_name,'/')) {
if ((res = open_this_config_file(config_file_name))) {
fprintf(stderr,"Could not locate or open config file\n");
fprintf(stderr,"%s: %s\n",config_file_name,strerror(-res));
exit(1);
}
}
else {
if (config_file_name)
filename = config_file_name;
else
filename = DEFAULT_CONFIG_FILE_NAME;
for (i = 0; config_file_path[i]; i++) {
if ((snprintf(buffer,MAX_FILENAME_LEN,
"%s/%s",config_file_path[i],filename)) < 1) {
fprintf(stderr,
"open_config_file: ridiculous long config file name!\n");
exit(1);
}
if (!open_this_config_file(buffer)) {
free(config_file_name);
config_file_name = strdup(buffer);
return;
}
}
fprintf(stderr,"Could not locate or open config file!\n");
exit(1);
}
}
int open_this_config_file(char *filename)
{
config_file = fopen(filename,"r");
if (! config_file)
return -errno;
return 0;
}
void close_config_file(void)
{
if (fclose(config_file)) {
fprintf(stderr,"Could not close config file\n");
fprintf(stderr,"%s: %s\n",config_file_name,strerror(errno));
}
free(config_file_name);
}
int main (int argc, char *argv[])
{
int c,res,i,error;
struct option long_opts[] = {
{ "help", no_argument, NULL, 'h' },
{ "set", no_argument, NULL, 's' },
{ "version", no_argument, NULL, 'v'},
{ "fahrenheit", no_argument, NULL, 'f' },
{ "no-adapter", no_argument, NULL, 'A' },
{ "no-unknown", no_argument, NULL, 'U' },
{ "config-file", required_argument, NULL, 'c' },
{ "unknown", no_argument, NULL, 'u' },
{ 0,0,0,0 }
};
do_unknown = 0;
do_sets = 0;
hide_adapter = 0;
while (1) {
c = getopt_long(argc,argv,"hsvfAUc:u",long_opts,NULL);
if (c == EOF)
break;
switch(c) {
case ':':
case '?':
print_short_help();
exit(1);
case 'h':
print_long_help();
exit(0);
case 'v':
print_version();
exit(0);
case 'c':
config_file_name = strdup(optarg);
break;
case 's':
do_sets = 1;
break;
case 'f':
fahrenheit = 1;
break;
case 'A':
hide_adapter = 1;
break;
case 'U':
hide_unknown = 1;
break;
case 'u':
do_unknown = 1;
break;
default:
fprintf(stderr,"Internal error while parsing options!\n");
exit(1);
}
}
if (optind == argc) {
chips[0].prefix = SENSORS_CHIP_NAME_PREFIX_ANY;
chips[0].bus = SENSORS_CHIP_NAME_BUS_ANY;
chips[0].addr = SENSORS_CHIP_NAME_ADDR_ANY;
chips_count = 1;
} else
for(i = optind; i < argc; i++)
if ((res = sensors_parse_chip_name(argv[i],chips+chips_count))) {
fprintf(stderr,"Parse error in chip name `%s'\n",argv[i]);
print_short_help();
exit(1);
} else if (++chips_count == CHIPS_MAX) {
fprintf(stderr,"Too many chips on command line!\n");
exit(1);
}
open_config_file();
if ((res = sensors_init(config_file))) {
fprintf(stderr,"%s\n",sensors_strerror(res));
if (res == -SENSORS_ERR_PROC)
fprintf(stderr,
"Unable to find i2c bus information;\n"
"For 2.6 kernels, make sure you have mounted sysfs!\n"
"For older kernels, make sure you have done 'modprobe i2c-proc'!\n");
exit(1);
}
close_config_file();
if(do_the_real_work(&error)) {
sensors_cleanup();
exit(error);
} else {
if(chips[0].prefix == SENSORS_CHIP_NAME_PREFIX_ANY)
fprintf(stderr,"No sensors found!\n");
else
fprintf(stderr,"Specified sensor(s) not found!\n");
sensors_cleanup();
exit(1);
}
}
/* returns number of chips found */
int do_the_real_work(int *error)
{
const sensors_chip_name *chip;
int chip_nr,i;
int cnt = 0;
*error = 0;
for (chip_nr = 0; (chip = sensors_get_detected_chips(&chip_nr));)
for(i = 0; i < chips_count; i++)
if (sensors_match_chip(*chip,chips[i])) {
if(do_sets) {
if (do_a_set(*chip))
*error = 1;
} else
do_a_print(*chip);
i = chips_count;
cnt++;
}
return(cnt);
}
/* returns 1 on error */
int do_a_set(sensors_chip_name name)
{
int res;
/* skip i2c subclients since sysfs doesn't hide these... */
if(name.bus >= 0)
if(name.addr >= 0x48 && name.addr <= 0x4f)
if(!strcmp(name.prefix, "as99127f") ||
!strcmp(name.prefix, "asb100") ||
!strcmp(name.prefix, "w83781d") ||
!strcmp(name.prefix, "w83782d") ||
!strcmp(name.prefix, "w83783s") ||
!strcmp(name.prefix, "w83791d") ||
!strcmp(name.prefix, "w83627hf") ||
!strcmp(name.prefix, "w83697hf"))
return 0;
if ((res = sensors_do_chip_sets(name))) {
if (res == -SENSORS_ERR_PROC) {
fprintf(stderr,"%s: %s for writing;\n",sprintf_chip_name(name),
sensors_strerror(res));
fprintf(stderr,"Run as root?\n");
return 1;
} else {
fprintf(stderr,"%s: %s\n",sprintf_chip_name(name),
sensors_strerror(res));
}
}
return 0;
}
const char *sprintf_chip_name(sensors_chip_name name)
{
#define BUF_SIZE 200
static char buf[BUF_SIZE];
if (name.bus == SENSORS_CHIP_NAME_BUS_ISA)
snprintf(buf,BUF_SIZE,"%s-isa-%04x",name.prefix,name.addr);
else if (name.bus == SENSORS_CHIP_NAME_BUS_DUMMY)
snprintf(buf,BUF_SIZE,"%s-%s-%04x",name.prefix,name.busname,name.addr);
else
snprintf(buf,BUF_SIZE,"%s-i2c-%d-%02x",name.prefix,name.bus,name.addr);
return buf;
}
struct match {
const char * prefix;
void (*fn) (const sensors_chip_name *name);
};
struct match matches[] = {
{ "ds1621", print_ds1621 },
{ "lm75", print_lm75 },
{ "adm1021", print_adm1021 },
{ "max1617", print_adm1021 },
{ "max1617a", print_adm1021 },
{ "thmc10", print_adm1021 },
{ "lm84", print_adm1021 },
{ "gl523", print_adm1021 },
{ "adm1023", print_adm1021 },
{ "mc1066", print_adm1021 },
{ "adm9240", print_adm9240 },
{ "ds1780", print_adm9240 },
{ "lm81", print_adm9240 },
{ "lm78", print_lm78 },
{ "lm78-j", print_lm78 },
{ "lm79", print_lm78 },
{ "mtp008", print_mtp008 },
{ "sis5595", print_sis5595 },
{ "via686a", print_via686a },
{ "lm80", print_lm80 },
{ "lm85", print_lm85 },
{ "lm85b", print_lm85 },
{ "lm85c", print_lm85 },
{ "adm1027", print_lm85 },
{ "adt7463", print_lm85 },
{ "emc6d100", print_lm85 },
{ "lm87", print_lm87 },
{ "gl518sm", print_gl518 },
{ "adm1025", print_adm1025 },
{ "adm1024", print_adm1024 },
{ "w83781d", print_w83781d },
{ "w83782d", print_w83781d },
{ "w83783d", print_w83781d },
{ "w83627hf", print_w83781d },
{ "w83627thf", print_w83781d },
{ "w83697hf", print_w83781d },
{ "w83791d", print_w83781d },
{ "as99127f", print_w83781d },
{ "maxilife", print_maxilife },
{ "maxilife-cg", print_maxilife },
{ "maxilife-co", print_maxilife },
{ "maxilife-as", print_maxilife },
{ "maxilife-nba", print_maxilife },
{ "it87", print_it87 },
{ "ddcmon", print_ddcmon },
{ "eeprom", print_eeprom },
{ "fscpos", print_fscpos },
{ "fscscy", print_fscscy },
{ "fscher", print_fscher },
{ "pcf8591", print_pcf8591 },
{ "vt1211", print_vt1211 },
{ "smsc47m1", print_smsc47m1 },
{ "lm92", print_lm92 },
{ "vt8231", print_vt8231 },
{ "bmc", print_bmc },
{ "adm1026", print_adm1026 },
{ "lm83", print_lm83 },
{ "lm90", print_lm90 },
{ "adm1032", print_lm90 },
{ "xeontemp", print_xeontemp },
{ "max6650", print_max6650 },
{ NULL, NULL }
};
void do_a_print(sensors_chip_name name)
{
const char *algo,*adap;
struct match *m;
/* skip i2c subclients since sysfs doesn't hide these... */
if(name.bus >= 0)
if(name.addr >= 0x48 && name.addr <= 0x4f)
if(!strcmp(name.prefix, "as99127f") ||
!strcmp(name.prefix, "asb100") ||
!strcmp(name.prefix, "w83781d") ||
!strcmp(name.prefix, "w83782d") ||
!strcmp(name.prefix, "w83783s") ||
!strcmp(name.prefix, "w83791d") ||
!strcmp(name.prefix, "w83627hf") ||
!strcmp(name.prefix, "w83697hf"))
return;
/* do we know how to display it? */
for(m = matches; m->prefix != NULL; m++) {
if(!strcmp(name.prefix, m->prefix)) break;
}
if(m->prefix==NULL && hide_unknown)
return;
printf("%s\n",sprintf_chip_name(name));
adap = sensors_get_adapter_name(name.bus);
if (adap && !hide_adapter)
printf("Adapter: %s\n",adap);
algo = sensors_get_algorithm_name(name.bus);
if (algo && !hide_adapter)
printf("Algorithm: %s\n",algo);
if (!algo || !adap)
printf(" ERROR: Can't get adapter or algorithm?!?\n");
if (do_unknown)
print_unknown_chip(&name);
else {
if(m->prefix == NULL)
print_unknown_chip(&name);
else
m->fn(&name);
}
printf("\n");
}