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 33 #define MAXEDITLINE 512 34 35 /* 36 * external references 37 */ 38 39 extern char const * progname; 40 41 /* 42 * globals, private prototypes 43 */ 44 45 static int ntp_readline_initted; 46 static char * lineedit_prompt; 47 48 49 #ifdef LE_EDITLINE 50 # ifndef H_SETSIZE 51 # define H_SETSIZE H_EVENT 52 # endif 53 static EditLine * ntp_el; 54 static History * ntp_hist; 55 static HistEvent hev; 56 57 char * ntp_prompt_callback(EditLine *); 58 #endif /* LE_EDITLINE */ 59 60 61 /* 62 * ntp_readline_init - setup, set or reset prompt string 63 */ 64 int 65 ntp_readline_init( 66 const char * prompt 67 ) 68 { 69 int success; 70 71 success = 1; 72 73 if (prompt) { 74 if (lineedit_prompt) 75 free(lineedit_prompt); 76 lineedit_prompt = estrdup(prompt); 77 } 78 79 #ifdef LE_EDITLINE 80 if (NULL == ntp_el) { 81 82 # if 4 == EL_INIT_ARGS 83 ntp_el = el_init(progname, stdin, stdout, stderr); 84 # else 85 ntp_el = el_init(progname, stdin, stdout); 86 # endif 87 if (ntp_el) { 88 89 el_set(ntp_el, EL_PROMPT, ntp_prompt_callback); 90 el_set(ntp_el, EL_EDITOR, "emacs"); 91 92 ntp_hist = history_init(); 93 94 if (NULL == ntp_hist) { 95 96 mfprintf(stderr, "history_init(): %m\n"); 97 fflush(stderr); 98 99 el_end(ntp_el); 100 ntp_el = NULL; 101 102 success = 0; 103 104 } else { 105 ZERO(hev); 106 #ifdef H_SETSIZE 107 history(ntp_hist, &hev, H_SETSIZE, 128); 108 #endif 109 el_set(ntp_el, EL_HIST, history, 110 ntp_hist); 111 /* use any .editrc */ 112 el_source(ntp_el, NULL); 113 } 114 } else 115 success = 0; 116 } 117 #endif /* LE_EDITLINE */ 118 119 ntp_readline_initted = success; 120 121 return success; 122 } 123 124 125 /* 126 * ntp_readline_uninit - release resources 127 */ 128 void 129 ntp_readline_uninit( 130 void 131 ) 132 { 133 #ifdef LE_EDITLINE 134 if (ntp_el) { 135 el_end(ntp_el); 136 ntp_el = NULL; 137 138 history_end(ntp_hist); 139 ntp_hist = NULL; 140 } 141 #endif /* LE_EDITLINE */ 142 143 if (lineedit_prompt) { 144 free(lineedit_prompt); 145 lineedit_prompt = NULL; 146 } 147 148 ntp_readline_initted = 0; 149 } 150 151 152 /* 153 * ntp_readline - read a line with the line editor available 154 * 155 * The string returned must be released with free() 156 */ 157 158 char * 159 ntp_readline( 160 int * pcount 161 ) 162 { 163 char * line; 164 #ifdef LE_NONE 165 char line_buf[MAXEDITLINE]; 166 #endif 167 #ifdef LE_EDITLINE 168 const char * cline; 169 #endif 170 171 if (!ntp_readline_initted) 172 return NULL; 173 174 *pcount = 0; 175 176 #ifdef LE_READLINE 177 line = readline(lineedit_prompt ? lineedit_prompt : ""); 178 if (NULL != line) { 179 if (*line) { 180 add_history(line); 181 } 182 *pcount = strlen(line); 183 } 184 #endif /* LE_READLINE */ 185 186 #ifdef LE_EDITLINE 187 cline = el_gets(ntp_el, pcount); 188 189 if (NULL != cline) { 190 history(ntp_hist, &hev, H_ENTER, cline); 191 line = estrdup(cline); 192 } else if (*pcount == -1) { 193 line = NULL; 194 } else { 195 line = estrdup(""); 196 } 197 #endif /* LE_EDITLINE */ 198 199 #ifdef LE_NONE 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 /* LE_NONE */ 222 223 224 if (!line) /* EOF */ 225 fputs("\n", stderr); 226 227 return line; 228 } 229 230 231 #ifdef LE_EDITLINE 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 /* LE_EDITLINE */ 245 246