2013-12-04 21:33:17 +00:00
|
|
|
/*
|
|
|
|
* ntp_lineedit.c - generic interface to various line editing libs
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#if defined(HAVE_READLINE_HISTORY) && \
|
|
|
|
(!defined(HAVE_READLINE_HISTORY_H) || \
|
|
|
|
!defined(HAVE_READLINE_READLINE_H))
|
|
|
|
# undef HAVE_READLINE_HISTORY
|
|
|
|
#endif
|
|
|
|
#if defined(HAVE_READLINE_HISTORY)
|
|
|
|
# include <readline/readline.h>
|
|
|
|
# include <readline/history.h>
|
|
|
|
# define LE_READLINE
|
|
|
|
#elif defined(HAVE_HISTEDIT_H)
|
|
|
|
# include <histedit.h>
|
|
|
|
# define LE_EDITLINE
|
|
|
|
#else
|
|
|
|
# define LE_NONE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "ntp.h"
|
|
|
|
#include "ntp_stdlib.h"
|
|
|
|
#include "ntp_lineedit.h"
|
2016-01-08 08:06:14 +00:00
|
|
|
#include "safecast.h"
|
2013-12-04 21:33:17 +00:00
|
|
|
|
|
|
|
#define MAXEDITLINE 512
|
|
|
|
|
|
|
|
/*
|
|
|
|
* external references
|
|
|
|
*/
|
|
|
|
|
2015-10-21 19:16:13 +00:00
|
|
|
extern char const * progname;
|
2013-12-04 21:33:17 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* globals, private prototypes
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int ntp_readline_initted;
|
|
|
|
static char * lineedit_prompt;
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef LE_EDITLINE
|
|
|
|
# ifndef H_SETSIZE
|
|
|
|
# define H_SETSIZE H_EVENT
|
|
|
|
# endif
|
|
|
|
static EditLine * ntp_el;
|
|
|
|
static History * ntp_hist;
|
|
|
|
static HistEvent hev;
|
|
|
|
|
|
|
|
char * ntp_prompt_callback(EditLine *);
|
|
|
|
#endif /* LE_EDITLINE */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ntp_readline_init - setup, set or reset prompt string
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ntp_readline_init(
|
|
|
|
const char * prompt
|
|
|
|
)
|
|
|
|
{
|
|
|
|
int success;
|
|
|
|
|
|
|
|
success = 1;
|
|
|
|
|
|
|
|
if (prompt) {
|
|
|
|
if (lineedit_prompt)
|
|
|
|
free(lineedit_prompt);
|
|
|
|
lineedit_prompt = estrdup(prompt);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef LE_EDITLINE
|
|
|
|
if (NULL == ntp_el) {
|
|
|
|
|
|
|
|
# if 4 == EL_INIT_ARGS
|
|
|
|
ntp_el = el_init(progname, stdin, stdout, stderr);
|
|
|
|
# else
|
|
|
|
ntp_el = el_init(progname, stdin, stdout);
|
|
|
|
# endif
|
|
|
|
if (ntp_el) {
|
|
|
|
|
|
|
|
el_set(ntp_el, EL_PROMPT, ntp_prompt_callback);
|
|
|
|
el_set(ntp_el, EL_EDITOR, "emacs");
|
|
|
|
|
|
|
|
ntp_hist = history_init();
|
|
|
|
|
|
|
|
if (NULL == ntp_hist) {
|
|
|
|
|
2014-12-20 22:52:39 +00:00
|
|
|
mfprintf(stderr, "history_init(): %m\n");
|
2013-12-04 21:33:17 +00:00
|
|
|
fflush(stderr);
|
|
|
|
|
|
|
|
el_end(ntp_el);
|
|
|
|
ntp_el = NULL;
|
|
|
|
|
|
|
|
success = 0;
|
|
|
|
|
|
|
|
} else {
|
2014-12-20 22:52:39 +00:00
|
|
|
ZERO(hev);
|
2013-12-04 21:33:17 +00:00
|
|
|
#ifdef H_SETSIZE
|
|
|
|
history(ntp_hist, &hev, H_SETSIZE, 128);
|
|
|
|
#endif
|
|
|
|
el_set(ntp_el, EL_HIST, history,
|
|
|
|
ntp_hist);
|
|
|
|
/* use any .editrc */
|
|
|
|
el_source(ntp_el, NULL);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
success = 0;
|
|
|
|
}
|
|
|
|
#endif /* LE_EDITLINE */
|
|
|
|
|
|
|
|
ntp_readline_initted = success;
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ntp_readline_uninit - release resources
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ntp_readline_uninit(
|
|
|
|
void
|
|
|
|
)
|
|
|
|
{
|
|
|
|
#ifdef LE_EDITLINE
|
|
|
|
if (ntp_el) {
|
|
|
|
el_end(ntp_el);
|
|
|
|
ntp_el = NULL;
|
|
|
|
|
|
|
|
history_end(ntp_hist);
|
|
|
|
ntp_hist = NULL;
|
|
|
|
}
|
|
|
|
#endif /* LE_EDITLINE */
|
|
|
|
|
|
|
|
if (lineedit_prompt) {
|
|
|
|
free(lineedit_prompt);
|
|
|
|
lineedit_prompt = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ntp_readline_initted = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ntp_readline - read a line with the line editor available
|
|
|
|
*
|
|
|
|
* The string returned must be released with free()
|
|
|
|
*/
|
|
|
|
|
|
|
|
char *
|
|
|
|
ntp_readline(
|
|
|
|
int * pcount
|
|
|
|
)
|
|
|
|
{
|
|
|
|
char * line;
|
|
|
|
#ifdef LE_NONE
|
|
|
|
char line_buf[MAXEDITLINE];
|
|
|
|
#endif
|
|
|
|
#ifdef LE_EDITLINE
|
|
|
|
const char * cline;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!ntp_readline_initted)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*pcount = 0;
|
|
|
|
|
|
|
|
#ifdef LE_READLINE
|
|
|
|
line = readline(lineedit_prompt ? lineedit_prompt : "");
|
|
|
|
if (NULL != line) {
|
|
|
|
if (*line) {
|
|
|
|
add_history(line);
|
|
|
|
}
|
2015-02-05 20:53:33 +00:00
|
|
|
*pcount = strlen(line);
|
2013-12-04 21:33:17 +00:00
|
|
|
}
|
|
|
|
#endif /* LE_READLINE */
|
|
|
|
|
|
|
|
#ifdef LE_EDITLINE
|
|
|
|
cline = el_gets(ntp_el, pcount);
|
|
|
|
|
2015-02-05 20:53:33 +00:00
|
|
|
if (NULL != cline) {
|
2013-12-04 21:33:17 +00:00
|
|
|
history(ntp_hist, &hev, H_ENTER, cline);
|
|
|
|
line = estrdup(cline);
|
2015-02-05 20:53:33 +00:00
|
|
|
} else if (*pcount == -1) {
|
2013-12-04 21:33:17 +00:00
|
|
|
line = NULL;
|
2015-02-05 20:53:33 +00:00
|
|
|
} else {
|
|
|
|
line = estrdup("");
|
|
|
|
}
|
2013-12-04 21:33:17 +00:00
|
|
|
#endif /* LE_EDITLINE */
|
|
|
|
|
|
|
|
#ifdef LE_NONE
|
|
|
|
/* stone hammers */
|
|
|
|
if (lineedit_prompt) {
|
|
|
|
# ifdef VMS
|
|
|
|
/*
|
|
|
|
* work around problem mixing
|
|
|
|
* stdout & stderr
|
|
|
|
*/
|
|
|
|
fputs("", stdout);
|
|
|
|
# endif /* VMS */
|
|
|
|
|
|
|
|
fputs(lineedit_prompt, stderr);
|
|
|
|
fflush(stderr);
|
|
|
|
}
|
|
|
|
|
|
|
|
line = fgets(line_buf, sizeof(line_buf), stdin);
|
|
|
|
if (NULL != line && *line) {
|
2016-01-08 08:06:14 +00:00
|
|
|
*pcount = (int)strlen(line); /* cannot overflow here */
|
2013-12-04 21:33:17 +00:00
|
|
|
line = estrdup(line);
|
|
|
|
} else
|
|
|
|
line = NULL;
|
|
|
|
|
|
|
|
#endif /* LE_NONE */
|
|
|
|
|
|
|
|
|
|
|
|
if (!line) /* EOF */
|
|
|
|
fputs("\n", stderr);
|
|
|
|
|
|
|
|
return line;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef LE_EDITLINE
|
|
|
|
/*
|
|
|
|
* ntp_prompt_callback - return prompt string to el_gets()
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
ntp_prompt_callback(
|
|
|
|
EditLine *el
|
|
|
|
)
|
|
|
|
{
|
|
|
|
UNUSED_ARG(el);
|
|
|
|
|
|
|
|
return lineedit_prompt;
|
|
|
|
}
|
|
|
|
#endif /* LE_EDITLINE */
|
|
|
|
|