ntp_lineedit.c revision 290001
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 39extern char const * progname; 40 41/* 42 * globals, private prototypes 43 */ 44 45static int ntp_readline_initted; 46static char * lineedit_prompt; 47 48 49#ifdef LE_EDITLINE 50# ifndef H_SETSIZE 51# define H_SETSIZE H_EVENT 52# endif 53static EditLine * ntp_el; 54static History * ntp_hist; 55static HistEvent hev; 56 57char * ntp_prompt_callback(EditLine *); 58#endif /* LE_EDITLINE */ 59 60 61/* 62 * ntp_readline_init - setup, set or reset prompt string 63 */ 64int 65ntp_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 */ 128void 129ntp_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 158char * 159ntp_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 */ 235char * 236ntp_prompt_callback( 237 EditLine *el 238 ) 239{ 240 UNUSED_ARG(el); 241 242 return lineedit_prompt; 243} 244#endif /* LE_EDITLINE */ 245 246