diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
--- a/Setup.hs
+++ /dev/null
@@ -1,6 +0,0 @@
-module Main (main) where
-
-import Distribution.Simple
-
-main :: IO ()
-main = defaultMainWithHooks defaultUserHooks
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,6 @@
+#!/usr/local/bin/runhaskell
+
+\begin{code}
+import Distribution.Simple
+main = defaultMainWithHooks defaultUserHooks
+\end{code}
diff --git a/System/Console/Editline/Readline.hsc b/System/Console/Editline/Readline.hsc
--- a/System/Console/Editline/Readline.hsc
+++ b/System/Console/Editline/Readline.hsc
@@ -36,21 +36,38 @@
 --
 
 -----------------------------------------------------------------------------
+#include "HsEditlineConfig.h"
 
 #ifdef HAVE_EDITLINE_READLINE_H
 #include <editline/readline.h>
 #else
 #ifdef HAVE_READLINE_READLINE_H
 #include <readline/readline.h>
+#else
+#ifdef HAVE_EDITLINE_EDITLINE_H
+#include <editline/editline.h>
 #endif
 #endif
+#endif
 
+
 module System.Console.Editline.Readline (
     --------------------------------------------------------------------
     -- Basic Behavior.
     
     readline,   -- :: String -> IO (Maybe String)
+
+    --------------------------------------------------------------------
+    -- History Functionality.
+
     addHistory, -- :: String -> IO ()
+    readHistory, -- :: String -> IO ()
+    writeHistory, -- :: String -> IO ()
+    clearHistory, -- :: IO ()
+    stifleHistory, -- :: Int -> IO ()
+    unstifleHistory, -- :: IO Int
+    historyIsStifled, -- :: IO Bool
+    historyMaxEntries, -- IO Int
     
     --------------------------------------------------------------------
     -- Readline Variables.
@@ -185,13 +202,78 @@
         return line
 foreign import ccall "readline" readlineC :: Ptr CChar -> IO (Ptr CChar)
 
+--------------------------------------------------------------------------
+-- History functionality
 
+-- TODO: older versions of libedit don't return errors correctly...
+
 -- |Add this command to the history.  This allows users to search backward
 -- through history with C-r and step through with up and down arrows, among
 -- other things.
 addHistory :: String -> IO ()
 addHistory line = withCString line add_history
 foreign import ccall unsafe add_history :: Ptr CChar -> IO ()
+
+-- |Read in a history file, throwing an error on failure.
+readHistory :: FilePath -- ^ The file to read (if null, read ~/.history)
+            -> IO ()
+readHistory fp = do
+  ok <- withCString fp read_history
+  unless (histResultIsOK ok) $ fail "Can't read history file"
+foreign import ccall unsafe read_history :: Ptr CChar -> IO CInt
+
+-- |Write out a history file, throwing an error on failure.
+writeHistory :: FilePath -- ^ The file to write (if null, write ~/.history
+             -> IO ()
+writeHistory fp = do
+  ok <- withCString fp write_history
+  unless (histResultIsOK ok) $ fail "Can't write history file"
+foreign import ccall unsafe write_history :: Ptr CChar -> IO CInt
+
+histResultIsOK :: CInt -> Bool
+#ifdef NEGATIVE_HIST_ERROR
+-- Old way that libedit handled errors; different from readline
+histResultIsOK = (>=0)
+#else
+histResultIsOK = (==0)
+#endif
+
+-- |Clear the history.
+clearHistory :: IO ()
+clearHistory = clear_history
+foreign import ccall unsafe clear_history :: IO ()
+
+-- |Stifle the history list, remembering only a certain number of entries.
+stifleHistory :: Int -> IO ()
+stifleHistory n = stifle_history n
+foreign import ccall unsafe stifle_history :: Int -> IO ()
+
+-- |Stop stifling the history, returning the previous amount the history was
+--  stifled by. 
+unstifleHistory :: IO Int
+unstifleHistory = unstifle_history
+foreign import ccall unsafe unstifle_history :: IO Int
+
+-- |Check whether the history is stifled or not. True if stifled, False if not.
+historyIsStifled :: IO Bool
+historyIsStifled = do
+  isStifledInt <- history_is_stifled
+  let isStifled = case isStifledInt of
+                    0 -> False
+                    1 -> True
+                    _ -> error "historyIsStifled: history_is_stifled returned unexpected value (expected 0 or 1, received other)" -- just for completeness - there is no conceivable way readline would not return either 0 or 1 here
+  return isStifled
+foreign import ccall unsafe history_is_stifled :: IO Int
+
+-- |Get the maximum number of history entries, returning 0 if the history is 
+-- unstifled.
+historyMaxEntries :: IO Int
+historyMaxEntries = liftM fromIntegral (peek max_input_history)
+
+-- Note: this variable is different than history_max_entries, but has the same
+-- use.
+foreign import ccall "&" max_input_history :: Ptr CInt
+
 
 ------------------------------------------------------------------------
 -- Readline Variables.
diff --git a/aclocal.m4 b/aclocal.m4
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -15,8 +15,47 @@
     [editline_libraries=NONE])
 ])# FP_ARG_EDITLINE
 
-AC_DEFUN([CHECK_EDITLINE],
-[AC_REQUIRE([AC_PROG_CPP])
-AC_REQUIRE([AC_PROG_CC])
+AC_DEFUN([CHECK_HIST_ERRORS],
+[
+dnl Older versions of libedit (up to at least 2.6.9) don't handle errors in
+dnl functions like read_history the same way that readline does; whereas
+dnl readline returns a positive errno on error and zero otherwise, 
+dnl editline may return -1 on error and a nonnegative value otherwise.
+AC_MSG_CHECKING(for sign of read_history result on error)
+AC_RUN_IFELSE(
+  [AC_LANG_SOURCE([[
+#include <stdio.h>
+#ifdef HAVE_EDITLINE_READLINE_H
+#include <editline/readline.h>
+#else
+#ifdef HAVE_READLINE_READLINE_H
+#include <readline/readline.h>
+#else
+#ifdef HAVE_EDITLINE_EDITLINE_H
+#include <editline/editline.h>
+#endif
+#endif
+#endif
 
-])
+int main(void) {
+    int ret;
+    rl_initialize();
+    ret = read_history("this/should/not/be/valid");
+    return (ret < 0);
+}
+]])],
+  [error_is_negative=NO],
+  [error_is_negative=YES]
+)
+
+if test "x$error_is_negative" = "xYES"; then
+    AC_DEFINE([NEGATIVE_HIST_ERROR],[1],
+                [Define if read_history returns a positive value on error])
+    AC_MSG_RESULT(negative)
+else
+    AC_MSG_RESULT(positive)
+fi
+
+
+
+])# CHECK_HIST_ERRORS
diff --git a/configure b/configure
--- a/configure
+++ b/configure
@@ -2493,35 +2493,61 @@
 fi
 
 
-HaveLibEdit=YES
 if test "x$HaveLibTermcap" = xYES ; then
-  LIBS="-l$LibTermcap $LIBS"
-
-echo "$as_me:$LINENO: checking for el_init in -ledit" >&5
-echo $ECHO_N "checking for el_init in -ledit... $ECHO_C" >&6
-if test "${ac_cv_lib_edit_el_init+set}" = set; then
+  HaveLibEdit=YES
+  LIBS="$LIBS -l$LibTermcap -ledit"
+  echo "$as_me:$LINENO: checking for el_init" >&5
+echo $ECHO_N "checking for el_init... $ECHO_C" >&6
+if test "${ac_cv_func_el_init+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-ledit  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
+/* Define el_init to an innocuous variant, in case <limits.h> declares el_init.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define el_init innocuous_el_init
 
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char el_init (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef el_init
+
 /* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
+{
 #endif
 /* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
 char el_init ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_el_init) || defined (__stub___el_init)
+choke me
+#else
+char (*f) () = el_init;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
 int
 main ()
 {
-el_init ();
+return f != el_init;
   ;
   return 0;
 }
@@ -2548,56 +2574,76 @@
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_edit_el_init=yes
+  ac_cv_func_el_init=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-ac_cv_lib_edit_el_init=no
+ac_cv_func_el_init=no
 fi
 rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_edit_el_init" >&5
-echo "${ECHO_T}$ac_cv_lib_edit_el_init" >&6
-if test $ac_cv_lib_edit_el_init = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBEDIT 1
-_ACEOF
-
-  LIBS="-ledit $LIBS"
-
+echo "$as_me:$LINENO: result: $ac_cv_func_el_init" >&5
+echo "${ECHO_T}$ac_cv_func_el_init" >&6
+if test $ac_cv_func_el_init = yes; then
+  :
 else
   HaveLibEdit=NO
 fi
 
-
-echo "$as_me:$LINENO: checking for readline in -ledit" >&5
-echo $ECHO_N "checking for readline in -ledit... $ECHO_C" >&6
-if test "${ac_cv_lib_edit_readline+set}" = set; then
+  echo "$as_me:$LINENO: checking for readline" >&5
+echo $ECHO_N "checking for readline... $ECHO_C" >&6
+if test "${ac_cv_func_readline+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-ledit  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
+/* Define readline to an innocuous variant, in case <limits.h> declares readline.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define readline innocuous_readline
 
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char readline (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef readline
+
 /* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
+{
 #endif
 /* We use char because int might match the return type of a gcc2
    builtin and then its argument prototype would still apply.  */
 char readline ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_readline) || defined (__stub___readline)
+choke me
+#else
+char (*f) () = readline;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
 int
 main ()
 {
-readline ();
+return f != readline;
   ;
   return 0;
 }
@@ -2624,32 +2670,27 @@
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_edit_readline=yes
+  ac_cv_func_readline=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-ac_cv_lib_edit_readline=no
+ac_cv_func_readline=no
 fi
 rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_edit_readline" >&5
-echo "${ECHO_T}$ac_cv_lib_edit_readline" >&6
-if test $ac_cv_lib_edit_readline = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBEDIT 1
-_ACEOF
-
-  LIBS="-ledit $LIBS"
-
+echo "$as_me:$LINENO: result: $ac_cv_func_readline" >&5
+echo "${ECHO_T}$ac_cv_func_readline" >&6
+if test $ac_cv_func_readline = yes; then
+  :
 else
   HaveLibEdit=NO
 fi
 
   EDITLINE_LIBS="edit $LibTermcap"
-  LIBS="$LIBS -ledit"
+else
+  HaveLibEdit=NO
 fi
 
 ac_ext=c
@@ -3142,7 +3183,8 @@
 
 
 
-for ac_header in editline/readline.h readline/readline.h
+
+for ac_header in editline/readline.h editline/editline.h readline/readline.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
 if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -3290,6 +3332,85 @@
 fi
 
 done
+
+
+
+echo "$as_me:$LINENO: checking for sign of read_history result on error" >&5
+echo $ECHO_N "checking for sign of read_history result on error... $ECHO_C" >&6
+if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#ifdef HAVE_EDITLINE_READLINE_H
+#include <editline/readline.h>
+#else
+#ifdef HAVE_READLINE_READLINE_H
+#include <readline/readline.h>
+#else
+#ifdef HAVE_EDITLINE_EDITLINE_H
+#include <editline/editline.h>
+#endif
+#endif
+#endif
+
+int main(void) {
+    int ret;
+    rl_initialize();
+    ret = read_history("this/should/not/be/valid");
+    return (ret < 0);
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  error_is_negative=NO
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+error_is_negative=YES
+
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+if test "x$error_is_negative" = "xYES"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define NEGATIVE_HIST_ERROR 1
+_ACEOF
+
+    echo "$as_me:$LINENO: result: negative" >&5
+echo "${ECHO_T}negative" >&6
+else
+    echo "$as_me:$LINENO: result: positive" >&5
+echo "${ECHO_T}positive" >&6
+fi
+
+
+
 
 
 if test "x$HaveLibEdit" = xYES ; then
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -31,17 +31,22 @@
     AC_CHECK_LIB(curses, tputs, HaveLibTermcap=YES; LibTermcap=curses,
       HaveLibTermcap=NO; LibTermcap=not-installed)))
 
-HaveLibEdit=YES
 if test "x$HaveLibTermcap" = xYES ; then
-  LIBS="-l$LibTermcap $LIBS"
-  AC_CHECK_LIB(edit, el_init, , HaveLibEdit=NO)
-  AC_CHECK_LIB(edit, readline, , HaveLibEdit=NO)
+  HaveLibEdit=YES
+  LIBS="$LIBS -l$LibTermcap -ledit"
+  AC_CHECK_FUNC(el_init, , HaveLibEdit=NO)
+  AC_CHECK_FUNC(readline, , HaveLibEdit=NO)
   EDITLINE_LIBS="edit $LibTermcap"
-  LIBS="$LIBS -ledit"
+else
+  HaveLibEdit=NO
 fi
 
-dnl Look for the equivalent of <readline.readline.h>
-AC_CHECK_HEADERS([editline/readline.h readline/readline.h], [break])
+dnl Look for the equivalent of <readline/readline.h>
+dnl Make sure to check <readline/readline.h> last, so that if both readline and
+dnl editline are installed, we'll pick the right one.
+AC_CHECK_HEADERS([editline/readline.h editline/editline.h readline/readline.h], [break])
+
+CHECK_HIST_ERRORS
 
 if test "x$HaveLibEdit" = xYES ; then
   BUILD_PACKAGE_BOOL=True
diff --git a/editline.cabal b/editline.cabal
--- a/editline.cabal
+++ b/editline.cabal
@@ -1,5 +1,5 @@
 name:		editline
-version:	0.1
+version:	0.2
 license:	BSD3
 license-file:	LICENSE
 maintainer:	Judah Jacobson <judah.jacobson@gmail.com>
@@ -16,8 +16,9 @@
                 readline package.
 homepage:       http://code.haskell.org/editline
 extra-source-files:
-		aclocal.m4 configure.ac configure
+		aclocal.m4 configure.ac
 		editline.buildinfo.in
+                configure include/HsEditlineConfig.h.in
 extra-tmp-files:
 		config.log config.status autom4te.cache
 		editline.buildinfo include/HsEditlineConfig.h
diff --git a/include/HsEditlineConfig.h b/include/HsEditlineConfig.h
--- a/include/HsEditlineConfig.h
+++ b/include/HsEditlineConfig.h
@@ -1,15 +1,15 @@
 /* include/HsEditlineConfig.h.  Generated by configure.  */
 /* include/HsEditlineConfig.h.in.  Generated from configure.ac by autoheader.  */
 
+/* Define to 1 if you have the <editline/editline.h> header file. */
+/* #undef HAVE_EDITLINE_EDITLINE_H */
+
 /* Define to 1 if you have the <editline/readline.h> header file. */
 /* #undef HAVE_EDITLINE_READLINE_H */
 
 /* Define to 1 if you have the <inttypes.h> header file. */
 #define HAVE_INTTYPES_H 1
 
-/* Define to 1 if you have the `edit' library (-ledit). */
-#define HAVE_LIBEDIT 1
-
 /* Define to 1 if you have the <memory.h> header file. */
 #define HAVE_MEMORY_H 1
 
@@ -36,6 +36,9 @@
 
 /* Define to 1 if you have the <unistd.h> header file. */
 #define HAVE_UNISTD_H 1
+
+/* Define if read_history returns a positive value on error */
+#define NEGATIVE_HIST_ERROR 1
 
 /* Define to the address where bug reports for this package should be sent. */
 #define PACKAGE_BUGREPORT "libraries@haskell.org"
diff --git a/include/HsEditlineConfig.h.in b/include/HsEditlineConfig.h.in
new file mode 100644
--- /dev/null
+++ b/include/HsEditlineConfig.h.in
@@ -0,0 +1,58 @@
+/* include/HsEditlineConfig.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the <editline/editline.h> header file. */
+#undef HAVE_EDITLINE_EDITLINE_H
+
+/* Define to 1 if you have the <editline/readline.h> header file. */
+#undef HAVE_EDITLINE_READLINE_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <readline/readline.h> header file. */
+#undef HAVE_READLINE_READLINE_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if read_history returns a positive value on error */
+#undef NEGATIVE_HIST_ERROR
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
