/* 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; }