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