129b76e53SScott Long /*- 2883bb7e9SScott Long * Copyright (c) 2015 Netflix, Inc. 3883bb7e9SScott Long * Written by: Scott Long <scottl@freebsd.org> 4883bb7e9SScott Long * 529b76e53SScott Long * Copyright (c) 2008 Yahoo!, Inc. 629b76e53SScott Long * All rights reserved. 729b76e53SScott Long * Written by: John Baldwin <jhb@FreeBSD.org> 829b76e53SScott Long * 929b76e53SScott Long * Redistribution and use in source and binary forms, with or without 1029b76e53SScott Long * modification, are permitted provided that the following conditions 1129b76e53SScott Long * are met: 1229b76e53SScott Long * 1. Redistributions of source code must retain the above copyright 1329b76e53SScott Long * notice, this list of conditions and the following disclaimer. 1429b76e53SScott Long * 2. Redistributions in binary form must reproduce the above copyright 1529b76e53SScott Long * notice, this list of conditions and the following disclaimer in the 1629b76e53SScott Long * documentation and/or other materials provided with the distribution. 1729b76e53SScott Long * 3. Neither the name of the author nor the names of any co-contributors 1829b76e53SScott Long * may be used to endorse or promote products derived from this software 1929b76e53SScott Long * without specific prior written permission. 2029b76e53SScott Long * 2129b76e53SScott Long * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2229b76e53SScott Long * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2329b76e53SScott Long * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2429b76e53SScott Long * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2529b76e53SScott Long * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2629b76e53SScott Long * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2729b76e53SScott Long * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2829b76e53SScott Long * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2929b76e53SScott Long * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3029b76e53SScott Long * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3129b76e53SScott Long * SUCH DAMAGE. 3229b76e53SScott Long */ 3329b76e53SScott Long 3429b76e53SScott Long #include <sys/cdefs.h> 3529b76e53SScott Long __RCSID("$FreeBSD$"); 3629b76e53SScott Long 3729b76e53SScott Long #include <sys/param.h> 3829b76e53SScott Long #include <sys/errno.h> 3929b76e53SScott Long #include <err.h> 40e9de7669SJuli Mallett #include <inttypes.h> 41e9de7669SJuli Mallett #include <paths.h> 4229b76e53SScott Long #include <stdio.h> 4329b76e53SScott Long #include <stdlib.h> 4429b76e53SScott Long #include <string.h> 4529b76e53SScott Long #include <unistd.h> 4629b76e53SScott Long #include "mpsutil.h" 4729b76e53SScott Long 4829b76e53SScott Long SET_DECLARE(MPS_DATASET(top), struct mpsutil_command); 4929b76e53SScott Long SET_DECLARE(MPS_DATASET(usage), struct mpsutil_usage); 5029b76e53SScott Long 5129b76e53SScott Long int mps_unit; 5248f31f4fSBaptiste Daroussin int is_mps; 5329b76e53SScott Long 5429b76e53SScott Long static void 5529b76e53SScott Long usage(void) 5629b76e53SScott Long { 5729b76e53SScott Long struct mpsutil_usage **cmd; 5829b76e53SScott Long const char *args, *desc; 5929b76e53SScott Long 6048f31f4fSBaptiste Daroussin fprintf(stderr, "usage: %s [-u unit] <command> ...\n\n", getprogname()); 6129b76e53SScott Long fprintf(stderr, "Commands include:\n"); 6229b76e53SScott Long SET_FOREACH(cmd, MPS_DATASET(usage)) { 639059c77eSEitan Adler if (*cmd == NULL) { 6429b76e53SScott Long fprintf(stderr, "\n"); 65c739854cSEitan Adler } else { 6629b76e53SScott Long (*cmd)->handler(&args, &desc); 6729b76e53SScott Long if (strncmp((*cmd)->set, "top", 3) == 0) 68*638e2a13SScott Long fprintf(stderr, "%-16s %-28s%s\n", 6929b76e53SScott Long (*cmd)->name, args, desc); 7029b76e53SScott Long else 71*638e2a13SScott Long fprintf(stderr, "%-5s %-10s %-28s%s\n", 7229b76e53SScott Long (*cmd)->set, (*cmd)->name, args, desc); 7329b76e53SScott Long } 749059c77eSEitan 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 90*638e2a13SScott Long MPS_COMMAND(top, version, version, "", "Version number") 9129b76e53SScott Long 9229b76e53SScott Long int 9329b76e53SScott Long main(int ac, char **av) 9429b76e53SScott Long { 9529b76e53SScott Long struct mpsutil_command **cmd; 96e9de7669SJuli Mallett uintmax_t unit; 97e9de7669SJuli Mallett char *end; 9829b76e53SScott Long int ch; 9929b76e53SScott Long 10048f31f4fSBaptiste Daroussin is_mps = !strcmp(getprogname(), "mpsutil"); 10148f31f4fSBaptiste Daroussin 10229b76e53SScott Long while ((ch = getopt(ac, av, "u:h?")) != -1) { 10329b76e53SScott Long switch (ch) { 10429b76e53SScott Long case 'u': 105e9de7669SJuli Mallett if (strncmp(optarg, _PATH_DEV, strlen(_PATH_DEV)) == 0) { 106e9de7669SJuli Mallett optarg += strlen(_PATH_DEV); 107e9de7669SJuli Mallett if (strncmp(optarg, is_mps ? "mps" : "mpr", 3) != 0) 108e9de7669SJuli Mallett errx(1, "Invalid device: %s", optarg); 109e9de7669SJuli Mallett } 110e9de7669SJuli Mallett if (strncmp(optarg, is_mps ? "mps" : "mpr", 3) == 0) 111e9de7669SJuli Mallett optarg += 3; 112e9de7669SJuli Mallett unit = strtoumax(optarg, &end, 10); 113e9de7669SJuli Mallett if (*end != '\0' || unit == UINTMAX_MAX || unit > INT_MAX) 114e9de7669SJuli Mallett errx(1, "Invalid unit: %s", optarg); 115e9de7669SJuli Mallett mps_unit = unit; 11629b76e53SScott Long break; 11729b76e53SScott Long case 'h': 11829b76e53SScott Long case '?': 11929b76e53SScott Long usage(); 12029b76e53SScott Long return (1); 12129b76e53SScott Long } 12229b76e53SScott Long } 12329b76e53SScott Long 12429b76e53SScott Long av += optind; 12529b76e53SScott Long ac -= optind; 12629b76e53SScott Long 12729b76e53SScott Long /* getopt() eats av[0], so we can't use mpt_table_handler() directly. */ 12829b76e53SScott Long if (ac == 0) { 12929b76e53SScott Long usage(); 13029b76e53SScott Long return (1); 13129b76e53SScott Long } 13229b76e53SScott Long 13329b76e53SScott Long SET_FOREACH(cmd, MPS_DATASET(top)) { 13429b76e53SScott Long if (strcmp((*cmd)->name, av[0]) == 0) { 13529b76e53SScott Long if ((*cmd)->handler(ac, av)) 13629b76e53SScott Long return (1); 13729b76e53SScott Long else 13829b76e53SScott Long return (0); 13929b76e53SScott Long } 14029b76e53SScott Long } 14129b76e53SScott Long warnx("Unknown command %s.", av[0]); 14229b76e53SScott Long return (1); 14329b76e53SScott Long } 14429b76e53SScott Long 14529b76e53SScott Long int 14629b76e53SScott Long mps_table_handler(struct mpsutil_command **start, struct mpsutil_command **end, 14729b76e53SScott Long int ac, char **av) 14829b76e53SScott Long { 14929b76e53SScott Long struct mpsutil_command **cmd; 15029b76e53SScott Long 15129b76e53SScott Long if (ac < 2) { 15229b76e53SScott Long warnx("The %s command requires a sub-command.", av[0]); 15329b76e53SScott Long return (EINVAL); 15429b76e53SScott Long } 15529b76e53SScott Long for (cmd = start; cmd < end; cmd++) { 15629b76e53SScott Long if (strcmp((*cmd)->name, av[1]) == 0) 15729b76e53SScott Long return ((*cmd)->handler(ac - 1, av + 1)); 15829b76e53SScott Long } 15929b76e53SScott Long 16029b76e53SScott Long warnx("%s is not a valid sub-command of %s.", av[1], av[0]); 16129b76e53SScott Long return (ENOENT); 16229b76e53SScott Long } 16329b76e53SScott Long 16429b76e53SScott Long void 16529b76e53SScott Long hexdump(const void *ptr, int length, const char *hdr, int flags) 16629b76e53SScott Long { 16729b76e53SScott Long int i, j, k; 16829b76e53SScott Long int cols; 16929b76e53SScott Long const unsigned char *cp; 17029b76e53SScott Long char delim; 17129b76e53SScott Long 17229b76e53SScott Long if ((flags & HD_DELIM_MASK) != 0) 17329b76e53SScott Long delim = (flags & HD_DELIM_MASK) >> 8; 17429b76e53SScott Long else 17529b76e53SScott Long delim = ' '; 17629b76e53SScott Long 17729b76e53SScott Long if ((flags & HD_COLUMN_MASK) != 0) 17829b76e53SScott Long cols = flags & HD_COLUMN_MASK; 17929b76e53SScott Long else 18029b76e53SScott Long cols = 16; 18129b76e53SScott Long 18229b76e53SScott Long cp = ptr; 18329b76e53SScott Long for (i = 0; i < length; i+= cols) { 18429b76e53SScott Long if (hdr != NULL) 18529b76e53SScott Long printf("%s", hdr); 18629b76e53SScott Long 18729b76e53SScott Long if ((flags & HD_OMIT_COUNT) == 0) 18829b76e53SScott Long printf("%04x ", i); 18929b76e53SScott Long 19029b76e53SScott Long if ((flags & HD_OMIT_HEX) == 0) { 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("%c%02x", delim, cp[k]); 19829b76e53SScott Long else 19929b76e53SScott Long printf(" "); 20029b76e53SScott Long } 20129b76e53SScott Long } 20229b76e53SScott Long 20329b76e53SScott Long if ((flags & HD_OMIT_CHARS) == 0) { 20429b76e53SScott Long printf(" |"); 20529b76e53SScott Long for (j = 0; j < cols; j++) { 20629b76e53SScott Long if (flags & HD_REVERSED) 20729b76e53SScott Long k = i + (cols - 1 - j); 20829b76e53SScott Long else 20929b76e53SScott Long k = i + j; 21029b76e53SScott Long if (k >= length) 21129b76e53SScott Long printf(" "); 21229b76e53SScott Long else if (cp[k] >= ' ' && cp[k] <= '~') 21329b76e53SScott Long printf("%c", cp[k]); 21429b76e53SScott Long else 21529b76e53SScott Long printf("."); 21629b76e53SScott Long } 21729b76e53SScott Long printf("|"); 21829b76e53SScott Long } 21929b76e53SScott Long printf("\n"); 22029b76e53SScott Long } 22129b76e53SScott Long } 222b3995bb8SScott Long 223b3995bb8SScott Long #define PCHAR(c) { if (retval < tmpsz) { *outbuf++ = (c); retval++; } } 224b3995bb8SScott Long 225b3995bb8SScott Long int 226b3995bb8SScott Long mps_parse_flags(uintmax_t num, const char *q, char *outbuf, int tmpsz) 227b3995bb8SScott Long { 228b3995bb8SScott Long int n, tmp, retval = 0; 229b3995bb8SScott Long 230b3995bb8SScott Long if (num == 0) 231b3995bb8SScott Long return (retval); 232b3995bb8SScott Long 233b3995bb8SScott Long /* %b conversion flag format. */ 234b3995bb8SScott Long tmp = retval; 235b3995bb8SScott Long while (*q) { 236b3995bb8SScott Long n = *q++; 237b3995bb8SScott Long if (num & (1 << (n - 1))) { 238b3995bb8SScott Long PCHAR(retval != tmp ? ',' : '<'); 239b3995bb8SScott Long for (; (n = *q) > ' '; ++q) 240b3995bb8SScott Long PCHAR(n); 241b3995bb8SScott Long } else 242b3995bb8SScott Long for (; *q > ' '; ++q) 243b3995bb8SScott Long continue; 244b3995bb8SScott Long } 245b3995bb8SScott Long if (retval != tmp) 246b3995bb8SScott Long PCHAR('>'); 247b3995bb8SScott Long 248b3995bb8SScott Long return (retval); 249b3995bb8SScott Long } 250b3995bb8SScott Long 251