commands.c revision 40106
1/*- 2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $Id: commands.c,v 1.4 1998/10/07 02:38:26 msmith Exp $ 27 */ 28 29#include <stand.h> 30#include <string.h> 31#include <sys/reboot.h> 32 33#include "bootstrap.h" 34 35char *command_errmsg; 36char command_errbuf[256]; /* XXX should have procedural interface for setting, size limit? */ 37 38COMMAND_SET(help, "help", "detailed help", command_help); 39 40static int 41command_help(int argc, char *argv[]) 42{ 43 char helppath[80]; /* XXX buffer size? */ 44 45 /* page the help text from our load path */ 46 sprintf(helppath, "%s/boot/boot.help", getenv("loaddev")); 47 printf("%s\n", helppath); 48 if (pager_file(helppath) == -1) 49 printf("Verbose help not available, use '?' to list commands\n"); 50 return(CMD_OK); 51} 52 53COMMAND_SET(commandlist, "?", "list commands", command_commandlist); 54 55static int 56command_commandlist(int argc, char *argv[]) 57{ 58 struct bootblk_command **cmdp; 59 int i; 60 61 printf("Available commands:\n"); 62 cmdp = (struct bootblk_command **)Xcommand_set.ls_items; 63 for (i = 0; i < Xcommand_set.ls_length; i++) 64 if ((cmdp[i]->c_name != NULL) && (cmdp[i]->c_desc != NULL)) 65 printf(" %-15s %s\n", cmdp[i]->c_name, cmdp[i]->c_desc); 66 return(CMD_OK); 67} 68 69/* 70 * XXX set/show should become set/echo if we have variable 71 * substitution happening. 72 */ 73 74COMMAND_SET(show, "show", "show variable(s)", command_show); 75 76static int 77command_show(int argc, char *argv[]) 78{ 79 struct env_var *ev; 80 char *cp; 81 82 if (argc < 2) { 83 /* 84 * With no arguments, print everything. 85 */ 86 pager_open(); 87 for (ev = environ; ev != NULL; ev = ev->ev_next) { 88 pager_output(ev->ev_name); 89 cp = getenv(ev->ev_name); 90 if (cp != NULL) { 91 pager_output("="); 92 pager_output(cp); 93 } 94 pager_output("\n"); 95 } 96 pager_close(); 97 } else { 98 if ((cp = getenv(argv[1])) != NULL) { 99 printf("%s\n", cp); 100 } else { 101 sprintf(command_errbuf, "variable '%s' not found", argv[1]); 102 return(CMD_ERROR); 103 } 104 } 105 return(CMD_OK); 106} 107 108COMMAND_SET(set, "set", "set a variable", command_set); 109 110static int 111command_set(int argc, char *argv[]) 112{ 113 int err; 114 115 if (argc != 2) { 116 command_errmsg = "wrong number of arguments"; 117 return(CMD_ERROR); 118 } else { 119 if ((err = putenv(argv[1])) != 0) { 120 command_errmsg = strerror(err); 121 return(CMD_ERROR); 122 } 123 } 124 return(CMD_OK); 125} 126 127COMMAND_SET(unset, "unset", "unset a variable", command_unset); 128 129static int 130command_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 if (name != NULL) 234 setenv(name, buf, 1); 235 return(CMD_OK); 236} 237