perfmonger 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }