1 /*	$NetBSD: ntp_lineedit.c,v 1.1.1.1 2009/12/13 16:55:02 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 			*pcount = strlen(line);
178 		} else {
179 			free(line);
180 			line = NULL;
181 		}
182 	}
183 
184 #endif	/* HAVE_READLINE_HISTORY */
185 
186 #if !defined(HAVE_READLINE_HISTORY) && defined(HAVE_HISTEDIT_H)
187 
188 	cline = el_gets(ntp_el, pcount);
189 
190 	if (NULL != cline && *cline) {
191 		history(ntp_hist, &hev, H_ENTER, cline);
192 		*pcount = strlen(cline);
193 		line = estrdup(cline);
194 	} else
195 		line = NULL;
196 
197 #endif	/* !HAVE_READLINE_HISTORY && HAVE_HISTEDIT_H */
198 
199 #if !defined(HAVE_READLINE_HISTORY) && !defined(HAVE_HISTEDIT_H)
200 					/* stone hammers */
201 	if (lineedit_prompt) {
202 # ifdef VMS
203 			/*
204 			 * work around problem mixing
205 			 * stdout & stderr
206 			 */
207 			fputs("", stdout);
208 # endif	/* VMS */
209 
210 		fputs(lineedit_prompt, stderr);
211 		fflush(stderr);
212 	}
213 
214 	line = fgets(line_buf, sizeof(line_buf), stdin);
215 	if (NULL != line && *line) {
216 		*pcount = strlen(line);
217 		line = estrdup(line);
218 	} else
219 		line = NULL;
220 
221 #endif	/* !HAVE_READLINE_HISTORY && !HAVE_HISTEDIT_H */
222 
223 
224 	if (!line)			/* EOF */
225 		fputs("\n", stderr);
226 
227 	return line;
228 }
229 
230 
231 #if !defined(HAVE_READLINE_HISTORY) && defined(HAVE_HISTEDIT_H)
232 /*
233  * ntp_prompt_callback - return prompt string to el_gets()
234  */
235 char *
236 ntp_prompt_callback(
237 	EditLine *el
238 	)
239 {
240 	UNUSED_ARG(el);
241 
242 	return lineedit_prompt;
243 }
244 #endif /* !HAVE_READLINE_HISTORY_H && HAVE_HISTEDIT_H */
245 
246