xref: /illumos-gate/usr/src/boot/common/commands.c (revision 22028508)
10a4f1df1SToomas Soome /*
2199767f8SToomas Soome  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3199767f8SToomas Soome  * All rights reserved.
4199767f8SToomas Soome  *
5199767f8SToomas Soome  * Redistribution and use in source and binary forms, with or without
6199767f8SToomas Soome  * modification, are permitted provided that the following conditions
7199767f8SToomas Soome  * are met:
8199767f8SToomas Soome  * 1. Redistributions of source code must retain the above copyright
9199767f8SToomas Soome  *    notice, this list of conditions and the following disclaimer.
10199767f8SToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
11199767f8SToomas Soome  *    notice, this list of conditions and the following disclaimer in the
12199767f8SToomas Soome  *    documentation and/or other materials provided with the distribution.
13199767f8SToomas Soome  *
14199767f8SToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15199767f8SToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16199767f8SToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17199767f8SToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18199767f8SToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19199767f8SToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20199767f8SToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21199767f8SToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22199767f8SToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23199767f8SToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24199767f8SToomas Soome  * SUCH DAMAGE.
25199767f8SToomas Soome  */
26199767f8SToomas Soome 
27199767f8SToomas Soome #include <sys/cdefs.h>
28199767f8SToomas Soome 
29199767f8SToomas Soome #include <stand.h>
30199767f8SToomas Soome #include <string.h>
31199767f8SToomas Soome 
32199767f8SToomas Soome #include "bootstrap.h"
33199767f8SToomas Soome 
34199767f8SToomas Soome const char	*command_errmsg;
35199767f8SToomas Soome /* XXX should have procedural interface for setting, size limit? */
36199767f8SToomas Soome char		command_errbuf[COMMAND_ERRBUFSZ];
37199767f8SToomas Soome 
38199767f8SToomas Soome static int page_file(char *filename);
39199767f8SToomas Soome 
40e4768a34SToomas Soome /* BEGIN CSTYLED */
41199767f8SToomas Soome /*
42199767f8SToomas Soome  * Help is read from a formatted text file.
43199767f8SToomas Soome  *
44e4768a34SToomas Soome  * Entries in the file are formatted as
45199767f8SToomas Soome 
46199767f8SToomas Soome # Ttopic [Ssubtopic] Ddescription
47199767f8SToomas Soome help
48199767f8SToomas Soome text
49199767f8SToomas Soome here
50199767f8SToomas Soome #
51199767f8SToomas Soome 
52199767f8SToomas Soome  *
53199767f8SToomas Soome  * Note that for code simplicity's sake, the above format must be followed
54199767f8SToomas Soome  * exactly.
55199767f8SToomas Soome  *
56199767f8SToomas Soome  * Subtopic entries must immediately follow the topic (this is used to
57199767f8SToomas Soome  * produce the listing of subtopics).
58199767f8SToomas Soome  *
59199767f8SToomas Soome  * If no argument(s) are supplied by the user, the help for 'help' is displayed.
60199767f8SToomas Soome  */
61e4768a34SToomas Soome /* END CSTYLED */
62199767f8SToomas Soome COMMAND_SET(help, "help", "detailed help", command_help);
63199767f8SToomas Soome 
64199767f8SToomas Soome static int
help_getnext(int fd,char ** topic,char ** subtopic,char ** desc)65e4768a34SToomas Soome help_getnext(int fd, char **topic, char **subtopic, char **desc)
66199767f8SToomas Soome {
67e4768a34SToomas Soome 	char	line[81], *cp, *ep;
68e4768a34SToomas Soome 
69e4768a34SToomas Soome 	/* Make sure we provide sane values. */
70e4768a34SToomas Soome 	*topic = *subtopic = *desc = NULL;
71e4768a34SToomas Soome 	for (;;) {
72e4768a34SToomas Soome 		if (fgetstr(line, 80, fd) < 0)
73e4768a34SToomas Soome 			return (0);
74e4768a34SToomas Soome 
75e4768a34SToomas Soome 		if (strlen(line) < 3 || line[0] != '#' || line[1] != ' ')
76e4768a34SToomas Soome 			continue;
77e4768a34SToomas Soome 
78e4768a34SToomas Soome 		*topic = *subtopic = *desc = NULL;
79e4768a34SToomas Soome 		cp = line + 2;
80e4768a34SToomas Soome 		while (cp != NULL && *cp != 0) {
81e4768a34SToomas Soome 			ep = strchr(cp, ' ');
82e4768a34SToomas Soome 			if (*cp == 'T' && *topic == NULL) {
83e4768a34SToomas Soome 				if (ep != NULL)
84e4768a34SToomas Soome 					*ep++ = 0;
85e4768a34SToomas Soome 				*topic = strdup(cp + 1);
86e4768a34SToomas Soome 			} else if (*cp == 'S' && *subtopic == NULL) {
87e4768a34SToomas Soome 				if (ep != NULL)
88e4768a34SToomas Soome 					*ep++ = 0;
89e4768a34SToomas Soome 				*subtopic = strdup(cp + 1);
90e4768a34SToomas Soome 			} else if (*cp == 'D') {
91e4768a34SToomas Soome 				*desc = strdup(cp + 1);
92e4768a34SToomas Soome 				ep = NULL;
93e4768a34SToomas Soome 			}
94e4768a34SToomas Soome 			cp = ep;
95e4768a34SToomas Soome 		}
96e4768a34SToomas Soome 		if (*topic == NULL) {
97e4768a34SToomas Soome 			free(*subtopic);
98e4768a34SToomas Soome 			free(*desc);
99e4768a34SToomas Soome 			*subtopic = *desc = NULL;
100e4768a34SToomas Soome 			continue;
101e4768a34SToomas Soome 		}
102e4768a34SToomas Soome 		return (1);
103199767f8SToomas Soome 	}
104199767f8SToomas Soome }
105199767f8SToomas Soome 
106199767f8SToomas Soome static int
help_emitsummary(char * topic,char * subtopic,char * desc)107199767f8SToomas Soome help_emitsummary(char *topic, char *subtopic, char *desc)
108199767f8SToomas Soome {
109e4768a34SToomas Soome 	int	i;
110e4768a34SToomas Soome 
111e4768a34SToomas Soome 	pager_output("    ");
112e4768a34SToomas Soome 	pager_output(topic);
113e4768a34SToomas Soome 	i = strlen(topic);
114e4768a34SToomas Soome 	if (subtopic != NULL) {
115e4768a34SToomas Soome 		pager_output(" ");
116e4768a34SToomas Soome 		pager_output(subtopic);
117e4768a34SToomas Soome 		i += strlen(subtopic) + 1;
118e4768a34SToomas Soome 	}
119e4768a34SToomas Soome 	if (desc != NULL) {
120e4768a34SToomas Soome 		do {
121e4768a34SToomas Soome 			pager_output(" ");
122e4768a34SToomas Soome 		} while (i++ < 30);
123e4768a34SToomas Soome 		pager_output(desc);
124e4768a34SToomas Soome 	}
125e4768a34SToomas Soome 	return (pager_output("\n"));
126199767f8SToomas Soome }
127199767f8SToomas Soome 
128e4768a34SToomas Soome 
129199767f8SToomas Soome static int
command_help(int argc,char * argv[])130e4768a34SToomas Soome command_help(int argc, char *argv[])
131199767f8SToomas Soome {
132e4768a34SToomas Soome 	char	buf[81];	/* XXX buffer size? */
133e4768a34SToomas Soome 	int	hfd, matched, doindex;
134e4768a34SToomas Soome 	char	*topic, *subtopic, *t, *s, *d;
135e4768a34SToomas Soome 
136e4768a34SToomas Soome 	/* page the help text from our load path */
137e4768a34SToomas Soome 	snprintf(buf, sizeof (buf), "%s/boot/loader.help", getenv("loaddev"));
138e4768a34SToomas Soome 	if ((hfd = open(buf, O_RDONLY)) < 0) {
139e4768a34SToomas Soome 		printf("Verbose help not available, "
140e4768a34SToomas Soome 		    "use '?' to list commands\n");
141e4768a34SToomas Soome 		return (CMD_OK);
142e4768a34SToomas Soome 	}
143199767f8SToomas Soome 
144e4768a34SToomas Soome 	/* pick up request from arguments */
145e4768a34SToomas Soome 	topic = subtopic = NULL;
146e4768a34SToomas Soome 	switch (argc) {
147e4768a34SToomas Soome 	case 3:
148e4768a34SToomas Soome 		subtopic = strdup(argv[2]);
149e4768a34SToomas Soome 		/* FALLTHROUGH */
150e4768a34SToomas Soome 	case 2:
151e4768a34SToomas Soome 		topic = strdup(argv[1]);
152e4768a34SToomas Soome 		break;
153e4768a34SToomas Soome 	case 1:
154e4768a34SToomas Soome 		topic = strdup("help");
155199767f8SToomas Soome 		break;
156e4768a34SToomas Soome 	default:
157e4768a34SToomas Soome 		command_errmsg = "usage is 'help <topic> [<subtopic>]";
158e4768a34SToomas Soome 		close(hfd);
159e4768a34SToomas Soome 		return (CMD_ERROR);
160e4768a34SToomas Soome 	}
161199767f8SToomas Soome 
162e4768a34SToomas Soome 	/* magic "index" keyword */
163e4768a34SToomas Soome 	doindex = strcmp(topic, "index") == 0? 1 : 0;
164e4768a34SToomas Soome 	matched = doindex;
165e4768a34SToomas Soome 
166e4768a34SToomas Soome 	/* Scan the helpfile looking for help matching the request */
167e4768a34SToomas Soome 	pager_open();
168e4768a34SToomas Soome 	while (help_getnext(hfd, &t, &s, &d)) {
169e4768a34SToomas Soome 
170e4768a34SToomas Soome 		if (doindex) {		/* dink around formatting */
171e4768a34SToomas Soome 			if (help_emitsummary(t, s, d))
172e4768a34SToomas Soome 				break;
173e4768a34SToomas Soome 
174e4768a34SToomas Soome 		} else if (strcmp(topic, t)) {
175e4768a34SToomas Soome 			/* topic mismatch */
176e4768a34SToomas Soome 			if (matched) {
177e4768a34SToomas Soome 				/* nothing more on this topic, stop scanning */
178e4768a34SToomas Soome 				break;
179e4768a34SToomas Soome 			}
180e4768a34SToomas Soome 		} else {
181e4768a34SToomas Soome 			/* topic matched */
182e4768a34SToomas Soome 			matched = 1;
183e4768a34SToomas Soome 			if ((subtopic == NULL && s == NULL) ||
184e4768a34SToomas Soome 			    (subtopic != NULL && s != NULL &&
185e4768a34SToomas Soome 			    strcmp(subtopic, s) == 0)) {
186e4768a34SToomas Soome 				/* exact match, print text */
187e4768a34SToomas Soome 				while (fgetstr(buf, 80, hfd) >= 0 &&
188e4768a34SToomas Soome 				    buf[0] != '#') {
189e4768a34SToomas Soome 					if (pager_output(buf))
190e4768a34SToomas Soome 						break;
191e4768a34SToomas Soome 					if (pager_output("\n"))
192e4768a34SToomas Soome 						break;
193e4768a34SToomas Soome 				}
194e4768a34SToomas Soome 			} else if (subtopic == NULL && s != NULL) {
195e4768a34SToomas Soome 				/* topic match, list subtopics */
196e4768a34SToomas Soome 				if (help_emitsummary(t, s, d))
197e4768a34SToomas Soome 					break;
198e4768a34SToomas Soome 			}
199199767f8SToomas Soome 		}
200e4768a34SToomas Soome 		free(t);
201e4768a34SToomas Soome 		free(s);
202e4768a34SToomas Soome 		free(d);
203e4768a34SToomas Soome 		t = s = d = NULL;
204199767f8SToomas Soome 	}
205199767f8SToomas Soome 	free(t);
206199767f8SToomas Soome 	free(s);
207199767f8SToomas Soome 	free(d);
208e4768a34SToomas Soome 	pager_close();
209e4768a34SToomas Soome 	close(hfd);
210e4768a34SToomas Soome 	if (!matched) {
211e4768a34SToomas Soome 		snprintf(command_errbuf, sizeof (command_errbuf),
212e4768a34SToomas Soome 		    "no help available for '%s'", topic);
213e4768a34SToomas Soome 		free(topic);
214e4768a34SToomas Soome 		free(subtopic);
215e4768a34SToomas Soome 		return (CMD_ERROR);
216e4768a34SToomas Soome 	}
217199767f8SToomas Soome 	free(topic);
2180a4f1df1SToomas Soome 	free(subtopic);
219e4768a34SToomas Soome 	return (CMD_OK);
220199767f8SToomas Soome }
221199767f8SToomas Soome 
222199767f8SToomas Soome COMMAND_SET(commandlist, "?", "list commands", command_commandlist);
223199767f8SToomas Soome 
224199767f8SToomas Soome static int
command_commandlist(int argc __unused,char * argv[]__unused)2250a4f1df1SToomas Soome command_commandlist(int argc __unused, char *argv[] __unused)
226199767f8SToomas Soome {
227e4768a34SToomas Soome 	struct bootblk_command	**cmdp;
228e4768a34SToomas Soome 	int	res;
229e4768a34SToomas Soome 	char	name[20];
230e4768a34SToomas Soome 
231e4768a34SToomas Soome 	res = 0;
232e4768a34SToomas Soome 	pager_open();
233e4768a34SToomas Soome 	res = pager_output("Available commands:\n");
234e4768a34SToomas Soome 	SET_FOREACH(cmdp, Xcommand_set) {
235e4768a34SToomas Soome 		if (res)
236e4768a34SToomas Soome 			break;
237e4768a34SToomas Soome 		if ((*cmdp)->c_name != NULL && (*cmdp)->c_desc != NULL) {
238e4768a34SToomas Soome 			snprintf(name, sizeof (name),"  %-15s  ",
239e4768a34SToomas Soome 			    (*cmdp)->c_name);
240e4768a34SToomas Soome 			pager_output(name);
241e4768a34SToomas Soome 			pager_output((*cmdp)->c_desc);
242e4768a34SToomas Soome 			res = pager_output("\n");
243e4768a34SToomas Soome 		}
244199767f8SToomas Soome 	}
245e4768a34SToomas Soome 	pager_close();
246e4768a34SToomas Soome 	return (CMD_OK);
247199767f8SToomas Soome }
248199767f8SToomas Soome 
249199767f8SToomas Soome /*
250199767f8SToomas Soome  * XXX set/show should become set/echo if we have variable
251199767f8SToomas Soome  * substitution happening.
252199767f8SToomas Soome  */
253199767f8SToomas Soome 
254199767f8SToomas Soome COMMAND_SET(show, "show", "show variable(s)", command_show);
255199767f8SToomas Soome 
256199767f8SToomas Soome static int
command_show(int argc,char * argv[])257199767f8SToomas Soome command_show(int argc, char *argv[])
258199767f8SToomas Soome {
259e4768a34SToomas Soome 	struct env_var	*ev;
260e4768a34SToomas Soome 	char		*cp;
261e4768a34SToomas Soome 
262e4768a34SToomas Soome 	if (argc < 2) {
263e4768a34SToomas Soome 		/*
264e4768a34SToomas Soome 		 * With no arguments, print everything.
265e4768a34SToomas Soome 		 */
266e4768a34SToomas Soome 		pager_open();
267e4768a34SToomas Soome 		for (ev = environ; ev != NULL; ev = ev->ev_next) {
268e4768a34SToomas Soome 			pager_output(ev->ev_name);
269e4768a34SToomas Soome 			cp = getenv(ev->ev_name);
270e4768a34SToomas Soome 			if (cp != NULL) {
271e4768a34SToomas Soome 				pager_output("=");
272e4768a34SToomas Soome 				pager_output(cp);
273e4768a34SToomas Soome 			}
274e4768a34SToomas Soome 			if (pager_output("\n"))
275e4768a34SToomas Soome 				break;
276e4768a34SToomas Soome 		}
277e4768a34SToomas Soome 		pager_close();
278199767f8SToomas Soome 	} else {
279e4768a34SToomas Soome 		if ((cp = getenv(argv[1])) != NULL) {
280e4768a34SToomas Soome 			printf("%s\n", cp);
281e4768a34SToomas Soome 		} else {
282e4768a34SToomas Soome 			snprintf(command_errbuf, sizeof (command_errbuf),
283e4768a34SToomas Soome 			    "variable '%s' not found", argv[1]);
284e4768a34SToomas Soome 			return (CMD_ERROR);
285e4768a34SToomas Soome 		}
286199767f8SToomas Soome 	}
287e4768a34SToomas Soome 	return (CMD_OK);
288199767f8SToomas Soome }
289199767f8SToomas Soome 
290199767f8SToomas Soome COMMAND_SET(set, "set", "set a variable", command_set);
291199767f8SToomas Soome 
292199767f8SToomas Soome static int
command_set(int argc,char * argv[])293199767f8SToomas Soome command_set(int argc, char *argv[])
294199767f8SToomas Soome {
295e4768a34SToomas Soome 	int	err;
296e4768a34SToomas Soome 
297e4768a34SToomas Soome 	if (argc != 2) {
298e4768a34SToomas Soome 		command_errmsg = "wrong number of arguments";
299e4768a34SToomas Soome 		return (CMD_ERROR);
300e4768a34SToomas Soome 	} else {
301e4768a34SToomas Soome 		if ((err = putenv(argv[1])) != 0) {
302e4768a34SToomas Soome 			command_errmsg = strerror(err);
303e4768a34SToomas Soome 			return (CMD_ERROR);
304e4768a34SToomas Soome 		}
305199767f8SToomas Soome 	}
306e4768a34SToomas Soome 	return (CMD_OK);
307199767f8SToomas Soome }
308199767f8SToomas Soome 
309199767f8SToomas Soome COMMAND_SET(setprop, "setprop", "set a variable", command_setprop);
310199767f8SToomas Soome 
311199767f8SToomas Soome static int
command_setprop(int argc,char * argv[])312199767f8SToomas Soome command_setprop(int argc, char *argv[])
313199767f8SToomas Soome {
314e4768a34SToomas Soome 	int	err;
315e4768a34SToomas Soome 
316e4768a34SToomas Soome 	if (argc != 3) {
317e4768a34SToomas Soome 		command_errmsg = "wrong number of arguments";
318e4768a34SToomas Soome 		return (CMD_ERROR);
319e4768a34SToomas Soome 	} else {
320e4768a34SToomas Soome 		if ((err = setenv(argv[1], argv[2], 1)) != 0) {
321e4768a34SToomas Soome 			command_errmsg = strerror(err);
322e4768a34SToomas Soome 			return (CMD_ERROR);
323e4768a34SToomas Soome 		}
324199767f8SToomas Soome 	}
325e4768a34SToomas Soome 	return (CMD_OK);
326199767f8SToomas Soome }
327199767f8SToomas Soome 
328199767f8SToomas Soome COMMAND_SET(unset, "unset", "unset a variable", command_unset);
329199767f8SToomas Soome 
330199767f8SToomas Soome static int
command_unset(int argc,char * argv[])331e4768a34SToomas Soome command_unset(int argc, char *argv[])
332199767f8SToomas Soome {
333e4768a34SToomas Soome 	int	err;
334e4768a34SToomas Soome 
335e4768a34SToomas Soome 	if (argc != 2) {
336e4768a34SToomas Soome 		command_errmsg = "wrong number of arguments";
337e4768a34SToomas Soome 		return (CMD_ERROR);
338e4768a34SToomas Soome 	} else {
339e4768a34SToomas Soome 		if ((err = unsetenv(argv[1])) != 0) {
340e4768a34SToomas Soome 			command_errmsg = strerror(err);
341e4768a34SToomas Soome 			return (CMD_ERROR);
342e4768a34SToomas Soome 		}
343199767f8SToomas Soome 	}
344e4768a34SToomas Soome 	return (CMD_OK);
345199767f8SToomas Soome }
346199767f8SToomas Soome 
347199767f8SToomas Soome COMMAND_SET(echo, "echo", "echo arguments", command_echo);
348199767f8SToomas Soome 
349199767f8SToomas Soome static int
command_echo(int argc,char * argv[])350199767f8SToomas Soome command_echo(int argc, char *argv[])
351199767f8SToomas Soome {
352e4768a34SToomas Soome 	char	*s;
353e4768a34SToomas Soome 	int	nl, ch;
354e4768a34SToomas Soome 
355e4768a34SToomas Soome 	nl = 0;
356e4768a34SToomas Soome 	optind = 1;
357e4768a34SToomas Soome 	optreset = 1;
358e4768a34SToomas Soome 	while ((ch = getopt(argc, argv, "n")) != -1) {
359e4768a34SToomas Soome 		switch (ch) {
360e4768a34SToomas Soome 		case 'n':
361e4768a34SToomas Soome 			nl = 1;
362e4768a34SToomas Soome 			break;
363e4768a34SToomas Soome 		case '?':
364e4768a34SToomas Soome 		default:
365e4768a34SToomas Soome 			/* getopt has already reported an error */
366e4768a34SToomas Soome 			return (CMD_OK);
367e4768a34SToomas Soome 		}
368199767f8SToomas Soome 	}
369e4768a34SToomas Soome 	argv += (optind);
370e4768a34SToomas Soome 	argc -= (optind);
371199767f8SToomas Soome 
372e4768a34SToomas Soome 	s = unargv(argc, argv);
373e4768a34SToomas Soome 	if (s != NULL) {
374e4768a34SToomas Soome 		printf("%s", s);
375e4768a34SToomas Soome 		free(s);
376e4768a34SToomas Soome 	}
377e4768a34SToomas Soome 	if (!nl)
378e4768a34SToomas Soome 		printf("\n");
379e4768a34SToomas Soome 	return (CMD_OK);
380199767f8SToomas Soome }
381199767f8SToomas Soome 
382199767f8SToomas Soome /*
383199767f8SToomas Soome  * A passable emulation of the sh(1) command of the same name.
384199767f8SToomas Soome  */
385199767f8SToomas Soome 
386199767f8SToomas Soome COMMAND_SET(read, "read", "read input from the terminal", command_read);
387199767f8SToomas Soome 
388199767f8SToomas Soome static int
command_read(int argc,char * argv[])389199767f8SToomas Soome command_read(int argc, char *argv[])
390199767f8SToomas Soome {
391e4768a34SToomas Soome 	char	*prompt;
392e4768a34SToomas Soome 	int	timeout;
393e4768a34SToomas Soome 	time_t	when;
394e4768a34SToomas Soome 	char	*cp;
395e4768a34SToomas Soome 	char	*name;
396e4768a34SToomas Soome 	char	buf[256];		/* XXX size? */
397e4768a34SToomas Soome 	int	c;
398e4768a34SToomas Soome 
399e4768a34SToomas Soome 	timeout = -1;
400e4768a34SToomas Soome 	prompt = NULL;
401e4768a34SToomas Soome 	optind = 1;
402e4768a34SToomas Soome 	optreset = 1;
403e4768a34SToomas Soome 	while ((c = getopt(argc, argv, "p:t:")) != -1) {
404e4768a34SToomas Soome 		switch (c) {
405e4768a34SToomas Soome 		case 'p':
406e4768a34SToomas Soome 			prompt = optarg;
407e4768a34SToomas Soome 			break;
408e4768a34SToomas Soome 		case 't':
409e4768a34SToomas Soome 			timeout = strtol(optarg, &cp, 0);
410e4768a34SToomas Soome 			if (cp == optarg) {
411e4768a34SToomas Soome 				snprintf(command_errbuf,
412e4768a34SToomas Soome 				    sizeof (command_errbuf),
413e4768a34SToomas Soome 				    "bad timeout '%s'", optarg);
414e4768a34SToomas Soome 				return (CMD_ERROR);
415e4768a34SToomas Soome 			}
416e4768a34SToomas Soome 			break;
417e4768a34SToomas Soome 		default:
418e4768a34SToomas Soome 			return (CMD_OK);
419e4768a34SToomas Soome 		}
420199767f8SToomas Soome 	}
421e4768a34SToomas Soome 
422e4768a34SToomas Soome 	argv += (optind);
423e4768a34SToomas Soome 	argc -= (optind);
424e4768a34SToomas Soome 	name = (argc > 0) ? argv[0]: NULL;
425e4768a34SToomas Soome 
426e4768a34SToomas Soome 	if (prompt != NULL)
427e4768a34SToomas Soome 		printf("%s", prompt);
428e4768a34SToomas Soome 	if (timeout >= 0) {
429e4768a34SToomas Soome 		when = time(NULL) + timeout;
430e4768a34SToomas Soome 		while (!ischar())
431e4768a34SToomas Soome 			if (time(NULL) >= when)
432e4768a34SToomas Soome 				return (CMD_OK); /* is timeout an error? */
433e4768a34SToomas Soome 	}
434e4768a34SToomas Soome 
435e4768a34SToomas Soome 	ngets(buf, sizeof (buf));
436e4768a34SToomas Soome 
437e4768a34SToomas Soome 	if (name != NULL)
438e4768a34SToomas Soome 		setenv(name, buf, 1);
439e4768a34SToomas Soome 	return (CMD_OK);
440199767f8SToomas Soome }
441199767f8SToomas Soome 
442199767f8SToomas Soome /*
443199767f8SToomas Soome  * File pager
444199767f8SToomas Soome  */
445199767f8SToomas Soome COMMAND_SET(more, "more", "show contents of a file", command_more);
446199767f8SToomas Soome 
447199767f8SToomas Soome static int
command_more(int argc,char * argv[])448199767f8SToomas Soome command_more(int argc, char *argv[])
449199767f8SToomas Soome {
450e4768a34SToomas Soome 	int	i;
451e4768a34SToomas Soome 	int	res;
452e4768a34SToomas Soome 	char	line[80];
453e4768a34SToomas Soome 
454e4768a34SToomas Soome 	res = 0;
455e4768a34SToomas Soome 	pager_open();
456e4768a34SToomas Soome 	for (i = 1; (i < argc) && (res == 0); i++) {
457e4768a34SToomas Soome 		snprintf(line, sizeof (line), "*** FILE %s BEGIN ***\n",
458e4768a34SToomas Soome 		    argv[i]);
459e4768a34SToomas Soome 		if (pager_output(line))
460e4768a34SToomas Soome 			break;
461e4768a34SToomas Soome 		res = page_file(argv[i]);
462e4768a34SToomas Soome 		if (!res) {
463e4768a34SToomas Soome 			snprintf(line, sizeof (line), "*** FILE %s END ***\n",
464e4768a34SToomas Soome 			    argv[i]);
465e4768a34SToomas Soome 			res = pager_output(line);
466e4768a34SToomas Soome 		}
467199767f8SToomas Soome 	}
468e4768a34SToomas Soome 	pager_close();
469199767f8SToomas Soome 
470e4768a34SToomas Soome 	if (res == 0)
471e4768a34SToomas Soome 		return (CMD_OK);
472e4768a34SToomas Soome 	else
473e4768a34SToomas Soome 		return (CMD_ERROR);
474199767f8SToomas Soome }
475199767f8SToomas Soome 
476199767f8SToomas Soome static int
page_file(char * filename)477199767f8SToomas Soome page_file(char *filename)
478199767f8SToomas Soome {
479e4768a34SToomas Soome 	int result;
480199767f8SToomas Soome 
481e4768a34SToomas Soome 	result = pager_file(filename);
482199767f8SToomas Soome 
483e4768a34SToomas Soome 	if (result == -1) {
484e4768a34SToomas Soome 		snprintf(command_errbuf, sizeof (command_errbuf),
485e4768a34SToomas Soome 		    "error showing %s", filename);
486e4768a34SToomas Soome 	}
487199767f8SToomas Soome 
488e4768a34SToomas Soome 	return (result);
489e4768a34SToomas Soome }
490199767f8SToomas Soome 
491199767f8SToomas Soome /*
492199767f8SToomas Soome  * List all disk-like devices
493199767f8SToomas Soome  */
494199767f8SToomas Soome COMMAND_SET(lsdev, "lsdev", "list all devices", command_lsdev);
495199767f8SToomas Soome 
496199767f8SToomas Soome static int
command_lsdev(int argc,char * argv[])497199767f8SToomas Soome command_lsdev(int argc, char *argv[])
498199767f8SToomas Soome {
499e4768a34SToomas Soome 	int	verbose, ch, i;
500e4768a34SToomas Soome 	char	line[80];
501e4768a34SToomas Soome 
502e4768a34SToomas Soome 	verbose = 0;
503e4768a34SToomas Soome 	optind = 1;
504e4768a34SToomas Soome 	optreset = 1;
505e4768a34SToomas Soome 	while ((ch = getopt(argc, argv, "v")) != -1) {
506e4768a34SToomas Soome 		switch (ch) {
507e4768a34SToomas Soome 		case 'v':
508e4768a34SToomas Soome 			verbose = 1;
509e4768a34SToomas Soome 			break;
510e4768a34SToomas Soome 		case '?':
511e4768a34SToomas Soome 		default:
512e4768a34SToomas Soome 			/* getopt has already reported an error */
513e4768a34SToomas Soome 			return (CMD_OK);
514e4768a34SToomas Soome 		}
515199767f8SToomas Soome 	}
516e4768a34SToomas Soome 	argv += (optind);
517e4768a34SToomas Soome 	argc -= (optind);
518e4768a34SToomas Soome 
519e4768a34SToomas Soome 	pager_open();
520e4768a34SToomas Soome 	for (i = 0; devsw[i] != NULL; i++) {
521e4768a34SToomas Soome 		if (devsw[i]->dv_print != NULL) {
522e4768a34SToomas Soome 			if (devsw[i]->dv_print(verbose))
523e4768a34SToomas Soome 				break;
524e4768a34SToomas Soome 		} else {
525e4768a34SToomas Soome 			snprintf(line, sizeof (line), "%s: (unknown)\n",
526e4768a34SToomas Soome 			    devsw[i]->dv_name);
527e4768a34SToomas Soome 			if (pager_output(line))
528e4768a34SToomas Soome 				break;
529e4768a34SToomas Soome 		}
530199767f8SToomas Soome 	}
531e4768a34SToomas Soome 	pager_close();
532e4768a34SToomas Soome 	return (CMD_OK);
533199767f8SToomas Soome }
534