summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2011-07-22 00:26:56 +0000
committerGreg Hudson <ghudson@mit.edu>2011-07-22 00:26:56 +0000
commited8bc7b5e8ba1f72a0ae083b3005fbe18718544b (patch)
treefc6cd75398fa2adb8ce685a50fcf56d5ee193e43
parent0d1a70cd014579f6134d73fc073dc090f574e1c8 (diff)
downloadkrb5-ed8bc7b5e8ba1f72a0ae083b3005fbe18718544b.tar.gz
krb5-ed8bc7b5e8ba1f72a0ae083b3005fbe18718544b.tar.xz
krb5-ed8bc7b5e8ba1f72a0ae083b3005fbe18718544b.zip
Add libedit/readline support to ss
By default, look for libedit (using pkg-config) and use it in libss. Alternatively, the builder can explicitly ask for GNU Readline, but using it will break the dejagnu test suite and will also add a GPL dependency to libss and the programs using it. ticket: 6931 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25035 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/config/pre.in6
-rw-r--r--src/configure.in38
-rw-r--r--src/util/ss/Makefile.in2
-rw-r--r--src/util/ss/listen.c54
4 files changed, 79 insertions, 21 deletions
diff --git a/src/config/pre.in b/src/config/pre.in
index 7b96ebc7d..67117d6b4 100644
--- a/src/config/pre.in
+++ b/src/config/pre.in
@@ -369,9 +369,13 @@ SS_DEPS-k5 = $(BUILDTOP)/include/ss/ss.h $(BUILDTOP)/include/ss/ss_err.h
# GEN_LIB is -lgen if needed for regexp
GEN_LIB = @GEN_LIB@
+# Editline or readline flags and libraries.
+RL_CFLAGS = @RL_CFLAGS@
+RL_LIBS = @RL_LIBS@
+
SS_LIB = $(SS_LIB-@SS_VERSION@)
SS_LIB-sys = @SS_LIB@
-SS_LIB-k5 = $(TOPLIBD)/libss.a
+SS_LIB-k5 = $(TOPLIBD)/libss.a $(RL_LIBS)
KDB5_LIB = -lkdb5 $(KDB5_PLUGIN_LIBS)
DL_LIB = @DL_LIB@
diff --git a/src/configure.in b/src/configure.in
index 4ed9e31e3..b057a3b48 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -1100,6 +1100,44 @@ if test "$ac_cv_lib_socket" = "yes" -a "$ac_cv_lib_nsl" = "yes"; then
AC_DEFINE(BROKEN_STREAMS_SOCKETS,1,[Define if socket can't be bound to 0.0.0.0])
fi
+# Compile with libedit support in ss by default if available. Compile
+# with readline only if asked, to avoid a default GPL dependency.
+# Building with readline also breaks the dejagnu test suite.
+AC_ARG_WITH([libedit],
+ AC_HELP_STRING([--without-libedit], [do not compile with libedit]),
+ [], [with_libedit=default])
+AC_ARG_WITH([readline],
+ AC_HELP_STRING([--with-readline], [compile with GNU Readline]),
+ [], [with_readline=no])
+AC_MSG_CHECKING([for readline support])
+if test "x$with_readline" = xyes; then
+ with_libedit=no
+fi
+RL_CFLAGS=
+RL_LIBS=
+if test "x$with_libedit" != xno; then
+ if RL_CFLAGS=`pkg-config --cflags libedit 2>&1`; then
+ RL_LIBS=`pkg-config --libs libedit`
+ AC_DEFINE([HAVE_LIBEDIT], 1, [Define if building with libedit.])
+ AC_MSG_RESULT([using libedit])
+ elif test "x$with_libedit" = yes; then
+ # We were explicitly asked for libedit and couldn't find it.
+ AC_MSG_ERROR([Could not detect libedit with pkg-config.])
+ else
+ AC_MSG_RESULT([not using any])
+ fi
+elif test "x$with_readline" = xyes; then
+ AC_MSG_RESULT([using GNU Readline])
+ AC_CHECK_LIB([readline], [main], :,
+ AC_MSG_FAILURE([Cannot find readline library.]), [-lncurses])
+ AC_DEFINE([HAVE_READLINE], 1, [Define if building with GNU Readline.])
+ RL_LIBS='-lreadline -lhistory -lncurses'
+else
+ AC_MSG_RESULT([not using any])
+fi
+AC_SUBST([RL_CFLAGS])
+AC_SUBST([RL_LIBS])
+
AC_CONFIG_FILES(krb5-config, [chmod +x krb5-config])
V5_AC_OUTPUT_MAKEFILE(.
diff --git a/src/util/ss/Makefile.in b/src/util/ss/Makefile.in
index 3f6fd84f9..48f022925 100644
--- a/src/util/ss/Makefile.in
+++ b/src/util/ss/Makefile.in
@@ -26,7 +26,7 @@ install-unix:: install-libs
# hard coded ../et is so com_err.h works
# CFLAGS= -g
# CPPFLAGS= -I${INCDIR} -I. -I.. -I../et
-LOCALINCLUDES= -I. -I$(srcdir)/
+LOCALINCLUDES= -I. -I$(srcdir)/ $(RL_CFLAGS)
# with ss_err.o first, ss_err.h should get rebuilt first too. should not
# be relying on this, though.
diff --git a/src/util/ss/listen.c b/src/util/ss/listen.c
index f7be47b13..10e04654a 100644
--- a/src/util/ss/listen.c
+++ b/src/util/ss/listen.c
@@ -14,20 +14,43 @@
#include <termios.h>
#include <sys/param.h>
+#if defined(HAVE_LIBEDIT)
+#include <editline/readline.h>
+#include <editline/history.h>
+#elif defined(HAVE_READLINE)
+#include <readline/readline.h>
+#include <readline/history.h>
+#else
+#define NO_READLINE
+#endif
+
static ss_data *current_info;
static jmp_buf listen_jmpb;
-static RETSIGTYPE print_prompt()
+#ifdef NO_READLINE
+/* Dumb replacement for readline when we don't have support for a real one. */
+static char *readline(const char *prompt)
{
struct termios termbuf;
+ char input[BUFSIZ];
if (tcgetattr(STDIN_FILENO, &termbuf) == 0) {
termbuf.c_lflag |= ICANON|ISIG|ECHO;
tcsetattr(STDIN_FILENO, TCSANOW, &termbuf);
}
- (void) fputs(current_info->prompt, stdout);
- (void) fflush(stdout);
+ printf("%s", prompt);
+ fflush(stdout);
+ if (fgets(input, BUFSIZ, stdin) == NULL)
+ return NULL;
+ input[strcspn(input, "\r\n")] = '\0';
+ return strdup(input);
+}
+
+/* No-op replacement for add_history() when we have no readline support. */
+static void add_history(const char *line)
+{
}
+#endif
static RETSIGTYPE listen_int_handler(signo)
int signo;
@@ -41,9 +64,7 @@ int ss_listen (sci_idx)
{
register char *cp;
register ss_data *info;
- char input[BUFSIZ];
- char buffer[BUFSIZ];
- char *volatile end = buffer;
+ char *input;
int code;
jmp_buf old_jmpb;
ss_data *old_info = current_info;
@@ -88,8 +109,6 @@ int ss_listen (sci_idx)
(void) sigsetmask(mask);
#endif
while(!info->abort) {
- print_prompt();
- *end = '\0';
#ifdef POSIX_SIGNALS
nsig.sa_handler = listen_int_handler; /* fgets is not signal-safe */
osig = csig;
@@ -98,29 +117,26 @@ int ss_listen (sci_idx)
csig = osig;
#else
old_sig_cont = sig_cont;
- sig_cont = signal(SIGCONT, print_prompt);
- if (sig_cont == print_prompt)
+ sig_cont = signal(SIGCONT, listen_int_handler);
+ if (sig_cont == listen_int_handler)
sig_cont = old_sig_cont;
#endif
- if (fgets(input, BUFSIZ, stdin) != input) {
+
+ input = readline(current_info->prompt);
+ if (input == NULL) {
code = SS_ET_EOF;
goto egress;
}
- cp = strchr(input, '\n');
- if (cp) {
- *cp = '\0';
- if (cp == input)
- continue;
- }
+ add_history(input);
+
#ifdef POSIX_SIGNALS
sigaction(SIGCONT, &csig, (struct sigaction *)0);
#else
(void) signal(SIGCONT, sig_cont);
#endif
- for (end = input; *end; end++)
- ;
code = ss_execute_line (sci_idx, input);
+ free(input);
if (code == SS_ET_COMMAND_NOT_FOUND) {
register char *c = input;
while (*c == ' ' || *c == '\t')