1192661Ssam/*-
2192661Ssam * Copyright (c) 2009 Sam Leffler, Errno Consulting
3192661Ssam * All rights reserved.
4192661Ssam *
5192661Ssam * Redistribution and use in source and binary forms, with or without
6192661Ssam * modification, are permitted provided that the following conditions
7192661Ssam * are met:
8192661Ssam * 1. Redistributions of source code must retain the above copyright
9192661Ssam *    notice, this list of conditions and the following disclaimer,
10192661Ssam *    without modification.
11192661Ssam * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12192661Ssam *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13192661Ssam *    redistribution must be conditioned upon including a substantially
14192661Ssam *    similar Disclaimer requirement for further binary redistribution.
15192661Ssam *
16192661Ssam * NO WARRANTY
17192661Ssam * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18192661Ssam * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19192661Ssam * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20192661Ssam * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21192661Ssam * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22192661Ssam * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23192661Ssam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24192661Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25192661Ssam * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26192661Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27192661Ssam * THE POSSIBILITY OF SUCH DAMAGES.
28192661Ssam *
29192661Ssam * $FreeBSD$
30192661Ssam */
31192661Ssam
32287297Srodrigc#include <sys/param.h>
33287297Srodrigc
34287297Srodrigc#include <err.h>
35287297Srodrigc#include <signal.h>
36192661Ssam#include <stdio.h>
37192661Ssam#include <stdlib.h>
38192661Ssam#include <strings.h>
39192661Ssam#include <unistd.h>
40192661Ssam
41192661Ssam#include "npestats.h"
42192661Ssam
43192661Ssamstatic struct {
44192661Ssam	const char *tag;
45192661Ssam	const char *fmt;
46192661Ssam} tags[] = {
47192661Ssam  { "default",
48192661Ssam    "align,fcs,macrx,overrun,learn,large,stp,badsrc,underflow,collision1,collisionM,deferred,late,excessive,mactx,carrier,toobig"
49192661Ssam  },
50192661Ssam};
51192661Ssam
52192661Ssamstatic const char *
53192661Ssamgetfmt(const char *tag)
54192661Ssam{
55192661Ssam	int i;
56287297Srodrigc	for (i = 0; i < nitems(tags); i++)
57192661Ssam		if (strcasecmp(tags[i].tag, tag) == 0)
58192661Ssam			return tags[i].fmt;
59192661Ssam	return tag;
60192661Ssam}
61192661Ssam
62192661Ssamstatic int signalled;
63192661Ssam
64192661Ssamstatic void
65192661Ssamcatchalarm(int signo __unused)
66192661Ssam{
67192661Ssam	signalled = 1;
68192661Ssam}
69192661Ssam
70192661Ssamint
71192661Ssammain(int argc, char *argv[])
72192661Ssam{
73192661Ssam	struct npestatfoo *wf;
74192661Ssam	const char *ifname;
75192661Ssam	int c, banner = 1;
76192661Ssam
77192661Ssam	ifname = getenv("NPE");
78192661Ssam	if (ifname == NULL)
79192661Ssam		ifname = "npe0";
80192661Ssam	wf = npestats_new(ifname, getfmt("default"));
81192661Ssam	while ((c = getopt(argc, argv, "bi:lo:z")) != -1) {
82192661Ssam		switch (c) {
83192661Ssam		case 'b':
84192661Ssam			banner = 0;
85192661Ssam			break;
86192661Ssam		case 'i':
87192661Ssam			wf->setifname(wf, optarg);
88192661Ssam			break;
89192661Ssam		case 'l':
90192661Ssam			wf->print_fields(wf, stdout);
91192661Ssam			return 0;
92192661Ssam		case 'o':
93192661Ssam			wf->setfmt(wf, getfmt(optarg));
94192661Ssam			break;
95192661Ssam		default:
96192661Ssam			errx(-1, "usage: %s [-a] [-i ifname] [-l] [-o fmt] [interval]\n", argv[0]);
97192661Ssam			/*NOTREACHED*/
98192661Ssam		}
99192661Ssam	}
100192661Ssam	argc -= optind;
101192661Ssam	argv += optind;
102192661Ssam
103192661Ssam	if (argc > 0) {
104192661Ssam		u_long interval = strtoul(argv[0], NULL, 0);
105192661Ssam		int line, omask;
106192661Ssam
107192661Ssam		if (interval < 1)
108192661Ssam			interval = 1;
109192661Ssam		signal(SIGALRM, catchalarm);
110192661Ssam		signalled = 0;
111192661Ssam		alarm(interval);
112192661Ssam	banner:
113192661Ssam		if (banner)
114192661Ssam			wf->print_header(wf, stdout);
115192661Ssam		line = 0;
116192661Ssam	loop:
117192661Ssam		if (line != 0) {
118192661Ssam			wf->collect_cur(wf);
119192661Ssam			wf->print_current(wf, stdout);
120192661Ssam			wf->update_tot(wf);
121192661Ssam		} else {
122192661Ssam			wf->collect_tot(wf);
123192661Ssam			wf->print_total(wf, stdout);
124192661Ssam		}
125192661Ssam		fflush(stdout);
126192661Ssam		omask = sigblock(sigmask(SIGALRM));
127192661Ssam		if (!signalled)
128192661Ssam			sigpause(0);
129192661Ssam		sigsetmask(omask);
130192661Ssam		signalled = 0;
131192661Ssam		alarm(interval);
132192661Ssam		line++;
133192661Ssam		if (line == 21)		/* XXX tty line count */
134192661Ssam			goto banner;
135192661Ssam		else
136192661Ssam			goto loop;
137192661Ssam		/*NOTREACHED*/
138192661Ssam	} else {
139192661Ssam		wf->collect_tot(wf);
140192661Ssam		wf->print_verbose(wf, stdout);
141192661Ssam	}
142192661Ssam	return 0;
143192661Ssam}
144