]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/console/console.cpp
patch to prevent writing ".messages" when notify is off.
[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_RUN_CMD:
686          if (mainWin->m_commDebug) Pmsg0(000, "RUN CMD\n");
687          new runCmdPage();
688          break;
689       case BNET_ERROR_MSG:
690          if (mainWin->m_commDebug) Pmsg0(000, "ERROR MSG\n");
691          m_sock->recv();              /* get the message */
692          display_text(msg());
693          QMessageBox::critical(this, "Error", msg(), QMessageBox::Ok);
694          break;
695       case BNET_WARNING_MSG:
696          if (mainWin->m_commDebug) Pmsg0(000, "WARNING MSG\n");
697          m_sock->recv();              /* get the message */
698          display_text(msg());
699          QMessageBox::critical(this, "Warning", msg(), QMessageBox::Ok);
700          break;
701       case BNET_INFO_MSG:
702          if (mainWin->m_commDebug) Pmsg0(000, "INFO MSG\n");
703          m_sock->recv();              /* get the message */
704          display_text(msg());
705          mainWin->set_status(msg());
706          break;
707       }
708       if (is_bnet_stop(m_sock)) {         /* error or term request */
709          if (mainWin->m_commDebug) Pmsg0(000, "BNET STOP\n");
710          stopTimer();
711          m_sock->close();
712          m_sock = NULL;
713          mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
714          QBrush redBrush(Qt::red);
715          QTreeWidgetItem *item = mainWin->getFromHash(this);
716          item->setForeground(0, redBrush);
717          m_notifier->setEnabled(false);
718          delete m_notifier;
719          m_notifier = NULL;
720          mainWin->set_status(_("Director disconnected."));
721          QApplication::restoreOverrideCursor();
722          stat = BNET_HARDEOF;
723       }
724       break;
725    } 
726    return stat;
727 }
728
729 /* Called by signal when the Director has output for us */
730 void Console::read_dir(int /* fd */)
731 {
732    if (mainWin->m_commDebug) Pmsg0(000, "read_dir\n");
733    while (read() >= 0) {
734       display_text(msg());
735    }
736 }
737
738 /*
739  * When the notifier is enabled, read_dir() will automatically be
740  * called by the Qt event loop when ever there is any output 
741  * from the Directory, and read_dir() will then display it on
742  * the console.
743  *
744  * When we are in a bat dialog, we want to control *all* output
745  * from the Directory, so we set notify to off.
746  *    m_console->notifiy(false);
747  */
748 void Console::notify(bool enable) 
749
750    m_notifier->setEnabled(enable);   
751 }
752
753 void Console::setDirectorTreeItem(QTreeWidgetItem *item)
754 {
755    m_directorTreeItem = item;
756 }
757
758 void Console::setDirRes(DIRRES *dir) 
759
760    m_dir = dir;
761 }
762
763 /*
764  * To have the ability to get the name of the director resource.
765  */
766 void Console::getDirResName(QString &name_returned)
767 {
768    name_returned = m_dir->name();
769 }
770
771 bool Console::is_connectedGui()
772 {
773    if (is_connected()) {
774       return true;
775    } else {
776       QString message("Director ");
777       message += " is currently disconnected\n  Please reconnect!!";
778       QMessageBox::warning(this, "Bat",
779          tr(message.toUtf8().data()), QMessageBox::Ok );
780       return false;
781    }
782 }
783
784 /*
785  * A temporary function to prevent connecting to the director if the director
786  * is busy with a restore.
787  */
788 bool Console::preventInUseConnect()
789 {
790    if (!is_connected()) {
791       QString message("Director ");
792       message += m_dir->name();
793       message += " is currently disconnected\n  Please reconnect!!";
794       QMessageBox::warning(this, "Bat",
795          tr(message.toUtf8().data()), QMessageBox::Ok );
796       return false;
797    } else if (!m_at_main_prompt){
798       QString message("Director ");
799       message += m_dir->name();
800       message += " is currently busy\n  Please complete restore or other "
801                  " operation !!  This is a limitation that will be resolved before a beta"
802                  " release.  This is currently an alpha release.";
803       QMessageBox::warning(this, "Bat",
804          tr(message.toUtf8().data()), QMessageBox::Ok );
805       return false;
806    } else if (!m_at_prompt){
807       QString message("Director ");
808       message += m_dir->name();
809       message += " is currently not at a prompt\n  Please try again!!";
810       QMessageBox::warning(this, "Bat",
811          tr(message.toUtf8().data()), QMessageBox::Ok );
812       return false;
813    } else {
814       return true;
815    }
816 }
817
818 /*
819  * Call-back for reading a passphrase for an encrypted PEM file
820  * This function uses getpass(), 
821  *  which uses a static buffer and is NOT thread-safe.
822  */
823 static int tls_pem_callback(char *buf, int size, const void *userdata)
824 {
825    (void)size;
826    (void)userdata;
827 #ifdef HAVE_TLS
828    const char *prompt = (const char *)userdata;
829 # if defined(HAVE_WIN32)
830    sendit(prompt);
831    if (win32_cgets(buf, size) == NULL) {
832       buf[0] = 0;
833       return 0;
834    } else {
835       return strlen(buf);
836    }
837 # else
838    char *passwd;
839
840    passwd = getpass(prompt);
841    bstrncpy(buf, passwd, size);
842    return strlen(buf);
843 # endif
844 #else
845    buf[0] = 0;
846    return 0;
847 #endif
848 }
849
850 /* Slot for responding to page selectors status help command */
851 void Console::consoleHelp()
852 {
853    QString cmd("help");
854    consoleCommand(cmd);
855 }
856
857 /* Slot for responding to page selectors reload bacula-dir.conf */
858 void Console::consoleReload()
859 {
860    QString cmd("reload");
861    consoleCommand(cmd);
862 }
863
864 /* Function to get a list of volumes */
865 void Console::getVolumeList(QStringList &volumeList)
866 {
867    QString query("SELECT VolumeName AS Media FROM Media ORDER BY Media");
868    if (mainWin->m_sqlDebug) {
869       Pmsg1(000, "Query cmd : %s\n",query.toUtf8().data());
870    }
871    QStringList results;
872    if (sql_cmd(query, results)) {
873       QString field;
874       QStringList fieldlist;
875       /* Iterate through the lines of results. */
876       foreach (QString resultline, results) {
877          fieldlist = resultline.split("\t");
878          volumeList.append(fieldlist[0]);
879       } /* foreach resultline */
880    } /* if results from query */
881 }
882
883 /* Function to get a list of volumes */
884 void Console::getStatusList(QStringList &statusLongList)
885 {
886    QString statusQuery("SELECT JobStatusLong FROM Status");
887    if (mainWin->m_sqlDebug) {
888       Pmsg1(000, "Query cmd : %s\n",statusQuery.toUtf8().data());
889    }
890    QStringList statusResults;
891    if (sql_cmd(statusQuery, statusResults)) {
892       QString field;
893       QStringList fieldlist;
894       /* Iterate through the lines of results. */
895       foreach (QString resultline, statusResults) {
896          fieldlist = resultline.split("\t");
897          statusLongList.append(fieldlist[0]);
898       } /* foreach resultline */
899    } /* if results from statusquery */
900 }