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