ntp_lineedit.c revision 258945
1258945Sroberto/*
2258945Sroberto * ntp_lineedit.c - generic interface to various line editing libs
3258945Sroberto */
4258945Sroberto#ifdef HAVE_CONFIG_H
5258945Sroberto# include <config.h>
6258945Sroberto#endif
7258945Sroberto
8258945Sroberto#include <errno.h>
9258945Sroberto#include <string.h>
10258945Sroberto#include <stdlib.h>
11258945Sroberto#include <stdio.h>
12258945Sroberto
13258945Sroberto#if defined(HAVE_READLINE_HISTORY) &&		\
14258945Sroberto    (!defined(HAVE_READLINE_HISTORY_H) ||	\
15258945Sroberto     !defined(HAVE_READLINE_READLINE_H))
16258945Sroberto# undef HAVE_READLINE_HISTORY
17258945Sroberto#endif
18258945Sroberto#if defined(HAVE_READLINE_HISTORY)
19258945Sroberto# include <readline/readline.h>
20258945Sroberto# include <readline/history.h>
21258945Sroberto# define LE_READLINE
22258945Sroberto#elif defined(HAVE_HISTEDIT_H)
23258945Sroberto# include <histedit.h>
24258945Sroberto# define LE_EDITLINE
25258945Sroberto#else
26258945Sroberto# define LE_NONE
27258945Sroberto#endif
28258945Sroberto
29258945Sroberto#include "ntp.h"
30258945Sroberto#include "ntp_stdlib.h"
31258945Sroberto#include "ntp_lineedit.h"
32258945Sroberto
33258945Sroberto#define MAXEDITLINE	512
34258945Sroberto
35258945Sroberto/*
36258945Sroberto * external references
37258945Sroberto */
38258945Sroberto
39258945Srobertoextern char *	progname;
40258945Sroberto
41258945Sroberto/*
42258945Sroberto * globals, private prototypes
43258945Sroberto */
44258945Sroberto
45258945Srobertostatic int	ntp_readline_initted;
46258945Srobertostatic char *	lineedit_prompt;
47258945Sroberto
48258945Sroberto
49258945Sroberto#ifdef LE_EDITLINE
50258945Sroberto# ifndef H_SETSIZE
51258945Sroberto#  define H_SETSIZE H_EVENT
52258945Sroberto# endif
53258945Srobertostatic EditLine *	ntp_el;
54258945Srobertostatic History *	ntp_hist;
55258945Srobertostatic HistEvent	hev;
56258945Sroberto
57258945Srobertochar *	ntp_prompt_callback(EditLine *);
58258945Sroberto#endif	/* LE_EDITLINE */
59258945Sroberto
60258945Sroberto
61258945Sroberto/*
62258945Sroberto * ntp_readline_init - setup, set or reset prompt string
63258945Sroberto */
64258945Srobertoint
65258945Srobertontp_readline_init(
66258945Sroberto	const char *	prompt
67258945Sroberto	)
68258945Sroberto{
69258945Sroberto	int	success;
70258945Sroberto
71258945Sroberto	success = 1;
72258945Sroberto
73258945Sroberto	if (prompt) {
74258945Sroberto		if (lineedit_prompt)
75258945Sroberto			free(lineedit_prompt);
76258945Sroberto		lineedit_prompt = estrdup(prompt);
77258945Sroberto	}
78258945Sroberto
79258945Sroberto#ifdef LE_EDITLINE
80258945Sroberto	if (NULL == ntp_el) {
81258945Sroberto
82258945Sroberto# if 4 == EL_INIT_ARGS
83258945Sroberto		ntp_el = el_init(progname, stdin, stdout, stderr);
84258945Sroberto# else
85258945Sroberto		ntp_el = el_init(progname, stdin, stdout);
86258945Sroberto# endif
87258945Sroberto		if (ntp_el) {
88258945Sroberto
89258945Sroberto			el_set(ntp_el, EL_PROMPT, ntp_prompt_callback);
90258945Sroberto			el_set(ntp_el, EL_EDITOR, "emacs");
91258945Sroberto
92258945Sroberto			ntp_hist = history_init();
93258945Sroberto
94258945Sroberto			if (NULL == ntp_hist) {
95258945Sroberto
96258945Sroberto				fprintf(stderr, "history_init(): %s\n",
97258945Sroberto						strerror(errno));
98258945Sroberto				fflush(stderr);
99258945Sroberto
100258945Sroberto				el_end(ntp_el);
101258945Sroberto				ntp_el = NULL;
102258945Sroberto
103258945Sroberto				success = 0;
104258945Sroberto
105258945Sroberto			} else {
106258945Sroberto				memset(&hev, 0, sizeof(hev));
107258945Sroberto#ifdef H_SETSIZE
108258945Sroberto				history(ntp_hist, &hev, H_SETSIZE, 128);
109258945Sroberto#endif
110258945Sroberto				el_set(ntp_el, EL_HIST, history,
111258945Sroberto				       ntp_hist);
112258945Sroberto				/* use any .editrc */
113258945Sroberto				el_source(ntp_el, NULL);
114258945Sroberto			}
115258945Sroberto		} else
116258945Sroberto			success = 0;
117258945Sroberto	}
118258945Sroberto#endif	/* LE_EDITLINE */
119258945Sroberto
120258945Sroberto	ntp_readline_initted = success;
121258945Sroberto
122258945Sroberto	return success;
123258945Sroberto}
124258945Sroberto
125258945Sroberto
126258945Sroberto/*
127258945Sroberto * ntp_readline_uninit - release resources
128258945Sroberto */
129258945Srobertovoid
130258945Srobertontp_readline_uninit(
131258945Sroberto	void
132258945Sroberto	)
133258945Sroberto{
134258945Sroberto#ifdef LE_EDITLINE
135258945Sroberto	if (ntp_el) {
136258945Sroberto		el_end(ntp_el);
137258945Sroberto		ntp_el = NULL;
138258945Sroberto
139258945Sroberto		history_end(ntp_hist);
140258945Sroberto		ntp_hist = NULL;
141258945Sroberto	}
142258945Sroberto#endif	/* LE_EDITLINE */
143258945Sroberto
144258945Sroberto	if (lineedit_prompt) {
145258945Sroberto		free(lineedit_prompt);
146258945Sroberto		lineedit_prompt = NULL;
147258945Sroberto	}
148258945Sroberto
149258945Sroberto	ntp_readline_initted = 0;
150258945Sroberto}
151258945Sroberto
152258945Sroberto
153258945Sroberto/*
154258945Sroberto * ntp_readline - read a line with the line editor available
155258945Sroberto *
156258945Sroberto * The string returned must be released with free()
157258945Sroberto */
158258945Sroberto
159258945Srobertochar *
160258945Srobertontp_readline(
161258945Sroberto	int *	pcount
162258945Sroberto	)
163258945Sroberto{
164258945Sroberto	char *		line;
165258945Sroberto#ifdef LE_NONE
166258945Sroberto	char		line_buf[MAXEDITLINE];
167258945Sroberto#endif
168258945Sroberto#ifdef LE_EDITLINE
169258945Sroberto	const char *	cline;
170258945Sroberto#endif
171258945Sroberto
172258945Sroberto	if (!ntp_readline_initted)
173258945Sroberto		return NULL;
174258945Sroberto
175258945Sroberto	*pcount = 0;
176258945Sroberto
177258945Sroberto#ifdef LE_READLINE
178258945Sroberto	line = readline(lineedit_prompt ? lineedit_prompt : "");
179258945Sroberto	if (NULL != line) {
180258945Sroberto		if (*line) {
181258945Sroberto			add_history(line);
182258945Sroberto			*pcount = strlen(line);
183258945Sroberto		} else {
184258945Sroberto			free(line);
185258945Sroberto			line = NULL;
186258945Sroberto		}
187258945Sroberto	}
188258945Sroberto#endif	/* LE_READLINE */
189258945Sroberto
190258945Sroberto#ifdef LE_EDITLINE
191258945Sroberto	cline = el_gets(ntp_el, pcount);
192258945Sroberto
193258945Sroberto	if (NULL != cline && *cline) {
194258945Sroberto		history(ntp_hist, &hev, H_ENTER, cline);
195258945Sroberto		*pcount = strlen(cline);
196258945Sroberto		line = estrdup(cline);
197258945Sroberto	} else
198258945Sroberto		line = NULL;
199258945Sroberto#endif	/* LE_EDITLINE */
200258945Sroberto
201258945Sroberto#ifdef LE_NONE
202258945Sroberto					/* stone hammers */
203258945Sroberto	if (lineedit_prompt) {
204258945Sroberto# ifdef VMS
205258945Sroberto			/*
206258945Sroberto			 * work around problem mixing
207258945Sroberto			 * stdout & stderr
208258945Sroberto			 */
209258945Sroberto			fputs("", stdout);
210258945Sroberto# endif	/* VMS */
211258945Sroberto
212258945Sroberto		fputs(lineedit_prompt, stderr);
213258945Sroberto		fflush(stderr);
214258945Sroberto	}
215258945Sroberto
216258945Sroberto	line = fgets(line_buf, sizeof(line_buf), stdin);
217258945Sroberto	if (NULL != line && *line) {
218258945Sroberto		*pcount = strlen(line);
219258945Sroberto		line = estrdup(line);
220258945Sroberto	} else
221258945Sroberto		line = NULL;
222258945Sroberto
223258945Sroberto#endif	/* LE_NONE */
224258945Sroberto
225258945Sroberto
226258945Sroberto	if (!line)			/* EOF */
227258945Sroberto		fputs("\n", stderr);
228258945Sroberto
229258945Sroberto	return line;
230258945Sroberto}
231258945Sroberto
232258945Sroberto
233258945Sroberto#ifdef LE_EDITLINE
234258945Sroberto/*
235258945Sroberto * ntp_prompt_callback - return prompt string to el_gets()
236258945Sroberto */
237258945Srobertochar *
238258945Srobertontp_prompt_callback(
239258945Sroberto	EditLine *el
240258945Sroberto	)
241258945Sroberto{
242258945Sroberto	UNUSED_ARG(el);
243258945Sroberto
244258945Sroberto	return lineedit_prompt;
245258945Sroberto}
246258945Sroberto#endif /* LE_EDITLINE */
247258945Sroberto
248