#include <sys/cdefs.h>
#include <lib/libsa/stand.h>
#include <lib/libsa/loadfile.h>
#include <lib/libkern/libkern.h>
#include "bootstrap.h"
#ifdef BOOT_FORTH
#include "ficl.h"
#define RETURN(x) stackPushINT(bf_vm->pStack,!x); return(x)
extern FICL_VM *bf_vm;
#else
#define RETURN(x) return(x)
#endif
#define MAXARGS 20
static void prompt(void);
#ifndef BOOT_FORTH
static int perform(int argc, char *argv[]);
int
perform(int argc, char *argv[])
{
int result;
struct bootblk_command *cmdp;
bootblk_cmd_t *cmd;
int i;
if (argc < 1)
return(CMD_OK);
command_seterr("no error message");
cmd = NULL;
result = CMD_ERROR;
for (i = 0, cmdp = commands; (cmdp->c_name != NULL) && (cmdp->c_desc != NULL ); i++, cmdp = commands + i) {
if ((cmdp->c_name != NULL) && !strcmp(argv[0], cmdp->c_name))
cmd = cmdp->c_fn;
}
if (cmd != NULL) {
result = (cmd)(argc, argv);
} else {
command_seterr("unknown command");
}
RETURN(result);
}
#endif
void
interact(void)
{
char input[256];
#ifndef BOOT_FORTH
int argc;
char **argv;
#endif
#ifdef BOOT_FORTH
bf_init();
#endif
if(include("/boot/loader.rc")!=CMD_OK)
include("/boot/boot.conf");
printf("\n");
printf("\nType '?' for a list of commands, 'help' for more detailed help.\n");
if (getenv("prompt") == NULL)
setenv("prompt", "${interpret}", 1);
if (getenv("interpret") == NULL)
setenv("interpret", "OK", 1);
for (;;) {
input[0] = '\0';
prompt();
ngets(input, sizeof(input));
#ifdef BOOT_FORTH
bf_vm->sourceID.i = 0;
bf_run(input);
#else
if (!parse(&argc, &argv, input)) {
if (perform(argc, argv))
printf("%s: %s\n", argv[0], command_geterr());
free(argv);
} else {
printf("parse error\n");
}
#endif
}
}
int
command_include(int argc, char *argv[])
{
int i;
int res;
char **argvbuf;
argvbuf = (char**) calloc((u_int)argc, sizeof(char*));
for (i = 0; i < argc; i++)
argvbuf[i] = strdup(argv[i]);
res=CMD_OK;
for (i = 1; (i < argc) && (res == CMD_OK); i++)
res = include(argvbuf[i]);
for (i = 0; i < argc; i++)
free(argvbuf[i]);
free(argvbuf);
return(res);
}
struct includeline
{
char *text;
int flags;
int line;
#define SL_QUIET (1<<0)
#define SL_IGNOREERR (1<<1)
struct includeline *next;
};
int
include(const char *filename)
{
struct includeline *script, *se, *sp;
char input[256];
#ifdef BOOT_FORTH
int res;
char *cp;
int prevsrcid, fd, line;
#else
int argc,res;
char **argv, *cp;
int fd, flags, line;
#endif
if (((fd = open(filename, O_RDONLY)) == -1)) {
command_seterr("can't open '%s': %s\n", filename, strerror(errno));
return(CMD_ERROR);
}
script = se = NULL;
line = 0;
while (fgetstr(input, sizeof(input), fd) >= 0) {
line++;
#ifdef BOOT_FORTH
cp = input;
#else
flags = 0;
if (strncmp(input+strspn(input, " "), "\\ ", 2) == 0)
continue;
cp = input;
if (input[0] == '@') {
cp++;
flags |= SL_QUIET;
}
if (input[0] == '-') {
cp++;
flags |= SL_IGNOREERR;
}
#endif
sp = alloc(sizeof(struct includeline) + strlen(cp) + 1);
sp->text = (char *)sp + sizeof(struct includeline);
strcpy(sp->text, cp);
#ifndef BOOT_FORTH
sp->flags = flags;
#endif
sp->line = line;
sp->next = NULL;
if (script == NULL) {
script = sp;
} else {
se->next = sp;
}
se = sp;
}
close(fd);
#ifndef BOOT_FORTH
argv = NULL;
#else
prevsrcid = bf_vm->sourceID.i;
bf_vm->sourceID.i = fd;
#endif
res = CMD_OK;
for (sp = script; sp != NULL; sp = sp->next) {
#ifdef BOOT_FORTH
res = bf_run(sp->text);
if (res != VM_OUTOFTEXT) {
command_seterr("Error while including %s, in the line:\n%s",
filename, sp->text);
res = CMD_ERROR;
break;
} else
res = CMD_OK;
#else
if (!(sp->flags & SL_QUIET)) {
prompt();
printf("%s\n", sp->text);
}
if (!parse(&argc, &argv, sp->text)) {
if ((argc > 0) && (perform(argc, argv) != 0)) {
printf("%s: %s\n", argv[0], command_geterr());
if (!(sp->flags & SL_IGNOREERR)) {
res=CMD_ERROR;
break;
}
}
free(argv);
argv = NULL;
} else {
printf("%s line %d: parse error\n", filename, sp->line);
res=CMD_ERROR;
break;
}
#endif
}
#ifndef BOOT_FORTH
if (argv != NULL)
free(argv);
#else
bf_vm->sourceID.i = prevsrcid;
#endif
while(script != NULL) {
se = script;
script = script->next;
free(se);
}
return(res);
}
static void
prompt(void)
{
char *pr, *p, *cp, *ev;
if ((cp = getenv("prompt")) == NULL)
cp = ">";
pr = p = strdup(cp);
while (*p != 0) {
if ((*p == '$') && (*(p+1) == '{')) {
for (cp = p + 2; (*cp != 0) && (*cp != '}'); cp++)
;
*cp = 0;
ev = getenv(p + 2);
if (ev != NULL)
printf("%s", ev);
p = cp + 1;
continue;
}
putchar(*p++);
}
putchar(' ');
free(pr);
}