blob: 558046e76c246b551828caea18f242198234b116 [file] [log] [blame]
Jon Medhurstaaf37a32013-06-11 12:10:56 +01001/*
2 init.c - Part of libsensors, a Linux library for reading sensor data.
3 Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
4 Copyright (C) 2007, 2009 Jean Delvare <khali@linux-fr.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 MA 02110-1301 USA.
20*/
21
22/*** This file modified by ARM on Jan 23, 2013 to cast alphasort to supress a warning as it's prototype is different on android. ***/
23
24/* Needed for scandir() and alphasort() */
25#define _BSD_SOURCE
26
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <locale.h>
30#include <stdlib.h>
31#include <stdio.h>
32#include <string.h>
33#include <errno.h>
34#include <dirent.h>
35#include <unistd.h>
36#include "sensors.h"
37#include "data.h"
38#include "error.h"
39#include "access.h"
40#include "conf.h"
41#include "sysfs.h"
42#include "scanner.h"
43#include "init.h"
44
45#define DEFAULT_CONFIG_FILE ETCDIR "/sensors3.conf"
46#define ALT_CONFIG_FILE ETCDIR "/sensors.conf"
47#define DEFAULT_CONFIG_DIR ETCDIR "/sensors.d"
48
49/* Wrapper around sensors_yyparse(), which clears the locale so that
50 the decimal numbers are always parsed properly. */
51static int sensors_parse(void)
52{
53 int res;
54 char *locale;
55
56 /* Remember the current locale and clear it */
57 locale = setlocale(LC_ALL, NULL);
58 if (locale) {
59 locale = strdup(locale);
60 if (!locale)
61 sensors_fatal_error(__func__, "Out of memory");
62
63 setlocale(LC_ALL, "C");
64 }
65
66 res = sensors_yyparse();
67
68 /* Restore the old locale */
69 if (locale) {
70 setlocale(LC_ALL, locale);
71 free(locale);
72 }
73
74 return res;
75}
76
77static void free_bus(sensors_bus *bus)
78{
79 free(bus->adapter);
80}
81
82static void free_config_busses(void)
83{
84 int i;
85
86 for (i = 0; i < sensors_config_busses_count; i++)
87 free_bus(&sensors_config_busses[i]);
88 free(sensors_config_busses);
89 sensors_config_busses = NULL;
90 sensors_config_busses_count = sensors_config_busses_max = 0;
91}
92
93static int parse_config(FILE *input, const char *name)
94{
95 int err;
96 char *name_copy;
97
98 if (name) {
99 /* Record configuration file name for error reporting */
100 name_copy = strdup(name);
101 if (!name_copy)
102 sensors_fatal_error(__func__, "Out of memory");
103 sensors_add_config_files(&name_copy);
104 } else
105 name_copy = NULL;
106
107 if (sensors_scanner_init(input, name_copy)) {
108 err = -SENSORS_ERR_PARSE;
109 goto exit_cleanup;
110 }
111 err = sensors_parse();
112 sensors_scanner_exit();
113 if (err) {
114 err = -SENSORS_ERR_PARSE;
115 goto exit_cleanup;
116 }
117
118 err = sensors_substitute_busses();
119
120exit_cleanup:
121 free_config_busses();
122 return err;
123}
124
125static int config_file_filter(const struct dirent *entry)
126{
127 return entry->d_name[0] != '.'; /* Skip hidden files */
128}
129
130static int add_config_from_dir(const char *dir)
131{
132 int count, res, i;
133 struct dirent **namelist;
134
135 count = scandir(dir, &namelist, config_file_filter, (int (*)(const struct dirent **, const struct dirent **))alphasort);
136 if (count < 0) {
137 /* Do not return an error if directory does not exist */
138 if (errno == ENOENT)
139 return 0;
140
141 sensors_parse_error_wfn(strerror(errno), NULL, 0);
142 return -SENSORS_ERR_PARSE;
143 }
144
145 for (res = 0, i = 0; !res && i < count; i++) {
146 int len;
147 char path[PATH_MAX];
148 FILE *input;
149 struct stat st;
150
151 len = snprintf(path, sizeof(path), "%s/%s", dir,
152 namelist[i]->d_name);
153 if (len < 0 || len >= (int)sizeof(path)) {
154 res = -SENSORS_ERR_PARSE;
155 continue;
156 }
157
158 /* Only accept regular files */
159 if (stat(path, &st) < 0 || !S_ISREG(st.st_mode))
160 continue;
161
162 input = fopen(path, "r");
163 if (input) {
164 res = parse_config(input, path);
165 fclose(input);
166 } else {
167 res = -SENSORS_ERR_PARSE;
168 sensors_parse_error_wfn(strerror(errno), path, 0);
169 }
170 }
171
172 /* Free memory allocated by scandir() */
173 for (i = 0; i < count; i++)
174 free(namelist[i]);
175 free(namelist);
176
177 return res;
178}
179
180int sensors_init(FILE *input)
181{
182 int res;
183
184 if (!sensors_init_sysfs())
185 return -SENSORS_ERR_KERNEL;
186 if ((res = sensors_read_sysfs_bus()) ||
187 (res = sensors_read_sysfs_chips()))
188 goto exit_cleanup;
189
190 if (input) {
191 res = parse_config(input, NULL);
192 if (res)
193 goto exit_cleanup;
194 } else {
195 const char* name;
196
197 /* No configuration provided, use default */
198 input = fopen(name = DEFAULT_CONFIG_FILE, "r");
199 if (!input && errno == ENOENT)
200 input = fopen(name = ALT_CONFIG_FILE, "r");
201 if (input) {
202 res = parse_config(input, name);
203 fclose(input);
204 if (res)
205 goto exit_cleanup;
206
207 } else if (errno != ENOENT) {
208 sensors_parse_error_wfn(strerror(errno), name, 0);
209 res = -SENSORS_ERR_PARSE;
210 goto exit_cleanup;
211 }
212
213 /* Also check for files in default directory */
214 res = add_config_from_dir(DEFAULT_CONFIG_DIR);
215 if (res)
216 goto exit_cleanup;
217 }
218
219 return 0;
220
221exit_cleanup:
222 sensors_cleanup();
223 return res;
224}
225
226static void free_chip_name(sensors_chip_name *name)
227{
228 free(name->prefix);
229 free(name->path);
230}
231
232static void free_chip_features(sensors_chip_features *features)
233{
234 int i;
235
236 for (i = 0; i < features->subfeature_count; i++)
237 free(features->subfeature[i].name);
238 free(features->subfeature);
239 for (i = 0; i < features->feature_count; i++)
240 free(features->feature[i].name);
241 free(features->feature);
242}
243
244static void free_label(sensors_label *label)
245{
246 free(label->name);
247 free(label->value);
248}
249
250void sensors_free_expr(sensors_expr *expr)
251{
252 if (expr->kind == sensors_kind_var)
253 free(expr->data.var);
254 else if (expr->kind == sensors_kind_sub) {
255 if (expr->data.subexpr.sub1)
256 sensors_free_expr(expr->data.subexpr.sub1);
257 if (expr->data.subexpr.sub2)
258 sensors_free_expr(expr->data.subexpr.sub2);
259 }
260 free(expr);
261}
262
263static void free_set(sensors_set *set)
264{
265 free(set->name);
266 sensors_free_expr(set->value);
267}
268
269static void free_compute(sensors_compute *compute)
270{
271 free(compute->name);
272 sensors_free_expr(compute->from_proc);
273 sensors_free_expr(compute->to_proc);
274}
275
276static void free_ignore(sensors_ignore *ignore)
277{
278 free(ignore->name);
279}
280
281static void free_chip(sensors_chip *chip)
282{
283 int i;
284
285 for (i = 0; i < chip->chips.fits_count; i++)
286 free_chip_name(&chip->chips.fits[i]);
287 free(chip->chips.fits);
288 chip->chips.fits_count = chip->chips.fits_max = 0;
289
290 for (i = 0; i < chip->labels_count; i++)
291 free_label(&chip->labels[i]);
292 free(chip->labels);
293 chip->labels_count = chip->labels_max = 0;
294
295 for (i = 0; i < chip->sets_count; i++)
296 free_set(&chip->sets[i]);
297 free(chip->sets);
298 chip->sets_count = chip->sets_max = 0;
299
300 for (i = 0; i < chip->computes_count; i++)
301 free_compute(&chip->computes[i]);
302 free(chip->computes);
303 chip->computes_count = chip->computes_max = 0;
304
305 for (i = 0; i < chip->ignores_count; i++)
306 free_ignore(&chip->ignores[i]);
307 free(chip->ignores);
308 chip->ignores_count = chip->ignores_max = 0;
309}
310
311void sensors_cleanup(void)
312{
313 int i;
314
315 for (i = 0; i < sensors_proc_chips_count; i++) {
316 free_chip_name(&sensors_proc_chips[i].chip);
317 free_chip_features(&sensors_proc_chips[i]);
318 }
319 free(sensors_proc_chips);
320 sensors_proc_chips = NULL;
321 sensors_proc_chips_count = sensors_proc_chips_max = 0;
322
323 for (i = 0; i < sensors_config_chips_count; i++)
324 free_chip(&sensors_config_chips[i]);
325 free(sensors_config_chips);
326 sensors_config_chips = NULL;
327 sensors_config_chips_count = sensors_config_chips_max = 0;
328 sensors_config_chips_subst = 0;
329
330 for (i = 0; i < sensors_proc_bus_count; i++)
331 free_bus(&sensors_proc_bus[i]);
332 free(sensors_proc_bus);
333 sensors_proc_bus = NULL;
334 sensors_proc_bus_count = sensors_proc_bus_max = 0;
335
336 for (i = 0; i < sensors_config_files_count; i++)
337 free(sensors_config_files[i]);
338 free(sensors_config_files);
339 sensors_config_files = NULL;
340 sensors_config_files_count = sensors_config_files_max = 0;
341}