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)
49 m_textEdit = textEdit; /* our console screen */
50 m_cursor = new QTextCursor(m_textEdit->document());
51 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
56 /* Check for messages every 5 seconds */
57 // m_timer = new QTimer(this);
58 // QWidget::connect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
59 // m_timer->start(5000);
63 void Console::poll_messages()
65 m_messages_pending = true;
68 /* Terminate any open socket */
69 void Console::terminate()
79 * Connect to Director. If there are more than one, put up
80 * a modal dialog so that the user chooses one.
82 void Console::connect()
86 m_textEdit = textEdit; /* our console screen */
89 mainWin->set_status("No Director found.");
93 mainWin->set_status("Already connected.");
97 memset(&jcr, 0, sizeof(jcr));
99 mainWin->set_statusf(_("Connecting to Director %s:%d"), m_dir->address, m_dir->DIRport);
100 display_textf(_("Connecting to Director %s:%d\n\n"), m_dir->address, m_dir->DIRport);
102 /* Give GUI a chance */
103 app->processEvents();
106 /* If cons==NULL, default console will be used */
107 CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
110 m_sock = bnet_connect(NULL, 5, 15, _("Director daemon"), m_dir->address,
111 NULL, m_dir->DIRport, 0);
112 if (m_sock == NULL) {
113 mainWin->set_status("Connection failed");
116 /* Update page selector to green to indicate that Console is connected */
117 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/connected.png")));
118 QBrush greenBrush(Qt::green);
119 m_consoleItem->setForeground(0, greenBrush);
122 jcr.dir_bsock = m_sock;
124 if (!authenticate_director(&jcr, m_dir, cons)) {
125 display_text(m_sock->msg);
129 /* Give GUI a chance */
130 app->processEvents();
132 mainWin->set_status(_("Initializing ..."));
134 /* Set up input notifier */
135 m_notifier = new QSocketNotifier(m_sock->fd, QSocketNotifier::Read, 0);
136 QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(read_dir(int)));
142 job_list = get_list(".jobs");
143 client_list = get_list(".clients");
144 fileset_list = get_list(".filesets");
145 messages_list = get_list(".messages");
146 pool_list = get_list(".pools");
147 storage_list = get_list(".storage");
148 type_list = get_list(".types");
149 level_list = get_list(".levels");
151 mainWin->set_status(_("Connected"));
157 * Send a command to the director, and read all the resulting
158 * output into a list.
160 QStringList Console::get_list(char *cmd)
167 while ((stat = read()) > 0) {
168 strip_trailing_junk(msg());
177 * Send a job name to the director, and read all the resulting
180 bool Console::get_job_defaults(struct job_defaults &job_defs)
188 scmd = QString(".defaults job=\"%1\"").arg(job_defs.job_name);
190 while ((stat = read()) > 0) {
191 def = strchr(msg(), '=');
195 /* Pointer to default value */
197 strip_trailing_junk(def);
199 if (strcmp(msg(), "job") == 0) {
200 if (strcmp(def, job_defs.job_name.toUtf8().data()) != 0) {
205 if (strcmp(msg(), "pool") == 0) {
206 job_defs.pool_name = def;
209 if (strcmp(msg(), "messages") == 0) {
210 job_defs.messages_name = def;
213 if (strcmp(msg(), "client") == 0) {
214 job_defs.client_name = def;
217 if (strcmp(msg(), "storage") == 0) {
218 job_defs.store_name = def;
221 if (strcmp(msg(), "where") == 0) {
222 job_defs.where = def;
225 if (strcmp(msg(), "level") == 0) {
226 job_defs.level = def;
229 if (strcmp(msg(), "type") == 0) {
233 if (strcmp(msg(), "fileset") == 0) {
234 job_defs.fileset_name = def;
237 if (strcmp(msg(), "catalog") == 0) {
238 job_defs.catalog_name = def;
241 if (strcmp(msg(), "enabled") == 0) {
242 job_defs.enabled = *def == '1' ? true : false;
248 bsnprintf(cmd, sizeof(cmd), "job=%s pool=%s client=%s storage=%s where=%s\n"
249 "level=%s type=%s fileset=%s catalog=%s enabled=%d\n",
250 job_defs.job_name.toUtf8().data(), job_defs.pool_name.toUtf8().data(),
251 job_defs.client_name.toUtf8().data(),
252 job_defs.pool_name.toUtf8().data(), job_defs.messages_name.toUtf8().data(),
253 job_defs.store_name.toUtf8().data(),
254 job_defs.where.toUtf8().data(), job_defs.level.toUtf8().data(),
255 job_defs.type.toUtf8().data(), job_defs.fileset_name.toUtf8().data(),
256 job_defs.catalog_name.toUtf8().data(), job_defs.enabled);
269 * Save user settings associated with this console
271 void Console::writeSettings()
273 QFont font = get_font();
275 QSettings settings("bacula.org", "bat");
276 /* ***FIXME*** make console name unique */
277 settings.beginGroup("Console");
278 settings.setValue("consoleFont", font.family());
279 settings.setValue("consolePointSize", font.pointSize());
280 settings.setValue("consoleFixedPitch", font.fixedPitch());
285 * Read and restore user settings associated with this console
287 void Console::readSettings()
289 QFont font = get_font();
291 QSettings settings("bacula.org", "bat");
292 settings.beginGroup("Console");
293 font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
294 font.setPointSize(settings.value("consolePointSize", 10).toInt());
295 font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
297 m_textEdit->setFont(font);
301 * Set the console textEdit font
303 void Console::set_font()
306 QFont font = QFontDialog::getFont(&ok, QFont(m_textEdit->font()), this);
308 m_textEdit->setFont(font);
313 * Get the console text edit font
315 const QFont Console::get_font()
317 return m_textEdit->font();
321 void Console::status_dir()
323 write_dir("status dir\n");
328 * Put text into the console window
330 void Console::display_textf(const char *fmt, ...)
335 va_start(arg_ptr, fmt);
336 len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
341 void Console::display_text(const QString buf)
343 m_cursor->movePosition(QTextCursor::End);
344 m_cursor->insertText(buf);
348 void Console::display_text(const char *buf)
350 m_cursor->movePosition(QTextCursor::End);
351 m_cursor->insertText(buf);
354 /* Position cursor to end of screen */
355 void Console::update_cursor()
357 QApplication::restoreOverrideCursor();
358 m_textEdit->moveCursor(QTextCursor::End);
359 m_textEdit->ensureCursorVisible();
363 * This should be moved into a bSocket class
373 /* Send a command to the Director */
374 void Console::write_dir(const char *msg)
377 mainWin->set_status(_("Processing command ..."));
378 QApplication::setOverrideCursor(Qt::WaitCursor);
381 mainWin->set_status(" Director not connected. Click on connect button.");
382 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
383 QBrush redBrush(Qt::red);
384 m_consoleItem->setForeground(0, redBrush);
388 int Console::write(const QString msg)
390 return write(msg.toUtf8().data());
393 int Console::write(const char *msg)
395 m_sock->msglen = strlen(msg);
396 pm_strcpy(&m_sock->msg, msg);
398 if (commDebug) Pmsg1(000, "send: %s\n", msg);
399 return m_sock->send();
403 * Get to main command prompt
405 void Console::beginNewCommand()
419 void Console::displayToPrompt()
422 if (commDebug) Pmsg0(000, "DisplaytoPrompt\n");
423 m_notifier->setEnabled(false);
424 while ((stat = read()) > 0) {
427 if (commDebug) Pmsg1(000, "endDisplaytoPrompt=%d\n", stat);
428 m_notifier->setEnabled(true);
431 void Console::discardToPrompt()
434 if (commDebug) Pmsg0(000, "discardToPrompt\n");
435 m_notifier->setEnabled(false);
436 while ((stat = read()) > 0) {
438 if (commDebug) Pmsg1(000, "endDisplayToPrompt=%d\n", stat);
439 m_notifier->setEnabled(true);
444 * Blocking read from director
448 int stat = BNET_HARDEOF;
451 stat = bnet_wait_data_intr(m_sock, 1);
455 app->processEvents();
456 // if (m_api_set && m_messages_pending) {
457 // write_dir(".messages");
458 // m_messages_pending = false;
461 stat = m_sock->recv();
467 if (commDebug) Pmsg1(000, "got: %s", m_sock->msg);
470 switch (m_sock->msglen) {
471 case BNET_SERVER_READY:
472 // if (m_api_set && m_messages_pending) {
473 // write_dir(".messages");
474 // m_messages_pending = false;
478 case BNET_MESSAGES_PENDING:
479 m_messages_pending = true;
486 if (commDebug) Pmsg0(000, "CMD OK/PROMPT\n");
488 mainWin->set_status(_("At prompt waiting for input ..."));
490 QApplication::restoreOverrideCursor();
492 case BNET_CMD_FAILED:
493 if (commDebug) Pmsg0(000, "CMD FAIL\n");
495 mainWin->set_status(_("Command failed. At prompt waiting for input ..."));
497 QApplication::restoreOverrideCursor();
500 if (commDebug) Pmsg0(000, "EOD\n");
501 mainWin->set_status_ready();
503 QApplication::restoreOverrideCursor();
508 case BNET_START_SELECT:
509 new selectDialog(this);
512 if (is_bnet_stop(m_sock)) { /* error or term request */
515 mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
516 QBrush redBrush(Qt::red);
517 m_consoleItem->setForeground(0, redBrush);
518 m_notifier->setEnabled(false);
521 mainWin->set_status(_("Director disconnected."));
522 QApplication::restoreOverrideCursor();
529 /* Called by signal when the Director has output for us */
530 void Console::read_dir(int fd)
535 if (commDebug) Pmsg0(000, "read_dir\n");
536 while ((stat = read()) >= 0) {
541 void Console::setEnabled(bool enable)
543 m_notifier->setEnabled(enable);
546 void Console::setTreeItem(QTreeWidgetItem *item)
548 m_consoleItem = item;
551 void Console::setDirRes(DIRRES *dir)