root/lm-sensors/trunk/prog/sensors/main.c @ 2422

Revision 2422, 12.7 KB (checked in by khali, 11 years ago)

Premliminarily support PC87365 and PC87366.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    main.c - Part of sensors, a user-space program for hardware monitoring
3    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*/
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <getopt.h>
23#include <string.h>
24#include <errno.h>
25#include <locale.h>
26#include <langinfo.h>
27#include <iconv.h>
28
29#include "lib/sensors.h"
30#include "lib/error.h"
31#include "chips.h"
32#include "version.h"
33
34#define PROGRAM "sensors"
35#define VERSION LM_VERSION
36#define DEFAULT_CONFIG_FILE_NAME "sensors.conf"
37
38static char *config_file_name = NULL;
39FILE *config_file;
40static const char *config_file_path[] = 
41  { "/etc", "/usr/local/etc", "/usr/lib/sensors", "/usr/local/lib/sensors",
42    "/usr/lib", "/usr/local/lib", ".", 0 };
43
44extern int main(int argc, char *arv[]);
45static void print_short_help(void);
46static void print_long_help(void);
47static void print_version(void);
48static void open_config_file(void);
49static int open_this_config_file(char *filename);
50static void do_a_print(sensors_chip_name name);
51static int do_a_set(sensors_chip_name name);
52static int do_the_real_work(int *error);
53static const char *sprintf_chip_name(sensors_chip_name name);
54
55#define CHIPS_MAX 20
56sensors_chip_name chips[CHIPS_MAX];
57int chips_count=0;
58int do_sets, do_unknown, fahrenheit, show_algorithm, hide_adapter, hide_unknown;
59
60char degstr[5]; /* store the correct string to print degrees */
61
62void print_short_help(void)
63{
64  printf("Try `%s -h' for more information\n",PROGRAM);
65}
66
67void print_long_help(void)
68{
69  printf("Usage: %s [OPTION]... [CHIP]...\n",PROGRAM);
70  printf("  -c, --config-file     Specify a config file\n");
71  printf("  -h, --help            Display this help text\n");
72  printf("  -s, --set             Execute `set' statements too (root only)\n");
73  printf("  -f, --fahrenheit      Show temperatures in degrees fahrenheit\n");
74  printf("  -a, --algorithm       Show algorithm for each chip\n");
75  printf("  -A, --no-adapter      Do not show adapter for each chip\n");
76  printf("  -U, --no-unknown      Do not show unknown chips\n");
77  printf("  -u, --unknown         Treat chips as unknown ones (testing only)\n");
78  printf("  -v, --version         Display the program version\n");
79  printf("\n");
80  printf("By default, a list of directories is examined for config file `sensors.conf'.\n");
81  printf("Use `-' after `-c' to read the config file from stdin.\n");
82  printf("If no chips are specified, all chip info will be printed.\n");
83  printf("Example chip names:\n");
84  printf("\tlm78-i2c-0-2d\t*-i2c-0-2d\n");
85  printf("\tlm78-i2c-0-*\t*-i2c-0-*\n");
86  printf("\tlm78-i2c-*-2d\t*-i2c-*-2d\n");
87  printf("\tlm78-i2c-*-*\t*-i2c-*-*\n");
88  printf("\tlm78-isa-0290\t*-isa-0290\n");
89  printf("\tlm78-isa-*\t*-isa-*\n");
90  printf("\tlm78-*\n");
91}
92
93void print_version(void)
94{
95  printf("%s version %s\n", PROGRAM, VERSION);
96}
97
98/* This examines global var config_file, and leaves the name there too.
99   It also opens config_file. */
100void open_config_file(void)
101{
102#define MAX_FILENAME_LEN 1024
103  char *filename;
104  char buffer[MAX_FILENAME_LEN];
105  int res,i;
106
107  if (config_file_name && !strcmp(config_file_name,"-")) {
108    config_file = stdin;
109    return;
110  } else if (config_file_name && index(config_file_name,'/')) {
111    if ((res = open_this_config_file(config_file_name))) {
112      fprintf(stderr,"Could not locate or open config file\n");
113      fprintf(stderr,"%s: %s\n",config_file_name,strerror(-res));
114      exit(1);
115    }
116  }
117  else {
118    if (config_file_name)
119      filename = config_file_name;
120    else
121      filename = DEFAULT_CONFIG_FILE_NAME;
122    for (i = 0; config_file_path[i]; i++) {
123      if ((snprintf(buffer,MAX_FILENAME_LEN,
124                   "%s/%s",config_file_path[i],filename)) < 1) {
125        fprintf(stderr,
126                "open_config_file: ridiculous long config file name!\n");
127        exit(1);
128      }
129      if (!open_this_config_file(buffer)) {
130        free(config_file_name);
131        config_file_name = strdup(buffer);
132        return;
133      }
134    }
135    fprintf(stderr,"Could not locate or open config file!\n");
136    exit(1);
137  }
138}
139   
140int open_this_config_file(char *filename)
141{
142  config_file = fopen(filename,"r");
143  if (! config_file)
144    return -errno;
145  return 0;
146}
147
148void close_config_file(void)
149{
150  if (fclose(config_file)) {
151    fprintf(stderr,"Could not close config file\n");
152    fprintf(stderr,"%s: %s\n",config_file_name,strerror(errno));
153  }
154 
155  free(config_file_name);
156}
157
158static void set_degstr(void)
159{
160  /* Size hardcoded for better performance.
161     Don't forget to count the trailing \0! */
162  size_t deg_latin1_size = 3;
163  char *deg_latin1_text[2] = {"\260C", "\260F"};
164  const char *deg_default_text[2] = {" C", " F"};
165  size_t nconv;
166  size_t degstr_size = sizeof(degstr);
167  char *degstr_ptr = degstr;
168
169  iconv_t cd = iconv_open(nl_langinfo(CODESET), "ISO-8859-1");
170  if (cd != (iconv_t) -1) {
171    nconv = iconv(cd, &(deg_latin1_text[fahrenheit]), &deg_latin1_size,
172                  &degstr_ptr, &degstr_size);
173    iconv_close(cd);
174   
175    if (nconv != (size_t) -1)
176      return;     
177  }
178
179  /* There was an error during the conversion, use the default text */
180  strcpy(degstr, deg_default_text[fahrenheit]);
181}
182
183int main (int argc, char *argv[])
184{
185  int c,res,i,error;
186
187  struct option long_opts[] =  {
188    { "help", no_argument, NULL, 'h' },
189    { "set", no_argument, NULL, 's' },
190    { "version", no_argument, NULL, 'v'},
191    { "fahrenheit", no_argument, NULL, 'f' },
192    { "algorithm", no_argument, NULL, 'a' },
193    { "no-adapter", no_argument, NULL, 'A' },
194    { "no-unknown", no_argument, NULL, 'U' },
195    { "config-file", required_argument, NULL, 'c' },
196    { "unknown", no_argument, NULL, 'u' },
197    { 0,0,0,0 }
198  };
199
200  setlocale(LC_CTYPE, "");
201
202  do_unknown = 0;
203  do_sets = 0;
204  show_algorithm = 0;
205  hide_adapter = 0;
206  hide_unknown = 0;
207  while (1) {
208    c = getopt_long(argc,argv,"hsvfaAUc:u",long_opts,NULL);
209    if (c == EOF)
210      break;
211    switch(c) {
212    case ':':
213    case '?':
214      print_short_help();
215      exit(1);
216    case 'h':
217      print_long_help();
218      exit(0);
219    case 'v':
220      print_version();
221      exit(0);
222    case 'c':
223      config_file_name = strdup(optarg);
224      break;
225    case 's':
226      do_sets = 1;
227      break;
228    case 'f':
229      fahrenheit = 1;
230      break;
231    case 'a':
232      show_algorithm = 1;
233      break;
234    case 'A':
235      hide_adapter = 1;
236      break;
237    case 'U':
238      hide_unknown = 1;
239      break;
240    case 'u':
241      do_unknown = 1;
242      break;
243    default:
244      fprintf(stderr,"Internal error while parsing options!\n");
245      exit(1);
246    }
247  }
248
249  if (optind == argc) {
250    chips[0].prefix = SENSORS_CHIP_NAME_PREFIX_ANY;
251    chips[0].bus = SENSORS_CHIP_NAME_BUS_ANY;
252    chips[0].addr = SENSORS_CHIP_NAME_ADDR_ANY;
253    chips_count = 1;
254  } else 
255    for(i = optind; i < argc; i++) 
256      if ((res = sensors_parse_chip_name(argv[i],chips+chips_count))) {
257        fprintf(stderr,"Parse error in chip name `%s'\n",argv[i]);
258        print_short_help();
259        exit(1);
260      } else if (++chips_count == CHIPS_MAX) {
261        fprintf(stderr,"Too many chips on command line!\n");
262        exit(1);
263      }
264
265
266  open_config_file();
267
268  if ((res = sensors_init(config_file))) {
269    fprintf(stderr,"%s\n",sensors_strerror(res));
270    if (res == -SENSORS_ERR_PROC)
271      fprintf(stderr,
272              "Unable to find i2c bus information;\n"
273              "For 2.6 kernels, make sure you have mounted sysfs and done\n"
274              "'modprobe i2c_sensor'!\n"
275              "For older kernels, make sure you have done 'modprobe i2c-proc'!\n");
276    exit(1);
277  }
278
279  close_config_file();
280
281  /* build the degrees string */
282  set_degstr();
283
284  if(do_the_real_work(&error)) {
285    sensors_cleanup();
286    exit(error);
287  } else {
288    if(chips[0].prefix == SENSORS_CHIP_NAME_PREFIX_ANY)
289            fprintf(stderr,"No sensors found!\n");
290    else
291            fprintf(stderr,"Specified sensor(s) not found!\n");
292    sensors_cleanup();
293    exit(1);
294  }
295}
296
297/* returns number of chips found */
298int do_the_real_work(int *error)
299{
300  const sensors_chip_name *chip;
301  int chip_nr,i;
302  int cnt = 0;
303
304  *error = 0;
305  for (chip_nr = 0; (chip = sensors_get_detected_chips(&chip_nr));)
306    for(i = 0; i < chips_count; i++)
307      if (sensors_match_chip(*chip,chips[i])) {
308        if(do_sets) {
309          if (do_a_set(*chip))
310            *error = 1;
311        } else
312          do_a_print(*chip);
313        i = chips_count;
314        cnt++;
315      }
316   return(cnt);
317}
318
319/* returns 1 on error */
320int do_a_set(sensors_chip_name name)
321{
322  int res;
323
324  if ((res = sensors_do_chip_sets(name))) {
325    if (res == -SENSORS_ERR_PROC) {
326      fprintf(stderr,"%s: %s for writing;\n",sprintf_chip_name(name),
327              sensors_strerror(res));
328      fprintf(stderr,"Run as root?\n");
329      return 1;
330    } else {
331      fprintf(stderr,"%s: %s\n",sprintf_chip_name(name),
332              sensors_strerror(res));
333    }
334  }
335  return 0;
336}
337
338const char *sprintf_chip_name(sensors_chip_name name)
339{
340  #define BUF_SIZE 200
341  static char buf[BUF_SIZE];
342
343  if (name.bus == SENSORS_CHIP_NAME_BUS_ISA)
344    snprintf(buf,BUF_SIZE,"%s-isa-%04x",name.prefix,name.addr);
345  else if (name.bus == SENSORS_CHIP_NAME_BUS_DUMMY)
346    snprintf(buf,BUF_SIZE,"%s-%s-%04x",name.prefix,name.busname,name.addr);
347  else
348    snprintf(buf,BUF_SIZE,"%s-i2c-%d-%02x",name.prefix,name.bus,name.addr);
349  return buf;
350}
351
352struct match {
353        const char * prefix;
354        void (*fn) (const sensors_chip_name *name);
355};
356
357struct match matches[] = {
358        { "ds1621", print_ds1621 },
359        { "lm75", print_lm75 },
360        { "adm1021", print_adm1021 },
361        { "max1617", print_adm1021 },
362        { "max1617a", print_adm1021 },
363        { "thmc10", print_adm1021 },
364        { "lm84", print_adm1021 },
365        { "gl523", print_adm1021 },
366        { "adm1023", print_adm1021 },
367        { "mc1066", print_adm1021 },
368        { "adm9240", print_adm9240 },
369        { "ds1780", print_adm9240 },
370        { "lm81", print_adm9240 },
371        { "lm78", print_lm78 },
372        { "lm78-j", print_lm78 },
373        { "lm79", print_lm78 },
374        { "mtp008", print_mtp008 },
375        { "sis5595", print_sis5595 },
376        { "via686a", print_via686a },
377        { "lm80", print_lm80 },
378        { "lm85", print_lm85 },
379        { "lm85b", print_lm85 },
380        { "lm85c", print_lm85 },
381        { "adm1027", print_lm85 },
382        { "adt7463", print_lm85 },
383        { "emc6d100", print_lm85 },
384        { "lm87", print_lm87 },
385        { "gl518sm", print_gl518 },
386        { "adm1025", print_adm1025 },
387        { "ne1619", print_adm1025 },
388        { "adm1024", print_adm1024 },
389        { "w83781d", print_w83781d },
390        { "w83782d", print_w83781d },
391        { "w83783d", print_w83781d },
392        { "w83627hf", print_w83781d },
393        { "w83627thf", print_w83781d },
394        { "w83637hf", print_w83781d },
395        { "w83697hf", print_w83781d },
396        { "w83791d", print_w83781d },
397        { "w83l785ts", print_w83l785ts },
398        { "as99127f", print_w83781d },
399        { "maxilife", print_maxilife },
400        { "maxilife-cg", print_maxilife },
401        { "maxilife-co", print_maxilife },
402        { "maxilife-as", print_maxilife },
403        { "maxilife-nba", print_maxilife },
404        { "it87", print_it87 },
405        { "ddcmon", print_ddcmon },
406        { "eeprom", print_eeprom },
407        { "fscpos", print_fscpos },
408        { "fscscy", print_fscscy },
409        { "fscher", print_fscher },
410        { "pcf8591", print_pcf8591 },
411        { "vt1211", print_vt1211 },
412        { "smsc47m1", print_smsc47m1 },
413        { "pc87360", print_pc87360 },
414        { "pc87363", print_pc87360 },
415        { "pc87364", print_pc87364 },
416        { "pc87365", print_pc87364 },
417        { "pc87366", print_pc87364 },
418        { "lm92", print_lm92 },
419        { "vt8231", print_vt8231 },
420        { "bmc", print_bmc },
421        { "adm1026", print_adm1026 },
422        { "lm83", print_lm83 },
423        { "lm90", print_lm90 },
424        { "adm1032", print_lm90 },
425        { "xeontemp", print_xeontemp },
426        { "max6650", print_max6650 },
427        { "asb100", print_asb100 },
428        { NULL, NULL }
429};
430
431void do_a_print(sensors_chip_name name)
432{
433  const char *algo,*adap;
434  struct match *m;
435
436  /* do we know how to display it? */
437  for(m = matches; m->prefix != NULL; m++) {
438    if(!strcmp(name.prefix, m->prefix)) break;
439  }
440
441  if(m->prefix==NULL && hide_unknown)
442    return;
443
444  printf("%s\n",sprintf_chip_name(name));
445  adap = sensors_get_adapter_name(name.bus);
446  if (adap && !hide_adapter)
447    printf("Adapter: %s\n",adap);
448  algo = sensors_get_algorithm_name(name.bus);
449  if (algo && show_algorithm)
450    printf("Algorithm: %s\n",algo);
451  if (!algo || !adap)
452    printf(" ERROR: Can't get adapter or algorithm?!?\n");
453  if (do_unknown)
454    print_unknown_chip(&name);
455  else {
456    if(m->prefix == NULL)
457        print_unknown_chip(&name);
458    else
459        m->fn(&name);
460  }
461  printf("\n");
462}
Note: See TracBrowser for help on using the browser.