xref: /netbsd-src/external/bsd/ntp/dist/libntp/ntp_lineedit.c (revision b757af438b42b93f8c6571f026d8b8ef3eaf5fc9)
1 /*	$NetBSD: ntp_lineedit.c,v 1.3 2012/02/01 07:46:22 kardel 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 				fprintf(stderr, "history_init(): %s\n",
99 						strerror(errno));
100 				fflush(stderr);
101 
102 				el_end(ntp_el);
103 				ntp_el = NULL;
104 
105 				success = 0;
106 
107 			} else {
108 				memset(&hev, 0, sizeof(hev));
109 #ifdef H_SETSIZE
110 				history(ntp_hist, &hev, H_SETSIZE, 128);
111 #endif
112 				el_set(ntp_el, EL_HIST, history,
113 				       ntp_hist);
114 				/* use any .editrc */
115 				el_source(ntp_el, NULL);
116 			}
117 		} else
118 			success = 0;
119 	}
120 #endif	/* LE_EDITLINE */
121 
122 	ntp_readline_initted = success;
123 
124 	return success;
125 }
126 
127 
128 /*
129  * ntp_readline_uninit - release resources
130  */
131 void
132 ntp_readline_uninit(
133 	void
134 	)
135 {
136 #ifdef LE_EDITLINE
137 	if (ntp_el) {
138 		el_end(ntp_el);
139 		ntp_el = NULL;
140 
141 		history_end(ntp_hist);
142 		ntp_hist = NULL;
143 	}
144 #endif	/* LE_EDITLINE */
145 
146 	if (lineedit_prompt) {
147 		free(lineedit_prompt);
148 		lineedit_prompt = NULL;
149 	}
150 
151 	ntp_readline_initted = 0;
152 }
153 
154 
155 /*
156  * ntp_readline - read a line with the line editor available
157  *
158  * The string returned must be released with free()
159  */
160 
161 char *
162 ntp_readline(
163 	int *	pcount
164 	)
165 {
166 	char *		line;
167 #ifdef LE_NONE
168 	char		line_buf[MAXEDITLINE];
169 #endif
170 #ifdef LE_EDITLINE
171 	const char *	cline;
172 #endif
173 
174 	if (!ntp_readline_initted)
175 		return NULL;
176 
177 	*pcount = 0;
178 
179 #ifdef LE_READLINE
180 	line = readline(lineedit_prompt ? lineedit_prompt : "");
181 	if (NULL != line) {
182 		if (*line) {
183 			add_history(line);
184 		}
185 		*pcount = strlen(line);
186 	}
187 #endif	/* LE_READLINE */
188 
189 #ifdef LE_EDITLINE
190 	cline = el_gets(ntp_el, pcount);
191 
192 	if (NULL != cline) {
193 		history(ntp_hist, &hev, H_ENTER, cline);
194 		line = estrdup(cline);
195 	} else if (*pcount == -1) {
196 		line = NULL;
197 	} else {
198 		line = estrdup("");
199 	}
200 #endif	/* LE_EDITLINE */
201 
202 #ifdef LE_NONE
203 					/* stone hammers */
204 	if (lineedit_prompt) {
205 # ifdef VMS
206 			/*
207 			 * work around problem mixing
208 			 * stdout & stderr
209 			 */
210 			fputs("", stdout);
211 # endif	/* VMS */
212 
213 		fputs(lineedit_prompt, stderr);
214 		fflush(stderr);
215 	}
216 
217 	line = fgets(line_buf, sizeof(line_buf), stdin);
218 	if (NULL != line && *line) {
219 		*pcount = strlen(line);
220 		line = estrdup(line);
221 	} else
222 		line = NULL;
223 
224 #endif	/* LE_NONE */
225 
226 
227 	if (!line)			/* EOF */
228 		fputs("\n", stderr);
229 
230 	return line;
231 }
232 
233 
234 #ifdef LE_EDITLINE
235 /*
236  * ntp_prompt_callback - return prompt string to el_gets()
237  */
238 char *
239 ntp_prompt_callback(
240 	EditLine *el
241 	)
242 {
243 	UNUSED_ARG(el);
244 
245 	return lineedit_prompt;
246 }
247 #endif /* LE_EDITLINE */
248 
249