xref: /freebsd/usr.sbin/mpsutil/mpsutil.c (revision 883bb7e941d520b3d377c92aee0207c9e2bc8edb)
129b76e53SScott Long /*-
2*883bb7e9SScott Long  * Copyright (c) 2015 Netflix, Inc.
3*883bb7e9SScott Long  * All rights reserved.
4*883bb7e9SScott Long  * Written by: Scott Long <scottl@freebsd.org>
5*883bb7e9SScott Long  *
629b76e53SScott Long  * Copyright (c) 2008 Yahoo!, Inc.
729b76e53SScott Long  * All rights reserved.
829b76e53SScott Long  * Written by: John Baldwin <jhb@FreeBSD.org>
929b76e53SScott Long  *
1029b76e53SScott Long  * Redistribution and use in source and binary forms, with or without
1129b76e53SScott Long  * modification, are permitted provided that the following conditions
1229b76e53SScott Long  * are met:
1329b76e53SScott Long  * 1. Redistributions of source code must retain the above copyright
1429b76e53SScott Long  *    notice, this list of conditions and the following disclaimer.
1529b76e53SScott Long  * 2. Redistributions in binary form must reproduce the above copyright
1629b76e53SScott Long  *    notice, this list of conditions and the following disclaimer in the
1729b76e53SScott Long  *    documentation and/or other materials provided with the distribution.
1829b76e53SScott Long  * 3. Neither the name of the author nor the names of any co-contributors
1929b76e53SScott Long  *    may be used to endorse or promote products derived from this software
2029b76e53SScott Long  *    without specific prior written permission.
2129b76e53SScott Long  *
2229b76e53SScott Long  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2329b76e53SScott Long  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2429b76e53SScott Long  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2529b76e53SScott Long  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2629b76e53SScott Long  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2729b76e53SScott Long  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2829b76e53SScott Long  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2929b76e53SScott Long  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3029b76e53SScott Long  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3129b76e53SScott Long  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3229b76e53SScott Long  * SUCH DAMAGE.
3329b76e53SScott Long  */
3429b76e53SScott Long 
3529b76e53SScott Long #include <sys/cdefs.h>
3629b76e53SScott Long __RCSID("$FreeBSD$");
3729b76e53SScott Long 
3829b76e53SScott Long #include <sys/param.h>
3929b76e53SScott Long #include <sys/errno.h>
4029b76e53SScott Long #include <err.h>
4129b76e53SScott Long #include <stdio.h>
4229b76e53SScott Long #include <stdlib.h>
4329b76e53SScott Long #include <string.h>
4429b76e53SScott Long #include <unistd.h>
4529b76e53SScott Long #include "mpsutil.h"
4629b76e53SScott Long 
4729b76e53SScott Long SET_DECLARE(MPS_DATASET(top), struct mpsutil_command);
4829b76e53SScott Long SET_DECLARE(MPS_DATASET(usage), struct mpsutil_usage);
4929b76e53SScott Long 
5029b76e53SScott Long int mps_unit;
5148f31f4fSBaptiste Daroussin int is_mps;
5229b76e53SScott Long 
5329b76e53SScott Long static void
5429b76e53SScott Long usage(void)
5529b76e53SScott Long {
5629b76e53SScott Long 	struct mpsutil_usage **cmd;
5729b76e53SScott Long 	const char *args, *desc;
5829b76e53SScott Long 
5948f31f4fSBaptiste Daroussin 	fprintf(stderr, "usage: %s [-u unit] <command> ...\n\n", getprogname());
6029b76e53SScott Long 	fprintf(stderr, "Commands include:\n");
6129b76e53SScott Long 	SET_FOREACH(cmd, MPS_DATASET(usage)) {
6229b76e53SScott Long 		if (*cmd == NULL)
6329b76e53SScott Long 			fprintf(stderr, "\n");
6429b76e53SScott Long 		else
6529b76e53SScott Long 			(*cmd)->handler(&args, &desc);
6629b76e53SScott Long 			if (strncmp((*cmd)->set, "top", 3) == 0)
6729b76e53SScott Long 				fprintf(stderr, "%s %-30s\t%s\n",
6829b76e53SScott Long 				    (*cmd)->name, args, desc);
6929b76e53SScott Long 			else
7029b76e53SScott Long 				fprintf(stderr, "%s %s %-30s\t%s\n",
7129b76e53SScott Long 				    (*cmd)->set, (*cmd)->name, args, desc);
7229b76e53SScott Long 	}
7329b76e53SScott Long 	exit(1);
7429b76e53SScott Long }
7529b76e53SScott Long 
7629b76e53SScott Long static int
7729b76e53SScott Long version(int ac, char **av)
7829b76e53SScott Long {
7929b76e53SScott Long 
8048f31f4fSBaptiste Daroussin 	printf("%s: version %s", MPSUTIL_VERSION, getprogname());
8129b76e53SScott Long #ifdef DEBUG
8229b76e53SScott Long 	printf(" (DEBUG)");
8329b76e53SScott Long #endif
8429b76e53SScott Long 	printf("\n");
8529b76e53SScott Long 	return (0);
8629b76e53SScott Long }
8729b76e53SScott Long 
8829b76e53SScott Long MPS_COMMAND(top, version, version, "", "version")
8929b76e53SScott Long 
9029b76e53SScott Long int
9129b76e53SScott Long main(int ac, char **av)
9229b76e53SScott Long {
9329b76e53SScott Long 	struct mpsutil_command **cmd;
9429b76e53SScott Long 	int ch;
9529b76e53SScott Long 
9648f31f4fSBaptiste Daroussin 	is_mps = !strcmp(getprogname(), "mpsutil");
9748f31f4fSBaptiste Daroussin 
9829b76e53SScott Long 	while ((ch = getopt(ac, av, "u:h?")) != -1) {
9929b76e53SScott Long 		switch (ch) {
10029b76e53SScott Long 		case 'u':
10129b76e53SScott Long 			mps_unit = atoi(optarg);
10229b76e53SScott Long 			break;
10329b76e53SScott Long 		case 'h':
10429b76e53SScott Long 		case '?':
10529b76e53SScott Long 			usage();
10629b76e53SScott Long 			return (1);
10729b76e53SScott Long 		}
10829b76e53SScott Long 	}
10929b76e53SScott Long 
11029b76e53SScott Long 	av += optind;
11129b76e53SScott Long 	ac -= optind;
11229b76e53SScott Long 
11329b76e53SScott Long 	/* getopt() eats av[0], so we can't use mpt_table_handler() directly. */
11429b76e53SScott Long 	if (ac == 0) {
11529b76e53SScott Long 		usage();
11629b76e53SScott Long 		return (1);
11729b76e53SScott Long 	}
11829b76e53SScott Long 
11929b76e53SScott Long 	SET_FOREACH(cmd, MPS_DATASET(top)) {
12029b76e53SScott Long 		if (strcmp((*cmd)->name, av[0]) == 0) {
12129b76e53SScott Long 			if ((*cmd)->handler(ac, av))
12229b76e53SScott Long 				return (1);
12329b76e53SScott Long 			else
12429b76e53SScott Long 				return (0);
12529b76e53SScott Long 		}
12629b76e53SScott Long 	}
12729b76e53SScott Long 	warnx("Unknown command %s.", av[0]);
12829b76e53SScott Long 	return (1);
12929b76e53SScott Long }
13029b76e53SScott Long 
13129b76e53SScott Long int
13229b76e53SScott Long mps_table_handler(struct mpsutil_command **start, struct mpsutil_command **end,
13329b76e53SScott Long     int ac, char **av)
13429b76e53SScott Long {
13529b76e53SScott Long 	struct mpsutil_command **cmd;
13629b76e53SScott Long 
13729b76e53SScott Long 	if (ac < 2) {
13829b76e53SScott Long 		warnx("The %s command requires a sub-command.", av[0]);
13929b76e53SScott Long 		return (EINVAL);
14029b76e53SScott Long 	}
14129b76e53SScott Long 	for (cmd = start; cmd < end; cmd++) {
14229b76e53SScott Long 		if (strcmp((*cmd)->name, av[1]) == 0)
14329b76e53SScott Long 			return ((*cmd)->handler(ac - 1, av + 1));
14429b76e53SScott Long 	}
14529b76e53SScott Long 
14629b76e53SScott Long 	warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
14729b76e53SScott Long 	return (ENOENT);
14829b76e53SScott Long }
14929b76e53SScott Long 
15029b76e53SScott Long void
15129b76e53SScott Long hexdump(const void *ptr, int length, const char *hdr, int flags)
15229b76e53SScott Long {
15329b76e53SScott Long 	int i, j, k;
15429b76e53SScott Long 	int cols;
15529b76e53SScott Long 	const unsigned char *cp;
15629b76e53SScott Long 	char delim;
15729b76e53SScott Long 
15829b76e53SScott Long 	if ((flags & HD_DELIM_MASK) != 0)
15929b76e53SScott Long 		delim = (flags & HD_DELIM_MASK) >> 8;
16029b76e53SScott Long 	else
16129b76e53SScott Long 		delim = ' ';
16229b76e53SScott Long 
16329b76e53SScott Long 	if ((flags & HD_COLUMN_MASK) != 0)
16429b76e53SScott Long 		cols = flags & HD_COLUMN_MASK;
16529b76e53SScott Long 	else
16629b76e53SScott Long 		cols = 16;
16729b76e53SScott Long 
16829b76e53SScott Long 	cp = ptr;
16929b76e53SScott Long 	for (i = 0; i < length; i+= cols) {
17029b76e53SScott Long 		if (hdr != NULL)
17129b76e53SScott Long 			printf("%s", hdr);
17229b76e53SScott Long 
17329b76e53SScott Long 		if ((flags & HD_OMIT_COUNT) == 0)
17429b76e53SScott Long 			printf("%04x  ", i);
17529b76e53SScott Long 
17629b76e53SScott Long 		if ((flags & HD_OMIT_HEX) == 0) {
17729b76e53SScott Long 			for (j = 0; j < cols; j++) {
17829b76e53SScott Long 				if (flags & HD_REVERSED)
17929b76e53SScott Long 					k = i + (cols - 1 - j);
18029b76e53SScott Long 				else
18129b76e53SScott Long 					k = i + j;
18229b76e53SScott Long 				if (k < length)
18329b76e53SScott Long 					printf("%c%02x", delim, cp[k]);
18429b76e53SScott Long 				else
18529b76e53SScott Long 					printf("   ");
18629b76e53SScott Long 			}
18729b76e53SScott Long 		}
18829b76e53SScott Long 
18929b76e53SScott Long 		if ((flags & HD_OMIT_CHARS) == 0) {
19029b76e53SScott Long 			printf("  |");
19129b76e53SScott Long 			for (j = 0; j < cols; j++) {
19229b76e53SScott Long 				if (flags & HD_REVERSED)
19329b76e53SScott Long 					k = i + (cols - 1 - j);
19429b76e53SScott Long 				else
19529b76e53SScott Long 					k = i + j;
19629b76e53SScott Long 				if (k >= length)
19729b76e53SScott Long 					printf(" ");
19829b76e53SScott Long 				else if (cp[k] >= ' ' && cp[k] <= '~')
19929b76e53SScott Long 					printf("%c", cp[k]);
20029b76e53SScott Long 				else
20129b76e53SScott Long 					printf(".");
20229b76e53SScott Long 			}
20329b76e53SScott Long 			printf("|");
20429b76e53SScott Long 		}
20529b76e53SScott Long 		printf("\n");
20629b76e53SScott Long 	}
20729b76e53SScott Long }
208