#include <lib/libsa/stand.h>
#include <lib/libkern/libkern.h>
#include <sys/param.h>
#include <machine/bfs.h>
#include "cmd.h"
#include "local.h"
#define LOG_SIZE 2048
#define LOG_MASK (LOG_SIZE - 1)
uint8_t __log[LOG_SIZE];
int __log_cnt;
#define CMDBUF_HISTORY_MAX 8
#define PROMPT ">> "
struct cmd_buf {
char buf[CMDBUF_SIZE];
int cur, min, max;
} __cmd_buf[CMDBUF_HISTORY_MAX];
struct cmd_buf *__cmd;
int __cur_cmd;
void prompt_reset(void);
void prompt_input(int);
extern void __putchar(int);
void
prompt(void)
{
int c;
prompt_reset();
while (1)
if ((c = getchar()) != 0)
prompt_input(c);
}
void
prompt_input(int c)
{
int i;
switch (c) {
case 32 ... 127:
__cmd->buf[__cmd->cur] = c;
__cmd->cur = (__cmd->cur >= CMDBUF_SIZE - 1) ? __cmd->cur :
__cmd->cur + 1;
if (__cmd->cur >= __cmd->max)
__cmd->max = __cmd->cur;
putchar(c);
break;
case '\r':
putchar('\n');
if (__cmd->max > 0) {
cmd_exec(__cmd->buf);
prompt_reset();
} else {
printf(PROMPT);
}
break;
case '\b':
if (__cmd->cur > 0) {
__cmd->buf[--__cmd->cur] = 0;
putchar(c);
}
break;
case 1:
__cmd->cur = __cmd->min;
putchar('\r');
printf("%s", PROMPT);
break;
case 5:
__cmd->cur = __cmd->max;
goto redraw;
case 2:
if (__cmd->cur == __cmd->min)
return;
__cmd->cur--;
putchar(c);
break;
case 6:
if (__cmd->cur == __cmd->max)
return;
__cmd->cur++;
putchar(c);
break;
case 4:
if (__cmd->cur == __cmd->max)
return;
for (i = __cmd->cur; i < __cmd->max; i++)
__cmd->buf[i] = __cmd->buf[i + 1];
__cmd->buf[i] = '\0';
__cmd->max--;
goto redraw;
case 11:
for (i = __cmd->cur; i < __cmd->max; i++) {
__cmd->buf[i] = 0;
__cmd->max = __cmd->cur;
}
putchar(c);
break;
case 14:
__cur_cmd = (__cur_cmd + 1) & 0x7;
goto history_redraw;
case 16:
__cur_cmd = (__cur_cmd - 1) & 0x7;
history_redraw:
__cmd = &__cmd_buf[__cur_cmd];
__cmd->cur = __cmd->max;
case 12:
redraw:
putchar('\r');
putchar(11);
printf("%s%s", PROMPT, __cmd->buf);
break;
}
}
void
prompt_reset(void)
{
__cur_cmd = (__cur_cmd + 1) & 0x7;
__cmd = &__cmd_buf[__cur_cmd];
memset(__cmd, 0, sizeof *__cmd);
printf(PROMPT);
}
bool
prompt_yesno(int interactive)
{
int i;
if (!interactive)
return true;
while (1) {
if ((i = getchar()) == 0)
continue;
if (i == 'N' || i == 'n')
return false;
if (i == 'Y' || i == 'y')
return true;
}
}
void
putchar(int c)
{
__putchar(c);
__log[__log_cnt++] = c;
__log_cnt &= LOG_MASK;
}
int
cmd_log_save(int argc, char *argp[], int interactive)
{
struct bfs *bfs;
if (bfs_init(&bfs) != 0) {
printf("no BFS partition.\n");
return 1;
}
if (bfs_file_write(bfs, "boot.log", __log, LOG_SIZE) != 0)
printf("BFS write failed.\n");
bfs_fini(bfs);
return 0;
}