ntp_lineedit.c revision 280849
1258945Sroberto/* 2258945Sroberto * ntp_lineedit.c - generic interface to various line editing libs 3258945Sroberto */ 4258945Sroberto#ifdef HAVE_CONFIG_H 5258945Sroberto# include <config.h> 6258945Sroberto#endif 7258945Sroberto 8258945Sroberto#include <errno.h> 9258945Sroberto#include <string.h> 10258945Sroberto#include <stdlib.h> 11258945Sroberto#include <stdio.h> 12258945Sroberto 13258945Sroberto#if defined(HAVE_READLINE_HISTORY) && \ 14258945Sroberto (!defined(HAVE_READLINE_HISTORY_H) || \ 15258945Sroberto !defined(HAVE_READLINE_READLINE_H)) 16258945Sroberto# undef HAVE_READLINE_HISTORY 17258945Sroberto#endif 18258945Sroberto#if defined(HAVE_READLINE_HISTORY) 19258945Sroberto# include <readline/readline.h> 20258945Sroberto# include <readline/history.h> 21258945Sroberto# define LE_READLINE 22258945Sroberto#elif defined(HAVE_HISTEDIT_H) 23258945Sroberto# include <histedit.h> 24258945Sroberto# define LE_EDITLINE 25258945Sroberto#else 26258945Sroberto# define LE_NONE 27258945Sroberto#endif 28258945Sroberto 29258945Sroberto#include "ntp.h" 30258945Sroberto#include "ntp_stdlib.h" 31258945Sroberto#include "ntp_lineedit.h" 32258945Sroberto 33258945Sroberto#define MAXEDITLINE 512 34258945Sroberto 35258945Sroberto/* 36258945Sroberto * external references 37258945Sroberto */ 38258945Sroberto 39258945Srobertoextern char * progname; 40258945Sroberto 41258945Sroberto/* 42258945Sroberto * globals, private prototypes 43258945Sroberto */ 44258945Sroberto 45258945Srobertostatic int ntp_readline_initted; 46258945Srobertostatic char * lineedit_prompt; 47258945Sroberto 48258945Sroberto 49258945Sroberto#ifdef LE_EDITLINE 50258945Sroberto# ifndef H_SETSIZE 51258945Sroberto# define H_SETSIZE H_EVENT 52258945Sroberto# endif 53258945Srobertostatic EditLine * ntp_el; 54258945Srobertostatic History * ntp_hist; 55258945Srobertostatic HistEvent hev; 56258945Sroberto 57258945Srobertochar * ntp_prompt_callback(EditLine *); 58258945Sroberto#endif /* LE_EDITLINE */ 59258945Sroberto 60258945Sroberto 61258945Sroberto/* 62258945Sroberto * ntp_readline_init - setup, set or reset prompt string 63258945Sroberto */ 64258945Srobertoint 65258945Srobertontp_readline_init( 66258945Sroberto const char * prompt 67258945Sroberto ) 68258945Sroberto{ 69258945Sroberto int success; 70258945Sroberto 71258945Sroberto success = 1; 72258945Sroberto 73258945Sroberto if (prompt) { 74258945Sroberto if (lineedit_prompt) 75258945Sroberto free(lineedit_prompt); 76258945Sroberto lineedit_prompt = estrdup(prompt); 77258945Sroberto } 78258945Sroberto 79258945Sroberto#ifdef LE_EDITLINE 80258945Sroberto if (NULL == ntp_el) { 81258945Sroberto 82258945Sroberto# if 4 == EL_INIT_ARGS 83258945Sroberto ntp_el = el_init(progname, stdin, stdout, stderr); 84258945Sroberto# else 85258945Sroberto ntp_el = el_init(progname, stdin, stdout); 86258945Sroberto# endif 87258945Sroberto if (ntp_el) { 88258945Sroberto 89258945Sroberto el_set(ntp_el, EL_PROMPT, ntp_prompt_callback); 90258945Sroberto el_set(ntp_el, EL_EDITOR, "emacs"); 91258945Sroberto 92258945Sroberto ntp_hist = history_init(); 93258945Sroberto 94258945Sroberto if (NULL == ntp_hist) { 95258945Sroberto 96280849Scy mfprintf(stderr, "history_init(): %m\n"); 97258945Sroberto fflush(stderr); 98258945Sroberto 99258945Sroberto el_end(ntp_el); 100258945Sroberto ntp_el = NULL; 101258945Sroberto 102258945Sroberto success = 0; 103258945Sroberto 104258945Sroberto } else { 105280849Scy ZERO(hev); 106258945Sroberto#ifdef H_SETSIZE 107258945Sroberto history(ntp_hist, &hev, H_SETSIZE, 128); 108258945Sroberto#endif 109258945Sroberto el_set(ntp_el, EL_HIST, history, 110258945Sroberto ntp_hist); 111258945Sroberto /* use any .editrc */ 112258945Sroberto el_source(ntp_el, NULL); 113258945Sroberto } 114258945Sroberto } else 115258945Sroberto success = 0; 116258945Sroberto } 117258945Sroberto#endif /* LE_EDITLINE */ 118258945Sroberto 119258945Sroberto ntp_readline_initted = success; 120258945Sroberto 121258945Sroberto return success; 122258945Sroberto} 123258945Sroberto 124258945Sroberto 125258945Sroberto/* 126258945Sroberto * ntp_readline_uninit - release resources 127258945Sroberto */ 128258945Srobertovoid 129258945Srobertontp_readline_uninit( 130258945Sroberto void 131258945Sroberto ) 132258945Sroberto{ 133258945Sroberto#ifdef LE_EDITLINE 134258945Sroberto if (ntp_el) { 135258945Sroberto el_end(ntp_el); 136258945Sroberto ntp_el = NULL; 137258945Sroberto 138258945Sroberto history_end(ntp_hist); 139258945Sroberto ntp_hist = NULL; 140258945Sroberto } 141258945Sroberto#endif /* LE_EDITLINE */ 142258945Sroberto 143258945Sroberto if (lineedit_prompt) { 144258945Sroberto free(lineedit_prompt); 145258945Sroberto lineedit_prompt = NULL; 146258945Sroberto } 147258945Sroberto 148258945Sroberto ntp_readline_initted = 0; 149258945Sroberto} 150258945Sroberto 151258945Sroberto 152258945Sroberto/* 153258945Sroberto * ntp_readline - read a line with the line editor available 154258945Sroberto * 155258945Sroberto * The string returned must be released with free() 156258945Sroberto */ 157258945Sroberto 158258945Srobertochar * 159258945Srobertontp_readline( 160258945Sroberto int * pcount 161258945Sroberto ) 162258945Sroberto{ 163258945Sroberto char * line; 164258945Sroberto#ifdef LE_NONE 165258945Sroberto char line_buf[MAXEDITLINE]; 166258945Sroberto#endif 167258945Sroberto#ifdef LE_EDITLINE 168258945Sroberto const char * cline; 169258945Sroberto#endif 170258945Sroberto 171258945Sroberto if (!ntp_readline_initted) 172258945Sroberto return NULL; 173258945Sroberto 174258945Sroberto *pcount = 0; 175258945Sroberto 176258945Sroberto#ifdef LE_READLINE 177258945Sroberto line = readline(lineedit_prompt ? lineedit_prompt : ""); 178258945Sroberto if (NULL != line) { 179258945Sroberto if (*line) { 180258945Sroberto add_history(line); 181258945Sroberto } 182280849Scy *pcount = strlen(line); 183258945Sroberto } 184258945Sroberto#endif /* LE_READLINE */ 185258945Sroberto 186258945Sroberto#ifdef LE_EDITLINE 187258945Sroberto cline = el_gets(ntp_el, pcount); 188258945Sroberto 189280849Scy if (NULL != cline) { 190258945Sroberto history(ntp_hist, &hev, H_ENTER, cline); 191258945Sroberto line = estrdup(cline); 192280849Scy } else if (*pcount == -1) { 193258945Sroberto line = NULL; 194280849Scy } else { 195280849Scy line = estrdup(""); 196280849Scy } 197258945Sroberto#endif /* LE_EDITLINE */ 198258945Sroberto 199258945Sroberto#ifdef LE_NONE 200258945Sroberto /* stone hammers */ 201258945Sroberto if (lineedit_prompt) { 202258945Sroberto# ifdef VMS 203258945Sroberto /* 204258945Sroberto * work around problem mixing 205258945Sroberto * stdout & stderr 206258945Sroberto */ 207258945Sroberto fputs("", stdout); 208258945Sroberto# endif /* VMS */ 209258945Sroberto 210258945Sroberto fputs(lineedit_prompt, stderr); 211258945Sroberto fflush(stderr); 212258945Sroberto } 213258945Sroberto 214258945Sroberto line = fgets(line_buf, sizeof(line_buf), stdin); 215258945Sroberto if (NULL != line && *line) { 216258945Sroberto *pcount = strlen(line); 217258945Sroberto line = estrdup(line); 218258945Sroberto } else 219258945Sroberto line = NULL; 220258945Sroberto 221258945Sroberto#endif /* LE_NONE */ 222258945Sroberto 223258945Sroberto 224258945Sroberto if (!line) /* EOF */ 225258945Sroberto fputs("\n", stderr); 226258945Sroberto 227258945Sroberto return line; 228258945Sroberto} 229258945Sroberto 230258945Sroberto 231258945Sroberto#ifdef LE_EDITLINE 232258945Sroberto/* 233258945Sroberto * ntp_prompt_callback - return prompt string to el_gets() 234258945Sroberto */ 235258945Srobertochar * 236258945Srobertontp_prompt_callback( 237258945Sroberto EditLine *el 238258945Sroberto ) 239258945Sroberto{ 240258945Sroberto UNUSED_ARG(el); 241258945Sroberto 242258945Sroberto return lineedit_prompt; 243258945Sroberto} 244258945Sroberto#endif /* LE_EDITLINE */ 245258945Sroberto 246