lnav/test/rltest.cc

217 lines
6.0 KiB
C++

/**
* Copyright (c) 2007-2012, Timothy Stack
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Timothy Stack nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <errno.h>
#include <fcntl.h>
#include <readline/readline.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#include <util.h>
#include "vt52_curses.hh"
static const int KEY_TIMEOUT = 500 * 1000;
static int got_line = 0;
static int got_timeout = 0;
static void
sigalrm(int sig)
{
got_timeout = 1;
}
static void
line_ready(char* line)
{
fprintf(stderr, "got line: %s\n", line);
add_history(line);
got_line = 1;
}
static void
child_readline(void)
{
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
rl_callback_handler_install("/", (void (*)()) line_ready);
while (1) {
fd_set ready_rfds = rfds;
int rc;
rc = select(STDIN_FILENO + 1, &ready_rfds, NULL, NULL, NULL);
if (rc < 0) {
switch (errno) {
case EINTR:
break;
}
} else {
if (FD_ISSET(STDIN_FILENO, &ready_rfds)) {
struct itimerval itv;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = KEY_TIMEOUT;
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &itv, NULL);
rl_callback_read_char();
}
}
if (got_timeout) {
fprintf(stderr, "got timeout\n");
got_timeout = 0;
}
if (got_line) {
rl_callback_handler_remove();
got_line = 0;
rl_callback_handler_install("/", (void (*)()) line_ready);
}
}
}
static void
finish(int sig)
{
endwin();
exit(0);
}
int
main(int argc, char* argv[])
{
int fd, retval = EXIT_SUCCESS;
signal(SIGALRM, sigalrm);
fd = open("/tmp/rltest.err", O_WRONLY | O_CREAT | O_APPEND, 0666);
dup2(fd, STDERR_FILENO);
fprintf(stderr, "startup\n");
if (0) {
while (1) {
char* ret = readline("/");
add_history(ret);
}
}
(void) signal(SIGINT, finish); /* arrange interrupts to terminate */
WINDOW* mainwin = initscr(); /* initialize the curses library */
keypad(stdscr, TRUE); /* enable keyboard mapping */
(void) nonl(); /* tell curses not to do NL->CR/NL on output */
(void) cbreak(); /* take input chars one at a time, no wait for \n */
(void) noecho(); /* don't echo input */
if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) < 0)
perror("fcntl");
{
int master, slave;
pid_t rl;
if (openpty(&master, &slave, NULL, NULL, NULL) < 0) {
perror("openpty");
} else if ((rl = fork()) < 0) {
perror("fork");
} else if (rl == 0) {
close(master);
master = -1;
dup2(slave, STDIN_FILENO);
dup2(slave, STDOUT_FILENO);
setenv("TERM", "vt52", 1);
child_readline();
} else {
vt52_curses vc(mainwin);
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
FD_SET(master, &rfds);
while (1) {
fd_set ready_rfds = rfds;
int rc;
rc = select(master + 1, &ready_rfds, NULL, NULL, NULL);
if (rc < 0) {
break;
} else {
char buffer[1024];
if (FD_ISSET(STDIN_FILENO, &ready_rfds)) {
int ch;
if ((ch = getch()) != ERR) {
const char* bch;
int len;
bch = vc.map_input(ch, len);
if (len > 0) {
fprintf(stderr, "stdin: %x\n", ch);
if (write(master, bch, len) < 0)
perror("write");
}
}
}
if (FD_ISSET(master, &ready_rfds)) {
int lpc;
rc = read(master, buffer, sizeof(buffer));
fprintf(stderr, "child: ");
for (lpc = 0; lpc < rc; lpc++) {
fprintf(stderr, "%x ", buffer[lpc]);
}
fprintf(stderr, "\n");
vc.map_output(buffer, rc);
}
}
refresh();
}
}
}
finish(0);
return retval;
}