ntp_lineedit.c revision 280849
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
96280849Scy				mfprintf(stderr, "history_init(): %m\n");
97258945Sroberto				fflush(stderr);
98258945Sroberto
99258945Sroberto				el_end(ntp_el);
100258945Sroberto				ntp_el = NULL;
101258945Sroberto
102258945Sroberto				success = 0;
103258945Sroberto
104258945Sroberto			} else {
105280849Scy				ZERO(hev);
106258945Sroberto#ifdef H_SETSIZE
107258945Sroberto				history(ntp_hist, &hev, H_SETSIZE, 128);
108258945Sroberto#endif
109258945Sroberto				el_set(ntp_el, EL_HIST, history,
110258945Sroberto				       ntp_hist);
111258945Sroberto				/* use any .editrc */
112258945Sroberto				el_source(ntp_el, NULL);
113258945Sroberto			}
114258945Sroberto		} else
115258945Sroberto			success = 0;
116258945Sroberto	}
117258945Sroberto#endif	/* LE_EDITLINE */
118258945Sroberto
119258945Sroberto	ntp_readline_initted = success;
120258945Sroberto
121258945Sroberto	return success;
122258945Sroberto}
123258945Sroberto
124258945Sroberto
125258945Sroberto/*
126258945Sroberto * ntp_readline_uninit - release resources
127258945Sroberto */
128258945Srobertovoid
129258945Srobertontp_readline_uninit(
130258945Sroberto	void
131258945Sroberto	)
132258945Sroberto{
133258945Sroberto#ifdef LE_EDITLINE
134258945Sroberto	if (ntp_el) {
135258945Sroberto		el_end(ntp_el);
136258945Sroberto		ntp_el = NULL;
137258945Sroberto
138258945Sroberto		history_end(ntp_hist);
139258945Sroberto		ntp_hist = NULL;
140258945Sroberto	}
141258945Sroberto#endif	/* LE_EDITLINE */
142258945Sroberto
143258945Sroberto	if (lineedit_prompt) {
144258945Sroberto		free(lineedit_prompt);
145258945Sroberto		lineedit_prompt = NULL;
146258945Sroberto	}
147258945Sroberto
148258945Sroberto	ntp_readline_initted = 0;
149258945Sroberto}
150258945Sroberto
151258945Sroberto
152258945Sroberto/*
153258945Sroberto * ntp_readline - read a line with the line editor available
154258945Sroberto *
155258945Sroberto * The string returned must be released with free()
156258945Sroberto */
157258945Sroberto
158258945Srobertochar *
159258945Srobertontp_readline(
160258945Sroberto	int *	pcount
161258945Sroberto	)
162258945Sroberto{
163258945Sroberto	char *		line;
164258945Sroberto#ifdef LE_NONE
165258945Sroberto	char		line_buf[MAXEDITLINE];
166258945Sroberto#endif
167258945Sroberto#ifdef LE_EDITLINE
168258945Sroberto	const char *	cline;
169258945Sroberto#endif
170258945Sroberto
171258945Sroberto	if (!ntp_readline_initted)
172258945Sroberto		return NULL;
173258945Sroberto
174258945Sroberto	*pcount = 0;
175258945Sroberto
176258945Sroberto#ifdef LE_READLINE
177258945Sroberto	line = readline(lineedit_prompt ? lineedit_prompt : "");
178258945Sroberto	if (NULL != line) {
179258945Sroberto		if (*line) {
180258945Sroberto			add_history(line);
181258945Sroberto		}
182280849Scy		*pcount = strlen(line);
183258945Sroberto	}
184258945Sroberto#endif	/* LE_READLINE */
185258945Sroberto
186258945Sroberto#ifdef LE_EDITLINE
187258945Sroberto	cline = el_gets(ntp_el, pcount);
188258945Sroberto
189280849Scy	if (NULL != cline) {
190258945Sroberto		history(ntp_hist, &hev, H_ENTER, cline);
191258945Sroberto		line = estrdup(cline);
192280849Scy	} else if (*pcount == -1) {
193258945Sroberto		line = NULL;
194280849Scy	} else {
195280849Scy		line = estrdup("");
196280849Scy	}
197258945Sroberto#endif	/* LE_EDITLINE */
198258945Sroberto
199258945Sroberto#ifdef LE_NONE
200258945Sroberto					/* stone hammers */
201258945Sroberto	if (lineedit_prompt) {
202258945Sroberto# ifdef VMS
203258945Sroberto			/*
204258945Sroberto			 * work around problem mixing
205258945Sroberto			 * stdout & stderr
206258945Sroberto			 */
207258945Sroberto			fputs("", stdout);
208258945Sroberto# endif	/* VMS */
209258945Sroberto
210258945Sroberto		fputs(lineedit_prompt, stderr);
211258945Sroberto		fflush(stderr);
212258945Sroberto	}
213258945Sroberto
214258945Sroberto	line = fgets(line_buf, sizeof(line_buf), stdin);
215258945Sroberto	if (NULL != line && *line) {
216258945Sroberto		*pcount = strlen(line);
217258945Sroberto		line = estrdup(line);
218258945Sroberto	} else
219258945Sroberto		line = NULL;
220258945Sroberto
221258945Sroberto#endif	/* LE_NONE */
222258945Sroberto
223258945Sroberto
224258945Sroberto	if (!line)			/* EOF */
225258945Sroberto		fputs("\n", stderr);
226258945Sroberto
227258945Sroberto	return line;
228258945Sroberto}
229258945Sroberto
230258945Sroberto
231258945Sroberto#ifdef LE_EDITLINE
232258945Sroberto/*
233258945Sroberto * ntp_prompt_callback - return prompt string to el_gets()
234258945Sroberto */
235258945Srobertochar *
236258945Srobertontp_prompt_callback(
237258945Sroberto	EditLine *el
238258945Sroberto	)
239258945Sroberto{
240258945Sroberto	UNUSED_ARG(el);
241258945Sroberto
242258945Sroberto	return lineedit_prompt;
243258945Sroberto}
244258945Sroberto#endif /* LE_EDITLINE */
245258945Sroberto
246