#include <stand.h>
#include <string.h>
#include "bootstrap.h"
#include "dloader.h"
static void prompt(void);
static int iseol(char c);
static void skipeol(int fd);
int
perform(int argc, char *argv[])
{
int result;
struct bootblk_command **cmdp;
bootblk_cmd_t *cmd;
const char *av0;
if (argc < 1)
return(CMD_OK);
av0 = argv[0];
if (strchr(av0, '=') != NULL)
av0 = "local";
command_errmsg = command_errbuf;
strcpy(command_errbuf, "no error message");
cmd = NULL;
result = CMD_ERROR;
SET_FOREACH(cmdp, Xcommand_set) {
if (((*cmdp)->c_name != NULL) && !strcmp(av0, (*cmdp)->c_name)) {
cmd = (*cmdp)->c_fn;
break;
}
}
if (cmd != NULL) {
if ((*cmdp)->c_cond || CurrentCondition != 0)
result = (cmd)(argc, argv);
else
result = CMD_OK;
} else {
command_errmsg = "unknown command";
}
return(result);
}
void
interact(void)
{
char input[256];
int argc;
char **argv;
chdir("/boot");
setenv("base", DirBase, 1);
if (include("dloader.rc") != CMD_OK)
include("boot.conf");
chdir("/boot");
setenv("base", DirBase, 1);
printf("\n");
autoboot_maybe();
dloader_init_cmds();
printf("\nType '?' for a list of commands, 'help' for more detailed help.\n");
if (getenv("prompt") == NULL)
setenv("prompt", "OK", 1);
for (;;) {
input[0] = '\0';
prompt();
ngets(input, sizeof(input));
if (!parse(&argc, &argv, input)) {
if (perform(argc, argv))
printf("%s: %s\n", argv[0], command_errmsg);
free(argv);
} else {
printf("parse error\n");
}
}
}
COMMAND_SET(include, "include", "run commands from file", command_include);
static 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);
}
COMMAND_SET(optinclude, "optinclude",
"run commands from file; ignore exit status",
command_optinclude);
static int
command_optinclude(int argc, char *argv[])
{
int i;
char **argvbuf;
argvbuf = (char**) calloc((u_int)argc, sizeof(char*));
for (i = 0; i < argc; i++)
argvbuf[i] = strdup(argv[i]);
for (i = 1; (i < argc); i++)
include(argvbuf[i]);
for (i = 0; i < argc; i++)
free(argvbuf[i]);
free(argvbuf);
return(CMD_OK);
}
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[1024];
int argc,res;
char **argv, *cp;
int fd, flags, line;
if (((fd = rel_open(filename, NULL, O_RDONLY)) == -1)) {
command_errmsg = command_errbuf;
snprintf(command_errbuf, sizeof(command_errbuf),
"cannot find \"%s\"", filename);
return(CMD_ERROR);
}
script = se = NULL;
line = 0;
while (fgets(input, sizeof(input), fd) != NULL) {
line++;
flags = 0;
if(strlen(input) == sizeof(input) - 1 &&
!iseol(input[sizeof(input) - 2])) {
printf("WARNING: %s: %s: Line too long: truncating; have:\n",
__func__, filename);
printf("%s\n", input);
skipeol(fd);
}
if (strncmp(input+strspn(input, " "), "\\ ", 2) == 0)
continue;
cp = input;
if (input[0] == '@') {
cp++;
flags |= SL_QUIET;
}
if (input[0] == '-') {
cp++;
flags |= SL_IGNOREERR;
}
sp = malloc(sizeof(struct includeline) + strlen(cp) + 1);
sp->text = (char *)sp + sizeof(struct includeline);
strcpy(sp->text, cp);
sp->flags = flags;
sp->line = line;
sp->next = NULL;
if (script == NULL) {
script = sp;
} else {
se->next = sp;
}
se = sp;
}
close(fd);
argv = NULL;
res = CMD_OK;
for (sp = script; sp != NULL; sp = sp->next) {
#if 0
if (!(sp->flags & SL_QUIET)) {
prompt();
printf("%s\n", sp->text);
}
#endif
if (!parse(&argc, &argv, sp->text)) {
if ((argc > 0) && (perform(argc, argv) != 0)) {
printf("%s: %s\n", argv[0], command_errmsg);
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;
}
}
if (argv != NULL)
free(argv);
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);
}
static int
iseol(char c)
{
return(c == '\n' || c == '\r');
}
static void
skipeol(int fd)
{
char c;
while (read(fd, &c, 1) == 1) {
if (iseol(c))
break;
}
}