xref: /aosp_15_r20/external/iproute2/misc/lnstat.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /* lnstat - Unified linux network statistics
2*de1e4e89SAndroid Build Coastguard Worker  *
3*de1e4e89SAndroid Build Coastguard Worker  * Copyright (C) 2004 by Harald Welte <[email protected]>
4*de1e4e89SAndroid Build Coastguard Worker  *
5*de1e4e89SAndroid Build Coastguard Worker  * Development of this code was funded by Astaro AG, http://www.astaro.com/
6*de1e4e89SAndroid Build Coastguard Worker  *
7*de1e4e89SAndroid Build Coastguard Worker  * Based on original concept and ideas from predecessor rtstat.c:
8*de1e4e89SAndroid Build Coastguard Worker  *
9*de1e4e89SAndroid Build Coastguard Worker  * Copyright 2001 by Robert Olsson <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker  *                                 Uppsala University, Sweden
11*de1e4e89SAndroid Build Coastguard Worker  *
12*de1e4e89SAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify
13*de1e4e89SAndroid Build Coastguard Worker  * it under the terms of the GNU General Public License as published by
14*de1e4e89SAndroid Build Coastguard Worker  * the Free Software Foundation; either version 2 of the License, or
15*de1e4e89SAndroid Build Coastguard Worker  * (at your option) any later version.
16*de1e4e89SAndroid Build Coastguard Worker  *
17*de1e4e89SAndroid Build Coastguard Worker  */
18*de1e4e89SAndroid Build Coastguard Worker 
19*de1e4e89SAndroid Build Coastguard Worker /* Maximum number of fields that can be displayed */
20*de1e4e89SAndroid Build Coastguard Worker #define MAX_FIELDS		128
21*de1e4e89SAndroid Build Coastguard Worker 
22*de1e4e89SAndroid Build Coastguard Worker /* Maximum number of header lines */
23*de1e4e89SAndroid Build Coastguard Worker #define HDR_LINES		10
24*de1e4e89SAndroid Build Coastguard Worker 
25*de1e4e89SAndroid Build Coastguard Worker /* default field width if none specified */
26*de1e4e89SAndroid Build Coastguard Worker #define FIELD_WIDTH_DEFAULT	8
27*de1e4e89SAndroid Build Coastguard Worker #define FIELD_WIDTH_MAX		20
28*de1e4e89SAndroid Build Coastguard Worker 
29*de1e4e89SAndroid Build Coastguard Worker #define DEFAULT_INTERVAL	2
30*de1e4e89SAndroid Build Coastguard Worker 
31*de1e4e89SAndroid Build Coastguard Worker #define HDR_LINE_LENGTH		(MAX_FIELDS*FIELD_WIDTH_MAX)
32*de1e4e89SAndroid Build Coastguard Worker 
33*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
34*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
35*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
36*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
37*de1e4e89SAndroid Build Coastguard Worker #include <getopt.h>
38*de1e4e89SAndroid Build Coastguard Worker 
39*de1e4e89SAndroid Build Coastguard Worker #include <json_writer.h>
40*de1e4e89SAndroid Build Coastguard Worker #include "lnstat.h"
41*de1e4e89SAndroid Build Coastguard Worker 
42*de1e4e89SAndroid Build Coastguard Worker static struct option opts[] = {
43*de1e4e89SAndroid Build Coastguard Worker 	{ "version", 0, NULL, 'V' },
44*de1e4e89SAndroid Build Coastguard Worker 	{ "count", 1, NULL, 'c' },
45*de1e4e89SAndroid Build Coastguard Worker 	{ "dump", 0, NULL, 'd' },
46*de1e4e89SAndroid Build Coastguard Worker 	{ "json", 0, NULL, 'j' },
47*de1e4e89SAndroid Build Coastguard Worker 	{ "file", 1, NULL, 'f' },
48*de1e4e89SAndroid Build Coastguard Worker 	{ "help", 0, NULL, 'h' },
49*de1e4e89SAndroid Build Coastguard Worker 	{ "interval", 1, NULL, 'i' },
50*de1e4e89SAndroid Build Coastguard Worker 	{ "keys", 1, NULL, 'k' },
51*de1e4e89SAndroid Build Coastguard Worker 	{ "subject", 1, NULL, 's' },
52*de1e4e89SAndroid Build Coastguard Worker 	{ "width", 1, NULL, 'w' },
53*de1e4e89SAndroid Build Coastguard Worker 	{ "oneline", 0, NULL, 0 },
54*de1e4e89SAndroid Build Coastguard Worker };
55*de1e4e89SAndroid Build Coastguard Worker 
usage(char * name,int exit_code)56*de1e4e89SAndroid Build Coastguard Worker static int usage(char *name, int exit_code)
57*de1e4e89SAndroid Build Coastguard Worker {
58*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "%s Version %s\n", name, LNSTAT_VERSION);
59*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Copyright (C) 2004 by Harald Welte <[email protected]>\n");
60*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "This program is free software licensed under GNU GPLv2\nwith ABSOLUTELY NO WARRANTY.\n\n");
61*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Parameters:\n");
62*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-V --version\t\tPrint Version of Program\n");
63*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-c --count <count>\t"
64*de1e4e89SAndroid Build Coastguard Worker 			"Print <count> number of intervals\n");
65*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-d --dump\t\t"
66*de1e4e89SAndroid Build Coastguard Worker 			"Dump list of available files/keys\n");
67*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-j --json\t\t"
68*de1e4e89SAndroid Build Coastguard Worker 			"Display in JSON format\n");
69*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-f --file <file>\tStatistics file to use\n");
70*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-h --help\t\tThis help message\n");
71*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-i --interval <intv>\t"
72*de1e4e89SAndroid Build Coastguard Worker 			"Set interval to 'intv' seconds\n");
73*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-k --keys k,k,k,...\tDisplay only keys specified\n");
74*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-s --subject [0-2]\tControl header printing:\n");
75*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\t\t\t\t0 = never\n");
76*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\t\t\t\t1 = once\n");
77*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\t\t\t\t2 = every 20 lines (default))\n");
78*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\t-w --width n,n,n,...\tWidth for each field\n");
79*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "\n");
80*de1e4e89SAndroid Build Coastguard Worker 
81*de1e4e89SAndroid Build Coastguard Worker 	exit(exit_code);
82*de1e4e89SAndroid Build Coastguard Worker }
83*de1e4e89SAndroid Build Coastguard Worker 
84*de1e4e89SAndroid Build Coastguard Worker struct field_param {
85*de1e4e89SAndroid Build Coastguard Worker 	const char *name;
86*de1e4e89SAndroid Build Coastguard Worker 	struct lnstat_field *lf;
87*de1e4e89SAndroid Build Coastguard Worker 	struct {
88*de1e4e89SAndroid Build Coastguard Worker 		unsigned int width;
89*de1e4e89SAndroid Build Coastguard Worker 	} print;
90*de1e4e89SAndroid Build Coastguard Worker };
91*de1e4e89SAndroid Build Coastguard Worker 
92*de1e4e89SAndroid Build Coastguard Worker struct field_params {
93*de1e4e89SAndroid Build Coastguard Worker 	unsigned int num;
94*de1e4e89SAndroid Build Coastguard Worker 	struct field_param params[MAX_FIELDS];
95*de1e4e89SAndroid Build Coastguard Worker };
96*de1e4e89SAndroid Build Coastguard Worker 
print_line(FILE * of,const struct lnstat_file * lnstat_files,const struct field_params * fp)97*de1e4e89SAndroid Build Coastguard Worker static void print_line(FILE *of, const struct lnstat_file *lnstat_files,
98*de1e4e89SAndroid Build Coastguard Worker 		       const struct field_params *fp)
99*de1e4e89SAndroid Build Coastguard Worker {
100*de1e4e89SAndroid Build Coastguard Worker 	int i;
101*de1e4e89SAndroid Build Coastguard Worker 
102*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < fp->num; i++) {
103*de1e4e89SAndroid Build Coastguard Worker 		const struct lnstat_field *lf = fp->params[i].lf;
104*de1e4e89SAndroid Build Coastguard Worker 
105*de1e4e89SAndroid Build Coastguard Worker 		fprintf(of, "%*lu|", fp->params[i].print.width, lf->result);
106*de1e4e89SAndroid Build Coastguard Worker 	}
107*de1e4e89SAndroid Build Coastguard Worker 	fputc('\n', of);
108*de1e4e89SAndroid Build Coastguard Worker }
109*de1e4e89SAndroid Build Coastguard Worker 
print_json(FILE * of,const struct lnstat_file * lnstat_files,const struct field_params * fp)110*de1e4e89SAndroid Build Coastguard Worker static void print_json(FILE *of, const struct lnstat_file *lnstat_files,
111*de1e4e89SAndroid Build Coastguard Worker 		       const struct field_params *fp)
112*de1e4e89SAndroid Build Coastguard Worker {
113*de1e4e89SAndroid Build Coastguard Worker 	json_writer_t *jw = jsonw_new(of);
114*de1e4e89SAndroid Build Coastguard Worker 	int i;
115*de1e4e89SAndroid Build Coastguard Worker 
116*de1e4e89SAndroid Build Coastguard Worker 	jsonw_start_object(jw);
117*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < fp->num; i++) {
118*de1e4e89SAndroid Build Coastguard Worker 		const struct lnstat_field *lf = fp->params[i].lf;
119*de1e4e89SAndroid Build Coastguard Worker 
120*de1e4e89SAndroid Build Coastguard Worker 		jsonw_uint_field(jw, lf->name, lf->result);
121*de1e4e89SAndroid Build Coastguard Worker 	}
122*de1e4e89SAndroid Build Coastguard Worker 	jsonw_end_object(jw);
123*de1e4e89SAndroid Build Coastguard Worker 	jsonw_destroy(&jw);
124*de1e4e89SAndroid Build Coastguard Worker }
125*de1e4e89SAndroid Build Coastguard Worker 
126*de1e4e89SAndroid Build Coastguard Worker /* find lnstat_field according to user specification */
map_field_params(struct lnstat_file * lnstat_files,struct field_params * fps,int interval)127*de1e4e89SAndroid Build Coastguard Worker static int map_field_params(struct lnstat_file *lnstat_files,
128*de1e4e89SAndroid Build Coastguard Worker 			    struct field_params *fps, int interval)
129*de1e4e89SAndroid Build Coastguard Worker {
130*de1e4e89SAndroid Build Coastguard Worker 	int i, j = 0;
131*de1e4e89SAndroid Build Coastguard Worker 	struct lnstat_file *lf;
132*de1e4e89SAndroid Build Coastguard Worker 
133*de1e4e89SAndroid Build Coastguard Worker 	/* no field specification on commandline, need to build default */
134*de1e4e89SAndroid Build Coastguard Worker 	if (!fps->num) {
135*de1e4e89SAndroid Build Coastguard Worker 		for (lf = lnstat_files; lf; lf = lf->next) {
136*de1e4e89SAndroid Build Coastguard Worker 			for (i = 0; i < lf->num_fields; i++) {
137*de1e4e89SAndroid Build Coastguard Worker 				fps->params[j].lf = &lf->fields[i];
138*de1e4e89SAndroid Build Coastguard Worker 				fps->params[j].lf->file->interval.tv_sec =
139*de1e4e89SAndroid Build Coastguard Worker 								interval;
140*de1e4e89SAndroid Build Coastguard Worker 				if (!fps->params[j].print.width)
141*de1e4e89SAndroid Build Coastguard Worker 					fps->params[j].print.width =
142*de1e4e89SAndroid Build Coastguard Worker 							FIELD_WIDTH_DEFAULT;
143*de1e4e89SAndroid Build Coastguard Worker 
144*de1e4e89SAndroid Build Coastguard Worker 				if (++j >= MAX_FIELDS - 1) {
145*de1e4e89SAndroid Build Coastguard Worker 					fprintf(stderr,
146*de1e4e89SAndroid Build Coastguard Worker 						"WARN: MAX_FIELDS (%d) reached, truncating number of keys\n",
147*de1e4e89SAndroid Build Coastguard Worker 						MAX_FIELDS);
148*de1e4e89SAndroid Build Coastguard Worker 					goto full;
149*de1e4e89SAndroid Build Coastguard Worker 				}
150*de1e4e89SAndroid Build Coastguard Worker 			}
151*de1e4e89SAndroid Build Coastguard Worker 		}
152*de1e4e89SAndroid Build Coastguard Worker full:
153*de1e4e89SAndroid Build Coastguard Worker 		fps->num = j;
154*de1e4e89SAndroid Build Coastguard Worker 		return 1;
155*de1e4e89SAndroid Build Coastguard Worker 	}
156*de1e4e89SAndroid Build Coastguard Worker 
157*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < fps->num; i++) {
158*de1e4e89SAndroid Build Coastguard Worker 		fps->params[i].lf = lnstat_find_field(lnstat_files,
159*de1e4e89SAndroid Build Coastguard Worker 						      fps->params[i].name);
160*de1e4e89SAndroid Build Coastguard Worker 		if (!fps->params[i].lf) {
161*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Field `%s' unknown\n",
162*de1e4e89SAndroid Build Coastguard Worker 				fps->params[i].name);
163*de1e4e89SAndroid Build Coastguard Worker 			return 0;
164*de1e4e89SAndroid Build Coastguard Worker 		}
165*de1e4e89SAndroid Build Coastguard Worker 		fps->params[i].lf->file->interval.tv_sec = interval;
166*de1e4e89SAndroid Build Coastguard Worker 		if (!fps->params[i].print.width)
167*de1e4e89SAndroid Build Coastguard Worker 			fps->params[i].print.width = FIELD_WIDTH_DEFAULT;
168*de1e4e89SAndroid Build Coastguard Worker 	}
169*de1e4e89SAndroid Build Coastguard Worker 	return 1;
170*de1e4e89SAndroid Build Coastguard Worker }
171*de1e4e89SAndroid Build Coastguard Worker 
172*de1e4e89SAndroid Build Coastguard Worker struct table_hdr {
173*de1e4e89SAndroid Build Coastguard Worker 	int num_lines;
174*de1e4e89SAndroid Build Coastguard Worker 	char *hdr[HDR_LINES];
175*de1e4e89SAndroid Build Coastguard Worker };
176*de1e4e89SAndroid Build Coastguard Worker 
build_hdr_string(struct lnstat_file * lnstat_files,struct field_params * fps,int linewidth)177*de1e4e89SAndroid Build Coastguard Worker static struct table_hdr *build_hdr_string(struct lnstat_file *lnstat_files,
178*de1e4e89SAndroid Build Coastguard Worker 					  struct field_params *fps,
179*de1e4e89SAndroid Build Coastguard Worker 					  int linewidth)
180*de1e4e89SAndroid Build Coastguard Worker {
181*de1e4e89SAndroid Build Coastguard Worker 	int h, i;
182*de1e4e89SAndroid Build Coastguard Worker 	static struct table_hdr th;
183*de1e4e89SAndroid Build Coastguard Worker 	int ofs = 0;
184*de1e4e89SAndroid Build Coastguard Worker 
185*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < HDR_LINES; i++)
186*de1e4e89SAndroid Build Coastguard Worker 		th.hdr[i] = calloc(1, HDR_LINE_LENGTH);
187*de1e4e89SAndroid Build Coastguard Worker 
188*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < fps->num; i++) {
189*de1e4e89SAndroid Build Coastguard Worker 		char *cname, *fname = fps->params[i].lf->name;
190*de1e4e89SAndroid Build Coastguard Worker 		unsigned int width = fps->params[i].print.width;
191*de1e4e89SAndroid Build Coastguard Worker 
192*de1e4e89SAndroid Build Coastguard Worker 		snprintf(th.hdr[0]+ofs, width+2, "%*.*s|", width, width,
193*de1e4e89SAndroid Build Coastguard Worker 			 fps->params[i].lf->file->basename);
194*de1e4e89SAndroid Build Coastguard Worker 
195*de1e4e89SAndroid Build Coastguard Worker 		cname = fname;
196*de1e4e89SAndroid Build Coastguard Worker 		for (h = 1; h < HDR_LINES; h++) {
197*de1e4e89SAndroid Build Coastguard Worker 			if (cname - fname >= strlen(fname))
198*de1e4e89SAndroid Build Coastguard Worker 				snprintf(th.hdr[h]+ofs, width+2,
199*de1e4e89SAndroid Build Coastguard Worker 					 "%*.*s|", width, width, "");
200*de1e4e89SAndroid Build Coastguard Worker 			else {
201*de1e4e89SAndroid Build Coastguard Worker 				th.num_lines = h+1;
202*de1e4e89SAndroid Build Coastguard Worker 				snprintf(th.hdr[h]+ofs, width+2,
203*de1e4e89SAndroid Build Coastguard Worker 					 "%*.*s|", width, width, cname);
204*de1e4e89SAndroid Build Coastguard Worker 			}
205*de1e4e89SAndroid Build Coastguard Worker 			cname += width;
206*de1e4e89SAndroid Build Coastguard Worker 		}
207*de1e4e89SAndroid Build Coastguard Worker 		ofs += width+1;
208*de1e4e89SAndroid Build Coastguard Worker 	}
209*de1e4e89SAndroid Build Coastguard Worker 	/* fill in spaces */
210*de1e4e89SAndroid Build Coastguard Worker 	for (h = 1; h <= th.num_lines; h++) {
211*de1e4e89SAndroid Build Coastguard Worker 		for (i = 0; i < ofs; i++) {
212*de1e4e89SAndroid Build Coastguard Worker 			if (th.hdr[h][i] == '\0')
213*de1e4e89SAndroid Build Coastguard Worker 				th.hdr[h][i] = ' ';
214*de1e4e89SAndroid Build Coastguard Worker 		}
215*de1e4e89SAndroid Build Coastguard Worker 	}
216*de1e4e89SAndroid Build Coastguard Worker 
217*de1e4e89SAndroid Build Coastguard Worker 	return &th;
218*de1e4e89SAndroid Build Coastguard Worker }
219*de1e4e89SAndroid Build Coastguard Worker 
print_hdr(FILE * of,struct table_hdr * th)220*de1e4e89SAndroid Build Coastguard Worker static int print_hdr(FILE *of, struct table_hdr *th)
221*de1e4e89SAndroid Build Coastguard Worker {
222*de1e4e89SAndroid Build Coastguard Worker 	int i;
223*de1e4e89SAndroid Build Coastguard Worker 
224*de1e4e89SAndroid Build Coastguard Worker 	for (i = 0; i < th->num_lines; i++) {
225*de1e4e89SAndroid Build Coastguard Worker 		fputs(th->hdr[i], of);
226*de1e4e89SAndroid Build Coastguard Worker 		fputc('\n', of);
227*de1e4e89SAndroid Build Coastguard Worker 	}
228*de1e4e89SAndroid Build Coastguard Worker 	return 0;
229*de1e4e89SAndroid Build Coastguard Worker }
230*de1e4e89SAndroid Build Coastguard Worker 
231*de1e4e89SAndroid Build Coastguard Worker 
main(int argc,char ** argv)232*de1e4e89SAndroid Build Coastguard Worker int main(int argc, char **argv)
233*de1e4e89SAndroid Build Coastguard Worker {
234*de1e4e89SAndroid Build Coastguard Worker 	struct lnstat_file *lnstat_files;
235*de1e4e89SAndroid Build Coastguard Worker 	const char *basename;
236*de1e4e89SAndroid Build Coastguard Worker 	int i, c;
237*de1e4e89SAndroid Build Coastguard Worker 	int interval = DEFAULT_INTERVAL;
238*de1e4e89SAndroid Build Coastguard Worker 	int hdr = 2;
239*de1e4e89SAndroid Build Coastguard Worker 	enum {
240*de1e4e89SAndroid Build Coastguard Worker 		MODE_DUMP,
241*de1e4e89SAndroid Build Coastguard Worker 		MODE_JSON,
242*de1e4e89SAndroid Build Coastguard Worker 		MODE_NORMAL,
243*de1e4e89SAndroid Build Coastguard Worker 	} mode = MODE_NORMAL;
244*de1e4e89SAndroid Build Coastguard Worker 	unsigned long count = 0;
245*de1e4e89SAndroid Build Coastguard Worker 	struct table_hdr *header;
246*de1e4e89SAndroid Build Coastguard Worker 	static struct field_params fp;
247*de1e4e89SAndroid Build Coastguard Worker 	int num_req_files = 0;
248*de1e4e89SAndroid Build Coastguard Worker 	char *req_files[LNSTAT_MAX_FILES];
249*de1e4e89SAndroid Build Coastguard Worker 
250*de1e4e89SAndroid Build Coastguard Worker 	/* backwards compatibility mode for old tools */
251*de1e4e89SAndroid Build Coastguard Worker 	basename = strrchr(argv[0], '/');
252*de1e4e89SAndroid Build Coastguard Worker 	if (basename)
253*de1e4e89SAndroid Build Coastguard Worker 		basename += 1;	  /* name after slash */
254*de1e4e89SAndroid Build Coastguard Worker 	else
255*de1e4e89SAndroid Build Coastguard Worker 		basename = argv[0]; /* no slash */
256*de1e4e89SAndroid Build Coastguard Worker 
257*de1e4e89SAndroid Build Coastguard Worker 	if (!strcmp(basename, "rtstat")) {
258*de1e4e89SAndroid Build Coastguard Worker 		/* rtstat compatibility mode */
259*de1e4e89SAndroid Build Coastguard Worker 		req_files[0] = "rt_cache";
260*de1e4e89SAndroid Build Coastguard Worker 		num_req_files = 1;
261*de1e4e89SAndroid Build Coastguard Worker 	} else if (!strcmp(basename, "ctstat")) {
262*de1e4e89SAndroid Build Coastguard Worker 		/* ctstat compatibility mode */
263*de1e4e89SAndroid Build Coastguard Worker 		req_files[0] = "ip_conntrack";
264*de1e4e89SAndroid Build Coastguard Worker 		num_req_files = 1;
265*de1e4e89SAndroid Build Coastguard Worker 	}
266*de1e4e89SAndroid Build Coastguard Worker 
267*de1e4e89SAndroid Build Coastguard Worker 	while ((c = getopt_long(argc, argv, "Vc:djpf:h?i:k:s:w:",
268*de1e4e89SAndroid Build Coastguard Worker 				opts, NULL)) != -1) {
269*de1e4e89SAndroid Build Coastguard Worker 		int len = 0;
270*de1e4e89SAndroid Build Coastguard Worker 		char *tmp, *tok;
271*de1e4e89SAndroid Build Coastguard Worker 
272*de1e4e89SAndroid Build Coastguard Worker 		switch (c) {
273*de1e4e89SAndroid Build Coastguard Worker 		case 'c':
274*de1e4e89SAndroid Build Coastguard Worker 			count = strtoul(optarg, NULL, 0);
275*de1e4e89SAndroid Build Coastguard Worker 			break;
276*de1e4e89SAndroid Build Coastguard Worker 		case 'd':
277*de1e4e89SAndroid Build Coastguard Worker 			mode = MODE_DUMP;
278*de1e4e89SAndroid Build Coastguard Worker 			break;
279*de1e4e89SAndroid Build Coastguard Worker 		case 'j':
280*de1e4e89SAndroid Build Coastguard Worker 			mode = MODE_JSON;
281*de1e4e89SAndroid Build Coastguard Worker 			break;
282*de1e4e89SAndroid Build Coastguard Worker 		case 'f':
283*de1e4e89SAndroid Build Coastguard Worker 			req_files[num_req_files++] = strdup(optarg);
284*de1e4e89SAndroid Build Coastguard Worker 			break;
285*de1e4e89SAndroid Build Coastguard Worker 		case '?':
286*de1e4e89SAndroid Build Coastguard Worker 		case 'h':
287*de1e4e89SAndroid Build Coastguard Worker 			usage(argv[0], 0);
288*de1e4e89SAndroid Build Coastguard Worker 			break;
289*de1e4e89SAndroid Build Coastguard Worker 		case 'i':
290*de1e4e89SAndroid Build Coastguard Worker 			sscanf(optarg, "%u", &interval);
291*de1e4e89SAndroid Build Coastguard Worker 			break;
292*de1e4e89SAndroid Build Coastguard Worker 		case 'k':
293*de1e4e89SAndroid Build Coastguard Worker 			tmp = strdup(optarg);
294*de1e4e89SAndroid Build Coastguard Worker 			if (!tmp)
295*de1e4e89SAndroid Build Coastguard Worker 				break;
296*de1e4e89SAndroid Build Coastguard Worker 			for (tok = strtok(tmp, ",");
297*de1e4e89SAndroid Build Coastguard Worker 			     tok;
298*de1e4e89SAndroid Build Coastguard Worker 			     tok = strtok(NULL, ",")) {
299*de1e4e89SAndroid Build Coastguard Worker 				if (fp.num >= MAX_FIELDS) {
300*de1e4e89SAndroid Build Coastguard Worker 					fprintf(stderr,
301*de1e4e89SAndroid Build Coastguard Worker 						"WARN: too many keys requested: (%d max)\n",
302*de1e4e89SAndroid Build Coastguard Worker 						MAX_FIELDS);
303*de1e4e89SAndroid Build Coastguard Worker 					break;
304*de1e4e89SAndroid Build Coastguard Worker 				}
305*de1e4e89SAndroid Build Coastguard Worker 				fp.params[fp.num++].name = tok;
306*de1e4e89SAndroid Build Coastguard Worker 			}
307*de1e4e89SAndroid Build Coastguard Worker 			break;
308*de1e4e89SAndroid Build Coastguard Worker 		case 's':
309*de1e4e89SAndroid Build Coastguard Worker 			sscanf(optarg, "%u", &hdr);
310*de1e4e89SAndroid Build Coastguard Worker 			break;
311*de1e4e89SAndroid Build Coastguard Worker 		case 'w':
312*de1e4e89SAndroid Build Coastguard Worker 			tmp = strdup(optarg);
313*de1e4e89SAndroid Build Coastguard Worker 			if (!tmp)
314*de1e4e89SAndroid Build Coastguard Worker 				break;
315*de1e4e89SAndroid Build Coastguard Worker 			i = 0;
316*de1e4e89SAndroid Build Coastguard Worker 			for (tok = strtok(tmp, ",");
317*de1e4e89SAndroid Build Coastguard Worker 			     tok;
318*de1e4e89SAndroid Build Coastguard Worker 			     tok = strtok(NULL, ",")) {
319*de1e4e89SAndroid Build Coastguard Worker 				len  = strtoul(tok, NULL, 0);
320*de1e4e89SAndroid Build Coastguard Worker 				if (len > FIELD_WIDTH_MAX)
321*de1e4e89SAndroid Build Coastguard Worker 					len = FIELD_WIDTH_MAX;
322*de1e4e89SAndroid Build Coastguard Worker 				fp.params[i].print.width = len;
323*de1e4e89SAndroid Build Coastguard Worker 				i++;
324*de1e4e89SAndroid Build Coastguard Worker 			}
325*de1e4e89SAndroid Build Coastguard Worker 			if (i == 1) {
326*de1e4e89SAndroid Build Coastguard Worker 				for (i = 0; i < MAX_FIELDS; i++)
327*de1e4e89SAndroid Build Coastguard Worker 					fp.params[i].print.width = len;
328*de1e4e89SAndroid Build Coastguard Worker 			}
329*de1e4e89SAndroid Build Coastguard Worker 			break;
330*de1e4e89SAndroid Build Coastguard Worker 		default:
331*de1e4e89SAndroid Build Coastguard Worker 			usage(argv[0], 1);
332*de1e4e89SAndroid Build Coastguard Worker 			break;
333*de1e4e89SAndroid Build Coastguard Worker 		}
334*de1e4e89SAndroid Build Coastguard Worker 	}
335*de1e4e89SAndroid Build Coastguard Worker 
336*de1e4e89SAndroid Build Coastguard Worker 	lnstat_files = lnstat_scan_dir(PROC_NET_STAT, num_req_files,
337*de1e4e89SAndroid Build Coastguard Worker 				       (const char **) req_files);
338*de1e4e89SAndroid Build Coastguard Worker 
339*de1e4e89SAndroid Build Coastguard Worker 	switch (mode) {
340*de1e4e89SAndroid Build Coastguard Worker 	case MODE_DUMP:
341*de1e4e89SAndroid Build Coastguard Worker 		lnstat_dump(stdout, lnstat_files);
342*de1e4e89SAndroid Build Coastguard Worker 		break;
343*de1e4e89SAndroid Build Coastguard Worker 
344*de1e4e89SAndroid Build Coastguard Worker 	case MODE_NORMAL:
345*de1e4e89SAndroid Build Coastguard Worker 	case MODE_JSON:
346*de1e4e89SAndroid Build Coastguard Worker 		if (!map_field_params(lnstat_files, &fp, interval))
347*de1e4e89SAndroid Build Coastguard Worker 			exit(1);
348*de1e4e89SAndroid Build Coastguard Worker 
349*de1e4e89SAndroid Build Coastguard Worker 		header = build_hdr_string(lnstat_files, &fp, 80);
350*de1e4e89SAndroid Build Coastguard Worker 		if (!header)
351*de1e4e89SAndroid Build Coastguard Worker 			exit(1);
352*de1e4e89SAndroid Build Coastguard Worker 
353*de1e4e89SAndroid Build Coastguard Worker 		if (interval < 1)
354*de1e4e89SAndroid Build Coastguard Worker 			interval = 1;
355*de1e4e89SAndroid Build Coastguard Worker 
356*de1e4e89SAndroid Build Coastguard Worker 		for (i = 0; i < count || !count; i++) {
357*de1e4e89SAndroid Build Coastguard Worker 			lnstat_update(lnstat_files);
358*de1e4e89SAndroid Build Coastguard Worker 			if (mode == MODE_JSON)
359*de1e4e89SAndroid Build Coastguard Worker 				print_json(stdout, lnstat_files, &fp);
360*de1e4e89SAndroid Build Coastguard Worker 			else {
361*de1e4e89SAndroid Build Coastguard Worker 				if  ((hdr > 1 && !(i % 20)) ||
362*de1e4e89SAndroid Build Coastguard Worker 				     (hdr == 1 && i == 0))
363*de1e4e89SAndroid Build Coastguard Worker 					print_hdr(stdout, header);
364*de1e4e89SAndroid Build Coastguard Worker 				print_line(stdout, lnstat_files, &fp);
365*de1e4e89SAndroid Build Coastguard Worker 			}
366*de1e4e89SAndroid Build Coastguard Worker 			fflush(stdout);
367*de1e4e89SAndroid Build Coastguard Worker 			if (i < count - 1 || !count)
368*de1e4e89SAndroid Build Coastguard Worker 				sleep(interval);
369*de1e4e89SAndroid Build Coastguard Worker 		}
370*de1e4e89SAndroid Build Coastguard Worker 		break;
371*de1e4e89SAndroid Build Coastguard Worker 	}
372*de1e4e89SAndroid Build Coastguard Worker 
373*de1e4e89SAndroid Build Coastguard Worker 	return 1;
374*de1e4e89SAndroid Build Coastguard Worker }
375