/* rl-timeout: test various readline builtin timeouts. */
/* Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of the GNU Readline Library (Readline), a library for
reading lines of text with interactive input and history editing.
Readline is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Readline is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with readline. If not, see .
*/
/* Standard include files. stdio.h is required. */
#include
#include
#include
#include
/* Used for select(2) */
#include
#include
#include
#include
/* Standard readline include files. */
#if defined (READLINE_LIBRARY)
# include "readline.h"
# include "history.h"
#else
# include
# include
#endif
extern int errno;
static void cb_linehandler (char *);
int timeout_secs = 1, timeout_usecs = 0;
int running;
const char *prompt = "rl-timeout$ ";
/* **************************************************************** */
/* */
/* Example 1: readline () with rl_readline_state */
/* */
/* **************************************************************** */
void
rltest_timeout_readline1 ()
{
const char *temp;
rl_set_timeout (timeout_secs, timeout_usecs);
temp = readline (prompt);
if (RL_ISSTATE (RL_STATE_TIMEOUT))
printf ("timeout\n");
else if (temp == NULL)
printf ("no input line\n");
else
printf ("input line: %s\n", temp);
free ((void *) temp);
}
/* **************************************************************** */
/* */
/* Example 2: readline () with rl_timeout_event_hook */
/* */
/* **************************************************************** */
static int
timeout_handler ()
{
printf ("timeout\n");
return READERR;
}
void
rltest_timeout_readline2 ()
{
const char *temp;
rl_set_timeout (timeout_secs, timeout_usecs);
rl_timeout_event_hook = timeout_handler;
temp = readline (prompt);
if (temp == NULL)
printf ("no input line\n");
else
printf ("input line: %s\n", temp);
free ((void *)temp);
}
/* **************************************************************** */
/* */
/* Example 3: rl_callback_* () with rl_timeout_remaining */
/* */
/* **************************************************************** */
/* Callback function called for each line when accept-line executed, EOF
seen, or EOF character read. This sets a flag and returns; it could
also call exit(3). */
static void
cb_linehandler (char *line)
{
/* Can use ^D (stty eof) or `exit' to exit. */
if (line == NULL || strcmp (line, "exit") == 0)
{
if (line == 0)
printf ("\n");
printf ("exit\n");
/* This function needs to be called to reset the terminal settings,
and calling it from the line handler keeps one extra prompt from
being displayed. */
rl_callback_handler_remove ();
running = 0;
}
else
{
if (*line)
add_history (line);
printf ("input line: %s\n", line);
free (line);
}
}
void
rltest_timeout_callback1 ()
{
fd_set fds;
int r;
unsigned sec, usec;
rl_set_timeout (timeout_secs, timeout_usecs);
rl_callback_handler_install (prompt, cb_linehandler);
running = 1;
while (running)
{
FD_ZERO (&fds);
FD_SET (fileno (rl_instream), &fds);
r = rl_timeout_remaining (&sec, &usec);
if (r == 1)
{
struct timeval timeout = {sec, usec};
r = select (FD_SETSIZE, &fds, NULL, NULL, &timeout);
}
if (r < 0 && errno != EINTR)
{
perror ("rl-timeout: select");
rl_callback_handler_remove ();
break;
}
else if (r == 0)
{
printf ("rl-timeout: timeout\n");
rl_callback_handler_remove ();
break;
}
if (FD_ISSET (fileno (rl_instream), &fds))
rl_callback_read_char ();
}
printf ("rl-timeout: Event loop has exited\n");
}
/* **************************************************************** */
/* */
/* Example 4: rl_callback_* () with rl_timeout_event_hook */
/* */
/* **************************************************************** */
static int
cb_timeouthandler ()
{
printf ("timeout\n");
rl_callback_handler_remove ();
running = 0;
return READERR;
}
void
rltest_timeout_callback2 ()
{
int r;
rl_set_timeout (timeout_secs, timeout_usecs);
rl_timeout_event_hook = cb_timeouthandler;
rl_callback_handler_install (prompt, cb_linehandler);
running = 1;
while (running)
rl_callback_read_char ();
printf ("rl-timeout: Event loop has exited\n");
}
int
main (int argc, char **argv)
{
if (argc >= 2)
{
if (argc >= 3)
{
double timeout = atof (argv[2]);
if (timeout <= 0.0)
{
fprintf (stderr, "rl-timeout: specify a positive number for timeout.\n");
return 2;
}
else if (timeout > UINT_MAX)
{
fprintf (stderr, "rl-timeout: timeout too large.\n");
return 2;
}
timeout_secs = (unsigned) timeout;
timeout_usecs = (unsigned) ((timeout - timeout_secs) * 1000000 + 0.5);
}
if (strcmp (argv[1], "readline1") == 0)
rltest_timeout_readline1 ();
else if (strcmp (argv[1], "readline2") == 0)
rltest_timeout_readline2 ();
else if (strcmp (argv[1], "callback1") == 0)
rltest_timeout_callback1 ();
else if (strcmp (argv[1], "callback2") == 0)
rltest_timeout_callback2 ();
else
return 2;
}
else
{
fprintf (stderr, "usage: rl-timeout [readline1 | readline2 | callback1 | callback2] [timeout]\n");
return 2;
}
return 0;
}