]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Make libedit support optional
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 9 Nov 2021 15:37:17 +0000 (16:37 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 22 Dec 2021 08:30:43 +0000 (09:30 +0100)
pdns/dnsdist-console.cc
pdns/dnsdist.cc
pdns/dnsdistdist/configure.ac
pdns/dnsdistdist/m4/pdns_check_libedit.m4

index 7682d432a8b2ff0ae3045ffae039d08efc39bf01..5a7de283b03f019d7bb6678d053560bc3a88b81c 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
+#include "config.h"
 
 #include <fstream>
 // we need this to get the home directory of the current user
 #include <pwd.h>
 #include <thread>
 
+#ifdef HAVE_LIBEDIT
 #if defined (__OpenBSD__) || defined(__NetBSD__)
 // If this is not undeffed, __attribute__ wil be redefined by /usr/include/readline/rlstdc.h
 #undef __STRICT_ANSI__
@@ -33,6 +35,7 @@
 #else
 #include <editline/readline.h>
 #endif
+#endif /* HAVE_LIBEDIT */
 
 #include "ext/json11/json11.hpp"
 
@@ -108,6 +111,7 @@ static void feedConfigDelta(const std::string& line)
   g_confDelta.emplace_back(now, line);
 }
 
+#ifdef HAVE_LIBEDIT
 static string historyFile(const bool &ignoreHOME = false)
 {
   string ret;
@@ -127,6 +131,7 @@ static string historyFile(const bool &ignoreHOME = false)
   ret.append("/.dnsdist_history");
   return ret;
 }
+#endif /* HAVE_LIBEDIT */
 
 static bool getMsgLen32(int fd, uint32_t* len)
 {
@@ -245,12 +250,14 @@ void doClient(ComboAddress server, const std::string& command)
     return; 
   }
 
+#ifdef HAVE_LIBEDIT
   string histfile = historyFile();
   {
     ifstream history(histfile);
     string line;
-    while(getline(history, line))
+    while (getline(history, line)) {
       add_history(line.c_str());
+    }
   }
   ofstream history(histfile, std::ios_base::app);
   string lastline;
@@ -282,43 +289,79 @@ void doClient(ComboAddress server, const std::string& command)
       break;
     }
   }
+#else
+  errlog("Client mode requested but libedit support is not available");
+#endif /* HAVE_LIBEDIT */
   close(fd);
 }
 
+#ifdef HAVE_LIBEDIT
+static std::optional<std::string> getNextConsoleLine(ofstream& history, std::string& lastline)
+{
+  char* sline = readline("> ");
+  rl_bind_key('\t', rl_complete);
+  if (!sline) {
+    return std::nullopt;
+  }
+
+  string line(sline);
+  if (!line.empty() && line != lastline) {
+    add_history(sline);
+    history << sline <<endl;
+    history.flush();
+  }
+
+  lastline = line;
+  free(sline);
+
+  return line;
+}
+#else /* HAVE_LIBEDIT */
+static std::optional<std::string> getNextConsoleLine()
+{
+  std::string line;
+  if (!std::getline(std::cin, line)) {
+    return std::nullopt;
+  }
+  return line;
+}
+#endif /* HAVE_LIBEDIT */
+
 void doConsole()
 {
+#ifdef HAVE_LIBEDIT
   string histfile = historyFile(true);
   {
     ifstream history(histfile);
     string line;
-    while(getline(history, line))
+    while (getline(history, line)) {
       add_history(line.c_str());
+    }
   }
   ofstream history(histfile, std::ios_base::app);
   string lastline;
-  for(;;) {
-    char* sline = readline("> ");
-    rl_bind_key('\t',rl_complete);
-    if(!sline)
+#endif /* HAVE_LIBEDIT */
+
+  for (;;) {
+#ifdef HAVE_LIBEDIT
+    auto line = getNextConsoleLine(history, lastline);
+#else /* HAVE_LIBEDIT */
+    auto line = getNextConsoleLine();
+#endif /* HAVE_LIBEDIT */
+    if (!line) {
       break;
-
-    string line(sline);
-    if(!line.empty() && line != lastline) {
-      add_history(sline);
-      history << sline <<endl;
-      history.flush();
     }
-    lastline=line;
-    free(sline);
-    
-    if(line=="quit")
+
+    if (*line == "quit") {
       break;
-    if(line=="help" || line=="?")
-      line="help()";
+    }
+    if (*line == "help" || *line == "?") {
+      line = "help()";
+    }
 
     string response;
     try {
-      bool withReturn=true;
+      bool withReturn = true;
     retry:;
       try {
         auto lua = g_lua.lock();
@@ -333,8 +376,8 @@ void doConsole()
               std::unordered_map<string, double>
               >
             >
-          >(withReturn ? ("return "+line) : line);
-        if(ret) {
+          >(withReturn ? ("return "+*line) : *line);
+        if (ret) {
           if (const auto dsValue = boost::get<shared_ptr<DownstreamState>>(&*ret)) {
             if (*dsValue) {
               cout<<(*dsValue)->getName()<<endl;
@@ -348,7 +391,7 @@ void doConsole()
           else if (const auto strValue = boost::get<string>(&*ret)) {
             cout<<*strValue<<endl;
           }
-          else if(const auto um = boost::get<std::unordered_map<string, double> >(&*ret)) {
+          else if (const auto um = boost::get<std::unordered_map<string, double> >(&*ret)) {
             using namespace json11;
             Json::object o;
             for(const auto& v : *um)
@@ -357,42 +400,48 @@ void doConsole()
             cout<<out.dump()<<endl;
           }
         }
-        else 
+        else {
           cout << g_outputBuffer << std::flush;
-        if(!getLuaNoSideEffect())
-          feedConfigDelta(line);
+        }
+
+        if (!getLuaNoSideEffect()) {
+          feedConfigDelta(*line);
+        }
       }
-      catch(const LuaContext::SyntaxErrorException&) {
-        if(withReturn) {
+      catch (const LuaContext::SyntaxErrorException&) {
+        if (withReturn) {
           withReturn=false;
           goto retry;
         }
         throw;
       }
     }
-    catch(const LuaContext::WrongTypeException& e) {
+    catch (const LuaContext::WrongTypeException& e) {
       std::cerr<<"Command returned an object we can't print: "<<std::string(e.what())<<std::endl;
       // tried to return something we don't understand
     }
-    catch(const LuaContext::ExecutionErrorException& e) {
-      if(!strcmp(e.what(),"invalid key to 'next'"))
+    catch (const LuaContext::ExecutionErrorException& e) {
+      if (!strcmp(e.what(), "invalid key to 'next'")) {
         std::cerr<<"Error parsing parameters, did you forget parameter name?";
-      else
-        std::cerr << e.what(); 
+      }
+      else {
+        std::cerr << e.what();
+      }
+
       try {
         std::rethrow_if_nested(e);
 
         std::cerr << std::endl;
-      } catch(const std::exception& ne) {
+      } catch (const std::exception& ne) {
         // ne is the exception that was thrown from inside the lambda
         std::cerr << ": " << ne.what() << std::endl;
       }
-      catch(const PDNSException& ne) {
+      catch (const PDNSException& ne) {
         // ne is the exception that was thrown from inside the lambda
         std::cerr << ": " << ne.reason << std::endl;
       }
     }
-    catch(const std::exception& e) {
+    catch (const std::exception& e) {
       std::cerr << e.what() << std::endl;      
     }
   }
@@ -939,6 +988,8 @@ void controlThread(int fd, ComboAddress local)
 
 void clearConsoleHistory()
 {
+#ifdef HAVE_LIBEDIT
   clear_history();
+#endif /* HAVE_LIBEDIT */
   g_confDelta.clear();
 }
index d5eecce2d75c70843bc43d9a1ff794d0092a95d2..b3f61390fadb218cbdbc0de1f5005737b47cbb2d 100644 (file)
@@ -2240,10 +2240,12 @@ int main(int argc, char** argv)
   try {
     size_t udpBindsCount = 0;
     size_t tcpBindsCount = 0;
+#ifdef HAVE_LIBEDIT
 #ifndef DISABLE_COMPLETION
     rl_attempted_completion_function = my_completion;
     rl_completion_append_character = 0;
 #endif /* DISABLE_COMPLETION */
+#endif /* HAVE_LIBEDIT */
 
     signal(SIGPIPE, SIG_IGN);
     signal(SIGCHLD, SIG_IGN);
@@ -2384,6 +2386,9 @@ int main(int argc, char** argv)
 #ifdef HAVE_IPCIPHER
         cout<<"ipcipher ";
 #endif
+#ifdef HAVE_LIBEDIT
+        cout<<"libeditr ";
+#endif
 #ifdef HAVE_LIBSODIUM
         cout<<"libsodium ";
 #endif
index 65a44ac84057bf065c8d3a10a90d77b1a3b05536..35550f00668758abf34f4fd77378d31ae20c71ef 100644 (file)
@@ -24,7 +24,7 @@ CXXFLAGS="-g -O3 -Wall -Wextra -Wshadow -Wno-unused-parameter -Wmissing-declarat
 PDNS_WITH_LIBSODIUM
 PDNS_CHECK_DNSTAP([auto])
 PDNS_CHECK_RAGEL([dnslabeltext.cc], [www.dnsdist.org])
-PDNS_CHECK_LIBEDIT
+PDNS_WITH_LIBEDIT
 PDNS_CHECK_CLOCK_GETTIME
 
 PDNS_CHECK_OS
@@ -187,6 +187,10 @@ AS_IF([test "x$enable_ipcipher" != "xno"],
   [AC_MSG_NOTICE([ipcipher: yes])],
   [AC_MSG_NOTICE([ipcipher: no])]
 )
+AS_IF([test "x$LIBEDIT_LIBS" != "x"],
+  [AC_MSG_NOTICE([libedit: yes])],
+  [AC_MSG_NOTICE([libedit: no])]
+)
 AS_IF([test "x$LIBSODIUM_LIBS" != "x"],
   [AC_MSG_NOTICE([libsodium: yes])],
   [AC_MSG_NOTICE([libsodium: no])]
index 14fde4f0a7bfd0e06a33c5f7b1d945238a521794..841ff26ff83c8d9fb617ce21f216a627c3561c0a 100644 (file)
@@ -1,3 +1,31 @@
-AC_DEFUN([PDNS_CHECK_LIBEDIT], [
-  PKG_CHECK_MODULES([LIBEDIT], [libedit])
+AC_DEFUN([PDNS_WITH_LIBEDIT], [
+  AC_MSG_CHECKING([whether to link in libedit])
+  AC_ARG_WITH([libedit],
+    AS_HELP_STRING([--with-libedit], [enable libedit support @<:@default=yes@:>@]),
+    [with_libedit=$enableval],
+    [with_libedit=yes]
+  )
+  AC_MSG_RESULT([$with_libedit])
+
+  AS_IF([test "x$with_libedit" != "xno"], [
+    AS_IF([test "x$with_libedit" = "xyes" -o "x$with_libedit" = "xauto"], [
+      PKG_CHECK_MODULES([LIBEDIT], [libedit], [
+        [HAVE_LIBEDIT=1]
+        AC_DEFINE([HAVE_LIBEDIT], [1], [Define to 1 if you have libedit])
+        save_CFLAGS=$CFLAGS
+        save_LIBS=$LIBS
+        CFLAGS="$LIBEDIT_CFLAGS $CFLAGS"
+        LIBS="$LIBEDIT_LIBS $LIBS"
+        CFLAGS=$save_CFLAGS
+        LIBS=$save_LIBS
+
+      ], [ : ])
+    ])
+  ])
+  AM_CONDITIONAL([HAVE_LIBEDIT], [test "x$LIBEDIT_LIBS" != "x"])
+  AS_IF([test "x$with_libedit" = "xyes"], [
+    AS_IF([test x"$LIBEDIT_LIBS" = "x"], [
+      AC_MSG_ERROR([libedit support requested but library not found])
+    ])
+  ])
 ])