Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/net/ynl/ynltool/main.c
38189 views
1
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2
/* Copyright (C) 2017-2018 Netronome Systems, Inc. */
3
/* Copyright Meta Platforms, Inc. and affiliates */
4
5
#include <ctype.h>
6
#include <errno.h>
7
#include <getopt.h>
8
#include <stdio.h>
9
#include <stdlib.h>
10
#include <string.h>
11
#include <stdarg.h>
12
13
#include "main.h"
14
15
const char *bin_name;
16
static int last_argc;
17
static char **last_argv;
18
static int (*last_do_help)(int argc, char **argv);
19
json_writer_t *json_wtr;
20
bool pretty_output;
21
bool json_output;
22
23
static void __attribute__((noreturn)) clean_and_exit(int i)
24
{
25
if (json_output)
26
jsonw_destroy(&json_wtr);
27
28
exit(i);
29
}
30
31
void usage(void)
32
{
33
last_do_help(last_argc - 1, last_argv + 1);
34
35
clean_and_exit(-1);
36
}
37
38
static int do_help(int argc __attribute__((unused)),
39
char **argv __attribute__((unused)))
40
{
41
if (json_output) {
42
jsonw_null(json_wtr);
43
return 0;
44
}
45
46
fprintf(stderr,
47
"Usage: %s [OPTIONS] OBJECT { COMMAND | help }\n"
48
" %s version\n"
49
"\n"
50
" OBJECT := { page-pool | qstats }\n"
51
" " HELP_SPEC_OPTIONS "\n"
52
"",
53
bin_name, bin_name);
54
55
return 0;
56
}
57
58
static int do_version(int argc __attribute__((unused)),
59
char **argv __attribute__((unused)))
60
{
61
if (json_output) {
62
jsonw_start_object(json_wtr);
63
jsonw_name(json_wtr, "version");
64
jsonw_printf(json_wtr, SRC_VERSION);
65
jsonw_end_object(json_wtr);
66
} else {
67
printf("%s " SRC_VERSION "\n", bin_name);
68
}
69
return 0;
70
}
71
72
static const struct cmd commands[] = {
73
{ "help", do_help },
74
{ "page-pool", do_page_pool },
75
{ "qstats", do_qstats },
76
{ "version", do_version },
77
{ 0 }
78
};
79
80
int cmd_select(const struct cmd *cmds, int argc, char **argv,
81
int (*help)(int argc, char **argv))
82
{
83
unsigned int i;
84
85
last_argc = argc;
86
last_argv = argv;
87
last_do_help = help;
88
89
if (argc < 1 && cmds[0].func)
90
return cmds[0].func(argc, argv);
91
92
for (i = 0; cmds[i].cmd; i++) {
93
if (is_prefix(*argv, cmds[i].cmd)) {
94
if (!cmds[i].func) {
95
p_err("command '%s' is not available", cmds[i].cmd);
96
return -1;
97
}
98
return cmds[i].func(argc - 1, argv + 1);
99
}
100
}
101
102
help(argc - 1, argv + 1);
103
104
return -1;
105
}
106
107
bool is_prefix(const char *pfx, const char *str)
108
{
109
if (!pfx)
110
return false;
111
if (strlen(str) < strlen(pfx))
112
return false;
113
114
return !memcmp(str, pfx, strlen(pfx));
115
}
116
117
/* Last argument MUST be NULL pointer */
118
int detect_common_prefix(const char *arg, ...)
119
{
120
unsigned int count = 0;
121
const char *ref;
122
char msg[256];
123
va_list ap;
124
125
snprintf(msg, sizeof(msg), "ambiguous prefix: '%s' could be '", arg);
126
va_start(ap, arg);
127
while ((ref = va_arg(ap, const char *))) {
128
if (!is_prefix(arg, ref))
129
continue;
130
count++;
131
if (count > 1)
132
strncat(msg, "' or '", sizeof(msg) - strlen(msg) - 1);
133
strncat(msg, ref, sizeof(msg) - strlen(msg) - 1);
134
}
135
va_end(ap);
136
strncat(msg, "'", sizeof(msg) - strlen(msg) - 1);
137
138
if (count >= 2) {
139
p_err("%s", msg);
140
return -1;
141
}
142
143
return 0;
144
}
145
146
void p_err(const char *fmt, ...)
147
{
148
va_list ap;
149
150
va_start(ap, fmt);
151
if (json_output) {
152
jsonw_start_object(json_wtr);
153
jsonw_name(json_wtr, "error");
154
jsonw_vprintf_enquote(json_wtr, fmt, ap);
155
jsonw_end_object(json_wtr);
156
} else {
157
fprintf(stderr, "Error: ");
158
vfprintf(stderr, fmt, ap);
159
fprintf(stderr, "\n");
160
}
161
va_end(ap);
162
}
163
164
void p_info(const char *fmt, ...)
165
{
166
va_list ap;
167
168
if (json_output)
169
return;
170
171
va_start(ap, fmt);
172
vfprintf(stderr, fmt, ap);
173
fprintf(stderr, "\n");
174
va_end(ap);
175
}
176
177
int main(int argc, char **argv)
178
{
179
static const struct option options[] = {
180
{ "json", no_argument, NULL, 'j' },
181
{ "help", no_argument, NULL, 'h' },
182
{ "pretty", no_argument, NULL, 'p' },
183
{ "version", no_argument, NULL, 'V' },
184
{ 0 }
185
};
186
bool version_requested = false;
187
int opt, ret;
188
189
setlinebuf(stdout);
190
191
last_do_help = do_help;
192
pretty_output = false;
193
json_output = false;
194
bin_name = "ynltool";
195
196
opterr = 0;
197
while ((opt = getopt_long(argc, argv, "Vhjp",
198
options, NULL)) >= 0) {
199
switch (opt) {
200
case 'V':
201
version_requested = true;
202
break;
203
case 'h':
204
return do_help(argc, argv);
205
case 'p':
206
pretty_output = true;
207
/* fall through */
208
case 'j':
209
if (!json_output) {
210
json_wtr = jsonw_new(stdout);
211
if (!json_wtr) {
212
p_err("failed to create JSON writer");
213
return -1;
214
}
215
json_output = true;
216
}
217
jsonw_pretty(json_wtr, pretty_output);
218
break;
219
default:
220
p_err("unrecognized option '%s'", argv[optind - 1]);
221
if (json_output)
222
clean_and_exit(-1);
223
else
224
usage();
225
}
226
}
227
228
argc -= optind;
229
argv += optind;
230
if (argc < 0)
231
usage();
232
233
if (version_requested)
234
ret = do_version(argc, argv);
235
else
236
ret = cmd_select(commands, argc, argv, do_help);
237
238
if (json_output)
239
jsonw_destroy(&json_wtr);
240
241
return ret;
242
}
243
244