1 /* $NetBSD: commands.c,v 1.2 2006/04/22 07:58:53 cherry Exp $ */
4 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 /* __FBSDID("$FreeBSD: src/sys/boot/common/commands.c,v 1.19 2003/08/25 23:30:41 obrien Exp $"); */
32 #include <lib/libsa/stand.h>
33 #include <lib/libsa/loadfile.h>
34 #include <lib/libkern/libkern.h>
36 #include "bootstrap.h"
39 char command_errbuf
[256]; /* XXX should have procedural interface for setting, size limit? */
41 static int page_file(char *filename
);
44 * Help is read from a formatted text file.
46 * Entries in the file are formatted as
48 # Ttopic [Ssubtopic] Ddescription
55 * Note that for code simplicity's sake, the above format must be followed
58 * Subtopic entries must immediately follow the topic (this is used to
59 * produce the listing of subtopics).
61 * If no argument(s) are supplied by the user, the help for 'help' is displayed.
65 help_getnext(int fd
, char **topic
, char **subtopic
, char **desc
)
67 char line
[81], *cp
, *ep
;
70 if (fgetstr(line
, 80, fd
) < 0)
73 if ((strlen(line
) < 3) || (line
[0] != '#') || (line
[1] != ' '))
76 *topic
= *subtopic
= *desc
= NULL
;
78 while((cp
!= NULL
) && (*cp
!= 0)) {
80 if ((*cp
== 'T') && (*topic
== NULL
)) {
83 *topic
= strdup(cp
+ 1);
84 } else if ((*cp
== 'S') && (*subtopic
== NULL
)) {
87 *subtopic
= strdup(cp
+ 1);
88 } else if (*cp
== 'D') {
89 *desc
= strdup(cp
+ 1);
95 if (*subtopic
!= NULL
)
106 help_emitsummary(char *topic
, char *subtopic
, char *desc
)
113 if (subtopic
!= NULL
) {
115 pager_output(subtopic
);
116 i
+= strlen(subtopic
) + 1;
124 return (pager_output("\n"));
129 command_help(int argc
, char *argv
[])
131 char buf
[81]; /* XXX buffer size? */
132 int hfd
, matched
, doindex
;
133 char *topic
, *subtopic
, *t
, *s
, *d
;
135 /* page the help text from our load path */
136 sprintf(buf
, "%s/boot/loader.help", getenv("loaddev"));
137 if ((hfd
= open(buf
, O_RDONLY
)) < 0) {
138 printf("Verbose help not available, use '?' to list commands\n");
142 /* pick up request from arguments */
143 topic
= subtopic
= NULL
;
146 subtopic
= strdup(argv
[2]);
148 topic
= strdup(argv
[1]);
151 topic
= strdup("help");
154 command_errmsg
= "usage is 'help <topic> [<subtopic>]";
158 /* magic "index" keyword */
159 doindex
= !strcmp(topic
, "index");
162 /* Scan the helpfile looking for help matching the request */
164 while(help_getnext(hfd
, &t
, &s
, &d
)) {
166 if (doindex
) { /* dink around formatting */
167 if (help_emitsummary(t
, s
, d
))
170 } else if (strcmp(topic
, t
)) {
172 if(matched
) /* nothing more on this topic, stop scanning */
178 if (((subtopic
== NULL
) && (s
== NULL
)) ||
179 ((subtopic
!= NULL
) && (s
!= NULL
) && !strcmp(subtopic
, s
))) {
180 /* exact match, print text */
181 while((fgetstr(buf
, 80, hfd
) >= 0) && (buf
[0] != '#')) {
182 if (pager_output(buf
))
184 if (pager_output("\n"))
187 } else if ((subtopic
== NULL
) && (s
!= NULL
)) {
188 /* topic match, list subtopics */
189 if (help_emitsummary(t
, s
, d
))
200 sprintf(command_errbuf
, "no help available for '%s'", topic
);
214 command_commandlist(int argc
, char *argv
[])
216 struct bootblk_command
*cmdp
;
223 res
= pager_output("Available commands:\n");
225 for (i
= 0, cmdp
= commands
; (cmdp
->c_name
!= NULL
) && (cmdp
->c_desc
!= NULL
); i
++, cmdp
= commands
+ i
) {
228 if ((cmdp
->c_name
!= NULL
) && (cmdp
->c_desc
!= NULL
)) {
229 sprintf(name
, " %s ", cmdp
->c_name
);
231 pager_output(cmdp
->c_desc
);
232 res
= pager_output("\n");
240 * XXX set/show should become set/echo if we have variable
241 * substitution happening.
245 command_show(int argc
, char *argv
[])
252 * With no arguments, print everything.
255 for (ev
= environ
; ev
!= NULL
; ev
= ev
->ev_next
) {
256 pager_output(ev
->ev_name
);
257 cp
= getenv(ev
->ev_name
);
262 if (pager_output("\n"))
267 if ((cp
= getenv(argv
[1])) != NULL
) {
270 sprintf(command_errbuf
, "variable '%s' not found", argv
[1]);
279 command_set(int argc
, char *argv
[])
284 command_errmsg
= "wrong number of arguments";
287 if ((err
= putenv(argv
[1])) != 0) {
288 command_errmsg
= strerror(err
);
297 command_unset(int argc
, char *argv
[])
302 command_errmsg
= "wrong number of arguments";
305 if ((err
= unsetenv(argv
[1])) != 0) {
306 command_errmsg
= strerror(err
);
315 command_echo(int argc
, char *argv
[])
323 while ((ch
= getopt(argc
, argv
, "n")) != -1) {
330 /* getopt has already reported an error */
337 s
= unargv(argc
, argv
);
348 * A passable emulation of the sh(1) command of the same name.
353 command_read(int argc
, char *argv
[])
360 char buf
[256]; /* XXX size? */
367 while ((c
= getopt(argc
, argv
, "p:t:")) != -1) {
374 timeout
= strtol(optarg
, &cp
, 0);
376 sprintf(command_errbuf
, "bad timeout '%s'", optarg
);
387 name
= (argc
> 0) ? argv
[0]: NULL
;
390 printf("%s", prompt
);
392 when
= time(NULL
) + timeout
;
394 if (time(NULL
) >= when
)
395 return(CMD_OK
); /* is timeout an error? */
398 ngets(buf
, sizeof(buf
));
401 setenv(name
, buf
, 1);
410 command_more(int argc
, char *argv
[])
418 for (i
= 1; (i
< argc
) && (res
== 0); i
++) {
419 sprintf(line
, "*** FILE %s BEGIN ***\n", argv
[i
]);
420 if (pager_output(line
))
422 res
= page_file(argv
[i
]);
424 sprintf(line
, "*** FILE %s END ***\n", argv
[i
]);
425 res
= pager_output(line
);
437 page_file(char *filename
)
441 result
= pager_file(filename
);
444 sprintf(command_errbuf
, "error showing %s", filename
);
450 * List all disk-like devices
454 command_lsdev(int argc
, char *argv
[])
462 while ((ch
= getopt(argc
, argv
, "v")) != -1) {
469 /* getopt has already reported an error */
478 sprintf(line
, "Device Enumeration:\n");
481 for (i
= 0; i
< ndevs
; i
++) {
482 sprintf(line
, "%s\n", devsw
[i
].dv_name
);
483 if (pager_output(line
))