2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation plus additions
11 that are listed in the file LICENSE.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
33 * Kern Sibbald, January MMVII
37 #include <QAbstractEventDispatcher>
41 Console::Console(QStackedWidget *parent)
50 m_textEdit = textEdit; /* our console screen */
51 m_cursor = new QTextCursor(m_textEdit->document());
52 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
55 /* Check for messages every 5 seconds */
56 // m_timer = new QTimer(this);
57 // QWidget::connect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
58 // m_timer->start(5000);
65 void Console::poll_messages()
67 m_messages_pending = true;
70 /* Terminate any open socket */
71 void Console::terminate()
81 * Connect to Director. If there are more than one, put up
82 * a modal dialog so that the user chooses one.
84 void Console::connect()
88 m_textEdit = textEdit; /* our console screen */
91 mainWin->set_status("No Director found.");
95 mainWin->set_status("Already connected.");
99 memset(&jcr, 0, sizeof(jcr));
101 mainWin->set_statusf(_("Connecting to Director %s:%d"), m_dir->address, m_dir->DIRport);
102 display_textf(_("Connecting to Director %s:%d\n\n"), m_dir->address, m_dir->DIRport);
104 /* Give GUI a chance */
105 app->processEvents();
108 /* If cons==NULL, default console will be used */
109 CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
112 m_sock = bnet_connect(NULL, 5, 15, _("Director daemon"), m_dir->address,
113 NULL, m_dir->DIRport, 0);
114 if (m_sock == NULL) {
115 mainWin->set_status("Connection failed");
118 /* Update page selector to green to indicate that Console is connected */
119 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/connected.png")));
120 QBrush greenBrush(Qt::green);
121 m_treeItem->setForeground(0, greenBrush);
124 jcr.dir_bsock = m_sock;
126 if (!authenticate_director(&jcr, m_dir, cons)) {
127 display_text(m_sock->msg);
131 /* Give GUI a chance */
132 app->processEvents();
134 mainWin->set_status(_("Initializing ..."));
136 /* Set up input notifier */
137 m_notifier = new QSocketNotifier(m_sock->fd, QSocketNotifier::Read, 0);
138 QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(read_dir(int)));
144 dir_cmd(".jobs", job_list);
145 dir_cmd(".clients", client_list);
146 dir_cmd(".filesets", fileset_list);
147 dir_cmd(".messages", messages_list);
148 dir_cmd(".pools", pool_list);
149 dir_cmd(".storage", storage_list);
150 dir_cmd(".types", type_list);
151 dir_cmd(".levels", level_list);
153 mainWin->set_status(_("Connected"));
157 bool Console::dir_cmd(const char *cmd, QStringList &results)
163 while ((stat = read()) > 0) {
164 strip_trailing_junk(msg());
169 return true; /* ***FIXME*** return any command error */
174 * Send a job name to the director, and read all the resulting
177 bool Console::get_job_defaults(struct job_defaults &job_defs)
185 scmd = QString(".defaults job=\"%1\"").arg(job_defs.job_name);
187 while ((stat = read()) > 0) {
188 def = strchr(msg(), '=');
192 /* Pointer to default value */
194 strip_trailing_junk(def);
196 if (strcmp(msg(), "job") == 0) {
197 if (strcmp(def, job_defs.job_name.toUtf8().data()) != 0) {
202 if (strcmp(msg(), "pool") == 0) {
203 job_defs.pool_name = def;
206 if (strcmp(msg(), "messages") == 0) {
207 job_defs.messages_name = def;
210 if (strcmp(msg(), "client") == 0) {
211 job_defs.client_name = def;
214 if (strcmp(msg(), "storage") == 0) {
215 job_defs.store_name = def;
218 if (strcmp(msg(), "where") == 0) {
219 job_defs.where = def;
222 if (strcmp(msg(), "level") == 0) {
223 job_defs.level = def;
226 if (strcmp(msg(), "type") == 0) {
230 if (strcmp(msg(), "fileset") == 0) {
231 job_defs.fileset_name = def;
234 if (strcmp(msg(), "catalog") == 0) {
235 job_defs.catalog_name = def;
238 if (strcmp(msg(), "enabled") == 0) {
239 job_defs.enabled = *def == '1' ? true : false;
245 bsnprintf(cmd, sizeof(cmd), "job=%s pool=%s client=%s storage=%s where=%s\n"
246 "level=%s type=%s fileset=%s catalog=%s enabled=%d\n",
247 job_defs.job_name.toUtf8().data(), job_defs.pool_name.toUtf8().data(),
248 job_defs.client_name.toUtf8().data(),
249 job_defs.pool_name.toUtf8().data(), job_defs.messages_name.toUtf8().data(),
250 job_defs.store_name.toUtf8().data(),
251 job_defs.where.toUtf8().data(), job_defs.level.toUtf8().data(),
252 job_defs.type.toUtf8().data(), job_defs.fileset_name.toUtf8().data(),
253 job_defs.catalog_name.toUtf8().data(), job_defs.enabled);
266 * Save user settings associated with this console
268 void Console::writeSettings()
270 QFont font = get_font();
272 QSettings settings("bacula.org", "bat");
273 /* ***FIXME*** make console name unique */
274 settings.beginGroup("Console");
275 settings.setValue("consoleFont", font.family());
276 settings.setValue("consolePointSize", font.pointSize());
277 settings.setValue("consoleFixedPitch", font.fixedPitch());
282 * Read and restore user settings associated with this console
284 void Console::readSettings()
286 QFont font = get_font();
288 QSettings settings("bacula.org", "bat");
289 settings.beginGroup("Console");
290 font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
291 font.setPointSize(settings.value("consolePointSize", 10).toInt());
292 font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
294 m_textEdit->setFont(font);
298 * Set the console textEdit font
300 void Console::set_font()
303 QFont font = QFontDialog::getFont(&ok, QFont(m_textEdit->font()), this);
305 m_textEdit->setFont(font);
310 * Get the console text edit font
312 const QFont Console::get_font()
314 return m_textEdit->font();
318 void Console::status_dir()
320 write_dir("status dir\n");
325 * Put text into the console window
327 void Console::display_textf(const char *fmt, ...)
332 va_start(arg_ptr, fmt);
333 len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
338 void Console::display_text(const QString buf)
340 m_cursor->movePosition(QTextCursor::End);
341 m_cursor->insertText(buf);
345 void Console::display_text(const char *buf)
347 m_cursor->movePosition(QTextCursor::End);
348 m_cursor->insertText(buf);
351 /* Position cursor to end of screen */
352 void Console::update_cursor()
354 QApplication::restoreOverrideCursor();
355 m_textEdit->moveCursor(QTextCursor::End);
356 m_textEdit->ensureCursorVisible();
360 * This should be moved into a bSocket class
370 /* Send a command to the Director */
371 void Console::write_dir(const char *msg)
374 mainWin->set_status(_("Processing command ..."));
375 QApplication::setOverrideCursor(Qt::WaitCursor);
378 mainWin->set_status(" Director not connected. Click on connect button.");
379 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
380 QBrush redBrush(Qt::red);
381 m_treeItem->setForeground(0, redBrush);
386 int Console::write(const QString msg)
388 return write(msg.toUtf8().data());
391 int Console::write(const char *msg)
393 m_sock->msglen = strlen(msg);
394 pm_strcpy(&m_sock->msg, msg);
396 if (commDebug) Pmsg1(000, "send: %s\n", msg);
397 return m_sock->send();
401 * Get to main command prompt
403 void Console::beginNewCommand()
417 void Console::displayToPrompt()
420 if (commDebug) Pmsg0(000, "DisplaytoPrompt\n");
421 while (!m_at_prompt) {
422 if ((stat=read()) > 0) {
426 if (commDebug) Pmsg1(000, "endDisplaytoPrompt=%d\n", stat);
429 void Console::discardToPrompt()
432 if (commDebug) Pmsg0(000, "discardToPrompt\n");
433 while (!m_at_prompt) {
436 if (commDebug) Pmsg1(000, "endDisplayToPrompt=%d\n", stat);
441 * Blocking read from director
448 stat = bnet_wait_data_intr(m_sock, 1);
452 app->processEvents();
453 if (m_api_set && m_messages_pending) {
454 write_dir(".messages");
455 m_messages_pending = false;
458 stat = m_sock->recv();
464 if (commDebug) Pmsg1(000, "got: %s", m_sock->msg);
466 switch (m_sock->msglen) {
467 case BNET_SERVER_READY:
468 if (m_api_set && m_messages_pending) {
469 write_dir(".messages");
470 m_messages_pending = false;
474 case BNET_MSGS_PENDING:
475 if (commDebug) Pmsg0(000, "MSGS PENDING\n");
476 m_messages_pending = true;
479 if (commDebug) Pmsg0(000, "CMD OK\n");
483 if (commDebug) Pmsg0(000, "CMD BEGIN\n");
487 if (commDebug) Pmsg0(000, "PROMPT\n");
489 mainWin->set_status(_("At prompt waiting for input ..."));
491 QApplication::restoreOverrideCursor();
493 case BNET_CMD_FAILED:
494 if (commDebug) Pmsg0(000, "CMD FAIL\n");
495 mainWin->set_status(_("Command failed. At prompt waiting for input ..."));
497 QApplication::restoreOverrideCursor();
499 /* We should not get this one */
501 if (commDebug) Pmsg0(000, "EOD\n");
502 mainWin->set_status_ready();
504 QApplication::restoreOverrideCursor();
509 case BNET_START_SELECT:
510 new selectDialog(this);
513 new runCmdDialog(this);
516 m_sock->recv(); /* get the message */
518 QMessageBox::critical(this, "Error", msg(), QMessageBox::Ok);
520 case BNET_WARNING_MSG:
521 m_sock->recv(); /* get the message */
523 QMessageBox::critical(this, "Warning", msg(), QMessageBox::Ok);
526 m_sock->recv(); /* get the message */
528 mainWin->set_status(msg());
531 if (is_bnet_stop(m_sock)) { /* error or term request */
534 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
535 QBrush redBrush(Qt::red);
536 m_treeItem->setForeground(0, redBrush);
537 m_notifier->setEnabled(false);
540 mainWin->set_status(_("Director disconnected."));
541 QApplication::restoreOverrideCursor();
549 /* Called by signal when the Director has output for us */
550 void Console::read_dir(int fd)
555 if (commDebug) Pmsg0(000, "read_dir\n");
556 while ((stat = read()) >= 0) {
562 * When the notifier is enabled, read_dir() will automatically be
563 * called by the Qt event loop when ever there is any output
564 * from the Directory, and read_dir() will then display it on
567 * When we are in a bat dialog, we want to control *all* output
568 * from the Directory, so we set notify to off.
569 * m_console->notifiy(false);
571 void Console::notify(bool enable)
573 m_notifier->setEnabled(enable);
576 void Console::setDirRes(DIRRES *dir)
581 ******FIXME****** Just Delete me
582 void Console::dosql(QString* sqlcmd, QStringList& strlstret)
585 /* don't effect the string coming in */
586 QString cmd(*sqlcmd);
588 cmd = ".sql \"" + cmd + "\"";
590 write_dir(cmd.toUtf8().data());
591 while ((stat=read()) > 0) {
592 QString line = msg();
593 QRegExp regex("^Using Catalog");
594 if ( regex.indexIn(line) < 0 ){
595 strlstret.append(line);