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