interp.c revision 38716
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: interp.c,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $ 27 */ 28/* 29 * Simple commandline interpreter, toplevel and misc. 30 * 31 * XXX may be obsoleted by BootFORTH 32 */ 33 34#include <stand.h> 35#include <string.h> 36#include "bootstrap.h" 37 38#define MAXARGS 20 /* maximum number of arguments allowed */ 39 40extern int parse(int *argc, char ***argv, char *str); /* interp_parse.c */ 41 42static void prompt(void); 43 44/* 45 * Perform the command 46 */ 47static int 48perform(int argc, char *argv[]) 49{ 50 int i, result; 51 struct bootblk_command **cmdp; 52 bootblk_cmd_t *cmd; 53 54 if (argc < 1) 55 return(CMD_OK); 56 57 /* set return defaults; a successful command will override these */ 58 command_errmsg = command_errbuf; 59 strcpy(command_errbuf, "no error message"); 60 cmd = NULL; 61 result = CMD_ERROR; 62 63 cmdp = (struct bootblk_command **)Xcommand_set.ls_items; 64 for (i = 0; i < Xcommand_set.ls_length; i++) { 65 if ((cmdp[i]->c_name != NULL) && !strcmp(argv[0], cmdp[i]->c_name)) 66 cmd = cmdp[i]->c_fn; 67 } 68 if (cmd != NULL) { 69 result = (cmd)(argc, argv); 70 } else { 71 command_errmsg = "unknown command"; 72 } 73 return(result); 74} 75 76/* 77 * Interactive mode 78 */ 79void 80interact(void) 81{ 82 char input[256]; /* big enough? */ 83 int argc; 84 char **argv; 85 86 for (;;) { 87 input[0] = '\0'; 88 prompt(); 89 ngets(input, sizeof(input)); 90 if (!parse(&argc, &argv, input)) { 91 if (perform(argc, argv)) 92 printf("%s: %s\n", argv[0], command_errmsg); 93 free(argv); 94 } else { 95 printf("parse error\n"); 96 } 97 } 98} 99 100/* 101 * Read command from a file 102 */ 103COMMAND_SET(source, "source", "read commands from a file", command_source); 104 105static int 106command_source(int argc, char *argv[]) 107{ 108 int i; 109 110 for (i = 1; i < argc; i++) 111 source(argv[i]); 112 return(CMD_OK); 113} 114 115void 116source(char *filename) 117{ 118 char input[256]; /* big enough? */ 119 int argc; 120 char **argv, *cp; 121 int fd; 122 123 if (((fd = open(filename, O_RDONLY)) == -1)) { 124 printf("can't open '%s': %s\n", filename, strerror(errno)); 125 } else { 126 while (fgetstr(input, sizeof(input), fd) > 0) { 127 128 /* Discard comments */ 129 if (input[0] == '#') 130 continue; 131 cp = input; 132 /* Echo? */ 133 if (input[0] == '@') { 134 cp++; 135 } else { 136 prompt(); 137 printf("%s\n", input); 138 } 139 140 if (!parse(&argc, &argv, cp)) { 141 if ((argc > 0) && 142 (perform(argc, argv) != 0)) 143 printf("%s: %s\n", argv[0], command_errmsg); 144 free(argv); 145 } 146 } 147 close(fd); 148 } 149} 150 151/* 152 * Emit the current prompt; support primitive embedding of 153 * environment variables. 154 * We're a little rude here, modifying the return from getenv(). 155 */ 156static void 157prompt(void) 158{ 159 char *p, *cp, *ev, c; 160 161 if ((p = getenv("prompt")) == NULL) 162 p = ">"; 163 164 while (*p != 0) { 165 if (*p == '$') { 166 for (cp = p + 1; (*cp != 0) && isalpha(*cp); cp++) 167 ; 168 c = *cp; 169 *cp = 0; 170 ev = getenv(p + 1); 171 *cp = c; 172 173 if (ev != NULL) { 174 printf(ev); 175 p = cp; 176 continue; 177 } 178 } 179 putchar(*p++); 180 } 181 putchar(' '); 182} 183