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