diff --git a/ndb/src/Makefile.am b/ndb/src/Makefile.am
index eb1cf1c6543133f23117ec63f1ee7920d5f32660..d35790a2e4365416d15f6925e6260e2290ac8854 100644
--- a/ndb/src/Makefile.am
+++ b/ndb/src/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = common mgmapi ndbapi . kernel mgmsrv mgmclient cw
+SUBDIRS = common mgmapi ndbapi . kernel mgmclient mgmsrv cw
 
 include $(top_srcdir)/ndb/config/common.mk.am
 
diff --git a/ndb/src/mgmsrv/CommandInterpreter.cpp b/ndb/src/mgmsrv/CommandInterpreter.cpp
deleted file mode 100644
index 686155415d58c61aaa058062a7285920d03c3914..0000000000000000000000000000000000000000
--- a/ndb/src/mgmsrv/CommandInterpreter.cpp
+++ /dev/null
@@ -1,345 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
-
-#include "CommandInterpreter.hpp"
-
-#include <string.h>
-#include <ctype.h>
-
-#include "MgmtSrvr.hpp"
-#include "MgmtErrorReporter.hpp"
-#include <NdbOut.hpp>
-#include "convertStrToInt.hpp"
-#include <EventLogger.hpp>
-#include <signaldata/SetLogLevelOrd.hpp>
-#include "ConfigInfo.hpp"
-
-#include <version.h>
-#include <m_string.h>
-
-//******************************************************************************
-//******************************************************************************
-CommandInterpreter::CommandInterpreter(MgmtSrvr& mgmtSrvr) :
-  _mgmtSrvr(mgmtSrvr) {
-}
-
-
-bool emptyString(const char* s) {
-  if (s == NULL) {
-    return true;
-  }
-
-  for (unsigned int i = 0; i < strlen(s); ++i) {
-    if (! isspace(s[i])) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-class AutoPtr {
-public:
-  AutoPtr(void * ptr) : m_ptr(ptr) {}
-  ~AutoPtr() { free(m_ptr);}
-private:
-  void * m_ptr;
-};
-
-const char *CommandInterpreter::get_error_text(int err_no)
-{
-  return _mgmtSrvr.getErrorText(err_no, m_err_str, sizeof(m_err_str));
-}
-
-//*****************************************************************************
-//*****************************************************************************
-int CommandInterpreter::readAndExecute() {
-
-  char* _line = readline_gets(); 
-  char * line;
-  if(_line == NULL) {
-    ndbout << endl;
-    return true;
-  }
-
-  line = strdup(_line);
-  
-  AutoPtr ptr(line);
-  
-  if (emptyString(line)) {
-    return true;
-  }
-  
-  for (unsigned int i = 0; i < strlen(line); ++i) {
-    line[i] = toupper(line[i]);
-  }
-
-  // if there is anything in the line proceed
-  char* firstToken = strtok(line, " ");
-  char* allAfterFirstToken = strtok(NULL, "\0");
-  
-  if (strcmp(firstToken, "ALL") == 0) {
-    analyseAfterFirstToken(-1, allAfterFirstToken);
-  } 
-  else if(strcmp(firstToken, "QUIT") == 0 ||
-	  strcmp(firstToken, "EXIT") == 0 ||
-	  strcmp(firstToken, "BYE") == 0){
-    return false;
-  } else {
-    // First token should be a digit, process ID
-    
-    int processId;
-    if (! convert(firstToken, processId)) {
-      ndbout << "Invalid command: " << _line << "." << endl;
-      return true;
-    }
-    if (processId < 0) {
-      ndbout << "Invalid process ID: " << firstToken << "." << endl;
-      return true;
-    }
-    
-    analyseAfterFirstToken(processId, allAfterFirstToken);
-    
-  } // else
-  return true;
-}
-
-
-static const CommandInterpreter::CommandFunctionPair commands[] = {
-  { "TRACE", &CommandInterpreter::executeTrace }
-  ,{ "LOGIN", &CommandInterpreter::executeLogIn }
-  ,{ "LOGOUT", &CommandInterpreter::executeLogOut }
-  ,{ "LOGOFF", &CommandInterpreter::executeLogOff }
-};
-
-
-//*****************************************************************************
-//*****************************************************************************
-void
-CommandInterpreter::analyseAfterFirstToken(int processId,
-					   char* allAfterFirstToken) {
-  
-  if (emptyString(allAfterFirstToken)) {
-    if (processId == -1) {
-      ndbout << "Expected a command after ALL." << endl;
-    }
-    else {
-      ndbout << "Expected a command after process ID." << endl;
-    }
-    return;
-  }
-  
-
-  char* secondToken = strtok(allAfterFirstToken, " ");
-  char* allAfterSecondToken = strtok(NULL, "\0");
-
-  const int tmpSize = sizeof(commands)/sizeof(CommandFunctionPair);
-  ExecuteFunction fun = 0;
-  const char * command = 0;
-  for(int i = 0; i<tmpSize; i++){
-    if(strcmp(secondToken, commands[i].command) == 0){
-      fun = commands[i].executeFunction;
-      command = commands[i].command;
-      break;
-    }
-  }
-  
-  if(fun == 0){
-    ndbout << "Invalid command: " << secondToken << "." << endl;
-    return;
-  }
-  
-  if(processId == -1){
-    executeForAll(command, fun, allAfterSecondToken);
-  } else {
-    ndbout << "Executing " << command << " on node: " 
-	   << processId << endl << endl;
-    (this->*fun)(processId, allAfterSecondToken, false);
-    ndbout << endl;
-  }
-}
-
-void
-CommandInterpreter::executeForAll(const char * cmd, ExecuteFunction fun, 
-				  const char * allAfterSecondToken){
-
-  NodeId nodeId = 0;
-  while(_mgmtSrvr.getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)){
-    ndbout << "Executing " << cmd << " on node: " 
-	   << nodeId << endl << endl;
-    (this->*fun)(nodeId, allAfterSecondToken, true);
-    ndbout << endl;
-  }
-}
-
-//*****************************************************************************
-//*****************************************************************************
-bool CommandInterpreter::parseBlockSpecification(const char* allAfterLog,
-						 Vector<BaseString>& blocks) {
-  
-  // Parse: [BLOCK = {ALL|<blockName>+}]
-
-  if (emptyString(allAfterLog)) {
-    return true;
-  }
-
-  // Copy allAfterLog since strtok will modify it  
-  char* newAllAfterLog = strdup(allAfterLog);
-  char* firstTokenAfterLog = strtok(newAllAfterLog, " ");
-  for (unsigned int i = 0; i < strlen(firstTokenAfterLog); ++i) {
-    firstTokenAfterLog[i] = toupper(firstTokenAfterLog[i]);
-  }
-  
-  if (strcmp(firstTokenAfterLog, "BLOCK") != 0) {
-    ndbout << "Unexpected value: " << firstTokenAfterLog 
-	   << ". Expected BLOCK." << endl;
-    free(newAllAfterLog);
-    return false;
-  }
-
-  char* allAfterFirstToken = strtok(NULL, "\0");
-  if (emptyString(allAfterFirstToken)) {
-    ndbout << "Expected =." << endl;
-    free(newAllAfterLog);
-    return false;
-  }
-
-  char* secondTokenAfterLog = strtok(allAfterFirstToken, " ");
-  if (strcmp(secondTokenAfterLog, "=") != 0) {
-    ndbout << "Unexpected value: " << secondTokenAfterLog 
-	   << ". Expected =." << endl;
-    free(newAllAfterLog);
-    return false;
-  }
-
-  char* blockName = strtok(NULL, " ");
-  bool all = false;
-  if (blockName != NULL && (strcmp(blockName, "ALL") == 0)) {
-    all = true;
-  }
-  while (blockName != NULL) {
-    blocks.push_back(BaseString(blockName));
-    blockName = strtok(NULL, " ");
-  }
-
-  if (blocks.size() == 0) {
-    ndbout << "No block specified." << endl;
-    free(newAllAfterLog);
-    return false;
-  }
-  if (blocks.size() > 1 && all) {
-    // More than "ALL" specified
-    ndbout << "Nothing expected after ALL." << endl;
-    free(newAllAfterLog);
-    return false;
-  }
-  
-  free(newAllAfterLog);
-  return true;
-}
-
-void CommandInterpreter::executeLogIn(int processId, 
-				      const char* parameters, bool all) {
-
-  (void)all;  // Don't want compiler warning
-
-  Vector<BaseString> blocks;
-  if (! parseBlockSpecification(parameters, blocks)) {
-    return;
-  }
-
-  int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::In, blocks);
-  if (result != 0) {
-    ndbout << get_error_text(result) << endl;
-  }
-}
-
-//******************************************************************************
-//******************************************************************************
-void CommandInterpreter::executeLogOut(int processId, 
-				       const char* parameters, bool all) {
-
-  (void)all;  // Don't want compiler warning
-
-  Vector<BaseString> blocks;
-  if (! parseBlockSpecification(parameters, blocks)) {
-    return;
-  }
-
-
-  int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::Out, blocks);
-  if (result != 0) {
-    ndbout << get_error_text(result) << endl;
-  }
-
-}
-
-
-//******************************************************************************
-//******************************************************************************
-void CommandInterpreter::executeLogOff(int processId, 
-				       const char* parameters, bool all) {
-
-  (void)all;  // Don't want compiler warning 
-
-  Vector<BaseString> blocks;
-  if (! parseBlockSpecification(parameters, blocks)) {
-    return;
-  }
-
-
-  int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::Off, blocks);
-  if (result != 0) {
-    ndbout << get_error_text(result) << endl;
-  }
-
-}
-
-void CommandInterpreter::executeTrace(int processId, 
-				      const char* parameters, bool all) {
-
-  (void)all;  // Don't want compiler warning
-
-  if (emptyString(parameters)) {
-    ndbout << "Missing trace number." << endl;
-    return;
-  }
-
-  char* newpar = strdup(parameters);
-  char* firstParameter = strtok(newpar, " ");
-
-
-  int traceNo;
-  if (! convert(firstParameter, traceNo)) {
-    ndbout << "Expected an integer." << endl;
-    free(newpar);
-    return;
-  }
-
-  char* allAfterFirstParameter = strtok(NULL, "\0");  
-
-  if (! emptyString(allAfterFirstParameter)) {
-    ndbout << "Nothing expected after trace number." << endl;
-    free(newpar);
-    return;
-  }
-
-  int result = _mgmtSrvr.setTraceNo(processId, traceNo);
-  if (result != 0) {
-    ndbout << get_error_text(result) << endl;
-  }
-  free(newpar);
-}
diff --git a/ndb/src/mgmsrv/CommandInterpreter.hpp b/ndb/src/mgmsrv/CommandInterpreter.hpp
deleted file mode 100644
index 6b67d1a5a5f432d0a5c45e19d11d0af12a236b48..0000000000000000000000000000000000000000
--- a/ndb/src/mgmsrv/CommandInterpreter.hpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
-
-#ifndef CommandInterpreter_H
-#define CommandInterpreter_H
-
-#include <ndb_global.h>
-#include <Vector.hpp>
-#include <BaseString.hpp>
-
-class MgmtSrvr;
-
-class CommandInterpreter {
-public:
-  CommandInterpreter(MgmtSrvr& mgmtSrvr);
-  int readAndExecute();
-
-private:
-  char m_err_str[1024];
-  const char *get_error_text(int err_no);
-
-  char *readline_gets ()
-  {
-    static char linebuffer[254];
-    static char *line_read = (char *)NULL;
-
-    /* If the buffer has already been allocated, return the memory
-       to the free pool. */
-    if (line_read)
-    {
-      free (line_read);
-      line_read = (char *)NULL;
-    }
-    
-    /* Get a line from the user. */
-    fputs("ndb_mgmd> ", stdout);
-    linebuffer[sizeof(linebuffer)-1]=0;
-    line_read = fgets(linebuffer, sizeof(linebuffer)-1, stdin);
-    if (line_read == linebuffer) {
-      char *q=linebuffer;
-      while (*q > 31) q++;
-      *q=0;
-      line_read= strdup(linebuffer);
-    }
-    return (line_read);
-  }
-  
-  void analyseAfterFirstToken(int processId, char* allAfterFirstTokenCstr);
-  bool parseBlockSpecification(const char* allAfterLog, 
-			       Vector<BaseString>& blocks);
-
-public:
-  void executeTrace(int processId, const char* parameters, bool all);
-  void executeLogIn(int processId, const char* parameters, bool all);
-  void executeLogOut(int processId, const char* parameters, bool all);
-  void executeLogOff(int processId, const char* parameters, bool all);
-
-public:
-  typedef void (CommandInterpreter::* ExecuteFunction)(int processId, 
-						       const char * param, 
-						       bool all);
-  
-  struct CommandFunctionPair {
-    const char * command;
-    ExecuteFunction executeFunction;
-  };
-private:
-  /**
-   * 
-   */
-  void executeForAll(const char * cmd, ExecuteFunction fun, const char * param);
-
-  /**
-   *   Management server to use when executing commands
-   */
-  MgmtSrvr& _mgmtSrvr; 
-};
-
-#endif // CommandInterpreter_H
diff --git a/ndb/src/mgmsrv/Makefile.am b/ndb/src/mgmsrv/Makefile.am
index 50e0b6023adf2a629f48ef717ea66776b3c17e66..7fd3fa66b434738a7e7dd314cd0450605d23b346 100644
--- a/ndb/src/mgmsrv/Makefile.am
+++ b/ndb/src/mgmsrv/Makefile.am
@@ -16,17 +16,20 @@ ndb_mgmd_SOURCES = \
 	MgmtSrvrConfig.cpp \
 	ConfigInfo.cpp \
 	InitConfigFileParser.cpp \
-	Config.cpp \
-	CommandInterpreter.cpp
+	Config.cpp
 
 INCLUDES_LOC = -I$(top_srcdir)/ndb/src/ndbapi \
                -I$(top_srcdir)/ndb/src/mgmapi \
-               -I$(top_srcdir)/ndb/src/common/mgmcommon
+               -I$(top_srcdir)/ndb/src/common/mgmcommon \
+               -I$(top_srcdir)/ndb/src/mgmclient
 
-LDADD_LOC = $(top_builddir)/ndb/src/libndbclient.la \
+LDADD_LOC = $(top_srcdir)/ndb/src/mgmclient/CommandInterpreter.o \
+            $(top_builddir)/ndb/src/libndbclient.la \
             $(top_builddir)/dbug/libdbug.a \
             $(top_builddir)/mysys/libmysys.a \
-            $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@
+            $(top_builddir)/strings/libmystrings.a \
+            @readline_link@ \
+            @NDB_SCI_LIBS@ \
 	    @TERMCAP_LIB@
 
 DEFS_LOC =		-DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp
index a638b85426e6ff5acf98402505dfce799e0af354..482bc2e89cc02f4bc76ba994c6a13ece915103ee 100644
--- a/ndb/src/mgmsrv/main.cpp
+++ b/ndb/src/mgmsrv/main.cpp
@@ -40,7 +40,7 @@
 #if defined NDB_OSE || defined NDB_SOFTOSE
 #include <efs.h>
 #else
-#include "CommandInterpreter.hpp"
+#include <ndb_mgmclient.hpp>
 #endif
 
 #undef DEBUG
@@ -48,11 +48,54 @@
 
 const char progname[] = "mgmtsrvr";
 
+// copied from mysql.cc to get readline
+extern "C" {
+#if defined( __WIN__) || defined(OS2)
+#include <conio.h>
+#elif !defined(__NETWARE__)
+#include <readline/readline.h>
+extern "C" int add_history(const char *command); /* From readline directory */
+#define HAVE_READLINE
+#endif
+}
+
+static int 
+read_and_execute(Ndb_mgmclient* com, const char * prompt, int _try_reconnect) 
+{
+  static char *line_read = (char *)NULL;
+
+  /* If the buffer has already been allocated, return the memory
+     to the free pool. */
+  if (line_read)
+  {
+    free (line_read);
+    line_read = (char *)NULL;
+  }
+#ifdef HAVE_READLINE
+  /* Get a line from the user. */
+  line_read = readline (prompt);    
+  /* If the line has any text in it, save it on the history. */
+  if (line_read && *line_read)
+    add_history (line_read);
+#else
+  static char linebuffer[254];
+  fputs(prompt, stdout);
+  linebuffer[sizeof(linebuffer)-1]=0;
+  line_read = fgets(linebuffer, sizeof(linebuffer)-1, stdin);
+  if (line_read == linebuffer) {
+    char *q=linebuffer;
+    while (*q > 31) q++;
+    *q=0;
+    line_read= strdup(linebuffer);
+  }
+#endif
+  return com->execute(line_read,_try_reconnect);
+}
 
 /**
  * @struct  MgmGlobals
  * @brief   Global Variables used in the management server
- ******************************************************************************/
+ *****************************************************************************/
 struct MgmGlobals {
   MgmGlobals();
   ~MgmGlobals();
@@ -297,14 +340,19 @@ int main(int argc, char** argv)
 
 #if ! defined NDB_OSE && ! defined NDB_SOFTOSE
   if(glob.interactive) {
-    CommandInterpreter com(* glob.mgmObject);
-    while(com.readAndExecute());
+    BaseString con_str;
+    if(glob.interface_name)
+      con_str.appfmt("host=%s:%d", glob.interface_name, glob.port);
+    else 
+      con_str.appfmt("localhost:%d", glob.port);
+    Ndb_mgmclient com(con_str.c_str(), 1);
+    while(g_StopServer != true && read_and_execute(&com, "ndb_mgm> ", 1));
   } else 
 #endif
-    {
-      while(g_StopServer != true)
-	NdbSleep_MilliSleep(500);
-    }
+  {
+    while(g_StopServer != true)
+      NdbSleep_MilliSleep(500);
+  }
   
   g_eventLogger.info("Shutting down server...");
   glob.socketServer->stopServer();