xref: /freebsd/usr.sbin/mpsutil/mpsutil.c (revision 29b76e539f9c175b970dab38d5ef3d1b96bcc5ae)
1*29b76e53SScott Long /*-
2*29b76e53SScott Long  * Copyright (c) 2008 Yahoo!, Inc.
3*29b76e53SScott Long  * All rights reserved.
4*29b76e53SScott Long  * Written by: John Baldwin <jhb@FreeBSD.org>
5*29b76e53SScott Long  *
6*29b76e53SScott Long  * Redistribution and use in source and binary forms, with or without
7*29b76e53SScott Long  * modification, are permitted provided that the following conditions
8*29b76e53SScott Long  * are met:
9*29b76e53SScott Long  * 1. Redistributions of source code must retain the above copyright
10*29b76e53SScott Long  *    notice, this list of conditions and the following disclaimer.
11*29b76e53SScott Long  * 2. Redistributions in binary form must reproduce the above copyright
12*29b76e53SScott Long  *    notice, this list of conditions and the following disclaimer in the
13*29b76e53SScott Long  *    documentation and/or other materials provided with the distribution.
14*29b76e53SScott Long  * 3. Neither the name of the author nor the names of any co-contributors
15*29b76e53SScott Long  *    may be used to endorse or promote products derived from this software
16*29b76e53SScott Long  *    without specific prior written permission.
17*29b76e53SScott Long  *
18*29b76e53SScott Long  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19*29b76e53SScott Long  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*29b76e53SScott Long  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*29b76e53SScott Long  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22*29b76e53SScott Long  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*29b76e53SScott Long  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24*29b76e53SScott Long  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*29b76e53SScott Long  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26*29b76e53SScott Long  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27*29b76e53SScott Long  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*29b76e53SScott Long  * SUCH DAMAGE.
29*29b76e53SScott Long  */
30*29b76e53SScott Long 
31*29b76e53SScott Long #include <sys/cdefs.h>
32*29b76e53SScott Long __RCSID("$FreeBSD$");
33*29b76e53SScott Long 
34*29b76e53SScott Long #include <sys/param.h>
35*29b76e53SScott Long #include <sys/errno.h>
36*29b76e53SScott Long #include <err.h>
37*29b76e53SScott Long #include <stdio.h>
38*29b76e53SScott Long #include <stdlib.h>
39*29b76e53SScott Long #include <string.h>
40*29b76e53SScott Long #include <unistd.h>
41*29b76e53SScott Long #include "mpsutil.h"
42*29b76e53SScott Long 
43*29b76e53SScott Long SET_DECLARE(MPS_DATASET(top), struct mpsutil_command);
44*29b76e53SScott Long SET_DECLARE(MPS_DATASET(usage), struct mpsutil_usage);
45*29b76e53SScott Long 
46*29b76e53SScott Long int mps_unit;
47*29b76e53SScott Long 
48*29b76e53SScott Long static void
49*29b76e53SScott Long usage(void)
50*29b76e53SScott Long {
51*29b76e53SScott Long 	struct mpsutil_usage **cmd;
52*29b76e53SScott Long 	const char *args, *desc;
53*29b76e53SScott Long 
54*29b76e53SScott Long 	fprintf(stderr, "usage: mpsutil [-u unit] <command> ...\n\n");
55*29b76e53SScott Long 	fprintf(stderr, "Commands include:\n");
56*29b76e53SScott Long 	SET_FOREACH(cmd, MPS_DATASET(usage)) {
57*29b76e53SScott Long 		if (*cmd == NULL)
58*29b76e53SScott Long 			fprintf(stderr, "\n");
59*29b76e53SScott Long 		else
60*29b76e53SScott Long 			(*cmd)->handler(&args, &desc);
61*29b76e53SScott Long 			if (strncmp((*cmd)->set, "top", 3) == 0)
62*29b76e53SScott Long 				fprintf(stderr, "%s %-30s\t%s\n",
63*29b76e53SScott Long 				    (*cmd)->name, args, desc);
64*29b76e53SScott Long 			else
65*29b76e53SScott Long 				fprintf(stderr, "%s %s %-30s\t%s\n",
66*29b76e53SScott Long 				    (*cmd)->set, (*cmd)->name, args, desc);
67*29b76e53SScott Long 	}
68*29b76e53SScott Long 	exit(1);
69*29b76e53SScott Long }
70*29b76e53SScott Long 
71*29b76e53SScott Long static int
72*29b76e53SScott Long version(int ac, char **av)
73*29b76e53SScott Long {
74*29b76e53SScott Long 
75*29b76e53SScott Long 	printf("mpsutil: version %s", MPSUTIL_VERSION);
76*29b76e53SScott Long #ifdef DEBUG
77*29b76e53SScott Long 	printf(" (DEBUG)");
78*29b76e53SScott Long #endif
79*29b76e53SScott Long 	printf("\n");
80*29b76e53SScott Long 	return (0);
81*29b76e53SScott Long }
82*29b76e53SScott Long 
83*29b76e53SScott Long MPS_COMMAND(top, version, version, "", "version")
84*29b76e53SScott Long 
85*29b76e53SScott Long int
86*29b76e53SScott Long main(int ac, char **av)
87*29b76e53SScott Long {
88*29b76e53SScott Long 	struct mpsutil_command **cmd;
89*29b76e53SScott Long 	int ch;
90*29b76e53SScott Long 
91*29b76e53SScott Long 	while ((ch = getopt(ac, av, "u:h?")) != -1) {
92*29b76e53SScott Long 		switch (ch) {
93*29b76e53SScott Long 		case 'u':
94*29b76e53SScott Long 			mps_unit = atoi(optarg);
95*29b76e53SScott Long 			break;
96*29b76e53SScott Long 		case 'h':
97*29b76e53SScott Long 		case '?':
98*29b76e53SScott Long 			usage();
99*29b76e53SScott Long 			return (1);
100*29b76e53SScott Long 		}
101*29b76e53SScott Long 	}
102*29b76e53SScott Long 
103*29b76e53SScott Long 	av += optind;
104*29b76e53SScott Long 	ac -= optind;
105*29b76e53SScott Long 
106*29b76e53SScott Long 	/* getopt() eats av[0], so we can't use mpt_table_handler() directly. */
107*29b76e53SScott Long 	if (ac == 0) {
108*29b76e53SScott Long 		usage();
109*29b76e53SScott Long 		return (1);
110*29b76e53SScott Long 	}
111*29b76e53SScott Long 
112*29b76e53SScott Long 	SET_FOREACH(cmd, MPS_DATASET(top)) {
113*29b76e53SScott Long 		if (strcmp((*cmd)->name, av[0]) == 0) {
114*29b76e53SScott Long 			if ((*cmd)->handler(ac, av))
115*29b76e53SScott Long 				return (1);
116*29b76e53SScott Long 			else
117*29b76e53SScott Long 				return (0);
118*29b76e53SScott Long 		}
119*29b76e53SScott Long 	}
120*29b76e53SScott Long 	warnx("Unknown command %s.", av[0]);
121*29b76e53SScott Long 	return (1);
122*29b76e53SScott Long }
123*29b76e53SScott Long 
124*29b76e53SScott Long int
125*29b76e53SScott Long mps_table_handler(struct mpsutil_command **start, struct mpsutil_command **end,
126*29b76e53SScott Long     int ac, char **av)
127*29b76e53SScott Long {
128*29b76e53SScott Long 	struct mpsutil_command **cmd;
129*29b76e53SScott Long 
130*29b76e53SScott Long 	if (ac < 2) {
131*29b76e53SScott Long 		warnx("The %s command requires a sub-command.", av[0]);
132*29b76e53SScott Long 		return (EINVAL);
133*29b76e53SScott Long 	}
134*29b76e53SScott Long 	for (cmd = start; cmd < end; cmd++) {
135*29b76e53SScott Long 		if (strcmp((*cmd)->name, av[1]) == 0)
136*29b76e53SScott Long 			return ((*cmd)->handler(ac - 1, av + 1));
137*29b76e53SScott Long 	}
138*29b76e53SScott Long 
139*29b76e53SScott Long 	warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
140*29b76e53SScott Long 	return (ENOENT);
141*29b76e53SScott Long }
142*29b76e53SScott Long 
143*29b76e53SScott Long void
144*29b76e53SScott Long hexdump(const void *ptr, int length, const char *hdr, int flags)
145*29b76e53SScott Long {
146*29b76e53SScott Long 	int i, j, k;
147*29b76e53SScott Long 	int cols;
148*29b76e53SScott Long 	const unsigned char *cp;
149*29b76e53SScott Long 	char delim;
150*29b76e53SScott Long 
151*29b76e53SScott Long 	if ((flags & HD_DELIM_MASK) != 0)
152*29b76e53SScott Long 		delim = (flags & HD_DELIM_MASK) >> 8;
153*29b76e53SScott Long 	else
154*29b76e53SScott Long 		delim = ' ';
155*29b76e53SScott Long 
156*29b76e53SScott Long 	if ((flags & HD_COLUMN_MASK) != 0)
157*29b76e53SScott Long 		cols = flags & HD_COLUMN_MASK;
158*29b76e53SScott Long 	else
159*29b76e53SScott Long 		cols = 16;
160*29b76e53SScott Long 
161*29b76e53SScott Long 	cp = ptr;
162*29b76e53SScott Long 	for (i = 0; i < length; i+= cols) {
163*29b76e53SScott Long 		if (hdr != NULL)
164*29b76e53SScott Long 			printf("%s", hdr);
165*29b76e53SScott Long 
166*29b76e53SScott Long 		if ((flags & HD_OMIT_COUNT) == 0)
167*29b76e53SScott Long 			printf("%04x  ", i);
168*29b76e53SScott Long 
169*29b76e53SScott Long 		if ((flags & HD_OMIT_HEX) == 0) {
170*29b76e53SScott Long 			for (j = 0; j < cols; j++) {
171*29b76e53SScott Long 				if (flags & HD_REVERSED)
172*29b76e53SScott Long 					k = i + (cols - 1 - j);
173*29b76e53SScott Long 				else
174*29b76e53SScott Long 					k = i + j;
175*29b76e53SScott Long 				if (k < length)
176*29b76e53SScott Long 					printf("%c%02x", delim, cp[k]);
177*29b76e53SScott Long 				else
178*29b76e53SScott Long 					printf("   ");
179*29b76e53SScott Long 			}
180*29b76e53SScott Long 		}
181*29b76e53SScott Long 
182*29b76e53SScott Long 		if ((flags & HD_OMIT_CHARS) == 0) {
183*29b76e53SScott Long 			printf("  |");
184*29b76e53SScott Long 			for (j = 0; j < cols; j++) {
185*29b76e53SScott Long 				if (flags & HD_REVERSED)
186*29b76e53SScott Long 					k = i + (cols - 1 - j);
187*29b76e53SScott Long 				else
188*29b76e53SScott Long 					k = i + j;
189*29b76e53SScott Long 				if (k >= length)
190*29b76e53SScott Long 					printf(" ");
191*29b76e53SScott Long 				else if (cp[k] >= ' ' && cp[k] <= '~')
192*29b76e53SScott Long 					printf("%c", cp[k]);
193*29b76e53SScott Long 				else
194*29b76e53SScott Long 					printf(".");
195*29b76e53SScott Long 			}
196*29b76e53SScott Long 			printf("|");
197*29b76e53SScott Long 		}
198*29b76e53SScott Long 		printf("\n");
199*29b76e53SScott Long 	}
200*29b76e53SScott Long }
201