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 27 /* 28 * Simple commandline interpreter, toplevel and misc. 29 */ 30 31 #include <stand.h> 32 #include <string.h> 33 #include "bootstrap.h" 34 35 INTERP_DEFINE("simp"); 36 37 void 38 interp_preinit(void) 39 { 40 } 41 42 void 43 interp_init(void) 44 { 45 46 setenv("script.lang", "simple", 1); 47 /* Read our default configuration. */ 48 interp_include("/boot/loader.rc"); 49 } 50 51 int 52 interp_run(const char *input) 53 { 54 int argc; 55 char **argv; 56 57 if (parse(&argc, &argv, input)) { 58 printf("parse error\n"); 59 return CMD_ERROR; 60 } 61 62 if (interp_builtin_cmd(argc, argv)) { 63 printf("%s: %s\n", argv[0], command_errmsg); 64 free(argv); 65 return CMD_ERROR; 66 } 67 free(argv); 68 return CMD_OK; 69 } 70 71 /* 72 * Header prepended to each line. The text immediately follows the header. 73 * We try to make this short in order to save memory -- the loader has 74 * limited memory available, and some of the forth files are very long. 75 */ 76 struct includeline 77 { 78 struct includeline *next; 79 int flags; 80 int line; 81 #define SL_QUIET (1<<0) 82 #define SL_IGNOREERR (1<<1) 83 char text[0]; 84 }; 85 86 int 87 interp_include(const char *filename) 88 { 89 struct includeline *script, *se, *sp; 90 char input[256]; /* big enough? */ 91 int argc,res; 92 char **argv, *cp; 93 int fd, flags, line; 94 95 if (((fd = open(filename, O_RDONLY)) == -1)) { 96 snprintf(command_errbuf, sizeof(command_errbuf), 97 "can't open '%s': %s", filename, strerror(errno)); 98 return(CMD_ERROR); 99 } 100 101 #ifdef LOADER_VERIEXEC 102 if (verify_file(fd, filename, 0, VE_GUESS, __func__) < 0) { 103 close(fd); 104 sprintf(command_errbuf,"can't verify '%s'", filename); 105 return(CMD_ERROR); 106 } 107 #endif 108 109 /* 110 * Read the script into memory. 111 */ 112 script = se = NULL; 113 line = 0; 114 115 while (fgetstr(input, sizeof(input), fd) >= 0) { 116 line++; 117 flags = 0; 118 /* Discard comments */ 119 if (strncmp(input+strspn(input, " "), "\\", 1) == 0) 120 continue; 121 cp = input; 122 /* Echo? */ 123 if (input[0] == '@') { 124 cp++; 125 flags |= SL_QUIET; 126 } 127 /* Error OK? */ 128 if (input[0] == '-') { 129 cp++; 130 flags |= SL_IGNOREERR; 131 } 132 133 /* Allocate script line structure and copy line, flags */ 134 if (*cp == '\0') 135 continue; /* ignore empty line, save memory */ 136 sp = malloc(sizeof(struct includeline) + strlen(cp) + 1); 137 /* On malloc failure (it happens!), free as much as possible and exit */ 138 if (sp == NULL) { 139 while (script != NULL) { 140 se = script; 141 script = script->next; 142 free(se); 143 } 144 snprintf(command_errbuf, sizeof(command_errbuf), 145 "file '%s' line %d: memory allocation failure - aborting", 146 filename, line); 147 close(fd); 148 return (CMD_ERROR); 149 } 150 strcpy(sp->text, cp); 151 sp->flags = flags; 152 sp->line = line; 153 sp->next = NULL; 154 155 if (script == NULL) { 156 script = sp; 157 } else { 158 se->next = sp; 159 } 160 se = sp; 161 } 162 close(fd); 163 164 /* 165 * Execute the script 166 */ 167 argv = NULL; 168 res = CMD_OK; 169 for (sp = script; sp != NULL; sp = sp->next) { 170 171 /* print if not being quiet */ 172 if (!(sp->flags & SL_QUIET)) { 173 interp_emit_prompt(); 174 printf("%s\n", sp->text); 175 } 176 177 /* Parse the command */ 178 if (!parse(&argc, &argv, sp->text)) { 179 if ((argc > 0) && (interp_builtin_cmd(argc, argv) != 0)) { 180 /* normal command */ 181 printf("%s: %s\n", argv[0], command_errmsg); 182 if (!(sp->flags & SL_IGNOREERR)) { 183 res=CMD_ERROR; 184 break; 185 } 186 } 187 free(argv); 188 argv = NULL; 189 } else { 190 printf("%s line %d: parse error\n", filename, sp->line); 191 res=CMD_ERROR; 192 break; 193 } 194 } 195 if (argv != NULL) 196 free(argv); 197 198 while (script != NULL) { 199 se = script; 200 script = script->next; 201 free(se); 202 } 203 return(res); 204 } 205 206 /* 207 * There's no graphics commands for the simple interpreter. 208 */ 209 void 210 gfx_interp_ref(void) 211 { 212 } 213