# 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@
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(.
# 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.
#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;
{
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;
(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;
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')