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