ntp_lineedit.c revision 258945
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 96258945Sroberto fprintf(stderr, "history_init(): %s\n", 97258945Sroberto strerror(errno)); 98258945Sroberto fflush(stderr); 99258945Sroberto 100258945Sroberto el_end(ntp_el); 101258945Sroberto ntp_el = NULL; 102258945Sroberto 103258945Sroberto success = 0; 104258945Sroberto 105258945Sroberto } else { 106258945Sroberto memset(&hev, 0, sizeof(hev)); 107258945Sroberto#ifdef H_SETSIZE 108258945Sroberto history(ntp_hist, &hev, H_SETSIZE, 128); 109258945Sroberto#endif 110258945Sroberto el_set(ntp_el, EL_HIST, history, 111258945Sroberto ntp_hist); 112258945Sroberto /* use any .editrc */ 113258945Sroberto el_source(ntp_el, NULL); 114258945Sroberto } 115258945Sroberto } else 116258945Sroberto success = 0; 117258945Sroberto } 118258945Sroberto#endif /* LE_EDITLINE */ 119258945Sroberto 120258945Sroberto ntp_readline_initted = success; 121258945Sroberto 122258945Sroberto return success; 123258945Sroberto} 124258945Sroberto 125258945Sroberto 126258945Sroberto/* 127258945Sroberto * ntp_readline_uninit - release resources 128258945Sroberto */ 129258945Srobertovoid 130258945Srobertontp_readline_uninit( 131258945Sroberto void 132258945Sroberto ) 133258945Sroberto{ 134258945Sroberto#ifdef LE_EDITLINE 135258945Sroberto if (ntp_el) { 136258945Sroberto el_end(ntp_el); 137258945Sroberto ntp_el = NULL; 138258945Sroberto 139258945Sroberto history_end(ntp_hist); 140258945Sroberto ntp_hist = NULL; 141258945Sroberto } 142258945Sroberto#endif /* LE_EDITLINE */ 143258945Sroberto 144258945Sroberto if (lineedit_prompt) { 145258945Sroberto free(lineedit_prompt); 146258945Sroberto lineedit_prompt = NULL; 147258945Sroberto } 148258945Sroberto 149258945Sroberto ntp_readline_initted = 0; 150258945Sroberto} 151258945Sroberto 152258945Sroberto 153258945Sroberto/* 154258945Sroberto * ntp_readline - read a line with the line editor available 155258945Sroberto * 156258945Sroberto * The string returned must be released with free() 157258945Sroberto */ 158258945Sroberto 159258945Srobertochar * 160258945Srobertontp_readline( 161258945Sroberto int * pcount 162258945Sroberto ) 163258945Sroberto{ 164258945Sroberto char * line; 165258945Sroberto#ifdef LE_NONE 166258945Sroberto char line_buf[MAXEDITLINE]; 167258945Sroberto#endif 168258945Sroberto#ifdef LE_EDITLINE 169258945Sroberto const char * cline; 170258945Sroberto#endif 171258945Sroberto 172258945Sroberto if (!ntp_readline_initted) 173258945Sroberto return NULL; 174258945Sroberto 175258945Sroberto *pcount = 0; 176258945Sroberto 177258945Sroberto#ifdef LE_READLINE 178258945Sroberto line = readline(lineedit_prompt ? lineedit_prompt : ""); 179258945Sroberto if (NULL != line) { 180258945Sroberto if (*line) { 181258945Sroberto add_history(line); 182258945Sroberto *pcount = strlen(line); 183258945Sroberto } else { 184258945Sroberto free(line); 185258945Sroberto line = NULL; 186258945Sroberto } 187258945Sroberto } 188258945Sroberto#endif /* LE_READLINE */ 189258945Sroberto 190258945Sroberto#ifdef LE_EDITLINE 191258945Sroberto cline = el_gets(ntp_el, pcount); 192258945Sroberto 193258945Sroberto if (NULL != cline && *cline) { 194258945Sroberto history(ntp_hist, &hev, H_ENTER, cline); 195258945Sroberto *pcount = strlen(cline); 196258945Sroberto line = estrdup(cline); 197258945Sroberto } else 198258945Sroberto line = NULL; 199258945Sroberto#endif /* LE_EDITLINE */ 200258945Sroberto 201258945Sroberto#ifdef LE_NONE 202258945Sroberto /* stone hammers */ 203258945Sroberto if (lineedit_prompt) { 204258945Sroberto# ifdef VMS 205258945Sroberto /* 206258945Sroberto * work around problem mixing 207258945Sroberto * stdout & stderr 208258945Sroberto */ 209258945Sroberto fputs("", stdout); 210258945Sroberto# endif /* VMS */ 211258945Sroberto 212258945Sroberto fputs(lineedit_prompt, stderr); 213258945Sroberto fflush(stderr); 214258945Sroberto } 215258945Sroberto 216258945Sroberto line = fgets(line_buf, sizeof(line_buf), stdin); 217258945Sroberto if (NULL != line && *line) { 218258945Sroberto *pcount = strlen(line); 219258945Sroberto line = estrdup(line); 220258945Sroberto } else 221258945Sroberto line = NULL; 222258945Sroberto 223258945Sroberto#endif /* LE_NONE */ 224258945Sroberto 225258945Sroberto 226258945Sroberto if (!line) /* EOF */ 227258945Sroberto fputs("\n", stderr); 228258945Sroberto 229258945Sroberto return line; 230258945Sroberto} 231258945Sroberto 232258945Sroberto 233258945Sroberto#ifdef LE_EDITLINE 234258945Sroberto/* 235258945Sroberto * ntp_prompt_callback - return prompt string to el_gets() 236258945Sroberto */ 237258945Srobertochar * 238258945Srobertontp_prompt_callback( 239258945Sroberto EditLine *el 240258945Sroberto ) 241258945Sroberto{ 242258945Sroberto UNUSED_ARG(el); 243258945Sroberto 244258945Sroberto return lineedit_prompt; 245258945Sroberto} 246258945Sroberto#endif /* LE_EDITLINE */ 247258945Sroberto 248