]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/qt-console/bcomm/dircomm.cpp
Fix bat seg fault
[bacula/bacula] / bacula / src / qt-console / bcomm / dircomm.cpp
index b0456456fce31a86988d95d453adf7ca3a8091ee..4e6e978f26729c96dc5d1e0d73fb7cded978f161 100644 (file)
@@ -1,12 +1,12 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2007-2010 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
    This program is Free Software; you can redistribute it and/or
-   modify it under the terms of version two of the GNU General Public
+   modify it under the terms of version three of the GNU Affero General Public
    License as published by the Free Software Foundation and included
    in the file LICENSE.
 
    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
+   You should have received a copy of the GNU Affero General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Bacula® is a registered trademark of John Walker.
+   Bacula® is a registered trademark of Kern Sibbald.
    The licensor of Bacula is the Free Software Foundation Europe
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 */
 /*
- *   Version $Id$
+ *  DirComm, Director communications,class
  *
- *  Bacula Communications class that is at a higher level than BSOCK
- *
- *   Kern Sibbald, May MMVII
+ *   Kern Sibbald, January MMVII
  *
  */ 
 
 #include "console.h"
 #include "restore.h"
 #include "select.h"
+#include "textinput.h"
 #include "run/run.h"
-#include "dircomm.h"
 
 static int tls_pem_callback(char *buf, int size, const void *userdata);
 
-
-DirComm::DirComm(Console *console)
+DirComm::DirComm(Console *parent, int conn):  m_notifier(NULL),  m_api_set(false)
 {
-   m_console = console;
+   m_console = parent;
    m_sock = NULL;
    m_at_prompt = false;
    m_at_main_prompt = false;
-   m_timer = NULL;
+   m_conn = conn;
+   m_in_command = 0;
+   m_in_select = false;
 }
 
 DirComm::~DirComm()
 {
-   if (m_timer) {
-      stopTimer();
-   }
-}
-
-void DirComm::startTimer()
-{
-   m_timer = new QTimer(m_console);
-   QWidget::connect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
-   m_timer->start(mainWin->m_checkMessagesInterval*1000);
-}
-
-void DirComm::stopTimer()
-{
-   if (m_timer) {
-      QWidget::disconnect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
-      m_timer->stop();
-      delete m_timer;
-      m_timer = NULL;
-   }
-}
-      
-void DirComm::poll_messages()
-{
-   m_messages_pending = true;
-   if ((m_at_main_prompt) && (mainWin->m_checkMessages)){
-      write(".messages");
-      displayToPrompt();
-   }
 }
 
 /* Terminate any open socket */
 void DirComm::terminate()
 {
    if (m_sock) {
-      stopTimer();
+      if (m_notifier) {
+         m_notifier->setEnabled(false);
+         delete m_notifier;
+         m_notifier = NULL;
+      }
+      if (mainWin->m_connDebug)
+         Pmsg2(000, "DirComm %i terminating connections %s\n", m_conn, m_console->m_dir->name());
       m_sock->close();
       m_sock = NULL;
    }
@@ -99,30 +75,43 @@ void DirComm::terminate()
 /*
  * Connect to Director. 
  */
-void DirComm::connect_dir(DIRRES *dir, CONRES *cons)
+bool DirComm::connect_dir()
 {
-   JCR jcr;
+   JCR *jcr = new JCR;
    utime_t heart_beat;
    char buf[1024];
+   CONRES *cons;
+      
+   buf[0] = 0;
 
-   m_dir = dir;
-   if (!m_dir) {          
-      mainWin->set_status("No Director found.");
-      return;
-   }
    if (m_sock) {
-      mainWin->set_status("Already connected.");
-      return;
+      mainWin->set_status( tr("Already connected."));
+      m_console->display_textf(_("Already connected\"%s\".\n"),
+            m_console->m_dir->name());
+      if (mainWin->m_connDebug) {
+         Pmsg2(000, "DirComm %i BAILING already connected %s\n", m_conn, m_console->m_dir->name());
+      }
+      goto bail_out;
    }
 
-   memset(&jcr, 0, sizeof(jcr));
+   if (mainWin->m_connDebug) {
+      Pmsg2(000, "DirComm %i connecting %s\n", m_conn, m_console->m_dir->name());
+   }
+   memset(jcr, 0, sizeof(JCR));
 
-   mainWin->set_statusf(_("Connecting to Director %s:%d"), m_dir->address, m_dir->DIRport);
-   m_console->display_textf(_("Connecting to Director %s:%d\n\n"), m_dir->address, m_dir->DIRport);
+   mainWin->set_statusf(_("Connecting to Director %s:%d"), m_console->m_dir->address, m_console->m_dir->DIRport);
+   if (m_conn == 0) {
+      m_console->display_textf(_("Connecting to Director %s:%d\n\n"), m_console->m_dir->address, m_console->m_dir->DIRport);
+   }
 
    /* Give GUI a chance */
    app->processEvents();
    
+   LockRes();
+   /* If cons==NULL, default console will be used */
+   cons = (CONRES *)GetNextRes(R_CONSOLE, NULL);
+   UnlockRes();
+
    /* Initialize Console TLS context once */
    if (cons && !cons->tls_ctx && (cons->tls_enable || cons->tls_require)) {
       /* Generate passphrase prompt */
@@ -139,34 +128,38 @@ void DirComm::connect_dir(DIRRES *dir, CONRES *cons)
 
       if (!cons->tls_ctx) {
          m_console->display_textf(_("Failed to initialize TLS context for Console \"%s\".\n"),
-            m_dir->name());
-         return;
+            m_console->m_dir->name());
+         if (mainWin->m_connDebug)
+            Pmsg2(000, "DirComm %i BAILING Failed to initialize TLS context for Console %s\n", m_conn, m_console->m_dir->name());
+         goto bail_out;
       }
    }
 
    /* Initialize Director TLS context once */
-   if (!m_dir->tls_ctx && (m_dir->tls_enable || m_dir->tls_require)) {
+   if (!m_console->m_dir->tls_ctx && (m_console->m_dir->tls_enable || m_console->m_dir->tls_require)) {
       /* Generate passphrase prompt */
       bsnprintf(buf, sizeof(buf), "Passphrase for Director \"%s\" TLS private key: ", 
-                m_dir->name());
+                m_console->m_dir->name());
 
       /* Initialize TLS context:
        * Args: CA certfile, CA certdir, Certfile, Keyfile,
        * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
-      m_dir->tls_ctx = new_tls_context(m_dir->tls_ca_certfile,
-                          m_dir->tls_ca_certdir, m_dir->tls_certfile,
-                          m_dir->tls_keyfile, tls_pem_callback, &buf, NULL, true);
+      m_console->m_dir->tls_ctx = new_tls_context(m_console->m_dir->tls_ca_certfile,
+                          m_console->m_dir->tls_ca_certdir, m_console->m_dir->tls_certfile,
+                          m_console->m_dir->tls_keyfile, tls_pem_callback, &buf, NULL, true);
 
-      if (!m_dir->tls_ctx) {
+      if (!m_console->m_dir->tls_ctx) {
          m_console->display_textf(_("Failed to initialize TLS context for Director \"%s\".\n"),
-            m_dir->name());
+            m_console->m_dir->name());
          mainWin->set_status("Connection failed");
-         return;
+         if (mainWin->m_connDebug)
+            Pmsg2(000, "DirComm %i BAILING Failed to initialize TLS context for Director %s\n", m_conn, m_console->m_dir->name());
+         goto bail_out;
       }
    }
 
-   if (m_dir->heartbeat_interval) {
-      heart_beat = m_dir->heartbeat_interval;
+   if (m_console->m_dir->heartbeat_interval) {
+      heart_beat = m_console->m_dir->heartbeat_interval;
    } else if (cons) {
       heart_beat = cons->heartbeat_interval;
    } else {
@@ -174,25 +167,32 @@ void DirComm::connect_dir(DIRRES *dir, CONRES *cons)
    }        
 
    m_sock = bnet_connect(NULL, 5, 15, heart_beat,
-                          _("Director daemon"), m_dir->address,
-                          NULL, m_dir->DIRport, 0);
+                          _("Director daemon"), m_console->m_dir->address,
+                          NULL, m_console->m_dir->DIRport, 0);
    if (m_sock == NULL) {
       mainWin->set_status("Connection failed");
-      return;
+      if (mainWin->m_connDebug)
+         Pmsg2(000, "DirComm %i BAILING Connection failed %s\n", m_conn, m_console->m_dir->name());
+      goto bail_out;
    } else {
       /* Update page selector to green to indicate that Console is connected */
       mainWin->actionConnect->setIcon(QIcon(":images/connected.png"));
       QBrush greenBrush(Qt::green);
-      QTreeWidgetItem *item = mainWin->getFromHash(this);
-      item->setForeground(0, greenBrush);
+      QTreeWidgetItem *item = mainWin->getFromHash(m_console);
+      if (item) {
+         item->setForeground(0, greenBrush);
+      }
    }
 
-   jcr.dir_bsock = m_sock;
+   jcr->dir_bsock = m_sock;
 
-   if (!authenticate_director(&jcr, m_dir, cons, buf, sizeof(buf))) {
+   if (!authenticate_director(jcr, m_console->m_dir, cons, buf, sizeof(buf))) {
       m_console->display_text(buf);
-      return;
+      if (mainWin->m_connDebug)
+         Pmsg2(000, "DirComm %i BAILING Connection failed %s\n", m_conn, m_console->m_dir->name());
+      goto bail_out;
    }
+
    if (buf[0]) {
       m_console->display_text(buf);
    }
@@ -202,72 +202,32 @@ void DirComm::connect_dir(DIRRES *dir, CONRES *cons)
 
    mainWin->set_status(_("Initializing ..."));
 
-   /* Set up input notifier */
+   /* 
+    * Set up input notifier
+    */
    m_notifier = new QSocketNotifier(m_sock->m_fd, QSocketNotifier::Read, 0);
    QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(read_dir(int)));
+   m_notifier->setEnabled(false);
 
-   mainWin->set_status(_("Connected"));
-   startTimer();                      /* start message timer */
-   return;
-}
+   write(".api 1");
+   m_api_set = true;
+   m_console->displayToPrompt(m_conn);
 
-bool DirComm::dir_cmd(QString &cmd, QStringList &results)
-{
-   return dir_cmd(cmd.toUtf8().data(), results);
-}
-
-/*
- * Send a command to the Director, and return the
- *  results in a QStringList.  
- */
-bool DirComm::dir_cmd(const char *cmd, QStringList &results)
-{
-   int stat;
-
-   notify(false);
-   write(cmd);
-   while ((stat = read()) > 0) {
-      if (mainWin->m_displayAll) m_console->display_text(msg());
-      strip_trailing_junk(msg());
-      results << msg();
-   }
-   notify(true);
-   discardToPrompt();
-   return true;              /* ***FIXME*** return any command error */
-}
+   m_console->beginNewCommand(m_conn);
 
-bool DirComm::sql_cmd(QString &query, QStringList &results)
-{
-   return sql_cmd(query.toUtf8().data(), results);
-}
-
-/*
- * Send an sql query to the Director, and return the
- *  results in a QStringList.  
- */
-bool DirComm::sql_cmd(const char *query, QStringList &results)
-{
-   int stat;
-   POOL_MEM cmd(PM_MESSAGE);
+   mainWin->set_status(_("Connected"));
 
-   if (!is_connectedGui()) {
-      return false;
+   if (mainWin->m_connDebug) {
+      Pmsg2(000, "Returning TRUE from DirComm->connect_dir : %i %s\n", m_conn, m_console->m_dir->name());
    }
+   return true;
 
-   notify(false);
-   
-   pm_strcpy(cmd, ".sql query=\"");
-   pm_strcat(cmd, query);
-   pm_strcat(cmd, "\"");
-   write(cmd.c_str());
-   while ((stat = read()) > 0) {
-      if (mainWin->m_displayAll) m_console->display_text(msg());
-      strip_trailing_junk(msg());
-      results << msg();
+bail_out:
+   if (mainWin->m_connDebug) {
+      Pmsg2(000, "Returning FALSE from DirComm->connect_dir : %i %s\n", m_conn, m_console->m_dir->name());
    }
-   notify(true);
-   discardToPrompt();
-   return true;              /* ***FIXME*** return any command error */
+   delete jcr;
+   return false;
 }
 
 /* 
@@ -281,24 +241,6 @@ char *DirComm::msg()
    return NULL;
 }
 
-/* Send a command to the Director */
-void DirComm::write_dir(const char *msg)
-{
-   if (m_sock) {
-      mainWin->set_status(_("Processing command ..."));
-      QApplication::setOverrideCursor(Qt::WaitCursor);
-      write(msg);
-   } else {
-      mainWin->set_status(" Director not connected. Click on connect button.");
-      mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
-      QBrush redBrush(Qt::red);
-      QTreeWidgetItem *item = mainWin->getFromHash(this);
-      item->setForeground(0, redBrush);
-      m_at_prompt = false;
-      m_at_main_prompt = false;
-   }
-}
-
 int DirComm::write(const QString msg)
 {
    return write(msg.toUtf8().data());
@@ -312,75 +254,53 @@ int DirComm::write(const char *msg)
    m_sock->msglen = pm_strcpy(m_sock->msg, msg);
    m_at_prompt = false;
    m_at_main_prompt = false;
-   if (mainWin->m_commDebug) Pmsg1(000, "send: %s\n", msg);
+   if (mainWin->m_commDebug) Pmsg2(000, "conn %i send: %s\n", m_conn, msg);
    return m_sock->send();
-
 }
 
-/*
- * Get to main command prompt -- i.e. abort any suDirCommand
- */
-void DirComm::beginNewCommand()
+int DirComm::sock_read()
 {
-   for (int i=0; i < 3; i++) {
-      write(".\n");
-      while (read() > 0) {
-         if (mainWin->m_displayAll) m_console->display_text(msg());
-      }
-      if (m_at_main_prompt) {
-         break;
-      }
-   }
-   m_console->display_text("\n");
-}
-
-void DirComm::displayToPrompt()
-{ 
-   int stat = 0;
-   if (mainWin->m_commDebug) Pmsg0(000, "DisplaytoPrompt\n");
-   while (!m_at_prompt) {
-      if ((stat=read()) > 0) {
-         m_console->display_text(msg());
-      }
-   }
-   if (mainWin->m_commDebug) Pmsg1(000, "endDisplaytoPrompt=%d\n", stat);
-}
-
-void DirComm::discardToPrompt()
-{ 
-   int stat = 0;
-   if (mainWin->m_commDebug) Pmsg0(000, "discardToPrompt\n");
-   while (!m_at_prompt) {
-      if ((stat=read()) > 0) {
-         if (mainWin->m_displayAll) m_console->display_text(msg());
-      }
-   }
-   if (mainWin->m_commDebug) Pmsg1(000, "endDisplayToPrompt=%d\n", stat);
+   int stat;
+#ifdef HAVE_WIN32
+   bool wasEnabled = notify(false);
+   stat = m_sock->recv();
+   notify(wasEnabled);
+#else
+   stat = m_sock->recv();
+#endif
+   return stat;
 }
 
-
 /* 
  * Blocking read from director
  */
 int DirComm::read()
 {
-   int stat = 0;
+   int stat = -1;
+
+   if (!m_sock) {
+      return -1;
+   }
    while (m_sock) {
       for (;;) {
-         stat = bnet_wait_data_intr(m_sock, 1);
+         if (!m_sock) break;
+         stat = m_sock->wait_data_intr(0, 50000);
          if (stat > 0) {
             break;
          } 
          app->processEvents();
-         if (m_api_set && m_messages_pending) {
-            write_dir(".messages");
-            m_messages_pending = false;
+         if (m_api_set && m_console->is_messagesPending() && is_notify_enabled() && m_console->hasFocus()) {
+            m_console->write_dir(m_conn, ".messages", false);
+            m_console->messagesPending(false);
          }
       }
+      if (!m_sock) {
+         return -1;
+      }
       m_sock->msg[0] = 0;
-      stat = m_sock->recv();
+      stat = sock_read();
       if (stat >= 0) {
-         if (mainWin->m_commDebug) Pmsg1(000, "got: %s\n", m_sock->msg);
+         if (mainWin->m_commDebug) Pmsg2(000, "conn %i got: %s\n", m_conn, m_sock->msg);
          if (m_at_prompt) {
             m_console->display_text("\n");
             m_at_prompt = false;
@@ -389,99 +309,125 @@ int DirComm::read()
       }
       switch (m_sock->msglen) {
       case BNET_MSGS_PENDING :
-         if (m_notifier->isEnabled()) {
-            if (mainWin->m_commDebug) Pmsg0(000, "MSGS PENDING\n");
-            write_dir(".messages");
-            displayToPrompt();
-            m_messages_pending = false;
+         if (is_notify_enabled() && m_console->hasFocus()) {
+            if (mainWin->m_commDebug) Pmsg1(000, "conn %i MSGS PENDING\n", m_conn);
+            m_console->write_dir(m_conn, ".messages", false);
+            m_console->displayToPrompt(m_conn);
+            m_console->messagesPending(false);
          }
-         m_messages_pending = true;
+         m_console->messagesPending(true);
          continue;
       case BNET_CMD_OK:
-         if (mainWin->m_commDebug) Pmsg0(000, "CMD OK\n");
+         if (mainWin->m_commDebug) Pmsg1(000, "conn %i CMD OK\n", m_conn);
          m_at_prompt = false;
          m_at_main_prompt = false;
+         if (--m_in_command < 0) {
+            m_in_command = 0;
+         }
          mainWin->set_status(_("Command completed ..."));
          continue;
       case BNET_CMD_BEGIN:
-         if (mainWin->m_commDebug) Pmsg0(000, "CMD BEGIN\n");
+         if (mainWin->m_commDebug) Pmsg1(000, "conn %i CMD BEGIN\n", m_conn);
          m_at_prompt = false;
          m_at_main_prompt = false;
+         m_in_command++;
          mainWin->set_status(_("Processing command ..."));
          continue;
       case BNET_MAIN_PROMPT:
-         if (mainWin->m_commDebug) Pmsg0(000, "MAIN PROMPT\n");
-         m_at_prompt = true;
-         m_at_main_prompt = true;
-         mainWin->set_status(_("At main prompt waiting for input ..."));
-         QApplication::restoreOverrideCursor();
+         if (mainWin->m_commDebug) Pmsg1(000, "conn %i MAIN PROMPT\n", m_conn);
+         if (!m_at_prompt && ! m_at_main_prompt) {
+            m_at_prompt = true;
+            m_at_main_prompt = true;
+            mainWin->set_status(_("At main prompt waiting for input ..."));
+         }
          break;
       case BNET_PROMPT:
-         if (mainWin->m_commDebug) Pmsg0(000, "PROMPT\n");
+         if (mainWin->m_commDebug) Pmsg2(000, "conn %i PROMPT m_in_select %i\n", m_conn, m_in_select);
          m_at_prompt = true;
          m_at_main_prompt = false;
          mainWin->set_status(_("At prompt waiting for input ..."));
-         QApplication::restoreOverrideCursor();
+         /***** FIXME *****/
+         /* commented out until the prompt communication issue with the director is resolved 
+          * This is where I call a new text input dialog class to prevent the connection issues
+          * when a text input is requited.
+          *   if (!m_in_select) {
+          *      new textInputDialog(m_console, m_conn);
+          *   }
+          */
          break;
       case BNET_CMD_FAILED:
-         if (mainWin->m_commDebug) Pmsg0(000, "CMD FAILED\n");
+         if (mainWin->m_commDebug) Pmsg1(000, "CMD FAILED\n", m_conn);
+         if (--m_in_command < 0) {
+            m_in_command = 0;
+         }
          mainWin->set_status(_("Command failed."));
-         QApplication::restoreOverrideCursor();
          break;
       /* We should not get this one */
       case BNET_EOD:
-         if (mainWin->m_commDebug) Pmsg0(000, "EOD\n");
+         if (mainWin->m_commDebug) Pmsg1(000, "conn %i EOD\n", m_conn);
          mainWin->set_status_ready();
-         QApplication::restoreOverrideCursor();
          if (!m_api_set) {
             break;
          }
          continue;
       case BNET_START_SELECT:
-         if (mainWin->m_commDebug) Pmsg0(000, "START SELECT\n");
-         new selectDialog(m_console);
+         if (mainWin->m_commDebug) Pmsg1(000, "conn %i START SELECT\n", m_conn);
+         m_in_select = true;
+         new selectDialog(m_console, m_conn);
+         m_in_select = false;
          break;
       case BNET_YESNO:
-         if (mainWin->m_commDebug) Pmsg0(000, "YESNO\n");
-         new yesnoPopUp(m_console);
+         if (mainWin->m_commDebug) Pmsg1(000, "conn %i YESNO\n", m_conn);
+         new yesnoPopUp(m_console, m_conn);
          break;
       case BNET_RUN_CMD:
-         if (mainWin->m_commDebug) Pmsg0(000, "RUN CMD\n");
-         new runCmdPage();
+         if (mainWin->m_commDebug) Pmsg1(000, "conn %i RUN CMD\n", m_conn);
+         new runCmdPage(m_conn);
+         break;
+      case BNET_START_RTREE:
+         if (mainWin->m_commDebug) Pmsg1(000, "conn %i START RTREE CMD\n", m_conn);
+         new restorePage(m_conn);
+         break;
+      case BNET_END_RTREE:
+         if (mainWin->m_commDebug) Pmsg1(000, "conn %i END RTREE CMD\n", m_conn);
          break;
       case BNET_ERROR_MSG:
-         if (mainWin->m_commDebug) Pmsg0(000, "ERROR MSG\n");
-         m_sock->recv();              /* get the message */
+         if (mainWin->m_commDebug) Pmsg1(000, "conn %i ERROR MSG\n", m_conn);
+         stat = sock_read();          /* get the message */
          m_console->display_text(msg());
-         QMessageBox::critical(this, "Error", msg(), QMessageBox::Ok);
+         QMessageBox::critical(m_console, "Error", msg(), QMessageBox::Ok);
+         m_console->beginNewCommand(m_conn);
+         mainWin->waitExit();
          break;
       case BNET_WARNING_MSG:
-         if (mainWin->m_commDebug) Pmsg0(000, "WARNING MSG\n");
-         m_sock->recv();              /* get the message */
-         m_console->display_text(msg());
-         QMessageBox::critical(this, "Warning", msg(), QMessageBox::Ok);
+         if (mainWin->m_commDebug) Pmsg1(000, "conn %i WARNING MSG\n", m_conn);
+         stat = sock_read();          /* get the message */
+         if (!m_console->m_warningPrevent) {
+            QMessageBox::critical(m_console, "Warning", msg(), QMessageBox::Ok);
+         }
          break;
       case BNET_INFO_MSG:
-         if (mainWin->m_commDebug) Pmsg0(000, "INFO MSG\n");
-         m_sock->recv();              /* get the message */
+         if (mainWin->m_commDebug) Pmsg1(000, "conn %i INFO MSG\n", m_conn);
+         stat = sock_read();          /* get the message */
          m_console->display_text(msg());
          mainWin->set_status(msg());
          break;
       }
       if (is_bnet_stop(m_sock)) {         /* error or term request */
-         if (mainWin->m_commDebug) Pmsg0(000, "BNET STOP\n");
-         stopTimer();
+         if (mainWin->m_commDebug) Pmsg1(000, "conn %i BNET STOP\n", m_conn);
+         m_console->stopTimer();
          m_sock->close();
          m_sock = NULL;
          mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
          QBrush redBrush(Qt::red);
-         QTreeWidgetItem *item = mainWin->getFromHash(this);
+         QTreeWidgetItem *item = mainWin->getFromHash(m_console);
          item->setForeground(0, redBrush);
-         m_notifier->setEnabled(false);
-         delete m_notifier;
-         m_notifier = NULL;
+         if (m_notifier) {
+            m_notifier->setEnabled(false);
+            delete m_notifier;
+            m_notifier = NULL;
+         }
          mainWin->set_status(_("Director disconnected."));
-         QApplication::restoreOverrideCursor();
          stat = BNET_HARDEOF;
       }
       break;
@@ -492,38 +438,49 @@ int DirComm::read()
 /* Called by signal when the Director has output for us */
 void DirComm::read_dir(int /* fd */)
 {
-   if (mainWin->m_commDebug) Pmsg0(000, "read_dir\n");
-   while (read() >= 0) {
-      m_console->display_text(msg());
+   int stat;
+   if (mainWin->m_commDebug) Pmsg1(000, "enter read_dir conn %i read_dir\n", m_conn);
+   stat = m_sock->wait_data(0, 5000);
+   if (stat > 0) {
+      if (mainWin->m_commDebug) Pmsg2(000, "read_dir conn %i stat=%d\n", m_conn, stat);
+      while (read() >= 0) {
+         m_console->display_text(msg());
+      }
    }
+   if (mainWin->m_commDebug) Pmsg2(000, "exit read_dir conn %i stat=%d\n", m_conn, stat);
 }
 
 /*
  * When the notifier is enabled, read_dir() will automatically be
  * called by the Qt event loop when ever there is any output 
- * from the Directory, and read_dir() will then display it on
+ * from the Director, and read_dir() will then display it on
  * the console.
  *
  * When we are in a bat dialog, we want to control *all* output
  * from the Directory, so we set notify to off.
  *    m_console->notifiy(false);
  */
-void DirComm::notify(bool enable) 
+bool DirComm::notify(bool enable) 
 { 
-   m_notifier->setEnabled(enable);   
+   bool prev_enabled = false;
+   if (m_notifier) {
+      prev_enabled = m_notifier->isEnabled();   
+      m_notifier->setEnabled(enable);
+      if (mainWin->m_connDebug) {
+         Pmsg3(000, "conn=%i notify=%d prev=%d\n", m_conn, enable, prev_enabled);
+      }
+   } else if (mainWin->m_connDebug)
+      Pmsg2(000, "m_notifier does not exist: %i %s\n", m_conn, m_console->m_dir->name());
+   return prev_enabled;
 }
 
-bool DirComm::is_connectedGui()
+bool DirComm::is_notify_enabled() const
 {
-   if (is_connected()) {
-      return true;
-   } else {
-      QString message("Director ");
-      message += " is curerntly disconnected\n  Please reconnect!!";
-      QMessageBox::warning(this, tr("Bat"),
-         tr(message.toUtf8().data()), QMessageBox::Ok );
-      return false;
+   bool enabled = false;
+   if (m_notifier) {
+      enabled = m_notifier->isEnabled();   
    }
+   return enabled;
 }
 
 /*
@@ -536,9 +493,8 @@ static int tls_pem_callback(char *buf, int size, const void *userdata)
    (void)size;
    (void)userdata;
 #ifdef HAVE_TLS
-   const char *prompt = (const char *)userdata;
 # if defined(HAVE_WIN32)
-   sendit(prompt);
+   //sendit(prompt);
    if (win32_cgets(buf, size) == NULL) {
       buf[0] = 0;
       return 0;
@@ -546,6 +502,7 @@ static int tls_pem_callback(char *buf, int size, const void *userdata)
       return strlen(buf);
    }
 # else
+   const char *prompt = (const char *)userdata;
    char *passwd;
 
    passwd = getpass(prompt);