]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/status.c
kes Correct po warning message with datarootdir
[bacula/bacula] / bacula / src / stored / status.c
index db3a2c4c5eb250a932551a6342f7c8a6164a7b8c..a6050096a4ab090df26e8ab5c60a1b31a72c2545 100644 (file)
@@ -1,3 +1,30 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2003-2008 Free Software Foundation Europe e.V.
+
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation and included
+   in the file LICENSE.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
 /*
  *  This file handles the status command
  *
@@ -6,20 +33,6 @@
  *   Version $Id$
  *
  */
-/*
-   Copyright (C) 2003-2006 Kern Sibbald
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License
-   version 2 as amended with additional clauses defined in the
-   file LICENSE in the main source directory.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
-   the file LICENSE for additional details.
-
- */
 
 #include "bacula.h"
 #include "stored.h"
@@ -30,6 +43,7 @@
 extern BSOCK *filed_chan;
 extern int r_first, r_last;
 extern struct s_res resources[];
+extern void *start_heap;
 
 /* Static variables */
 static char qstatus[] = ".status %127s\n";
@@ -39,82 +53,93 @@ static char DotStatusJob[] = "JobId=%d JobStatus=%c JobErrors=%d\n";
 
 
 /* Forward referenced functions */
-static void send_blocked_status(DEVICE *dev, void sendit(const char *msg, int len, void *sarg), void *arg);
-static void list_terminated_jobs(void sendit(const char *msg, int len, void *sarg), void *arg);
-static void list_running_jobs(void sendit(const char *msg, int len, void *sarg), void *arg);
-static void list_jobs_waiting_on_reservation(void sendit(const char *msg, int len, void *sarg), void *arg);
-#if defined(HAVE_WIN32)
-static void win32_sendit(const char *msg, int len, void *arg);
-#endif
+static void sendit(const char *msg, int len, BSOCK *bs);
+static void sendit(POOL_MEM &msg, int len, BSOCK *bs);
+static void sendit(const char *msg, int len, void *arg);
+
+static void send_blocked_status(DEVICE *dev, BSOCK *bs);
+static void list_terminated_jobs(BSOCK *bs);
+static void list_running_jobs(BSOCK *bs);
+static void list_jobs_waiting_on_reservation(BSOCK *bs);
+static void list_status_header(BSOCK *bs);
+static void list_devices(BSOCK *bs);
 
 static const char *level_to_str(int level);
 
 /*
  * Status command from Director
  */
-bool do_status(void sendit(const char *msg, int len, void *sarg), void *arg)
+void output_status(BSOCK *bs)
 {
-   DEVRES *device;
-   AUTOCHANGER *changer;
-   DEVICE *dev;
-   char dt[MAX_TIME_LENGTH];
-   char *msg, b1[35], b2[35], b3[35], b4[35];
-   int bpb;
+   POOL_MEM msg(PM_MESSAGE);
    int len;
 
-   msg = (char *)get_pool_memory(PM_MESSAGE);
-
-   len = Mmsg(msg, _("%s Version: %s (%s) %s %s %s\n"), 
-              my_name, VERSION, BDATE, HOST_OS, DISTNAME, DISTVER);
-   sendit(msg, len, arg);
-
-   bstrftime_nc(dt, sizeof(dt), daemon_start_time);
-
-
-   len = Mmsg(msg, _("Daemon started %s, %d Job%s run since started.\n"),
-        dt, num_jobs_run, num_jobs_run == 1 ? "" : "s");
-   sendit(msg, len, arg);
-
-   len = Mmsg(msg, _(" Heap: bytes=%s max_bytes=%s bufs=%s max_bufs=%s\n"),
-         edit_uint64_with_commas(sm_bytes, b1),
-         edit_uint64_with_commas(sm_max_bytes, b2),
-         edit_uint64_with_commas(sm_buffers, b3),
-         edit_uint64_with_commas(sm_max_buffers, b4));
-   sendit(msg, len, arg);
+   list_status_header(bs);
 
    /*
     * List running jobs
     */
-   list_running_jobs(sendit, arg);
+   list_running_jobs(bs);
 
    /*
     * List jobs stuck in reservation system
     */
-   list_jobs_waiting_on_reservation(sendit, arg);
+   list_jobs_waiting_on_reservation(bs);
 
    /*
     * List terminated jobs
     */
-   list_terminated_jobs(sendit, arg);
+   list_terminated_jobs(bs);
 
    /*
     * List devices
     */
+   list_devices(bs);
+
+
+   len = Mmsg(msg, _("In Use Volume status:\n"));
+   sendit(msg, len, bs);
+
+   list_volumes(sendit, (void *)bs);
+   sendit("====\n\n", 6, bs);
+
+#ifdef xxx
+   if (debug_level > 10) {
+      bs->fsend(_("====\n\n"));
+      dump_resource(R_DEVICE, resources[R_DEVICE-r_first].res_head, sendit, user);
+      bs->fsend(_("====\n\n"));
+   }
+#endif
+
+   list_spool_stats(sendit, (void *)bs);
+}
+
+
+static void list_devices(BSOCK *bs)
+{
+   DEVRES *device;
+   AUTOCHANGER *changer;
+   DEVICE *dev;
+   char b1[35], b2[35], b3[35];
+   POOL_MEM msg(PM_MESSAGE);
+   int len;
+   int bpb;
+
    len = Mmsg(msg, _("\nDevice status:\n"));
-   sendit(msg, len, arg);
+   sendit(msg, len, bs);
 
    foreach_res(changer, R_AUTOCHANGER) {
       len = Mmsg(msg, _("Autochanger \"%s\" with devices:\n"),
          changer->hdr.name);
-      sendit(msg, len, arg);
+      sendit(msg, len, bs);
 
       foreach_alist(device, changer->device) {
          if (device->dev) {
             len = Mmsg(msg, "   %s\n", device->dev->print_name());
-            sendit(msg, len, arg);
+            sendit(msg, len, bs);
          } else {
             len = Mmsg(msg, "   %s\n", device->hdr.name);
-            sendit(msg, len, arg);
+            sendit(msg, len, bs);
          }
       }
    }
@@ -122,16 +147,21 @@ bool do_status(void sendit(const char *msg, int len, void *sarg), void *arg)
       dev = device->dev;
       if (dev && dev->is_open()) {
          if (dev->is_labeled()) {
-            len = Mmsg(msg, _("Device %s is mounted with Volume=\"%s\" Pool=\"%s\"\n"),
-               dev->print_name(), dev->VolHdr.VolumeName, 
-               dev->pool_name[0]?dev->pool_name:"*unknown*");
-            sendit(msg, len, arg);
+            len = Mmsg(msg, _("Device %s is mounted with:\n"
+                              "    Volume:      %s\n"
+                              "    Pool:        %s\n"
+                              "    Media type:  %s\n"),
+               dev->print_name(), 
+               dev->VolHdr.VolumeName, 
+               dev->pool_name[0]?dev->pool_name:"*unknown*",
+               dev->device->media_type);
+            sendit(msg, len, bs);
          } else {
-            len = Mmsg(msg, _("Device %s open but no Bacula volume is mounted.\n"), 
+            len = Mmsg(msg, _("Device %s open but no Bacula volume is currently mounted.\n"), 
                dev->print_name());
-            sendit(msg, len, arg);
+            sendit(msg, len, bs);
          }
-         send_blocked_status(dev, sendit, arg);
+         send_blocked_status(dev, bs);
          if (dev->can_append()) {
             bpb = dev->VolCatInfo.VolCatBlocks;
             if (bpb <= 0) {
@@ -142,7 +172,7 @@ bool do_status(void sendit(const char *msg, int len, void *sarg), void *arg)
                edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1),
                edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2),
                edit_uint64_with_commas(bpb, b3));
-            sendit(msg, len, arg);
+            sendit(msg, len, bs);
          } else {  /* reading */
             bpb = dev->VolCatInfo.VolCatReads;
             if (bpb <= 0) {
@@ -157,67 +187,76 @@ bool do_status(void sendit(const char *msg, int len, void *sarg), void *arg)
                edit_uint64_with_commas(dev->VolCatInfo.VolCatRBytes, b1),
                edit_uint64_with_commas(dev->VolCatInfo.VolCatReads, b2),
                edit_uint64_with_commas(bpb, b3));
-            sendit(msg, len, arg);
+            sendit(msg, len, bs);
          }
          len = Mmsg(msg, _("    Positioned at File=%s Block=%s\n"),
             edit_uint64_with_commas(dev->file, b1),
             edit_uint64_with_commas(dev->block_num, b2));
-         sendit(msg, len, arg);
+         sendit(msg, len, bs);
 
       } else {
          if (dev) {
             len = Mmsg(msg, _("Device %s is not open.\n"), dev->print_name());
-            sendit(msg, len, arg);
+            sendit(msg, len, bs);
+            send_blocked_status(dev, bs);
         } else {
             len = Mmsg(msg, _("Device \"%s\" is not open or does not exist.\n"), device->hdr.name);
-            sendit(msg, len, arg);
+            sendit(msg, len, bs);
          }
-         send_blocked_status(dev, sendit, arg);
       }
    }
-   len = Mmsg(msg, _("====\n\n"));
-   sendit(msg, len, arg);
-   len = Mmsg(msg, _("In Use Volume status:\n"));
-   sendit(msg, len, arg);
-   list_volumes(sendit, arg);
-   len = Mmsg(msg, _("====\n\n"));
-   sendit(msg, len, arg);
-       
-#ifdef xxx
-   if (debug_level > 10) {
-      bnet_fsend(user, _("====\n\n"));
-      dump_resource(R_DEVICE, resources[R_DEVICE-r_first].res_head, sendit, user);
-      bnet_fsend(user, _("====\n\n"));
-   }
-#endif
+   sendit("====\n\n", 6, bs);
+}
+
+static void list_status_header(BSOCK *bs)
+{
+   char dt[MAX_TIME_LENGTH];
+   char b1[35], b2[35], b3[35], b4[35], b5[35];
+   POOL_MEM msg(PM_MESSAGE);
+   int len;
 
-   list_spool_stats(sendit, arg);
+   len = Mmsg(msg, _("%s Version: %s (%s) %s %s %s\n"), 
+              my_name, VERSION, BDATE, HOST_OS, DISTNAME, DISTVER);
+   sendit(msg, len, bs);
 
-   free_pool_memory(msg);
-   return true;
+   bstrftime_nc(dt, sizeof(dt), daemon_start_time);
+
+
+   len = Mmsg(msg, _("Daemon started %s, %d Job%s run since started.\n"),
+        dt, num_jobs_run, num_jobs_run == 1 ? "" : "s");
+   sendit(msg, len, bs);
+
+   len = Mmsg(msg, _(" Heap: heap=%s smbytes=%s max_bytes=%s bufs=%s max_bufs=%s\n"),
+         edit_uint64_with_commas((char *)sbrk(0)-(char *)start_heap, b1),
+         edit_uint64_with_commas(sm_bytes, b2),
+         edit_uint64_with_commas(sm_max_bytes, b3),
+         edit_uint64_with_commas(sm_buffers, b4),
+         edit_uint64_with_commas(sm_max_buffers, b5));
+   sendit(msg, len, bs);
+   len = Mmsg(msg, "Sizes: boffset_t=%d size_t=%d int32_t=%d int64_t=%d\n", 
+         (int)sizeof(boffset_t), (int)sizeof(size_t), (int)sizeof(int32_t),
+         (int)sizeof(int64_t));
+   sendit(msg, len, bs);
 }
 
-static void send_blocked_status(DEVICE *dev, void sendit(const char *msg, int len, void *sarg), void *arg)
+static void send_blocked_status(DEVICE *dev, BSOCK *bs)
 {
-   char *msg;
+   POOL_MEM msg(PM_MESSAGE);
    int len;
 
-   msg = (char *)get_pool_memory(PM_MESSAGE);
-
    if (!dev) {
       len = Mmsg(msg, _("No DEVICE structure.\n\n"));
-      sendit(msg, len, arg);
-      free_pool_memory(msg);
+      sendit(msg, len, bs);
       return;
    }
-   switch (dev->dev_blocked) {
+   switch (dev->blocked()) {
    case BST_UNMOUNTED:
       len = Mmsg(msg, _("    Device is BLOCKED. User unmounted.\n"));
-      sendit(msg, len, arg);
+      sendit(msg, len, bs);
       break;
    case BST_UNMOUNTED_WAITING_FOR_SYSOP:
       len = Mmsg(msg, _("    Device is BLOCKED. User unmounted during wait for media/mount.\n"));
-      sendit(msg, len, arg);
+      sendit(msg, len, bs);
       break;
    case BST_WAITING_FOR_SYSOP:
       {
@@ -226,12 +265,23 @@ static void send_blocked_status(DEVICE *dev, void sendit(const char *msg, int le
 
          if (dcrs != NULL) {
             DCR *dcr;
-
             for (dcr = (DCR *)dcrs->first(); dcr != NULL; dcr = (DCR *)dcrs->next(dcr)) {
                if (dcr->jcr->JobStatus == JS_WaitMount) {
-                  len = Mmsg(msg, _("    Device is BLOCKED waiting for mount of volume \"%s\".\n"),
-                     dcr->VolumeName);
-                  sendit(msg, len, arg);
+                  len = Mmsg(msg, _("    Device is BLOCKED waiting for mount of volume \"%s\",\n"
+                                    "       Pool:        %s\n"
+                                    "       Media type:  %s\n"),
+                             dcr->VolumeName,
+                             dcr->pool_name,
+                             dcr->media_type);
+                  sendit(msg, len, bs);
+                  found_jcr = true;
+               } else if (dcr->jcr->JobStatus == JS_WaitMedia) {
+                  len = Mmsg(msg, _("    Device is BLOCKED waiting to create a volume for:\n"
+                                    "       Pool:        %s\n"
+                                    "       Media type:  %s\n"),
+                             dcr->pool_name,
+                             dcr->media_type);
+                  sendit(msg, len, bs);
                   found_jcr = true;
                }
             }
@@ -239,17 +289,17 @@ static void send_blocked_status(DEVICE *dev, void sendit(const char *msg, int le
 
          if (!found_jcr) {
             len = Mmsg(msg, _("    Device is BLOCKED waiting for media.\n"));
-            sendit(msg, len, arg);
+            sendit(msg, len, bs);
          }
       }
       break;
    case BST_DOING_ACQUIRE:
       len = Mmsg(msg, _("    Device is being initialized.\n"));
-      sendit(msg, len, arg);
+      sendit(msg, len, bs);
       break;
    case BST_WRITING_LABEL:
       len = Mmsg(msg, _("    Device is blocked labeling a Volume.\n"));
-      sendit(msg, len, arg);
+      sendit(msg, len, bs);
       break;
    default:
       break;
@@ -259,18 +309,18 @@ static void send_blocked_status(DEVICE *dev, void sendit(const char *msg, int le
       if (dev->Slot > 0) {
          len = Mmsg(msg, _("    Slot %d is loaded in drive %d.\n"), 
             dev->Slot, dev->drive_index);
-         sendit(msg, len, arg);
+         sendit(msg, len, bs);
       } else if (dev->Slot == 0) {
          len = Mmsg(msg, _("    Drive %d is not loaded.\n"), dev->drive_index);
-         sendit(msg, len, arg);
+         sendit(msg, len, bs);
       } else {
          len = Mmsg(msg, _("    Drive %d status unknown.\n"), dev->drive_index);
-         sendit(msg, len, arg);
+         sendit(msg, len, bs);
       }
    }
    if (debug_level > 1) {
       len = Mmsg(msg, _("Configured device capabilities:\n"));
-      sendit(msg, len, arg);
+      sendit(msg, len, bs);
 
       len = Mmsg(msg, "%sEOF %sBSR %sBSF %sFSR %sFSF %sEOM %sREM %sRACCESS %sAUTOMOUNT %sLABEL %sANONVOLS %sALWAYSOPEN\n",
          dev->capabilities & CAP_EOF ? "" : "!", 
@@ -285,10 +335,10 @@ static void send_blocked_status(DEVICE *dev, void sendit(const char *msg, int le
          dev->capabilities & CAP_LABEL ? "" : "!", 
          dev->capabilities & CAP_ANONVOLS ? "" : "!", 
          dev->capabilities & CAP_ALWAYSOPEN ? "" : "!");
-      sendit(msg, len, arg);
+      sendit(msg, len, bs);
 
       len = Mmsg(msg, _("Device state:\n"));
-      sendit(msg, len, arg);
+      sendit(msg, len, bs);
 
       len = Mmsg(msg, "%sOPENED %sTAPE %sLABEL %sMALLOC %sAPPEND %sREAD %sEOT %sWEOT %sEOF %sNEXTVOL %sSHORT %sMOUNTED\n", 
          dev->is_open() ? "" : "!", 
@@ -303,48 +353,45 @@ static void send_blocked_status(DEVICE *dev, void sendit(const char *msg, int le
          dev->state & ST_NEXTVOL ? "" : "!", 
          dev->state & ST_SHORT ? "" : "!", 
          dev->state & ST_MOUNTED ? "" : "!");
-      sendit(msg, len, arg);
+      sendit(msg, len, bs);
 
-      len = Mmsg(msg, _("num_writers=%d block=%d\n\n"), dev->num_writers, dev->dev_blocked);
-      sendit(msg, len, arg);
+      len = Mmsg(msg, _("num_writers=%d block=%d\n\n"), dev->num_writers, dev->blocked());
+      sendit(msg, len, bs);
 
       len = Mmsg(msg, _("Device parameters:\n"));
-      sendit(msg, len, arg);
+      sendit(msg, len, bs);
 
       len = Mmsg(msg, _("Archive name: %s Device name: %s\n"), dev->archive_name(),
          dev->name());
-      sendit(msg, len, arg);
+      sendit(msg, len, bs);
 
       len = Mmsg(msg, _("File=%u block=%u\n"), dev->file, dev->block_num);
-      sendit(msg, len, arg);
+      sendit(msg, len, bs);
 
       len = Mmsg(msg, _("Min block=%u Max block=%u\n"), dev->min_block_size, dev->max_block_size);
-      sendit(msg, len, arg);
+      sendit(msg, len, bs);
    }
-
-   free_pool_memory(msg);
 }
 
-static void list_running_jobs(void sendit(const char *msg, int len, void *sarg), void *arg)
+static void list_running_jobs(BSOCK *bs)
 {
    bool found = false;
    int bps, sec;
    JCR *jcr;
    DCR *dcr, *rdcr;
    char JobName[MAX_NAME_LENGTH];
-   char *msg, b1[30], b2[30], b3[30];
+   char b1[30], b2[30], b3[30];
    int len;
-
-   msg = (char *)get_pool_memory(PM_MESSAGE);
+   POOL_MEM msg(PM_MESSAGE);
 
    len = Mmsg(msg, _("\nRunning Jobs:\n"));
-   sendit(msg, len, arg);
+   sendit(msg, len, bs);
 
    foreach_jcr(jcr) {
       if (jcr->JobStatus == JS_WaitFD) {
          len = Mmsg(msg, _("%s Job %s waiting for Client connection.\n"),
             job_type_to_str(jcr->JobType), jcr->Job);
-         sendit(msg, len, arg);
+         sendit(msg, len, bs);
       }
       dcr = jcr->dcr;
       rdcr = jcr->read_dcr;
@@ -359,7 +406,7 @@ static void list_running_jobs(void sendit(const char *msg, int len, void *sarg),
          }
          if (rdcr && rdcr->device) {
             len = Mmsg(msg, _("Reading: %s %s job %s JobId=%d Volume=\"%s\"\n"
-                            "    pool=\"%s\" device=\"%s\"\n"),
+                            "    pool=\"%s\" device=%s\n"),
                    job_level_to_str(jcr->JobLevel),
                    job_type_to_str(jcr->JobType),
                    JobName,
@@ -368,11 +415,11 @@ static void list_running_jobs(void sendit(const char *msg, int len, void *sarg),
                    rdcr->pool_name,
                    rdcr->dev?rdcr->dev->print_name(): 
                             rdcr->device->device_name);
-            sendit(msg, len, arg);
+            sendit(msg, len, bs);
          }
          if (dcr && dcr->device) {
             len = Mmsg(msg, _("Writing: %s %s job %s JobId=%d Volume=\"%s\"\n"
-                            "    pool=\"%s\" device=\"%s\"\n"),
+                            "    pool=\"%s\" device=%s\n"),
                    job_level_to_str(jcr->JobLevel),
                    job_type_to_str(jcr->JobType),
                    JobName,
@@ -381,7 +428,10 @@ static void list_running_jobs(void sendit(const char *msg, int len, void *sarg),
                    dcr->pool_name,
                    dcr->dev?dcr->dev->print_name(): 
                             dcr->device->device_name);
-            sendit(msg, len, arg);
+            sendit(msg, len, bs);
+            len= Mmsg(msg, _("    spooling=%d despooling=%d despool_wait=%d\n"),
+                   dcr->spooling, dcr->despooling, dcr->despool_wait);
+            sendit(msg, len, bs);
          }
          sec = time(NULL) - jcr->run_time;
          if (sec <= 0) {
@@ -392,18 +442,18 @@ static void list_running_jobs(void sendit(const char *msg, int len, void *sarg),
             edit_uint64_with_commas(jcr->JobFiles, b1),
             edit_uint64_with_commas(jcr->JobBytes, b2),
             edit_uint64_with_commas(bps, b3));
-         sendit(msg, len, arg);
+         sendit(msg, len, bs);
          found = true;
 #ifdef DEBUG
          if (jcr->file_bsock) {
             len = Mmsg(msg, _("    FDReadSeqNo=%s in_msg=%u out_msg=%d fd=%d\n"),
                edit_uint64_with_commas(jcr->file_bsock->read_seqno, b1),
                jcr->file_bsock->in_msg_no, jcr->file_bsock->out_msg_no,
-               jcr->file_bsock->fd);
-            sendit(msg, len, arg);
+               jcr->file_bsock->m_fd);
+            sendit(msg, len, bs);
          } else {
             len = Mmsg(msg, _("    FDSocket closed\n"));
-            sendit(msg, len, arg);
+            sendit(msg, len, bs);
          }
 #endif
       }
@@ -412,54 +462,50 @@ static void list_running_jobs(void sendit(const char *msg, int len, void *sarg),
 
    if (!found) {
       len = Mmsg(msg, _("No Jobs running.\n"));
-      sendit(msg, len, arg);
+      sendit(msg, len, bs);
    }
-   len = Mmsg(msg, _("====\n"));
-   sendit(msg, len, arg);
-
-   free_pool_memory(msg);
+   sendit("====\n", 5, bs);
 }
 
-static void list_jobs_waiting_on_reservation(void sendit(const char *msg, int len, void *sarg), void *arg)
+static void list_jobs_waiting_on_reservation(BSOCK *bs)
 { 
    JCR *jcr;
-   char *msg;
+   POOL_MEM msg(PM_MESSAGE);
+   int len;
 
-   msg = _("\nJobs waiting to reserve a drive:\n");
-   sendit(msg, strlen(msg), arg);
+   len = Mmsg(msg, _("\nJobs waiting to reserve a drive:\n"));
+   sendit(msg, len, bs);
 
    foreach_jcr(jcr) {
       if (!jcr->reserve_msgs) {
          continue;
       }
-      send_drive_reserve_messages(jcr, sendit, arg);
+      send_drive_reserve_messages(jcr, sendit, bs);
    }
    endeach_jcr(jcr);
 
-   msg = _("====\n");
-   sendit(msg, strlen(msg), arg);
+   sendit("====\n", 5, bs);
 }
 
 
-static void list_terminated_jobs(void sendit(const char *msg, int len, void *sarg), void *arg)
+static void list_terminated_jobs(BSOCK *bs)
 {
    char dt[MAX_TIME_LENGTH], b1[30], b2[30];
    char level[10];
    struct s_last_job *je;
    const char *msg;
 
+   msg =  _("\nTerminated Jobs:\n");
+   sendit(msg, strlen(msg), bs);
    if (last_jobs->size() == 0) {
-      msg = _("No Terminated Jobs.\n");
-      sendit(msg, strlen(msg), arg);
+      sendit("====\n", 5, bs);
       return;
    }
    lock_last_jobs_list();
-   msg =  _("\nTerminated Jobs:\n");
-   sendit(msg, strlen(msg), arg);
    msg =  _(" JobId  Level    Files      Bytes   Status   Finished        Name \n");
-   sendit(msg, strlen(msg), arg);
+   sendit(msg, strlen(msg), bs);
    msg =  _("===================================================================\n");
-   sendit(msg, strlen(msg), arg);
+   sendit(msg, strlen(msg), bs);
    foreach_dlist(je, last_jobs) {
       char JobName[MAX_NAME_LENGTH];
       const char *termstat;
@@ -512,10 +558,10 @@ static void list_terminated_jobs(void sendit(const char *msg, int len, void *sar
          edit_uint64_with_suffix(je->JobBytes, b2),
          termstat,
          dt, JobName);
-      sendit(buf, strlen(buf), arg);
+      sendit(buf, strlen(buf), bs);
    }
-   sendit(_("====\n"), 5, arg);
    unlock_last_jobs_list();
+   sendit("====\n", 5, bs);
 }
 
 /*
@@ -568,26 +614,39 @@ static const char *level_to_str(int level)
 /*
  * Send to Director
  */
-static void bsock_sendit(const char *msg, int len, void *arg)
+static void sendit(const char *msg, int len, BSOCK *bs)
+{
+   memcpy(bs->msg, msg, len+1);
+   bs->msglen = len+1;
+   bs->send();
+}
+
+static void sendit(const char *msg, int len, void *arg)
 {
-   BSOCK *user = (BSOCK *)arg;
+   BSOCK *bs = (BSOCK *)arg;
+   memcpy(bs->msg, msg, len+1);
+   bs->msglen = len+1;
+   bs->send();
+}
 
-   memcpy(user->msg, msg, len+1);
-   user->msglen = len+1;
-   bnet_send(user);
+static void sendit(POOL_MEM &msg, int len, BSOCK *bs)
+{
+   memcpy(bs->msg, msg.c_str(), len+1);
+   bs->msglen = len+1;
+   bs->send();
 }
 
+
 /*
  * Status command from Director
  */
 bool status_cmd(JCR *jcr)
 {
-   BSOCK *user = jcr->dir_bsock;
+   BSOCK *bs = jcr->dir_bsock;
 
-   bnet_fsend(user, "\n");
-   do_status(bsock_sendit, (void *)user);
-
-   bnet_sig(user, BNET_EOD);
+   bs->fsend("\n");
+   output_status(bs);
+   bs->signal(BNET_EOD);
    return 1;
 }
 
@@ -604,80 +663,45 @@ bool qstatus_cmd(JCR *jcr)
    if (sscanf(dir->msg, qstatus, time.c_str()) != 1) {
       pm_strcpy(jcr->errmsg, dir->msg);
       Jmsg1(jcr, M_FATAL, 0, _("Bad .status command: %s\n"), jcr->errmsg);
-      bnet_fsend(dir, _("3900 Bad .status command, missing argument.\n"));
-      bnet_sig(dir, BNET_EOD);
+      dir->fsend(_("3900 Bad .status command, missing argument.\n"));
+      dir->signal(BNET_EOD);
       return false;
    }
    unbash_spaces(time);
 
    if (strcmp(time.c_str(), "current") == 0) {
-      bnet_fsend(dir, OKqstatus, time.c_str());
+      dir->fsend(OKqstatus, time.c_str());
       foreach_jcr(njcr) {
          if (njcr->JobId != 0) {
-            bnet_fsend(dir, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
+            dir->fsend(DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
          }
       }
       endeach_jcr(njcr);
    } else if (strcmp(time.c_str(), "last") == 0) {
-      bnet_fsend(dir, OKqstatus, time.c_str());
+      dir->fsend(OKqstatus, time.c_str());
       if ((last_jobs) && (last_jobs->size() > 0)) {
          job = (s_last_job*)last_jobs->last();
-         bnet_fsend(dir, DotStatusJob, job->JobId, job->JobStatus, job->Errors);
+         dir->fsend(DotStatusJob, job->JobId, job->JobStatus, job->Errors);
       }
    } else {
       pm_strcpy(jcr->errmsg, dir->msg);
       Jmsg1(jcr, M_FATAL, 0, _("Bad .status command: %s\n"), jcr->errmsg);
-      bnet_fsend(dir, _("3900 Bad .status command, wrong argument.\n"));
-      bnet_sig(dir, BNET_EOD);
+      dir->fsend(_("3900 Bad .status command, wrong argument.\n"));
+      dir->signal(BNET_EOD);
       return false;
    }
-   bnet_sig(dir, BNET_EOD);
+   dir->signal(BNET_EOD);
    return true;
 }
 
 #if defined(HAVE_WIN32)
 int bacstat = 0;
 
-struct s_win32_arg {
-   HWND hwnd;
-   int idlist;
-};
-
-/*
- * Put message in Window List Box
- */
-static void win32_sendit(const char *msg, int len, void *marg)
-{
-   struct s_win32_arg *arg = (struct s_win32_arg *)marg;
-
-   if (len > 0 && msg[len-1] == '\n') {
-       // when compiling with visual studio some strings are read-only
-       // and cause access violations.  So we creat a tmp copy.
-       char *_msg = (char *)alloca(len);
-       bstrncpy(_msg, msg, len);
-       msg = _msg;
-   }
-   SendDlgItemMessage(arg->hwnd, arg->idlist, LB_ADDSTRING, 0, (LONG)msg);
-
-}
-
-void FillStatusBox(HWND hwnd, int idlist)
-{
-   struct s_win32_arg arg;
-
-   arg.hwnd = hwnd;
-   arg.idlist = idlist;
-
-   /* Empty box */
-   for ( ; SendDlgItemMessage(hwnd, idlist, LB_DELETESTRING, 0, (LONG)0) > 0; )
-      { }
-   do_status(win32_sendit, (void *)&arg);
-}
-
+/* Return a one line status for the tray monitor */
 char *bac_status(char *buf, int buf_len)
 {
    JCR *njcr;
-   const char *termstat = _("Bacula Idle");
+   const char *termstat = _("Bacula Storage: Idle");
    struct s_last_job *job;
    int stat = 0;                      /* Idle */
 
@@ -688,7 +712,7 @@ char *bac_status(char *buf, int buf_len)
    foreach_jcr(njcr) {
       if (njcr->JobId != 0) {
          stat = JS_Running;
-         termstat = _("Bacula Running");
+         termstat = _("Bacula Storage: Running");
          break;
       }
    }
@@ -702,15 +726,15 @@ char *bac_status(char *buf, int buf_len)
       stat = job->JobStatus;
       switch (job->JobStatus) {
       case JS_Canceled:
-         termstat = _("Last Job Canceled");
+         termstat = _("Bacula Storage: Last Job Canceled");
          break;
       case JS_ErrorTerminated:
       case JS_FatalError:
-         termstat = _("Last Job Failed");
+         termstat = _("Bacula Storage: Last Job Failed");
          break;
       default:
          if (job->Errors) {
-            termstat = _("Last Job had Warnings");
+            termstat = _("Bacula Storage: Last Job had Warnings");
          }
          break;
       }