File: ifctrstat.c

package info (click to toggle)
ifupdown-ng 0.12.1-8
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 964 kB
  • sloc: ansic: 3,572; sh: 980; makefile: 233
file content (160 lines) | stat: -rw-r--r-- 3,650 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
 * cmd/ifctrstat.c
 * Purpose: Display statistics about interfaces on the system
 *
 * Copyright (c) 2020 Adélie Software in the Public Benefit, Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * This software is provided 'as is' and without any warranty, express or
 * implied.  In no event shall the authors be liable for any damages arising
 * from the use of this software.
 */

#include <errno.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "libifupdown/libifupdown.h"
#include "cmd/multicall.h"
#include "cmd/ifctrstat-linux.h"

extern struct counter_desc { const char *name; const void *data; } avail_counters[];
extern int avail_counters_count;

static bool show_label = true;

static bool
counter_is_valid(const char *candidate)
{
	for (int i = 0; i < avail_counters_count; i++)
	{
		if (strcasecmp(avail_counters[i].name, candidate) == 0)
			return true;
	}

	return false;
}

static void
print_counter(const char *iface, const char *name, const char *value)
{
	(void) iface;

	if (show_label)
		fprintf(stdout, "%s: %s\n", name, value);
	else
		fprintf(stdout, "%s\n", value);
}

static int
print_all_counters(const char *iface)
{
	int code = EXIT_SUCCESS;
	const char *res;

	for (int i = 0; i < avail_counters_count; i++)
	{
		const char *ctr = avail_counters[i].name;

		res = read_counter(iface, ctr);
		if (!res)
		{
			fprintf(stderr, "%s: could not determine value of %s for interface %s: %s\n", argv0, ctr, iface, strerror(errno));
			code = EXIT_FAILURE;
		}
		else
		{
			print_counter(iface, ctr, res);
		}
	}

	return code;
}

static void
ifctrstat_list_counters(const char *opt_arg)
{
	(void) opt_arg;

	for (int i = 0; i < avail_counters_count; i++)
	{
		fprintf(stdout, "%s\n", avail_counters[i].name);
	}

	exit(EXIT_SUCCESS);
}

static void
ifctrstat_set_nolabel(const char *opt_arg)
{
	(void) opt_arg;
	show_label = false;
}

static int
ifctrstat_main(int argc, char *argv[])
{
	if (optind >= argc)
		generic_usage(self_applet, EXIT_FAILURE);

	int idx = optind;
	if (argc - idx == 0)
	{
		fprintf(stderr, "%s: interface required\n",
			argv0);
		return EXIT_FAILURE;
	}

	const char *iface = argv[idx++];

	if (argc - idx == 0)
	{
		return print_all_counters(iface);
	}

	for (; idx < argc; idx++)
	{
		if (!counter_is_valid(argv[idx]))
		{
			fprintf(stderr, "%s: counter %s is not valid or not available\n", argv0, argv[idx]);
			return EXIT_FAILURE;
		}

		errno = 0;
		const char *res = read_counter(iface, argv[idx]);
		if (!res)
		{
			fprintf(stderr, "%s: could not determine value of %s for interface %s: %s\n", argv0, argv[idx], iface, strerror(errno));
			return EXIT_FAILURE;
		}

		print_counter(iface, argv[idx], res);
	}

	return EXIT_SUCCESS;
}

static struct if_option local_options[] = {
	{'L', "list", NULL, "list available counters", false, ifctrstat_list_counters},
	{'n', "no-label", NULL, "print value without counter label", false, ifctrstat_set_nolabel}
};

static struct if_option_group local_option_group = {
	.desc = "Program-specific options",
	.group_size = ARRAY_SIZE(local_options),
	.group = local_options
};

struct if_applet ifctrstat_applet = {
	.name = "ifctrstat",
	.desc = "display statistics about an interface",
	.main = ifctrstat_main,
	.usage = "ifctrstat [options] <interface> <counter>\n  ifctrstat [options] --list",
	.manpage = "8 ifctrstat",
	.groups = { &global_option_group, &local_option_group, NULL }
};
APPLET_REGISTER(ifctrstat_applet)