perfmonger 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +15 -0
  2. data/.dir-locals.el +2 -0
  3. data/.gitignore +4 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +12 -0
  6. data/COPYING +674 -0
  7. data/Gemfile +5 -0
  8. data/HOWTO.md +15 -0
  9. data/NEWS +115 -0
  10. data/README.md +61 -0
  11. data/Rakefile +8 -0
  12. data/bin/perfmonger +6 -0
  13. data/data/NOTICE +8 -0
  14. data/data/Twitter_Bootstrap_LICENSE.txt +176 -0
  15. data/data/assets/css/bootstrap-responsive.css +1109 -0
  16. data/data/assets/css/bootstrap.css +6167 -0
  17. data/data/assets/css/perfmonger.css +17 -0
  18. data/data/assets/dashboard.erb +319 -0
  19. data/data/assets/img/glyphicons-halflings-white.png +0 -0
  20. data/data/assets/img/glyphicons-halflings.png +0 -0
  21. data/data/assets/js/bootstrap.js +2280 -0
  22. data/data/assets/js/bootstrap.min.js +6 -0
  23. data/data/assets/js/canvasjs.js +9042 -0
  24. data/data/assets/js/canvasjs.min.js +271 -0
  25. data/data/sysstat.ioconf +268 -0
  26. data/ext/perfmonger/extconf.rb +19 -0
  27. data/ext/perfmonger/perfmonger.h +58 -0
  28. data/ext/perfmonger/perfmonger_record.c +754 -0
  29. data/ext/perfmonger/sysstat/common.c +627 -0
  30. data/ext/perfmonger/sysstat/common.h +207 -0
  31. data/ext/perfmonger/sysstat/ioconf.c +515 -0
  32. data/ext/perfmonger/sysstat/ioconf.h +84 -0
  33. data/ext/perfmonger/sysstat/iostat.c +1100 -0
  34. data/ext/perfmonger/sysstat/iostat.h +121 -0
  35. data/ext/perfmonger/sysstat/libsysstat.h +19 -0
  36. data/ext/perfmonger/sysstat/mpstat.c +953 -0
  37. data/ext/perfmonger/sysstat/mpstat.h +79 -0
  38. data/ext/perfmonger/sysstat/rd_stats.c +2388 -0
  39. data/ext/perfmonger/sysstat/rd_stats.h +651 -0
  40. data/ext/perfmonger/sysstat/sysconfig.h +13 -0
  41. data/lib/perfmonger/cli.rb +115 -0
  42. data/lib/perfmonger/command/base_command.rb +39 -0
  43. data/lib/perfmonger/command/fingerprint.rb +453 -0
  44. data/lib/perfmonger/command/plot.rb +429 -0
  45. data/lib/perfmonger/command/record.rb +32 -0
  46. data/lib/perfmonger/command/record_option.rb +149 -0
  47. data/lib/perfmonger/command/server.rb +294 -0
  48. data/lib/perfmonger/command/stat.rb +60 -0
  49. data/lib/perfmonger/command/stat_option.rb +29 -0
  50. data/lib/perfmonger/command/summary.rb +402 -0
  51. data/lib/perfmonger/config.rb +6 -0
  52. data/lib/perfmonger/version.rb +5 -0
  53. data/lib/perfmonger.rb +12 -0
  54. data/misc/release-howto.txt +17 -0
  55. data/misc/sample-cpu.png +0 -0
  56. data/misc/sample-read-iops.png +0 -0
  57. data/perfmonger.gemspec +44 -0
  58. data/test/run-test.sh +39 -0
  59. data/test/spec/bin_spec.rb +37 -0
  60. data/test/spec/data/2devices.expected +42 -0
  61. data/test/spec/data/2devices.output +42 -0
  62. data/test/spec/spec_helper.rb +20 -0
  63. data/test/spec/summary_spec.rb +193 -0
  64. data/test/test-perfmonger.c +145 -0
  65. data/test/test.h +9 -0
  66. metadata +154 -0
@@ -0,0 +1,2388 @@
1
+ /*
2
+ * rd_stats.c: Read system statistics
3
+ * (C) 1999-2010 by Sebastien GODARD (sysstat <at> orange.fr)
4
+ *
5
+ ***************************************************************************
6
+ * This program is free software; you can redistribute it and/or modify it *
7
+ * under the terms of the GNU General Public License as published by the *
8
+ * Free Software Foundation; either version 2 of the License, or (at your *
9
+ * option) any later version. *
10
+ * *
11
+ * This program is distributed in the hope that it will be useful, but *
12
+ * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY *
13
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
14
+ * for more details. *
15
+ * *
16
+ * You should have received a copy of the GNU General Public License along *
17
+ * with this program; if not, write to the Free Software Foundation, Inc., *
18
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
19
+ ***************************************************************************
20
+ */
21
+
22
+ #include <stdio.h>
23
+ #include <string.h>
24
+ #include <stdlib.h>
25
+ #include <errno.h>
26
+ #include <dirent.h>
27
+ #include <ctype.h>
28
+ #include <sys/types.h>
29
+ #include <sys/stat.h>
30
+ #include <unistd.h>
31
+
32
+ #include "common.h"
33
+ #include "rd_stats.h"
34
+ #include "ioconf.h"
35
+
36
+ #ifdef USE_NLS
37
+ #include <locale.h>
38
+ #include <libintl.h>
39
+ #define _(string) gettext(string)
40
+ #else
41
+ #define _(string) (string)
42
+ #endif
43
+
44
+ #ifdef HAVE_SENSORS
45
+ #include "sensors/sensors.h"
46
+ #endif
47
+
48
+ /*
49
+ ***************************************************************************
50
+ * Read CPU statistics and machine uptime.
51
+ *
52
+ * IN:
53
+ * @st_cpu Structure where stats will be saved.
54
+ * @nbr Total number of CPU (including cpu "all").
55
+ *
56
+ * OUT:
57
+ * @st_cpu Structure with statistics.
58
+ * @uptime Machine uptime multiplied by the number of processors.
59
+ * @uptime0 Machine uptime. Filled only if previously set to zero.
60
+ ***************************************************************************
61
+ */
62
+ void read_stat_cpu(struct stats_cpu *st_cpu, int nbr,
63
+ unsigned long long *uptime, unsigned long long *uptime0)
64
+ {
65
+ FILE *fp;
66
+ struct stats_cpu *st_cpu_i;
67
+ struct stats_cpu sc;
68
+ char line[8192];
69
+ int proc_nb;
70
+
71
+ if ((fp = fopen(STAT, "r")) == NULL) {
72
+ fprintf(stderr, _("Cannot open %s: %s\n"), STAT, strerror(errno));
73
+ exit(2);
74
+ }
75
+
76
+ while (fgets(line, 8192, fp) != NULL) {
77
+
78
+ if (!strncmp(line, "cpu ", 4)) {
79
+
80
+ /*
81
+ * All the fields don't necessarily exist,
82
+ * depending on the kernel version used.
83
+ */
84
+ memset(st_cpu, 0, STATS_CPU_SIZE);
85
+
86
+ /*
87
+ * Read the number of jiffies spent in the different modes
88
+ * (user, nice, etc.) among all proc. CPU usage is not reduced
89
+ * to one processor to avoid rounding problems.
90
+ */
91
+ sscanf(line + 5, "%llu %llu %llu %llu %llu %llu %llu %llu %llu",
92
+ &st_cpu->cpu_user,
93
+ &st_cpu->cpu_nice,
94
+ &st_cpu->cpu_sys,
95
+ &st_cpu->cpu_idle,
96
+ &st_cpu->cpu_iowait,
97
+ &st_cpu->cpu_hardirq,
98
+ &st_cpu->cpu_softirq,
99
+ &st_cpu->cpu_steal,
100
+ &st_cpu->cpu_guest);
101
+
102
+ /*
103
+ * Compute the uptime of the system in jiffies (1/100ths of a second
104
+ * if HZ=100).
105
+ * Machine uptime is multiplied by the number of processors here.
106
+ *
107
+ * NB: Don't add cpu_guest because cpu_user already includes it.
108
+ */
109
+ *uptime = st_cpu->cpu_user + st_cpu->cpu_nice +
110
+ st_cpu->cpu_sys + st_cpu->cpu_idle +
111
+ st_cpu->cpu_iowait + st_cpu->cpu_hardirq +
112
+ st_cpu->cpu_steal + st_cpu->cpu_softirq;
113
+ }
114
+
115
+ else if (!strncmp(line, "cpu", 3)) {
116
+ if (nbr > 1) {
117
+ /* All the fields don't necessarily exist */
118
+ memset(&sc, 0, STATS_CPU_SIZE);
119
+ /*
120
+ * Read the number of jiffies spent in the different modes
121
+ * (user, nice, etc) for current proc.
122
+ * This is done only on SMP machines.
123
+ */
124
+ sscanf(line + 3, "%d %llu %llu %llu %llu %llu %llu %llu %llu %llu",
125
+ &proc_nb,
126
+ &sc.cpu_user,
127
+ &sc.cpu_nice,
128
+ &sc.cpu_sys,
129
+ &sc.cpu_idle,
130
+ &sc.cpu_iowait,
131
+ &sc.cpu_hardirq,
132
+ &sc.cpu_softirq,
133
+ &sc.cpu_steal,
134
+ &sc.cpu_guest);
135
+
136
+ if (proc_nb < (nbr - 1)) {
137
+ st_cpu_i = st_cpu + proc_nb + 1;
138
+ *st_cpu_i = sc;
139
+ }
140
+ /*
141
+ * else additional CPUs have been dynamically registered
142
+ * in /proc/stat.
143
+ */
144
+
145
+ if (!proc_nb && !*uptime0) {
146
+ /*
147
+ * Compute uptime reduced to one proc using proc#0.
148
+ * Done if /proc/uptime was unavailable.
149
+ *
150
+ * NB: Don't add cpu_guest because cpu_user already
151
+ * includes it.
152
+ */
153
+ *uptime0 = sc.cpu_user + sc.cpu_nice +
154
+ sc.cpu_sys + sc.cpu_idle +
155
+ sc.cpu_iowait + sc.cpu_steal +
156
+ sc.cpu_hardirq + sc.cpu_softirq;
157
+ }
158
+ }
159
+ }
160
+ }
161
+
162
+ fclose(fp);
163
+ }
164
+
165
+ /*
166
+ ***************************************************************************
167
+ * Read processes (tasks) creation and context switches statistics
168
+ * from /proc/stat.
169
+ *
170
+ * IN:
171
+ * @st_pcsw Structure where stats will be saved.
172
+ *
173
+ * OUT:
174
+ * @st_pcsw Structure with statistics.
175
+ ***************************************************************************
176
+ */
177
+ void read_stat_pcsw(struct stats_pcsw *st_pcsw)
178
+ {
179
+ FILE *fp;
180
+ char line[8192];
181
+
182
+ if ((fp = fopen(STAT, "r")) == NULL)
183
+ return;
184
+
185
+ while (fgets(line, 8192, fp) != NULL) {
186
+
187
+ if (!strncmp(line, "ctxt ", 5)) {
188
+ /* Read number of context switches */
189
+ sscanf(line + 5, "%llu", &st_pcsw->context_switch);
190
+ }
191
+
192
+ else if (!strncmp(line, "processes ", 10)) {
193
+ /* Read number of processes created since system boot */
194
+ sscanf(line + 10, "%lu", &st_pcsw->processes);
195
+ }
196
+ }
197
+
198
+ fclose(fp);
199
+ }
200
+
201
+ /*
202
+ ***************************************************************************
203
+ * Read interrupts statistics from /proc/stat.
204
+ *
205
+ * IN:
206
+ * @st_irq Structure where stats will be saved.
207
+ * @nbr Number of interrupts to read, including the total number
208
+ * of interrupts.
209
+ *
210
+ * OUT:
211
+ * @st_irq Structure with statistics.
212
+ ***************************************************************************
213
+ */
214
+ void read_stat_irq(struct stats_irq *st_irq, int nbr)
215
+ {
216
+ FILE *fp;
217
+ struct stats_irq *st_irq_i;
218
+ char line[8192];
219
+ int i, pos;
220
+
221
+ if ((fp = fopen(STAT, "r")) == NULL)
222
+ return;
223
+
224
+ while (fgets(line, 8192, fp) != NULL) {
225
+
226
+ if (!strncmp(line, "intr ", 5)) {
227
+ /* Read total number of interrupts received since system boot */
228
+ sscanf(line + 5, "%llu", &st_irq->irq_nr);
229
+ pos = strcspn(line + 5, " ") + 5;
230
+
231
+ for (i = 1; i < nbr; i++) {
232
+ st_irq_i = st_irq + i;
233
+ sscanf(line + pos, " %llu", &st_irq_i->irq_nr);
234
+ pos += strcspn(line + pos + 1, " ") + 1;
235
+ }
236
+ }
237
+ }
238
+
239
+ fclose(fp);
240
+ }
241
+
242
+ /*
243
+ ***************************************************************************
244
+ * Read queue and load statistics from /proc/loadavg and /proc/stat.
245
+ *
246
+ * IN:
247
+ * @st_queue Structure where stats will be saved.
248
+ *
249
+ * OUT:
250
+ * @st_queue Structure with statistics.
251
+ ***************************************************************************
252
+ */
253
+ void read_loadavg(struct stats_queue *st_queue)
254
+ {
255
+ FILE *fp;
256
+ char line[8192];
257
+ int load_tmp[3];
258
+
259
+ if ((fp = fopen(LOADAVG, "r")) == NULL)
260
+ return;
261
+
262
+ /* Read load averages and queue length */
263
+ fscanf(fp, "%d.%d %d.%d %d.%d %ld/%d %*d\n",
264
+ &load_tmp[0], &st_queue->load_avg_1,
265
+ &load_tmp[1], &st_queue->load_avg_5,
266
+ &load_tmp[2], &st_queue->load_avg_15,
267
+ &st_queue->nr_running,
268
+ &st_queue->nr_threads);
269
+
270
+ fclose(fp);
271
+
272
+ st_queue->load_avg_1 += load_tmp[0] * 100;
273
+ st_queue->load_avg_5 += load_tmp[1] * 100;
274
+ st_queue->load_avg_15 += load_tmp[2] * 100;
275
+
276
+ if (st_queue->nr_running) {
277
+ /* Do not take current process into account */
278
+ st_queue->nr_running--;
279
+ }
280
+
281
+ /* Read nr of tasks blocked from /proc/stat */
282
+ if ((fp = fopen(STAT, "r")) == NULL)
283
+ return;
284
+
285
+ while (fgets(line, 8192, fp) != NULL) {
286
+
287
+ if (!strncmp(line, "procs_blocked ", 14)) {
288
+ /* Read number of processes blocked */
289
+ sscanf(line + 14, "%lu", &st_queue->procs_blocked);
290
+ break;
291
+ }
292
+ }
293
+
294
+ fclose(fp);
295
+ }
296
+
297
+ /*
298
+ ***************************************************************************
299
+ * Read memory statistics from /proc/meminfo.
300
+ *
301
+ * IN:
302
+ * @st_memory Structure where stats will be saved.
303
+ *
304
+ * OUT:
305
+ * @st_memory Structure with statistics.
306
+ ***************************************************************************
307
+ */
308
+ void read_meminfo(struct stats_memory *st_memory)
309
+ {
310
+ FILE *fp;
311
+ char line[128];
312
+
313
+ if ((fp = fopen(MEMINFO, "r")) == NULL)
314
+ return;
315
+
316
+ while (fgets(line, 128, fp) != NULL) {
317
+
318
+ if (!strncmp(line, "MemTotal:", 9)) {
319
+ /* Read the total amount of memory in kB */
320
+ sscanf(line + 9, "%lu", &st_memory->tlmkb);
321
+ }
322
+ else if (!strncmp(line, "MemFree:", 8)) {
323
+ /* Read the amount of free memory in kB */
324
+ sscanf(line + 8, "%lu", &st_memory->frmkb);
325
+ }
326
+ else if (!strncmp(line, "Buffers:", 8)) {
327
+ /* Read the amount of buffered memory in kB */
328
+ sscanf(line + 8, "%lu", &st_memory->bufkb);
329
+ }
330
+ else if (!strncmp(line, "Cached:", 7)) {
331
+ /* Read the amount of cached memory in kB */
332
+ sscanf(line + 7, "%lu", &st_memory->camkb);
333
+ }
334
+ else if (!strncmp(line, "SwapCached:", 11)) {
335
+ /* Read the amount of cached swap in kB */
336
+ sscanf(line + 11, "%lu", &st_memory->caskb);
337
+ }
338
+ else if (!strncmp(line, "Active:", 7)) {
339
+ /* Read the amount of active memory in kB */
340
+ sscanf(line + 7, "%lu", &st_memory->activekb);
341
+ }
342
+ else if (!strncmp(line, "Inactive:", 9)) {
343
+ /* Read the amount of inactive memory in kB */
344
+ sscanf(line + 9, "%lu", &st_memory->inactkb);
345
+ }
346
+ else if (!strncmp(line, "SwapTotal:", 10)) {
347
+ /* Read the total amount of swap memory in kB */
348
+ sscanf(line + 10, "%lu", &st_memory->tlskb);
349
+ }
350
+ else if (!strncmp(line, "SwapFree:", 9)) {
351
+ /* Read the amount of free swap memory in kB */
352
+ sscanf(line + 9, "%lu", &st_memory->frskb);
353
+ }
354
+ else if (!strncmp(line, "Committed_AS:", 13)) {
355
+ /* Read the amount of commited memory in kB */
356
+ sscanf(line + 13, "%lu", &st_memory->comkb);
357
+ }
358
+ }
359
+
360
+ fclose(fp);
361
+ }
362
+
363
+ /*
364
+ ***************************************************************************
365
+ * Read swapping statistics from /proc/vmstat.
366
+ *
367
+ * IN:
368
+ * @st_swap Structure where stats will be saved.
369
+ *
370
+ * OUT:
371
+ * @st_swap Structure with statistics.
372
+ ***************************************************************************
373
+ */
374
+ void read_vmstat_swap(struct stats_swap *st_swap)
375
+ {
376
+ FILE *fp;
377
+ char line[128];
378
+
379
+ if ((fp = fopen(VMSTAT, "r")) == NULL)
380
+ return;
381
+
382
+ while (fgets(line, 128, fp) != NULL) {
383
+
384
+ if (!strncmp(line, "pswpin ", 7)) {
385
+ /* Read number of swap pages brought in */
386
+ sscanf(line + 7, "%lu", &st_swap->pswpin);
387
+ }
388
+ else if (!strncmp(line, "pswpout ", 8)) {
389
+ /* Read number of swap pages brought out */
390
+ sscanf(line + 8, "%lu", &st_swap->pswpout);
391
+ }
392
+ }
393
+
394
+ fclose(fp);
395
+ }
396
+
397
+ /*
398
+ ***************************************************************************
399
+ * Read paging statistics from /proc/vmstat.
400
+ *
401
+ * IN:
402
+ * @st_paging Structure where stats will be saved.
403
+ *
404
+ * OUT:
405
+ * @st_paging Structure with statistics.
406
+ ***************************************************************************
407
+ */
408
+ void read_vmstat_paging(struct stats_paging *st_paging)
409
+ {
410
+ FILE *fp;
411
+ char line[128];
412
+ unsigned long pgtmp;
413
+
414
+ if ((fp = fopen(VMSTAT, "r")) == NULL)
415
+ return;
416
+
417
+ st_paging->pgsteal = 0;
418
+ st_paging->pgscan_kswapd = st_paging->pgscan_direct = 0;
419
+
420
+ while (fgets(line, 128, fp) != NULL) {
421
+
422
+ if (!strncmp(line, "pgpgin ", 7)) {
423
+ /* Read number of pages the system paged in */
424
+ sscanf(line + 7, "%lu", &st_paging->pgpgin);
425
+ }
426
+ else if (!strncmp(line, "pgpgout ", 8)) {
427
+ /* Read number of pages the system paged out */
428
+ sscanf(line + 8, "%lu", &st_paging->pgpgout);
429
+ }
430
+ else if (!strncmp(line, "pgfault ", 8)) {
431
+ /* Read number of faults (major+minor) made by the system */
432
+ sscanf(line + 8, "%lu", &st_paging->pgfault);
433
+ }
434
+ else if (!strncmp(line, "pgmajfault ", 11)) {
435
+ /* Read number of faults (major only) made by the system */
436
+ sscanf(line + 11, "%lu", &st_paging->pgmajfault);
437
+ }
438
+ else if (!strncmp(line, "pgfree ", 7)) {
439
+ /* Read number of pages freed by the system */
440
+ sscanf(line + 7, "%lu", &st_paging->pgfree);
441
+ }
442
+ else if (!strncmp(line, "pgsteal_", 8)) {
443
+ /* Read number of pages stolen by the system */
444
+ sscanf(strchr(line, ' '), "%lu", &pgtmp);
445
+ st_paging->pgsteal += pgtmp;
446
+ }
447
+ else if (!strncmp(line, "pgscan_kswapd_", 14)) {
448
+ /* Read number of pages scanned by the kswapd daemon */
449
+ sscanf(strchr(line, ' '), "%lu", &pgtmp);
450
+ st_paging->pgscan_kswapd += pgtmp;
451
+ }
452
+ else if (!strncmp(line, "pgscan_direct_", 14)) {
453
+ /* Read number of pages scanned directly */
454
+ sscanf(strchr(line, ' '), "%lu", &pgtmp);
455
+ st_paging->pgscan_direct += pgtmp;
456
+ }
457
+ }
458
+
459
+ fclose(fp);
460
+ }
461
+
462
+ /*
463
+ ***************************************************************************
464
+ * Read I/O and transfer rates statistics from /proc/diskstats.
465
+ *
466
+ * IN:
467
+ * @st_io Structure where stats will be saved.
468
+ *
469
+ * OUT:
470
+ * @st_io Structure with statistics.
471
+ ***************************************************************************
472
+ */
473
+ void read_diskstats_io(struct stats_io *st_io)
474
+ {
475
+ FILE *fp;
476
+ char line[256];
477
+ char dev_name[MAX_NAME_LEN];
478
+ unsigned int major, minor;
479
+ unsigned long rd_ios, wr_ios;
480
+ unsigned long long rd_sec, wr_sec;
481
+
482
+ if ((fp = fopen(DISKSTATS, "r")) == NULL)
483
+ return;
484
+
485
+ while (fgets(line, 256, fp) != NULL) {
486
+
487
+ if (sscanf(line, "%u %u %s %lu %*u %llu %*u %lu %*u %llu",
488
+ &major, &minor, dev_name,
489
+ &rd_ios, &rd_sec, &wr_ios, &wr_sec) == 7) {
490
+
491
+ if (is_device(dev_name)) {
492
+ /*
493
+ * OK: It's a device and not a partition.
494
+ * Note: Structure should have been initialized first!
495
+ */
496
+ st_io->dk_drive += rd_ios + wr_ios;
497
+ st_io->dk_drive_rio += rd_ios;
498
+ st_io->dk_drive_rblk += (unsigned int) rd_sec;
499
+ st_io->dk_drive_wio += wr_ios;
500
+ st_io->dk_drive_wblk += (unsigned int) wr_sec;
501
+ }
502
+ }
503
+ }
504
+
505
+ fclose(fp);
506
+ }
507
+
508
+ /*
509
+ ***************************************************************************
510
+ * Read block devices statistics from /proc/diskstats.
511
+ *
512
+ * IN:
513
+ * @st_disk Structure where stats will be saved.
514
+ * @nbr Maximum number of block devices.
515
+ * @read_part True if disks *and* partitions should be read; False if only
516
+ * disks are read.
517
+ *
518
+ * OUT:
519
+ * @st_disk Structure with statistics.
520
+ ***************************************************************************
521
+ */
522
+ void read_diskstats_disk(struct stats_disk *st_disk, int nbr, int read_part)
523
+ {
524
+ FILE *fp;
525
+ char line[256];
526
+ char dev_name[MAX_NAME_LEN];
527
+ int dsk = 0;
528
+ struct stats_disk *st_disk_i;
529
+ unsigned int major, minor;
530
+ unsigned long rd_ios, wr_ios, rd_ticks, wr_ticks;
531
+ unsigned long tot_ticks, rq_ticks;
532
+ unsigned long long rd_sec, wr_sec;
533
+
534
+ if ((fp = fopen(DISKSTATS, "r")) == NULL)
535
+ return;
536
+
537
+ while ((fgets(line, 256, fp) != NULL) && (dsk < nbr)) {
538
+
539
+ if (sscanf(line, "%u %u %s %lu %*u %llu %lu %lu %*u %llu"
540
+ " %lu %*u %lu %lu",
541
+ &major, &minor, dev_name,
542
+ &rd_ios, &rd_sec, &rd_ticks, &wr_ios, &wr_sec, &wr_ticks,
543
+ &tot_ticks, &rq_ticks) == 11) {
544
+
545
+ if (!rd_ios && !wr_ios)
546
+ /* Unused device: Ignore it */
547
+ continue;
548
+ if (read_part || is_device(dev_name)) {
549
+ st_disk_i = st_disk + dsk++;
550
+ st_disk_i->major = major;
551
+ st_disk_i->minor = minor;
552
+ st_disk_i->nr_ios = rd_ios + wr_ios;
553
+ st_disk_i->rd_sect = rd_sec;
554
+ st_disk_i->wr_sect = wr_sec;
555
+ st_disk_i->rd_ticks = rd_ticks;
556
+ st_disk_i->wr_ticks = wr_ticks;
557
+ st_disk_i->tot_ticks = tot_ticks;
558
+ st_disk_i->rq_ticks = rq_ticks;
559
+ }
560
+ }
561
+ }
562
+
563
+ fclose(fp);
564
+ }
565
+
566
+ /*
567
+ ***************************************************************************
568
+ * Read serial lines statistics from /proc/tty/driver/serial.
569
+ *
570
+ * IN:
571
+ * @st_serial Structure where stats will be saved.
572
+ * @nbr Maximum number of serial lines.
573
+ *
574
+ * OUT:
575
+ * @st_serial Structure with statistics.
576
+ ***************************************************************************
577
+ */
578
+ void read_tty_driver_serial(struct stats_serial *st_serial, int nbr)
579
+ {
580
+ FILE *fp;
581
+ struct stats_serial *st_serial_i;
582
+ int sl = 0;
583
+ char line[256];
584
+ char *p;
585
+
586
+ if ((fp = fopen(SERIAL, "r")) == NULL)
587
+ return;
588
+
589
+ while ((fgets(line, 256, fp) != NULL) && (sl < nbr)) {
590
+
591
+ if ((p = strstr(line, "tx:")) != NULL) {
592
+ st_serial_i = st_serial + sl;
593
+ sscanf(line, "%u", &st_serial_i->line);
594
+ /*
595
+ * A value of 0 means an unused structure.
596
+ * So increment it to make sure it is not null.
597
+ */
598
+ (st_serial_i->line)++;
599
+ /*
600
+ * Read the number of chars transmitted and received by
601
+ * current serial line.
602
+ */
603
+ sscanf(p + 3, "%u", &st_serial_i->tx);
604
+ if ((p = strstr(line, "rx:")) != NULL) {
605
+ sscanf(p + 3, "%u", &st_serial_i->rx);
606
+ }
607
+ if ((p = strstr(line, "fe:")) != NULL) {
608
+ sscanf(p + 3, "%u", &st_serial_i->frame);
609
+ }
610
+ if ((p = strstr(line, "pe:")) != NULL) {
611
+ sscanf(p + 3, "%u", &st_serial_i->parity);
612
+ }
613
+ if ((p = strstr(line, "brk:")) != NULL) {
614
+ sscanf(p + 4, "%u", &st_serial_i->brk);
615
+ }
616
+ if ((p = strstr(line, "oe:")) != NULL) {
617
+ sscanf(p + 3, "%u", &st_serial_i->overrun);
618
+ }
619
+
620
+ sl++;
621
+ }
622
+ }
623
+
624
+ fclose(fp);
625
+ }
626
+
627
+ /*
628
+ ***************************************************************************
629
+ * Read kernel tables statistics from various system files.
630
+ *
631
+ * IN:
632
+ * @st_ktables Structure where stats will be saved.
633
+ *
634
+ * OUT:
635
+ * @st_ktables Structure with statistics.
636
+ ***************************************************************************
637
+ */
638
+ void read_kernel_tables(struct stats_ktables *st_ktables)
639
+ {
640
+ FILE *fp;
641
+ unsigned int parm;
642
+
643
+ /* Open /proc/sys/fs/dentry-state file */
644
+ if ((fp = fopen(FDENTRY_STATE, "r")) != NULL) {
645
+ fscanf(fp, "%*d %u",
646
+ &st_ktables->dentry_stat);
647
+ fclose(fp);
648
+ }
649
+
650
+ /* Open /proc/sys/fs/file-nr file */
651
+ if ((fp = fopen(FFILE_NR, "r")) != NULL) {
652
+ fscanf(fp, "%u %u",
653
+ &st_ktables->file_used, &parm);
654
+ fclose(fp);
655
+ /*
656
+ * The number of used handles is the number of allocated ones
657
+ * minus the number of free ones.
658
+ */
659
+ st_ktables->file_used -= parm;
660
+ }
661
+
662
+ /* Open /proc/sys/fs/inode-state file */
663
+ if ((fp = fopen(FINODE_STATE, "r")) != NULL) {
664
+ fscanf(fp, "%u %u",
665
+ &st_ktables->inode_used, &parm);
666
+ fclose(fp);
667
+ /*
668
+ * The number of inuse inodes is the number of allocated ones
669
+ * minus the number of free ones.
670
+ */
671
+ st_ktables->inode_used -= parm;
672
+ }
673
+
674
+ /* Open /proc/sys/kernel/pty/nr file */
675
+ if ((fp = fopen(PTY_NR, "r")) != NULL) {
676
+ fscanf(fp, "%u",
677
+ &st_ktables->pty_nr);
678
+ fclose(fp);
679
+ }
680
+ }
681
+
682
+ /*
683
+ ***************************************************************************
684
+ * Read network interfaces statistics from /proc/net/dev.
685
+ *
686
+ * IN:
687
+ * @st_net_dev Structure where stats will be saved.
688
+ * @nbr Maximum number of network interfaces.
689
+ *
690
+ * OUT:
691
+ * @st_net_dev Structure with statistics.
692
+ ***************************************************************************
693
+ */
694
+ void read_net_dev(struct stats_net_dev *st_net_dev, int nbr)
695
+ {
696
+ FILE *fp;
697
+ struct stats_net_dev *st_net_dev_i;
698
+ char line[256];
699
+ char iface[MAX_IFACE_LEN];
700
+ int dev = 0;
701
+ int pos;
702
+
703
+ if ((fp = fopen(NET_DEV, "r")) == NULL)
704
+ return;
705
+
706
+ while ((fgets(line, 256, fp) != NULL) && (dev < nbr)) {
707
+
708
+ pos = strcspn(line, ":");
709
+ if (pos < strlen(line)) {
710
+ st_net_dev_i = st_net_dev + dev;
711
+ strncpy(iface, line, MINIMUM(pos, MAX_IFACE_LEN - 1));
712
+ iface[MINIMUM(pos, MAX_IFACE_LEN - 1)] = '\0';
713
+ sscanf(iface, "%s", st_net_dev_i->interface); /* Skip heading spaces */
714
+ sscanf(line + pos + 1, "%lu %lu %*u %*u %*u %*u %lu %lu %lu %lu "
715
+ "%*u %*u %*u %*u %*u %lu",
716
+ &st_net_dev_i->rx_bytes,
717
+ &st_net_dev_i->rx_packets,
718
+ &st_net_dev_i->rx_compressed,
719
+ &st_net_dev_i->multicast,
720
+ &st_net_dev_i->tx_bytes,
721
+ &st_net_dev_i->tx_packets,
722
+ &st_net_dev_i->tx_compressed);
723
+ dev++;
724
+ }
725
+ }
726
+
727
+ fclose(fp);
728
+ }
729
+
730
+ /*
731
+ ***************************************************************************
732
+ * Read network interfaces errors statistics from /proc/net/dev.
733
+ *
734
+ * IN:
735
+ * @st_net_edev Structure where stats will be saved.
736
+ * @nbr Maximum number of network interfaces.
737
+ *
738
+ * OUT:
739
+ * @st_net_edev Structure with statistics.
740
+ ***************************************************************************
741
+ */
742
+ void read_net_edev(struct stats_net_edev *st_net_edev, int nbr)
743
+ {
744
+ FILE *fp;
745
+ struct stats_net_edev *st_net_edev_i;
746
+ static char line[256];
747
+ char iface[MAX_IFACE_LEN];
748
+ int dev = 0;
749
+ int pos;
750
+
751
+ if ((fp = fopen(NET_DEV, "r")) == NULL)
752
+ return;
753
+
754
+ while ((fgets(line, 256, fp) != NULL) && (dev < nbr)) {
755
+
756
+ pos = strcspn(line, ":");
757
+ if (pos < strlen(line)) {
758
+ st_net_edev_i = st_net_edev + dev;
759
+ strncpy(iface, line, MINIMUM(pos, MAX_IFACE_LEN - 1));
760
+ iface[MINIMUM(pos, MAX_IFACE_LEN - 1)] = '\0';
761
+ sscanf(iface, "%s", st_net_edev_i->interface); /* Skip heading spaces */
762
+ sscanf(line + pos + 1, "%*u %*u %lu %lu %lu %lu %*u %*u %*u %*u "
763
+ "%lu %lu %lu %lu %lu",
764
+ &st_net_edev_i->rx_errors,
765
+ &st_net_edev_i->rx_dropped,
766
+ &st_net_edev_i->rx_fifo_errors,
767
+ &st_net_edev_i->rx_frame_errors,
768
+ &st_net_edev_i->tx_errors,
769
+ &st_net_edev_i->tx_dropped,
770
+ &st_net_edev_i->tx_fifo_errors,
771
+ &st_net_edev_i->collisions,
772
+ &st_net_edev_i->tx_carrier_errors);
773
+ dev++;
774
+ }
775
+ }
776
+
777
+ fclose(fp);
778
+ }
779
+
780
+ /*
781
+ ***************************************************************************
782
+ * Read NFS client statistics from /proc/net/rpc/nfs.
783
+ *
784
+ * IN:
785
+ * @st_net_nfs Structure where stats will be saved.
786
+ *
787
+ * OUT:
788
+ * @st_net_nfs Structure with statistics.
789
+ ***************************************************************************
790
+ */
791
+ void read_net_nfs(struct stats_net_nfs *st_net_nfs)
792
+ {
793
+ FILE *fp;
794
+ char line[256];
795
+ unsigned int getattcnt = 0, accesscnt = 0, readcnt = 0, writecnt = 0;
796
+
797
+ if ((fp = fopen(NET_RPC_NFS, "r")) == NULL)
798
+ return;
799
+
800
+ memset(st_net_nfs, 0, STATS_NET_NFS_SIZE);
801
+
802
+ while (fgets(line, 256, fp) != NULL) {
803
+
804
+ if (!strncmp(line, "rpc ", 4)) {
805
+ sscanf(line + 4, "%u %u",
806
+ &st_net_nfs->nfs_rpccnt, &st_net_nfs->nfs_rpcretrans);
807
+ }
808
+ else if (!strncmp(line, "proc3 ", 6)) {
809
+ sscanf(line + 6, "%*u %*u %u %*u %*u %u %*u %u %u",
810
+ &getattcnt, &accesscnt, &readcnt, &writecnt);
811
+
812
+ st_net_nfs->nfs_getattcnt += getattcnt;
813
+ st_net_nfs->nfs_accesscnt += accesscnt;
814
+ st_net_nfs->nfs_readcnt += readcnt;
815
+ st_net_nfs->nfs_writecnt += writecnt;
816
+ }
817
+ else if (!strncmp(line, "proc4 ", 6)) {
818
+ sscanf(line + 6, "%*u %*u %u %u "
819
+ "%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %u %u",
820
+ &readcnt, &writecnt, &accesscnt, &getattcnt);
821
+
822
+ st_net_nfs->nfs_getattcnt += getattcnt;
823
+ st_net_nfs->nfs_accesscnt += accesscnt;
824
+ st_net_nfs->nfs_readcnt += readcnt;
825
+ st_net_nfs->nfs_writecnt += writecnt;
826
+ }
827
+ }
828
+
829
+ fclose(fp);
830
+ }
831
+
832
+ /*
833
+ ***************************************************************************
834
+ * Read NFS server statistics from /proc/net/rpc/nfsd.
835
+ *
836
+ * IN:
837
+ * @st_net_nfsd Structure where stats will be saved.
838
+ *
839
+ * OUT:
840
+ * @st_net_nfsd Structure with statistics.
841
+ ***************************************************************************
842
+ */
843
+ void read_net_nfsd(struct stats_net_nfsd *st_net_nfsd)
844
+ {
845
+ FILE *fp;
846
+ char line[256];
847
+ unsigned int getattcnt = 0, accesscnt = 0, readcnt = 0, writecnt = 0;
848
+
849
+ if ((fp = fopen(NET_RPC_NFSD, "r")) == NULL)
850
+ return;
851
+
852
+ memset(st_net_nfsd, 0, STATS_NET_NFSD_SIZE);
853
+
854
+ while (fgets(line, 256, fp) != NULL) {
855
+
856
+ if (!strncmp(line, "rc ", 3)) {
857
+ sscanf(line + 3, "%u %u",
858
+ &st_net_nfsd->nfsd_rchits, &st_net_nfsd->nfsd_rcmisses);
859
+ }
860
+ else if (!strncmp(line, "net ", 4)) {
861
+ sscanf(line + 4, "%u %u %u",
862
+ &st_net_nfsd->nfsd_netcnt, &st_net_nfsd->nfsd_netudpcnt,
863
+ &st_net_nfsd->nfsd_nettcpcnt);
864
+ }
865
+ else if (!strncmp(line, "rpc ", 4)) {
866
+ sscanf(line + 4, "%u %u",
867
+ &st_net_nfsd->nfsd_rpccnt, &st_net_nfsd->nfsd_rpcbad);
868
+ }
869
+ else if (!strncmp(line, "proc3 ", 6)) {
870
+ sscanf(line + 6, "%*u %*u %u %*u %*u %u %*u %u %u",
871
+ &getattcnt, &accesscnt, &readcnt, &writecnt);
872
+
873
+ st_net_nfsd->nfsd_getattcnt += getattcnt;
874
+ st_net_nfsd->nfsd_accesscnt += accesscnt;
875
+ st_net_nfsd->nfsd_readcnt += readcnt;
876
+ st_net_nfsd->nfsd_writecnt += writecnt;
877
+
878
+ }
879
+ else if (!strncmp(line, "proc4ops ", 9)) {
880
+ sscanf(line + 9, "%*u %*u %*u %*u %u "
881
+ "%*u %*u %*u %*u %*u %u "
882
+ "%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %u "
883
+ "%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %u",
884
+ &accesscnt, &getattcnt, &readcnt, &writecnt);
885
+
886
+ st_net_nfsd->nfsd_getattcnt += getattcnt;
887
+ st_net_nfsd->nfsd_accesscnt += accesscnt;
888
+ st_net_nfsd->nfsd_readcnt += readcnt;
889
+ st_net_nfsd->nfsd_writecnt += writecnt;
890
+ }
891
+ }
892
+
893
+ fclose(fp);
894
+ }
895
+
896
+ /*
897
+ ***************************************************************************
898
+ * Read network sockets statistics from /proc/net/sockstat.
899
+ *
900
+ * IN:
901
+ * @st_net_sock Structure where stats will be saved.
902
+ *
903
+ * OUT:
904
+ * @st_net_sock Structure with statistics.
905
+ ***************************************************************************
906
+ */
907
+ void read_net_sock(struct stats_net_sock *st_net_sock)
908
+ {
909
+ FILE *fp;
910
+ char line[96];
911
+ char *p;
912
+
913
+ if ((fp = fopen(NET_SOCKSTAT, "r")) == NULL)
914
+ return;
915
+
916
+ while (fgets(line, 96, fp) != NULL) {
917
+
918
+ if (!strncmp(line, "sockets:", 8)) {
919
+ /* Sockets */
920
+ sscanf(line + 14, "%u", &st_net_sock->sock_inuse);
921
+ }
922
+ else if (!strncmp(line, "TCP:", 4)) {
923
+ /* TCP sockets */
924
+ sscanf(line + 11, "%u", &st_net_sock->tcp_inuse);
925
+ if ((p = strstr(line, "tw")) != NULL) {
926
+ sscanf(p + 2, "%u", &st_net_sock->tcp_tw);
927
+ }
928
+ }
929
+ else if (!strncmp(line, "UDP:", 4)) {
930
+ /* UDP sockets */
931
+ sscanf(line + 11, "%u", &st_net_sock->udp_inuse);
932
+ }
933
+ else if (!strncmp(line, "RAW:", 4)) {
934
+ /* RAW sockets */
935
+ sscanf(line + 11, "%u", &st_net_sock->raw_inuse);
936
+ }
937
+ else if (!strncmp(line, "FRAG:", 5)) {
938
+ /* FRAGments */
939
+ sscanf(line + 12, "%u", &st_net_sock->frag_inuse);
940
+ }
941
+ }
942
+
943
+ fclose(fp);
944
+ }
945
+
946
+ /*
947
+ ***************************************************************************
948
+ * Read IP network traffic statistics from /proc/net/snmp.
949
+ *
950
+ * IN:
951
+ * @st_net_ip Structure where stats will be saved.
952
+ *
953
+ * OUT:
954
+ * @st_net_ip Structure with statistics.
955
+ ***************************************************************************
956
+ */
957
+ void read_net_ip(struct stats_net_ip *st_net_ip)
958
+ {
959
+ FILE *fp;
960
+ char line[1024];
961
+ int sw = FALSE;
962
+
963
+ if ((fp = fopen(NET_SNMP, "r")) == NULL)
964
+ return;
965
+
966
+ while (fgets(line, 1024, fp) != NULL) {
967
+
968
+ if (!strncmp(line, "Ip:", 3)) {
969
+ if (sw) {
970
+ sscanf(line + 3, "%*u %*u %lu %*u %*u %lu %*u %*u "
971
+ "%lu %lu %*u %*u %*u %lu %lu %*u %lu %*u %lu",
972
+ &st_net_ip->InReceives,
973
+ &st_net_ip->ForwDatagrams,
974
+ &st_net_ip->InDelivers,
975
+ &st_net_ip->OutRequests,
976
+ &st_net_ip->ReasmReqds,
977
+ &st_net_ip->ReasmOKs,
978
+ &st_net_ip->FragOKs,
979
+ &st_net_ip->FragCreates);
980
+
981
+ break;
982
+ }
983
+ else {
984
+ sw = TRUE;
985
+ }
986
+ }
987
+ }
988
+
989
+ fclose(fp);
990
+ }
991
+
992
+ /*
993
+ ***************************************************************************
994
+ * Read IP network error statistics from /proc/net/snmp.
995
+ *
996
+ * IN:
997
+ * @st_net_eip Structure where stats will be saved.
998
+ *
999
+ * OUT:
1000
+ * @st_net_eip Structure with statistics.
1001
+ ***************************************************************************
1002
+ */
1003
+ void read_net_eip(struct stats_net_eip *st_net_eip)
1004
+ {
1005
+ FILE *fp;
1006
+ char line[1024];
1007
+ int sw = FALSE;
1008
+
1009
+ if ((fp = fopen(NET_SNMP, "r")) == NULL)
1010
+ return;
1011
+
1012
+ while (fgets(line, 1024, fp) != NULL) {
1013
+
1014
+ if (!strncmp(line, "Ip:", 3)) {
1015
+ if (sw) {
1016
+ sscanf(line + 3, "%*u %*u %*u %lu %lu %*u %lu %lu "
1017
+ "%*u %*u %lu %lu %*u %*u %*u %lu %*u %lu",
1018
+ &st_net_eip->InHdrErrors,
1019
+ &st_net_eip->InAddrErrors,
1020
+ &st_net_eip->InUnknownProtos,
1021
+ &st_net_eip->InDiscards,
1022
+ &st_net_eip->OutDiscards,
1023
+ &st_net_eip->OutNoRoutes,
1024
+ &st_net_eip->ReasmFails,
1025
+ &st_net_eip->FragFails);
1026
+
1027
+ break;
1028
+ }
1029
+ else {
1030
+ sw = TRUE;
1031
+ }
1032
+ }
1033
+ }
1034
+
1035
+ fclose(fp);
1036
+ }
1037
+
1038
+ /*
1039
+ ***************************************************************************
1040
+ * Read ICMP network traffic statistics from /proc/net/snmp.
1041
+ *
1042
+ * IN:
1043
+ * @st_net_icmp Structure where stats will be saved.
1044
+ *
1045
+ * OUT:
1046
+ * @st_net_icmp Structure with statistics.
1047
+ ***************************************************************************
1048
+ */
1049
+ void read_net_icmp(struct stats_net_icmp *st_net_icmp)
1050
+ {
1051
+ FILE *fp;
1052
+ char line[1024];
1053
+ int sw = FALSE;
1054
+
1055
+ if ((fp = fopen(NET_SNMP, "r")) == NULL)
1056
+ return;
1057
+
1058
+ while (fgets(line, 1024, fp) != NULL) {
1059
+
1060
+ if (!strncmp(line, "Icmp:", 5)) {
1061
+ if (sw) {
1062
+ sscanf(line + 5, "%lu %*u %*u %*u %*u %*u %*u "
1063
+ "%lu %lu %lu %lu %lu %lu %lu %*u %*u %*u %*u "
1064
+ "%*u %*u %lu %lu %lu %lu %lu %lu",
1065
+ &st_net_icmp->InMsgs,
1066
+ &st_net_icmp->InEchos,
1067
+ &st_net_icmp->InEchoReps,
1068
+ &st_net_icmp->InTimestamps,
1069
+ &st_net_icmp->InTimestampReps,
1070
+ &st_net_icmp->InAddrMasks,
1071
+ &st_net_icmp->InAddrMaskReps,
1072
+ &st_net_icmp->OutMsgs,
1073
+ &st_net_icmp->OutEchos,
1074
+ &st_net_icmp->OutEchoReps,
1075
+ &st_net_icmp->OutTimestamps,
1076
+ &st_net_icmp->OutTimestampReps,
1077
+ &st_net_icmp->OutAddrMasks,
1078
+ &st_net_icmp->OutAddrMaskReps);
1079
+
1080
+ break;
1081
+ }
1082
+ else {
1083
+ sw = TRUE;
1084
+ }
1085
+ }
1086
+ }
1087
+
1088
+ fclose(fp);
1089
+ }
1090
+
1091
+ /*
1092
+ ***************************************************************************
1093
+ * Read ICMP network error statistics from /proc/net/snmp.
1094
+ *
1095
+ * IN:
1096
+ * @st_net_eicmp Structure where stats will be saved.
1097
+ *
1098
+ * OUT:
1099
+ * @st_net_eicmp Structure with statistics.
1100
+ ***************************************************************************
1101
+ */
1102
+ void read_net_eicmp(struct stats_net_eicmp *st_net_eicmp)
1103
+ {
1104
+ FILE *fp;
1105
+ char line[1024];
1106
+ int sw = FALSE;
1107
+
1108
+ if ((fp = fopen(NET_SNMP, "r")) == NULL)
1109
+ return;
1110
+
1111
+ while (fgets(line, 1024, fp) != NULL) {
1112
+
1113
+ if (!strncmp(line, "Icmp:", 5)) {
1114
+ if (sw) {
1115
+ sscanf(line + 5, "%*u %lu %lu %lu %lu %lu %lu %*u %*u "
1116
+ "%*u %*u %*u %*u %*u %lu %lu %lu %lu %lu %lu",
1117
+ &st_net_eicmp->InErrors,
1118
+ &st_net_eicmp->InDestUnreachs,
1119
+ &st_net_eicmp->InTimeExcds,
1120
+ &st_net_eicmp->InParmProbs,
1121
+ &st_net_eicmp->InSrcQuenchs,
1122
+ &st_net_eicmp->InRedirects,
1123
+ &st_net_eicmp->OutErrors,
1124
+ &st_net_eicmp->OutDestUnreachs,
1125
+ &st_net_eicmp->OutTimeExcds,
1126
+ &st_net_eicmp->OutParmProbs,
1127
+ &st_net_eicmp->OutSrcQuenchs,
1128
+ &st_net_eicmp->OutRedirects);
1129
+
1130
+ break;
1131
+ }
1132
+ else {
1133
+ sw = TRUE;
1134
+ }
1135
+ }
1136
+ }
1137
+
1138
+ fclose(fp);
1139
+ }
1140
+
1141
+ /*
1142
+ ***************************************************************************
1143
+ * Read TCP network traffic statistics from /proc/net/snmp.
1144
+ *
1145
+ * IN:
1146
+ * @st_net_tcp Structure where stats will be saved.
1147
+ *
1148
+ * OUT:
1149
+ * @st_net_tcp Structure with statistics.
1150
+ ***************************************************************************
1151
+ */
1152
+ void read_net_tcp(struct stats_net_tcp *st_net_tcp)
1153
+ {
1154
+ FILE *fp;
1155
+ char line[1024];
1156
+ int sw = FALSE;
1157
+
1158
+ if ((fp = fopen(NET_SNMP, "r")) == NULL)
1159
+ return;
1160
+
1161
+ while (fgets(line, 1024, fp) != NULL) {
1162
+
1163
+ if (!strncmp(line, "Tcp:", 4)) {
1164
+ if (sw) {
1165
+ sscanf(line + 4, "%*u %*u %*u %*d %lu %lu "
1166
+ "%*u %*u %*u %lu %lu",
1167
+ &st_net_tcp->ActiveOpens,
1168
+ &st_net_tcp->PassiveOpens,
1169
+ &st_net_tcp->InSegs,
1170
+ &st_net_tcp->OutSegs);
1171
+
1172
+ break;
1173
+ }
1174
+ else {
1175
+ sw = TRUE;
1176
+ }
1177
+ }
1178
+ }
1179
+
1180
+ fclose(fp);
1181
+ }
1182
+
1183
+ /*
1184
+ ***************************************************************************
1185
+ * Read TCP network error statistics from /proc/net/snmp.
1186
+ *
1187
+ * IN:
1188
+ * @st_net_etcp Structure where stats will be saved.
1189
+ *
1190
+ * OUT:
1191
+ * @st_net_etcp Structure with statistics.
1192
+ ***************************************************************************
1193
+ */
1194
+ void read_net_etcp(struct stats_net_etcp *st_net_etcp)
1195
+ {
1196
+ FILE *fp;
1197
+ char line[1024];
1198
+ int sw = FALSE;
1199
+
1200
+ if ((fp = fopen(NET_SNMP, "r")) == NULL)
1201
+ return;
1202
+
1203
+ while (fgets(line, 1024, fp) != NULL) {
1204
+
1205
+ if (!strncmp(line, "Tcp:", 4)) {
1206
+ if (sw) {
1207
+ sscanf(line + 4, "%*u %*u %*u %*d %*u %*u "
1208
+ "%lu %lu %*u %*u %*u %lu %lu %lu",
1209
+ &st_net_etcp->AttemptFails,
1210
+ &st_net_etcp->EstabResets,
1211
+ &st_net_etcp->RetransSegs,
1212
+ &st_net_etcp->InErrs,
1213
+ &st_net_etcp->OutRsts);
1214
+
1215
+ break;
1216
+ }
1217
+ else {
1218
+ sw = TRUE;
1219
+ }
1220
+ }
1221
+ }
1222
+
1223
+ fclose(fp);
1224
+ }
1225
+
1226
+ /*
1227
+ ***************************************************************************
1228
+ * Read UDP network traffic statistics from /proc/net/snmp.
1229
+ *
1230
+ * IN:
1231
+ * @st_net_udp Structure where stats will be saved.
1232
+ *
1233
+ * OUT:
1234
+ * @st_net_udp Structure with statistics.
1235
+ ***************************************************************************
1236
+ */
1237
+ void read_net_udp(struct stats_net_udp *st_net_udp)
1238
+ {
1239
+ FILE *fp;
1240
+ char line[1024];
1241
+ int sw = FALSE;
1242
+
1243
+ if ((fp = fopen(NET_SNMP, "r")) == NULL)
1244
+ return;
1245
+
1246
+ while (fgets(line, 1024, fp) != NULL) {
1247
+
1248
+ if (!strncmp(line, "Udp:", 4)) {
1249
+ if (sw) {
1250
+ sscanf(line + 4, "%lu %lu %lu %lu",
1251
+ &st_net_udp->InDatagrams,
1252
+ &st_net_udp->NoPorts,
1253
+ &st_net_udp->InErrors,
1254
+ &st_net_udp->OutDatagrams);
1255
+
1256
+ break;
1257
+ }
1258
+ else {
1259
+ sw = TRUE;
1260
+ }
1261
+ }
1262
+ }
1263
+
1264
+ fclose(fp);
1265
+ }
1266
+
1267
+ /*
1268
+ ***************************************************************************
1269
+ * Read IPv6 network sockets statistics from /proc/net/sockstat6.
1270
+ *
1271
+ * IN:
1272
+ * @st_net_sock6 Structure where stats will be saved.
1273
+ *
1274
+ * OUT:
1275
+ * @st_net_sock6 Structure with statistics.
1276
+ ***************************************************************************
1277
+ */
1278
+ void read_net_sock6(struct stats_net_sock6 *st_net_sock6)
1279
+ {
1280
+ FILE *fp;
1281
+ char line[96];
1282
+
1283
+ if ((fp = fopen(NET_SOCKSTAT6, "r")) == NULL)
1284
+ return;
1285
+
1286
+ while (fgets(line, 96, fp) != NULL) {
1287
+
1288
+ if (!strncmp(line, "TCP6:", 5)) {
1289
+ /* TCPv6 sockets */
1290
+ sscanf(line + 12, "%u", &st_net_sock6->tcp6_inuse);
1291
+ }
1292
+ else if (!strncmp(line, "UDP6:", 5)) {
1293
+ /* UDPv6 sockets */
1294
+ sscanf(line + 12, "%u", &st_net_sock6->udp6_inuse);
1295
+ }
1296
+ else if (!strncmp(line, "RAW6:", 5)) {
1297
+ /* IPv6 RAW sockets */
1298
+ sscanf(line + 12, "%u", &st_net_sock6->raw6_inuse);
1299
+ }
1300
+ else if (!strncmp(line, "FRAG6:", 6)) {
1301
+ /* IPv6 FRAGments */
1302
+ sscanf(line + 13, "%u", &st_net_sock6->frag6_inuse);
1303
+ }
1304
+ }
1305
+
1306
+ fclose(fp);
1307
+ }
1308
+
1309
+ /*
1310
+ ***************************************************************************
1311
+ * Read IPv6 network traffic statistics from /proc/net/snmp6.
1312
+ *
1313
+ * IN:
1314
+ * @st_net_ip6 Structure where stats will be saved.
1315
+ *
1316
+ * OUT:
1317
+ * @st_net_ip6 Structure with statistics.
1318
+ ***************************************************************************
1319
+ */
1320
+ void read_net_ip6(struct stats_net_ip6 *st_net_ip6)
1321
+ {
1322
+ FILE *fp;
1323
+ char line[128];
1324
+
1325
+ if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1326
+ return;
1327
+
1328
+ while (fgets(line, 128, fp) != NULL) {
1329
+
1330
+ if (!strncmp(line, "Ip6InReceives ", 14)) {
1331
+ sscanf(line + 14, "%lu", &st_net_ip6->InReceives6);
1332
+ }
1333
+ else if (!strncmp(line, "Ip6OutForwDatagrams ", 20)) {
1334
+ sscanf(line + 20, "%lu", &st_net_ip6->OutForwDatagrams6);
1335
+ }
1336
+ else if (!strncmp(line, "Ip6InDelivers ", 14)) {
1337
+ sscanf(line + 14, "%lu", &st_net_ip6->InDelivers6);
1338
+ }
1339
+ else if (!strncmp(line, "Ip6OutRequests ", 15)) {
1340
+ sscanf(line + 15, "%lu", &st_net_ip6->OutRequests6);
1341
+ }
1342
+ else if (!strncmp(line, "Ip6ReasmReqds ", 14)) {
1343
+ sscanf(line + 14, "%lu", &st_net_ip6->ReasmReqds6);
1344
+ }
1345
+ else if (!strncmp(line, "Ip6ReasmOKs ", 12)) {
1346
+ sscanf(line + 12, "%lu", &st_net_ip6->ReasmOKs6);
1347
+ }
1348
+ else if (!strncmp(line, "Ip6InMcastPkts ", 15)) {
1349
+ sscanf(line + 15, "%lu", &st_net_ip6->InMcastPkts6);
1350
+ }
1351
+ else if (!strncmp(line, "Ip6OutMcastPkts ", 16)) {
1352
+ sscanf(line + 16, "%lu", &st_net_ip6->OutMcastPkts6);
1353
+ }
1354
+ else if (!strncmp(line, "Ip6FragOKs ", 11)) {
1355
+ sscanf(line + 11, "%lu", &st_net_ip6->FragOKs6);
1356
+ }
1357
+ else if (!strncmp(line, "Ip6FragCreates ", 15)) {
1358
+ sscanf(line + 15, "%lu", &st_net_ip6->FragCreates6);
1359
+ }
1360
+ }
1361
+
1362
+ fclose(fp);
1363
+ }
1364
+
1365
+ /*
1366
+ ***************************************************************************
1367
+ * Read IPv6 network error statistics from /proc/net/snmp6.
1368
+ *
1369
+ * IN:
1370
+ * @st_net_eip6 Structure where stats will be saved.
1371
+ *
1372
+ * OUT:
1373
+ * @st_net_eip6 Structure with statistics.
1374
+ ***************************************************************************
1375
+ */
1376
+ void read_net_eip6(struct stats_net_eip6 *st_net_eip6)
1377
+ {
1378
+ FILE *fp;
1379
+ char line[128];
1380
+
1381
+ if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1382
+ return;
1383
+
1384
+ while (fgets(line, 128, fp) != NULL) {
1385
+
1386
+ if (!strncmp(line, "Ip6InHdrErrors ", 15)) {
1387
+ sscanf(line + 15, "%lu", &st_net_eip6->InHdrErrors6);
1388
+ }
1389
+ else if (!strncmp(line, "Ip6InAddrErrors ", 16)) {
1390
+ sscanf(line + 16, "%lu", &st_net_eip6->InAddrErrors6);
1391
+ }
1392
+ else if (!strncmp(line, "Ip6InUnknownProtos ", 19)) {
1393
+ sscanf(line + 19, "%lu", &st_net_eip6->InUnknownProtos6);
1394
+ }
1395
+ else if (!strncmp(line, "Ip6InTooBigErrors ", 18)) {
1396
+ sscanf(line + 18, "%lu", &st_net_eip6->InTooBigErrors6);
1397
+ }
1398
+ else if (!strncmp(line, "Ip6InDiscards ", 14)) {
1399
+ sscanf(line + 14, "%lu", &st_net_eip6->InDiscards6);
1400
+ }
1401
+ else if (!strncmp(line, "Ip6OutDiscards ", 15)) {
1402
+ sscanf(line + 15, "%lu", &st_net_eip6->OutDiscards6);
1403
+ }
1404
+ else if (!strncmp(line, "Ip6InNoRoutes ", 14)) {
1405
+ sscanf(line + 14, "%lu", &st_net_eip6->InNoRoutes6);
1406
+ }
1407
+ else if (!strncmp(line, "Ip6OutNoRoutes ", 15)) {
1408
+ sscanf(line + 15, "%lu", &st_net_eip6->OutNoRoutes6);
1409
+ }
1410
+ else if (!strncmp(line, "Ip6ReasmFails ", 14)) {
1411
+ sscanf(line + 14, "%lu", &st_net_eip6->ReasmFails6);
1412
+ }
1413
+ else if (!strncmp(line, "Ip6FragFails ", 13)) {
1414
+ sscanf(line + 13, "%lu", &st_net_eip6->FragFails6);
1415
+ }
1416
+ else if (!strncmp(line, "Ip6InTruncatedPkts ", 19)) {
1417
+ sscanf(line + 19, "%lu", &st_net_eip6->InTruncatedPkts6);
1418
+ }
1419
+ }
1420
+
1421
+ fclose(fp);
1422
+ }
1423
+
1424
+ /*
1425
+ ***************************************************************************
1426
+ * Read ICMPv6 network traffic statistics from /proc/net/snmp6.
1427
+ *
1428
+ * IN:
1429
+ * @st_net_icmp6 Structure where stats will be saved.
1430
+ *
1431
+ * OUT:
1432
+ * @st_net_icmp6 Structure with statistics.
1433
+ ***************************************************************************
1434
+ */
1435
+ void read_net_icmp6(struct stats_net_icmp6 *st_net_icmp6)
1436
+ {
1437
+ FILE *fp;
1438
+ char line[128];
1439
+
1440
+ if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1441
+ return;
1442
+
1443
+ while (fgets(line, 128, fp) != NULL) {
1444
+
1445
+ if (!strncmp(line, "Icmp6InMsgs ", 12)) {
1446
+ sscanf(line + 12, "%lu", &st_net_icmp6->InMsgs6);
1447
+ }
1448
+ else if (!strncmp(line, "Icmp6OutMsgs ", 13)) {
1449
+ sscanf(line + 13, "%lu", &st_net_icmp6->OutMsgs6);
1450
+ }
1451
+ else if (!strncmp(line, "Icmp6InEchos ", 13)) {
1452
+ sscanf(line + 13, "%lu", &st_net_icmp6->InEchos6);
1453
+ }
1454
+ else if (!strncmp(line, "Icmp6InEchoReplies ", 19)) {
1455
+ sscanf(line + 19, "%lu", &st_net_icmp6->InEchoReplies6);
1456
+ }
1457
+ else if (!strncmp(line, "Icmp6OutEchoReplies ", 20)) {
1458
+ sscanf(line + 20, "%lu", &st_net_icmp6->OutEchoReplies6);
1459
+ }
1460
+ else if (!strncmp(line, "Icmp6InGroupMembQueries ", 24)) {
1461
+ sscanf(line + 24, "%lu", &st_net_icmp6->InGroupMembQueries6);
1462
+ }
1463
+ else if (!strncmp(line, "Icmp6InGroupMembResponses ", 26)) {
1464
+ sscanf(line + 26, "%lu", &st_net_icmp6->InGroupMembResponses6);
1465
+ }
1466
+ else if (!strncmp(line, "Icmp6OutGroupMembResponses ", 27)) {
1467
+ sscanf(line + 27, "%lu", &st_net_icmp6->OutGroupMembResponses6);
1468
+ }
1469
+ else if (!strncmp(line, "Icmp6InGroupMembReductions ", 27)) {
1470
+ sscanf(line + 27, "%lu", &st_net_icmp6->InGroupMembReductions6);
1471
+ }
1472
+ else if (!strncmp(line, "Icmp6OutGroupMembReductions ", 28)) {
1473
+ sscanf(line + 28, "%lu", &st_net_icmp6->OutGroupMembReductions6);
1474
+ }
1475
+ else if (!strncmp(line, "Icmp6InRouterSolicits ", 22)) {
1476
+ sscanf(line + 22, "%lu", &st_net_icmp6->InRouterSolicits6);
1477
+ }
1478
+ else if (!strncmp(line, "Icmp6OutRouterSolicits ", 23)) {
1479
+ sscanf(line + 23, "%lu", &st_net_icmp6->OutRouterSolicits6);
1480
+ }
1481
+ else if (!strncmp(line, "Icmp6InRouterAdvertisements ", 28)) {
1482
+ sscanf(line + 28, "%lu", &st_net_icmp6->InRouterAdvertisements6);
1483
+ }
1484
+ else if (!strncmp(line, "Icmp6InNeighborSolicits ", 24)) {
1485
+ sscanf(line + 24, "%lu", &st_net_icmp6->InNeighborSolicits6);
1486
+ }
1487
+ else if (!strncmp(line, "Icmp6OutNeighborSolicits ", 25)) {
1488
+ sscanf(line + 25, "%lu", &st_net_icmp6->OutNeighborSolicits6);
1489
+ }
1490
+ else if (!strncmp(line, "Icmp6InNeighborAdvertisements ", 30)) {
1491
+ sscanf(line + 30, "%lu", &st_net_icmp6->InNeighborAdvertisements6);
1492
+ }
1493
+ else if (!strncmp(line, "Icmp6OutNeighborAdvertisements ", 31)) {
1494
+ sscanf(line + 31, "%lu", &st_net_icmp6->OutNeighborAdvertisements6);
1495
+ }
1496
+ }
1497
+
1498
+ fclose(fp);
1499
+ }
1500
+
1501
+ /*
1502
+ ***************************************************************************
1503
+ * Read ICMPv6 network error statistics from /proc/net/snmp6.
1504
+ *
1505
+ * IN:
1506
+ * @st_net_eicmp6 Structure where stats will be saved.
1507
+ *
1508
+ * OUT:
1509
+ * @st_net_eicmp6 Structure with statistics.
1510
+ ***************************************************************************
1511
+ */
1512
+ void read_net_eicmp6(struct stats_net_eicmp6 *st_net_eicmp6)
1513
+ {
1514
+ FILE *fp;
1515
+ char line[128];
1516
+
1517
+ if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1518
+ return;
1519
+
1520
+ while (fgets(line, 128, fp) != NULL) {
1521
+
1522
+ if (!strncmp(line, "Icmp6InErrors ", 14)) {
1523
+ sscanf(line + 14, "%lu", &st_net_eicmp6->InErrors6);
1524
+ }
1525
+ else if (!strncmp(line, "Icmp6InDestUnreachs ", 20)) {
1526
+ sscanf(line + 20, "%lu", &st_net_eicmp6->InDestUnreachs6);
1527
+ }
1528
+ else if (!strncmp(line, "Icmp6OutDestUnreachs ", 21)) {
1529
+ sscanf(line + 21, "%lu", &st_net_eicmp6->OutDestUnreachs6);
1530
+ }
1531
+ else if (!strncmp(line, "Icmp6InTimeExcds ", 17)) {
1532
+ sscanf(line + 17, "%lu", &st_net_eicmp6->InTimeExcds6);
1533
+ }
1534
+ else if (!strncmp(line, "Icmp6OutTimeExcds ", 18)) {
1535
+ sscanf(line + 18, "%lu", &st_net_eicmp6->OutTimeExcds6);
1536
+ }
1537
+ else if (!strncmp(line, "Icmp6InParmProblems ", 20)) {
1538
+ sscanf(line + 20, "%lu", &st_net_eicmp6->InParmProblems6);
1539
+ }
1540
+ else if (!strncmp(line, "Icmp6OutParmProblems ", 21)) {
1541
+ sscanf(line + 21, "%lu", &st_net_eicmp6->OutParmProblems6);
1542
+ }
1543
+ else if (!strncmp(line, "Icmp6InRedirects ", 17)) {
1544
+ sscanf(line + 17, "%lu", &st_net_eicmp6->InRedirects6);
1545
+ }
1546
+ else if (!strncmp(line, "Icmp6OutRedirects ", 18)) {
1547
+ sscanf(line + 18, "%lu", &st_net_eicmp6->OutRedirects6);
1548
+ }
1549
+ else if (!strncmp(line, "Icmp6InPktTooBigs ", 18)) {
1550
+ sscanf(line + 18, "%lu", &st_net_eicmp6->InPktTooBigs6);
1551
+ }
1552
+ else if (!strncmp(line, "Icmp6OutPktTooBigs ", 19)) {
1553
+ sscanf(line + 19, "%lu", &st_net_eicmp6->OutPktTooBigs6);
1554
+ }
1555
+ }
1556
+
1557
+ fclose(fp);
1558
+ }
1559
+
1560
+ /*
1561
+ ***************************************************************************
1562
+ * Read UDPv6 network traffic statistics from /proc/net/snmp6.
1563
+ *
1564
+ * IN:
1565
+ * @st_net_udp6 Structure where stats will be saved.
1566
+ *
1567
+ * OUT:
1568
+ * @st_net_udp6 Structure with statistics.
1569
+ ***************************************************************************
1570
+ */
1571
+ void read_net_udp6(struct stats_net_udp6 *st_net_udp6)
1572
+ {
1573
+ FILE *fp;
1574
+ char line[128];
1575
+
1576
+ if ((fp = fopen(NET_SNMP6, "r")) == NULL)
1577
+ return;
1578
+
1579
+ while (fgets(line, 128, fp) != NULL) {
1580
+
1581
+ if (!strncmp(line, "Udp6InDatagrams ", 16)) {
1582
+ sscanf(line + 16, "%lu", &st_net_udp6->InDatagrams6);
1583
+ }
1584
+ else if (!strncmp(line, "Udp6OutDatagrams ", 17)) {
1585
+ sscanf(line + 17, "%lu", &st_net_udp6->OutDatagrams6);
1586
+ }
1587
+ else if (!strncmp(line, "Udp6NoPorts ", 12)) {
1588
+ sscanf(line + 12, "%lu", &st_net_udp6->NoPorts6);
1589
+ }
1590
+ else if (!strncmp(line, "Udp6InErrors ", 13)) {
1591
+ sscanf(line + 13, "%lu", &st_net_udp6->InErrors6);
1592
+ }
1593
+ }
1594
+
1595
+ fclose(fp);
1596
+ }
1597
+
1598
+ /*
1599
+ ***************************************************************************
1600
+ * Read CPU frequency statistics.
1601
+ *
1602
+ * IN:
1603
+ * @st_pwr_cpufreq Structure where stats will be saved.
1604
+ * @nbr Total number of CPU (including cpu "all").
1605
+ *
1606
+ * OUT:
1607
+ * @st_pwr_cpufreq Structure with statistics.
1608
+ ***************************************************************************
1609
+ */
1610
+ void read_cpuinfo(struct stats_pwr_cpufreq *st_pwr_cpufreq, int nbr)
1611
+ {
1612
+ FILE *fp;
1613
+ struct stats_pwr_cpufreq *st_pwr_cpufreq_i;
1614
+ char line[1024];
1615
+ int proc_nb = 0, nr = 0;
1616
+ unsigned int ifreq, dfreq;
1617
+
1618
+ if ((fp = fopen(CPUINFO, "r")) == NULL)
1619
+ return;
1620
+
1621
+ st_pwr_cpufreq->cpufreq = 0;
1622
+
1623
+ while (fgets(line, 1024, fp) != NULL) {
1624
+
1625
+ if (!strncmp(line, "processor\t", 10)) {
1626
+ sscanf(strchr(line, ':') + 1, "%d", &proc_nb);
1627
+ }
1628
+
1629
+ else if (!strncmp(line, "cpu MHz\t", 8)) {
1630
+ sscanf(strchr(line, ':') + 1, "%u.%u", &ifreq, &dfreq);
1631
+
1632
+ if (proc_nb < (nbr - 1)) {
1633
+ /* Save current CPU frequency */
1634
+ st_pwr_cpufreq_i = st_pwr_cpufreq + proc_nb + 1;
1635
+ st_pwr_cpufreq_i->cpufreq = ifreq * 100 + dfreq / 10;
1636
+
1637
+ /* Also save it to compute an average CPU frequency */
1638
+ st_pwr_cpufreq->cpufreq += st_pwr_cpufreq_i->cpufreq;
1639
+ nr++;
1640
+ }
1641
+ else if (!proc_nb && (nbr == 1)) {
1642
+ /*
1643
+ * We are reading freq for "Processor 0" and we have a machine
1644
+ * with only one processor and not an SMP kernel, with /sys not mounted
1645
+ * (the nr of proc has been counted using /proc/stat and there was
1646
+ * only one line with global CPU stats here).
1647
+ * This is a very specific case, I must admit...
1648
+ */
1649
+ st_pwr_cpufreq->cpufreq = ifreq * 100 + dfreq / 10;
1650
+ }
1651
+ }
1652
+ }
1653
+
1654
+ fclose(fp);
1655
+
1656
+ if (nr) {
1657
+ /* Compute average CPU frequency for this machine */
1658
+ st_pwr_cpufreq->cpufreq /= nr;
1659
+ }
1660
+ }
1661
+
1662
+ /*
1663
+ ***************************************************************************
1664
+ * Read fan statistics.
1665
+ *
1666
+ * IN:
1667
+ * @st_pwr_fan Structure where stats will be saved.
1668
+ * @nbr Total number of fans.
1669
+ *
1670
+ * OUT:
1671
+ * @st_pwr_fan Structure with statistics.
1672
+ ***************************************************************************
1673
+ */
1674
+ void read_fan(struct stats_pwr_fan *st_pwr_fan, int nbr)
1675
+ {
1676
+ #ifdef HAVE_SENSORS
1677
+ int count = 0;
1678
+ const sensors_chip_name *chip;
1679
+ const sensors_feature *feature;
1680
+ const sensors_subfeature *sub;
1681
+ struct stats_pwr_fan *st_pwr_fan_i;
1682
+ int chip_nr = 0;
1683
+ int i, j;
1684
+
1685
+ memset(st_pwr_fan, 0, STATS_PWR_FAN_SIZE);
1686
+ int err = 0;
1687
+
1688
+ while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) {
1689
+ i = 0;
1690
+ while ((feature = sensors_get_features(chip, &i))) {
1691
+ if ((feature->type == SENSORS_FEATURE_FAN) && (count < nbr)) {
1692
+ j = 0;
1693
+ st_pwr_fan_i = st_pwr_fan + count;
1694
+ sensors_snprintf_chip_name(st_pwr_fan_i->device, MAX_SENSORS_DEV_LEN, chip);
1695
+
1696
+ while ((sub = sensors_get_all_subfeatures(chip, feature, &j))) {
1697
+ if ((sub->type == SENSORS_SUBFEATURE_FAN_INPUT) &&
1698
+ (sub->flags & SENSORS_MODE_R)) {
1699
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_fan_i->rpm))) {
1700
+ st_pwr_fan_i->rpm = 0;
1701
+ }
1702
+ }
1703
+ else if ((sub->type == SENSORS_SUBFEATURE_FAN_MIN)) {
1704
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_fan_i->rpm_min))) {
1705
+ st_pwr_fan_i->rpm_min = 0;
1706
+ }
1707
+ }
1708
+ }
1709
+ count++;
1710
+ }
1711
+ }
1712
+ }
1713
+ #endif /* HAVE_SENSORS */
1714
+ }
1715
+
1716
+ /*
1717
+ ***************************************************************************
1718
+ * Read device temperature statistics.
1719
+ *
1720
+ * IN:
1721
+ * @st_pwr_temp Structure where stats will be saved.
1722
+ * @nbr Total number of fans.
1723
+ *
1724
+ * OUT:
1725
+ * @st_pwr_temp Structure with statistics.
1726
+ ***************************************************************************
1727
+ */
1728
+ void read_temp(struct stats_pwr_temp *st_pwr_temp, int nbr)
1729
+ {
1730
+ #ifdef HAVE_SENSORS
1731
+ int count = 0;
1732
+ const sensors_chip_name *chip;
1733
+ const sensors_feature *feature;
1734
+ const sensors_subfeature *sub;
1735
+ struct stats_pwr_temp *st_pwr_temp_i;
1736
+ int chip_nr = 0;
1737
+ int i, j;
1738
+
1739
+ memset(st_pwr_temp, 0, STATS_PWR_TEMP_SIZE);
1740
+ int err = 0;
1741
+
1742
+ while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) {
1743
+ i = 0;
1744
+ while ((feature = sensors_get_features(chip, &i))) {
1745
+ if ((feature->type == SENSORS_FEATURE_TEMP) && (count < nbr)) {
1746
+ j = 0;
1747
+ st_pwr_temp_i = st_pwr_temp + count;
1748
+ sensors_snprintf_chip_name(st_pwr_temp_i->device, MAX_SENSORS_DEV_LEN, chip);
1749
+
1750
+ while ((sub = sensors_get_all_subfeatures(chip, feature, &j))) {
1751
+ if ((sub->type == SENSORS_SUBFEATURE_TEMP_INPUT) &&
1752
+ (sub->flags & SENSORS_MODE_R)) {
1753
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_temp_i->temp))) {
1754
+ st_pwr_temp_i->temp = 0;
1755
+ }
1756
+ }
1757
+ else if ((sub->type == SENSORS_SUBFEATURE_TEMP_MIN)) {
1758
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_temp_i->temp_min))) {
1759
+ st_pwr_temp_i->temp_min = 0;
1760
+ }
1761
+ }
1762
+ else if ((sub->type == SENSORS_SUBFEATURE_TEMP_MAX)) {
1763
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_temp_i->temp_max))) {
1764
+ st_pwr_temp_i->temp_max = 0;
1765
+ }
1766
+ }
1767
+ }
1768
+ count++;
1769
+ }
1770
+ }
1771
+ }
1772
+ #endif /* HAVE_SENSORS */
1773
+ }
1774
+
1775
+ /*
1776
+ ***************************************************************************
1777
+ * Read voltage inputs statistics.
1778
+ *
1779
+ * IN:
1780
+ * @st_pwr_in Structure where stats will be saved.
1781
+ * @nbr Total number of voltage inputs.
1782
+ *
1783
+ * OUT:
1784
+ * @st_pwr_in Structure with statistics.
1785
+ ***************************************************************************
1786
+ */
1787
+ void read_in(struct stats_pwr_in *st_pwr_in, int nbr)
1788
+ {
1789
+ #ifdef HAVE_SENSORS
1790
+ int count = 0;
1791
+ const sensors_chip_name *chip;
1792
+ const sensors_feature *feature;
1793
+ const sensors_subfeature *sub;
1794
+ struct stats_pwr_in *st_pwr_in_i;
1795
+ int chip_nr = 0;
1796
+ int i, j;
1797
+
1798
+ memset(st_pwr_in, 0, STATS_PWR_IN_SIZE);
1799
+ int err = 0;
1800
+
1801
+ while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) {
1802
+ i = 0;
1803
+ while ((feature = sensors_get_features(chip, &i))) {
1804
+ if ((feature->type == SENSORS_FEATURE_IN) && (count < nbr)) {
1805
+ j = 0;
1806
+ st_pwr_in_i = st_pwr_in + count;
1807
+ sensors_snprintf_chip_name(st_pwr_in_i->device, MAX_SENSORS_DEV_LEN, chip);
1808
+
1809
+ while ((sub = sensors_get_all_subfeatures(chip, feature, &j))) {
1810
+ if ((sub->type == SENSORS_SUBFEATURE_IN_INPUT) &&
1811
+ (sub->flags & SENSORS_MODE_R)) {
1812
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_in_i->in))) {
1813
+ st_pwr_in_i->in = 0;
1814
+ }
1815
+ }
1816
+ else if ((sub->type == SENSORS_SUBFEATURE_IN_MIN)) {
1817
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_in_i->in_min))) {
1818
+ st_pwr_in_i->in_min = 0;
1819
+ }
1820
+ }
1821
+ else if ((sub->type == SENSORS_SUBFEATURE_IN_MAX)) {
1822
+ if ((err = sensors_get_value(chip, sub->number, &st_pwr_in_i->in_max))) {
1823
+ st_pwr_in_i->in_max = 0;
1824
+ }
1825
+ }
1826
+ }
1827
+ count++;
1828
+ }
1829
+ }
1830
+ }
1831
+ #endif /* HAVE_SENSORS */
1832
+ }
1833
+
1834
+ /*
1835
+ ***************************************************************************
1836
+ * Read hugepages statistics from /proc/meminfo.
1837
+ *
1838
+ * IN:
1839
+ * @st_huge Structure where stats will be saved.
1840
+ *
1841
+ * OUT:
1842
+ * @st_huge Structure with statistics.
1843
+ ***************************************************************************
1844
+ */
1845
+ void read_meminfo_huge(struct stats_huge *st_huge)
1846
+ {
1847
+ FILE *fp;
1848
+ char line[128];
1849
+ unsigned long szhkb = 0;
1850
+
1851
+ if ((fp = fopen(MEMINFO, "r")) == NULL)
1852
+ return;
1853
+
1854
+ while (fgets(line, 128, fp) != NULL) {
1855
+
1856
+ if (!strncmp(line, "HugePages_Total:", 16)) {
1857
+ /* Read the total number of huge pages */
1858
+ sscanf(line + 16, "%lu", &st_huge->tlhkb);
1859
+ }
1860
+ else if (!strncmp(line, "HugePages_Free:", 15)) {
1861
+ /* Read the number of free huge pages */
1862
+ sscanf(line + 15, "%lu", &st_huge->frhkb);
1863
+ }
1864
+ else if (!strncmp(line, "Hugepagesize:", 13)) {
1865
+ /* Read the default size of a huge page in kB */
1866
+ sscanf(line + 13, "%lu", &szhkb);
1867
+ }
1868
+ }
1869
+
1870
+ fclose(fp);
1871
+
1872
+ /* We want huge pages stats in kB and not expressed in a number of pages */
1873
+ st_huge->tlhkb *= szhkb;
1874
+ st_huge->frhkb *= szhkb;
1875
+ }
1876
+
1877
+ /*
1878
+ ***************************************************************************
1879
+ * Read CPU average frequencies statistics.
1880
+ *
1881
+ * IN:
1882
+ * @st_pwr_wghfreq Structure where stats will be saved.
1883
+ * @cpu_nr CPU number for which time_in_state date will be read.
1884
+ * @nbr Total number of states (frequencies).
1885
+ *
1886
+ * OUT:
1887
+ * @st_pwr_wghfreq Structure with statistics.
1888
+ ***************************************************************************
1889
+ */
1890
+ void read_time_in_state(struct stats_pwr_wghfreq *st_pwr_wghfreq, int cpu_nr, int nbr)
1891
+ {
1892
+ FILE *fp;
1893
+ struct stats_pwr_wghfreq *st_pwr_wghfreq_j;
1894
+ char filename[MAX_PF_NAME];
1895
+ char line[128];
1896
+ int j = 0;
1897
+ unsigned long freq;
1898
+ unsigned long long time_in_state;
1899
+
1900
+ snprintf(filename, MAX_PF_NAME, "%s/cpu%d/%s",
1901
+ SYSFS_DEVCPU, cpu_nr, SYSFS_TIME_IN_STATE);
1902
+ if ((fp = fopen(filename, "r")) == NULL)
1903
+ return;
1904
+
1905
+ while (fgets(line, 128, fp) != NULL) {
1906
+
1907
+ sscanf(line, "%lu %llu", &freq, &time_in_state);
1908
+
1909
+ if (j < nbr) {
1910
+ /* Save current frequency and time */
1911
+ st_pwr_wghfreq_j = st_pwr_wghfreq + j;
1912
+ st_pwr_wghfreq_j->freq = freq;
1913
+ st_pwr_wghfreq_j->time_in_state = time_in_state;
1914
+ j++;
1915
+ }
1916
+ }
1917
+
1918
+ fclose(fp);
1919
+ }
1920
+
1921
+ /*
1922
+ ***************************************************************************
1923
+ * Read machine uptime, independently of the number of processors.
1924
+ *
1925
+ * OUT:
1926
+ * @uptime Uptime value in jiffies.
1927
+ ***************************************************************************
1928
+ */
1929
+ void read_uptime(unsigned long long *uptime)
1930
+ {
1931
+ FILE *fp;
1932
+ char line[128];
1933
+ unsigned long up_sec, up_cent;
1934
+
1935
+ if ((fp = fopen(UPTIME, "r")) == NULL)
1936
+ return;
1937
+
1938
+ if (fgets(line, 128, fp) == NULL)
1939
+ return;
1940
+
1941
+ sscanf(line, "%lu.%lu", &up_sec, &up_cent);
1942
+ *uptime = (unsigned long long) up_sec * HZ +
1943
+ (unsigned long long) up_cent * HZ / 100;
1944
+
1945
+ fclose(fp);
1946
+
1947
+ }
1948
+
1949
+ /*
1950
+ ***************************************************************************
1951
+ * Count number of interrupts that are in /proc/stat file.
1952
+ *
1953
+ * RETURNS:
1954
+ * Number of interrupts, including total number of interrupts.
1955
+ ***************************************************************************
1956
+ */
1957
+ int get_irq_nr(void)
1958
+ {
1959
+ FILE *fp;
1960
+ char line[8192];
1961
+ int in = 0;
1962
+ int pos = 4;
1963
+
1964
+ if ((fp = fopen(STAT, "r")) == NULL)
1965
+ return 0;
1966
+
1967
+ while (fgets(line, 8192, fp) != NULL) {
1968
+
1969
+ if (!strncmp(line, "intr ", 5)) {
1970
+
1971
+ while (pos < strlen(line)) {
1972
+ in++;
1973
+ pos += strcspn(line + pos + 1, " ") + 1;
1974
+ }
1975
+ }
1976
+ }
1977
+
1978
+ fclose(fp);
1979
+
1980
+ return in;
1981
+ }
1982
+
1983
+ /*
1984
+ ***************************************************************************
1985
+ * Find number of serial lines that support tx/rx accounting
1986
+ * in /proc/tty/driver/serial file.
1987
+ *
1988
+ * RETURNS:
1989
+ * Number of serial lines supporting tx/rx accouting.
1990
+ ***************************************************************************
1991
+ */
1992
+ int get_serial_nr(void)
1993
+ {
1994
+ FILE *fp;
1995
+ char line[256];
1996
+ int sl = 0;
1997
+
1998
+ if ((fp = fopen(SERIAL, "r")) == NULL)
1999
+ return 0; /* No SERIAL file */
2000
+
2001
+ while (fgets(line, 256, fp) != NULL) {
2002
+ /*
2003
+ * tx/rx statistics are always present,
2004
+ * except when serial line is unknown.
2005
+ */
2006
+ if (strstr(line, "tx:") != NULL) {
2007
+ sl++;
2008
+ }
2009
+ }
2010
+
2011
+ fclose(fp);
2012
+
2013
+ return sl;
2014
+ }
2015
+
2016
+ /*
2017
+ ***************************************************************************
2018
+ * Find number of interfaces (network devices) that are in /proc/net/dev
2019
+ * file.
2020
+ *
2021
+ * RETURNS:
2022
+ * Number of network interfaces.
2023
+ ***************************************************************************
2024
+ */
2025
+ int get_iface_nr(void)
2026
+ {
2027
+ FILE *fp;
2028
+ char line[128];
2029
+ int iface = 0;
2030
+
2031
+ if ((fp = fopen(NET_DEV, "r")) == NULL)
2032
+ return 0; /* No network device file */
2033
+
2034
+ while (fgets(line, 128, fp) != NULL) {
2035
+ if (strchr(line, ':')) {
2036
+ iface++;
2037
+ }
2038
+ }
2039
+
2040
+ fclose(fp);
2041
+
2042
+ return iface;
2043
+ }
2044
+
2045
+ /*
2046
+ ***************************************************************************
2047
+ * Find number of devices and partitions available in /proc/diskstats.
2048
+ *
2049
+ * IN:
2050
+ * @count_part Set to TRUE if devices _and_ partitions are to be
2051
+ * counted.
2052
+ * @only_used_dev When counting devices, set to TRUE if only devices
2053
+ * with non zero stats must be counted.
2054
+ *
2055
+ * RETURNS:
2056
+ * Number of devices (and partitions).
2057
+ ***************************************************************************
2058
+ */
2059
+ int get_diskstats_dev_nr(int count_part, int only_used_dev)
2060
+ {
2061
+ FILE *fp;
2062
+ char line[256];
2063
+ char dev_name[MAX_NAME_LEN];
2064
+ int dev = 0, i;
2065
+ unsigned long rd_ios, wr_ios;
2066
+
2067
+ if ((fp = fopen(DISKSTATS, "r")) == NULL)
2068
+ /* File non-existent */
2069
+ return 0;
2070
+
2071
+ /*
2072
+ * Counting devices and partitions is simply a matter of counting
2073
+ * the number of lines...
2074
+ */
2075
+ while (fgets(line, 256, fp) != NULL) {
2076
+ if (!count_part) {
2077
+ i = sscanf(line, "%*d %*d %s %lu %*u %*u %*u %lu",
2078
+ dev_name, &rd_ios, &wr_ios);
2079
+ if ((i == 2) || !is_device(dev_name))
2080
+ /* It was a partition and not a device */
2081
+ continue;
2082
+ if (only_used_dev && !rd_ios && !wr_ios)
2083
+ /* Unused device */
2084
+ continue;
2085
+ }
2086
+ dev++;
2087
+ }
2088
+
2089
+ fclose(fp);
2090
+
2091
+ return dev;
2092
+ }
2093
+
2094
+ /*
2095
+ ***************************************************************************
2096
+ * Get number of devices in /proc/diskstats.
2097
+ *
2098
+ * IN:
2099
+ * @f Non zero (true) if disks *and* partitions should be counted, and
2100
+ * zero (false) if only disks must be counted.
2101
+ *
2102
+ * RETURNS:
2103
+ * Number of devices.
2104
+ ***************************************************************************
2105
+ */
2106
+ int get_disk_nr(unsigned int f)
2107
+ {
2108
+ int disk_nr;
2109
+
2110
+ /*
2111
+ * Partitions are taken into account by sar -d only with
2112
+ * kernels 2.6.25 and later.
2113
+ */
2114
+ disk_nr = get_diskstats_dev_nr(f, CNT_USED_DEV);
2115
+
2116
+ return disk_nr;
2117
+ }
2118
+
2119
+ /*
2120
+ ***************************************************************************
2121
+ * Count number of processors in /sys.
2122
+ *
2123
+ * RETURNS:
2124
+ * Number of processors (online and offline).
2125
+ * A value of 0 means that /sys was not mounted.
2126
+ * A value of N (!=0) means N processor(s) (cpu0 .. cpu(N-1)).
2127
+ ***************************************************************************
2128
+ */
2129
+ int get_sys_cpu_nr(void)
2130
+ {
2131
+ DIR *dir;
2132
+ struct dirent *drd;
2133
+ struct stat buf;
2134
+ char line[MAX_PF_NAME];
2135
+ int proc_nr = 0;
2136
+
2137
+ /* Open relevant /sys directory */
2138
+ if ((dir = opendir(SYSFS_DEVCPU)) == NULL)
2139
+ return 0;
2140
+
2141
+ /* Get current file entry */
2142
+ while ((drd = readdir(dir)) != NULL) {
2143
+
2144
+ if (!strncmp(drd->d_name, "cpu", 3) && isdigit(drd->d_name[3])) {
2145
+ snprintf(line, MAX_PF_NAME, "%s/%s", SYSFS_DEVCPU, drd->d_name);
2146
+ line[MAX_PF_NAME - 1] = '\0';
2147
+ if (stat(line, &buf) < 0)
2148
+ continue;
2149
+ if (S_ISDIR(buf.st_mode)) {
2150
+ proc_nr++;
2151
+ }
2152
+ }
2153
+ }
2154
+
2155
+ /* Close directory */
2156
+ closedir(dir);
2157
+
2158
+ return proc_nr;
2159
+ }
2160
+
2161
+ /*
2162
+ ***************************************************************************
2163
+ * Count number of processors in /proc/stat.
2164
+ *
2165
+ * RETURNS:
2166
+ * Number of processors. The returned value is greater than or equal to the
2167
+ * number of online processors.
2168
+ * A value of 0 means one processor and non SMP kernel.
2169
+ * A value of N (!=0) means N processor(s) (0 .. N-1) with SMP kernel.
2170
+ ***************************************************************************
2171
+ */
2172
+ int get_proc_cpu_nr(void)
2173
+ {
2174
+ FILE *fp;
2175
+ char line[16];
2176
+ int num_proc, proc_nr = -1;
2177
+
2178
+ if ((fp = fopen(STAT, "r")) == NULL) {
2179
+ fprintf(stderr, _("Cannot open %s: %s\n"), STAT, strerror(errno));
2180
+ exit(1);
2181
+ }
2182
+
2183
+ while (fgets(line, 16, fp) != NULL) {
2184
+
2185
+ if (strncmp(line, "cpu ", 4) && !strncmp(line, "cpu", 3)) {
2186
+ sscanf(line + 3, "%d", &num_proc);
2187
+ if (num_proc > proc_nr) {
2188
+ proc_nr = num_proc;
2189
+ }
2190
+ }
2191
+ }
2192
+
2193
+ fclose(fp);
2194
+
2195
+ return (proc_nr + 1);
2196
+ }
2197
+
2198
+ /*
2199
+ ***************************************************************************
2200
+ * Count the number of processors on the machine.
2201
+ * Try to use /sys for that, or /proc/stat if /sys doesn't exist.
2202
+ *
2203
+ * IN:
2204
+ * @max_nr_cpus Maximum number of proc that sysstat can handle.
2205
+ *
2206
+ * RETURNS:
2207
+ * Number of processors.
2208
+ * 0: one proc and non SMP kernel.
2209
+ * 1: one proc and SMP kernel (NB: On SMP machines where all the CPUs but
2210
+ * one have been disabled, we get the total number of proc since we use
2211
+ * /sys to count them).
2212
+ * 2: two proc...
2213
+ ***************************************************************************
2214
+ */
2215
+ int get_cpu_nr(unsigned int max_nr_cpus)
2216
+ {
2217
+ int cpu_nr;
2218
+
2219
+ if ((cpu_nr = get_sys_cpu_nr()) == 0) {
2220
+ /* /sys may be not mounted. Use /proc/stat instead */
2221
+ cpu_nr = get_proc_cpu_nr();
2222
+ }
2223
+
2224
+ if (cpu_nr > max_nr_cpus) {
2225
+ fprintf(stderr, _("Cannot handle so many processors!\n"));
2226
+ exit(1);
2227
+ }
2228
+
2229
+ return cpu_nr;
2230
+ }
2231
+
2232
+ /*
2233
+ ***************************************************************************
2234
+ * Find number of interrupts available per processor (use
2235
+ * /proc/interrupts file or /proc/softirqs).
2236
+ *
2237
+ * IN:
2238
+ * @file /proc file to read (interrupts or softirqs).
2239
+ * @max_nr_irqcpu Maximum number of interrupts per processor that
2240
+ * sadc can handle.
2241
+ * @cpu_nr Number of processors.
2242
+ *
2243
+ * RETURNS:
2244
+ * Number of interrupts per processor + a pre-allocation constant.
2245
+ ***************************************************************************
2246
+ */
2247
+ int get_irqcpu_nr(char *file, int max_nr_irqcpu, int cpu_nr)
2248
+ {
2249
+ FILE *fp;
2250
+ char *line = NULL;
2251
+ unsigned int irq = 0;
2252
+ int p;
2253
+
2254
+ if ((fp = fopen(file, "r")) == NULL)
2255
+ return 0; /* No interrupts file */
2256
+
2257
+ SREALLOC(line, char, INTERRUPTS_LINE + 11 * cpu_nr);
2258
+
2259
+ while ((fgets(line, INTERRUPTS_LINE + 11 * cpu_nr , fp) != NULL) &&
2260
+ (irq < max_nr_irqcpu)) {
2261
+ p = strcspn(line, ":");
2262
+ if ((p > 0) && (p < 16)) {
2263
+ irq++;
2264
+ }
2265
+ }
2266
+
2267
+ fclose(fp);
2268
+
2269
+ if (line) {
2270
+ free(line);
2271
+ }
2272
+
2273
+ return irq;
2274
+ }
2275
+
2276
+ #ifdef HAVE_SENSORS
2277
+ /*
2278
+ ***************************************************************************
2279
+ * Count the number of sensors of given type on the machine.
2280
+ *
2281
+ * IN:
2282
+ * @type Type of sensors.
2283
+ *
2284
+ * RETURNS:
2285
+ * Number of sensors.
2286
+ ***************************************************************************
2287
+ */
2288
+ int get_sensors_nr(sensors_feature_type type) {
2289
+ int count = 0;
2290
+ const sensors_chip_name *chip;
2291
+ const sensors_feature *feature;
2292
+ int chip_nr = 0;
2293
+ int i;
2294
+
2295
+ while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) {
2296
+ i = 0;
2297
+ while ((feature = sensors_get_features(chip, &i))) {
2298
+ if (feature->type == type) {
2299
+ count++;
2300
+ }
2301
+ }
2302
+ }
2303
+
2304
+ return count;
2305
+ }
2306
+ #endif /* HAVE_SENSORS */
2307
+
2308
+ /*
2309
+ ***************************************************************************
2310
+ * Count the number of fans on the machine.
2311
+ *
2312
+ * RETURNS:
2313
+ * Number of fans.
2314
+ ***************************************************************************
2315
+ */
2316
+ int get_fan_nr(void)
2317
+ {
2318
+ #ifdef HAVE_SENSORS
2319
+ return get_sensors_nr(SENSORS_FEATURE_FAN);
2320
+ #else
2321
+ return 0;
2322
+ #endif /* HAVE_SENSORS */
2323
+ }
2324
+
2325
+ /*
2326
+ ***************************************************************************
2327
+ * Count the number of temperature sensors on the machine.
2328
+ *
2329
+ * RETURNS:
2330
+ * Number of temperature sensors.
2331
+ ***************************************************************************
2332
+ */
2333
+ int get_temp_nr(void)
2334
+ {
2335
+ #ifdef HAVE_SENSORS
2336
+ return get_sensors_nr(SENSORS_FEATURE_TEMP);
2337
+ #else
2338
+ return 0;
2339
+ #endif /* HAVE_SENSORS */
2340
+
2341
+ }
2342
+
2343
+ /*
2344
+ ***************************************************************************
2345
+ * Count the number of voltage inputs on the machine.
2346
+ *
2347
+ * RETURNS:
2348
+ * Number of voltage inputs.
2349
+ ***************************************************************************
2350
+ */
2351
+ int get_in_nr(void)
2352
+ {
2353
+ #ifdef HAVE_SENSORS
2354
+ return get_sensors_nr(SENSORS_FEATURE_IN);
2355
+ #else
2356
+ return 0;
2357
+ #endif /* HAVE_SENSORS */
2358
+
2359
+ }
2360
+
2361
+ /*
2362
+ ***************************************************************************
2363
+ * Count number of possible frequencies for CPU#0.
2364
+ *
2365
+ * RETURNS:
2366
+ * Number of frequencies.
2367
+ ***************************************************************************
2368
+ */
2369
+ int get_freq_nr(void)
2370
+ {
2371
+ FILE *fp;
2372
+ char filename[MAX_PF_NAME];
2373
+ char line[128];
2374
+ int freq = 0;
2375
+
2376
+ snprintf(filename, MAX_PF_NAME, "%s/cpu0/%s",
2377
+ SYSFS_DEVCPU, SYSFS_TIME_IN_STATE);
2378
+ if ((fp = fopen(filename, "r")) == NULL)
2379
+ return 0; /* No time_in_state file for CPU#0 */
2380
+
2381
+ while (fgets(line, 128, fp) != NULL) {
2382
+ freq++;
2383
+ }
2384
+
2385
+ fclose(fp);
2386
+
2387
+ return freq;
2388
+ }