]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/ntp/libntp/ntp_lineedit.c
o Fix invalid TCP checksums with pf(4). [EN-16:02.pf]
[FreeBSD/releng/9.3.git] / contrib / ntp / libntp / ntp_lineedit.c
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 #include "safecast.h"
33
34 #define MAXEDITLINE     512
35
36 /*
37  * external references
38  */
39
40 extern char const *     progname;
41
42 /*
43  * globals, private prototypes
44  */
45
46 static int      ntp_readline_initted;
47 static char *   lineedit_prompt;
48
49
50 #ifdef LE_EDITLINE
51 # ifndef H_SETSIZE
52 #  define H_SETSIZE H_EVENT
53 # endif
54 static EditLine *       ntp_el;
55 static History *        ntp_hist;
56 static HistEvent        hev;
57
58 char *  ntp_prompt_callback(EditLine *);
59 #endif  /* LE_EDITLINE */
60
61
62 /*
63  * ntp_readline_init - setup, set or reset prompt string
64  */
65 int
66 ntp_readline_init(
67         const char *    prompt
68         )
69 {
70         int     success;
71
72         success = 1;
73
74         if (prompt) {
75                 if (lineedit_prompt) 
76                         free(lineedit_prompt);
77                 lineedit_prompt = estrdup(prompt);
78         }
79
80 #ifdef LE_EDITLINE
81         if (NULL == ntp_el) {
82
83 # if 4 == EL_INIT_ARGS
84                 ntp_el = el_init(progname, stdin, stdout, stderr);
85 # else
86                 ntp_el = el_init(progname, stdin, stdout);
87 # endif
88                 if (ntp_el) {
89
90                         el_set(ntp_el, EL_PROMPT, ntp_prompt_callback);
91                         el_set(ntp_el, EL_EDITOR, "emacs");
92
93                         ntp_hist = history_init();
94
95                         if (NULL == ntp_hist) {
96
97                                 mfprintf(stderr, "history_init(): %m\n");
98                                 fflush(stderr);
99
100                                 el_end(ntp_el);
101                                 ntp_el = NULL;
102
103                                 success = 0;
104
105                         } else {
106                                 ZERO(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  */
129 void
130 ntp_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
159 char *
160 ntp_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                 }
183                 *pcount = strlen(line);
184         }
185 #endif  /* LE_READLINE */
186
187 #ifdef LE_EDITLINE
188         cline = el_gets(ntp_el, pcount);
189
190         if (NULL != cline) {
191                 history(ntp_hist, &hev, H_ENTER, cline);
192                 line = estrdup(cline);
193         } else if (*pcount == -1) {
194                 line = NULL;
195         } else {
196                 line = estrdup("");
197         }
198 #endif  /* LE_EDITLINE */
199
200 #ifdef LE_NONE
201                                         /* stone hammers */
202         if (lineedit_prompt) {
203 # ifdef VMS
204                         /*
205                          * work around problem mixing
206                          * stdout & stderr
207                          */
208                         fputs("", stdout);
209 # endif /* VMS */
210
211                 fputs(lineedit_prompt, stderr);
212                 fflush(stderr);
213         }
214
215         line = fgets(line_buf, sizeof(line_buf), stdin);
216         if (NULL != line && *line) {
217                 *pcount = (int)strlen(line); /* cannot overflow here */
218                 line = estrdup(line);
219         } else
220                 line = NULL;
221
222 #endif  /* LE_NONE */
223
224
225         if (!line)                      /* EOF */
226                 fputs("\n", stderr);
227
228         return line;
229 }
230
231
232 #ifdef LE_EDITLINE
233 /*
234  * ntp_prompt_callback - return prompt string to el_gets()
235  */
236 char *
237 ntp_prompt_callback(
238         EditLine *el
239         )
240 {
241         UNUSED_ARG(el);
242
243         return lineedit_prompt;
244 }
245 #endif /* LE_EDITLINE */
246