#include <ctype.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include "menu.h"
#include "ui.h"
#include "util.h"
#define MAX_PASS 128
#define NO_OPT 0
static char pass[MAX_PASS];
static int getip(const State *state, int fd);
static pid_t run(const char *cmd);
static void updatestat(const State *state, unsigned typ, int pos);
int menuinit(const State *state, int fd)
{
int rc, wfd = -1, status = 0;
pid_t pid;
if (state->floc)
if ((wfd = open(state->floc, O_WRONLY | O_CREAT)) == -1)
die ("can't open %s", state->floc);
do {
if (WEXITSTATUS(status))
pui(state->headerr, state->statfail);
else
pui(state->cmds[PASS].name, state->statstr[0]);
rc = getip(state, fd);
if (wfd >= 0 && rc == PASS)
write(wfd, pass, strlen(pass));
pid = run(state->cmds[rc].cmd);
if (rc == PASS) {
pui(state->headverf, state->statverf);
waitpid(pid, &status, NO_OPT);
}
} while (WEXITSTATUS(status) || rc != PASS);
if (wfd >= 0)
close(wfd);
return rc;
}
static int getip(const State *state, int fd)
{
unsigned i;
int rc, floor, ceil;
rc = floor = ceil = PASS;
if (state->cmds[DOWN].name)
floor = DOWN;
if (state->cmds[UP].name)
ceil = UP;
for (i = 0; i + 1 < MAX_PASS; ) {
read(fd, pass + i, 1);
if (pass[i] == DEL) {
if (i > 0)
--i;
} else if (pass[i] == NL) {
break;
} else if (i >= 2 && pass[i-2] == ESC && pass[i-1] == '[' ) {
if (pass[i] == 'A' && rc < ceil)
++rc;
else if (pass[i] == 'B' && rc > floor)
--rc;
i -= 2;
} else {
++i;
}
pheader(state->cmds[rc].name);
updatestat(state, rc, i);
}
pass[i] = '\0';
return rc;
}
static void updatestat(const State *state, unsigned typ, int pos)
{
if (typ == PASS) {
if (pos)
genrandstat(state->cmds[PASS].name, state->statstr);
else
pstaticstat(state->cmds[PASS].name, state->statstr[0]);
} else {
pstaticstat(state->cmds[typ].name, state->statverf);
}
}
static pid_t run(const char *cmd)
{
pid_t pid;
if ((pid = fork()) == 0) {
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
execlp("sh", "sh", "-c", cmd, NULL);
die("run: fork(): %s", cmd);
}
return pid;
}