129b76e53SScott Long /*- 2883bb7e9SScott Long * Copyright (c) 2015 Netflix, Inc. 3883bb7e9SScott Long * All rights reserved. 4883bb7e9SScott Long * Written by: Scott Long <scottl@freebsd.org> 5883bb7e9SScott 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)) { 62*9059c77eSEitan Adler if (*cmd == NULL) { 6329b76e53SScott Long fprintf(stderr, "\n"); 64*9059c77eSEitan Adler } 65*9059c77eSEitan Adler else { 6629b76e53SScott Long (*cmd)->handler(&args, &desc); 6729b76e53SScott Long if (strncmp((*cmd)->set, "top", 3) == 0) 6829b76e53SScott Long fprintf(stderr, "%s %-30s\t%s\n", 6929b76e53SScott Long (*cmd)->name, args, desc); 7029b76e53SScott Long else 7129b76e53SScott Long fprintf(stderr, "%s %s %-30s\t%s\n", 7229b76e53SScott Long (*cmd)->set, (*cmd)->name, args, desc); 7329b76e53SScott Long } 74*9059c77eSEitan Adler } 7529b76e53SScott Long exit(1); 7629b76e53SScott Long } 7729b76e53SScott Long 7829b76e53SScott Long static int 7929b76e53SScott Long version(int ac, char **av) 8029b76e53SScott Long { 8129b76e53SScott Long 8248f31f4fSBaptiste Daroussin printf("%s: version %s", MPSUTIL_VERSION, getprogname()); 8329b76e53SScott Long #ifdef DEBUG 8429b76e53SScott Long printf(" (DEBUG)"); 8529b76e53SScott Long #endif 8629b76e53SScott Long printf("\n"); 8729b76e53SScott Long return (0); 8829b76e53SScott Long } 8929b76e53SScott Long 9029b76e53SScott Long MPS_COMMAND(top, version, version, "", "version") 9129b76e53SScott Long 9229b76e53SScott Long int 9329b76e53SScott Long main(int ac, char **av) 9429b76e53SScott Long { 9529b76e53SScott Long struct mpsutil_command **cmd; 9629b76e53SScott Long int ch; 9729b76e53SScott Long 9848f31f4fSBaptiste Daroussin is_mps = !strcmp(getprogname(), "mpsutil"); 9948f31f4fSBaptiste Daroussin 10029b76e53SScott Long while ((ch = getopt(ac, av, "u:h?")) != -1) { 10129b76e53SScott Long switch (ch) { 10229b76e53SScott Long case 'u': 10329b76e53SScott Long mps_unit = atoi(optarg); 10429b76e53SScott Long break; 10529b76e53SScott Long case 'h': 10629b76e53SScott Long case '?': 10729b76e53SScott Long usage(); 10829b76e53SScott Long return (1); 10929b76e53SScott Long } 11029b76e53SScott Long } 11129b76e53SScott Long 11229b76e53SScott Long av += optind; 11329b76e53SScott Long ac -= optind; 11429b76e53SScott Long 11529b76e53SScott Long /* getopt() eats av[0], so we can't use mpt_table_handler() directly. */ 11629b76e53SScott Long if (ac == 0) { 11729b76e53SScott Long usage(); 11829b76e53SScott Long return (1); 11929b76e53SScott Long } 12029b76e53SScott Long 12129b76e53SScott Long SET_FOREACH(cmd, MPS_DATASET(top)) { 12229b76e53SScott Long if (strcmp((*cmd)->name, av[0]) == 0) { 12329b76e53SScott Long if ((*cmd)->handler(ac, av)) 12429b76e53SScott Long return (1); 12529b76e53SScott Long else 12629b76e53SScott Long return (0); 12729b76e53SScott Long } 12829b76e53SScott Long } 12929b76e53SScott Long warnx("Unknown command %s.", av[0]); 13029b76e53SScott Long return (1); 13129b76e53SScott Long } 13229b76e53SScott Long 13329b76e53SScott Long int 13429b76e53SScott Long mps_table_handler(struct mpsutil_command **start, struct mpsutil_command **end, 13529b76e53SScott Long int ac, char **av) 13629b76e53SScott Long { 13729b76e53SScott Long struct mpsutil_command **cmd; 13829b76e53SScott Long 13929b76e53SScott Long if (ac < 2) { 14029b76e53SScott Long warnx("The %s command requires a sub-command.", av[0]); 14129b76e53SScott Long return (EINVAL); 14229b76e53SScott Long } 14329b76e53SScott Long for (cmd = start; cmd < end; cmd++) { 14429b76e53SScott Long if (strcmp((*cmd)->name, av[1]) == 0) 14529b76e53SScott Long return ((*cmd)->handler(ac - 1, av + 1)); 14629b76e53SScott Long } 14729b76e53SScott Long 14829b76e53SScott Long warnx("%s is not a valid sub-command of %s.", av[1], av[0]); 14929b76e53SScott Long return (ENOENT); 15029b76e53SScott Long } 15129b76e53SScott Long 15229b76e53SScott Long void 15329b76e53SScott Long hexdump(const void *ptr, int length, const char *hdr, int flags) 15429b76e53SScott Long { 15529b76e53SScott Long int i, j, k; 15629b76e53SScott Long int cols; 15729b76e53SScott Long const unsigned char *cp; 15829b76e53SScott Long char delim; 15929b76e53SScott Long 16029b76e53SScott Long if ((flags & HD_DELIM_MASK) != 0) 16129b76e53SScott Long delim = (flags & HD_DELIM_MASK) >> 8; 16229b76e53SScott Long else 16329b76e53SScott Long delim = ' '; 16429b76e53SScott Long 16529b76e53SScott Long if ((flags & HD_COLUMN_MASK) != 0) 16629b76e53SScott Long cols = flags & HD_COLUMN_MASK; 16729b76e53SScott Long else 16829b76e53SScott Long cols = 16; 16929b76e53SScott Long 17029b76e53SScott Long cp = ptr; 17129b76e53SScott Long for (i = 0; i < length; i+= cols) { 17229b76e53SScott Long if (hdr != NULL) 17329b76e53SScott Long printf("%s", hdr); 17429b76e53SScott Long 17529b76e53SScott Long if ((flags & HD_OMIT_COUNT) == 0) 17629b76e53SScott Long printf("%04x ", i); 17729b76e53SScott Long 17829b76e53SScott Long if ((flags & HD_OMIT_HEX) == 0) { 17929b76e53SScott Long for (j = 0; j < cols; j++) { 18029b76e53SScott Long if (flags & HD_REVERSED) 18129b76e53SScott Long k = i + (cols - 1 - j); 18229b76e53SScott Long else 18329b76e53SScott Long k = i + j; 18429b76e53SScott Long if (k < length) 18529b76e53SScott Long printf("%c%02x", delim, cp[k]); 18629b76e53SScott Long else 18729b76e53SScott Long printf(" "); 18829b76e53SScott Long } 18929b76e53SScott Long } 19029b76e53SScott Long 19129b76e53SScott Long if ((flags & HD_OMIT_CHARS) == 0) { 19229b76e53SScott Long printf(" |"); 19329b76e53SScott Long for (j = 0; j < cols; j++) { 19429b76e53SScott Long if (flags & HD_REVERSED) 19529b76e53SScott Long k = i + (cols - 1 - j); 19629b76e53SScott Long else 19729b76e53SScott Long k = i + j; 19829b76e53SScott Long if (k >= length) 19929b76e53SScott Long printf(" "); 20029b76e53SScott Long else if (cp[k] >= ' ' && cp[k] <= '~') 20129b76e53SScott Long printf("%c", cp[k]); 20229b76e53SScott Long else 20329b76e53SScott Long printf("."); 20429b76e53SScott Long } 20529b76e53SScott Long printf("|"); 20629b76e53SScott Long } 20729b76e53SScott Long printf("\n"); 20829b76e53SScott Long } 20929b76e53SScott Long } 210b3995bb8SScott Long 211b3995bb8SScott Long #define PCHAR(c) { if (retval < tmpsz) { *outbuf++ = (c); retval++; } } 212b3995bb8SScott Long 213b3995bb8SScott Long int 214b3995bb8SScott Long mps_parse_flags(uintmax_t num, const char *q, char *outbuf, int tmpsz) 215b3995bb8SScott Long { 216b3995bb8SScott Long int n, tmp, retval = 0; 217b3995bb8SScott Long 218b3995bb8SScott Long if (num == 0) 219b3995bb8SScott Long return (retval); 220b3995bb8SScott Long 221b3995bb8SScott Long /* %b conversion flag format. */ 222b3995bb8SScott Long tmp = retval; 223b3995bb8SScott Long while (*q) { 224b3995bb8SScott Long n = *q++; 225b3995bb8SScott Long if (num & (1 << (n - 1))) { 226b3995bb8SScott Long PCHAR(retval != tmp ? ',' : '<'); 227b3995bb8SScott Long for (; (n = *q) > ' '; ++q) 228b3995bb8SScott Long PCHAR(n); 229b3995bb8SScott Long } else 230b3995bb8SScott Long for (; *q > ' '; ++q) 231b3995bb8SScott Long continue; 232b3995bb8SScott Long } 233b3995bb8SScott Long if (retval != tmp) 234b3995bb8SScott Long PCHAR('>'); 235b3995bb8SScott Long 236b3995bb8SScott Long return (retval); 237b3995bb8SScott Long } 238b3995bb8SScott Long 239