xref: /freebsd/stand/common/interp_simple.c (revision 68344c9c)
179a6a17aSWarner Losh /*-
279a6a17aSWarner Losh  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
379a6a17aSWarner Losh  * All rights reserved.
479a6a17aSWarner Losh  *
579a6a17aSWarner Losh  * Redistribution and use in source and binary forms, with or without
679a6a17aSWarner Losh  * modification, are permitted provided that the following conditions
779a6a17aSWarner Losh  * are met:
879a6a17aSWarner Losh  * 1. Redistributions of source code must retain the above copyright
979a6a17aSWarner Losh  *    notice, this list of conditions and the following disclaimer.
1079a6a17aSWarner Losh  * 2. Redistributions in binary form must reproduce the above copyright
1179a6a17aSWarner Losh  *    notice, this list of conditions and the following disclaimer in the
1279a6a17aSWarner Losh  *    documentation and/or other materials provided with the distribution.
1379a6a17aSWarner Losh  *
1479a6a17aSWarner Losh  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1579a6a17aSWarner Losh  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1679a6a17aSWarner Losh  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1779a6a17aSWarner Losh  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1879a6a17aSWarner Losh  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1979a6a17aSWarner Losh  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2079a6a17aSWarner Losh  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2179a6a17aSWarner Losh  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2279a6a17aSWarner Losh  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2379a6a17aSWarner Losh  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2479a6a17aSWarner Losh  * SUCH DAMAGE.
2579a6a17aSWarner Losh  */
2679a6a17aSWarner Losh 
2779a6a17aSWarner Losh /*
2879a6a17aSWarner Losh  * Simple commandline interpreter, toplevel and misc.
2979a6a17aSWarner Losh  */
3079a6a17aSWarner Losh 
3179a6a17aSWarner Losh #include <stand.h>
3279a6a17aSWarner Losh #include <string.h>
3379a6a17aSWarner Losh #include "bootstrap.h"
3479a6a17aSWarner Losh 
35d3d381b2SKyle Evans INTERP_DEFINE("simp");
36d3d381b2SKyle Evans 
3779a6a17aSWarner Losh void
interp_preinit(void)38*68344c9cSWarner Losh interp_preinit(void)
39*68344c9cSWarner Losh {
40*68344c9cSWarner Losh }
41*68344c9cSWarner Losh 
42*68344c9cSWarner Losh void
interp_init(void)4379a6a17aSWarner Losh interp_init(void)
4479a6a17aSWarner Losh {
4579a6a17aSWarner Losh 
4686411ec1SWarner Losh 	setenv("script.lang", "simple", 1);
4779a6a17aSWarner Losh 	/* Read our default configuration. */
4879a6a17aSWarner Losh 	interp_include("/boot/loader.rc");
4979a6a17aSWarner Losh }
5079a6a17aSWarner Losh 
5179a6a17aSWarner Losh int
interp_run(const char * input)5279a6a17aSWarner Losh interp_run(const char *input)
5379a6a17aSWarner Losh {
5479a6a17aSWarner Losh 	int			argc;
5579a6a17aSWarner Losh 	char			**argv;
5679a6a17aSWarner Losh 
5779a6a17aSWarner Losh 	if (parse(&argc, &argv, input)) {
5879a6a17aSWarner Losh 		printf("parse error\n");
5979a6a17aSWarner Losh 		return CMD_ERROR;
6079a6a17aSWarner Losh 	}
6179a6a17aSWarner Losh 
623a4a3639SWarner Losh 	if (interp_builtin_cmd(argc, argv)) {
6379a6a17aSWarner Losh 		printf("%s: %s\n", argv[0], command_errmsg);
6479a6a17aSWarner Losh 		free(argv);
6579a6a17aSWarner Losh 		return CMD_ERROR;
6679a6a17aSWarner Losh 	}
6779a6a17aSWarner Losh 	free(argv);
6879a6a17aSWarner Losh 	return CMD_OK;
6979a6a17aSWarner Losh }
7079a6a17aSWarner Losh 
7179a6a17aSWarner Losh /*
7279a6a17aSWarner Losh  * Header prepended to each line. The text immediately follows the header.
7379a6a17aSWarner Losh  * We try to make this short in order to save memory -- the loader has
7479a6a17aSWarner Losh  * limited memory available, and some of the forth files are very long.
7579a6a17aSWarner Losh  */
7679a6a17aSWarner Losh struct includeline
7779a6a17aSWarner Losh {
7879a6a17aSWarner Losh 	struct includeline	*next;
7979a6a17aSWarner Losh 	int			flags;
8079a6a17aSWarner Losh 	int			line;
8179a6a17aSWarner Losh #define SL_QUIET	(1<<0)
8279a6a17aSWarner Losh #define SL_IGNOREERR	(1<<1)
8379a6a17aSWarner Losh 	char			text[0];
8479a6a17aSWarner Losh };
8579a6a17aSWarner Losh 
8679a6a17aSWarner Losh int
interp_include(const char * filename)8779a6a17aSWarner Losh interp_include(const char *filename)
8879a6a17aSWarner Losh {
8979a6a17aSWarner Losh 	struct includeline	*script, *se, *sp;
9079a6a17aSWarner Losh 	char			input[256];			/* big enough? */
9179a6a17aSWarner Losh 	int			argc,res;
9279a6a17aSWarner Losh 	char			**argv, *cp;
9379a6a17aSWarner Losh 	int			fd, flags, line;
9479a6a17aSWarner Losh 
9579a6a17aSWarner Losh 	if (((fd = open(filename, O_RDONLY)) == -1)) {
9679a6a17aSWarner Losh 		snprintf(command_errbuf, sizeof(command_errbuf),
9779a6a17aSWarner Losh 		    "can't open '%s': %s", filename, strerror(errno));
9879a6a17aSWarner Losh 		return(CMD_ERROR);
9979a6a17aSWarner Losh 	}
10079a6a17aSWarner Losh 
1018df8b2d3SSimon J. Gerraty #ifdef LOADER_VERIEXEC
102afc571b1SSimon J. Gerraty 	if (verify_file(fd, filename, 0, VE_GUESS, __func__) < 0) {
1038df8b2d3SSimon J. Gerraty 		close(fd);
1048df8b2d3SSimon J. Gerraty 		sprintf(command_errbuf,"can't verify '%s'", filename);
1058df8b2d3SSimon J. Gerraty 		return(CMD_ERROR);
1068df8b2d3SSimon J. Gerraty 	}
1078df8b2d3SSimon J. Gerraty #endif
1088df8b2d3SSimon J. Gerraty 
10979a6a17aSWarner Losh 	/*
11079a6a17aSWarner Losh 	 * Read the script into memory.
11179a6a17aSWarner Losh 	 */
11279a6a17aSWarner Losh 	script = se = NULL;
11379a6a17aSWarner Losh 	line = 0;
11479a6a17aSWarner Losh 
11579a6a17aSWarner Losh 	while (fgetstr(input, sizeof(input), fd) >= 0) {
11679a6a17aSWarner Losh 		line++;
11779a6a17aSWarner Losh 		flags = 0;
11879a6a17aSWarner Losh 		/* Discard comments */
119ea13a931SRebecca Cran 		if (strncmp(input+strspn(input, " "), "\\", 1) == 0)
12079a6a17aSWarner Losh 			continue;
12179a6a17aSWarner Losh 		cp = input;
12279a6a17aSWarner Losh 		/* Echo? */
12379a6a17aSWarner Losh 		if (input[0] == '@') {
12479a6a17aSWarner Losh 			cp++;
12579a6a17aSWarner Losh 			flags |= SL_QUIET;
12679a6a17aSWarner Losh 		}
12779a6a17aSWarner Losh 		/* Error OK? */
12879a6a17aSWarner Losh 		if (input[0] == '-') {
12979a6a17aSWarner Losh 			cp++;
13079a6a17aSWarner Losh 			flags |= SL_IGNOREERR;
13179a6a17aSWarner Losh 		}
13279a6a17aSWarner Losh 
13379a6a17aSWarner Losh 		/* Allocate script line structure and copy line, flags */
13479a6a17aSWarner Losh 		if (*cp == '\0')
13579a6a17aSWarner Losh 			continue;	/* ignore empty line, save memory */
13679a6a17aSWarner Losh 		sp = malloc(sizeof(struct includeline) + strlen(cp) + 1);
13779a6a17aSWarner Losh 		/* On malloc failure (it happens!), free as much as possible and exit */
13879a6a17aSWarner Losh 		if (sp == NULL) {
13979a6a17aSWarner Losh 			while (script != NULL) {
14079a6a17aSWarner Losh 				se = script;
14179a6a17aSWarner Losh 				script = script->next;
14279a6a17aSWarner Losh 				free(se);
14379a6a17aSWarner Losh 			}
14479a6a17aSWarner Losh 			snprintf(command_errbuf, sizeof(command_errbuf),
14579a6a17aSWarner Losh 			    "file '%s' line %d: memory allocation failure - aborting",
14679a6a17aSWarner Losh 			    filename, line);
14779a6a17aSWarner Losh 			close(fd);
14879a6a17aSWarner Losh 			return (CMD_ERROR);
14979a6a17aSWarner Losh 		}
15079a6a17aSWarner Losh 		strcpy(sp->text, cp);
15179a6a17aSWarner Losh 		sp->flags = flags;
15279a6a17aSWarner Losh 		sp->line = line;
15379a6a17aSWarner Losh 		sp->next = NULL;
15479a6a17aSWarner Losh 
15579a6a17aSWarner Losh 		if (script == NULL) {
15679a6a17aSWarner Losh 			script = sp;
15779a6a17aSWarner Losh 		} else {
15879a6a17aSWarner Losh 			se->next = sp;
15979a6a17aSWarner Losh 		}
16079a6a17aSWarner Losh 		se = sp;
16179a6a17aSWarner Losh 	}
16279a6a17aSWarner Losh 	close(fd);
16379a6a17aSWarner Losh 
16479a6a17aSWarner Losh 	/*
16579a6a17aSWarner Losh 	 * Execute the script
16679a6a17aSWarner Losh 	 */
16779a6a17aSWarner Losh 	argv = NULL;
16879a6a17aSWarner Losh 	res = CMD_OK;
16979a6a17aSWarner Losh 	for (sp = script; sp != NULL; sp = sp->next) {
17079a6a17aSWarner Losh 
17179a6a17aSWarner Losh 		/* print if not being quiet */
17279a6a17aSWarner Losh 		if (!(sp->flags & SL_QUIET)) {
17379a6a17aSWarner Losh 			interp_emit_prompt();
17479a6a17aSWarner Losh 			printf("%s\n", sp->text);
17579a6a17aSWarner Losh 		}
17679a6a17aSWarner Losh 
17779a6a17aSWarner Losh 		/* Parse the command */
17879a6a17aSWarner Losh 		if (!parse(&argc, &argv, sp->text)) {
1793a4a3639SWarner Losh 			if ((argc > 0) && (interp_builtin_cmd(argc, argv) != 0)) {
18079a6a17aSWarner Losh 				/* normal command */
18179a6a17aSWarner Losh 				printf("%s: %s\n", argv[0], command_errmsg);
18279a6a17aSWarner Losh 				if (!(sp->flags & SL_IGNOREERR)) {
18379a6a17aSWarner Losh 					res=CMD_ERROR;
18479a6a17aSWarner Losh 					break;
18579a6a17aSWarner Losh 				}
18679a6a17aSWarner Losh 			}
18779a6a17aSWarner Losh 			free(argv);
18879a6a17aSWarner Losh 			argv = NULL;
18979a6a17aSWarner Losh 		} else {
19079a6a17aSWarner Losh 			printf("%s line %d: parse error\n", filename, sp->line);
19179a6a17aSWarner Losh 			res=CMD_ERROR;
19279a6a17aSWarner Losh 			break;
19379a6a17aSWarner Losh 		}
19479a6a17aSWarner Losh 	}
19579a6a17aSWarner Losh 	if (argv != NULL)
19679a6a17aSWarner Losh 		free(argv);
19779a6a17aSWarner Losh 
19879a6a17aSWarner Losh 	while (script != NULL) {
19979a6a17aSWarner Losh 		se = script;
20079a6a17aSWarner Losh 		script = script->next;
20179a6a17aSWarner Losh 		free(se);
20279a6a17aSWarner Losh 	}
20379a6a17aSWarner Losh 	return(res);
20479a6a17aSWarner Losh }
20560e199d9SWarner Losh 
20660e199d9SWarner Losh /*
20760e199d9SWarner Losh  * There's no graphics commands for the simple interpreter.
20860e199d9SWarner Losh  */
20960e199d9SWarner Losh void
gfx_interp_ref(void)2106faf55c8SWarner Losh gfx_interp_ref(void)
21160e199d9SWarner Losh {
21260e199d9SWarner Losh }
213