Changeset 5678
- Timestamp:
- 03/09/09 16:32:03 (4 years ago)
- Location:
- lm-sensors/trunk/prog/sensord
- Files:
-
- 7 modified
Legend:
- Unmodified
- Added
- Removed
-
lm-sensors/trunk/prog/sensord/args.c
r5163 r5678 52 52 int numChipNames = 0; 53 53 54 static int 55 parseTime 56 (char *arg) { 57 char *end; 58 int value = strtoul (arg, &end, 10); 59 if ((end > arg) && (*end == 's')) { 60 ++ end; 61 } else if ((end > arg) && (*end == 'm')) { 62 value *= 60; 63 ++ end; 64 } else if ((end > arg) && (*end == 'h')) { 65 value *= 60 * 60; 66 ++ end; 67 } 68 if ((end == arg) || *end) { 69 fprintf (stderr, "Error parsing time value `%s'.\n", arg); 70 return -1; 71 } 72 return value; 54 static int parseTime(char *arg) 55 { 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; 73 72 } 74 73 75 74 static struct { 76 const char *name;77 int id;75 const char *name; 76 int id; 78 77 } facilities[] = { 79 { "local0", LOG_LOCAL0 }, { "local1", LOG_LOCAL1 }, 80 { "local2", LOG_LOCAL2 }, { "local3", LOG_LOCAL3 }, 81 { "local4", LOG_LOCAL4 }, { "local5", LOG_LOCAL5 }, 82 { "local6", LOG_LOCAL6 }, { "local7", LOG_LOCAL7 }, 83 { "daemon", LOG_DAEMON }, { "user", LOG_USER }, 84 { NULL, 0 } 78 { "local0", LOG_LOCAL0 }, 79 { "local1", LOG_LOCAL1 }, 80 { "local2", LOG_LOCAL2 }, 81 { "local3", LOG_LOCAL3 }, 82 { "local4", LOG_LOCAL4 }, 83 { "local5", LOG_LOCAL5 }, 84 { "local6", LOG_LOCAL6 }, 85 { "local7", LOG_LOCAL7 }, 86 { "daemon", LOG_DAEMON }, 87 { "user", LOG_USER }, 88 { NULL, 0 } 85 89 }; 86 90 87 static int 88 parseFacility 89 (char *arg) { 90 int i = 0; 91 while (facilities[i].name && strcasecmp (arg, facilities[i].name)) 92 ++ i; 93 if (!facilities[i].name) { 94 fprintf (stderr, "Error parsing facility value `%s'.\n", arg); 95 return -1; 96 } 97 return facilities[i].id; 91 static int parseFacility(char *arg) 92 { 93 int i = 0; 94 while (facilities[i].name && strcasecmp(arg, facilities[i].name)) 95 ++ i; 96 if (!facilities[i].name) { 97 fprintf(stderr, "Error parsing facility value `%s'.\n", arg); 98 return -1; 99 } 100 return facilities[i].id; 98 101 } 99 102 100 103 static const char *daemonSyntax = 101 " -i, --interval <time> -- interval between scanning alarms (default 60s)\n"102 " -l, --log-interval <time> -- interval between logging sensors (default 30m)\n"103 " -t, --rrd-interval <time> -- interval between updating RRD file (default 5m)\n"104 " -T, --rrd-no-average -- switch RRD in non-average mode\n"105 " -r, --rrd-file <file> -- RRD file (default <none>)\n"106 " -c, --config-file <file> -- configuration file\n"107 " -p, --pid-file <file> -- PID file (default /var/run/sensord.pid)\n"108 " -f, --syslog-facility <f> -- syslog facility to use (default local4)\n"109 " -g, --rrd-cgi <img-dir> -- output an RRD CGI script and exit\n"110 " -a, --load-average -- include load average in RRD file\n"111 " -d, --debug -- display some debug information\n"112 " -v, --version -- display version and exit\n"113 " -h, --help -- display help and exit\n"114 "\n"115 "Specify a value of 0 for any interval to disable that operation;\n"116 "for example, specify --log-interval 0 to only scan for alarms."117 "\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";104 " -i, --interval <time> -- interval between scanning alarms (default 60s)\n" 105 " -l, --log-interval <time> -- interval between logging sensors (default 30m)\n" 106 " -t, --rrd-interval <time> -- interval between updating RRD file (default 5m)\n" 107 " -T, --rrd-no-average -- switch RRD in non-average mode\n" 108 " -r, --rrd-file <file> -- RRD file (default <none>)\n" 109 " -c, --config-file <file> -- configuration file\n" 110 " -p, --pid-file <file> -- PID file (default /var/run/sensord.pid)\n" 111 " -f, --syslog-facility <f> -- syslog facility to use (default local4)\n" 112 " -g, --rrd-cgi <img-dir> -- output an RRD CGI script and exit\n" 113 " -a, --load-average -- include load average in RRD file\n" 114 " -d, --debug -- display some debug information\n" 115 " -v, --version -- display version and exit\n" 116 " -h, --help -- display help and exit\n" 117 "\n" 118 "Specify a value of 0 for any interval to disable that operation;\n" 119 "for example, specify --log-interval 0 to only scan for alarms." 120 "\n" 121 "Specify the filename `-' to read the config file from stdin.\n" 122 "\n" 123 "If no chips are specified, all chip info will be printed.\n" 124 "\n" 125 "If unspecified, no RRD (round robin database) is used. If specified and the\n" 126 "file does not exist, it will be created. For RRD updates to be successful,\n" 127 "the RRD file configuration must EXACTLY match the sensors that are used. If\n" 128 "your configuration changes, delete the old RRD file and restart sensord.\n"; 126 129 127 130 static 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\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 "Specify the filename `-' to read the config file from stdin.\n"137 "\n"138 "If no chips are specified, all chip info will be printed.\n";131 " -a, --alarm-scan -- only scan for alarms\n" 132 " -s, --set -- execute set statements (root only)\n" 133 " -r, --rrd-file <file> -- only update RRD file\n" 134 " -c, --config-file <file> -- configuration file\n" 135 " -d, --debug -- display some debug information\n" 136 " -v, --version -- display version and exit\n" 137 " -h, --help -- display help and exit\n" 138 "\n" 139 "Specify the filename `-' to read the config file from stdin.\n" 140 "\n" 141 "If no chips are specified, all chip info will be printed.\n"; 139 142 140 143 static const char *daemonShortOptions = "i:l:t:Tf:r:c:p:advhg:"; 141 144 142 145 static const struct option daemonLongOptions[] = { 143 { "interval", required_argument, NULL, 'i' },144 { "log-interval", required_argument, NULL, 'l' },145 { "rrd-interval", required_argument, NULL, 't' },146 { "rrd-no-average", no_argument, NULL, 'T' },147 { "syslog-facility", required_argument, NULL, 'f' },148 { "rrd-file", required_argument, NULL, 'r' },149 { "config-file", required_argument, NULL, 'c' },150 { "pid-file", required_argument, NULL, 'p' },151 { "rrd-cgi", required_argument, NULL, 'g' },152 { "load-average", no_argument, NULL, 'a' },153 { "debug", no_argument, NULL, 'd' },154 { "version", no_argument, NULL, 'v' },155 { "help", no_argument, NULL, 'h' },156 { NULL, 0, NULL, 0 }146 { "interval", required_argument, NULL, 'i' }, 147 { "log-interval", required_argument, NULL, 'l' }, 148 { "rrd-interval", required_argument, NULL, 't' }, 149 { "rrd-no-average", no_argument, NULL, 'T' }, 150 { "syslog-facility", required_argument, NULL, 'f' }, 151 { "rrd-file", required_argument, NULL, 'r' }, 152 { "config-file", required_argument, NULL, 'c' }, 153 { "pid-file", required_argument, NULL, 'p' }, 154 { "rrd-cgi", required_argument, NULL, 'g' }, 155 { "load-average", no_argument, NULL, 'a' }, 156 { "debug", no_argument, NULL, 'd' }, 157 { "version", no_argument, NULL, 'v' }, 158 { "help", no_argument, NULL, 'h' }, 159 { NULL, 0, NULL, 0 } 157 160 }; 158 161 … … 160 163 161 164 static const struct option appLongOptions[] = { 162 { "alarm-scan", no_argument, NULL, 'a' },163 { "set", no_argument, NULL, 's' },164 { "rrd-file", required_argument, NULL, 'r' },165 { "config-file", required_argument, NULL, 'c' },166 { "debug", no_argument, NULL, 'd' },167 { "version", no_argument, NULL, 'v' },168 { "help", no_argument, NULL, 'h' },169 { NULL, 0, NULL, 0 }165 { "alarm-scan", no_argument, NULL, 'a' }, 166 { "set", no_argument, NULL, 's' }, 167 { "rrd-file", required_argument, NULL, 'r' }, 168 { "config-file", required_argument, NULL, 'c' }, 169 { "debug", no_argument, NULL, 'd' }, 170 { "version", no_argument, NULL, 'v' }, 171 { "help", no_argument, NULL, 'h' }, 172 { NULL, 0, NULL, 0 } 170 173 }; 171 174 172 int 173 parseArgs 174 (int argc, char **argv) { 175 int c; 176 const char *shortOptions; 177 const struct option *longOptions; 178 179 isDaemon = (argv[0][strlen (argv[0]) - 1] == 'd'); 180 shortOptions = isDaemon ? daemonShortOptions : appShortOptions; 181 longOptions = isDaemon ? daemonLongOptions : appLongOptions; 182 183 while ((c = getopt_long (argc, argv, shortOptions, longOptions, NULL)) != EOF) { 184 switch(c) { 185 case 'i': 186 if ((scanTime = parseTime (optarg)) < 0) 187 return -1; 188 break; 189 case 'l': 190 if ((logTime = parseTime (optarg)) < 0) 191 return -1; 192 break; 193 case 't': 194 if ((rrdTime = parseTime (optarg)) < 0) 195 return -1; 196 break; 197 case 'T': 198 rrdNoAverage = 1; 199 break; 200 case 'f': 201 if ((syslogFacility = parseFacility (optarg)) < 0) 202 return -1; 203 break; 204 case 'a': 205 if (isDaemon) 206 doLoad = 1; 207 else 208 doScan = 1; 209 break; 210 case 's': 211 doSet = 1; 212 break; 213 case 'c': 214 sensorsCfgFile = optarg; 215 break; 216 case 'p': 217 pidFile = optarg; 218 break; 219 case 'r': 220 rrdFile = optarg; 221 break; 222 case 'd': 223 debug = 1; 224 break; 225 case 'g': 226 doCGI = 1; 227 cgiDir = optarg; 228 break; 229 case 'v': 230 printf ("sensord version %s\n", LM_VERSION); 231 exit (EXIT_SUCCESS); 232 break; 233 case 'h': 234 printf ("Syntax: %s {options} {chips}\n%s", argv[0], isDaemon ? daemonSyntax : appSyntax); 235 exit (EXIT_SUCCESS); 236 break; 237 case ':': 238 case '?': 239 printf ("Try `%s --help' for more information.\n", argv[0]); 240 return -1; 241 break; 242 default: 243 fprintf (stderr, "Internal error while parsing options.\n"); 244 return -1; 245 break; 246 } 247 } 248 249 if (doScan && doSet) { 250 fprintf (stderr, "Error: Incompatible --set and --alarm-scan.\n"); 251 return -1; 252 } 175 int parseArgs(int argc, char **argv) 176 { 177 int c; 178 const char *shortOptions; 179 const struct option *longOptions; 180 181 isDaemon = (argv[0][strlen (argv[0]) - 1] == 'd'); 182 shortOptions = isDaemon ? daemonShortOptions : appShortOptions; 183 longOptions = isDaemon ? daemonLongOptions : appLongOptions; 184 185 while ((c = getopt_long(argc, argv, shortOptions, longOptions, NULL)) 186 != EOF) { 187 switch(c) { 188 case 'i': 189 if ((scanTime = parseTime(optarg)) < 0) 190 return -1; 191 break; 192 case 'l': 193 if ((logTime = parseTime(optarg)) < 0) 194 return -1; 195 break; 196 case 't': 197 if ((rrdTime = parseTime(optarg)) < 0) 198 return -1; 199 break; 200 case 'T': 201 rrdNoAverage = 1; 202 break; 203 case 'f': 204 if ((syslogFacility = parseFacility(optarg)) < 0) 205 return -1; 206 break; 207 case 'a': 208 if (isDaemon) 209 doLoad = 1; 210 else 211 doScan = 1; 212 break; 213 case 's': 214 doSet = 1; 215 break; 216 case 'c': 217 sensorsCfgFile = optarg; 218 break; 219 case 'p': 220 pidFile = optarg; 221 break; 222 case 'r': 223 rrdFile = optarg; 224 break; 225 case 'd': 226 debug = 1; 227 break; 228 case 'g': 229 doCGI = 1; 230 cgiDir = optarg; 231 break; 232 case 'v': 233 printf("sensord version %s\n", LM_VERSION); 234 exit(EXIT_SUCCESS); 235 break; 236 case 'h': 237 printf("Syntax: %s {options} {chips}\n%s", argv[0], 238 isDaemon ? daemonSyntax : appSyntax); 239 exit(EXIT_SUCCESS); 240 break; 241 case ':': 242 case '?': 243 printf("Try `%s --help' for more information.\n", 244 argv[0]); 245 return -1; 246 break; 247 default: 248 fprintf(stderr, 249 "Internal error while parsing options.\n"); 250 return -1; 251 break; 252 } 253 } 254 255 if (doScan && doSet) { 256 fprintf(stderr, 257 "Error: Incompatible --set and --alarm-scan.\n"); 258 return -1; 259 } 253 260 254 if (rrdFile && doSet) { 255 fprintf (stderr, "Error: Incompatible --set and --rrd-file.\n"); 256 return -1; 257 } 261 if (rrdFile && doSet) { 262 fprintf(stderr, 263 "Error: Incompatible --set and --rrd-file.\n"); 264 return -1; 265 } 258 266 259 if (doScan && rrdFile) { 260 fprintf (stderr, "Error: Incompatible --rrd-file and --alarm-scan.\n"); 261 return -1; 262 } 263 264 if (doCGI && !rrdFile) { 265 fprintf (stderr, "Error: Incompatible --rrd-cgi without --rrd-file.\n"); 266 return -1; 267 } 267 if (doScan && rrdFile) { 268 fprintf(stderr, 269 "Error: Incompatible --rrd-file and --alarm-scan.\n"); 270 return -1; 271 } 272 273 if (doCGI && !rrdFile) { 274 fprintf(stderr, 275 "Error: Incompatible --rrd-cgi without --rrd-file.\n"); 276 return -1; 277 } 268 278 269 if (rrdFile && !rrdTime) { 270 fprintf (stderr, "Error: Incompatible --rrd-file without --rrd-interval.\n"); 271 return -1; 272 } 279 if (rrdFile && !rrdTime) { 280 fprintf(stderr, 281 "Error: Incompatible --rrd-file without --rrd-interval.\n"); 282 return -1; 283 } 273 284 274 if (!logTime && !scanTime && !rrdFile) { 275 fprintf (stderr, "Error: No logging, alarm or RRD scanning.\n"); 276 return -1; 277 } 278 279 return 0; 285 if (!logTime && !scanTime && !rrdFile) { 286 fprintf(stderr, 287 "Error: No logging, alarm or RRD scanning.\n"); 288 return -1; 289 } 290 291 return 0; 280 292 } 281 293 282 int 283 parseChips 284 (int argc, char **argv) { 285 if (optind == argc) { 286 chipNames[0].prefix = SENSORS_CHIP_NAME_PREFIX_ANY; 287 chipNames[0].bus.type = SENSORS_BUS_TYPE_ANY; 288 chipNames[0].bus.nr = SENSORS_BUS_NR_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 return -1; 302 } 303 } 304 numChipNames = n; 305 } 306 return 0; 294 int parseChips(int argc, char **argv) 295 { 296 if (optind == argc) { 297 chipNames[0].prefix = SENSORS_CHIP_NAME_PREFIX_ANY; 298 chipNames[0].bus.type = SENSORS_BUS_TYPE_ANY; 299 chipNames[0].bus.nr = SENSORS_BUS_NR_ANY; 300 chipNames[0].addr = SENSORS_CHIP_NAME_ADDR_ANY; 301 numChipNames = 1; 302 } else { 303 int i, n = argc - optind, err; 304 if (n > MAX_CHIP_NAMES) { 305 fprintf(stderr, "Too many chip names.\n"); 306 return -1; 307 } 308 for (i = 0; i < n; ++ i) { 309 char *arg = argv[optind + i]; 310 if ((err = sensors_parse_chip_name(arg, 311 chipNames + i))) { 312 fprintf(stderr, 313 "Invalid chip name `%s': %s\n", arg, 314 sensors_strerror(err)); 315 return -1; 316 } 317 } 318 numChipNames = n; 319 } 320 return 0; 307 321 } -
lm-sensors/trunk/prog/sensord/chips.c
r5163 r5678 34 34 static char buff[4096]; 35 35 36 static const char * 37 fmtExtra 38 (int alarm, int beep) { 39 if (alarm) 40 sprintf (buff + strlen (buff), " [ALARM]"); 41 if (beep) 42 sprintf (buff + strlen (buff), " (beep)"); 43 return buff; 44 } 45 46 static const char * 47 fmtTemps_1 48 (const double values[], int alarm, int beep) { 49 sprintf (buff, "%.1f C (limit = %.1f C, hysteresis = %.1f C)", values[0], values[1], values[2]); 50 return fmtExtra (alarm, beep); 51 } 52 53 static const char * 54 fmtTemps_minmax_1 55 (const double values[], int alarm, int beep) { 56 sprintf (buff, "%.1f C (min = %.1f C, max = %.1f C)", values[0], values[1], values[2]); 57 return fmtExtra (alarm, beep); 58 } 59 60 static const char * 61 fmtTemp_only 62 (const double values[], int alarm, int beep) { 63 sprintf (buff, "%.1f C", values[0]); 64 return fmtExtra (alarm, beep); 65 } 66 67 static const char * 68 fmtVolt_2 69 (const double values[], int alarm, int beep) { 70 sprintf (buff, "%+.2f V", values[0]); 71 return fmtExtra (alarm, beep); 72 } 73 74 static const char * 75 fmtVolt_3 76 (const double values[], int alarm, int beep) { 77 sprintf (buff, "%+.3f V", values[0]); 78 return fmtExtra (alarm, beep); 79 } 80 81 static const char * 82 fmtVolts_2 83 (const double values[], int alarm, int beep) { 84 sprintf (buff, "%+.2f V (min = %+.2f V, max = %+.2f V)", values[0], values[1], values[2]); 85 return fmtExtra (alarm, beep); 86 } 87 88 static const char * 89 fmtFans_0 90 (const double values[], int alarm, int beep) { 91 sprintf (buff, "%.0f RPM (min = %.0f RPM, div = %.0f)", values[0], values[1], values[2]); 92 return fmtExtra (alarm, beep); 93 } 94 95 static const char * 96 fmtFans_nodiv_0 97 (const double values[], int alarm, int beep) { 98 sprintf (buff, "%.0f RPM (min = %.0f RPM)", values[0], values[1]); 99 return fmtExtra (alarm, beep); 100 } 101 102 static const char * 103 fmtFan_only 104 (const double values[], int alarm, int beep) { 105 sprintf (buff, "%.0f RPM", values[0]); 106 return fmtExtra (alarm, beep); 107 } 108 109 static const char * 110 fmtSoundAlarm 111 (const double values[], int alarm, int beep) { 112 sprintf (buff, "Sound alarm %s", (values[0] < 0.5) ? "disabled" : "enabled"); 113 return fmtExtra (alarm, beep); 114 } 115 116 static const char * 117 rrdF0 118 (const double values[]) { 119 sprintf (buff, "%.0f", values[0]); 120 return buff; 121 } 122 123 static const char * 124 rrdF1 125 (const double values[]) { 126 sprintf (buff, "%.1f", values[0]); 127 return buff; 128 } 129 130 static const char * 131 rrdF2 132 (const double values[]) { 133 sprintf (buff, "%.2f", values[0]); 134 return buff; 135 } 136 137 static const char * 138 rrdF3 139 (const double values[]) { 140 sprintf (buff, "%.3f", values[0]); 141 return buff; 142 } 143 144 static void fillChipVoltage (FeatureDescriptor *voltage, 145 const sensors_chip_name *name, 146 const sensors_feature *feature) 147 { 148 const sensors_subfeature *sf, *sfmin, *sfmax; 149 int pos = 0; 150 151 voltage->rrd = rrdF2; 152 voltage->type = DataType_voltage; 153 154 sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_IN_INPUT); 155 if (sf) 156 voltage->dataNumbers[pos++] = sf->number; 157 158 sfmin = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_IN_MIN); 159 sfmax = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_IN_MAX); 160 if (sfmin && sfmax) { 161 voltage->format = fmtVolts_2; 162 voltage->dataNumbers[pos++] = sfmin->number; 163 voltage->dataNumbers[pos++] = sfmax->number; 164 } else { 165 voltage->format = fmtVolt_2; 166 } 36 static const char *fmtExtra(int alarm, int beep) 37 { 38 if (alarm) 39 sprintf(buff + strlen(buff), " [ALARM]"); 40 if (beep) 41 sprintf(buff + strlen(buff), " (beep)"); 42 return buff; 43 } 44 45 static const char *fmtTemps_1(const double values[], int alarm, int beep) 46 { 47 sprintf(buff, "%.1f C (limit = %.1f C, hysteresis = %.1f C)", 48 values[0], values[1], values[2]); 49 return fmtExtra(alarm, beep); 50 } 51 52 static const char *fmtTemps_minmax_1(const double values[], int alarm, 53 int beep) { 54 sprintf(buff, "%.1f C (min = %.1f C, max = %.1f C)", values[0], 55 values[1], values[2]); 56 return fmtExtra(alarm, beep); 57 } 58 59 static const char *fmtTemp_only(const double values[], int alarm, int beep) 60 { 61 sprintf(buff, "%.1f C", values[0]); 62 return fmtExtra(alarm, beep); 63 } 64 65 static const char *fmtVolt_2(const double values[], int alarm, int beep) 66 { 67 sprintf(buff, "%+.2f V", values[0]); 68 return fmtExtra(alarm, beep); 69 } 70 71 static const char *fmtVolt_3(const double values[], int alarm, int beep) 72 { 73 sprintf(buff, "%+.3f V", values[0]); 74 return fmtExtra(alarm, beep); 75 } 76 77 static const char *fmtVolts_2(const double values[], int alarm, int beep) 78 { 79 sprintf(buff, "%+.2f V (min = %+.2f V, max = %+.2f V)", values[0], 80 values[1], values[2]); 81 return fmtExtra(alarm, beep); 82 } 83 84 static const char *fmtFans_0(const double values[], int alarm, int beep) 85 { 86 sprintf(buff, "%.0f RPM (min = %.0f RPM, div = %.0f)", values[0], 87 values[1], values[2]); 88 return fmtExtra(alarm, beep); 89 } 90 91 static const char *fmtFans_nodiv_0(const double values[], int alarm, int beep) 92 { 93 sprintf(buff, "%.0f RPM (min = %.0f RPM)", values[0], values[1]); 94 return fmtExtra(alarm, beep); 95 } 96 97 static const char *fmtFan_only(const double values[], int alarm, int beep) 98 { 99 sprintf(buff, "%.0f RPM", values[0]); 100 return fmtExtra(alarm, beep); 101 } 102 103 static const char *fmtSoundAlarm(const double values[], int alarm, int beep) 104 { 105 sprintf(buff, "Sound alarm %s", 106 (values[0] < 0.5) ? "disabled" : "enabled"); 107 return fmtExtra(alarm, beep); 108 } 109 110 static const char *rrdF0(const double values[]) 111 { 112 sprintf(buff, "%.0f", values[0]); 113 return buff; 114 } 115 116 static const char *rrdF1(const double values[]) 117 { 118 sprintf(buff, "%.1f", values[0]); 119 return buff; 120 } 121 122 static const char *rrdF2(const double values[]) 123 { 124 sprintf(buff, "%.2f", values[0]); 125 return buff; 126 } 127 128 static const char *rrdF3(const double values[]) 129 { 130 sprintf(buff, "%.3f", values[0]); 131 return buff; 132 } 133 134 static void fillChipVoltage(FeatureDescriptor *voltage, 135 const sensors_chip_name *name, 136 const sensors_feature *feature) 137 { 138 const sensors_subfeature *sf, *sfmin, *sfmax; 139 int pos = 0; 140 141 voltage->rrd = rrdF2; 142 voltage->type = DataType_voltage; 143 144 sf = sensors_get_subfeature(name, feature, 145 SENSORS_SUBFEATURE_IN_INPUT); 146 if (sf) 147 voltage->dataNumbers[pos++] = sf->number; 148 149 sfmin = sensors_get_subfeature(name, feature, 150 SENSORS_SUBFEATURE_IN_MIN); 151 sfmax = sensors_get_subfeature(name, feature, 152 SENSORS_SUBFEATURE_IN_MAX); 153 if (sfmin && sfmax) { 154 voltage->format = fmtVolts_2; 155 voltage->dataNumbers[pos++] = sfmin->number; 156 voltage->dataNumbers[pos++] = sfmax->number; 157 } else { 158 voltage->format = fmtVolt_2; 159 } 167 160 168 /* terminate the list */ 169 voltage->dataNumbers[pos] = -1; 170 171 /* alarm if applicable */ 172 if ((sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_IN_ALARM)) || 173 (sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_IN_MIN_ALARM)) || 174 (sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_IN_MAX_ALARM))) { 175 voltage->alarmNumber = sf->number; 176 } else { 177 voltage->alarmNumber = -1; 178 } 179 /* beep if applicable */ 180 if ((sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_IN_BEEP))) { 181 voltage->beepNumber = sf->number; 182 } else { 183 voltage->beepNumber = -1; 184 } 185 } 186 187 static void fillChipTemperature (FeatureDescriptor *temperature, 188 const sensors_chip_name *name, 189 const sensors_feature *feature) 190 { 191 const sensors_subfeature *sf, *sfmin, *sfmax, *sfhyst; 192 int pos = 0; 193 194 temperature->rrd = rrdF1; 195 temperature->type = DataType_temperature; 196 197 sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_INPUT); 198 if (sf) 199 temperature->dataNumbers[pos++] = sf->number; 200 201 sfmin = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_MIN); 202 sfmax = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_MAX); 203 sfhyst = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_MAX_HYST); 204 if (sfmin && sfmax) { 205 temperature->format = fmtTemps_minmax_1; 206 temperature->dataNumbers[pos++] = sfmin->number; 207 temperature->dataNumbers[pos++] = sfmax->number; 208 } else if (sfmax && sfhyst) { 209 temperature->format = fmtTemps_1; 210 temperature->dataNumbers[pos++] = sfmax->number; 211 temperature->dataNumbers[pos++] = sfhyst->number; 212 } else { 213 temperature->format = fmtTemp_only; 214 } 161 /* terminate the list */ 162 voltage->dataNumbers[pos] = -1; 163 164 /* alarm if applicable */ 165 if ((sf = sensors_get_subfeature(name, feature, 166 SENSORS_SUBFEATURE_IN_ALARM)) || 167 (sf = sensors_get_subfeature(name, feature, 168 SENSORS_SUBFEATURE_IN_MIN_ALARM)) || 169 (sf = sensors_get_subfeature(name, feature, 170 SENSORS_SUBFEATURE_IN_MAX_ALARM))) { 171 voltage->alarmNumber = sf->number; 172 } else { 173 voltage->alarmNumber = -1; 174 } 175 /* beep if applicable */ 176 if ((sf = sensors_get_subfeature(name, feature, 177 SENSORS_SUBFEATURE_IN_BEEP))) { 178 voltage->beepNumber = sf->number; 179 } else { 180 voltage->beepNumber = -1; 181 } 182 } 183 184 static void fillChipTemperature(FeatureDescriptor *temperature, 185 const sensors_chip_name *name, 186 const sensors_feature *feature) 187 { 188 const sensors_subfeature *sf, *sfmin, *sfmax, *sfhyst; 189 int pos = 0; 190 191 temperature->rrd = rrdF1; 192 temperature->type = DataType_temperature; 193 194 sf = sensors_get_subfeature(name, feature, 195 SENSORS_SUBFEATURE_TEMP_INPUT); 196 if (sf) 197 temperature->dataNumbers[pos++] = sf->number; 198 199 sfmin = sensors_get_subfeature(name, feature, 200 SENSORS_SUBFEATURE_TEMP_MIN); 201 sfmax = sensors_get_subfeature(name, feature, 202 SENSORS_SUBFEATURE_TEMP_MAX); 203 sfhyst = sensors_get_subfeature(name, feature, 204 SENSORS_SUBFEATURE_TEMP_MAX_HYST); 205 if (sfmin && sfmax) { 206 temperature->format = fmtTemps_minmax_1; 207 temperature->dataNumbers[pos++] = sfmin->number; 208 temperature->dataNumbers[pos++] = sfmax->number; 209 } else if (sfmax && sfhyst) { 210 temperature->format = fmtTemps_1; 211 temperature->dataNumbers[pos++] = sfmax->number; 212 temperature->dataNumbers[pos++] = sfhyst->number; 213 } else { 214 temperature->format = fmtTemp_only; 215 } 215 216 216 /* terminate the list */ 217 temperature->dataNumbers[pos] = -1; 218 219 /* alarm if applicable */ 220 if ((sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_ALARM)) || 221 (sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_MAX_ALARM))) { 222 temperature->alarmNumber = sf->number; 223 } else { 224 temperature->alarmNumber = -1; 225 } 226 /* beep if applicable */ 227 if ((sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_BEEP))) { 228 temperature->beepNumber = sf->number; 229 } else { 230 temperature->beepNumber = -1; 231 } 232 } 233 234 static void fillChipFan (FeatureDescriptor *fan, 235 const sensors_chip_name *name, 236 const sensors_feature *feature) 237 { 238 const sensors_subfeature *sf, *sfmin, *sfdiv; 239 int pos = 0; 240 241 fan->rrd = rrdF0; 242 fan->type = DataType_rpm; 243 244 sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_FAN_INPUT); 245 if (sf) 246 fan->dataNumbers[pos++] = sf->number; 247 248 sfmin = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_FAN_MIN); 249 if (sfmin) { 250 fan->dataNumbers[pos++] = sfmin->number; 251 sfdiv = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_FAN_DIV); 252 if (sfdiv) { 253 fan->format = fmtFans_0; 254 fan->dataNumbers[pos++] = sfdiv->number; 255 } else { 256 fan->format = fmtFans_nodiv_0; 257 } 258 } else { 259 fan->format = fmtFan_only; 260 } 217 /* terminate the list */ 218 temperature->dataNumbers[pos] = -1; 219 220 /* alarm if applicable */ 221 if ((sf = sensors_get_subfeature(name, feature, 222 SENSORS_SUBFEATURE_TEMP_ALARM)) || 223 (sf = sensors_get_subfeature(name, feature, 224 SENSORS_SUBFEATURE_TEMP_MAX_ALARM))) { 225 temperature->alarmNumber = sf->number; 226 } else { 227 temperature->alarmNumber = -1; 228 } 229 /* beep if applicable */ 230 if ((sf = sensors_get_subfeature(name, feature, 231 SENSORS_SUBFEATURE_TEMP_BEEP))) { 232 temperature->beepNumber = sf->number; 233 } else { 234 temperature->beepNumber = -1; 235 } 236 } 237 238 static void fillChipFan(FeatureDescriptor *fan, 239 const sensors_chip_name *name, 240 const sensors_feature *feature) 241 { 242 const sensors_subfeature *sf, *sfmin, *sfdiv; 243 int pos = 0; 244 245 fan->rrd = rrdF0; 246 fan->type = DataType_rpm; 247 248 sf = sensors_get_subfeature(name, feature, 249 SENSORS_SUBFEATURE_FAN_INPUT); 250 if (sf) 251 fan->dataNumbers[pos++] = sf->number; 252 253 sfmin = sensors_get_subfeature(name, feature, 254 SENSORS_SUBFEATURE_FAN_MIN); 255 if (sfmin) { 256 fan->dataNumbers[pos++] = sfmin->number; 257 sfdiv = sensors_get_subfeature(name, feature, 258 SENSORS_SUBFEATURE_FAN_DIV); 259 if (sfdiv) { 260 fan->format = fmtFans_0; 261 fan->dataNumbers[pos++] = sfdiv->number; 262 } else { 263 fan->format = fmtFans_nodiv_0; 264 } 265 } else { 266 fan->format = fmtFan_only; 267 } 261 268 262 /* terminate the list */ 263 fan->dataNumbers[pos] = -1; 264 265 /* alarm if applicable */ 266 sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_FAN_ALARM); 267 if (sf) { 268 fan->alarmNumber = sf->number; 269 } else { 270 fan->alarmNumber = -1; 271 } 272 /* beep if applicable */ 273 sf = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_FAN_BEEP); 274 if (sf) { 275 fan->beepNumber = sf->number; 276 } else { 277 fan->beepNumber = -1; 278 } 279 } 280 281 static void fillChipVid (FeatureDescriptor *vid, 282 const sensors_chip_name *name, 283 const sensors_feature *feature) 284 { 285 const sensors_subfeature *sub; 286 287 sub = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_VID); 288 if (!sub) 289 return; 290 291 vid->format = fmtVolt_3; 292 vid->rrd = rrdF3; 293 vid->type = DataType_voltage; 294 vid->alarmNumber = -1; 295 vid->beepNumber = -1; 296 vid->dataNumbers[0] = sub->number; 297 vid->dataNumbers[1] = -1; 298 } 299 300 static void fillChipBeepEnable (FeatureDescriptor *beepen, 301 const sensors_chip_name *name, 302 const sensors_feature *feature) 303 { 304 const sensors_subfeature *sub; 305 306 sub = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_BEEP_ENABLE); 307 if (!sub) 308 return; 309 310 beepen->format = fmtSoundAlarm; 311 beepen->rrd = rrdF0; 312 beepen->type = DataType_other; 313 beepen->alarmNumber = -1; 314 beepen->beepNumber = -1; 315 beepen->dataNumbers[0] = sub->number; 316 beepen->dataNumbers[1] = -1; 317 } 318 319 static 320 FeatureDescriptor * generateChipFeatures (const sensors_chip_name *chip) 269 /* terminate the list */ 270 fan->dataNumbers[pos] = -1; 271 272 /* alarm if applicable */ 273 sf = sensors_get_subfeature(name, feature, 274 SENSORS_SUBFEATURE_FAN_ALARM); 275 if (sf) { 276 fan->alarmNumber = sf->number; 277 } else { 278 fan->alarmNumber = -1; 279 } 280 /* beep if applicable */ 281 sf = sensors_get_subfeature(name, feature, 282 SENSORS_SUBFEATURE_FAN_BEEP); 283 if (sf) { 284 fan->beepNumber = sf->number; 285 } else { 286 fan->beepNumber = -1; 287 } 288 } 289 290 static void fillChipVid(FeatureDescriptor *vid, 291 const sensors_chip_name *name, 292 const sensors_feature *feature) 293 { 294 const sensors_subfeature *sub; 295 296 sub = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_VID); 297 if (!sub) 298 return; 299 300 vid->format = fmtVolt_3; 301 vid->rrd = rrdF3; 302 vid->type = DataType_voltage; 303 vid->alarmNumber = -1; 304 vid->beepNumber = -1; 305 vid->dataNumbers[0] = sub->number; 306 vid->dataNumbers[1] = -1; 307 } 308 309 static void fillChipBeepEnable(FeatureDescriptor *beepen, 310 const sensors_chip_name *name, 311 const sensors_feature *feature) 312 { 313 const sensors_subfeature *sub; 314 315 sub = sensors_get_subfeature(name, feature, 316 SENSORS_SUBFEATURE_BEEP_ENABLE); 317 if (!sub) 318 return; 319 320 beepen->format = fmtSoundAlarm; 321 beepen->rrd = rrdF0; 322 beepen->type = DataType_other; 323 beepen->alarmNumber = -1; 324 beepen->beepNumber = -1; 325 beepen->dataNumbers[0] = sub->number; 326 beepen->dataNumbers[1] = -1; 327 } 328 329 static FeatureDescriptor * generateChipFeatures(const sensors_chip_name *chip) 321 330 { 322 331 int nr, count = 1; … … 367 376 ChipDescriptor * knownChips; 368 377 369 int initKnownChips (void)370 { 371 int nr, count = 1;372 const sensors_chip_name *name;373 374 /* How many chips do we have? */375 nr = 0;376 while ((name = sensors_get_detected_chips(NULL, &nr)))377 count++;378 379 /* Allocate the memory we need */380 knownChips = calloc(count, sizeof(ChipDescriptor));381 if (!knownChips)382 return 1;383 384 /* Fill in the data structures */385 count = 0;386 nr = 0;387 while ((name = sensors_get_detected_chips(NULL, &nr))) {388 knownChips[count].name = name;389 if ((knownChips[count].features = generateChipFeatures(name)))390 count++;391 }392 393 return 0;394 } 395 396 void freeKnownChips (void)397 { 398 int index0;399 400 for (index0 = 0; knownChips[index0].features; index0++)401 free(knownChips[index0].features);402 free(knownChips);403 } 378 int initKnownChips(void) 379 { 380 int nr, count = 1; 381 const sensors_chip_name *name; 382 383 /* How many chips do we have? */ 384 nr = 0; 385 while ((name = sensors_get_detected_chips(NULL, &nr))) 386 count++; 387 388 /* Allocate the memory we need */ 389 knownChips = calloc(count, sizeof(ChipDescriptor)); 390 if (!knownChips) 391 return 1; 392 393 /* Fill in the data structures */ 394 count = 0; 395 nr = 0; 396 while ((name = sensors_get_detected_chips(NULL, &nr))) { 397 knownChips[count].name = name; 398 if ((knownChips[count].features = generateChipFeatures(name))) 399 count++; 400 } 401 402 return 0; 403 } 404 405 void freeKnownChips(void) 406 { 407 int index0; 408 409 for (index0 = 0; knownChips[index0].features; index0++) 410 free(knownChips[index0].features); 411 free(knownChips); 412 } -
lm-sensors/trunk/prog/sensord/lib.c
r5163 r5678 33 33 #include "lib/error.h" 34 34 35 static int 36 loadConfig 37 (const char *cfgPath, int reload) { 38 struct stat stats; 39 FILE *cfg = NULL; 40 int ret = 0; 35 static int loadConfig(const char *cfgPath, int reload) 36 { 37 struct stat stats; 38 FILE *cfg = NULL; 39 int ret = 0; 41 40 42 if (cfgPath && !strcmp (cfgPath, "-")) { 43 if (!reload) { 44 if ((ret = sensors_init (stdin))) { 45 sensorLog (LOG_ERR, "Error loading sensors configuration file <stdin>: %s", 46 sensors_strerror (ret)); 47 ret = 12; 48 } 49 } 50 } else if (cfgPath && stat (cfgPath, &stats) < 0) { 51 sensorLog (LOG_ERR, "Error stating sensors configuration file: %s", cfgPath); 52 ret = 10; 53 } else { 54 if (reload) { 55 sensorLog (LOG_INFO, "configuration reloading"); 56 sensors_cleanup (); 57 } 58 if (cfgPath && !(cfg = fopen (cfgPath, "r"))) { 59 sensorLog (LOG_ERR, "Error opening sensors configuration file: %s", cfgPath); 60 ret = 11; 61 } else if ((ret = sensors_init (cfg))) { 62 sensorLog (LOG_ERR, "Error loading sensors configuration file %s: %s", 63 cfgPath ? cfgPath : "(default)", sensors_strerror (ret)); 64 ret = 11; 65 } 66 if (cfg) 67 fclose (cfg); 68 } 41 if (cfgPath && !strcmp(cfgPath, "-")) { 42 if (!reload) { 43 if ((ret = sensors_init(stdin))) { 44 sensorLog(LOG_ERR, 45 "Error loading sensors configuration file <stdin>: %s", 46 sensors_strerror(ret)); 47 ret = 12; 48 } 49 } 50 } else if (cfgPath && stat(cfgPath, &stats) < 0) { 51 sensorLog(LOG_ERR, 52 "Error stating sensors configuration file: %s", 53 cfgPath); 54 ret = 10; 55 } else { 56 if (reload) { 57 sensorLog(LOG_INFO, "configuration reloading"); 58 sensors_cleanup(); 59 } 60 if (cfgPath && !(cfg = fopen(cfgPath, "r"))) { 61 sensorLog(LOG_ERR, 62 "Error opening sensors configuration file: %s", 63 cfgPath); 64 ret = 11; 65 } else if ((ret = sensors_init(cfg))) { 66 sensorLog(LOG_ERR, 67 "Error loading sensors configuration file %s: %s", 68 cfgPath ? cfgPath : "(default)", 69 sensors_strerror(ret)); 70 ret = 11; 71 } 72 if (cfg) 73 fclose(cfg); 74 } 69 75 70 return ret;76 return ret; 71 77 } 72 78 73 int 74 loadLib 75 (const char *cfgPath) { 76 int ret; 77 ret = loadConfig (cfgPath, 0); 78 if (!ret) 79 ret = initKnownChips (); 80 return ret; 79 int loadLib(const char *cfgPath) 80 { 81 int ret; 82 ret = loadConfig(cfgPath, 0); 83 if (!ret) 84 ret = initKnownChips(); 85 return ret; 81 86 } 82 87 83 int 84 reloadLib 85 (const char *cfgPath) { 86 int ret; 87 freeKnownChips (); 88 ret = loadConfig (cfgPath, 1); 89 if (!ret) 90 ret = initKnownChips (); 91 return ret; 88 int reloadLib(const char *cfgPath) 89 { 90 int ret; 91 freeKnownChips(); 92 ret = loadConfig(cfgPath, 1); 93 if (!ret) 94 ret = initKnownChips(); 95 return ret; 92 96 } 93 97 94 int 95 unloadLib 96 (void) { 97 freeKnownChips (); 98 sensors_cleanup (); 99 return 0; 98 int unloadLib(void) 99 { 100 freeKnownChips(); 101 sensors_cleanup(); 102 return 0; 100 103 } -
lm-sensors/trunk/prog/sensord/rrd.c
r5473 r5678 68 68 #define LOAD_AVERAGE "Load Average" 69 69 70 typedef int (*FeatureFN) (void *data, const char *rawLabel, const char *label, const FeatureDescriptor *feature); 71 72 static char 73 rrdNextChar 74 (char c) { 75 if (c == '9') { 76 return 'A'; 77 } else if (c == 'Z') { 78 return 'a'; 79 } else if (c == 'z') { 80 return 0; 81 } else { 82 return c + 1; 83 } 84 } 85 86 static void 87 rrdCheckLabel 88 (const char *rawLabel, int index0) { 89 char *buffer = rrdLabels[index0]; 90 int i, j, okay; 70 typedef int (*FeatureFN) (void *data, const char *rawLabel, const char *label, 71 const FeatureDescriptor *feature); 72 73 static char rrdNextChar(char c) 74 { 75 if (c == '9') { 76 return 'A'; 77 } else if (c == 'Z') { 78 return 'a'; 79 } else if (c == 'z') { 80 return 0; 81 } else { 82 return c + 1; 83 } 84 } 85 86 static void rrdCheckLabel(const char *rawLabel, int index0) 87 { 88 char *buffer = rrdLabels[index0]; 89 int i, j, okay; 91 90 92 i = 0; 93 while ((i < RAW_LABEL_LENGTH) && rawLabel[i]) { /* contrain raw label to [A-Za-z0-9_] */ 94 char c = rawLabel[i]; 95 if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')) || (c == '_')) { 96 buffer[i] = c; 97 } else { 98 buffer[i] = '_'; 99 } 100 ++ i; 101 } 102 buffer[i] = '\0'; 103 104 j = 0; 105 okay = (i > 0); 106 while (okay && (j < index0)) /* locate duplicates */ 107 okay = strcmp (rrdLabels[j ++], buffer); 108 109 while (!okay) { /* uniquify duplicate labels with _? or _?? */ 110 if (!buffer[i]) { 111 if (i > RAW_LABEL_LENGTH - 3) 112 i = RAW_LABEL_LENGTH - 3; 113 buffer[i] = '_'; 114 buffer[i + 1] = '0'; 115 buffer[i + 2] = '\0'; 116 } else if (!buffer[i + 2]) { 117 if (!(buffer[i + 1] = rrdNextChar (buffer[i + 1]))) { 118 buffer[i + 1] = '0'; 119 buffer[i + 2] = '0'; 120 buffer[i + 3] = '\0'; 121 } 122 } else { 123 if (!(buffer[i + 2] = rrdNextChar (buffer[i + 2]))) { 124 buffer[i + 1] = rrdNextChar (buffer[i + 1]); 125 buffer[i + 2] = '0'; 126 } 127 } 128 j = 0; 129 okay = 1; 130 while (okay && (j < index0)) 131 okay = strcmp (rrdLabels[j ++], buffer); 132 } 133 } 134 135 static int 136 applyToFeatures 137 (FeatureFN fn, void *data) { 138 const sensors_chip_name *chip; 139 int i, j, ret = 0, num = 0; 140 141 for (j = 0; (ret == 0) && (j < numChipNames); ++ j) { 142 i = 0; 143 while ((ret == 0) && ((chip = sensors_get_detected_chips (&chipNames[j], &i)) != NULL)) { 144 int index0, chipindex = -1; 145 for (index0 = 0; knownChips[index0].features; ++ index0) 146 /* Trick: we compare addresses here. We know it works because both 147 pointers were returned by sensors_get_detected_chips(), so they 148 refer to libsensors internal structures, which do not move. */ 149 if (knownChips[index0].name == chip) { 150 chipindex = index0; 151 break; 152 } 153 if (chipindex >= 0) { 154 const ChipDescriptor *descriptor = &knownChips[chipindex]; 155 const FeatureDescriptor *features = descriptor->features; 156 157 for (index0 = 0; (ret == 0) && (num < MAX_RRD_SENSORS) && features[index0].format; ++ index0) { 158 const FeatureDescriptor *feature = features + index0; 159 const char *rawLabel = feature->feature->name; 160 char *label = NULL; 161 162 if (!(label = sensors_get_label (chip, feature->feature))) { 163 sensorLog (LOG_ERR, "Error getting sensor label: %s/%s", chip->prefix, rawLabel); 164 ret = -1; 165 } else { 166 rrdCheckLabel (rawLabel, num); 167 ret = fn (data, rrdLabels[num], label, feature); 168 ++ num; 169 } 170 if (label) 171 free (label); 172 } 173 } 174 } 175 } 176 177 return ret; 91 i = 0; 92 /* contrain raw label to [A-Za-z0-9_] */ 93 while ((i < RAW_LABEL_LENGTH) && rawLabel[i]) { 94 char c = rawLabel[i]; 95 if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) 96 || ((c >= '0') && (c <= '9')) || (c == '_')) { 97 buffer[i] = c; 98 } else { 99 buffer[i] = '_'; 100 } 101 ++ i; 102 } 103 buffer[i] = '\0'; 104 105 j = 0; 106 okay = (i > 0); 107 108 /* locate duplicates */ 109 while (okay && (j < index0)) 110 okay = strcmp(rrdLabels[j ++], buffer); 111 112 /* uniquify duplicate labels with _? or _?? */ 113 while (!okay) { 114 if (!buffer[i]) { 115 if (i > RAW_LABEL_LENGTH - 3) 116 i = RAW_LABEL_LENGTH - 3; 117 buffer[i] = '_'; 118 buffer[i + 1] = '0'; 119 buffer[i + 2] = '\0'; 120 } else if (!buffer[i + 2]) { 121 if (!(buffer[i + 1] = rrdNextChar(buffer[i + 1]))) { 122 buffer[i + 1] = '0'; 123 buffer[i + 2] = '0'; 124 buffer[i + 3] = '\0'; 125 } 126 } else { 127 if (!(buffer[i + 2] = rrdNextChar(buffer[i + 2]))) { 128 buffer[i + 1] = rrdNextChar(buffer[i + 1]); 129 buffer[i + 2] = '0'; 130 } 131 } 132 j = 0; 133 okay = 1; 134 while (okay && (j < index0)) 135 okay = strcmp(rrdLabels[j ++], buffer); 136 } 137 } 138 139 static int applyToFeatures(FeatureFN fn, void *data) 140 { 141 const sensors_chip_name *chip; 142 int i, j, ret = 0, num = 0; 143 144 for (j = 0; (ret == 0) && (j < numChipNames); ++ j) { 145 i = 0; 146 while ((ret == 0) && ((chip = sensors_get_detected_chips(&chipNames[j], &i)) != NULL)) { 147 int index0, chipindex = -1; 148 149 /* Trick: we compare addresses here. We know it works 150 * because both pointers were returned by 151 * sensors_get_detected_chips(), so they refer to 152 * libsensors internal structures, which do not move. 153 */ 154 for (index0 = 0; knownChips[index0].features; ++index0) 155 if (knownChips[index0].name == chip) { 156 chipindex = index0; 157 break; 158 } 159 if (chipindex >= 0) { 160 const ChipDescriptor *descriptor = &knownChips[chipindex]; 161 const FeatureDescriptor *features = descriptor->features; 162 163 for (index0 = 0; (ret == 0) && (num < MAX_RRD_SENSORS) && features[index0].format; ++index0) { 164 const FeatureDescriptor *feature = features + index0; 165 const char *rawLabel = feature->feature->name; 166 char *label = NULL; 167 168 if (!(label = sensors_get_label(chip, feature->feature))) { 169 sensorLog(LOG_ERR, "Error getting sensor label: %s/%s", chip->prefix, rawLabel); 170 ret = -1; 171 } else { 172 rrdCheckLabel(rawLabel, num); 173 ret = fn(data, 174 rrdLabels[num], 175 label, feature); 176 ++ num; 177 } 178 if (label) 179 free(label); 180 } 181 } 182 } 183 } 184 return ret; 178 185 } 179 186 180 187 struct ds { 181 int num;182 const char **argv;188 int num; 189 const char **argv; 183 190 }; 184 191 185 static int 186 rrdGetSensors_DS 187 (void *_data, const char *rawLabel, const char *label, const FeatureDescriptor *feature) { 188 (void) label; /* no warning */ 189 if (!feature || feature->rrd) { 190 struct ds *data = (struct ds *) _data; 191 char *ptr = rrdBuff + data->num * RRD_BUFF; 192 const char *min, *max; 193 data->argv[data->num ++] = ptr; 194 switch (feature ? feature->type : DataType_other) { /* arbitrary sanity limits */ 195 case DataType_voltage: 196 min="-25"; 197 max="25"; 198 break; 199 case DataType_rpm: 200 min = "0"; 201 max = "12000"; 202 break; 203 case DataType_temperature: 204 min = "-100"; 205 max = "250"; 206 break; 207 default: 208 min = max = "U"; 209 break; 210 } 211 sprintf (ptr, "DS:%s:GAUGE:%d:%s:%s", rawLabel, /* number of seconds downtime during which average be used instead of unknown */ 5 * rrdTime, min, max); 212 } 213 return 0; 214 } 215 216 static int 217 rrdGetSensors 218 (const char **argv) { 219 int ret = 0; 220 struct ds data = { 0, argv}; 221 ret = applyToFeatures (rrdGetSensors_DS, &data); 222 if (!ret && doLoad) 223 ret = rrdGetSensors_DS (&data, LOADAVG, LOAD_AVERAGE, NULL); 224 return ret ? -1 : data.num; 225 } 226 227 int 228 rrdInit 229 (void) { 230 int ret = 0; 231 struct stat tmp; 192 static int rrdGetSensors_DS(void *_data, const char *rawLabel, 193 const char *label, 194 const FeatureDescriptor *feature) 195 { 196 (void) label; /* no warning */ 197 if (!feature || feature->rrd) { 198 struct ds *data = (struct ds *) _data; 199 char *ptr = rrdBuff + data->num * RRD_BUFF; 200 const char *min, *max; 201 data->argv[data->num ++] = ptr; 202 203 /* arbitrary sanity limits */ 204 switch (feature ? feature->type : DataType_other) { 205 case DataType_voltage: 206 min="-25"; 207 max="25"; 208 break; 209 case DataType_rpm: 210 min = "0"; 211 max = "12000"; 212 break; 213 case DataType_temperature: 214 min = "-100"; 215 max = "250"; 216 break; 217 default: 218 min = max = "U"; 219 break; 220 } 221 222 /* 223 * number of seconds downtime during which average be used 224 * instead of unknown 225 */ 226 sprintf(ptr, "DS:%s:GAUGE:%d:%s:%s", rawLabel, 5 * rrdTime, 227 min, max); 228 } 229 return 0; 230 } 231 232 static int rrdGetSensors(const char **argv) 233 { 234 int ret = 0; 235 struct ds data = { 0, argv}; 236 ret = applyToFeatures(rrdGetSensors_DS, &data); 237 if (!ret && doLoad) 238 ret = rrdGetSensors_DS(&data, LOADAVG, LOAD_AVERAGE, NULL); 239 return ret ? -1 : data.num; 240 } 241 242 int rrdInit(void) 243 { 244 int ret = 0; 245 struct stat tmp; 232 246 233 sensorLog (LOG_DEBUG, "sensor RRD init"); 234 if (stat(rrdFile, &tmp)) {235 if (errno == ENOENT) {236 char stepBuff[STEP_BUFF], rraBuff[RRA_BUFF];237 int argc = 4, num;238 const char *argv[6 + MAX_RRD_SENSORS] = {239 "sensord", rrdFile, "-s", stepBuff240 };247 sensorLog(LOG_DEBUG, "sensor RRD init"); 248 if (stat(rrdFile, &tmp)) { 249 if (errno == ENOENT) { 250 char stepBuff[STEP_BUFF], rraBuff[RRA_BUFF]; 251 int argc = 4, num; 252 const char *argv[6 + MAX_RRD_SENSORS] = { 253 "sensord", rrdFile, "-s", stepBuff 254 }; 241 255 242 sensorLog (LOG_INFO, "creating round robin database"); 243 num = rrdGetSensors (argv + argc); 244 if (num == 0) { 245 sensorLog (LOG_ERR, "Error creating RRD: %s: %s", rrdFile, "No sensors detected"); 246 ret = 2; 247 } else if (num < 0) { 248 ret = -num; 249 } else { 250 sprintf (stepBuff, "%d", rrdTime); 251 sprintf (rraBuff, "RRA:%s:%f:%d:%d", rrdNoAverage?"LAST":"AVERAGE", 0.5 /* fraction of non-unknown samples needed per entry */, 1 /* samples per entry */, 7 * 24 * 60 * 60 / rrdTime /* 1 week */); 252 argc += num; 253 argv[argc ++] = rraBuff; 254 argv[argc] = NULL; 255 if ((ret = rrd_create (argc, (char **) /* WEAK */ argv))) { 256 sensorLog (LOG_ERR, "Error creating RRD file: %s: %s", rrdFile, rrd_get_error ()); 257 } 258 } 259 } else { 260 sensorLog (LOG_ERR, "Error stat()ing RRD: %s: %s", rrdFile, strerror (errno)); 261 ret = 1; 262 } 263 } 264 sensorLog (LOG_DEBUG, "sensor RRD inited"); 256 sensorLog(LOG_INFO, "creating round robin database"); 257 num = rrdGetSensors(argv + argc); 258 if (num == 0) { 259 sensorLog(LOG_ERR, 260 "Error creating RRD: %s: %s", 261 rrdFile, "No sensors detected"); 262 ret = 2; 263 } else if (num < 0) { 264 ret = -num; 265 } else { 266 sprintf(stepBuff, "%d", rrdTime); 267 sprintf(rraBuff, "RRA:%s:%f:%d:%d", 268 rrdNoAverage?"LAST":"AVERAGE", 269 0.5 /* fraction of non-unknown samples needed per entry */, 270 1 /* samples per entry */, 271 7 * 24 * 60 * 60 / rrdTime /* 1 week */); 272 argc += num; 273 argv[argc ++] = rraBuff; 274 argv[argc] = NULL; 275 if ((ret = rrd_create(argc, 276 (char **) /* WEAK */ argv))) { 277 sensorLog(LOG_ERR, 278 "Error creating RRD file: %s: %s", 279 rrdFile, rrd_get_error()); 280 } 281 } 282 } else { 283 sensorLog(LOG_ERR, "Error stat()ing RRD: %s: %s", 284 rrdFile, strerror(errno)); 285 ret = 1; 286 } 287 } 288 sensorLog(LOG_DEBUG, "sensor RRD inited"); 265 289 266 return ret;290 return ret; 267 291 } 268 292 … … 271 295 272 296 struct gr { 273 DataType type;274 const char *h2;275 const char *image;276 const char *title;277 const char *axisTitle;278 const char *axisDefn;279 const char *options;280 int loadAvg;297 DataType type; 298 const char *h2; 299 const char *image; 300 const char *title; 301 const char *axisTitle; 302 const char *axisDefn; 303 const char *options; 304 int loadAvg; 281 305 }; 282 306 283 static int 284 rrdCGI_DEF 285 (void *_data, const char *rawLabel, const char *label, const FeatureDescriptor *feature) { 286 struct gr *data = (struct gr *) _data; 287 (void) label; /* no warning */ 288 if (!feature || (feature->rrd && (feature->type == data->type))) 289 printf ("\n\tDEF:%s=%s:%s:AVERAGE", rawLabel, rrdFile, rawLabel); 290 return 0; 291 } 292 293 /* Compute an arbitrary color based on the sensor label. This is preferred 294 over a random value because this guarantees that daily and weekly charts 295 will use the same colors. */ 296 static int 297 rrdCGI_color 298 (const char *label) { 299 unsigned long color = 0, brightness; 300 const char *c; 301 302 for (c = label; *c; c++) { 303 color = (color << 6) + (color >> (*c & 7)); 304 color ^= (*c) * 0x401; 305 } 306 color &= 0xffffff; 307 /* Adjust very light colors */ 308 brightness = (color & 0xff) + ((color >> 8) & 0xff) + (color >> 16); 309 if (brightness > 672) 310 color &= 0x7f7f7f; 311 /* Adjust very dark colors */ 312 else if (brightness < 96) 313 color |= 0x808080; 314 return color; 315 } 316 317 static int 318 rrdCGI_LINE 319 (void *_data, const char *rawLabel, const char *label, const FeatureDescriptor *feature) { 320 struct gr *data = (struct gr *) _data; 321 if (!feature || (feature->rrd && (feature->type == data->type))) 322 printf ("\n\tLINE2:%s#%.6x:\"%s\"", rawLabel, rrdCGI_color(label), label); 323 return 0; 307 static int rrdCGI_DEF(void *_data, const char *rawLabel, const char *label, 308 const FeatureDescriptor *feature) 309 { 310 struct gr *data = (struct gr *) _data; 311 (void) label; /* no warning */ 312 if (!feature || (feature->rrd && (feature->type == data->type))) 313 printf("\n\tDEF:%s=%s:%s:AVERAGE", rawLabel, rrdFile, 314 rawLabel); 315 return 0; 316 } 317 318 /* 319 * Compute an arbitrary color based on the sensor label. This is preferred 320 * over a random value because this guarantees that daily and weekly charts 321 * will use the same colors. 322 */ 323 static int rrdCGI_color(const char *label) 324 { 325 unsigned long color = 0, brightness; 326 const char *c; 327 328 for (c = label; *c; c++) { 329 color = (color << 6) + (color >> (*c & 7)); 330 color ^= (*c) * 0x401; 331 } 332 color &= 0xffffff; 333 /* Adjust very light colors */ 334 brightness = (color & 0xff) + ((color >> 8) & 0xff) + (color >> 16); 335 if (brightness > 672) 336 color &= 0x7f7f7f; 337 /* Adjust very dark colors */ 338 else if (brightness < 96) 339 color |= 0x808080; 340 return color; 341 } 342 343 static int rrdCGI_LINE(void *_data, const char *rawLabel, const char *label, 344 const FeatureDescriptor *feature) 345 { 346 struct gr *data = (struct gr *) _data; 347 if (!feature || (feature->rrd && (feature->type == data->type))) 348 printf("\n\tLINE2:%s#%.6x:\"%s\"", rawLabel, 349 rrdCGI_color(label), label); 350 return 0; 324 351 } 325 352 326 353 static struct gr graphs[] = { 327 {328 DataType_temperature,329 "Daily Temperature Summary",330 "daily-temperature",331 "Temperature",332 "Temperature (C)",333 "HOUR:1:HOUR:3:HOUR:3:0:%b %d %H:00",334 "-s -1d -l 0",335 1336 }, {337 DataType_rpm,338 "Daily Fan Speed Summary",339 "daily-rpm",340 "Fan Speed",341 "Speed (RPM)",342 "HOUR:1:HOUR:3:HOUR:3:0:%b %d %H:00",343 "-s -1d -l 0",344 0345 }, {346 DataType_voltage,347 "Daily Voltage Summary",348 "daily-voltage",349 "Power Supply",350 "Voltage (V)",351 "HOUR:1:HOUR:3:HOUR:3:0:%b %d %H:00",352 "-s -1d --alt-autoscale",353 0354 }, {355 DataType_temperature,356 "Weekly Temperature Summary",357 "weekly-temperature",358 "Temperature",359 "Temperature (C)",360 "HOUR:6:DAY:1:DAY:1:86400:%a %b %d",361 "-s -1w -l 0",362 1363 }, {364 DataType_rpm,365 "Weekly Fan Speed Summary",366 "weekly-rpm",367 "Fan Speed",368 "Speed (RPM)",369 "HOUR:6:DAY:1:DAY:1:86400:%a %b %d",370 "-s -1w -l 0",371 0372 }, {373 DataType_voltage,374 "Weekly Voltage Summary",375 "weekly-voltage",376 "Power Supply",377 "Voltage (V)",378 "HOUR:6:DAY:1:DAY:1:86400:%a %b %d",379 "-s -1w --alt-autoscale",380 0381 }, {382 DataType_other,383 NULL,384 NULL,385 NULL,386 NULL,387 NULL,388 NULL,389 0390 } 354 { 355 DataType_temperature, 356 "Daily Temperature Summary", 357 "daily-temperature", 358 "Temperature", 359 "Temperature (C)", 360 "HOUR:1:HOUR:3:HOUR:3:0:%b %d %H:00", 361 "-s -1d -l 0", 362 1 363 }, { 364 DataType_rpm, 365 "Daily Fan Speed Summary", 366 "daily-rpm", 367 "Fan Speed", 368 "Speed (RPM)", 369 "HOUR:1:HOUR:3:HOUR:3:0:%b %d %H:00", 370 "-s -1d -l 0", 371 0 372 }, { 373 DataType_voltage, 374 "Daily Voltage Summary", 375 "daily-voltage", 376 "Power Supply", 377 "Voltage (V)", 378 "HOUR:1:HOUR:3:HOUR:3:0:%b %d %H:00", 379 "-s -1d --alt-autoscale", 380 0 381 }, { 382 DataType_temperature, 383 "Weekly Temperature Summary", 384 "weekly-temperature", 385 "Temperature", 386 "Temperature (C)", 387 "HOUR:6:DAY:1:DAY:1:86400:%a %b %d", 388 "-s -1w -l 0", 389 1 390 }, { 391 DataType_rpm, 392 "Weekly Fan Speed Summary", 393 "weekly-rpm", 394 "Fan Speed", 395 "Speed (RPM)", 396 "HOUR:6:DAY:1:DAY:1:86400:%a %b %d", 397 "-s -1w -l 0", 398 0 399 }, { 400 DataType_voltage, 401 "Weekly Voltage Summary", 402 "weekly-voltage", 403 "Power Supply", 404 "Voltage (V)", 405 "HOUR:6:DAY:1:DAY:1:86400:%a %b %d", 406 "-s -1w --alt-autoscale", 407 0 408 }, { 409 DataType_other, 410 NULL, 411 NULL, 412 NULL, 413 NULL, 414 NULL, 415 NULL, 416 0 417 } 391 418 }; 392 419 393 int 394 rrdUpdate 395 (void) { 396 int ret = rrdChips (); 397 if (!ret && doLoad) { 398 FILE *loadavg; 399 if (!(loadavg = fopen ("/proc/loadavg", "r"))) { 400 sensorLog (LOG_ERR, "Error opening `/proc/loadavg': %s", strerror (errno)); 401 ret = 1; 402 } else { 403 float value; 404 if (fscanf (loadavg, "%f", &value) != 1) { 405 sensorLog (LOG_ERR, "Error reading load average"); 406 ret = 2; 407 } else { 408 sprintf (rrdBuff + strlen (rrdBuff), ":%f", value); 409 } 410 fclose (loadavg); 411 } 412 } 413 if (!ret) { 414 const char *argv[] = { 415 "sensord", rrdFile, rrdBuff, NULL 416 }; 417 if ((ret = rrd_update (3, (char **) /* WEAK */ argv))) { 418 sensorLog (LOG_ERR, "Error updating RRD file: %s: %s", rrdFile, rrd_get_error ()); 419 } 420 } 421 sensorLog (LOG_DEBUG, "sensor rrd updated"); 420 int rrdUpdate(void) 421 { 422 int ret = rrdChips (); 423 if (!ret && doLoad) { 424 FILE *loadavg; 425 if (!(loadavg = fopen("/proc/loadavg", "r"))) { 426 sensorLog(LOG_ERR, 427 "Error opening `/proc/loadavg': %s", 428 strerror(errno)); 429 ret = 1; 430 } else { 431 float value; 432 if (fscanf(loadavg, "%f", &value) != 1) { 433 sensorLog(LOG_ERR, 434 "Error reading load average"); 435 ret = 2; 436 } else { 437 sprintf(rrdBuff + strlen(rrdBuff), ":%f", 438 value); 439 } 440 fclose(loadavg); 441 } 442 } 443 if (!ret) { 444 const char *argv[] = { 445 "sensord", rrdFile, rrdBuff, NULL 446 }; 447 if ((ret = rrd_update(3, (char **) /* WEAK */ argv))) { 448 sensorLog(LOG_ERR, "Error updating RRD file: %s: %s", 449 rrdFile, rrd_get_error()); 450 } 451 } 452 sensorLog(LOG_DEBUG, "sensor rrd updated"); 422 453 423 return ret; 424 } 425 426 int 427 rrdCGI 428 (void) { 429 int ret = 0; 430 struct gr *graph = graphs; 431 432 printf ("#!" RRDCGI "\n\n<HTML>\n<HEAD>\n<TITLE>sensord</TITLE>\n</HEAD>\n<BODY>\n<H1>sensord</H1>\n"); 433 while (graph->type != DataType_other) { 434 printf ("<H2>%s</H2>\n", graph->h2); 435 printf ("<P>\n<RRD::GRAPH %s/%s.png\n\t--imginfo '<IMG SRC=" WWWDIR "/%%s WIDTH=%%lu HEIGHT=%%lu>'\n\t-a PNG\n\t-h 200 -w 800\n", cgiDir, graph->image); 436 printf ("\t--lazy\n\t-v '%s'\n\t-t '%s'\n\t-x '%s'\n\t%s", graph->axisTitle, graph->title, graph->axisDefn, graph->options); 437 if (!ret) 438 ret = applyToFeatures (rrdCGI_DEF, graph); 439 if (!ret && doLoad && graph->loadAvg) 440 ret = rrdCGI_DEF (graph, LOADAVG, LOAD_AVERAGE, NULL); 441 if (!ret) 442 ret = applyToFeatures (rrdCGI_LINE, graph); 443 if (!ret && doLoad && graph->loadAvg) 444 ret = rrdCGI_LINE (graph, LOADAVG, LOAD_AVERAGE, NULL); 445 printf (">\n</P>\n"); 446 ++ graph; 447 } 448 printf ("<p>\n<small><b>sensord</b> by <a href=\"mailto:merlin@merlin.org\">Merlin Hughes</a>, all credit to the <a href=\"http://www.lm-sensors.org/\">lm_sensors</a> crew.</small>\n</p>\n"); 449 printf ("</BODY>\n</HTML>\n"); 454 return ret; 455 } 456 457 int rrdCGI(void) 458 { 459 int ret = 0; 460 struct gr *graph = graphs; 461 462 printf("#!" RRDCGI "\n\n<HTML>\n<HEAD>\n<TITLE>sensord</TITLE>\n</HEAD>\n<BODY>\n<H1>sensord</H1>\n"); 463 while (graph->type != DataType_other) { 464 printf("<H2>%s</H2>\n", graph->h2); 465 printf("<P>\n<RRD::GRAPH %s/%s.png\n\t--imginfo '<IMG SRC=" WWWDIR "/%%s WIDTH=%%lu HEIGHT=%%lu>'\n\t-a PNG\n\t-h 200 -w 800\n", 466 cgiDir, graph->image); 467 printf("\t--lazy\n\t-v '%s'\n\t-t '%s'\n\t-x '%s'\n\t%s", 468 graph->axisTitle, graph->title, graph->axisDefn, 469 graph->options); 470 if (!ret) 471 ret = applyToFeatures(rrdCGI_DEF, graph); 472 if (!ret && doLoad && graph->loadAvg) 473 ret = rrdCGI_DEF(graph, LOADAVG, LOAD_AVERAGE, NULL); 474 if (!ret) 475 ret = applyToFeatures(rrdCGI_LINE, graph); 476 if (!ret && doLoad && graph->loadAvg) 477 ret = rrdCGI_LINE(graph, LOADAVG, LOAD_AVERAGE, NULL); 478 printf (">\n</P>\n"); 479 ++ graph; 480 } 481 printf("<p>\n<small><b>sensord</b> by <a href=\"mailto:merlin@merlin.org\">Merlin Hughes</a>, all credit to the <a href=\"http://www.lm-sensors.org/\">lm_sensors</a> crew.</small>\n</p>\n"); 482 printf("</BODY>\n</HTML>\n"); 450 483 451 return ret;452 } 484 return ret; 485 } -
lm-sensors/trunk/prog/sensord/sense.c
r5252 r5678 35 35 #define DO_RRD 3 36 36 37 static const char * 38 chipName 39 (const sensors_chip_name *chip) { 40 static char buffer[256]; 41 if (sensors_snprintf_chip_name(buffer, 256, chip) < 0) 42 return NULL; 43 return buffer; 44 } 45 46 static int 47 idChip 48 (const sensors_chip_name *chip) { 49 const char *adapter; 50 51 sensorLog (LOG_INFO, "Chip: %s", chipName (chip)); 52 adapter = sensors_get_adapter_name (&chip->bus); 53 if (adapter) 54 sensorLog (LOG_INFO, "Adapter: %s", adapter); 55 56 return 0; 57 } 58 59 static int 60 doKnownChip 61 (const sensors_chip_name *chip, const ChipDescriptor *descriptor, int action) { 62 const FeatureDescriptor *features = descriptor->features; 63 int index0, subindex; 64 int ret = 0; 65 double tmp; 66 67 if (action == DO_READ) 68 ret = idChip (chip); 69 for (index0 = 0; (ret == 0) && features[index0].format; ++ index0) { 70 const FeatureDescriptor *feature = features + index0; 71 int alarm, beep; 72 char *label = NULL; 73 74 if (!(label = sensors_get_label (chip, feature->feature))) { 75 sensorLog (LOG_ERR, "Error getting sensor label: %s/%s", chip->prefix, feature->feature->name); 76 ret = 22; 77 } else { 78 double values[MAX_DATA]; 79 80 alarm = 0; 81 if (!ret && feature->alarmNumber != -1) { 82 if ((ret = sensors_get_value (chip, feature->alarmNumber, &tmp))) { 83 sensorLog (LOG_ERR, "Error getting sensor data: %s/#%d: %s", chip->prefix, feature->alarmNumber, sensors_strerror (ret)); 84 ret = 20; 85 } else { 86 alarm = (int) (tmp + 0.5); 87 } 88 } 89 if ((action == DO_SCAN) && !alarm) 90 continue; 91 92 beep = 0; 93 if (!ret && feature->beepNumber != -1) { 94 if ((ret = sensors_get_value (chip, feature->beepNumber, &tmp))) { 95 sensorLog (LOG_ERR, "Error getting sensor data: %s/#%d: %s", chip->prefix, feature->beepNumber, sensors_strerror (ret)); 96 ret = 21; 97 } else { 98 beep = (int) (tmp + 0.5); 99 } 100 } 101 102 for (subindex = 0; !ret && (feature->dataNumbers[subindex] >= 0); ++ subindex) { 103 if ((ret = sensors_get_value (chip, feature->dataNumbers[subindex], values + subindex))) { 104 sensorLog (LOG_ERR, "Error getting sensor data: %s/#%d: %s", chip->prefix, feature->dataNumbers[subindex], sensors_strerror (ret)); 105 ret = 23; 106 } 107 } 108 if (ret == 0) { 109 if (action == DO_RRD) { // arse = "N:" 110 if (feature->rrd) { 111 const char *rrded = feature->rrd (values); 112 strcat (strcat (rrdBuff, ":"), rrded ? rrded : "U"); 113 } 114 } else { 115 const char *formatted = feature->format (values, alarm, beep); 116 if (formatted) { 117 if (action == DO_READ) { 118 sensorLog (LOG_INFO, " %s: %s", label, formatted); 119 } else { 120 sensorLog (LOG_ALERT, "Sensor alarm: Chip %s: %s: %s", chipName (chip), label, formatted); 121 } 122 } 123 } 124 } 125 } 126 if (label) 127 free (label); 128 } 129 return ret; 130 } 131 132 static int 133 setChip 134 (const sensors_chip_name *chip) { 135 int ret = 0; 136 if ((ret = idChip (chip))) { 137 sensorLog (LOG_ERR, "Error identifying chip: %s", chip->prefix); 138 } else if ((ret = sensors_do_chip_sets (chip))) { 139 sensorLog (LOG_ERR, "Error performing chip sets: %s: %s", chip->prefix, sensors_strerror (ret)); 140 ret = 50; 141 } else { 142 sensorLog (LOG_INFO, "Set."); 143 } 144 return ret; 145 } 146 147 static int 148 doChip 149 (const sensors_chip_name *chip, int action) { 150 int ret = 0; 151 if (action == DO_SET) { 152 ret = setChip (chip); 153 } else { 154 int index0, chipindex = -1; 155 for (index0 = 0; knownChips[index0].features; ++ index0) 156 /* Trick: we compare addresses here. We know it works because both 157 pointers were returned by sensors_get_detected_chips(), so they 158 refer to libsensors internal structures, which do not move. */ 159 if (knownChips[index0].name == chip) { 160 chipindex = index0; 161 break; 162 } 163 if (chipindex >= 0) 164 ret = doKnownChip (chip, &knownChips[chipindex], action); 165 } 166 return ret; 167 } 168 169 static int 170 doChips 171 (int action) { 172 const sensors_chip_name *chip; 173 int i, j, ret = 0; 174 175 for (j = 0; (ret == 0) && (j < numChipNames); ++ j) { 176 i = 0; 177 while ((ret == 0) && ((chip = sensors_get_detected_chips (&chipNames[j], &i)) != NULL)) { 178 ret = doChip (chip, action); 179 } 180 } 181 182 return ret; 183 } 184 185 int 186 readChips 187 (void) { 188 int ret = 0; 189 190 sensorLog (LOG_DEBUG, "sensor read started"); 191 ret = doChips (DO_READ); 192 sensorLog (LOG_DEBUG, "sensor read finished"); 193 194 return ret; 195 } 196 197 int 198 scanChips 199 (void) { 200 int ret = 0; 201 202 sensorLog (LOG_DEBUG, "sensor sweep started"); /* only logged in debug mode */ 203 ret = doChips (DO_SCAN); 204 sensorLog (LOG_DEBUG, "sensor sweep finished"); 205 206 return ret; 207 } 208 209 int 210 setChips 211 (void) { 212 int ret = 0; 213 214 sensorLog (LOG_DEBUG, "sensor set started"); 215 ret = doChips (DO_SET); 216 sensorLog (LOG_DEBUG, "sensor set finished"); 217 218 return ret; 37 static const char *chipName(const sensors_chip_name *chip) 38 { 39 static char buffer[256]; 40 if (sensors_snprintf_chip_name(buffer, 256, chip) < 0) 41 return NULL; 42 return buffer; 43 } 44 45 static int idChip(const sensors_chip_name *chip) 46 { 47 const char *adapter; 48 49 sensorLog(LOG_INFO, "Chip: %s", chipName (chip)); 50 adapter = sensors_get_adapter_name(&chip->bus); 51 if (adapter) 52 sensorLog(LOG_INFO, "Adapter: %s", adapter); 53 54 return 0; 55 } 56 57 static int doKnownChip(const sensors_chip_name *chip, 58 const ChipDescriptor *descriptor, int action) 59 { 60 const FeatureDescriptor *features = descriptor->features; 61 int index0, subindex; 62 int ret = 0; 63 double tmp; 64 65 if (action == DO_READ) 66 ret = idChip(chip); 67 for (index0 = 0; (ret == 0) && features[index0].format; ++ index0) { 68 const FeatureDescriptor *feature = features + index0; 69 int alarm, beep; 70 char *label = NULL; 71 72 if (!(label = sensors_get_label(chip, feature->feature))) { 73 sensorLog(LOG_ERR, 74 "Error getting sensor label: %s/%s", 75 chip->prefix, feature->feature->name); 76 ret = 22; 77 } else { 78 double values[MAX_DATA]; 79 80 alarm = 0; 81 if (!ret && feature->alarmNumber != -1) { 82 if ((ret = sensors_get_value(chip, 83 feature->alarmNumber, 84 &tmp))) { 85 sensorLog(LOG_ERR, 86 "Error getting sensor data: %s/#%d: %s", 87 chip->prefix, 88 feature->alarmNumber, 89 sensors_strerror(ret)); 90 ret = 20; 91 } else { 92 alarm = (int) (tmp + 0.5); 93 } 94 } 95 if ((action == DO_SCAN) && !alarm) 96 continue; 97 98 beep = 0; 99 if (!ret && feature->beepNumber != -1) { 100 if ((ret = sensors_get_value(chip, 101 feature->beepNumber, 102 &tmp))) { 103 sensorLog(LOG_ERR, 104 "Error getting sensor data: %s/#%d: %s", 105 chip->prefix, 106 feature->beepNumber, 107 sensors_strerror(ret)); 108 ret = 21; 109 } else { 110 beep = (int) (tmp + 0.5); 111 } 112 } 113 114 for (subindex = 0; !ret && 115 (feature->dataNumbers[subindex] >= 0); ++ subindex) { 116 if ((ret = sensors_get_value(chip, feature->dataNumbers[subindex], values + subindex))) { 117 sensorLog(LOG_ERR, "Error getting sensor data: %s/#%d: %s", chip->prefix, feature->dataNumbers[subindex], sensors_strerror(ret)); 118 ret = 23; 119 } 120 } 121 if (ret == 0) { 122 if (action == DO_RRD) { // arse = "N:" 123 if (feature->rrd) { 124 const char *rrded = feature->rrd (values); 125 strcat(strcat (rrdBuff, ":"), 126 rrded ? rrded : "U"); 127 } 128 } else { 129 const char *formatted = feature->format (values, alarm, beep); 130 if (formatted) { 131 if (action == DO_READ) { 132 sensorLog(LOG_INFO, " %s: %s", label, formatted); 133 } else { 134 sensorLog(LOG_ALERT, "Sensor alarm: Chip %s: %s: %s", chipName(chip), label, formatted); 135 } 136 } 137 } 138 } 139 } 140 if (label) 141 free(label); 142 } 143 return ret; 144 } 145 146 static int setChip(const sensors_chip_name *chip) 147 { 148 int ret = 0; 149 if ((ret = idChip(chip))) { 150 sensorLog(LOG_ERR, "Error identifying chip: %s", 151 chip->prefix); 152 } else if ((ret = sensors_do_chip_sets(chip))) { 153 sensorLog(LOG_ERR, "Error performing chip sets: %s: %s", 154 chip->prefix, sensors_strerror(ret)); 155 ret = 50; 156 } else { 157 sensorLog(LOG_INFO, "Set."); 158 } 159 return ret; 160 } 161 162 static int doChip(const sensors_chip_name *chip, int action) 163 { 164 int ret = 0; 165 if (action == DO_SET) { 166 ret = setChip(chip); 167 } else { 168 int index0, chipindex = -1; 169 for (index0 = 0; knownChips[index0].features; ++ index0) 170 /* 171 * Trick: we compare addresses here. We know it works 172 * because both pointers were returned by 173 * sensors_get_detected_chips(), so they refer to 174 * libsensors internal structures, which do not move. 175 */ 176 if (knownChips[index0].name == chip) { 177 chipindex = index0; 178 break; 179 } 180 if (chipindex >= 0) 181 ret = doKnownChip(chip, &knownChips[chipindex], 182 action); 183 } 184 return ret; 185 } 186 187 static int doChips(int action) 188 { 189 const sensors_chip_name *chip; 190 int i, j, ret = 0; 191 192 for (j = 0; (ret == 0) && (j < numChipNames); ++ j) { 193 i = 0; 194 while ((ret == 0) && 195 ((chip = sensors_get_detected_chips(&chipNames[j], &i)) 196 != NULL)) { 197 ret = doChip(chip, action); 198 } 199 } 200 201 return ret; 202 } 203 204 int readChips(void) 205 { 206 int ret = 0; 207 208 sensorLog(LOG_DEBUG, "sensor read started"); 209 ret = doChips(DO_READ); 210 sensorLog(LOG_DEBUG, "sensor read finished"); 211 212 return ret; 213 } 214 215 int scanChips(void) 216 { 217 int ret = 0; 218 219 sensorLog(LOG_DEBUG, "sensor sweep started"); 220 ret = doChips(DO_SCAN); 221 sensorLog(LOG_DEBUG, "sensor sweep finished"); 222 223 return ret; 224 } 225 226 int setChips(void) 227 { 228 int ret = 0; 229 230 sensorLog(LOG_DEBUG, "sensor set started"); 231 ret = doChips(DO_SET); 232 sensorLog(LOG_DEBUG, "sensor set finished"); 233 234 return ret; 219 235 } 220 236 221 237 /* TODO: loadavg entry */ 222 238 223 int 224 rrdChips 225 (void) { 226 int ret = 0; 227 228 strcpy (rrdBuff, "N"); 229 230 sensorLog (LOG_DEBUG, "sensor rrd started"); 231 ret = doChips (DO_RRD); 232 sensorLog (LOG_DEBUG, "sensor rrd finished"); 233 234 return ret; 235 } 239 int rrdChips(void) 240 { 241 int ret = 0; 242 243 strcpy(rrdBuff, "N"); 244 245 sensorLog(LOG_DEBUG, "sensor rrd started"); 246 ret = doChips(DO_RRD); 247 sensorLog(LOG_DEBUG, "sensor rrd finished"); 248 249 return ret; 250 } -
lm-sensors/trunk/prog/sensord/sensord.c
r5580 r5678 45 45 #include <stdarg.h> 46 46 47 void 48 sensorLog 49 (int priority, const char *fmt, ...) { 50 static char buffer[1 + LOG_BUFFER]; 51 va_list ap; 52 va_start (ap, fmt); 53 vsnprintf (buffer, LOG_BUFFER, fmt, ap); 54 buffer[LOG_BUFFER] = '\0'; 55 va_end (ap); 56 if (debug || (priority < LOG_DEBUG)) { 57 if (logOpened) { 58 syslog (priority, "%s", buffer); 59 } else { 60 fprintf (stderr, "%s\n", buffer); 61 fflush (stderr); 62 } 63 } 64 } 65 66 static void 67 signalHandler 68 (int sig) { 69 signal (sig, signalHandler); 70 switch (sig) { 71 case SIGTERM: 72 done = 1; 73 break; 74 case SIGHUP: 75 reload = 1; 76 break; 77 } 78 } 79 80 static int 81 sensord 82 (void) { 83 int ret = 0; 84 int scanValue = 0, logValue = 0; 85 /* 86 * First RRD update at next RRD timeslot to prevent failures due 87 * one timeslot updated twice on restart for example. 88 */ 89 int rrdValue = rrdTime - time(NULL) % rrdTime; 90 91 sensorLog (LOG_INFO, "sensord started"); 92 93 while (!done) { 94 if (reload) { 95 ret = reloadLib (sensorsCfgFile); 96 if (ret) 97 sensorLog (LOG_NOTICE, "config reload error (%d)", ret); 98 reload = 0; 99 } 100 if (scanTime && (scanValue <= 0)) { 101 if ((ret = scanChips ())) 102 sensorLog (LOG_NOTICE, "sensor scan error (%d)", ret); 103 scanValue += scanTime; 104 } 105 if (logTime && (logValue <= 0)) { 106 if ((ret = readChips ())) 107 sensorLog (LOG_NOTICE, "sensor read error (%d)", ret); 108 logValue += logTime; 109 } 110 if (rrdTime && rrdFile && (rrdValue <= 0)) { 111 if ((ret = rrdUpdate ())) 112 sensorLog (LOG_NOTICE, "rrd update error (%d)", ret); 113 /* 114 * The amount of time to wait is computed using the same method as 115 * in RRD instead of simply adding the interval. 116 */ 117 rrdValue = rrdTime - time(NULL) % rrdTime; 118 } 119 if (!done) { 120 int a = logTime ? logValue : INT_MAX; 121 int b = scanTime ? scanValue : INT_MAX; 122 int c = (rrdTime && rrdFile) ? rrdValue : INT_MAX; 123 int sleepTime = (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c); 124 sleep (sleepTime); 125 scanValue -= sleepTime; 126 logValue -= sleepTime; 127 rrdValue -= sleepTime; 128 } 129 } 130 131 sensorLog (LOG_INFO, "sensord stopped"); 132 133 return ret; 134 } 135 136 static void 137 openLog 138 (void) { 139 openlog ("sensord", 0, syslogFacility); 140 logOpened = 1; 141 } 142 143 static void 144 daemonize 145 (void) { 146 int pid; 147 struct stat fileStat; 148 FILE *file; 149 150 if (chdir ("/") < 0) { 151 perror ("chdir()"); 152 exit (EXIT_FAILURE); 153 } 154 155 if (!(stat (pidFile, &fileStat)) && 156 ((!S_ISREG (fileStat.st_mode)) || (fileStat.st_size > 11))) { 157 fprintf (stderr, "Error: PID file `%s' already exists and looks suspicious.\n", pidFile); 158 exit (EXIT_FAILURE); 159 } 160 161 if (!(file = fopen (pidFile, "w"))) { 162 fprintf (stderr, "fopen(\"%s\"): %s\n", pidFile, strerror (errno)); 163 exit (EXIT_FAILURE); 164 } 165 166 /* I should use sigaction but... */ 167 if (signal (SIGTERM, signalHandler) == SIG_ERR || 168 signal (SIGHUP, signalHandler) == SIG_ERR) { 169 perror ("signal"); 170 exit (EXIT_FAILURE); 171 } 172 173 if ((pid = fork ()) == -1) { 174 perror ("fork()"); 175 exit (EXIT_FAILURE); 176 } else if (pid != 0) { 177 fprintf (file, "%d\n", pid); 178 fclose (file); 179 unloadLib (); 180 exit (EXIT_SUCCESS); 181 } 182 183 if (setsid () < 0) { 184 perror ("setsid()"); 185 exit (EXIT_FAILURE); 186 } 187 188 fclose (file); 189 close (STDIN_FILENO); 190 close (STDOUT_FILENO); 191 close (STDERR_FILENO); 192 } 193 194 static void 195 undaemonize 196 (void) { 197 unlink (pidFile); 198 closelog (); 199 } 200 201 int 202 main 203 (int argc, char **argv) { 204 int ret = 0; 205 206 if (parseArgs (argc, argv) || 207 parseChips (argc, argv)) 208 exit (EXIT_FAILURE); 209 210 if (loadLib (sensorsCfgFile)) 211 exit (EXIT_FAILURE); 212 213 if (isDaemon) 214 openLog (); 215 if (rrdFile) 216 ret = rrdInit (); 217 218 if (ret) { 219 } else if (doCGI) { 220 ret = rrdCGI (); 221 } else if (isDaemon) { 222 daemonize (); 223 ret = sensord (); 224 undaemonize (); 225 } else { 226 if (doSet) 227 ret = setChips (); 228 else if (doScan) 229 ret = scanChips (); 230 else if (rrdFile) 231 ret = rrdUpdate (); 232 else 233 ret = readChips (); 234 } 235 236 if (unloadLib ()) 237 exit (EXIT_FAILURE); 238 239 return ret; 240 } 47 void sensorLog(int priority, const char *fmt, ...) 48 { 49 static char buffer[1 + LOG_BUFFER]; 50 va_list ap; 51 va_start(ap, fmt); 52 vsnprintf(buffer, LOG_BUFFER, fmt, ap); 53 buffer[LOG_BUFFER] = '\0'; 54 va_end(ap); 55 if (debug || (priority < LOG_DEBUG)) { 56 if (logOpened) { 57 syslog(priority, "%s", buffer); 58 } else { 59 fprintf(stderr, "%s\n", buffer); 60 fflush(stderr); 61 } 62 } 63 } 64 65 static void signalHandler(int sig) 66 { 67 signal(sig, signalHandler); 68 switch (sig) { 69 case SIGTERM: 70 done = 1; 71 break; 72 case SIGHUP: 73 reload = 1; 74 break; 75 } 76 } 77 78 static int sensord(void) 79 { 80 int ret = 0; 81 int scanValue = 0, logValue = 0; 82 /* 83 * First RRD update at next RRD timeslot to prevent failures due 84 * one timeslot updated twice on restart for example. 85 */ 86 int rrdValue = rrdTime - time(NULL) % rrdTime; 87 88 sensorLog(LOG_INFO, "sensord started"); 89 90 while (!done) { 91 if (reload) { 92 ret = reloadLib(sensorsCfgFile); 93 if (ret) 94 sensorLog(LOG_NOTICE, 95 "config reload error (%d)", ret); 96 reload = 0; 97 } 98 if (scanTime && (scanValue <= 0)) { 99 if ((ret = scanChips())) 100 sensorLog(LOG_NOTICE, 101 "sensor scan error (%d)", ret); 102 scanValue += scanTime; 103 } 104 if (logTime && (logValue <= 0)) { 105 if ((ret = readChips())) 106 sensorLog(LOG_NOTICE, 107 "sensor read error (%d)", ret); 108 logValue += logTime; 109 } 110 if (rrdTime && rrdFile && (rrdValue <= 0)) { 111 if ((ret = rrdUpdate())) 112 sensorLog(LOG_NOTICE, 113 "rrd update error (%d)", ret); 114 /* 115 * The amount of time to wait is computed using the 116 * same method as in RRD instead of simply adding the 117 * interval. 118 */ 119 rrdValue = rrdTime - time(NULL) % rrdTime; 120 } 121 if (!done) { 122 int a = logTime ? logValue : INT_MAX; 123 int b = scanTime ? scanValue : INT_MAX; 124 int c = (rrdTime && rrdFile) ? rrdValue : INT_MAX; 125 int sleepTime = (a < b) ? ((a < c) ? a : c) : 126 ((b < c) ? b : c); 127 sleep(sleepTime); 128 scanValue -= sleepTime; 129 logValue -= sleepTime; 130 rrdValue -= sleepTime; 131 } 132 } 133 134 sensorLog(LOG_INFO, "sensord stopped"); 135 136 return ret; 137 } 138 139 static void openLog(void) 140 { 141 openlog("sensord", 0, syslogFacility); 142 logOpened = 1; 143 } 144 145 static void daemonize(void) 146 { 147 int pid; 148 struct stat fileStat; 149 FILE *file; 150 151 if (chdir("/") < 0) { 152 perror("chdir()"); 153 exit(EXIT_FAILURE); 154 } 155 156 if (!(stat(pidFile, &fileStat)) && 157 ((!S_ISREG(fileStat.st_mode)) || (fileStat.st_size > 11))) { 158 fprintf(stderr, 159 "Error: PID file `%s' already exists and looks suspicious.\n", 160 pidFile); 161 exit(EXIT_FAILURE); 162 } 163 164 if (!(file = fopen(pidFile, "w"))) { 165 fprintf(stderr, "fopen(\"%s\"): %s\n", pidFile, 166 strerror(errno)); 167 exit(EXIT_FAILURE); 168 } 169 170 /* I should use sigaction but... */ 171 if (signal(SIGTERM, signalHandler) == SIG_ERR || 172 signal (SIGHUP, signalHandler) == SIG_ERR) { 173 perror("signal"); 174 exit(EXIT_FAILURE); 175 } 176 177 if ((pid = fork()) == -1) { 178 perror("fork()"); 179 exit(EXIT_FAILURE); 180 } else if (pid != 0) { 181 fprintf(file, "%d\n", pid); 182 fclose(file); 183 unloadLib(); 184 exit(EXIT_SUCCESS); 185 } 186 187 if (setsid() < 0) { 188 perror("setsid()"); 189 exit(EXIT_FAILURE); 190 } 191 192 fclose(file); 193 close(STDIN_FILENO); 194 close(STDOUT_FILENO); 195 close(STDERR_FILENO); 196 } 197 198 static void undaemonize(void) 199 { 200 unlink(pidFile); 201 closelog(); 202 } 203 204 int main(int argc, char **argv) 205 { 206 int ret = 0; 207 208 if (parseArgs(argc, argv) || 209 parseChips(argc, argv)) 210 exit(EXIT_FAILURE); 211 212 if (loadLib(sensorsCfgFile)) 213 exit(EXIT_FAILURE); 214 215 if (isDaemon) 216 openLog(); 217 if (rrdFile) 218 ret = rrdInit(); 219 220 if (ret) { 221 } else if (doCGI) { 222 ret = rrdCGI(); 223 } else if (isDaemon) { 224 daemonize(); 225 ret = sensord(); 226 undaemonize(); 227 } else { 228 if (doSet) 229 ret = setChips(); 230 else if (doScan) 231 ret = scanChips(); 232 else if (rrdFile) 233 ret = rrdUpdate(); 234 else 235 ret = readChips(); 236 } 237 238 if (unloadLib()) 239 exit(EXIT_FAILURE); 240 241 return ret; 242 } -
lm-sensors/trunk/prog/sensord/sensord.h
r5163 r5678 24 24 #include "lib/sensors.h" 25 25 26 extern void sensorLog (int priority, const char *fmt, ...);26 extern void sensorLog(int priority, const char *fmt, ...); 27 27 28 28 /* from args.c */ … … 46 46 extern int numChipNames; 47 47 48 extern int parseArgs (int argc, char **argv);49 extern int parseChips (int argc, char **argv);48 extern int parseArgs(int argc, char **argv); 49 extern int parseChips(int argc, char **argv); 50 50 51 51 /* from lib.c */ 52 52 53 extern int loadLib (const char *cfgPath);54 extern int reloadLib (const char *cfgPath);55 extern int unloadLib (void);53 extern int loadLib(const char *cfgPath); 54 extern int reloadLib(const char *cfgPath); 55 extern int unloadLib(void); 56 56 57 57 /* from sense.c */ 58 58 59 extern int readChips (void);60 extern int scanChips (void);61 extern int setChips (void);62 extern int rrdChips (void);59 extern int readChips(void); 60 extern int scanChips(void); 61 extern int setChips(void); 62 extern int rrdChips(void); 63 63 64 64 /* from rrd.c */ 65 65 66 66 extern char rrdBuff[]; 67 extern int rrdInit (void);68 extern int rrdUpdate (void);69 extern int rrdCGI (void);67 extern int rrdInit(void); 68 extern int rrdUpdate(void); 69 extern int rrdCGI(void); 70 70 71 71 /* from chips.c */ … … 73 73 #define MAX_DATA 5 74 74 75 typedef const char * (*FormatterFN) (const double values[], int alarm, int beep); 75 typedef const char *(*FormatterFN) (const double values[], int alarm, 76 int beep); 76 77 77 typedef const char * (*RRDFN) (const double values[]);78 typedef const char *(*RRDFN) (const double values[]); 78 79 79 80 typedef enum { 80 DataType_voltage = 0,81 DataType_rpm,82 DataType_temperature,83 DataType_other = -181 DataType_voltage = 0, 82 DataType_rpm, 83 DataType_temperature, 84 DataType_other = -1 84 85 } DataType; 85 86 86 87 typedef struct { 87 FormatterFN format;88 RRDFN rrd;89 DataType type;90 int alarmNumber;91 int beepNumber;92 const sensors_feature *feature;93 int dataNumbers[MAX_DATA + 1];88 FormatterFN format; 89 RRDFN rrd; 90 DataType type; 91 int alarmNumber; 92 int beepNumber; 93 const sensors_feature *feature; 94 int dataNumbers[MAX_DATA + 1]; 94 95 } FeatureDescriptor; 95 96 96 97 typedef struct { 97 const sensors_chip_name *name;98 FeatureDescriptor *features;98 const sensors_chip_name *name; 99 FeatureDescriptor *features; 99 100 } ChipDescriptor; 100 101 101 102 extern ChipDescriptor * knownChips; 102 extern int initKnownChips (void);103 extern void freeKnownChips (void);103 extern int initKnownChips(void); 104 extern void freeKnownChips(void);
