/*-1* Copyright (c) 1998 Michael Smith <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526/*27* Simple commandline interpreter, toplevel and misc.28*/2930#include <stand.h>31#include <string.h>32#include "bootstrap.h"3334INTERP_DEFINE("simp");3536void37interp_preinit(void)38{39}4041void42interp_init(void)43{4445setenv("script.lang", "simple", 1);46/* Read our default configuration. */47interp_include("/boot/loader.rc");48}4950int51interp_run(const char *input)52{53int argc;54char **argv;5556if (parse(&argc, &argv, input)) {57printf("parse error\n");58return CMD_ERROR;59}6061if (interp_builtin_cmd(argc, argv)) {62printf("%s: %s\n", argv[0], command_errmsg);63free(argv);64return CMD_ERROR;65}66free(argv);67return CMD_OK;68}6970/*71* Header prepended to each line. The text immediately follows the header.72* We try to make this short in order to save memory -- the loader has73* limited memory available, and some of the forth files are very long.74*/75struct includeline76{77struct includeline *next;78int flags;79int line;80#define SL_QUIET (1<<0)81#define SL_IGNOREERR (1<<1)82char text[0];83};8485int86interp_include(const char *filename)87{88struct includeline *script, *se, *sp;89char input[256]; /* big enough? */90int argc,res;91char **argv, *cp;92int fd, flags, line;9394if (((fd = open(filename, O_RDONLY)) == -1)) {95snprintf(command_errbuf, sizeof(command_errbuf),96"can't open '%s': %s", filename, strerror(errno));97return(CMD_ERROR);98}99100#ifdef LOADER_VERIEXEC101if (verify_file(fd, filename, 0, VE_GUESS, __func__) < 0) {102close(fd);103sprintf(command_errbuf,"can't verify '%s'", filename);104return(CMD_ERROR);105}106#endif107108/*109* Read the script into memory.110*/111script = se = NULL;112line = 0;113114while (fgetstr(input, sizeof(input), fd) >= 0) {115line++;116flags = 0;117/* Discard comments */118if (strncmp(input+strspn(input, " "), "\\", 1) == 0)119continue;120cp = input;121/* Echo? */122if (input[0] == '@') {123cp++;124flags |= SL_QUIET;125}126/* Error OK? */127if (input[0] == '-') {128cp++;129flags |= SL_IGNOREERR;130}131132/* Allocate script line structure and copy line, flags */133if (*cp == '\0')134continue; /* ignore empty line, save memory */135sp = malloc(sizeof(struct includeline) + strlen(cp) + 1);136/* On malloc failure (it happens!), free as much as possible and exit */137if (sp == NULL) {138while (script != NULL) {139se = script;140script = script->next;141free(se);142}143snprintf(command_errbuf, sizeof(command_errbuf),144"file '%s' line %d: memory allocation failure - aborting",145filename, line);146close(fd);147return (CMD_ERROR);148}149strcpy(sp->text, cp);150sp->flags = flags;151sp->line = line;152sp->next = NULL;153154if (script == NULL) {155script = sp;156} else {157se->next = sp;158}159se = sp;160}161close(fd);162163/*164* Execute the script165*/166argv = NULL;167res = CMD_OK;168for (sp = script; sp != NULL; sp = sp->next) {169170/* print if not being quiet */171if (!(sp->flags & SL_QUIET)) {172interp_emit_prompt();173printf("%s\n", sp->text);174}175176/* Parse the command */177if (!parse(&argc, &argv, sp->text)) {178if ((argc > 0) && (interp_builtin_cmd(argc, argv) != 0)) {179/* normal command */180printf("%s: %s\n", argv[0], command_errmsg);181if (!(sp->flags & SL_IGNOREERR)) {182res=CMD_ERROR;183break;184}185}186free(argv);187argv = NULL;188} else {189printf("%s line %d: parse error\n", filename, sp->line);190res=CMD_ERROR;191break;192}193}194if (argv != NULL)195free(argv);196197while (script != NULL) {198se = script;199script = script->next;200free(se);201}202return(res);203}204205/*206* There's no graphics commands for the simple interpreter.207*/208void209gfx_interp_ref(void)210{211}212213214