]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/console/console.cpp
Add preference for longlist or short list when context sensitive list command is
[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 plus additions
11    that are listed 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    dir_cmd(".jobs", job_list);
234    dir_cmd(".clients", client_list);
235    dir_cmd(".filesets", fileset_list);  
236    dir_cmd(".msgs", messages_list);
237    dir_cmd(".pools", pool_list);
238    dir_cmd(".storage", storage_list);
239    dir_cmd(".types", type_list);
240    dir_cmd(".levels", level_list);
241
242    mainWin->set_status(_("Connected"));
243    startTimer();                      /* start message timer */
244    return;
245 }
246
247 bool Console::dir_cmd(QString &cmd, QStringList &results)
248 {
249    return dir_cmd(cmd.toUtf8().data(), results);
250 }
251
252 /*
253  * Send a command to the Director, and return the
254  *  results in a QStringList.  
255  */
256 bool Console::dir_cmd(const char *cmd, QStringList &results)
257 {
258    int stat;
259
260    notify(false);
261    write(cmd);
262    while ((stat = read()) > 0) {
263       if (mainWin->m_displayAll) display_text(msg());
264       strip_trailing_junk(msg());
265       results << msg();
266    }
267    notify(true);
268    discardToPrompt();
269    return true;              /* ***FIXME*** return any command error */
270 }
271
272 bool Console::sql_cmd(QString &query, QStringList &results)
273 {
274    return sql_cmd(query.toUtf8().data(), results);
275 }
276
277 /*
278  * Send an sql query to the Director, and return the
279  *  results in a QStringList.  
280  */
281 bool Console::sql_cmd(const char *query, QStringList &results)
282 {
283    int stat;
284    POOL_MEM cmd(PM_MESSAGE);
285
286    if (!is_connectedGui()) {
287       return false;
288    }
289
290    notify(false);
291    
292    pm_strcpy(cmd, ".sql query=\"");
293    pm_strcat(cmd, query);
294    pm_strcat(cmd, "\"");
295    write(cmd.c_str());
296    while ((stat = read()) > 0) {
297       if (mainWin->m_displayAll) display_text(msg());
298       strip_trailing_junk(msg());
299       results << msg();
300    }
301    notify(true);
302    discardToPrompt();
303    return true;              /* ***FIXME*** return any command error */
304 }
305
306
307 /*  
308  * Send a job name to the director, and read all the resulting
309  *  defaults. 
310  */
311 bool Console::get_job_defaults(struct job_defaults &job_defs)
312 {
313    QString scmd;
314    int stat;
315    char *def;
316
317    notify(false);
318    beginNewCommand();
319    scmd = QString(".defaults job=\"%1\"").arg(job_defs.job_name);
320    write(scmd);
321    while ((stat = read()) > 0) {
322       if (mainWin->m_displayAll) display_text(msg());
323       def = strchr(msg(), '=');
324       if (!def) {
325          continue;
326       }
327       /* Pointer to default value */
328       *def++ = 0;
329       strip_trailing_junk(def);
330
331       if (strcmp(msg(), "job") == 0) {
332          if (strcmp(def, job_defs.job_name.toUtf8().data()) != 0) {
333             goto bail_out;
334          }
335          continue;
336       }
337       if (strcmp(msg(), "pool") == 0) {
338          job_defs.pool_name = def;
339          continue;
340       }
341       if (strcmp(msg(), "messages") == 0) {
342          job_defs.messages_name = def;
343          continue;
344       }
345       if (strcmp(msg(), "client") == 0) {
346          job_defs.client_name = def;
347          continue;
348       }
349       if (strcmp(msg(), "storage") == 0) {
350          job_defs.store_name = def;
351          continue;
352       }
353       if (strcmp(msg(), "where") == 0) {
354          job_defs.where = def;
355          continue;
356       }
357       if (strcmp(msg(), "level") == 0) {
358          job_defs.level = def;
359          continue;
360       }
361       if (strcmp(msg(), "type") == 0) {
362          job_defs.type = def;
363          continue;
364       }
365       if (strcmp(msg(), "fileset") == 0) {
366          job_defs.fileset_name = def;
367          continue;
368       }
369       if (strcmp(msg(), "catalog") == 0) {
370          job_defs.catalog_name = def;
371          continue;
372       }
373       if (strcmp(msg(), "enabled") == 0) {
374          job_defs.enabled = *def == '1' ? true : false;
375          continue;
376       }
377    }
378
379    notify(true);
380    return true;
381
382 bail_out:
383    notify(true);
384    return false;
385 }
386
387
388 /*
389  * Save user settings associated with this console
390  */
391 void Console::writeSettings()
392 {
393    QFont font = get_font();
394
395    QSettings settings(m_dir->name(), "bat");
396    settings.beginGroup("Console");
397    settings.setValue("consoleFont", font.family());
398    settings.setValue("consolePointSize", font.pointSize());
399    settings.setValue("consoleFixedPitch", font.fixedPitch());
400    settings.endGroup();
401 }
402
403 /*
404  * Read and restore user settings associated with this console
405  */
406 void Console::readSettings()
407
408    QFont font = get_font();
409
410    QSettings settings(m_dir->name(), "bat");
411    settings.beginGroup("Console");
412    font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
413    font.setPointSize(settings.value("consolePointSize", 10).toInt());
414    font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
415    settings.endGroup();
416    m_textEdit->setFont(font);
417 }
418
419 /*
420  * Set the console textEdit font
421  */
422 void Console::set_font()
423 {
424    bool ok;
425    QFont font = QFontDialog::getFont(&ok, QFont(m_textEdit->font()), this);
426    if (ok) {
427       m_textEdit->setFont(font);
428    }
429 }
430
431 /*
432  * Get the console text edit font
433  */
434 const QFont Console::get_font()
435 {
436    return m_textEdit->font();
437 }
438
439 /*
440  * Slot for responding to status dir button on button bar
441  */
442 void Console::status_dir()
443 {
444    QString cmd("status dir");
445    consoleCommand(cmd);
446 }
447
448 /*
449  * Slot for responding to messages button on button bar
450  */
451 void Console::messages()
452 {
453    QString cmd(".messages");
454    consoleCommand(cmd);
455 }
456
457 /*
458  * Put text into the console window
459  */
460 void Console::display_textf(const char *fmt, ...)
461 {
462    va_list arg_ptr;
463    char buf[1000];
464    int len;
465    va_start(arg_ptr, fmt);
466    len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
467    va_end(arg_ptr);
468    display_text(buf);
469 }
470
471 void Console::display_text(const QString buf)
472 {
473    m_cursor->insertText(buf);
474    update_cursor();
475 }
476
477
478 void Console::display_text(const char *buf)
479 {
480    m_cursor->insertText(buf);
481    update_cursor();
482 }
483
484 void Console::display_html(const QString buf)
485 {
486    m_cursor->insertHtml(buf);
487    update_cursor();
488 }
489
490 /* Position cursor to end of screen */
491 void Console::update_cursor()
492 {
493    QApplication::restoreOverrideCursor();
494    m_textEdit->moveCursor(QTextCursor::End);
495    m_textEdit->ensureCursorVisible();
496 }
497
498 /* 
499  * This should be moved into a bSocket class 
500  */
501 char *Console::msg()
502 {
503    if (m_sock) {
504       return m_sock->msg;
505    }
506    return NULL;
507 }
508
509 /* Send a command to the Director */
510 void Console::write_dir(const char *msg)
511 {
512    if (m_sock) {
513       mainWin->set_status(_("Processing command ..."));
514       QApplication::setOverrideCursor(Qt::WaitCursor);
515       write(msg);
516    } else {
517       mainWin->set_status(" Director not connected. Click on connect button.");
518       mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
519       QBrush redBrush(Qt::red);
520       QTreeWidgetItem *item = mainWin->getFromHash(this);
521       item->setForeground(0, redBrush);
522       m_at_prompt = false;
523       m_at_main_prompt = false;
524    }
525 }
526
527 int Console::write(const QString msg)
528 {
529    return write(msg.toUtf8().data());
530 }
531
532 int Console::write(const char *msg)
533 {
534    if (!m_sock) {
535       return -1;
536    }
537    m_sock->msglen = pm_strcpy(m_sock->msg, msg);
538    m_at_prompt = false;
539    m_at_main_prompt = false;
540    if (mainWin->m_commDebug) Pmsg1(000, "send: %s\n", msg);
541    return m_sock->send();
542
543 }
544
545 /*
546  * Get to main command prompt -- i.e. abort any subcommand
547  */
548 void Console::beginNewCommand()
549 {
550    for (int i=0; i < 3; i++) {
551       write(".\n");
552       while (read() > 0) {
553          if (mainWin->m_displayAll) display_text(msg());
554       }
555       if (m_at_main_prompt) {
556          break;
557       }
558    }
559    display_text("\n");
560 }
561
562 void Console::displayToPrompt()
563
564    int stat = 0;
565    if (mainWin->m_commDebug) Pmsg0(000, "DisplaytoPrompt\n");
566    while (!m_at_prompt) {
567       if ((stat=read()) > 0) {
568          display_text(msg());
569       }
570    }
571    if (mainWin->m_commDebug) Pmsg1(000, "endDisplaytoPrompt=%d\n", stat);
572 }
573
574 void Console::discardToPrompt()
575
576    int stat = 0;
577    if (mainWin->m_commDebug) Pmsg0(000, "discardToPrompt\n");
578    while (!m_at_prompt) {
579       if ((stat=read()) > 0) {
580          if (mainWin->m_displayAll) display_text(msg());
581       }
582    }
583    if (mainWin->m_commDebug) Pmsg1(000, "endDisplayToPrompt=%d\n", stat);
584 }
585
586
587 /* 
588  * Blocking read from director
589  */
590 int Console::read()
591 {
592    int stat = 0;
593    while (m_sock) {
594       for (;;) {
595          stat = bnet_wait_data_intr(m_sock, 1);
596          if (stat > 0) {
597             break;
598          } 
599          app->processEvents();
600          if (m_api_set && m_messages_pending) {
601             write_dir(".messages");
602             m_messages_pending = false;
603          }
604       }
605       stat = m_sock->recv();
606       if (stat >= 0) {
607          if (m_at_prompt) {
608             display_text("\n");
609             m_at_prompt = false;
610             m_at_main_prompt = false;
611          }
612          if (mainWin->m_commDebug) Pmsg1(000, "got: %s", m_sock->msg);
613       }
614       switch (m_sock->msglen) {
615       case BNET_MSGS_PENDING:
616          if (mainWin->m_commDebug) Pmsg0(000, "MSGS PENDING\n");
617          write_dir(".messages");
618          displayToPrompt();
619          m_messages_pending = false;
620          continue;
621       case BNET_CMD_OK:
622          if (mainWin->m_commDebug) Pmsg0(000, "CMD OK\n");
623          m_at_prompt = false;
624          m_at_main_prompt = false;
625          continue;
626       case BNET_CMD_BEGIN:
627          if (mainWin->m_commDebug) Pmsg0(000, "CMD BEGIN\n");
628          m_at_prompt = false;
629          m_at_main_prompt = false;
630          continue;
631       case BNET_MAIN_PROMPT:
632          if (mainWin->m_commDebug) Pmsg0(000, "MAIN PROMPT\n");
633          m_at_prompt = true;
634          m_at_main_prompt = true;
635          mainWin->set_status(_("At main prompt waiting for input ..."));
636          QApplication::restoreOverrideCursor();
637          break;
638       case BNET_PROMPT:
639          if (mainWin->m_commDebug) Pmsg0(000, "PROMPT\n");
640          m_at_prompt = true;
641          m_at_main_prompt = false;
642          mainWin->set_status(_("At prompt waiting for input ..."));
643          QApplication::restoreOverrideCursor();
644          break;
645       case BNET_CMD_FAILED:
646          if (mainWin->m_commDebug) Pmsg0(000, "CMD FAILED\n");
647          mainWin->set_status(_("Command failed."));
648          QApplication::restoreOverrideCursor();
649          break;
650       /* We should not get this one */
651       case BNET_EOD:
652          if (mainWin->m_commDebug) Pmsg0(000, "EOD\n");
653          mainWin->set_status_ready();
654          QApplication::restoreOverrideCursor();
655          if (!m_api_set) {
656             break;
657          }
658          continue;
659       case BNET_START_SELECT:
660          if (mainWin->m_commDebug) Pmsg0(000, "START SELECT\n");
661          new selectDialog(this);    
662          break;
663       case BNET_RUN_CMD:
664          if (mainWin->m_commDebug) Pmsg0(000, "RUN CMD\n");
665          new runCmdPage();
666          break;
667       case BNET_ERROR_MSG:
668          if (mainWin->m_commDebug) Pmsg0(000, "ERROR MSG\n");
669          m_sock->recv();              /* get the message */
670          display_text(msg());
671          QMessageBox::critical(this, "Error", msg(), QMessageBox::Ok);
672          break;
673       case BNET_WARNING_MSG:
674          if (mainWin->m_commDebug) Pmsg0(000, "WARNING MSG\n");
675          m_sock->recv();              /* get the message */
676          display_text(msg());
677          QMessageBox::critical(this, "Warning", msg(), QMessageBox::Ok);
678          break;
679       case BNET_INFO_MSG:
680          if (mainWin->m_commDebug) Pmsg0(000, "INFO MSG\n");
681          m_sock->recv();              /* get the message */
682          display_text(msg());
683          mainWin->set_status(msg());
684          break;
685       }
686       if (is_bnet_stop(m_sock)) {         /* error or term request */
687          if (mainWin->m_commDebug) Pmsg0(000, "BNET STOP\n");
688          stopTimer();
689          m_sock->close();
690          m_sock = NULL;
691          mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
692          QBrush redBrush(Qt::red);
693          QTreeWidgetItem *item = mainWin->getFromHash(this);
694          item->setForeground(0, redBrush);
695          m_notifier->setEnabled(false);
696          delete m_notifier;
697          m_notifier = NULL;
698          mainWin->set_status(_("Director disconnected."));
699          QApplication::restoreOverrideCursor();
700          stat = BNET_HARDEOF;
701       }
702       break;
703    } 
704    return stat;
705 }
706
707 /* Called by signal when the Director has output for us */
708 void Console::read_dir(int /* fd */)
709 {
710    if (mainWin->m_commDebug) Pmsg0(000, "read_dir\n");
711    while (read() >= 0) {
712       display_text(msg());
713    }
714 }
715
716 /*
717  * When the notifier is enabled, read_dir() will automatically be
718  * called by the Qt event loop when ever there is any output 
719  * from the Directory, and read_dir() will then display it on
720  * the console.
721  *
722  * When we are in a bat dialog, we want to control *all* output
723  * from the Directory, so we set notify to off.
724  *    m_console->notifiy(false);
725  */
726 void Console::notify(bool enable) 
727
728    m_notifier->setEnabled(enable);   
729 }
730
731 void Console::setDirectorTreeItem(QTreeWidgetItem *item)
732 {
733    m_directorTreeItem = item;
734 }
735
736 void Console::setDirRes(DIRRES *dir) 
737
738    m_dir = dir;
739 }
740
741 /*
742  * To have the ability to get the name of the director resource.
743  */
744 void Console::getDirResName(QString &name_returned)
745 {
746    name_returned = m_dir->name();
747 }
748
749 bool Console::is_connectedGui()
750 {
751    if (is_connected()) {
752       return true;
753    } else {
754       QString message("Director ");
755       message += " is curerntly disconnected\n  Please reconnect!!";
756       QMessageBox::warning(this, "Bat",
757          tr(message.toUtf8().data()), QMessageBox::Ok );
758       return false;
759    }
760 }
761
762 /*
763  * A temporary function to prevent connecting to the director if the director
764  * is busy with a restore.
765  */
766 bool Console::preventInUseConnect()
767 {
768    if (!is_connected()) {
769       QString message("Director ");
770       message += m_dir->name();
771       message += " is curerntly disconnected\n  Please reconnect!!";
772       QMessageBox::warning(this, "Bat",
773          tr(message.toUtf8().data()), QMessageBox::Ok );
774       return false;
775    } else if (!m_at_main_prompt){
776       QString message("Director ");
777       message += m_dir->name();
778       message += " is curerntly busy\n  Please complete restore or other "
779                  " operation !!  This is a limitation that will be resolved before a beta"
780                  " release.  This is currently an alpha release.";
781       QMessageBox::warning(this, "Bat",
782          tr(message.toUtf8().data()), QMessageBox::Ok );
783       return false;
784    } else if (!m_at_prompt){
785       QString message("Director ");
786       message += m_dir->name();
787       message += " is curerntly not at a prompt\n  Please try again!!";
788       QMessageBox::warning(this, "Bat",
789          tr(message.toUtf8().data()), QMessageBox::Ok );
790       return false;
791    } else {
792       return true;
793    }
794 }
795
796 /*
797  * Call-back for reading a passphrase for an encrypted PEM file
798  * This function uses getpass(), 
799  *  which uses a static buffer and is NOT thread-safe.
800  */
801 static int tls_pem_callback(char *buf, int size, const void *userdata)
802 {
803    (void)size;
804    (void)userdata;
805 #ifdef HAVE_TLS
806    const char *prompt = (const char *)userdata;
807 # if defined(HAVE_WIN32)
808    sendit(prompt);
809    if (win32_cgets(buf, size) == NULL) {
810       buf[0] = 0;
811       return 0;
812    } else {
813       return strlen(buf);
814    }
815 # else
816    char *passwd;
817
818    passwd = getpass(prompt);
819    bstrncpy(buf, passwd, size);
820    return strlen(buf);
821 # endif
822 #else
823    buf[0] = 0;
824    return 0;
825 #endif
826 }
827
828 /* Slot for responding to page selectors status help command */
829 void Console::consoleHelp()
830 {
831    QString cmd("help");
832    consoleCommand(cmd);
833 }
834
835 /* Slot for responding to page selectors reload bacula-dir.conf */
836 void Console::consoleReload()
837 {
838    QString cmd("reload");
839    consoleCommand(cmd);
840 }