1ca987d46SWarner Losh /*-
2ca987d46SWarner Losh * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3ca987d46SWarner Losh * All rights reserved.
4ca987d46SWarner Losh *
5ca987d46SWarner Losh * Redistribution and use in source and binary forms, with or without
6ca987d46SWarner Losh * modification, are permitted provided that the following conditions
7ca987d46SWarner Losh * are met:
8ca987d46SWarner Losh * 1. Redistributions of source code must retain the above copyright
9ca987d46SWarner Losh * notice, this list of conditions and the following disclaimer.
10ca987d46SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright
11ca987d46SWarner Losh * notice, this list of conditions and the following disclaimer in the
12ca987d46SWarner Losh * documentation and/or other materials provided with the distribution.
13ca987d46SWarner Losh *
14ca987d46SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15ca987d46SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16ca987d46SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17ca987d46SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18ca987d46SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19ca987d46SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20ca987d46SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21ca987d46SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22ca987d46SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23ca987d46SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24ca987d46SWarner Losh * SUCH DAMAGE.
25ca987d46SWarner Losh */
26ca987d46SWarner Losh
27ca987d46SWarner Losh #include <stand.h>
28ca987d46SWarner Losh #include <string.h>
29ca987d46SWarner Losh
30ca987d46SWarner Losh #include "bootstrap.h"
31ca987d46SWarner Losh
32746dddb1SToomas Soome const char *command_errmsg;
33ca987d46SWarner Losh /* XXX should have procedural interface for setting, size limit? */
34ca987d46SWarner Losh char command_errbuf[COMMAND_ERRBUFSZ];
35ca987d46SWarner Losh
36ca987d46SWarner Losh static int page_file(char *filename);
37ca987d46SWarner Losh
38ca987d46SWarner Losh /*
39ca987d46SWarner Losh * Help is read from a formatted text file.
40ca987d46SWarner Losh *
41ca987d46SWarner Losh * Entries in the file are formatted as
42ca987d46SWarner Losh
43ca987d46SWarner Losh # Ttopic [Ssubtopic] Ddescription
44ca987d46SWarner Losh help
45ca987d46SWarner Losh text
46ca987d46SWarner Losh here
47ca987d46SWarner Losh #
48ca987d46SWarner Losh
49ca987d46SWarner Losh *
50ca987d46SWarner Losh * Note that for code simplicity's sake, the above format must be followed
51ca987d46SWarner Losh * exactly.
52ca987d46SWarner Losh *
53ca987d46SWarner Losh * Subtopic entries must immediately follow the topic (this is used to
54ca987d46SWarner Losh * produce the listing of subtopics).
55ca987d46SWarner Losh *
56ca987d46SWarner Losh * If no argument(s) are supplied by the user, the help for 'help' is displayed.
57ca987d46SWarner Losh */
58ca987d46SWarner Losh COMMAND_SET(help, "help", "detailed help", command_help);
59ca987d46SWarner Losh
60ca987d46SWarner Losh static int
help_getnext(int fd,char ** topic,char ** subtopic,char ** desc)61ca987d46SWarner Losh help_getnext(int fd, char **topic, char **subtopic, char **desc)
62ca987d46SWarner Losh {
63ca987d46SWarner Losh char line[81], *cp, *ep;
64ca987d46SWarner Losh
655276f604SToomas Soome /* Make sure we provide sane values. */
665276f604SToomas Soome *topic = *subtopic = *desc = NULL;
67ca987d46SWarner Losh for (;;) {
68ca987d46SWarner Losh if (fgetstr(line, 80, fd) < 0)
69ca987d46SWarner Losh return (0);
70ca987d46SWarner Losh
71b67d407aSToomas Soome if (strlen(line) < 3 || line[0] != '#' || line[1] != ' ')
72ca987d46SWarner Losh continue;
73ca987d46SWarner Losh
74ca987d46SWarner Losh cp = line + 2;
75b67d407aSToomas Soome while (cp != NULL && *cp != 0) {
76ca987d46SWarner Losh ep = strchr(cp, ' ');
77b67d407aSToomas Soome if (*cp == 'T' && *topic == NULL) {
78ca987d46SWarner Losh if (ep != NULL)
79ca987d46SWarner Losh *ep++ = 0;
80ca987d46SWarner Losh *topic = strdup(cp + 1);
81b67d407aSToomas Soome } else if (*cp == 'S' && *subtopic == NULL) {
82ca987d46SWarner Losh if (ep != NULL)
83ca987d46SWarner Losh *ep++ = 0;
84ca987d46SWarner Losh *subtopic = strdup(cp + 1);
85ca987d46SWarner Losh } else if (*cp == 'D') {
86ca987d46SWarner Losh *desc = strdup(cp + 1);
87ca987d46SWarner Losh ep = NULL;
88ca987d46SWarner Losh }
89ca987d46SWarner Losh cp = ep;
90ca987d46SWarner Losh }
91ca987d46SWarner Losh if (*topic == NULL) {
92ca987d46SWarner Losh free(*subtopic);
93ca987d46SWarner Losh free(*desc);
946d68f8acSToomas Soome *subtopic = *desc = NULL;
95ca987d46SWarner Losh continue;
96ca987d46SWarner Losh }
97ca987d46SWarner Losh return (1);
98ca987d46SWarner Losh }
99ca987d46SWarner Losh }
100ca987d46SWarner Losh
101ca987d46SWarner Losh static int
help_emitsummary(char * topic,char * subtopic,char * desc)102ca987d46SWarner Losh help_emitsummary(char *topic, char *subtopic, char *desc)
103ca987d46SWarner Losh {
104ca987d46SWarner Losh int i;
105ca987d46SWarner Losh
106ca987d46SWarner Losh pager_output(" ");
107ca987d46SWarner Losh pager_output(topic);
108ca987d46SWarner Losh i = strlen(topic);
109ca987d46SWarner Losh if (subtopic != NULL) {
110ca987d46SWarner Losh pager_output(" ");
111ca987d46SWarner Losh pager_output(subtopic);
112ca987d46SWarner Losh i += strlen(subtopic) + 1;
113ca987d46SWarner Losh }
114ca987d46SWarner Losh if (desc != NULL) {
115ca987d46SWarner Losh do {
116ca987d46SWarner Losh pager_output(" ");
117ca987d46SWarner Losh } while (i++ < 30);
118ca987d46SWarner Losh pager_output(desc);
119ca987d46SWarner Losh }
120ca987d46SWarner Losh return (pager_output("\n"));
121ca987d46SWarner Losh }
122ca987d46SWarner Losh
123ca987d46SWarner Losh static int
command_help(int argc,char * argv[])124ca987d46SWarner Losh command_help(int argc, char *argv[])
125ca987d46SWarner Losh {
126ca987d46SWarner Losh char buf[81]; /* XXX buffer size? */
127ca987d46SWarner Losh int hfd, matched, doindex;
128ca987d46SWarner Losh char *topic, *subtopic, *t, *s, *d;
129ca987d46SWarner Losh
130ca987d46SWarner Losh /* page the help text from our load path */
13188599604SMitchell Horne snprintf(buf, sizeof(buf), "%s/boot/%s", getenv("loaddev"),
13288599604SMitchell Horne HELP_FILENAME);
133ca987d46SWarner Losh if ((hfd = open(buf, O_RDONLY)) < 0) {
134b67d407aSToomas Soome printf("Verbose help not available, "
135b67d407aSToomas Soome "use '?' to list commands\n");
136ca987d46SWarner Losh return (CMD_OK);
137ca987d46SWarner Losh }
138ca987d46SWarner Losh
139ca987d46SWarner Losh /* pick up request from arguments */
140ca987d46SWarner Losh topic = subtopic = NULL;
141ca987d46SWarner Losh switch (argc) {
142ca987d46SWarner Losh case 3:
143ca987d46SWarner Losh subtopic = strdup(argv[2]);
144b67d407aSToomas Soome /* FALLTHROUGH */
145ca987d46SWarner Losh case 2:
146ca987d46SWarner Losh topic = strdup(argv[1]);
147ca987d46SWarner Losh break;
148ca987d46SWarner Losh case 1:
149ca987d46SWarner Losh topic = strdup("help");
150ca987d46SWarner Losh break;
151ca987d46SWarner Losh default:
152ca987d46SWarner Losh command_errmsg = "usage is 'help <topic> [<subtopic>]";
153ca987d46SWarner Losh close(hfd);
154ca987d46SWarner Losh return(CMD_ERROR);
155ca987d46SWarner Losh }
156ca987d46SWarner Losh
157ca987d46SWarner Losh /* magic "index" keyword */
158b67d407aSToomas Soome doindex = strcmp(topic, "index") == 0? 1 : 0;
159ca987d46SWarner Losh matched = doindex;
160ca987d46SWarner Losh
161ca987d46SWarner Losh /* Scan the helpfile looking for help matching the request */
162ca987d46SWarner Losh pager_open();
163ca987d46SWarner Losh while (help_getnext(hfd, &t, &s, &d)) {
164ca987d46SWarner Losh
165ca987d46SWarner Losh if (doindex) { /* dink around formatting */
166ca987d46SWarner Losh if (help_emitsummary(t, s, d))
167ca987d46SWarner Losh break;
168ca987d46SWarner Losh
169ca987d46SWarner Losh } else if (strcmp(topic, t)) {
170ca987d46SWarner Losh /* topic mismatch */
171b67d407aSToomas Soome if (matched) {
172b67d407aSToomas Soome /* nothing more on this topic, stop scanning */
173ca987d46SWarner Losh break;
174b67d407aSToomas Soome }
175ca987d46SWarner Losh } else {
176ca987d46SWarner Losh /* topic matched */
177ca987d46SWarner Losh matched = 1;
178b67d407aSToomas Soome if ((subtopic == NULL && s == NULL) ||
179b67d407aSToomas Soome (subtopic != NULL && s != NULL &&
180b67d407aSToomas Soome strcmp(subtopic, s) == 0)) {
181ca987d46SWarner Losh /* exact match, print text */
182b67d407aSToomas Soome while (fgetstr(buf, 80, hfd) >= 0 &&
183b67d407aSToomas Soome buf[0] != '#') {
184ca987d46SWarner Losh if (pager_output(buf))
185ca987d46SWarner Losh break;
186ca987d46SWarner Losh if (pager_output("\n"))
187ca987d46SWarner Losh break;
188ca987d46SWarner Losh }
189b67d407aSToomas Soome } else if (subtopic == NULL && s != NULL) {
190ca987d46SWarner Losh /* topic match, list subtopics */
191ca987d46SWarner Losh if (help_emitsummary(t, s, d))
192ca987d46SWarner Losh break;
193ca987d46SWarner Losh }
194ca987d46SWarner Losh }
195ca987d46SWarner Losh free(t);
196ca987d46SWarner Losh free(s);
197ca987d46SWarner Losh free(d);
19874ecc441SWarner Losh t = s = d = NULL;
199ca987d46SWarner Losh }
20074ecc441SWarner Losh free(t);
20174ecc441SWarner Losh free(s);
20274ecc441SWarner Losh free(d);
203ca987d46SWarner Losh pager_close();
204ca987d46SWarner Losh close(hfd);
205ca987d46SWarner Losh if (!matched) {
206ca987d46SWarner Losh snprintf(command_errbuf, sizeof(command_errbuf),
207ca987d46SWarner Losh "no help available for '%s'", topic);
208ca987d46SWarner Losh free(topic);
209ca987d46SWarner Losh free(subtopic);
210ca987d46SWarner Losh return (CMD_ERROR);
211ca987d46SWarner Losh }
212ca987d46SWarner Losh free(topic);
213ca987d46SWarner Losh free(subtopic);
214ca987d46SWarner Losh return (CMD_OK);
215ca987d46SWarner Losh }
216ca987d46SWarner Losh
217ca987d46SWarner Losh COMMAND_SET(commandlist, "?", "list commands", command_commandlist);
218ca987d46SWarner Losh
219ca987d46SWarner Losh /*
220ca987d46SWarner Losh * Please note: although we use the pager for the list of commands,
221ca987d46SWarner Losh * this routine is called from the ? FORTH function which then
222ca987d46SWarner Losh * unconditionally prints some commands. This will lead to anomalous
223ca987d46SWarner Losh * behavior. There's no 'pager_output' binding to FORTH to allow
224ca987d46SWarner Losh * things to work right, so I'm documenting the bug rather than
225ca987d46SWarner Losh * fixing it.
226ca987d46SWarner Losh */
227ca987d46SWarner Losh static int
command_commandlist(int argc __unused,char * argv[]__unused)228b67d407aSToomas Soome command_commandlist(int argc __unused, char *argv[] __unused)
229ca987d46SWarner Losh {
230ca987d46SWarner Losh struct bootblk_command **cmdp;
231ca987d46SWarner Losh int res;
232*ab08da53SAhmad Khalifa char name[23];
233ca987d46SWarner Losh
234ca987d46SWarner Losh res = 0;
235ca987d46SWarner Losh pager_open();
236ca987d46SWarner Losh res = pager_output("Available commands:\n");
237ca987d46SWarner Losh SET_FOREACH(cmdp, Xcommand_set) {
238ca987d46SWarner Losh if (res)
239ca987d46SWarner Losh break;
240b67d407aSToomas Soome if ((*cmdp)->c_name != NULL && (*cmdp)->c_desc != NULL) {
241*ab08da53SAhmad Khalifa snprintf(name, sizeof(name), " %-20s",
242b67d407aSToomas Soome (*cmdp)->c_name);
243ca987d46SWarner Losh pager_output(name);
244*ab08da53SAhmad Khalifa pager_output(" ");
245ca987d46SWarner Losh pager_output((*cmdp)->c_desc);
246ca987d46SWarner Losh res = pager_output("\n");
247ca987d46SWarner Losh }
248ca987d46SWarner Losh }
249ca987d46SWarner Losh pager_close();
250ca987d46SWarner Losh return (CMD_OK);
251ca987d46SWarner Losh }
252ca987d46SWarner Losh
253ca987d46SWarner Losh /*
254ca987d46SWarner Losh * XXX set/show should become set/echo if we have variable
255ca987d46SWarner Losh * substitution happening.
256ca987d46SWarner Losh */
257ca987d46SWarner Losh
258ca987d46SWarner Losh COMMAND_SET(show, "show", "show variable(s)", command_show);
259ca987d46SWarner Losh
260ca987d46SWarner Losh static int
command_show(int argc,char * argv[])261ca987d46SWarner Losh command_show(int argc, char *argv[])
262ca987d46SWarner Losh {
263ca987d46SWarner Losh struct env_var *ev;
264ca987d46SWarner Losh char *cp;
265ca987d46SWarner Losh
266ca987d46SWarner Losh if (argc < 2) {
267ca987d46SWarner Losh /*
268ca987d46SWarner Losh * With no arguments, print everything.
269ca987d46SWarner Losh */
270ca987d46SWarner Losh pager_open();
271ca987d46SWarner Losh for (ev = environ; ev != NULL; ev = ev->ev_next) {
272ca987d46SWarner Losh pager_output(ev->ev_name);
273ca987d46SWarner Losh cp = getenv(ev->ev_name);
274ca987d46SWarner Losh if (cp != NULL) {
275ca987d46SWarner Losh pager_output("=");
276ca987d46SWarner Losh pager_output(cp);
277ca987d46SWarner Losh }
278ca987d46SWarner Losh if (pager_output("\n"))
279ca987d46SWarner Losh break;
280ca987d46SWarner Losh }
281ca987d46SWarner Losh pager_close();
282ca987d46SWarner Losh } else {
283ca987d46SWarner Losh if ((cp = getenv(argv[1])) != NULL) {
284ca987d46SWarner Losh printf("%s\n", cp);
285ca987d46SWarner Losh } else {
286ca987d46SWarner Losh snprintf(command_errbuf, sizeof(command_errbuf),
287ca987d46SWarner Losh "variable '%s' not found", argv[1]);
288ca987d46SWarner Losh return (CMD_ERROR);
289ca987d46SWarner Losh }
290ca987d46SWarner Losh }
291ca987d46SWarner Losh return (CMD_OK);
292ca987d46SWarner Losh }
293ca987d46SWarner Losh
294ca987d46SWarner Losh COMMAND_SET(set, "set", "set a variable", command_set);
295ca987d46SWarner Losh
296ca987d46SWarner Losh static int
command_set(int argc,char * argv[])297ca987d46SWarner Losh command_set(int argc, char *argv[])
298ca987d46SWarner Losh {
299ca987d46SWarner Losh int err;
300ca987d46SWarner Losh
301ca987d46SWarner Losh if (argc != 2) {
302ca987d46SWarner Losh command_errmsg = "wrong number of arguments";
303ca987d46SWarner Losh return (CMD_ERROR);
304ca987d46SWarner Losh } else {
305bbac74caSSimon J. Gerraty #ifdef LOADER_VERIEXEC
306bbac74caSSimon J. Gerraty /*
307bbac74caSSimon J. Gerraty * Impose restrictions if input is not verified
308bbac74caSSimon J. Gerraty */
309bbac74caSSimon J. Gerraty const char *restricted[] = {
310bbac74caSSimon J. Gerraty "boot",
311bbac74caSSimon J. Gerraty "init",
312bbac74caSSimon J. Gerraty "loader.ve.",
313bbac74caSSimon J. Gerraty "rootfs",
314bbac74caSSimon J. Gerraty "secur",
315bbac74caSSimon J. Gerraty "vfs.",
316bbac74caSSimon J. Gerraty NULL,
317bbac74caSSimon J. Gerraty };
318bbac74caSSimon J. Gerraty const char **cp;
319bbac74caSSimon J. Gerraty int ves;
320bbac74caSSimon J. Gerraty
321bbac74caSSimon J. Gerraty ves = ve_status_get(-1);
322bbac74caSSimon J. Gerraty if (ves == VE_UNVERIFIED_OK) {
323bbac74caSSimon J. Gerraty #ifdef LOADER_VERIEXEC_TESTING
324bbac74caSSimon J. Gerraty printf("Checking: %s\n", argv[1]);
325bbac74caSSimon J. Gerraty #endif
326bbac74caSSimon J. Gerraty for (cp = restricted; *cp; cp++) {
327bbac74caSSimon J. Gerraty if (strncmp(argv[1], *cp, strlen(*cp)) == 0) {
328bbac74caSSimon J. Gerraty printf("Ignoring restricted variable: %s\n",
329bbac74caSSimon J. Gerraty argv[1]);
330bbac74caSSimon J. Gerraty return (CMD_OK);
331bbac74caSSimon J. Gerraty }
332bbac74caSSimon J. Gerraty }
333bbac74caSSimon J. Gerraty }
334bbac74caSSimon J. Gerraty #endif
335ca987d46SWarner Losh if ((err = putenv(argv[1])) != 0) {
336ca987d46SWarner Losh command_errmsg = strerror(err);
337ca987d46SWarner Losh return (CMD_ERROR);
338ca987d46SWarner Losh }
339ca987d46SWarner Losh }
340ca987d46SWarner Losh return (CMD_OK);
341ca987d46SWarner Losh }
342ca987d46SWarner Losh
343ca987d46SWarner Losh COMMAND_SET(unset, "unset", "unset a variable", command_unset);
344ca987d46SWarner Losh
345ca987d46SWarner Losh static int
command_unset(int argc,char * argv[])346ca987d46SWarner Losh command_unset(int argc, char *argv[])
347ca987d46SWarner Losh {
348ca987d46SWarner Losh int err;
349ca987d46SWarner Losh
350ca987d46SWarner Losh if (argc != 2) {
351ca987d46SWarner Losh command_errmsg = "wrong number of arguments";
352ca987d46SWarner Losh return (CMD_ERROR);
353ca987d46SWarner Losh } else {
354ca987d46SWarner Losh if ((err = unsetenv(argv[1])) != 0) {
355ca987d46SWarner Losh command_errmsg = strerror(err);
356ca987d46SWarner Losh return (CMD_ERROR);
357ca987d46SWarner Losh }
358ca987d46SWarner Losh }
359ca987d46SWarner Losh return (CMD_OK);
360ca987d46SWarner Losh }
361ca987d46SWarner Losh
362ca987d46SWarner Losh COMMAND_SET(echo, "echo", "echo arguments", command_echo);
363ca987d46SWarner Losh
364ca987d46SWarner Losh static int
command_echo(int argc,char * argv[])365ca987d46SWarner Losh command_echo(int argc, char *argv[])
366ca987d46SWarner Losh {
367ca987d46SWarner Losh char *s;
368ca987d46SWarner Losh int nl, ch;
369ca987d46SWarner Losh
370ca987d46SWarner Losh nl = 0;
371ca987d46SWarner Losh optind = 1;
372ca987d46SWarner Losh optreset = 1;
373ca987d46SWarner Losh while ((ch = getopt(argc, argv, "n")) != -1) {
374ca987d46SWarner Losh switch (ch) {
375ca987d46SWarner Losh case 'n':
376ca987d46SWarner Losh nl = 1;
377ca987d46SWarner Losh break;
378ca987d46SWarner Losh case '?':
379ca987d46SWarner Losh default:
380ca987d46SWarner Losh /* getopt has already reported an error */
381ca987d46SWarner Losh return (CMD_OK);
382ca987d46SWarner Losh }
383ca987d46SWarner Losh }
384ca987d46SWarner Losh argv += (optind);
385ca987d46SWarner Losh argc -= (optind);
386ca987d46SWarner Losh
387ca987d46SWarner Losh s = unargv(argc, argv);
388ca987d46SWarner Losh if (s != NULL) {
389ca987d46SWarner Losh printf("%s", s);
390ca987d46SWarner Losh free(s);
391ca987d46SWarner Losh }
392ca987d46SWarner Losh if (!nl)
393ca987d46SWarner Losh printf("\n");
394ca987d46SWarner Losh return (CMD_OK);
395ca987d46SWarner Losh }
396ca987d46SWarner Losh
397ca987d46SWarner Losh /*
398ca987d46SWarner Losh * A passable emulation of the sh(1) command of the same name.
399ca987d46SWarner Losh */
400ca987d46SWarner Losh
401ca987d46SWarner Losh COMMAND_SET(read, "read", "read input from the terminal", command_read);
402ca987d46SWarner Losh
403ca987d46SWarner Losh static int
command_read(int argc,char * argv[])404ca987d46SWarner Losh command_read(int argc, char *argv[])
405ca987d46SWarner Losh {
406ca987d46SWarner Losh char *prompt;
407ca987d46SWarner Losh int timeout;
408ca987d46SWarner Losh time_t when;
409ca987d46SWarner Losh char *cp;
410ca987d46SWarner Losh char *name;
411ca987d46SWarner Losh char buf[256]; /* XXX size? */
412ca987d46SWarner Losh int c;
413ca987d46SWarner Losh
414ca987d46SWarner Losh timeout = -1;
415ca987d46SWarner Losh prompt = NULL;
416ca987d46SWarner Losh optind = 1;
417ca987d46SWarner Losh optreset = 1;
418ca987d46SWarner Losh while ((c = getopt(argc, argv, "p:t:")) != -1) {
419ca987d46SWarner Losh switch (c) {
420ca987d46SWarner Losh case 'p':
421ca987d46SWarner Losh prompt = optarg;
422ca987d46SWarner Losh break;
423ca987d46SWarner Losh case 't':
424ca987d46SWarner Losh timeout = strtol(optarg, &cp, 0);
425ca987d46SWarner Losh if (cp == optarg) {
426b67d407aSToomas Soome snprintf(command_errbuf,
427b67d407aSToomas Soome sizeof(command_errbuf),
428ca987d46SWarner Losh "bad timeout '%s'", optarg);
429ca987d46SWarner Losh return (CMD_ERROR);
430ca987d46SWarner Losh }
431ca987d46SWarner Losh break;
432ca987d46SWarner Losh default:
433ca987d46SWarner Losh return (CMD_OK);
434ca987d46SWarner Losh }
435ca987d46SWarner Losh }
436ca987d46SWarner Losh
437ca987d46SWarner Losh argv += (optind);
438ca987d46SWarner Losh argc -= (optind);
439ca987d46SWarner Losh name = (argc > 0) ? argv[0]: NULL;
440ca987d46SWarner Losh
441ca987d46SWarner Losh if (prompt != NULL)
442ca987d46SWarner Losh printf("%s", prompt);
443ca987d46SWarner Losh if (timeout >= 0) {
444ca987d46SWarner Losh when = time(NULL) + timeout;
445ca987d46SWarner Losh while (!ischar())
446ca987d46SWarner Losh if (time(NULL) >= when)
447ca987d46SWarner Losh return (CMD_OK); /* is timeout an error? */
448ca987d46SWarner Losh }
449ca987d46SWarner Losh
450ca987d46SWarner Losh ngets(buf, sizeof(buf));
451ca987d46SWarner Losh
452ca987d46SWarner Losh if (name != NULL)
453ca987d46SWarner Losh setenv(name, buf, 1);
454ca987d46SWarner Losh return (CMD_OK);
455ca987d46SWarner Losh }
456ca987d46SWarner Losh
457ca987d46SWarner Losh /*
458ca987d46SWarner Losh * File pager
459ca987d46SWarner Losh */
460ca987d46SWarner Losh COMMAND_SET(more, "more", "show contents of a file", command_more);
461ca987d46SWarner Losh
462ca987d46SWarner Losh static int
command_more(int argc,char * argv[])463ca987d46SWarner Losh command_more(int argc, char *argv[])
464ca987d46SWarner Losh {
465ca987d46SWarner Losh int i;
466ca987d46SWarner Losh int res;
467ca987d46SWarner Losh char line[80];
468ca987d46SWarner Losh
469ca987d46SWarner Losh res = 0;
470ca987d46SWarner Losh pager_open();
471ca987d46SWarner Losh for (i = 1; (i < argc) && (res == 0); i++) {
472b67d407aSToomas Soome snprintf(line, sizeof(line), "*** FILE %s BEGIN ***\n",
473b67d407aSToomas Soome argv[i]);
474ca987d46SWarner Losh if (pager_output(line))
475ca987d46SWarner Losh break;
476ca987d46SWarner Losh res = page_file(argv[i]);
477ca987d46SWarner Losh if (!res) {
478b67d407aSToomas Soome snprintf(line, sizeof(line), "*** FILE %s END ***\n",
479b67d407aSToomas Soome argv[i]);
480ca987d46SWarner Losh res = pager_output(line);
481ca987d46SWarner Losh }
482ca987d46SWarner Losh }
483ca987d46SWarner Losh pager_close();
484ca987d46SWarner Losh
485b67d407aSToomas Soome return (CMD_OK);
486ca987d46SWarner Losh }
487ca987d46SWarner Losh
488ca987d46SWarner Losh static int
page_file(char * filename)489ca987d46SWarner Losh page_file(char *filename)
490ca987d46SWarner Losh {
491ca987d46SWarner Losh int result;
492ca987d46SWarner Losh
493ca987d46SWarner Losh result = pager_file(filename);
494ca987d46SWarner Losh
495ca987d46SWarner Losh if (result == -1) {
496ca987d46SWarner Losh snprintf(command_errbuf, sizeof(command_errbuf),
497ca987d46SWarner Losh "error showing %s", filename);
498ca987d46SWarner Losh }
499ca987d46SWarner Losh
500b67d407aSToomas Soome return (result);
501ca987d46SWarner Losh }
502ca987d46SWarner Losh
503ca987d46SWarner Losh /*
504ca987d46SWarner Losh * List all disk-like devices
505ca987d46SWarner Losh */
506ca987d46SWarner Losh COMMAND_SET(lsdev, "lsdev", "list all devices", command_lsdev);
507ca987d46SWarner Losh
508ca987d46SWarner Losh static int
command_lsdev(int argc,char * argv[])509ca987d46SWarner Losh command_lsdev(int argc, char *argv[])
510ca987d46SWarner Losh {
511ca987d46SWarner Losh int verbose, ch, i;
512ca987d46SWarner Losh char line[80];
513ca987d46SWarner Losh
514ca987d46SWarner Losh verbose = 0;
515ca987d46SWarner Losh optind = 1;
516ca987d46SWarner Losh optreset = 1;
517ca987d46SWarner Losh while ((ch = getopt(argc, argv, "v")) != -1) {
518ca987d46SWarner Losh switch (ch) {
519ca987d46SWarner Losh case 'v':
520ca987d46SWarner Losh verbose = 1;
521ca987d46SWarner Losh break;
522ca987d46SWarner Losh case '?':
523ca987d46SWarner Losh default:
524ca987d46SWarner Losh /* getopt has already reported an error */
525ca987d46SWarner Losh return (CMD_OK);
526ca987d46SWarner Losh }
527ca987d46SWarner Losh }
528ca987d46SWarner Losh argv += (optind);
529ca987d46SWarner Losh argc -= (optind);
530ca987d46SWarner Losh
531ca987d46SWarner Losh pager_open();
532ca987d46SWarner Losh for (i = 0; devsw[i] != NULL; i++) {
533ca987d46SWarner Losh if (devsw[i]->dv_print != NULL) {
534ca987d46SWarner Losh if (devsw[i]->dv_print(verbose))
535ca987d46SWarner Losh break;
536ca987d46SWarner Losh } else {
537b67d407aSToomas Soome snprintf(line, sizeof(line), "%s: (unknown)\n",
538b67d407aSToomas Soome devsw[i]->dv_name);
539ca987d46SWarner Losh if (pager_output(line))
540ca987d46SWarner Losh break;
541ca987d46SWarner Losh }
542ca987d46SWarner Losh }
543ca987d46SWarner Losh pager_close();
544ca987d46SWarner Losh return (CMD_OK);
545ca987d46SWarner Losh }
54670661eaaSEmmanuel Vadot
54770661eaaSEmmanuel Vadot static int
command_readtest(int argc,char * argv[])54870661eaaSEmmanuel Vadot command_readtest(int argc, char *argv[])
54970661eaaSEmmanuel Vadot {
55070661eaaSEmmanuel Vadot int fd;
55170661eaaSEmmanuel Vadot time_t start, end;
55270661eaaSEmmanuel Vadot char buf[512];
55370661eaaSEmmanuel Vadot ssize_t rv, count = 0;
55470661eaaSEmmanuel Vadot
55570661eaaSEmmanuel Vadot if (argc != 2) {
55670661eaaSEmmanuel Vadot snprintf(command_errbuf, sizeof(command_errbuf),
55770661eaaSEmmanuel Vadot "Usage: readtest <filename>");
55870661eaaSEmmanuel Vadot return (CMD_ERROR);
55970661eaaSEmmanuel Vadot }
56070661eaaSEmmanuel Vadot
56170661eaaSEmmanuel Vadot start = getsecs();
56270661eaaSEmmanuel Vadot if ((fd = open(argv[1], O_RDONLY)) < 0) {
56370661eaaSEmmanuel Vadot snprintf(command_errbuf, sizeof(command_errbuf),
56470661eaaSEmmanuel Vadot "can't open '%s'", argv[1]);
56570661eaaSEmmanuel Vadot return (CMD_ERROR);
56670661eaaSEmmanuel Vadot }
56770661eaaSEmmanuel Vadot while ((rv = read(fd, buf, sizeof(buf))) > 0)
56870661eaaSEmmanuel Vadot count += rv;
56970661eaaSEmmanuel Vadot end = getsecs();
57070661eaaSEmmanuel Vadot
57170661eaaSEmmanuel Vadot printf("Received %zd bytes during %jd seconds\n", count, (intmax_t)end - start);
57270661eaaSEmmanuel Vadot close(fd);
57370661eaaSEmmanuel Vadot return (CMD_OK);
57470661eaaSEmmanuel Vadot }
57570661eaaSEmmanuel Vadot
57670661eaaSEmmanuel Vadot COMMAND_SET(readtest, "readtest", "Time a file read", command_readtest);
5772101541fSWarner Losh
5782101541fSWarner Losh static int
command_quit(int argc,char * argv[])5792101541fSWarner Losh command_quit(int argc, char *argv[])
5802101541fSWarner Losh {
5812101541fSWarner Losh exit(0);
5822101541fSWarner Losh return (CMD_OK);
5832101541fSWarner Losh }
5842101541fSWarner Losh
5852101541fSWarner Losh COMMAND_SET(quit, "quit", "exit the loader", command_quit);
586