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