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