]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/console/console.cpp
Fix debug code
[bacula/bacula] / bacula / src / qt-console / console / console.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
5
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 and included
11    in the file LICENSE.
12
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.
17
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
21    02110-1301, USA.
22
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.
27 */
28 /*
29  *   Version $Id$
30  *
31  *  Console Class
32  *
33  *   Kern Sibbald, January MMVII
34  *
35  */ 
36
37 //#include <QAbstractEventDispatcher>
38 #include "bat.h"
39 #include "console.h"
40 #include "restore.h"
41 #include "select.h"
42 #include "run/run.h"
43
44 static int tls_pem_callback(char *buf, int size, const void *userdata);
45
46
47 Console::Console(QStackedWidget *parent)
48 {
49    QFont font;
50    m_parent = parent;
51    m_closeable = false;
52    m_console = this;
53
54    setupUi(this);
55    m_sock = NULL;
56    m_at_prompt = false;
57    m_at_main_prompt = false;
58    m_textEdit = textEdit;   /* our console screen */
59    m_cursor = new QTextCursor(m_textEdit->document());
60    mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
61
62    m_timer = NULL;
63    m_contextActions.append(actionStatusDir);
64    m_contextActions.append(actionConsoleHelp);
65    m_contextActions.append(actionRequestMessages);
66    m_contextActions.append(actionConsoleReload);
67    connect(actionStatusDir, SIGNAL(triggered()), this, SLOT(status_dir()));
68    connect(actionConsoleHelp, SIGNAL(triggered()), this, SLOT(consoleHelp()));
69    connect(actionConsoleReload, SIGNAL(triggered()), this, SLOT(consoleReload()));
70    connect(actionRequestMessages, SIGNAL(triggered()), this, SLOT(messages()));
71 }
72
73 Console::~Console()
74 {
75 }
76
77 void Console::startTimer()
78 {
79    m_timer = new QTimer(this);
80    QWidget::connect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
81    m_timer->start(mainWin->m_checkMessagesInterval*1000);
82 }
83
84 void Console::stopTimer()
85 {
86    if (m_timer) {
87       QWidget::disconnect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
88       m_timer->stop();
89       delete m_timer;
90       m_timer = NULL;
91    }
92 }
93       
94 void Console::poll_messages()
95 {
96    m_messages_pending = true;
97    if ((m_at_main_prompt) && (mainWin->m_checkMessages)){
98       write(".messages");
99       displayToPrompt();
100    }
101 }
102
103 /* Terminate any open socket */
104 void Console::terminate()
105 {
106    if (m_sock) {
107       stopTimer();
108       m_sock->close();
109       m_sock = NULL;
110    }
111 }
112
113 /*
114  * Connect to Director. 
115  */
116 void Console::connect_dir()
117 {
118    JCR jcr;
119    utime_t heart_beat;
120    char buf[1024];
121
122    m_textEdit = textEdit;   /* our console screen */
123
124    if (!m_dir) {          
125       mainWin->set_status("No Director found.");
126       return;
127    }
128    if (m_sock) {
129       mainWin->set_status("Already connected.");
130       return;
131    }
132
133    memset(&jcr, 0, sizeof(jcr));
134
135    mainWin->set_statusf(_("Connecting to Director %s:%d"), m_dir->address, m_dir->DIRport);
136    display_textf(_("Connecting to Director %s:%d\n\n"), m_dir->address, m_dir->DIRport);
137
138    /* Give GUI a chance */
139    app->processEvents();
140    
141    LockRes();
142    /* If cons==NULL, default console will be used */
143    CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, NULL);
144    UnlockRes();
145
146    /* Initialize Console TLS context once */
147    if (cons && !cons->tls_ctx && (cons->tls_enable || cons->tls_require)) {
148       /* Generate passphrase prompt */
149       bsnprintf(buf, sizeof(buf), "Passphrase for Console \"%s\" TLS private key: ", 
150                 cons->name());
151
152       /* Initialize TLS context:
153        * Args: CA certfile, CA certdir, Certfile, Keyfile,
154        * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer   
155        */
156       cons->tls_ctx = new_tls_context(cons->tls_ca_certfile,
157          cons->tls_ca_certdir, cons->tls_certfile,
158          cons->tls_keyfile, tls_pem_callback, &buf, NULL, true);
159
160       if (!cons->tls_ctx) {
161          display_textf(_("Failed to initialize TLS context for Console \"%s\".\n"),
162             m_dir->name());
163          return;
164       }
165    }
166
167    /* Initialize Director TLS context once */
168    if (!m_dir->tls_ctx && (m_dir->tls_enable || m_dir->tls_require)) {
169       /* Generate passphrase prompt */
170       bsnprintf(buf, sizeof(buf), "Passphrase for Director \"%s\" TLS private key: ", 
171                 m_dir->name());
172
173       /* Initialize TLS context:
174        * Args: CA certfile, CA certdir, Certfile, Keyfile,
175        * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
176       m_dir->tls_ctx = new_tls_context(m_dir->tls_ca_certfile,
177                           m_dir->tls_ca_certdir, m_dir->tls_certfile,
178                           m_dir->tls_keyfile, tls_pem_callback, &buf, NULL, true);
179
180       if (!m_dir->tls_ctx) {
181          display_textf(_("Failed to initialize TLS context for Director \"%s\".\n"),
182             m_dir->name());
183          mainWin->set_status("Connection failed");
184          return;
185       }
186    }
187
188    if (m_dir->heartbeat_interval) {
189       heart_beat = m_dir->heartbeat_interval;
190    } else if (cons) {
191       heart_beat = cons->heartbeat_interval;
192    } else {
193       heart_beat = 0;
194    }        
195
196    m_sock = bnet_connect(NULL, 5, 15, heart_beat,
197                           _("Director daemon"), m_dir->address,
198                           NULL, m_dir->DIRport, 0);
199    if (m_sock == NULL) {
200       mainWin->set_status("Connection failed");
201       return;
202    } else {
203       /* Update page selector to green to indicate that Console is connected */
204       mainWin->actionConnect->setIcon(QIcon(":images/connected.png"));
205       QBrush greenBrush(Qt::green);
206       QTreeWidgetItem *item = mainWin->getFromHash(this);
207       item->setForeground(0, greenBrush);
208    }
209
210    jcr.dir_bsock = m_sock;
211
212    if (!authenticate_director(&jcr, m_dir, cons, buf, sizeof(buf))) {
213       display_text(buf);
214       return;
215    }
216    if (buf[0]) {
217       display_text(buf);
218    }
219
220    /* Give GUI a chance */
221    app->processEvents();
222
223    mainWin->set_status(_("Initializing ..."));
224
225    /* Set up input notifier */
226    m_notifier = new QSocketNotifier(m_sock->m_fd, QSocketNotifier::Read, 0);
227    QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(read_dir(int)));
228
229    write(".api 1");
230    displayToPrompt();
231
232    beginNewCommand();
233    job_list.clear();
234    client_list.clear();
235    fileset_list.clear();
236    fileset_list.clear();
237    messages_list.clear();
238    pool_list.clear();
239    storage_list.clear();
240    type_list.clear();
241    level_list.clear();
242    dir_cmd(".jobs", job_list);
243    dir_cmd(".clients", client_list);
244    dir_cmd(".filesets", fileset_list);  
245    dir_cmd(".msgs", messages_list);
246    dir_cmd(".pools", pool_list);
247    dir_cmd(".storage", storage_list);
248    dir_cmd(".types", type_list);
249    dir_cmd(".levels", level_list);
250
251    mainWin->set_status(_("Connected"));
252    startTimer();                      /* start message timer */
253    return;
254 }
255
256 bool Console::dir_cmd(QString &cmd, QStringList &results)
257 {
258    return dir_cmd(cmd.toUtf8().data(), results);
259 }
260
261 /*
262  * Send a command to the Director, and return the
263  *  results in a QStringList.  
264  */
265 bool Console::dir_cmd(const char *cmd, QStringList &results)
266 {
267    int stat;
268
269    notify(false);
270    write(cmd);
271    while ((stat = read()) > 0) {
272       if (mainWin->m_displayAll) display_text(msg());
273       strip_trailing_junk(msg());
274       results << msg();
275    }
276    notify(true);
277    discardToPrompt();
278    return true;              /* ***FIXME*** return any command error */
279 }
280
281 bool Console::sql_cmd(QString &query, QStringList &results)
282 {
283    return sql_cmd(query.toUtf8().data(), results);
284 }
285
286 /*
287  * Send an sql query to the Director, and return the
288  *  results in a QStringList.  
289  */
290 bool Console::sql_cmd(const char *query, QStringList &results)
291 {
292    int stat;
293    POOL_MEM cmd(PM_MESSAGE);
294
295    if (!is_connectedGui()) {
296       return false;
297    }
298
299    notify(false);
300    
301    pm_strcpy(cmd, ".sql query=\"");
302    pm_strcat(cmd, query);
303    pm_strcat(cmd, "\"");
304    write(cmd.c_str());
305    while ((stat = read()) > 0) {
306       if (mainWin->m_displayAll) display_text(msg());
307       strip_trailing_junk(msg());
308       results << msg();
309    }
310    notify(true);
311    discardToPrompt();
312    return true;              /* ***FIXME*** return any command error */
313 }
314
315
316 /*  
317  * Send a job name to the director, and read all the resulting
318  *  defaults. 
319  */
320 bool Console::get_job_defaults(struct job_defaults &job_defs)
321 {
322    QString scmd;
323    int stat;
324    char *def;
325
326    notify(false);
327    beginNewCommand();
328    scmd = QString(".defaults job=\"%1\"").arg(job_defs.job_name);
329    write(scmd);
330    while ((stat = read()) > 0) {
331       if (mainWin->m_displayAll) display_text(msg());
332       def = strchr(msg(), '=');
333       if (!def) {
334          continue;
335       }
336       /* Pointer to default value */
337       *def++ = 0;
338       strip_trailing_junk(def);
339
340       if (strcmp(msg(), "job") == 0) {
341          if (strcmp(def, job_defs.job_name.toUtf8().data()) != 0) {
342             goto bail_out;
343          }
344          continue;
345       }
346       if (strcmp(msg(), "pool") == 0) {
347          job_defs.pool_name = def;
348          continue;
349       }
350       if (strcmp(msg(), "messages") == 0) {
351          job_defs.messages_name = def;
352          continue;
353       }
354       if (strcmp(msg(), "client") == 0) {
355          job_defs.client_name = def;
356          continue;
357       }
358       if (strcmp(msg(), "storage") == 0) {
359          job_defs.store_name = def;
360          continue;
361       }
362       if (strcmp(msg(), "where") == 0) {
363          job_defs.where = def;
364          continue;
365       }
366       if (strcmp(msg(), "level") == 0) {
367          job_defs.level = def;
368          continue;
369       }
370       if (strcmp(msg(), "type") == 0) {
371          job_defs.type = def;
372          continue;
373       }
374       if (strcmp(msg(), "fileset") == 0) {
375          job_defs.fileset_name = def;
376          continue;
377       }
378       if (strcmp(msg(), "catalog") == 0) {
379          job_defs.catalog_name = def;
380          continue;
381       }
382       if (strcmp(msg(), "enabled") == 0) {
383          job_defs.enabled = *def == '1' ? true : false;
384          continue;
385       }
386    }
387
388    notify(true);
389    return true;
390
391 bail_out:
392    notify(true);
393    return false;
394 }
395
396
397 /*
398  * Save user settings associated with this console
399  */
400 void Console::writeSettings()
401 {
402    QFont font = get_font();
403
404    QSettings settings(m_dir->name(), "bat");
405    settings.beginGroup("Console");
406    settings.setValue("consoleFont", font.family());
407    settings.setValue("consolePointSize", font.pointSize());
408    settings.setValue("consoleFixedPitch", font.fixedPitch());
409    settings.endGroup();
410 }
411
412 /*
413  * Read and restore user settings associated with this console
414  */
415 void Console::readSettings()
416
417    QFont font = get_font();
418
419    QSettings settings(m_dir->name(), "bat");
420    settings.beginGroup("Console");
421    font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
422    font.setPointSize(settings.value("consolePointSize", 10).toInt());
423    font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
424    settings.endGroup();
425    m_textEdit->setFont(font);
426 }
427
428 /*
429  * Set the console textEdit font
430  */
431 void Console::set_font()
432 {
433    bool ok;
434    QFont font = QFontDialog::getFont(&ok, QFont(m_textEdit->font()), this);
435    if (ok) {
436       m_textEdit->setFont(font);
437    }
438 }
439
440 /*
441  * Get the console text edit font
442  */
443 const QFont Console::get_font()
444 {
445    return m_textEdit->font();
446 }
447
448 /*
449  * Slot for responding to status dir button on button bar
450  */
451 void Console::status_dir()
452 {
453    QString cmd("status dir");
454    consoleCommand(cmd);
455 }
456
457 /*
458  * Slot for responding to messages button on button bar
459  */
460 void Console::messages()
461 {
462    QString cmd(".messages");
463    consoleCommand(cmd);
464 }
465
466 /*
467  * Put text into the console window
468  */
469 void Console::display_textf(const char *fmt, ...)
470 {
471    va_list arg_ptr;
472    char buf[1000];
473    int len;
474    va_start(arg_ptr, fmt);
475    len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
476    va_end(arg_ptr);
477    display_text(buf);
478 }
479
480 void Console::display_text(const QString buf)
481 {
482    m_cursor->insertText(buf);
483    update_cursor();
484 }
485
486
487 void Console::display_text(const char *buf)
488 {
489    m_cursor->insertText(buf);
490    update_cursor();
491 }
492
493 void Console::display_html(const QString buf)
494 {
495    m_cursor->insertHtml(buf);
496    update_cursor();
497 }
498
499 /* Position cursor to end of screen */
500 void Console::update_cursor()
501 {
502    QApplication::restoreOverrideCursor();
503    m_textEdit->moveCursor(QTextCursor::End);
504    m_textEdit->ensureCursorVisible();
505 }
506
507 /* 
508  * This should be moved into a bSocket class 
509  */
510 char *Console::msg()
511 {
512    if (m_sock) {
513       return m_sock->msg;
514    }
515    return NULL;
516 }
517
518 /* Send a command to the Director */
519 void Console::write_dir(const char *msg)
520 {
521    if (m_sock) {
522       mainWin->set_status(_("Processing command ..."));
523       QApplication::setOverrideCursor(Qt::WaitCursor);
524       write(msg);
525    } else {
526       mainWin->set_status(" Director not connected. Click on connect button.");
527       mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
528       QBrush redBrush(Qt::red);
529       QTreeWidgetItem *item = mainWin->getFromHash(this);
530       item->setForeground(0, redBrush);
531       m_at_prompt = false;
532       m_at_main_prompt = false;
533    }
534 }
535
536 int Console::write(const QString msg)
537 {
538    return write(msg.toUtf8().data());
539 }
540
541 int Console::write(const char *msg)
542 {
543    if (!m_sock) {
544       return -1;
545    }
546    m_sock->msglen = pm_strcpy(m_sock->msg, msg);
547    m_at_prompt = false;
548    m_at_main_prompt = false;
549    if (mainWin->m_commDebug) Pmsg1(000, "send: %s\n", msg);
550    return m_sock->send();
551
552 }
553
554 /*
555  * Get to main command prompt -- i.e. abort any subcommand
556  */
557 void Console::beginNewCommand()
558 {
559    for (int i=0; i < 3; i++) {
560       write(".");
561       while (read() > 0) {
562          if (mainWin->m_displayAll) display_text(msg());
563       }
564       if (m_at_main_prompt) {
565          break;
566       }
567    }
568    display_text("\n");
569 }
570
571 void Console::displayToPrompt()
572
573    int stat = 0;
574    if (mainWin->m_commDebug) Pmsg0(000, "DisplaytoPrompt\n");
575    while (!m_at_prompt) {
576       if ((stat=read()) > 0) {
577          display_text(msg());
578       }
579    }
580    if (mainWin->m_commDebug) Pmsg1(000, "endDisplaytoPrompt=%d\n", stat);
581 }
582
583 void Console::discardToPrompt()
584
585    int stat = 0;
586    if (mainWin->m_commDebug) Pmsg0(000, "discardToPrompt\n");
587    while (!m_at_prompt) {
588       if ((stat=read()) > 0) {
589          if (mainWin->m_displayAll) display_text(msg());
590       }
591    }
592    if (mainWin->m_commDebug) Pmsg1(000, "endDisplayToPrompt=%d\n", stat);
593 }
594
595
596 /* 
597  * Blocking read from director
598  */
599 int Console::read()
600 {
601    int stat = 0;
602    while (m_sock) {
603       for (;;) {
604          stat = bnet_wait_data_intr(m_sock, 1);
605          if (stat > 0) {
606             break;
607          } 
608          app->processEvents();
609          if (m_api_set && m_messages_pending) {
610             write_dir(".messages");
611             m_messages_pending = false;
612          }
613       }
614       m_sock->msg[0] = 0;
615       stat = m_sock->recv();
616       if (stat >= 0) {
617          if (mainWin->m_commDebug) Pmsg1(000, "got: %s\n", m_sock->msg);
618          if (m_at_prompt) {
619             display_text("\n");
620             m_at_prompt = false;
621             m_at_main_prompt = false;
622          }
623       }
624       switch (m_sock->msglen) {
625       case BNET_MSGS_PENDING:
626          if (mainWin->m_commDebug) Pmsg0(000, "MSGS PENDING\n");
627          write_dir(".messages");
628          displayToPrompt();
629          m_messages_pending = false;
630          continue;
631       case BNET_CMD_OK:
632          if (mainWin->m_commDebug) Pmsg0(000, "CMD OK\n");
633          m_at_prompt = false;
634          m_at_main_prompt = false;
635          mainWin->set_status(_("Command completed ..."));
636          continue;
637       case BNET_CMD_BEGIN:
638          if (mainWin->m_commDebug) Pmsg0(000, "CMD BEGIN\n");
639          m_at_prompt = false;
640          m_at_main_prompt = false;
641          mainWin->set_status(_("Processing command ..."));
642          continue;
643       case BNET_MAIN_PROMPT:
644          if (mainWin->m_commDebug) Pmsg0(000, "MAIN PROMPT\n");
645          m_at_prompt = true;
646          m_at_main_prompt = true;
647          mainWin->set_status(_("At main prompt waiting for input ..."));
648          QApplication::restoreOverrideCursor();
649          break;
650       case BNET_PROMPT:
651          if (mainWin->m_commDebug) Pmsg0(000, "PROMPT\n");
652          m_at_prompt = true;
653          m_at_main_prompt = false;
654          mainWin->set_status(_("At prompt waiting for input ..."));
655          QApplication::restoreOverrideCursor();
656          break;
657       case BNET_CMD_FAILED:
658          if (mainWin->m_commDebug) Pmsg0(000, "CMD FAILED\n");
659          mainWin->set_status(_("Command failed."));
660          QApplication::restoreOverrideCursor();
661          break;
662       /* We should not get this one */
663       case BNET_EOD:
664          if (mainWin->m_commDebug) Pmsg0(000, "EOD\n");
665          mainWin->set_status_ready();
666          QApplication::restoreOverrideCursor();
667          if (!m_api_set) {
668             break;
669          }
670          continue;
671       case BNET_START_SELECT:
672          if (mainWin->m_commDebug) Pmsg0(000, "START SELECT\n");
673          new selectDialog(this);    
674          break;
675       case BNET_RUN_CMD:
676          if (mainWin->m_commDebug) Pmsg0(000, "RUN CMD\n");
677          new runCmdPage();
678          break;
679       case BNET_ERROR_MSG:
680          if (mainWin->m_commDebug) Pmsg0(000, "ERROR MSG\n");
681          m_sock->recv();              /* get the message */
682          display_text(msg());
683          QMessageBox::critical(this, "Error", msg(), QMessageBox::Ok);
684          break;
685       case BNET_WARNING_MSG:
686          if (mainWin->m_commDebug) Pmsg0(000, "WARNING MSG\n");
687          m_sock->recv();              /* get the message */
688          display_text(msg());
689          QMessageBox::critical(this, "Warning", msg(), QMessageBox::Ok);
690          break;
691       case BNET_INFO_MSG:
692          if (mainWin->m_commDebug) Pmsg0(000, "INFO MSG\n");
693          m_sock->recv();              /* get the message */
694          display_text(msg());
695          mainWin->set_status(msg());
696          break;
697       }
698       if (is_bnet_stop(m_sock)) {         /* error or term request */
699          if (mainWin->m_commDebug) Pmsg0(000, "BNET STOP\n");
700          stopTimer();
701          m_sock->close();
702          m_sock = NULL;
703          mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
704          QBrush redBrush(Qt::red);
705          QTreeWidgetItem *item = mainWin->getFromHash(this);
706          item->setForeground(0, redBrush);
707          m_notifier->setEnabled(false);
708          delete m_notifier;
709          m_notifier = NULL;
710          mainWin->set_status(_("Director disconnected."));
711          QApplication::restoreOverrideCursor();
712          stat = BNET_HARDEOF;
713       }
714       break;
715    } 
716    return stat;
717 }
718
719 /* Called by signal when the Director has output for us */
720 void Console::read_dir(int /* fd */)
721 {
722    if (mainWin->m_commDebug) Pmsg0(000, "read_dir\n");
723    while (read() >= 0) {
724       display_text(msg());
725    }
726 }
727
728 /*
729  * When the notifier is enabled, read_dir() will automatically be
730  * called by the Qt event loop when ever there is any output 
731  * from the Directory, and read_dir() will then display it on
732  * the console.
733  *
734  * When we are in a bat dialog, we want to control *all* output
735  * from the Directory, so we set notify to off.
736  *    m_console->notifiy(false);
737  */
738 void Console::notify(bool enable) 
739
740    m_notifier->setEnabled(enable);   
741 }
742
743 void Console::setDirectorTreeItem(QTreeWidgetItem *item)
744 {
745    m_directorTreeItem = item;
746 }
747
748 void Console::setDirRes(DIRRES *dir) 
749
750    m_dir = dir;
751 }
752
753 /*
754  * To have the ability to get the name of the director resource.
755  */
756 void Console::getDirResName(QString &name_returned)
757 {
758    name_returned = m_dir->name();
759 }
760
761 bool Console::is_connectedGui()
762 {
763    if (is_connected()) {
764       return true;
765    } else {
766       QString message("Director ");
767       message += " is currently disconnected\n  Please reconnect!!";
768       QMessageBox::warning(this, "Bat",
769          tr(message.toUtf8().data()), QMessageBox::Ok );
770       return false;
771    }
772 }
773
774 /*
775  * A temporary function to prevent connecting to the director if the director
776  * is busy with a restore.
777  */
778 bool Console::preventInUseConnect()
779 {
780    if (!is_connected()) {
781       QString message("Director ");
782       message += m_dir->name();
783       message += " is currently disconnected\n  Please reconnect!!";
784       QMessageBox::warning(this, "Bat",
785          tr(message.toUtf8().data()), QMessageBox::Ok );
786       return false;
787    } else if (!m_at_main_prompt){
788       QString message("Director ");
789       message += m_dir->name();
790       message += " is currently busy\n  Please complete restore or other "
791                  " operation !!  This is a limitation that will be resolved before a beta"
792                  " release.  This is currently an alpha release.";
793       QMessageBox::warning(this, "Bat",
794          tr(message.toUtf8().data()), QMessageBox::Ok );
795       return false;
796    } else if (!m_at_prompt){
797       QString message("Director ");
798       message += m_dir->name();
799       message += " is currently not at a prompt\n  Please try again!!";
800       QMessageBox::warning(this, "Bat",
801          tr(message.toUtf8().data()), QMessageBox::Ok );
802       return false;
803    } else {
804       return true;
805    }
806 }
807
808 /*
809  * Call-back for reading a passphrase for an encrypted PEM file
810  * This function uses getpass(), 
811  *  which uses a static buffer and is NOT thread-safe.
812  */
813 static int tls_pem_callback(char *buf, int size, const void *userdata)
814 {
815    (void)size;
816    (void)userdata;
817 #ifdef HAVE_TLS
818    const char *prompt = (const char *)userdata;
819 # if defined(HAVE_WIN32)
820    sendit(prompt);
821    if (win32_cgets(buf, size) == NULL) {
822       buf[0] = 0;
823       return 0;
824    } else {
825       return strlen(buf);
826    }
827 # else
828    char *passwd;
829
830    passwd = getpass(prompt);
831    bstrncpy(buf, passwd, size);
832    return strlen(buf);
833 # endif
834 #else
835    buf[0] = 0;
836    return 0;
837 #endif
838 }
839
840 /* Slot for responding to page selectors status help command */
841 void Console::consoleHelp()
842 {
843    QString cmd("help");
844    consoleCommand(cmd);
845 }
846
847 /* Slot for responding to page selectors reload bacula-dir.conf */
848 void Console::consoleReload()
849 {
850    QString cmd("reload");
851    consoleCommand(cmd);
852 }