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