+
+#if HAVE_READLINE
+
+static int pfd[2];
+static bool sigint_received ;
+
+/*
+ A function similar to getc from stdio.
+ However this one may be interrupted by SIGINT.
+ If that happens it will return EOF and the global variable
+ sigint_received will be set to true.
+ */
+static int
+interruptible_getc (FILE *fp)
+{
+ int c = 0;
+ int ret = -1;
+ do
+ {
+ struct timeval timeout = {0, 50000};
+ fd_set what;
+ int max_fd = 0;
+ int fd ;
+ FD_ZERO (&what);
+ fd = fileno (fp);
+ max_fd = (max_fd > fd) ? max_fd : fd;
+ FD_SET (fd, &what);
+ fd = pfd[0];
+ max_fd = (max_fd > fd) ? max_fd : fd;
+ FD_SET (fd, &what);
+ ret = select (max_fd + 1, &what, NULL, NULL, &timeout);
+ if (ret == -1 && errno != EINTR)
+ {
+ perror ("Select failed");
+ continue;
+ }
+
+ if (ret > 0)
+ {
+ if (FD_ISSET (pfd[0], &what))
+ {
+ char dummy[1];
+ read (pfd[0], dummy, 1);
+ sigint_received = true;
+ return EOF;
+ }
+ }
+ }
+ while (ret <= 0);
+
+ /* This will not block! */
+ read (fileno (fp), &c, 1);
+
+ return c;
+}
+
+static void
+handler (int sig)
+{
+ rl_end = 0;
+
+ write (pfd[1], "x", 1);
+ rl_echo_signal_char (sig);
+}
+
+
+static void
+readline_init (void)
+{
+ if (0 != pipe2 (pfd, O_NONBLOCK))
+ perror ("Cannot create pipe");
+
+ if (SIG_ERR == signal (SIGINT, handler))
+ perror ("Cannot add signal handler");
+
+ rl_catch_signals = 0;
+ rl_getc_function = interruptible_getc;
+ rl_basic_word_break_characters = "\n";
+ using_history ();
+ stifle_history (500);
+ if (history_file == NULL)
+ {
+ const char *home_dir = getenv ("HOME");
+ if (home_dir != NULL)
+ {
+ history_file = xasprintf ("%s/.pspp_history", home_dir);
+ read_history (history_file);
+ }
+ }
+}
+
+static void
+readline_done (void)
+{
+ if (history_file != NULL && false == settings_get_testing_mode ())
+ write_history (history_file);
+ clear_history ();
+ free (history_file);
+}
+
+/* Prompt the user for a line of input and return it in LINE.
+ Returns true if the LINE should be considered valid, false otherwise.
+ */
+static bool
+readline_read (struct substring *line, enum prompt_style style)