commands.c revision 40015
1179189Sjb/*-
2179189Sjb * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3321268Sngie * All rights reserved.
4321268Sngie *
5179189Sjb * Redistribution and use in source and binary forms, with or without
6179189Sjb * modification, are permitted provided that the following conditions
7179189Sjb * are met:
8179189Sjb * 1. Redistributions of source code must retain the above copyright
9179189Sjb *    notice, this list of conditions and the following disclaimer.
10179189Sjb * 2. Redistributions in binary form must reproduce the above copyright
11179189Sjb *    notice, this list of conditions and the following disclaimer in the
12179189Sjb *    documentation and/or other materials provided with the distribution.
13179189Sjb *
14179189Sjb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15179189Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16179189Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17179189Sjb * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18179189Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19179189Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20179189Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21211554Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22179189Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23179189Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24179189Sjb * SUCH DAMAGE.
25179189Sjb *
26179189Sjb *	$Id: commands.c,v 1.3 1998/09/18 02:01:38 msmith Exp $
27179189Sjb */
28179189Sjb
29179189Sjb#include <stand.h>
30179189Sjb#include <string.h>
31179189Sjb#include <sys/reboot.h>
32179189Sjb
33179189Sjb#include "bootstrap.h"
34250574Smarkj
35179189Sjbchar		*command_errmsg;
36248708Spfgchar		command_errbuf[256];	/* XXX should have procedural interface for setting, size limit? */
37179189Sjb
38179189SjbCOMMAND_SET(help, "help", "detailed help", command_help);
39179189Sjb
40179189Sjbstatic int
41179189Sjbcommand_help(int argc, char *argv[])
42179189Sjb{
43179189Sjb    char	helppath[80];	/* XXX buffer size? */
44179189Sjb
45179189Sjb    /* page the help text from our load path */
46179189Sjb    sprintf(helppath, "%s/boot/boot.help", getenv("loaddev"));
47233415Sgonzo    printf("%s\n", helppath);
48179189Sjb    if (pager_file(helppath) == -1)
49179189Sjb	printf("Verbose help not available, use '?' to list commands\n");
50238366Sgnn    return(CMD_OK);
51254889Smarkj}
52179189Sjb
53283026SmarkjCOMMAND_SET(commandlist, "?", "list commands", command_commandlist);
54179189Sjb
55254889Smarkjstatic int
56323814Sgnncommand_commandlist(int argc, char *argv[])
57254889Smarkj{
58179189Sjb    struct bootblk_command	**cmdp;
59179189Sjb    int				i;
60287971Sbdrewery
61287971Sbdrewery    printf("Available commands:\n");
62287971Sbdrewery    cmdp = (struct bootblk_command **)Xcommand_set.ls_items;
63287971Sbdrewery    for (i = 0; i < Xcommand_set.ls_length; i++)
64204597Suqs	if ((cmdp[i]->c_name != NULL) && (cmdp[i]->c_desc != NULL))
65179189Sjb	    printf("  %-15s  %s\n", cmdp[i]->c_name, cmdp[i]->c_desc);
66211554Srpaulo    return(CMD_OK);
67321268Sngie}
68321268Sngie
69321268Sngie/*
70179189Sjb * XXX set/show should become set/echo if we have variable
71179189Sjb * substitution happening.
72179189Sjb */
73179189Sjb
74179189SjbCOMMAND_SET(show, "show", "show variable(s)", command_show);
75179189Sjb
76179189Sjbstatic int
77285009Sbrcommand_show(int argc, char *argv[])
78285009Sbr{
79321268Sngie    struct env_var	*ev;
80321268Sngie    char		*cp;
81285009Sbr
82321268Sngie    if (argc < 2) {
83211554Srpaulo	/*
84321268Sngie	 * With no arguments, print everything.
85321268Sngie	 */
86321268Sngie	pager_open();
87285009Sbr	for (ev = environ; ev != NULL; ev = ev->ev_next) {
88285009Sbr	    pager_output(ev->ev_name);
89321268Sngie	    cp = getenv(ev->ev_name);
90321268Sngie	    if (cp != NULL) {
91233415Sgonzo		pager_output("=");
92233415Sgonzo		pager_output(cp);
93321268Sngie	    }
94321268Sngie	    pager_output("\n");
95242723Sjhibbits	}
96242723Sjhibbits	pager_close();
97321268Sngie    } else {
98321268Sngie	if ((cp = getenv(argv[1])) != NULL) {
99300618Sbr	    printf("%s\n", cp);
100300618Sbr	} else {
101321268Sngie	    sprintf(command_errbuf, "variable '%s' not found", argv[1]);
102321268Sngie	    return(CMD_ERROR);
103285009Sbr	}
104285009Sbr    }
105321268Sngie    return(CMD_OK);
106179189Sjb}
107179189Sjb
108179189SjbCOMMAND_SET(set, "set", "set a variable", command_set);
109179189Sjb
110179189Sjbstatic int
111211554Srpaulocommand_set(int argc, char *argv[])
112233415Sgonzo{
113211554Srpaulo    int		err;
114211554Srpaulo
115211554Srpaulo    if (argc != 2) {
116179189Sjb	command_errmsg = "wrong number of arguments";
117179189Sjb	return(CMD_ERROR);
118179189Sjb    } else {
119179189Sjb	if ((err = putenv(argv[1])) != 0) {
120283133Sbapt	    command_errmsg = strerror(err);
121283133Sbapt	    return(CMD_ERROR);
122179189Sjb	}
123179189Sjb    }
124313131Smarkj    return(CMD_OK);
125179189Sjb}
126313131Smarkj
127313131SmarkjCOMMAND_SET(unset, "unset", "unset a variable", command_unset);
128179189Sjb
129313131Smarkjstatic int
130313131Smarkjcommand_unset(int argc, char *argv[])
131{
132    int		err;
133
134    if (argc != 2) {
135	command_errmsg = "wrong number of arguments";
136	return(CMD_ERROR);
137    } else {
138	if ((err = unsetenv(argv[1])) != 0) {
139	    command_errmsg = strerror(err);
140	    return(CMD_ERROR);
141	}
142    }
143    return(CMD_OK);
144}
145
146COMMAND_SET(echo, "echo", NULL, command_echo);
147
148static int
149command_echo(int argc, char *argv[])
150{
151    char	*s;
152    int		nl, ch;
153
154    nl = 0;
155    optind = 1;
156    while ((ch = getopt(argc, argv, "n")) != -1) {
157	switch(ch) {
158	case 'n':
159	    nl = 1;
160	    break;
161	case '?':
162	default:
163	    /* getopt has already reported an error */
164	    return(CMD_OK);
165	}
166    }
167    argv += (optind);
168    argc -= (optind);
169
170    s = unargv(argc, argv);
171    if (s != NULL) {
172	printf(s);
173	free(s);
174    }
175    if (!nl)
176	printf("\n");
177    return(CMD_OK);
178}
179
180/*
181 * A passable emulation of the sh(1) command of the same name.
182 */
183
184COMMAND_SET(read, "read", NULL, command_read);
185
186static int
187command_read(int argc, char *argv[])
188{
189    char	*prompt;
190    int		timeout;
191    time_t	when;
192    char	*cp;
193    char	*name;
194    char	buf[256];		/* XXX size? */
195    int		c;
196
197    timeout = -1;
198    prompt = NULL;
199    optind = 1;
200    while ((c = getopt(argc, argv, "p:t:")) != -1) {
201	switch(c) {
202
203	case 'p':
204	    prompt = optarg;
205	    break;
206	case 't':
207	    timeout = strtol(optarg, &cp, 0);
208	    if (cp == optarg) {
209		sprintf(command_errbuf, "bad timeout '%s'", optarg);
210		return(CMD_ERROR);
211	    }
212	    break;
213	default:
214	    return(CMD_OK);
215	}
216    }
217
218    argv += (optind);
219    argc -= (optind);
220    name = (argc > 0) ? argv[0]: NULL;
221
222    if (prompt != NULL)
223	printf(prompt);
224    if (timeout >= 0) {
225	when = time(NULL) + timeout;
226	while (!ischar())
227	    if (time(NULL) >= when)
228		return(CMD_OK);		/* is timeout an error? */
229    }
230
231    ngets(buf, sizeof(buf));
232
233    printf("read name '%s' value '%s'\n", name, buf);
234
235    if (name != NULL)
236	setenv(name, buf, 1);
237    return(CMD_OK);
238}
239