root/lm-sensors/trunk/prog/sensord/sense.c

Revision 6027, 6.0 KB (checked in by khali, 3 months ago)

Calling strcat twice in a row is inefficient, it's better to use
sprintf at the end of the string, so that we look for that end only
once.

  • 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., 51 Franklin Street, Fifth Floor, Boston,
21 * MA 02110-1301 USA.
22 */
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <syslog.h>
28
29#include "args.h"
30#include "sensord.h"
31#include "lib/error.h"
32
33#define DO_READ 0
34#define DO_SCAN 1
35#define DO_SET 2
36#define DO_RRD 3
37
38static const char *chipName(const sensors_chip_name *chip)
39{
40        static char buffer[256];
41        if (sensors_snprintf_chip_name(buffer, 256, chip) < 0)
42                return NULL;
43        return buffer;
44}
45
46static int idChip(const sensors_chip_name *chip)
47{
48        const char *name, *adapter;
49
50        name = chipName(chip);
51        if (!name) {
52                sensorLog(LOG_ERR, "Error getting chip name");
53                return -1;
54        }
55
56        sensorLog(LOG_INFO, "Chip: %s", name);
57
58        adapter = sensors_get_adapter_name(&chip->bus);
59        if (!adapter)
60                sensorLog(LOG_INFO, "Error getting adapter name");
61        else
62                sensorLog(LOG_INFO, "Adapter: %s", adapter);
63
64        return 0;
65}
66
67static int get_flag(const sensors_chip_name *chip, int num)
68{
69        double val;
70        int ret;
71
72        if (num == -1)
73                return 0;
74
75        ret = sensors_get_value(chip, num, &val);
76        if (ret) {
77                sensorLog(LOG_ERR, "Error getting sensor data: %s/#%d: %s",
78                          chip->prefix, num, sensors_strerror(ret));
79                return -1;
80        }
81
82        return (int) (val + 0.5);
83}
84
85static int do_features(const sensors_chip_name *chip,
86                       const FeatureDescriptor *feature, int action)
87{
88        char *label;
89        const char *formatted;
90        int i, alrm, beep, ret;
91        double val[MAX_DATA];
92
93        /* If only scanning, take a quick exit if alarm is off */
94        alrm = get_flag(chip, feature->alarmNumber);
95        if (alrm == -1)
96                return -1;
97        if (action == DO_SCAN && !alrm)
98                return 0;
99
100        for (i = 0; feature->dataNumbers[i] >= 0; i++) {
101                ret = sensors_get_value(chip, feature->dataNumbers[i],
102                                        val + i);
103                if (ret) {
104                        sensorLog(LOG_ERR,
105                                  "Error getting sensor data: %s/#%d: %s",
106                                  chip->prefix, feature->dataNumbers[i],
107                                  sensors_strerror(ret));
108                        return -1;
109                }
110        }
111
112        /* For RRD, we don't need anything else */
113        if (action == DO_RRD) {
114                if (feature->rrd) {
115                        const char *rrded = feature->rrd(val);
116
117                        sprintf(rrdBuff + strlen(rrdBuff), ":%s",
118                                rrded ? rrded : "U");
119                }
120
121                return 0;
122        }
123
124        /* For scanning and logging, we need extra information */
125        beep = get_flag(chip, feature->beepNumber);
126        if (beep == -1)
127                return -1;
128
129        formatted = feature->format(val, alrm, beep);
130        if (!formatted) {
131                sensorLog(LOG_ERR, "Error formatting sensor data");
132                return -1;
133        }
134
135        /* FIXME: It would be more efficient to store the label at
136         * initialization time.
137         */
138        label = sensors_get_label(chip, feature->feature);
139        if (!label) {
140                sensorLog(LOG_ERR, "Error getting sensor label: %s/%s",
141                          chip->prefix, feature->feature->name);
142                return -1;
143        }
144
145        if (action == DO_READ)
146                sensorLog(LOG_INFO, "  %s: %s", label, formatted);
147        else
148                sensorLog(LOG_ALERT, "Sensor alarm: Chip %s: %s: %s",
149                          chipName(chip), label, formatted);
150
151        free(label);
152
153        return 0;
154}
155
156static int doKnownChip(const sensors_chip_name *chip,
157                       const ChipDescriptor *descriptor, int action)
158{
159        const FeatureDescriptor *features = descriptor->features;
160        int i, ret = 0;
161
162        if (action == DO_READ) {
163                ret = idChip(chip);
164                if (ret)
165                        return ret;
166        }
167
168        for (i = 0; features[i].format; i++) {
169                ret = do_features(chip, features + i, action);
170                if (ret == -1)
171                        break;
172        }
173
174        return ret;
175}
176
177static int setChip(const sensors_chip_name *chip)
178{
179        int ret = 0;
180        if ((ret = idChip(chip))) {
181                sensorLog(LOG_ERR, "Error identifying chip: %s",
182                          chip->prefix);
183        } else if ((ret = sensors_do_chip_sets(chip))) {
184                sensorLog(LOG_ERR, "Error performing chip sets: %s: %s",
185                          chip->prefix, sensors_strerror(ret));
186                ret = 50;
187        } else {
188                sensorLog(LOG_INFO, "Set.");
189        }
190        return ret;
191}
192
193static int doChip(const sensors_chip_name *chip, int action)
194{
195        int ret = 0;
196        if (action == DO_SET) {
197                ret = setChip(chip);
198        } else {
199                int index0, chipindex = -1;
200                for (index0 = 0; knownChips[index0].features; ++index0) {
201                        /*
202                         * Trick: we compare addresses here. We know it works
203                         * because both pointers were returned by
204                         * sensors_get_detected_chips(), so they refer to
205                         * libsensors internal structures, which do not move.
206                         */
207                        if (knownChips[index0].name == chip) {
208                                chipindex = index0;
209                                break;
210                        }
211                }
212
213                if (chipindex >= 0) {
214                        ret = doKnownChip(chip, &knownChips[chipindex],
215                                          action);
216                }
217        }
218        return ret;
219}
220
221static int doChips(int action)
222{
223        const sensors_chip_name *chip, *chip_arg;
224        int i, j, ret = 0;
225
226        for (j = 0; j < sensord_args.numChipNames; j++) {
227                chip_arg = &sensord_args.chipNames[j];
228                i = 0;
229                while ((chip = sensors_get_detected_chips(chip_arg, &i))) {
230                        ret = doChip(chip, action);
231                        if (ret)
232                                return ret;
233                }
234        }
235        return ret;
236}
237
238int readChips(void)
239{
240        int ret = 0;
241
242        sensorLog(LOG_DEBUG, "sensor read started");
243        ret = doChips(DO_READ);
244        sensorLog(LOG_DEBUG, "sensor read finished");
245
246        return ret;
247}
248
249int scanChips(void)
250{
251        int ret = 0;
252
253        sensorLog(LOG_DEBUG, "sensor sweep started");
254        ret = doChips(DO_SCAN);
255        sensorLog(LOG_DEBUG, "sensor sweep finished");
256
257        return ret;
258}
259
260int setChips(void)
261{
262        int ret = 0;
263
264        sensorLog(LOG_DEBUG, "sensor set started");
265        ret = doChips(DO_SET);
266        sensorLog(LOG_DEBUG, "sensor set finished");
267
268        return ret;
269}
270
271/* TODO: loadavg entry */
272
273int rrdChips(void)
274{
275        int ret = 0;
276
277        strcpy(rrdBuff, "N");
278
279        sensorLog(LOG_DEBUG, "sensor rrd started");
280        ret = doChips(DO_RRD);
281        sensorLog(LOG_DEBUG, "sensor rrd finished");
282
283        return ret;
284}
Note: See TracBrowser for help on using the browser.