ntp_lineedit.c revision 258945
1/*
2 * ntp_lineedit.c - generic interface to various line editing libs
3 */
4#ifdef HAVE_CONFIG_H
5# include <config.h>
6#endif
7
8#include <errno.h>
9#include <string.h>
10#include <stdlib.h>
11#include <stdio.h>
12
13#if defined(HAVE_READLINE_HISTORY) &&		\
14    (!defined(HAVE_READLINE_HISTORY_H) ||	\
15     !defined(HAVE_READLINE_READLINE_H))
16# undef HAVE_READLINE_HISTORY
17#endif
18#if defined(HAVE_READLINE_HISTORY)
19# include <readline/readline.h>
20# include <readline/history.h>
21# define LE_READLINE
22#elif defined(HAVE_HISTEDIT_H)
23# include <histedit.h>
24# define LE_EDITLINE
25#else
26# define LE_NONE
27#endif
28
29#include "ntp.h"
30#include "ntp_stdlib.h"
31#include "ntp_lineedit.h"
32
33#define MAXEDITLINE	512
34
35/*
36 * external references
37 */
38
39extern char *	progname;
40
41/*
42 * globals, private prototypes
43 */
44
45static int	ntp_readline_initted;
46static char *	lineedit_prompt;
47
48
49#ifdef LE_EDITLINE
50# ifndef H_SETSIZE
51#  define H_SETSIZE H_EVENT
52# endif
53static EditLine *	ntp_el;
54static History *	ntp_hist;
55static HistEvent	hev;
56
57char *	ntp_prompt_callback(EditLine *);
58#endif	/* LE_EDITLINE */
59
60
61/*
62 * ntp_readline_init - setup, set or reset prompt string
63 */
64int
65ntp_readline_init(
66	const char *	prompt
67	)
68{
69	int	success;
70
71	success = 1;
72
73	if (prompt) {
74		if (lineedit_prompt)
75			free(lineedit_prompt);
76		lineedit_prompt = estrdup(prompt);
77	}
78
79#ifdef LE_EDITLINE
80	if (NULL == ntp_el) {
81
82# if 4 == EL_INIT_ARGS
83		ntp_el = el_init(progname, stdin, stdout, stderr);
84# else
85		ntp_el = el_init(progname, stdin, stdout);
86# endif
87		if (ntp_el) {
88
89			el_set(ntp_el, EL_PROMPT, ntp_prompt_callback);
90			el_set(ntp_el, EL_EDITOR, "emacs");
91
92			ntp_hist = history_init();
93
94			if (NULL == ntp_hist) {
95
96				fprintf(stderr, "history_init(): %s\n",
97						strerror(errno));
98				fflush(stderr);
99
100				el_end(ntp_el);
101				ntp_el = NULL;
102
103				success = 0;
104
105			} else {
106				memset(&hev, 0, sizeof(hev));
107#ifdef H_SETSIZE
108				history(ntp_hist, &hev, H_SETSIZE, 128);
109#endif
110				el_set(ntp_el, EL_HIST, history,
111				       ntp_hist);
112				/* use any .editrc */
113				el_source(ntp_el, NULL);
114			}
115		} else
116			success = 0;
117	}
118#endif	/* LE_EDITLINE */
119
120	ntp_readline_initted = success;
121
122	return success;
123}
124
125
126/*
127 * ntp_readline_uninit - release resources
128 */
129void
130ntp_readline_uninit(
131	void
132	)
133{
134#ifdef LE_EDITLINE
135	if (ntp_el) {
136		el_end(ntp_el);
137		ntp_el = NULL;
138
139		history_end(ntp_hist);
140		ntp_hist = NULL;
141	}
142#endif	/* LE_EDITLINE */
143
144	if (lineedit_prompt) {
145		free(lineedit_prompt);
146		lineedit_prompt = NULL;
147	}
148
149	ntp_readline_initted = 0;
150}
151
152
153/*
154 * ntp_readline - read a line with the line editor available
155 *
156 * The string returned must be released with free()
157 */
158
159char *
160ntp_readline(
161	int *	pcount
162	)
163{
164	char *		line;
165#ifdef LE_NONE
166	char		line_buf[MAXEDITLINE];
167#endif
168#ifdef LE_EDITLINE
169	const char *	cline;
170#endif
171
172	if (!ntp_readline_initted)
173		return NULL;
174
175	*pcount = 0;
176
177#ifdef LE_READLINE
178	line = readline(lineedit_prompt ? lineedit_prompt : "");
179	if (NULL != line) {
180		if (*line) {
181			add_history(line);
182			*pcount = strlen(line);
183		} else {
184			free(line);
185			line = NULL;
186		}
187	}
188#endif	/* LE_READLINE */
189
190#ifdef LE_EDITLINE
191	cline = el_gets(ntp_el, pcount);
192
193	if (NULL != cline && *cline) {
194		history(ntp_hist, &hev, H_ENTER, cline);
195		*pcount = strlen(cline);
196		line = estrdup(cline);
197	} else
198		line = NULL;
199#endif	/* LE_EDITLINE */
200
201#ifdef LE_NONE
202					/* stone hammers */
203	if (lineedit_prompt) {
204# ifdef VMS
205			/*
206			 * work around problem mixing
207			 * stdout & stderr
208			 */
209			fputs("", stdout);
210# endif	/* VMS */
211
212		fputs(lineedit_prompt, stderr);
213		fflush(stderr);
214	}
215
216	line = fgets(line_buf, sizeof(line_buf), stdin);
217	if (NULL != line && *line) {
218		*pcount = strlen(line);
219		line = estrdup(line);
220	} else
221		line = NULL;
222
223#endif	/* LE_NONE */
224
225
226	if (!line)			/* EOF */
227		fputs("\n", stderr);
228
229	return line;
230}
231
232
233#ifdef LE_EDITLINE
234/*
235 * ntp_prompt_callback - return prompt string to el_gets()
236 */
237char *
238ntp_prompt_callback(
239	EditLine *el
240	)
241{
242	UNUSED_ARG(el);
243
244	return lineedit_prompt;
245}
246#endif /* LE_EDITLINE */
247
248