X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fqt-console%2Fbcomm%2Fdircomm.cpp;h=94ddd6d105b48669cabe8d90f22e6351c3181012;hb=5fa10ef8ba78dada465c587779130fbce964e0d9;hp=700d53dc1503f2500fb0c1a132aaccc6a8400986;hpb=e7b8010c6b0e188759e133209420ad9e7128f7e6;p=bacula%2Fbacula diff --git a/bacula/src/qt-console/bcomm/dircomm.cpp b/bacula/src/qt-console/bcomm/dircomm.cpp index 700d53dc15..94ddd6d105 100644 --- a/bacula/src/qt-console/bcomm/dircomm.cpp +++ b/bacula/src/qt-console/bcomm/dircomm.cpp @@ -1,12 +1,12 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2007-2009 Free Software Foundation Europe e.V. + Copyright (C) 2007-2011 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. @@ -15,7 +15,7 @@ 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. @@ -26,9 +26,7 @@ Switzerland, email:ftf@fsfeurope.org. */ /* - * Version $Id$ - * - * Console Class + * DirComm, Director communications,class * * Kern Sibbald, January MMVII * @@ -38,6 +36,7 @@ #include "console.h" #include "restore.h" #include "select.h" +#include "textinput.h" #include "run/run.h" static int tls_pem_callback(char *buf, int size, const void *userdata); @@ -48,8 +47,11 @@ DirComm::DirComm(Console *parent, int conn): m_notifier(NULL), m_api_set(false m_sock = NULL; m_at_prompt = false; m_at_main_prompt = false; + m_sent_blank = false; m_conn = conn; m_in_command = 0; + m_in_select = false; + m_notify = false; } DirComm::~DirComm() @@ -64,6 +66,7 @@ void DirComm::terminate() m_notifier->setEnabled(false); delete m_notifier; m_notifier = NULL; + m_notify = false; } if (mainWin->m_connDebug) Pmsg2(000, "DirComm %i terminating connections %s\n", m_conn, m_console->m_dir->name()); @@ -88,15 +91,19 @@ bool DirComm::connect_dir() mainWin->set_status( tr("Already connected.")); m_console->display_textf(_("Already connected\"%s\".\n"), m_console->m_dir->name()); - if (mainWin->m_connDebug) + if (mainWin->m_connDebug) { Pmsg2(000, "DirComm %i BAILING already connected %s\n", m_conn, m_console->m_dir->name()); + } goto bail_out; } + 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_console->m_dir->address, m_console->m_dir->DIRport); - m_console->display_textf(_("Connecting to Director %s:%d\n\n"), 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(); @@ -123,8 +130,9 @@ bool DirComm::connect_dir() if (!cons->tls_ctx) { m_console->display_textf(_("Failed to initialize TLS context for Console \"%s\".\n"), m_console->m_dir->name()); - if (mainWin->m_connDebug) + 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; } } @@ -146,8 +154,9 @@ bool DirComm::connect_dir() m_console->display_textf(_("Failed to initialize TLS context for Director \"%s\".\n"), m_console->m_dir->name()); mainWin->set_status("Connection failed"); - if (mainWin->m_connDebug) + 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; } } @@ -165,23 +174,27 @@ bool DirComm::connect_dir() NULL, m_console->m_dir->DIRport, 0); if (m_sock == NULL) { mainWin->set_status("Connection failed"); - if (mainWin->m_connDebug) + 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(m_console); - item->setForeground(0, greenBrush); + if (item) { + item->setForeground(0, greenBrush); + } } jcr->dir_bsock = m_sock; if (!authenticate_director(jcr, m_console->m_dir, cons, buf, sizeof(buf))) { m_console->display_text(buf); - if (mainWin->m_connDebug) + if (mainWin->m_connDebug) { Pmsg2(000, "DirComm %i BAILING Connection failed %s\n", m_conn, m_console->m_dir->name()); + } goto bail_out; } @@ -194,11 +207,13 @@ bool DirComm::connect_dir() mainWin->set_status(_("Initializing ...")); -#ifndef HAVE_WIN32 - /* 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))); -#endif + QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(notify_read_dir(int))); + m_notifier->setEnabled(true); + m_notify = true; write(".api 1"); m_api_set = true; @@ -208,13 +223,15 @@ bool DirComm::connect_dir() mainWin->set_status(_("Connected")); - if (mainWin->m_connDebug) + if (mainWin->m_connDebug) { Pmsg2(000, "Returning TRUE from DirComm->connect_dir : %i %s\n", m_conn, m_console->m_dir->name()); + } return true; bail_out: - if (mainWin->m_connDebug) + if (mainWin->m_connDebug) { Pmsg2(000, "Returning FALSE from DirComm->connect_dir : %i %s\n", m_conn, m_console->m_dir->name()); + } delete jcr; return false; } @@ -244,6 +261,19 @@ int DirComm::write(const char *msg) m_at_prompt = false; m_at_main_prompt = false; if (mainWin->m_commDebug) Pmsg2(000, "conn %i send: %s\n", m_conn, msg); + /* + * Ensure we send only one blank line. Multiple blank lines are + * simply discarded, it keeps the console output looking nicer. + */ + if (m_sock->msglen == 0 || (m_sock->msglen == 1 && *m_sock->msg == '\n')) { + if (!m_sent_blank) { + m_sent_blank = true; + return m_sock->send(); + } else { + return -1; /* discard multiple blanks */ + } + } + m_sent_blank = false; /* clear flag */ return m_sock->send(); } @@ -279,8 +309,9 @@ int DirComm::read() } app->processEvents(); if (m_api_set && m_console->is_messagesPending() && is_notify_enabled() && m_console->hasFocus()) { - m_console->write_dir(m_conn, ".messages", false); + if (mainWin->m_commDebug) Pmsg1(000, "conn %i process_events\n", m_conn); m_console->messagesPending(false); + m_console->write_dir(m_conn, ".messages", false); } } if (!m_sock) { @@ -299,10 +330,11 @@ int DirComm::read() switch (m_sock->msglen) { case BNET_MSGS_PENDING : if (is_notify_enabled() && m_console->hasFocus()) { + m_console->messagesPending(false); 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); + continue; } m_console->messagesPending(true); continue; @@ -310,9 +342,7 @@ int DirComm::read() if (mainWin->m_commDebug) Pmsg1(000, "conn %i CMD OK\n", m_conn); m_at_prompt = false; m_at_main_prompt = false; -// Pmsg1(000, "before dec m_in_command=%d\n", m_in_command); if (--m_in_command < 0) { -// Pmsg0(000, "m_in_command < 0\n"); m_in_command = 0; } mainWin->set_status(_("Command completed ...")); @@ -322,21 +352,35 @@ int DirComm::read() m_at_prompt = false; m_at_main_prompt = false; m_in_command++; -// Pmsg1(000, "after inc m_in_command=%d\n", m_in_command); mainWin->set_status(_("Processing command ...")); continue; case BNET_MAIN_PROMPT: if (mainWin->m_commDebug) Pmsg1(000, "conn %i MAIN PROMPT\n", m_conn); - m_at_prompt = true; - m_at_main_prompt = true; - mainWin->set_status(_("At main prompt waiting for input ...")); + 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) Pmsg1(000, "conn %i PROMPT\n", m_conn); + case BNET_SUB_PROMPT: + if (mainWin->m_commDebug) Pmsg2(000, "conn %i SUB_PROMPT m_in_select=%d\n", m_conn, m_in_select); m_at_prompt = true; m_at_main_prompt = false; mainWin->set_status(_("At prompt waiting for input ...")); break; + case BNET_TEXT_INPUT: + if (mainWin->m_commDebug) Pmsg4(000, "conn %i TEXT_INPUT at_prompt=%d m_in_select=%d notify=%d\n", + m_conn, m_at_prompt, m_in_select, is_notify_enabled()); + if (!m_in_select && is_notify_enabled()) { + mainWin->waitExit(); + new textInputDialog(m_console, m_conn); + } else { + if (mainWin->m_commDebug) Pmsg0(000, "!m_in_select && is_notify_enabled\n"); + m_at_prompt = true; + m_at_main_prompt = false; + mainWin->set_status(_("At prompt waiting for input ...")); + } + break; case BNET_CMD_FAILED: if (mainWin->m_commDebug) Pmsg1(000, "CMD FAILED\n", m_conn); if (--m_in_command < 0) { @@ -354,7 +398,9 @@ int DirComm::read() continue; case BNET_START_SELECT: if (mainWin->m_commDebug) Pmsg1(000, "conn %i START SELECT\n", m_conn); - new selectDialog(m_console); + m_in_select = true; + new selectDialog(m_console, m_conn); + m_in_select = false; break; case BNET_YESNO: if (mainWin->m_commDebug) Pmsg1(000, "conn %i YESNO\n", m_conn); @@ -376,12 +422,15 @@ int DirComm::read() stat = sock_read(); /* get the message */ m_console->display_text(msg()); QMessageBox::critical(m_console, "Error", msg(), QMessageBox::Ok); + m_console->beginNewCommand(m_conn); + mainWin->waitExit(); break; case BNET_WARNING_MSG: if (mainWin->m_commDebug) Pmsg1(000, "conn %i WARNING MSG\n", m_conn); stat = sock_read(); /* get the message */ - m_console->display_text(msg()); - QMessageBox::critical(m_console, "Warning", msg(), QMessageBox::Ok); + if (!m_console->m_warningPrevent) { + QMessageBox::critical(m_console, "Warning", msg(), QMessageBox::Ok); + } break; case BNET_INFO_MSG: if (mainWin->m_commDebug) Pmsg1(000, "conn %i INFO MSG\n", m_conn); @@ -390,6 +439,11 @@ int DirComm::read() mainWin->set_status(msg()); break; } + + if (!m_sock) { + stat = BNET_HARDEOF; + return stat; + } if (is_bnet_stop(m_sock)) { /* error or term request */ if (mainWin->m_commDebug) Pmsg1(000, "conn %i BNET STOP\n", m_conn); m_console->stopTimer(); @@ -403,9 +457,9 @@ int DirComm::read() m_notifier->setEnabled(false); delete m_notifier; m_notifier = NULL; + m_notify = false; } mainWin->set_status(_("Director disconnected.")); -// QApplication::restoreOverrideCursor(); stat = BNET_HARDEOF; } break; @@ -414,47 +468,52 @@ int DirComm::read() } /* Called by signal when the Director has output for us */ -void DirComm::read_dir(int /* fd */) +void DirComm::notify_read_dir(int /* fd */) { - if (mainWin->m_commDebug) Pmsg1(000, "conn %i read_dir\n", m_conn); - while (read() >= 0) { - m_console->display_text(msg()); + int stat; + if (!mainWin->m_notify) { + return; + } + 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); + * m_console->notify(false); */ bool DirComm::notify(bool enable) { bool prev_enabled = false; + /* Set global flag */ + mainWin->m_notify = enable; if (m_notifier) { prev_enabled = m_notifier->isEnabled(); m_notifier->setEnabled(enable); - if (mainWin->m_connDebug) { - if (prev_enabled && !enable) - Pmsg2(000, "m_notifier Disabling notifier: %i %s\n", m_conn, m_console->m_dir->name()); - else if (!prev_enabled && enable) - Pmsg2(000, "m_notifier Enabling notifier: %i %s\n", m_conn, m_console->m_dir->name()); - } - } else if (mainWin->m_connDebug) + m_notify = enable; + if (mainWin->m_connDebug) Pmsg3(000, "conn=%i set_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_notify_enabled() const { - bool enabled = false; - if (m_notifier) - enabled = m_notifier->isEnabled(); - return enabled; + return m_notify; } /* @@ -467,7 +526,6 @@ 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); if (win32_cgets(buf, size) == NULL) { @@ -477,6 +535,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);