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