]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/console/console.cpp
Merge branch 'master' into basejobv3
[bacula/bacula] / bacula / src / qt-console / console / console.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2009 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 Kern Sibbald.
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 Console::Console(QTabWidget *parent)
44 {
45    QFont font;
46    m_name = tr("Console");
47    m_messages_pending = false;
48    m_parent = parent;
49    m_closeable = false;
50    m_console = this;
51    m_warningPrevent = false;
52    m_dircommCounter = 0;
53
54    /* 
55     * Create a connection to the Director and put it in a hash table
56     */
57    m_dircommHash.insert(m_dircommCounter, new DirComm(this, m_dircommCounter));
58
59    setupUi(this);
60    m_textEdit = textEdit;   /* our console screen */
61    m_cursor = new QTextCursor(m_textEdit->document());
62    mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
63
64    m_timer = NULL;
65    m_contextActions.append(actionStatusDir);
66    m_contextActions.append(actionConsoleHelp);
67    m_contextActions.append(actionRequestMessages);
68    m_contextActions.append(actionConsoleReload);
69    connect(actionStatusDir, SIGNAL(triggered()), this, SLOT(status_dir()));
70    connect(actionConsoleHelp, SIGNAL(triggered()), this, SLOT(consoleHelp()));
71    connect(actionConsoleReload, SIGNAL(triggered()), this, SLOT(consoleReload()));
72    connect(actionRequestMessages, SIGNAL(triggered()), this, SLOT(messages()));
73 }
74
75 Console::~Console()
76 {
77 }
78
79 void Console::startTimer()
80 {
81    m_timer = new QTimer(this);
82    QWidget::connect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
83    m_timer->start(mainWin->m_checkMessagesInterval*1000);
84 }
85
86 void Console::stopTimer()
87 {
88    if (m_timer) {
89       QWidget::disconnect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
90       m_timer->stop();
91       delete m_timer;
92       m_timer = NULL;
93    }
94 }
95
96 /* slot connected to the timer
97  * requires preferences of check messages and operates at interval */
98 void Console::poll_messages()
99 {
100    int conn;
101    if (!availableDirComm(conn))
102       return;
103    DirComm *dircomm = m_dircommHash.value(conn);
104
105    if (mainWin->m_checkMessages && dircomm->m_at_main_prompt && hasFocus() && !mainWin->getWaitState()){
106       messagesPending(true);
107       dircomm->write(".messages");
108       displayToPrompt(conn);
109       messagesPending(false);
110    }
111 }
112
113 /*
114  * Connect to Director.  This does not connect to the director, dircomm does.
115  * This creates the first and possibly 2nd dircomm instance
116  */
117 void Console::connect_dir()
118 {
119    DirComm *dircomm = m_dircommHash.value(0);
120
121    if (!m_console->m_dir) {
122       mainWin->set_status( tr("No Director found."));
123       return;
124    }
125
126    m_textEdit = textEdit;   /* our console screen */
127
128    if (dircomm->connect_dir()) {
129       if (mainWin->m_connDebug)
130          Pmsg1(000, "DirComm 0 Seems to have Connected %s\n", m_dir->name());
131       beginNewCommand(0);
132    }
133    mainWin->set_status(_("Connected"));
134    
135    startTimer();                      /* start message timer */
136 }
137
138 /*
139  * A function created to separate out the population of the lists
140  * from the Console::connect_dir function
141  */
142 void Console::populateLists(bool forcenew)
143 {
144    int conn;
145    if (forcenew) {
146       if (!newDirComm(conn)) {
147          Pmsg1(000, "newDirComm Seems to Failed to create a connection for populateLists %s\n", m_dir->name());
148          return;
149       }
150    } else {
151       if (!availableDirComm(conn)) {
152          Pmsg1(000, "availableDirComm Seems to Failed to find a connection for populateListsi %s\n", m_dir->name());
153          return;
154       }
155    }
156    populateLists(conn);
157 }
158
159 void Console::populateLists(int conn)
160 {
161    job_list.clear();
162    client_list.clear();
163    fileset_list.clear();
164    messages_list.clear();
165    pool_list.clear();
166    storage_list.clear();
167    type_list.clear();
168    level_list.clear();
169    dir_cmd(conn, ".jobs", job_list);
170    dir_cmd(conn, ".clients", client_list);
171    dir_cmd(conn, ".filesets", fileset_list);  
172    dir_cmd(conn, ".msgs", messages_list);
173    dir_cmd(conn, ".pools", pool_list);
174    dir_cmd(conn, ".storage", storage_list);
175    dir_cmd(conn, ".types", type_list);
176    dir_cmd(conn, ".levels", level_list);
177
178    if (mainWin->m_connDebug) {
179       QString dbgmsg = QString("jobs=%1 clients=%2 filesets=%3 msgs=%4 pools=%5 storage=%6 types=%7 levels=%8 conn=%9 %10\n")
180         .arg(job_list.count()).arg(client_list.count()).arg(fileset_list.count()).arg(messages_list.count())
181         .arg(pool_list.count()).arg(storage_list.count()).arg(type_list.count()).arg(level_list.count())
182         .arg(conn).arg(m_dir->name());
183       Pmsg1(000, "%s", dbgmsg.toUtf8().data());
184    }
185    job_list.sort();
186    client_list.sort();
187    fileset_list.sort();
188    messages_list.sort();
189    pool_list.sort();
190    storage_list.sort();
191    type_list.sort();
192    level_list.sort();
193 }
194
195 /*
196  *  Overload function for dir_cmd with a QString
197  *  Ease of use
198  */
199 bool Console::dir_cmd(QString &cmd, QStringList &results)
200 {
201    return dir_cmd(cmd.toUtf8().data(), results);
202 }
203
204 /*
205  *  Overload function for dir_cmd, this is if connection is not worried about
206  */
207 bool Console::dir_cmd(const char *cmd, QStringList &results)
208 {
209    int conn;
210    if (availableDirComm(conn)) {
211       dir_cmd(conn, cmd, results);
212       return true;
213    } else {
214       Pmsg1(000, "dir_cmd Seems to Failed to find a connection %s\n", m_dir->name());
215       return false;
216    }
217 }
218
219 /*
220  * Send a command to the Director, and return the
221  *  results in a QStringList.  
222  */
223 bool Console::dir_cmd(int conn, const char *cmd, QStringList &results)
224 {
225    mainWin->waitEnter();
226    DirComm *dircomm = m_dircommHash.value(conn);
227    int stat;
228
229    if (mainWin->m_connDebug) {
230       QString dbgmsg = QString("dir_cmd conn %1 %2 %3\n").arg(conn).arg(m_dir->name()).arg(cmd);
231       Pmsg1(000, "%s", dbgmsg.toUtf8().data());
232    }
233    notify(conn, false);
234    dircomm->write(cmd);
235    while ((stat = dircomm->read()) > 0 && dircomm->is_in_command()) {
236       if (mainWin->m_displayAll) display_text(dircomm->msg());
237       strip_trailing_junk(dircomm->msg());
238       results << dircomm->msg();
239    }
240    if (stat > 0 && mainWin->m_displayAll) display_text(dircomm->msg());
241    notify(conn, true);
242    discardToPrompt(conn);
243    mainWin->waitExit();
244    return true;              /* ***FIXME*** return any command error */
245 }
246
247 /*
248  * OverLoads for sql_cmd
249  */
250 bool Console::sql_cmd(int &conn, QString &query, QStringList &results)
251 {
252    return sql_cmd(conn, query.toUtf8().data(), results, false);
253 }
254
255 bool Console::sql_cmd(QString &query, QStringList &results)
256 {
257    int conn;
258    if (!availableDirComm(conn))
259       return false;
260    return sql_cmd(conn, query.toUtf8().data(), results, true);
261 }
262
263 bool Console::sql_cmd(const char *query, QStringList &results)
264 {
265    int conn;
266    if (!availableDirComm(conn))
267       return false;
268    return sql_cmd(conn, query, results, true);
269 }
270
271 /*
272  * Send an sql query to the Director, and return the
273  *  results in a QStringList.  
274  */
275 bool Console::sql_cmd(int &conn, const char *query, QStringList &results, bool donotify)
276 {
277    DirComm *dircomm = m_dircommHash.value(conn);
278    int stat;
279    POOL_MEM cmd(PM_MESSAGE);
280
281    if (!is_connectedGui()) {
282       return false;
283    }
284
285    if (mainWin->m_connDebug)
286       Pmsg2(000, "sql_cmd conn %i %s\n", conn, query);
287    if (donotify)
288       dircomm->notify(false);
289    mainWin->waitEnter();
290    
291    pm_strcpy(cmd, ".sql query=\"");
292    pm_strcat(cmd, query);
293    pm_strcat(cmd, "\"");
294    dircomm->write(cmd.c_str());
295    while ((stat = dircomm->read()) > 0) {
296       bool first = true;
297       if (mainWin->m_displayAll) {
298          display_text(dircomm->msg());
299          display_text("\n");
300       }
301       strip_trailing_junk(dircomm->msg());
302       bool doappend = true;
303       if (first) {
304          QString dum = dircomm->msg();
305          if ((dum.left(6) == "*None*")) doappend = false;
306       }
307       if (doappend)
308          results << dircomm->msg();
309       first = false;
310    }
311    if (donotify)
312       dircomm->notify(true);
313    discardToPrompt(conn);
314    mainWin->waitExit();
315    return true;              /* ***FIXME*** return any command error */
316 }
317
318 /* 
319  * Overloads for
320  * Sending a command to the Director
321  */
322 int Console::write_dir(const char *msg)
323 {
324    int conn;
325    if (availableDirComm(conn))
326       write_dir(conn, msg);
327    return conn;
328 }
329
330 int Console::write_dir(const char *msg, bool dowait)
331 {
332    int conn;
333    if (availableDirComm(conn))
334       write_dir(conn, msg, dowait);
335    return conn;
336 }
337
338 void Console::write_dir(int conn, const char *msg)
339 {
340    write_dir(conn, msg, true);
341 }
342
343 /*
344  * Send a command to the Director
345  */
346 void Console::write_dir(int conn, const char *msg, bool dowait)
347 {
348    DirComm *dircomm = m_dircommHash.value(conn);
349
350    if (dircomm->m_sock) {
351       mainWin->set_status(_("Processing command ..."));
352       if (dowait)
353          mainWin->waitEnter();
354       dircomm->write(msg);
355       if (dowait)
356          mainWin->waitExit();
357    } else {
358       mainWin->set_status( tr(" Director not connected. Click on connect button."));
359       mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png"));
360       QBrush redBrush(Qt::red);
361       QTreeWidgetItem *item = mainWin->getFromHash(this);
362       item->setForeground(0, redBrush);
363       dircomm->m_at_prompt = false;
364       dircomm->m_at_main_prompt = false;
365    }
366 }
367
368 /*
369  * get_job_defaults overload
370  */
371 bool Console::get_job_defaults(struct job_defaults &job_defs)
372 {
373    int conn;
374    return get_job_defaults(conn, job_defs, true);
375 }
376
377 bool Console::get_job_defaults(int &conn, struct job_defaults &job_defs)
378 {
379    return get_job_defaults(conn, job_defs, false);
380 }
381
382 /*  
383  * Send a job name to the director, and read all the resulting
384  *  defaults. 
385  */
386 bool Console::get_job_defaults(int &conn, struct job_defaults &job_defs, bool donotify)
387 {
388    QString scmd;
389    int stat;
390    char *def;
391
392    if (donotify)
393       conn = notifyOff();
394    beginNewCommand(conn);
395    DirComm *dircomm = m_dircommHash.value(conn);
396    bool prevWaitState = mainWin->getWaitState();
397    if (!prevWaitState)
398       mainWin->waitEnter();
399    if (mainWin->m_connDebug)
400       Pmsg2(000, "job_defaults conn %i %s\n", conn, m_dir->name());
401    scmd = QString(".defaults job=\"%1\"").arg(job_defs.job_name);
402    dircomm->write(scmd);
403    while ((stat = dircomm->read()) > 0) {
404       if (mainWin->m_displayAll) display_text(dircomm->msg());
405       def = strchr(dircomm->msg(), '=');
406       if (!def) {
407          continue;
408       }
409       /* Pointer to default value */
410       *def++ = 0;
411       strip_trailing_junk(def);
412
413       if (strcmp(dircomm->msg(), "job") == 0) {
414          if (strcmp(def, job_defs.job_name.toUtf8().data()) != 0) {
415             goto bail_out;
416          }
417          continue;
418       }
419       if (strcmp(dircomm->msg(), "pool") == 0) {
420          job_defs.pool_name = def;
421          continue;
422       }
423       if (strcmp(dircomm->msg(), "messages") == 0) {
424          job_defs.messages_name = def;
425          continue;
426       }
427       if (strcmp(dircomm->msg(), "client") == 0) {
428          job_defs.client_name = def;
429          continue;
430       }
431       if (strcmp(dircomm->msg(), "storage") == 0) {
432          job_defs.store_name = def;
433          continue;
434       }
435       if (strcmp(dircomm->msg(), "where") == 0) {
436          job_defs.where = def;
437          continue;
438       }
439       if (strcmp(dircomm->msg(), "level") == 0) {
440          job_defs.level = def;
441          continue;
442       }
443       if (strcmp(dircomm->msg(), "type") == 0) {
444          job_defs.type = def;
445          continue;
446       }
447       if (strcmp(dircomm->msg(), "fileset") == 0) {
448          job_defs.fileset_name = def;
449          continue;
450       }
451       if (strcmp(dircomm->msg(), "catalog") == 0) {
452          job_defs.catalog_name = def;
453          continue;
454       }
455       if (strcmp(dircomm->msg(), "enabled") == 0) {
456          job_defs.enabled = *def == '1' ? true : false;
457          continue;
458       }
459    }
460
461    if (donotify)
462       notify(conn, true);
463    if (!prevWaitState)
464       mainWin->waitExit();
465    return true;
466
467 bail_out:
468    if (donotify)
469       notify(conn, true);
470    if (!prevWaitState)
471       mainWin->waitExit();
472    return false;
473 }
474
475
476 /*
477  * Save user settings associated with this console
478  */
479 void Console::writeSettings()
480 {
481    QFont font = get_font();
482
483    QSettings settings(m_dir->name(), "bat");
484    settings.beginGroup("Console");
485    settings.setValue("consoleFont", font.family());
486    settings.setValue("consolePointSize", font.pointSize());
487    settings.setValue("consoleFixedPitch", font.fixedPitch());
488    settings.endGroup();
489 }
490
491 /*
492  * Read and restore user settings associated with this console
493  */
494 void Console::readSettings()
495
496    QFont font = get_font();
497
498    QSettings settings(m_dir->name(), "bat");
499    settings.beginGroup("Console");
500    font.setFamily(settings.value("consoleFont", "Courier").value<QString>());
501    font.setPointSize(settings.value("consolePointSize", 10).toInt());
502    font.setFixedPitch(settings.value("consoleFixedPitch", true).toBool());
503    settings.endGroup();
504    m_textEdit->setFont(font);
505 }
506
507 /*
508  * Set the console textEdit font
509  */
510 void Console::set_font()
511 {
512    bool ok;
513    QFont font = QFontDialog::getFont(&ok, QFont(m_textEdit->font()), this);
514    if (ok) {
515       m_textEdit->setFont(font);
516    }
517 }
518
519 /*
520  * Get the console text edit font
521  */
522 const QFont Console::get_font()
523 {
524    return m_textEdit->font();
525 }
526
527 /*
528  * Slot for responding to status dir button on button bar
529  */
530 void Console::status_dir()
531 {
532    QString cmd("status dir");
533    consoleCommand(cmd);
534 }
535
536 /*
537  * Slot for responding to messages button on button bar
538  * Here we want to bring the console to the front so use pages' consoleCommand
539  */
540 void Console::messages()
541 {
542    QString cmd(".messages");
543    consoleCommand(cmd);
544    messagesPending(false);
545 }
546
547 /*
548  * Put text into the console window
549  */
550 void Console::display_textf(const char *fmt, ...)
551 {
552    va_list arg_ptr;
553    char buf[1000];
554    int len;
555    va_start(arg_ptr, fmt);
556    len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
557    va_end(arg_ptr);
558    display_text(buf);
559 }
560
561 void Console::display_text(const QString buf)
562 {
563    m_cursor->insertText(buf);
564    update_cursor();
565 }
566
567
568 void Console::display_text(const char *buf)
569 {
570    m_cursor->insertText(buf);
571    update_cursor();
572 }
573
574 void Console::display_html(const QString buf)
575 {
576    m_cursor->insertHtml(buf);
577    update_cursor();
578 }
579
580 /* Position cursor to end of screen */
581 void Console::update_cursor()
582 {
583    m_textEdit->moveCursor(QTextCursor::End);
584    m_textEdit->ensureCursorVisible();
585 }
586
587 void Console::beginNewCommand(int conn)
588 {
589    DirComm *dircomm = m_dircommHash.value(conn);
590
591    for (int i=0; i < 3; i++) {
592       dircomm->write(".");
593       while (dircomm->read() > 0) {
594          Pmsg2(000, "begin new command loop %i %s\n", i, m_dir->name());
595          if (mainWin->m_displayAll) display_text(dircomm->msg());
596       }
597       if (dircomm->m_at_main_prompt) {
598          break;
599       }
600    }
601    display_text("\n");
602 }
603
604 void Console::displayToPrompt(int conn)
605
606    DirComm *dircomm = m_dircommHash.value(conn);
607
608    int stat = 0;
609    QString buf;
610    if (mainWin->m_commDebug) Pmsg1(000, "DisplaytoPrompt %s\n", m_dir->name());
611    while (!dircomm->m_at_prompt) {
612       if ((stat=dircomm->read()) > 0) {
613          buf += dircomm->msg();
614          if (buf.size() >= 8196 || m_messages_pending) {
615             display_text(buf);
616             buf.clear();
617             messagesPending(false);
618          }
619       }
620    }
621    display_text(buf);
622    if (mainWin->m_commDebug) Pmsg2(000, "endDisplaytoPrompt=%d %s\n", stat, m_dir->name());
623 }
624
625 void Console::discardToPrompt(int conn)
626 {
627    DirComm *dircomm = m_dircommHash.value(conn);
628
629    int stat = 0;
630    if (mainWin->m_commDebug) Pmsg1(000, "discardToPrompt %s\n", m_dir->name());
631    if (mainWin->m_displayAll) {
632       displayToPrompt(conn);
633    } else {
634       while (!dircomm->m_at_prompt) {
635          stat = dircomm->read();
636          if (stat < 0) {
637             break;
638          }
639       }
640    }
641    if (mainWin->m_commDebug) Pmsg2(000, "endDiscardToPrompt=%d %s\n", stat, m_dir->name());
642 }
643
644 QString Console::returnFromPrompt(int conn)
645
646    DirComm *dircomm = m_dircommHash.value(conn);
647    QString text("");
648
649    int stat = 0;
650    text = "";
651    if (mainWin->m_commDebug) Pmsg1(000, "returnFromPrompt %s\n", m_dir->name());
652    while (!dircomm->m_at_prompt) {
653       if ((stat=dircomm->read()) > 0) {
654          text += dircomm->msg();
655       }
656    }
657    if (mainWin->m_commDebug) Pmsg2(000, "endreturnFromPrompt=%d %s\n", stat, m_dir->name());
658    return text;
659 }
660
661 /*
662  * When the notifier is enabled, read_dir() will automatically be
663  * called by the Qt event loop when ever there is any output 
664  * from the Director, and read_dir() will then display it on
665  * the console.
666  *
667  * When we are in a bat dialog, we want to control *all* output
668  * from the Director, so we set notify to off.
669  *    m_console->notifiy(false);
670  */
671
672 /* dual purpose function to turn notify off and return an available connection */
673 int Console::notifyOff()
674
675    int conn = 0;
676    if (availableDirComm(conn))
677       notify(conn, false);
678    return conn;
679 }
680
681 /* knowing a connection, turn notify off or on */
682 bool Console::notify(int conn, bool enable)
683
684    DirComm *dircomm = m_dircommHash.value(conn);
685    return dircomm->notify(enable);
686 }
687
688 /* knowing a connection, return notify state */
689 bool Console::is_notify_enabled(int conn) const
690 {
691    DirComm *dircomm = m_dircommHash.value(conn);
692    return dircomm->is_notify_enabled();
693 }
694
695 void Console::setDirectorTreeItem(QTreeWidgetItem *item)
696 {
697    m_directorTreeItem = item;
698 }
699
700 void Console::setDirRes(DIRRES *dir) 
701
702    m_dir = dir;
703 }
704
705 /*
706  * To have the ability to get the name of the director resource.
707  */
708 void Console::getDirResName(QString &name_returned)
709 {
710    name_returned = m_dir->name();
711 }
712
713 /* Slot for responding to page selectors status help command */
714 void Console::consoleHelp()
715 {
716    QString cmd("help");
717    consoleCommand(cmd);
718 }
719
720 /* Slot for responding to page selectors reload bacula-dir.conf */
721 void Console::consoleReload()
722 {
723    QString cmd("reload");
724    consoleCommand(cmd);
725 }
726
727 /* For suppressing .messages
728  * This may be rendered not needed if the multiple connections feature gets working */
729 bool Console::hasFocus()
730 {
731    if (mainWin->tabWidget->currentIndex() == mainWin->tabWidget->indexOf(this))
732       return true;
733    else
734       return false;
735 }
736
737 /* For adding feature to have the gui's messages button change when 
738  * messages are pending */
739 bool Console::messagesPending(bool pend)
740 {
741    bool prev = m_messages_pending;
742    m_messages_pending = pend;
743    mainWin->setMessageIcon();
744    return prev;
745 }
746
747 /* terminate all existing connections */
748 void Console::terminate()
749 {
750    foreach(DirComm* dircomm,  m_dircommHash) {
751       dircomm->terminate();
752    }
753    m_console->stopTimer();
754 }
755
756 /* Maybe this should be checking the list, for the moment lets check 0 which should be connected */
757 bool Console::is_connectedGui()
758 {
759    if (is_connected(0)) {
760       return true;
761    } else {
762       QString message = tr("Director is currently disconnected\nPlease reconnect!");
763       QMessageBox::warning(this, "Bat", message, QMessageBox::Ok );
764       return false;
765    }
766 }
767
768 int Console::read(int conn)
769 {
770    DirComm *dircomm = m_dircommHash.value(conn);
771    return dircomm->read();
772 }
773
774 char *Console::msg(int conn)
775 {
776    DirComm *dircomm = m_dircommHash.value(conn);
777    return dircomm->msg();
778 }
779
780 int Console::write(int conn, const QString msg)
781 {
782    DirComm *dircomm = m_dircommHash.value(conn);
783    mainWin->waitEnter();
784    int ret = dircomm->write(msg);
785    mainWin->waitExit();
786    return ret;
787 }
788
789 int Console::write(int conn, const char *msg)
790 {
791    DirComm *dircomm = m_dircommHash.value(conn);
792    mainWin->waitEnter();
793    int ret = dircomm->write(msg);
794    mainWin->waitExit();
795    return ret;
796 }
797
798 /* This checks to see if any is connected */
799 bool Console::is_connected()
800 {
801    bool connected = false;
802    foreach(DirComm* dircomm,  m_dircommHash) {
803       if (dircomm->is_connected())
804          return true;
805    }
806    return connected;
807 }
808
809 /* knowing the connection id, is it connected */
810 bool Console::is_connected(int conn)
811 {
812    DirComm *dircomm = m_dircommHash.value(conn);
813    return dircomm->is_connected();
814 }
815
816 /*
817  * Need an available connection.  Check existing connections or create one
818  */
819 bool Console::availableDirComm(int &conn)
820 {
821    QHash<int, DirComm*>::const_iterator iter = m_dircommHash.constBegin();
822    while (iter != m_dircommHash.constEnd()) {
823       DirComm *dircomm = iter.value();
824       if (dircomm->m_at_prompt && dircomm->m_at_main_prompt && dircomm->is_notify_enabled()) {
825          conn = dircomm->m_conn;
826          return true;
827       }
828       ++iter;
829    }
830    if (newDirComm(conn))
831       return true;
832    else
833       return false;
834 }
835
836
837 /*
838  * Need current connection.
839  */
840 bool Console::currentDirComm(int &conn)
841 {
842    QHash<int, DirComm*>::const_iterator iter = m_dircommHash.constBegin();
843    while (iter != m_dircommHash.constEnd()) {
844       DirComm *dircomm = iter.value();
845       if (dircomm->m_at_prompt && !dircomm->m_at_main_prompt && dircomm->is_notify_enabled()) {
846          conn = dircomm->m_conn;
847          return true;
848       }
849       ++iter;
850    }
851    return false;
852 }
853
854 /*
855  *  Create a new connection
856  */
857 bool Console::newDirComm(int &conn)
858 {
859    m_dircommCounter += 1;
860    conn = m_dircommCounter;
861    if (mainWin->m_connDebug)
862       Pmsg2(000, "DirComm %i About to Create and Connect %s\n", m_dircommCounter, m_dir->name());
863    DirComm *dircomm = new DirComm(this, m_dircommCounter);
864    m_dircommHash.insert(m_dircommCounter, dircomm);
865    bool success = dircomm->connect_dir();
866    if (mainWin->m_connDebug) {
867       if (success)
868          Pmsg2(000, "DirComm %i Connected %s\n", conn, m_dir->name());
869       else
870          Pmsg2(000, "DirComm %i NOT Connected %s\n", conn, m_dir->name());
871    }
872    return success;
873 }