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