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