ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/statgrab/statgrab.c
(Generate patch)

Comparing projects/libstatgrab/src/statgrab/statgrab.c (file contents):
Revision 1.6 by ats, Fri Aug 29 06:48:04 2003 UTC vs.
Revision 1.27 by ats, Fri Jul 16 11:17:16 2004 UTC

# Line 1 | Line 1
1   /*
2 < * i-scream central monitoring system
2 > * i-scream libstatgrab
3   * http://www.i-scream.org
4 < * Copyright (C) 2000-2003 i-scream
4 > * Copyright (C) 2000-2004 i-scream
5   *
6   * This program is free software; you can redistribute it and/or
7   * modify it under the terms of the GNU General Public License
# Line 16 | Line 16
16   * You should have received a copy of the GNU General Public License
17   * along with this program; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 + *
20 + * $Id$
21   */
22  
23   #ifdef HAVE_CONFIG_H
# Line 35 | Line 37 | typedef enum {
37          FLOAT,
38          DOUBLE,
39          STRING,
40 <        INT
40 >        INT,
41 >        BOOL,
42 >        DUPLEX
43   } stat_type;
44  
45   typedef enum {
# Line 66 | Line 70 | display_mode_type display_mode = DISPLAY_LINUX;
70   repeat_mode_type repeat_mode = REPEAT_NONE;
71   int repeat_time = 1;
72   int use_cpu_percent = 0;
73 + int use_diffs = 0;
74  
75   /* Exit with an error message. */
76   void die(const char *s) {
# Line 139 | Line 144 | void add_stat(stat_type type, void *stat, ...) {
144          ++num_stats;
145   }
146  
147 < /* Compare two stats by name, for sorting purposes. */
147 > /* Compare two stats by name for qsort and bsearch. */
148   int stats_compare(const void *a, const void *b) {
149          return strcmp(((stat *)a)->name, ((stat *)b)->name);
150   }
151  
152 < /* Clear and rebuild the stats array. */
153 < void get_stats(int use_diffs) {
154 <        cpu_states_t *cpu_s;
155 <        cpu_percent_t *cpu_p;
151 <        mem_stat_t *mem;
152 <        load_stat_t *load;
153 <        user_stat_t *user;
154 <        swap_stat_t *swap;
155 <        general_stat_t *gen;
156 <        disk_stat_t *disk;
157 <        diskio_stat_t *diskio;
158 <        process_stat_t *proc;
159 <        network_stat_t *net;
160 <        page_stat_t *page;
161 <        static int zero = 0;
162 <        int n, i;
152 > /* Compare up to the length of the key for bsearch. */
153 > int stats_compare_prefix(const void *key, const void *item) {
154 >        const char *kn = ((stat *)key)->name;
155 >        const char *in = ((stat *)item)->name;
156  
157 <        clear_stats();
157 >        return strncmp(kn, in, strlen(kn));
158 > }
159  
160 + void populate_const() {
161 +        static int zero = 0;
162 +
163          /* Constants, for use with MRTG mode. */
164          add_stat(INT, &zero, "const", "0", NULL);
165 + }
166  
167 <        /* FIXME when only fetching some stats, it'd be more efficient to only
170 <           do the libstatgrab calls needed, rather than fetching everything. */
171 <
167 > void populate_cpu() {
168          if (use_cpu_percent) {
169 <                cpu_p = cpu_percent_usage();
169 >                sg_cpu_percents *cpu_p = sg_get_cpu_percents();
170 >
171                  if (cpu_p != NULL) {
172                          add_stat(FLOAT, &cpu_p->user,
173 <                                 "cpu", "user", NULL);
173 >                                 "cpu", "user", NULL);
174                          add_stat(FLOAT, &cpu_p->kernel,
175 <                                 "cpu", "kernel", NULL);
175 >                                 "cpu", "kernel", NULL);
176                          add_stat(FLOAT, &cpu_p->idle,
177 <                                 "cpu", "idle", NULL);
177 >                                 "cpu", "idle", NULL);
178                          add_stat(FLOAT, &cpu_p->iowait,
179 <                                 "cpu", "iowait", NULL);
179 >                                 "cpu", "iowait", NULL);
180                          add_stat(FLOAT, &cpu_p->swap,
181 <                                 "cpu", "swap", NULL);
181 >                                 "cpu", "swap", NULL);
182                          add_stat(FLOAT, &cpu_p->nice,
183 <                                 "cpu", "nice", NULL);
184 <                        add_stat(TIME_T, &cpu_p->systime,
185 <                                 "cpu", "time_taken", NULL);
183 >                                 "cpu", "nice", NULL);
184 >                        add_stat(TIME_T, &cpu_p->time_taken,
185 >                                 "cpu", "time_taken", NULL);
186                  }
187          } else {
188 <                cpu_s = use_diffs ? get_cpu_diff() : get_cpu_totals();
188 >                sg_cpu_stats *cpu_s;
189 >
190 >                cpu_s = use_diffs ? sg_get_cpu_stats_diff()
191 >                                  : sg_get_cpu_stats();
192                  if (cpu_s != NULL) {
193                          add_stat(LONG_LONG, &cpu_s->user,
194 <                                 "cpu", "user", NULL);
194 >                                 "cpu", "user", NULL);
195                          add_stat(LONG_LONG, &cpu_s->kernel,
196 <                                 "cpu", "kernel", NULL);
196 >                                 "cpu", "kernel", NULL);
197                          add_stat(LONG_LONG, &cpu_s->idle,
198 <                                 "cpu", "idle", NULL);
198 >                                 "cpu", "idle", NULL);
199                          add_stat(LONG_LONG, &cpu_s->iowait,
200 <                                 "cpu", "iowait", NULL);
200 >                                 "cpu", "iowait", NULL);
201                          add_stat(LONG_LONG, &cpu_s->swap,
202 <                                 "cpu", "swap", NULL);
202 >                                 "cpu", "swap", NULL);
203                          add_stat(LONG_LONG, &cpu_s->nice,
204 <                                 "cpu", "nice", NULL);
204 >                                 "cpu", "nice", NULL);
205                          add_stat(LONG_LONG, &cpu_s->total,
206 <                                 "cpu", "total", NULL);
206 >                                 "cpu", "total", NULL);
207                          add_stat(TIME_T, &cpu_s->systime,
208 <                                 "cpu", "systime", NULL);
208 >                                 "cpu", "systime", NULL);
209                  }
210          }
211 + }
212  
213 <        mem = get_memory_stats();
213 > void populate_mem() {
214 >        sg_mem_stats *mem = sg_get_mem_stats();
215 >
216          if (mem != NULL) {
217                  add_stat(LONG_LONG, &mem->total, "mem", "total", NULL);
218                  add_stat(LONG_LONG, &mem->free, "mem", "free", NULL);
219                  add_stat(LONG_LONG, &mem->used, "mem", "used", NULL);
220                  add_stat(LONG_LONG, &mem->cache, "mem", "cache", NULL);
221          }
222 + }
223  
224 <        load = get_load_stats();
224 > void populate_load() {
225 >        sg_load_stats *load = sg_get_load_stats();
226 >
227          if (load != NULL) {
228                  add_stat(DOUBLE, &load->min1, "load", "min1", NULL);
229                  add_stat(DOUBLE, &load->min5, "load", "min5", NULL);
230                  add_stat(DOUBLE, &load->min15, "load", "min15", NULL);
231          }
232 + }
233  
234 <        user = get_user_stats();
234 > void populate_user() {
235 >        sg_user_stats *user = sg_get_user_stats();
236 >
237          if (user != NULL) {
238                  add_stat(INT, &user->num_entries, "user", "num", NULL);
239                  add_stat(STRING, &user->name_list, "user", "names", NULL);
240          }
241 + }
242  
243 <        swap = get_swap_stats();
243 > void populate_swap() {
244 >        sg_swap_stats *swap = sg_get_swap_stats();
245 >
246          if (swap != NULL) {
247                  add_stat(LONG_LONG, &swap->total, "swap", "total", NULL);
248                  add_stat(LONG_LONG, &swap->used, "swap", "used", NULL);
249                  add_stat(LONG_LONG, &swap->free, "swap", "free", NULL);
250          }
251 + }
252  
253 <        gen = get_general_stats();
254 <        if (gen != NULL) {
255 <                add_stat(STRING, &gen->os_name,
256 <                         "general", "os_name", NULL);
257 <                add_stat(STRING, &gen->os_release,
258 <                         "general", "os_release", NULL);
259 <                add_stat(STRING, &gen->os_version,
260 <                         "general", "os_version", NULL);
261 <                add_stat(STRING, &gen->platform, "general", "platform", NULL);
262 <                add_stat(STRING, &gen->hostname, "general", "hostname", NULL);
263 <                add_stat(TIME_T, &gen->uptime, "general", "uptime", NULL);
253 > void populate_general() {
254 >        /* FIXME this should be renamed to host. */
255 >        sg_host_info *host = sg_get_host_info();
256 >
257 >        if (host != NULL) {
258 >                add_stat(STRING, &host->os_name,
259 >                         "general", "os_name", NULL);
260 >                add_stat(STRING, &host->os_release,
261 >                         "general", "os_release", NULL);
262 >                add_stat(STRING, &host->os_version,
263 >                         "general", "os_version", NULL);
264 >                add_stat(STRING, &host->platform, "general", "platform", NULL);
265 >                add_stat(STRING, &host->hostname, "general", "hostname", NULL);
266 >                add_stat(TIME_T, &host->uptime, "general", "uptime", NULL);
267          }
268 + }
269  
270 <        disk = get_disk_stats(&n);
270 > void populate_fs() {
271 >        int n, i;
272 >        sg_fs_stats *disk = sg_get_fs_stats(&n);
273 >
274          if (disk != NULL) {
275                  for (i = 0; i < n; i++) {
276                          /* FIXME it'd be nicer if libstatgrab did this */
277 <                        const char *name = disk[i].device_name,
278 <                                   *p = strrchr(name, '/');
279 <                        if (p != NULL)
280 <                                name = p + 1;
281 <                        if (*name == '\0')
282 <                                name = "root";
283 <        
277 >                        char *buf, *name, *p;
278 >                        const char *device = disk[i].device_name;
279 >
280 >                        if (strcmp(device, "/") == 0)
281 >                                device = "root";
282 >
283 >                        buf = strdup(device);
284 >                        if (buf == NULL)
285 >                                die("out of memory");
286 >
287 >                        name = buf;
288 >                        if (strlen(name) == 2 && name[1] == ':')
289 >                                name[1] = '\0';
290 >                        if (strncmp(name, "/dev/", 5) == 0)
291 >                                name += 5;
292 >                        while ((p = strchr(name, '/')) != NULL)
293 >                                *p = '_';
294 >
295                          add_stat(STRING, &disk[i].device_name,
296 <                                 "fs", name, "device_name", NULL);
296 >                                 "fs", name, "device_name", NULL);
297                          add_stat(STRING, &disk[i].fs_type,
298 <                                 "fs", name, "fs_type", NULL);
298 >                                 "fs", name, "fs_type", NULL);
299                          add_stat(STRING, &disk[i].mnt_point,
300 <                                 "fs", name, "mnt_point", NULL);
300 >                                 "fs", name, "mnt_point", NULL);
301                          add_stat(LONG_LONG, &disk[i].size,
302 <                                 "fs", name, "size", NULL);
302 >                                 "fs", name, "size", NULL);
303                          add_stat(LONG_LONG, &disk[i].used,
304 <                                 "fs", name, "used", NULL);
304 >                                 "fs", name, "used", NULL);
305                          add_stat(LONG_LONG, &disk[i].avail,
306 <                                 "fs", name, "avail", NULL);
306 >                                 "fs", name, "avail", NULL);
307                          add_stat(LONG_LONG, &disk[i].total_inodes,
308 <                                 "fs", name, "total_inodes", NULL);
308 >                                 "fs", name, "total_inodes", NULL);
309                          add_stat(LONG_LONG, &disk[i].used_inodes,
310 <                                 "fs", name, "used_inodes", NULL);
310 >                                 "fs", name, "used_inodes", NULL);
311                          add_stat(LONG_LONG, &disk[i].free_inodes,
312 <                                 "fs", name, "free_inodes", NULL);
312 >                                 "fs", name, "free_inodes", NULL);
313 >
314 >                        free(buf);
315                  }
316          }
317 + }
318  
319 <        diskio = use_diffs ? get_diskio_stats_diff(&n) : get_diskio_stats(&n);
319 > void populate_disk() {
320 >        int n, i;
321 >        sg_disk_io_stats *diskio;
322 >
323 >        diskio = use_diffs ? sg_get_disk_io_stats_diff(&n)
324 >                           : sg_get_disk_io_stats(&n);
325          if (diskio != NULL) {
326                  for (i = 0; i < n; i++) {
327                          const char *name = diskio[i].disk_name;
328          
329                          add_stat(STRING, &diskio[i].disk_name,
330 <                                 "disk", name, "disk_name", NULL);
330 >                                 "disk", name, "disk_name", NULL);
331                          add_stat(LONG_LONG, &diskio[i].read_bytes,
332 <                                 "disk", name, "read_bytes", NULL);
332 >                                 "disk", name, "read_bytes", NULL);
333                          add_stat(LONG_LONG, &diskio[i].write_bytes,
334 <                                 "disk", name, "write_bytes", NULL);
334 >                                 "disk", name, "write_bytes", NULL);
335                          add_stat(TIME_T, &diskio[i].systime,
336 <                                 "disk", name, "systime", NULL);
336 >                                 "disk", name, "systime", NULL);
337                  }
338          }
339 + }
340  
341 <        proc = get_process_stats();
341 > void populate_proc() {
342 >        /* FIXME expose individual process info too */
343 >        sg_process_count *proc = sg_get_process_count();
344 >
345          if (proc != NULL) {
346                  add_stat(INT, &proc->total, "proc", "total", NULL);
347                  add_stat(INT, &proc->running, "proc", "running", NULL);
# Line 306 | Line 349 | void get_stats(int use_diffs) {
349                  add_stat(INT, &proc->stopped, "proc", "stopped", NULL);
350                  add_stat(INT, &proc->zombie, "proc", "zombie", NULL);
351          }
352 + }
353  
354 <        net = use_diffs ? get_network_stats_diff(&n) : get_network_stats(&n);
355 <        if (net != NULL) {
356 <                for (i = 0; i < n; i++) {
357 <                        const char *name = net[i].interface_name;
354 > void populate_net() {
355 >        int num_io, num_iface, i;
356 >        sg_network_io_stats *io;
357 >        sg_network_iface_stats *iface;
358 >
359 >        io = use_diffs ? sg_get_network_io_stats_diff(&num_io)
360 >                       : sg_get_network_io_stats(&num_io);
361 >        if (io != NULL) {
362 >                for (i = 0; i < num_io; i++) {
363 >                        const char *name = io[i].interface_name;
364          
365 <                        add_stat(STRING, &net[i].interface_name,
366 <                                 "net", name, "interface_name", NULL);
367 <                        add_stat(LONG_LONG, &net[i].tx,
368 <                                 "net", name, "tx", NULL);
369 <                        add_stat(LONG_LONG, &net[i].rx,
370 <                                 "net", name, "rx", NULL);
371 <                        add_stat(TIME_T, &net[i].systime,
372 <                                 "net", name, "systime", NULL);
365 >                        add_stat(STRING, &io[i].interface_name,
366 >                                 "net", name, "interface_name", NULL);
367 >                        add_stat(LONG_LONG, &io[i].tx,
368 >                                 "net", name, "tx", NULL);
369 >                        add_stat(LONG_LONG, &io[i].rx,
370 >                                 "net", name, "rx", NULL);
371 >                        add_stat(LONG_LONG, &io[i].ipackets,
372 >                                 "net", name, "ipackets", NULL);
373 >                        add_stat(LONG_LONG, &io[i].opackets,
374 >                                 "net", name, "opackets", NULL);
375 >                        add_stat(LONG_LONG, &io[i].ierrors,
376 >                                 "net", name, "ierrors", NULL);
377 >                        add_stat(LONG_LONG, &io[i].oerrors,
378 >                                 "net", name, "oerrors", NULL);
379 >                        add_stat(LONG_LONG, &io[i].collisions,
380 >                                 "net", name, "collisions", NULL);
381 >                        add_stat(TIME_T, &io[i].systime,
382 >                                 "net", name, "systime", NULL);
383                  }
384          }
385  
386 <        page = use_diffs ? get_page_stats_diff() : get_page_stats();
386 >        iface = sg_get_network_iface_stats(&num_iface);
387 >        if (iface != NULL) {
388 >                for (i = 0; i < num_iface; i++) {
389 >                        const char *name = iface[i].interface_name;
390 >                        int had_io = 0, j;
391 >
392 >                        /* If there wasn't a corresponding io stat,
393 >                           add interface_name from here. */
394 >                        if (io != NULL) {
395 >                                for (j = 0; j < num_io; j++) {
396 >                                        if (strcmp(io[j].interface_name,
397 >                                                   name) == 0) {
398 >                                                had_io = 1;
399 >                                                break;
400 >                                        }
401 >                                }
402 >                        }
403 >                        if (!had_io) {
404 >                                add_stat(STRING, &iface[i].interface_name,
405 >                                        "net", name, "interface_name", NULL);
406 >                        }
407 >
408 >                        add_stat(INT, &iface[i].speed,
409 >                                 "net", name, "speed", NULL);
410 >                        add_stat(BOOL, &iface[i].up,
411 >                                 "net", name, "up", NULL);
412 >                        add_stat(DUPLEX, &iface[i].dup,
413 >                                 "net", name, "duplex", NULL);
414 >                }
415 >        }
416 > }
417 >
418 > void populate_page() {
419 >        sg_page_stats *page;
420 >
421 >        page = use_diffs ? sg_get_page_stats_diff() : sg_get_page_stats();
422          if (page != NULL) {
423                  add_stat(LONG_LONG, &page->pages_pagein, "page", "in", NULL);
424                  add_stat(LONG_LONG, &page->pages_pageout, "page", "out", NULL);
425 <                add_stat(LONG_LONG, &page->systime, "page", "systime", NULL);
425 >                add_stat(TIME_T, &page->systime, "page", "systime", NULL);
426          }
427 + }
428  
429 <        qsort(stats, num_stats, sizeof *stats, stats_compare);
429 > typedef struct {
430 >        const char *name;
431 >        void (*populate)();
432 >        int interesting;
433 > } toplevel;
434 > toplevel toplevels[] = {
435 >        {"const.", populate_const, 0},
436 >        {"cpu.", populate_cpu, 0},
437 >        {"mem.", populate_mem, 0},
438 >        {"load.", populate_load, 0},
439 >        {"user.", populate_user, 0},
440 >        {"swap.", populate_swap, 0},
441 >        {"general.", populate_general, 0},
442 >        {"fs.", populate_fs, 0},
443 >        {"disk.", populate_disk, 0},
444 >        {"proc.", populate_proc, 0},
445 >        {"net.", populate_net, 0},
446 >        {"page.", populate_page, 0},
447 >        {NULL, NULL, 0}
448 > };
449 >
450 > /* Set the "interesting" flag on the sections that we actually need to
451 >   fetch. */
452 > void select_interesting(int argc, char **argv) {
453 >        toplevel *t;
454 >
455 >        if (argc == 0) {
456 >                for (t = &toplevels[0]; t->name != NULL; t++)
457 >                        t->interesting = 1;
458 >        } else {
459 >                int i;
460 >
461 >                for (i = 0; i < argc; i++) {
462 >                        for (t = &toplevels[0]; t->name != NULL; t++) {
463 >                                if (strncmp(argv[i], t->name,
464 >                                            strlen(t->name)) == 0) {
465 >                                        t->interesting = 1;
466 >                                        break;
467 >                                }
468 >                        }
469 >                }
470 >        }
471   }
472  
473 + /* Clear and rebuild the stats array. */
474 + void get_stats() {
475 +        toplevel *t;
476 +
477 +        clear_stats();
478 +
479 +        for (t = &toplevels[0]; t->name != NULL; t++) {
480 +                if (t->interesting)
481 +                        t->populate();
482 +        }
483 +
484 +        if (stats != NULL)
485 +                qsort(stats, num_stats, sizeof *stats, stats_compare);
486 + }
487 +
488   /* Print the value of a stat. */
489   void print_stat_value(const stat *s) {
490          void *v = s->stat;
491 +        long l;
492  
493          switch (s->type) {
494          case LONG_LONG:
# Line 343 | Line 496 | void print_stat_value(const stat *s) {
496                  break;
497          case TIME_T:
498                  /* FIXME option for formatted time? */
499 <                printf("%ld", *(time_t *)v);
499 >                l = *(time_t *)v;
500 >                printf("%ld", l);
501                  break;
502          case FLOAT:
503                  printf("%f", *(float *)v);
# Line 358 | Line 512 | void print_stat_value(const stat *s) {
512          case INT:
513                  printf("%d", *(int *)v);
514                  break;
515 +        case BOOL:
516 +                printf("%s", *(int *)v ? "true" : "false");
517 +                break;
518 +        case DUPLEX:
519 +                switch (*(sg_iface_duplex *) v) {
520 +                case SG_IFACE_DUPLEX_FULL:
521 +                        printf("full");
522 +                        break;
523 +                case SG_IFACE_DUPLEX_HALF:
524 +                        printf("half");
525 +                        break;
526 +                default:
527 +                        printf("unknown");
528 +                        break;
529 +                }
530 +                break;
531          }
532   }
533  
# Line 389 | Line 559 | void print_stats(int argc, char **argv) {
559          } else {
560                  /* Print selected stats. */
561                  for (i = optind; i < argc; i++) {
562 +                        char *name = argv[i];
563                          stat key;
564 <                        const stat *s;
564 >                        const stat *s, *end;
565 >                        int (*compare)(const void *, const void *);
566  
567 <                        key.name = argv[i];
568 <                        s = (const stat *)bsearch(&key, stats, num_stats,
569 <                                                  sizeof *stats,
570 <                                                  stats_compare);
571 <                        if (s != NULL) {
567 >                        key.name = name;
568 >                        if (name[strlen(name) - 1] == '.')
569 >                                compare = stats_compare_prefix;
570 >                        else
571 >                                compare = stats_compare;
572 >
573 >                        if (stats == NULL) {
574 >                                s = NULL;
575 >                        } else {
576 >                                s = (const stat *)bsearch(&key, stats,
577 >                                                          num_stats,
578 >                                                          sizeof *stats,
579 >                                                          compare);
580 >                        }
581 >
582 >                        if (s == NULL) {
583 >                                printf("Unknown stat %s\n", name);
584 >                                continue;
585 >                        }
586 >
587 >                        /* Find the range of stats the user wanted. */
588 >                        for (; s >= stats; s--) {
589 >                                if (compare(&key, s) != 0)
590 >                                        break;
591 >                        }
592 >                        s++;
593 >                        for (end = s; end < &stats[num_stats]; end++) {
594 >                                if (compare(&key, end) != 0)
595 >                                        break;
596 >                        }
597 >
598 >                        /* And print them. */
599 >                        for (; s < end; s++) {
600                                  print_stat(s);
601                          }
602                  }
# Line 405 | Line 605 | void print_stats(int argc, char **argv) {
605  
606   void usage() {
607          printf("Usage: statgrab [OPTION]... [STAT]...\n"
608 <               "Display system statistics (all statistics by default).\n"
608 >               "Display system statistics.\n"
609 >               "\n"
610 >               "If no STATs are given, all will be displayed. Specify 'STAT.' to display all\n"
611 >               "statistics starting with that prefix.\n"
612                 "\n");
613 <        printf("  -l         Linux sysctl-style output (default)\n"
614 <               "  -b         BSD sysctl-style output\n"
615 <               "  -m         MRTG-compatible output\n"
616 <               "  -u         Plain output (only show values)\n"
617 <               "  -n         Display cumulative stats once (default)\n"
618 <               "  -s         Display stat differences repeatedly\n"
619 <               "  -o         Display stat differences once\n"
613 >        printf("  -l     Linux sysctl-style output (default)\n"
614 >               "  -b     BSD sysctl-style output\n"
615 >               "  -m     MRTG-compatible output\n"
616 >               "  -u     Plain output (only show values)\n"
617 >               "  -n     Display cumulative stats once (default)\n"
618 >               "  -s     Display stat differences repeatedly\n"
619 >               "  -o     Display stat differences once\n"
620                 "  -t DELAY   When repeating, wait DELAY seconds between updates (default 1)\n"
621 <               "  -p         Display CPU usage differences as percentages rather than\n"
622 <               "             absolute values\n"
621 >               "  -p     Display CPU usage differences as percentages rather than\n"
622 >               "             absolute values\n"
623                 "\n");
624          printf("Version %s - report bugs to <%s>.\n",
625                 PACKAGE_VERSION, PACKAGE_BUGREPORT);
# Line 472 | Line 675 | int main(int argc, char **argv) {
675          if (use_cpu_percent && repeat_mode == REPEAT_NONE)
676                  die("CPU percentage usage display requires stat differences");
677  
678 +        if (repeat_mode == REPEAT_NONE)
679 +                use_diffs = 0;
680 +        else
681 +                use_diffs = 1;
682 +
683 +        select_interesting(argc - optind, &argv[optind]);
684 +
685 +        /* We don't care if statgrab_init fails, because we can just display
686 +           the statistics that can be read as non-root. */
687 +        sg_init();
688 +        if (sg_drop_privileges() != 0)
689 +                die("Failed to drop setuid/setgid privileges");
690 +
691          switch (repeat_mode) {
692          case REPEAT_NONE:
693 <                get_stats(0);
693 >                get_stats();
694                  print_stats(argc, argv);
695                  break;
696          case REPEAT_ONCE:
697 <                get_stats(1);
697 >                get_stats();
698                  sleep(repeat_time);
699 <                get_stats(1);
699 >                get_stats();
700                  print_stats(argc, argv);
701                  break;
702          case REPEAT_FOREVER:
703                  while (1) {
704 <                        get_stats(1);
704 >                        get_stats();
705                          print_stats(argc, argv);
706                          printf("\n");
707                          sleep(repeat_time);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines