1297590Ssbruno/*-
2297590Ssbruno * Copyright (c) 2015 Netflix, Inc.
3297590Ssbruno * All rights reserved.
4297590Ssbruno * Written by: Scott Long <scottl@freebsd.org>
5297590Ssbruno *
6297590Ssbruno * Copyright (c) 2008 Yahoo!, Inc.
7297590Ssbruno * All rights reserved.
8297590Ssbruno * Written by: John Baldwin <jhb@FreeBSD.org>
9297590Ssbruno *
10297590Ssbruno * Redistribution and use in source and binary forms, with or without
11297590Ssbruno * modification, are permitted provided that the following conditions
12297590Ssbruno * are met:
13297590Ssbruno * 1. Redistributions of source code must retain the above copyright
14297590Ssbruno *    notice, this list of conditions and the following disclaimer.
15297590Ssbruno * 2. Redistributions in binary form must reproduce the above copyright
16297590Ssbruno *    notice, this list of conditions and the following disclaimer in the
17297590Ssbruno *    documentation and/or other materials provided with the distribution.
18297590Ssbruno * 3. Neither the name of the author nor the names of any co-contributors
19297590Ssbruno *    may be used to endorse or promote products derived from this software
20297590Ssbruno *    without specific prior written permission.
21297590Ssbruno *
22297590Ssbruno * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23297590Ssbruno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24297590Ssbruno * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25297590Ssbruno * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26297590Ssbruno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27297590Ssbruno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28297590Ssbruno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29297590Ssbruno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30297590Ssbruno * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31297590Ssbruno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32297590Ssbruno * SUCH DAMAGE.
33297590Ssbruno */
34297590Ssbruno
35297590Ssbruno#include <sys/cdefs.h>
36297590Ssbruno__RCSID("$FreeBSD$");
37297590Ssbruno
38297590Ssbruno#include <sys/param.h>
39297590Ssbruno#include <sys/errno.h>
40297590Ssbruno#include <err.h>
41297590Ssbruno#include <stdio.h>
42297590Ssbruno#include <stdlib.h>
43297590Ssbruno#include <string.h>
44297590Ssbruno#include <unistd.h>
45297590Ssbruno#include "mpsutil.h"
46297590Ssbruno
47297590SsbrunoSET_DECLARE(MPS_DATASET(top), struct mpsutil_command);
48297590SsbrunoSET_DECLARE(MPS_DATASET(usage), struct mpsutil_usage);
49297590Ssbruno
50297590Ssbrunoint mps_unit;
51297590Ssbrunoint is_mps;
52297590Ssbruno
53297590Ssbrunostatic void
54297590Ssbrunousage(void)
55297590Ssbruno{
56297590Ssbruno	struct mpsutil_usage **cmd;
57297590Ssbruno	const char *args, *desc;
58297590Ssbruno
59297590Ssbruno	fprintf(stderr, "usage: %s [-u unit] <command> ...\n\n", getprogname());
60297590Ssbruno	fprintf(stderr, "Commands include:\n");
61297590Ssbruno	SET_FOREACH(cmd, MPS_DATASET(usage)) {
62297590Ssbruno		if (*cmd == NULL)
63297590Ssbruno			fprintf(stderr, "\n");
64297590Ssbruno		else
65297590Ssbruno			(*cmd)->handler(&args, &desc);
66297590Ssbruno			if (strncmp((*cmd)->set, "top", 3) == 0)
67297590Ssbruno				fprintf(stderr, "%s %-30s\t%s\n",
68297590Ssbruno				    (*cmd)->name, args, desc);
69297590Ssbruno			else
70297590Ssbruno				fprintf(stderr, "%s %s %-30s\t%s\n",
71297590Ssbruno				    (*cmd)->set, (*cmd)->name, args, desc);
72297590Ssbruno	}
73297590Ssbruno	exit(1);
74297590Ssbruno}
75297590Ssbruno
76297590Ssbrunostatic int
77297590Ssbrunoversion(int ac, char **av)
78297590Ssbruno{
79297590Ssbruno
80297590Ssbruno	printf("%s: version %s", MPSUTIL_VERSION, getprogname());
81297590Ssbruno#ifdef DEBUG
82297590Ssbruno	printf(" (DEBUG)");
83297590Ssbruno#endif
84297590Ssbruno	printf("\n");
85297590Ssbruno	return (0);
86297590Ssbruno}
87297590Ssbruno
88297590SsbrunoMPS_COMMAND(top, version, version, "", "version")
89297590Ssbruno
90297590Ssbrunoint
91297590Ssbrunomain(int ac, char **av)
92297590Ssbruno{
93297590Ssbruno	struct mpsutil_command **cmd;
94297590Ssbruno	int ch;
95297590Ssbruno
96297590Ssbruno	is_mps = !strcmp(getprogname(), "mpsutil");
97297590Ssbruno
98297590Ssbruno	while ((ch = getopt(ac, av, "u:h?")) != -1) {
99297590Ssbruno		switch (ch) {
100297590Ssbruno		case 'u':
101297590Ssbruno			mps_unit = atoi(optarg);
102297590Ssbruno			break;
103297590Ssbruno		case 'h':
104297590Ssbruno		case '?':
105297590Ssbruno			usage();
106297590Ssbruno			return (1);
107297590Ssbruno		}
108297590Ssbruno	}
109297590Ssbruno
110297590Ssbruno	av += optind;
111297590Ssbruno	ac -= optind;
112297590Ssbruno
113297590Ssbruno	/* getopt() eats av[0], so we can't use mpt_table_handler() directly. */
114297590Ssbruno	if (ac == 0) {
115297590Ssbruno		usage();
116297590Ssbruno		return (1);
117297590Ssbruno	}
118297590Ssbruno
119297590Ssbruno	SET_FOREACH(cmd, MPS_DATASET(top)) {
120297590Ssbruno		if (strcmp((*cmd)->name, av[0]) == 0) {
121297590Ssbruno			if ((*cmd)->handler(ac, av))
122297590Ssbruno				return (1);
123297590Ssbruno			else
124297590Ssbruno				return (0);
125297590Ssbruno		}
126297590Ssbruno	}
127297590Ssbruno	warnx("Unknown command %s.", av[0]);
128297590Ssbruno	return (1);
129297590Ssbruno}
130297590Ssbruno
131297590Ssbrunoint
132297590Ssbrunomps_table_handler(struct mpsutil_command **start, struct mpsutil_command **end,
133297590Ssbruno    int ac, char **av)
134297590Ssbruno{
135297590Ssbruno	struct mpsutil_command **cmd;
136297590Ssbruno
137297590Ssbruno	if (ac < 2) {
138297590Ssbruno		warnx("The %s command requires a sub-command.", av[0]);
139297590Ssbruno		return (EINVAL);
140297590Ssbruno	}
141297590Ssbruno	for (cmd = start; cmd < end; cmd++) {
142297590Ssbruno		if (strcmp((*cmd)->name, av[1]) == 0)
143297590Ssbruno			return ((*cmd)->handler(ac - 1, av + 1));
144297590Ssbruno	}
145297590Ssbruno
146297590Ssbruno	warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
147297590Ssbruno	return (ENOENT);
148297590Ssbruno}
149297590Ssbruno
150297590Ssbrunovoid
151297590Ssbrunohexdump(const void *ptr, int length, const char *hdr, int flags)
152297590Ssbruno{
153297590Ssbruno	int i, j, k;
154297590Ssbruno	int cols;
155297590Ssbruno	const unsigned char *cp;
156297590Ssbruno	char delim;
157297590Ssbruno
158297590Ssbruno	if ((flags & HD_DELIM_MASK) != 0)
159297590Ssbruno		delim = (flags & HD_DELIM_MASK) >> 8;
160297590Ssbruno	else
161297590Ssbruno		delim = ' ';
162297590Ssbruno
163297590Ssbruno	if ((flags & HD_COLUMN_MASK) != 0)
164297590Ssbruno		cols = flags & HD_COLUMN_MASK;
165297590Ssbruno	else
166297590Ssbruno		cols = 16;
167297590Ssbruno
168297590Ssbruno	cp = ptr;
169297590Ssbruno	for (i = 0; i < length; i+= cols) {
170297590Ssbruno		if (hdr != NULL)
171297590Ssbruno			printf("%s", hdr);
172297590Ssbruno
173297590Ssbruno		if ((flags & HD_OMIT_COUNT) == 0)
174297590Ssbruno			printf("%04x  ", i);
175297590Ssbruno
176297590Ssbruno		if ((flags & HD_OMIT_HEX) == 0) {
177297590Ssbruno			for (j = 0; j < cols; j++) {
178297590Ssbruno				if (flags & HD_REVERSED)
179297590Ssbruno					k = i + (cols - 1 - j);
180297590Ssbruno				else
181297590Ssbruno					k = i + j;
182297590Ssbruno				if (k < length)
183297590Ssbruno					printf("%c%02x", delim, cp[k]);
184297590Ssbruno				else
185297590Ssbruno					printf("   ");
186297590Ssbruno			}
187297590Ssbruno		}
188297590Ssbruno
189297590Ssbruno		if ((flags & HD_OMIT_CHARS) == 0) {
190297590Ssbruno			printf("  |");
191297590Ssbruno			for (j = 0; j < cols; j++) {
192297590Ssbruno				if (flags & HD_REVERSED)
193297590Ssbruno					k = i + (cols - 1 - j);
194297590Ssbruno				else
195297590Ssbruno					k = i + j;
196297590Ssbruno				if (k >= length)
197297590Ssbruno					printf(" ");
198297590Ssbruno				else if (cp[k] >= ' ' && cp[k] <= '~')
199297590Ssbruno					printf("%c", cp[k]);
200297590Ssbruno				else
201297590Ssbruno					printf(".");
202297590Ssbruno			}
203297590Ssbruno			printf("|");
204297590Ssbruno		}
205297590Ssbruno		printf("\n");
206297590Ssbruno	}
207297590Ssbruno}
208