root/lm-sensors/branches/lm-sensors-2.10/prog/sensord/args.c @ 5738

Revision 5738, 9.4 KB (checked in by khali, 5 years ago)

sensord, sensors: Fix a memory leak when one or more chip names are
provided on the command line.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * sensord
3 *
4 * A daemon that periodically logs sensor information to syslog.
5 *
6 * Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <getopt.h>
27#include <syslog.h>
28
29#include "sensord.h"
30#include "lib/error.h"
31#include "version.h"
32
33#define MAX_CHIP_NAMES 32
34
35int isDaemon = 0;
36const char *sensorsCfgFile = "sensors.conf";
37const char *pidFile = "/var/run/sensord.pid";
38const char *rrdFile = NULL;
39const char *cgiDir = NULL;
40int scanTime = 60;
41int logTime = 30 * 60;
42int rrdTime = 5 * 60;
43int rrdNoAverage = 0;
44int syslogFacility = LOG_LOCAL4;
45int doScan = 0;
46int doSet = 0;
47int doCGI = 0;
48int doLoad = 0;
49int debug = 0;
50sensors_chip_name chipNames[MAX_CHIP_NAMES];
51int numChipNames = 0;
52
53static int
54parseTime
55(char *arg) {
56  char *end;
57  int value = strtoul (arg, &end, 10);
58  if ((end > arg) && (*end == 's')) {
59    ++ end;
60  } else if ((end > arg) && (*end == 'm')) {
61    value *= 60;
62    ++ end;
63  } else if ((end > arg) && (*end == 'h')) {
64    value *= 60 * 60;
65    ++ end;
66  }
67  if ((end == arg) || *end) {
68    fprintf (stderr, "Error parsing time value `%s'.\n", arg);
69    return -1;
70  }
71  return value;
72}
73
74static struct {
75  const char *name;
76  int id;
77} facilities[] = {
78  { "local0", LOG_LOCAL0 }, { "local1", LOG_LOCAL1 },
79  { "local2", LOG_LOCAL2 }, { "local3", LOG_LOCAL3 },
80  { "local4", LOG_LOCAL4 }, { "local5", LOG_LOCAL5 },
81  { "local6", LOG_LOCAL6 }, { "local7", LOG_LOCAL7 },
82  { "daemon", LOG_DAEMON }, { "user", LOG_USER },
83  { NULL, 0 }
84};
85
86static int
87parseFacility
88(char *arg) {
89  int i = 0;
90  while (facilities[i].name && strcasecmp (arg, facilities[i].name))
91    ++ i;
92  if (!facilities[i].name) {
93    fprintf (stderr, "Error parsing facility value `%s'.\n", arg);
94    return -1;
95  }
96  return facilities[i].id;
97}
98
99static const char *daemonSyntax =
100  "  -i, --interval <time>     -- interval between scanning alarms (default 60s)\n"
101  "  -l, --log-interval <time> -- interval between logging sensors (default 30m)\n"
102  "  -t, --rrd-interval <time> -- interval between updating RRD file (default 5m)\n"
103  "  -T, --rrd-no-average      -- switch RRD in non-average mode\n"
104  "  -r, --rrd-file <file>     -- RRD file (default <none>)\n"
105  "  -c, --config-file <file>  -- configuration file (default sensors.conf)\n"
106  "  -p, --pid-file <file>     -- PID file (default /var/run/sensord.pid)\n"
107  "  -f, --syslog-facility <f> -- syslog facility to use (default local4)\n"
108  "  -g, --rrd-cgi <img-dir>   -- output an RRD CGI script and exit\n"
109  "  -a, --load-average        -- include load average in RRD file\n"
110  "  -d, --debug               -- display some debug information\n"
111  "  -v, --version             -- display version and exit\n"
112  "  -h, --help                -- display help and exit\n"
113  "\n"
114  "Specify a value of 0 for any interval to disable that operation;\n"
115  "for example, specify --log-interval 0 to only scan for alarms."
116  "\n"
117  "If no path is specified, a list of directories is examined for the config file;\n"
118  "specify the filename `-' to read the config file from stdin.\n"
119  "\n"
120  "If no chips are specified, all chip info will be printed.\n"
121  "\n"
122  "If unspecified, no RRD (round robin database) is used. If specified and the\n"
123  "file does not exist, it will be created. For RRD updates to be successful,\n"
124  "the RRD file configuration must EXACTLY match the sensors that are used. If\n"
125  "your configuration changes, delete the old RRD file and restart sensord.\n";
126
127static const char *appSyntax =
128  "  -a, --alarm-scan          -- only scan for alarms\n"
129  "  -s, --set                 -- execute set statements (root only)\n"
130  "  -r, --rrd-file <file>     -- only update RRD file\n"
131  "  -c, --config-file <file>  -- configuration file (default sensors.conf)\n"
132  "  -d, --debug               -- display some debug information\n"
133  "  -v, --version             -- display version and exit\n"
134  "  -h, --help                -- display help and exit\n"
135  "\n"
136  "If no path is specified, a list of directories is examined for the config file;\n"
137  "specify the filename `-' to read the config file from stdin.\n"
138  "\n"
139  "If no chips are specified, all chip info will be printed.\n";
140
141static const char *daemonShortOptions = "i:l:t:Tf:r:c:p:advhg:";
142
143static const struct option daemonLongOptions[] = {
144  { "interval", required_argument, NULL, 'i' },
145  { "log-interval", required_argument, NULL, 'l' },
146  { "rrd-interval", required_argument, NULL, 't' },
147  { "rrd-no-average", no_argument, NULL, 'T' },
148  { "syslog-facility", required_argument, NULL, 'f' },
149  { "rrd-file", required_argument, NULL, 'r' },
150  { "config-file", required_argument, NULL, 'c' },
151  { "pid-file", required_argument, NULL, 'p' },
152  { "rrd-cgi", required_argument, NULL, 'g' },
153  { "load-average", no_argument, NULL, 'a' },
154  { "debug", no_argument, NULL, 'd' },
155  { "version", no_argument, NULL, 'v' },
156  { "help", no_argument, NULL, 'h' },
157  { NULL, 0, NULL, 0 }
158};
159
160static const char *appShortOptions = "asr:c:dvh";
161
162static const struct option appLongOptions[] = {
163  { "alarm-scan", no_argument, NULL, 'a' },
164  { "set", no_argument, NULL, 's' },
165  { "rrd-file", required_argument, NULL, 'r' },
166  { "config-file", required_argument, NULL, 'c' },
167  { "debug", no_argument, NULL, 'd' },
168  { "version", no_argument, NULL, 'v' },
169  { "help", no_argument, NULL, 'h' },
170  { NULL, 0, NULL, 0 }
171};
172
173int
174parseArgs
175(int argc, char **argv) {
176  int c;
177  const char *shortOptions;
178  const struct option *longOptions;
179
180  isDaemon = (argv[0][strlen (argv[0]) - 1] == 'd');
181  shortOptions = isDaemon ? daemonShortOptions : appShortOptions;
182  longOptions = isDaemon ? daemonLongOptions : appLongOptions;
183
184  while ((c = getopt_long (argc, argv, shortOptions, longOptions, NULL)) != EOF) {
185    switch(c) {
186      case 'i':
187        if ((scanTime = parseTime (optarg)) < 0)
188          return -1;
189        break;
190      case 'l':
191        if ((logTime = parseTime (optarg)) < 0)
192          return -1;
193        break;
194      case 't':
195        if ((rrdTime = parseTime (optarg)) < 0)
196          return -1;
197        break;
198      case 'T':
199        rrdNoAverage = 1;
200        break;
201      case 'f':
202        if ((syslogFacility = parseFacility (optarg)) < 0)
203          return -1;
204        break;
205      case 'a':
206        if (isDaemon)
207          doLoad = 1;
208        else
209          doScan = 1;
210        break;
211      case 's':
212        doSet = 1;
213        break;
214      case 'c':
215        sensorsCfgFile = optarg;
216        break;
217      case 'p':
218        pidFile = optarg;
219        break;
220      case 'r':
221        rrdFile = optarg;
222        break;
223      case 'd':
224        debug = 1;
225        break;
226      case 'g':
227        doCGI = 1;
228        cgiDir = optarg;
229        break;
230      case 'v':
231        printf ("sensord version %s\n", LM_VERSION);
232        exit (EXIT_SUCCESS);
233        break;
234      case 'h':
235        printf ("Syntax: %s {options} {chips}\n%s", argv[0], isDaemon ? daemonSyntax : appSyntax);
236        exit (EXIT_SUCCESS);
237        break;
238      case ':':
239      case '?':
240        printf ("Try `%s --help' for more information.\n", argv[0]);
241        return -1;
242        break;
243      default:
244        fprintf (stderr, "Internal error while parsing options.\n");
245        return -1;
246        break;
247    }
248  }
249
250  if (doScan && doSet) {
251    fprintf (stderr, "Error: Incompatible --set and --alarm-scan.\n");
252    return -1;
253  }
254 
255  if (rrdFile && doSet) {
256    fprintf (stderr, "Error: Incompatible --set and --rrd-file.\n");
257    return -1;
258  }
259 
260  if (doScan && rrdFile) {
261    fprintf (stderr, "Error: Incompatible --rrd-file and --alarm-scan.\n");
262    return -1;
263  }
264
265  if (doCGI && !rrdFile) {
266    fprintf (stderr, "Error: Incompatible --rrd-cgi without --rrd-file.\n");
267    return -1;
268  }
269 
270  if (rrdFile && !rrdTime) {
271    fprintf (stderr, "Error: Incompatible --rrd-file without --rrd-interval.\n");
272    return -1;
273  }
274 
275  if (!logTime && !scanTime && !rrdFile) {
276    fprintf (stderr, "Error: No logging, alarm or RRD scanning.\n");
277    return -1;
278  }
279
280  return 0;
281}
282
283int
284parseChips
285(int argc, char **argv) {
286  if (optind == argc) {
287    chipNames[0].prefix = SENSORS_CHIP_NAME_PREFIX_ANY;
288    chipNames[0].bus = SENSORS_CHIP_NAME_BUS_ANY;
289    chipNames[0].addr = SENSORS_CHIP_NAME_ADDR_ANY;
290    numChipNames = 1;
291  } else {
292    int i, n = argc - optind, err;
293    if (n > MAX_CHIP_NAMES) {
294      fprintf (stderr, "Too many chip names.\n");
295      return -1;
296    }
297    for (i = 0; i < n; ++ i) {
298      char *arg = argv[optind + i];
299      if ((err = sensors_parse_chip_name (arg, chipNames + i))) {
300        fprintf (stderr, "Invalid chip name `%s': %s\n", arg, sensors_strerror (err));
301        for (-- i; i >= 0; -- i)
302          free (chipNames[i].prefix);
303        return -1;
304      }
305    }
306    numChipNames = n;
307  }
308  return 0;
309}
310
311void
312freeChips
313() {
314  int i;
315  for (i = 0; i < numChipNames; ++ i)
316    free (chipNames[i].prefix);
317}
Note: See TracBrowser for help on using the browser.