]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/ua_cmds.c
Fix conio.h problem on Solaris
[bacula/bacula] / bacula / src / dird / ua_cmds.c
index 3bdd2be7172ead66effb329a343892fdf4788246..e79094fb4d09f0b9340686cb8d2a66d547a0dc8d 100644 (file)
@@ -43,53 +43,56 @@ extern jobq_t job_queue;          /* job queue */
 extern char *list_pool;
 
 /* Imported functions */
-extern int status_cmd(UAContext *ua, char *cmd);
-extern int list_cmd(UAContext *ua, char *cmd);
-extern int llist_cmd(UAContext *ua, char *cmd);
-extern int show_cmd(UAContext *ua, char *cmd);
-extern int messagescmd(UAContext *ua, char *cmd);
-extern int autodisplay_cmd(UAContext *ua, char *cmd);
-extern int gui_cmd(UAContext *ua, char *cmd);
-extern int sqlquerycmd(UAContext *ua, char *cmd);
-extern int querycmd(UAContext *ua, char *cmd);
-extern int run_cmd(UAContext *ua, char *cmd);
-extern int retentioncmd(UAContext *ua, char *cmd);
-extern int prunecmd(UAContext *ua, char *cmd);
-extern int purgecmd(UAContext *ua, char *cmd);
-extern int restore_cmd(UAContext *ua, char *cmd);
-extern int label_cmd(UAContext *ua, char *cmd);
-extern int relabel_cmd(UAContext *ua, char *cmd);
+extern int status_cmd(UAContext *ua, const char *cmd);
+extern int list_cmd(UAContext *ua, const char *cmd);
+extern int llist_cmd(UAContext *ua, const char *cmd);
+extern int show_cmd(UAContext *ua, const char *cmd);
+extern int messagescmd(UAContext *ua, const char *cmd);
+extern int autodisplay_cmd(UAContext *ua, const char *cmd);
+extern int gui_cmd(UAContext *ua, const char *cmd);
+extern int sqlquerycmd(UAContext *ua, const char *cmd);
+extern int querycmd(UAContext *ua, const char *cmd);
+extern int run_cmd(UAContext *ua, const char *cmd);
+extern int retentioncmd(UAContext *ua, const char *cmd);
+extern int prunecmd(UAContext *ua, const char *cmd);
+extern int purgecmd(UAContext *ua, const char *cmd);
+extern int restore_cmd(UAContext *ua, const char *cmd);
+extern int label_cmd(UAContext *ua, const char *cmd);
+extern int relabel_cmd(UAContext *ua, const char *cmd);
 extern int update_slots(UAContext *ua);  /* ua_label.c */
 
 /* Forward referenced functions */
-static int add_cmd(UAContext *ua, char *cmd);  
-static int create_cmd(UAContext *ua, char *cmd); 
-static int cancel_cmd(UAContext *ua, char *cmd); 
-static int setdebug_cmd(UAContext *ua, char *cmd);
-static int trace_cmd(UAContext *ua, char *cmd);
-static int var_cmd(UAContext *ua, char *cmd);
-static int estimate_cmd(UAContext *ua, char *cmd);
-static int help_cmd(UAContext *ua, char *cmd);
-static int delete_cmd(UAContext *ua, char *cmd);
-static int use_cmd(UAContext *ua, char *cmd),  unmount_cmd(UAContext *ua, char *cmd);
-static int version_cmd(UAContext *ua, char *cmd), automount_cmd(UAContext *ua, char *cmd);
-static int time_cmd(UAContext *ua, char *cmd);
-static int reload_cmd(UAContext *ua, char *cmd);
+static int add_cmd(UAContext *ua, const char *cmd);  
+static int create_cmd(UAContext *ua, const char *cmd); 
+static int cancel_cmd(UAContext *ua, const char *cmd); 
+static int setdebug_cmd(UAContext *ua, const char *cmd);
+static int trace_cmd(UAContext *ua, const char *cmd);
+static int var_cmd(UAContext *ua, const char *cmd);
+static int estimate_cmd(UAContext *ua, const char *cmd);
+static int help_cmd(UAContext *ua, const char *cmd);
+static int delete_cmd(UAContext *ua, const char *cmd);
+static int use_cmd(UAContext *ua, const char *cmd);
+static int unmount_cmd(UAContext *ua, const char *cmd);
+static int version_cmd(UAContext *ua, const char *cmd);
+static int automount_cmd(UAContext *ua, const char *cmd);
+static int time_cmd(UAContext *ua, const char *cmd);
+static int reload_cmd(UAContext *ua, const char *cmd);
 static int update_volume(UAContext *ua);
 static int update_pool(UAContext *ua);
 static int delete_volume(UAContext *ua);
 static int delete_pool(UAContext *ua);
 static int delete_job(UAContext *ua);
-static int mount_cmd(UAContext *ua, char *cmd);
-static int release_cmd(UAContext *ua, char *cmd);
-static int update_cmd(UAContext *ua, char *cmd);
-static int wait_cmd(UAContext *ua, char *cmd);
-static int setip_cmd(UAContext *ua, char *cmd);
+static int mount_cmd(UAContext *ua, const char *cmd);
+static int release_cmd(UAContext *ua, const char *cmd);
+static int update_cmd(UAContext *ua, const char *cmd);
+static int wait_cmd(UAContext *ua, const char *cmd);
+static int setip_cmd(UAContext *ua, const char *cmd);
 
-int quit_cmd(UAContext *ua, char *cmd);
+int qhelp_cmd(UAContext *ua, const char *cmd);
+int quit_cmd(UAContext *ua, const char *cmd);
 
 
-struct cmdstruct { char *key; int (*func)(UAContext *ua, char *cmd); char *help; }; 
+struct cmdstruct { const char *key; int (*func)(UAContext *ua, const char *cmd); const char *help; }; 
 static struct cmdstruct commands[] = {
  { N_("add"),        add_cmd,         _("add media to a pool")},
  { N_("autodisplay"), autodisplay_cmd, _("autodisplay [on/off] -- console messages")},
@@ -134,7 +137,7 @@ static struct cmdstruct commands[] = {
 /*
  * Execute a command from the UA
  */
-int do_a_command(UAContext *ua, char *cmd)
+int do_a_command(UAContext *ua, const char *cmd)
 {
    unsigned int i;
    int len, stat;
@@ -185,7 +188,7 @@ void set_pool_dbr_defaults_in_media_dbr(MEDIA_DBR *mr, POOL_DBR *pr)
 /*
  *  Add Volumes to an existing Pool
  */
-static int add_cmd(UAContext *ua, char *cmd) 
+static int add_cmd(UAContext *ua, const char *cmd) 
 {
    POOL_DBR pr;
    MEDIA_DBR mr;
@@ -310,7 +313,7 @@ getVolName:
       mr.InChanger = InChanger;
       Dmsg1(200, "Create Volume %s\n", mr.VolumeName);
       if (!db_create_media_record(ua->jcr, ua->db, &mr)) {
-        bsendmsg(ua, db_strerror(ua->db));
+         bsendmsg(ua, "%s", db_strerror(ua->db));
         return 1;
       }
       if (i == startnum) {
@@ -320,7 +323,7 @@ getVolName:
    pr.NumVols += num;
    Dmsg0(200, "Update pool record.\n"); 
    if (db_update_pool_record(ua->jcr, ua->db, &pr) != 1) {
-      bsendmsg(ua, db_strerror(ua->db));
+      bsendmsg(ua, "%s", db_strerror(ua->db));
       return 1;
    }
    bsendmsg(ua, _("%d Volumes created in pool %s\n"), num, pr.Name);
@@ -334,7 +337,7 @@ getVolName:
  *  automount on 
  *  automount off
  */
-int automount_cmd(UAContext *ua, char *cmd)
+int automount_cmd(UAContext *ua, const char *cmd)
 {
    char *onoff;
 
@@ -355,7 +358,7 @@ int automount_cmd(UAContext *ua, char *cmd)
 /*
  * Cancel a job
  */
-static int cancel_cmd(UAContext *ua, char *cmd)
+static int cancel_cmd(UAContext *ua, const char *cmd)
 {
    int i, ret;
    int njobs = 0;
@@ -522,7 +525,7 @@ int create_pool(JCR *jcr, B_DB *db, POOL *pool, e_pool_op op)
  * Create a Pool Record in the database.
  *  It is always created from the Resource record.
  */
-static int create_cmd(UAContext *ua, char *cmd) 
+static int create_cmd(UAContext *ua, const char *cmd) 
 {
    POOL *pool;
 
@@ -542,7 +545,7 @@ static int create_cmd(UAContext *ua, char *cmd)
       break;
 
    case -1:
-      bsendmsg(ua, db_strerror(ua->db));
+      bsendmsg(ua, "%s", db_strerror(ua->db));
       break;
 
    default:
@@ -558,26 +561,30 @@ static int create_cmd(UAContext *ua, char *cmd)
  *  if the Console name is the same as the Client name 
  *  and the Console can access the client.
  */
-static int setip_cmd(UAContext *ua, char *cmd) 
+static int setip_cmd(UAContext *ua, const char *cmd) 
 {
    CLIENT *client;
+   char buf[1024]; 
    if (!ua->cons || !acl_access_ok(ua, Client_ACL, ua->cons->hdr.name)) {
       bsendmsg(ua, _("Illegal command from this console.\n"));
       return 1;
    }
+   LockRes();
    client = (CLIENT *)GetResWithName(R_CLIENT, ua->cons->hdr.name);
 
    if (!client) {
       bsendmsg(ua, _("Client \"%s\" not found.\n"), ua->cons->hdr.name);
-      return 1;
+      goto get_out;
    }
-   LockRes();
    if (client->address) {
       free(client->address);
    }
-   client->address = bstrdup(inet_ntoa(ua->UA_sock->client_addr.sin_addr));
+   /* MA Bug 6 remove ifdef */
+   sockaddr_to_ascii(&(ua->UA_sock->client_addr), buf, sizeof(buf)); 
+   client->address = bstrdup(buf);
    bsendmsg(ua, _("Client \"%s\" address set to %s\n"),
            client->hdr.name, client->address);
+get_out:
    UnlockRes();
    return 1;
 }
@@ -591,10 +598,12 @@ static int setip_cmd(UAContext *ua, char *cmd)
  *        updates pool from Pool resource
  *    update media pool=<pool-name> volume=<volume-name>
  *        changes pool info for volume
+ *    update slots [scan=...]
+ *        updates autochanger slots
  */
-static int update_cmd(UAContext *ua, char *cmd) 
+static int update_cmd(UAContext *ua, const char *cmd) 
 {
-   static char *kw[] = {
+   static const char *kw[] = {
       N_("media"),  /* 0 */
       N_("volume"), /* 1 */
       N_("pool"),   /* 2 */
@@ -640,10 +649,10 @@ static int update_cmd(UAContext *ua, char *cmd)
    return 1;
 }
 
-static void update_volstatus(UAContext *ua, char *val, MEDIA_DBR *mr)
+static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr)
 {
    POOLMEM *query = get_pool_memory(PM_MESSAGE);
-   char *kw[] = {
+   const char *kw[] = {
       "Append",
       "Archive",
       "Disabled",
@@ -666,7 +675,7 @@ static void update_volstatus(UAContext *ua, char *val, MEDIA_DBR *mr)
       bsendmsg(ua, _("Invalid VolStatus specified: %s\n"), val);
    } else {
       bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus));
-      Mmsg(&query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%u",
+      Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%u",
         mr->VolStatus, mr->MediaId);
       if (!db_sql_query(ua->db, query, NULL, NULL)) {  
          bsendmsg(ua, "%s", db_strerror(ua->db));
@@ -679,27 +688,27 @@ static void update_volstatus(UAContext *ua, char *val, MEDIA_DBR *mr)
 
 static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
 {
-   char ed1[50];
+   char ed1[150];
    POOLMEM *query;
    if (!duration_to_utime(val, &mr->VolRetention)) {
       bsendmsg(ua, _("Invalid retention period specified: %s\n"), val);
       return;
    }
    query = get_pool_memory(PM_MESSAGE);
-   Mmsg(&query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%u",
+   Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%u",
       edit_uint64(mr->VolRetention, ed1), mr->MediaId);
    if (!db_sql_query(ua->db, query, NULL, NULL)) {  
       bsendmsg(ua, "%s", db_strerror(ua->db));
    } else {
-      bsendmsg(ua, _("New retention seconds is: %s\n"),
-        edit_utime(mr->VolRetention, ed1));
+      bsendmsg(ua, _("New retention period is: %s\n"),
+        edit_utime(mr->VolRetention, ed1, sizeof(ed1)));
    }
    free_pool_memory(query);
 }
 
 static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
 {
-   char ed1[50];
+   char ed1[150];
    POOLMEM *query;
 
    if (!duration_to_utime(val, &mr->VolUseDuration)) {
@@ -707,13 +716,13 @@ static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
       return;
    }
    query = get_pool_memory(PM_MESSAGE);
-   Mmsg(&query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%u",
+   Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%u",
       edit_uint64(mr->VolUseDuration, ed1), mr->MediaId);
    if (!db_sql_query(ua->db, query, NULL, NULL)) {  
       bsendmsg(ua, "%s", db_strerror(ua->db));
    } else {
       bsendmsg(ua, _("New use duration is: %s\n"),
-        edit_utime(mr->VolUseDuration, ed1));
+        edit_utime(mr->VolUseDuration, ed1, sizeof(ed1)));
    }
    free_pool_memory(query);
 }
@@ -721,7 +730,7 @@ static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
 static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
 {
    POOLMEM *query = get_pool_memory(PM_MESSAGE);
-   Mmsg(&query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%u",
+   Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%u",
       val, mr->MediaId);
    if (!db_sql_query(ua->db, query, NULL, NULL)) {  
       bsendmsg(ua, "%s", db_strerror(ua->db));
@@ -734,7 +743,7 @@ static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
 static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
 {
    POOLMEM *query = get_pool_memory(PM_MESSAGE);
-   Mmsg(&query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%u",
+   Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%u",
       val, mr->MediaId);
    if (!db_sql_query(ua->db, query, NULL, NULL)) {  
       bsendmsg(ua, "%s", db_strerror(ua->db));
@@ -755,7 +764,7 @@ static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
       return;
    } 
    query = get_pool_memory(PM_MESSAGE);
-   Mmsg(&query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%u",
+   Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%u",
       edit_uint64(maxbytes, ed1), mr->MediaId);
    if (!db_sql_query(ua->db, query, NULL, NULL)) {  
       bsendmsg(ua, "%s", db_strerror(ua->db));
@@ -778,7 +787,7 @@ static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
       return;
    }
    query = get_pool_memory(PM_MESSAGE);
-   Mmsg(&query, "UPDATE Media SET Recycle=%d WHERE MediaId=%u",
+   Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%u",
       recycle, mr->MediaId);
    if (!db_sql_query(ua->db, query, NULL, NULL)) {  
       bsendmsg(ua, "%s", db_strerror(ua->db));
@@ -790,9 +799,10 @@ static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
 }
 
 /* Modify the Pool in which this Volume is located */
-static void update_volpool(UAContext *ua, char *val, MEDIA_DBR *mr)
+static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
 {
    POOL_DBR pr;
+   POOLMEM *query;
 
    memset(&pr, 0, sizeof(pr));
    bstrncpy(pr.Name, val, sizeof(pr.Name));
@@ -801,36 +811,73 @@ static void update_volpool(UAContext *ua, char *val, MEDIA_DBR *mr)
    }
    mr->PoolId = pr.PoolId;           /* set new PoolId */
    /*
-    * Make sure to use db_update... rather than doing this directly,
-    *  so that any Slot is handled correctly. 
     */
-   if (!db_update_media_record(ua->jcr, ua->db, mr)) {
-      bsendmsg(ua, _("Error updating media record Pool: ERR=%s"), db_strerror(ua->db));
-   } else {
+   query = get_pool_memory(PM_MESSAGE);
+   db_lock(ua->db);
+   Mmsg(query, "UPDATE Media SET PoolId=%d WHERE MediaId=%u",
+      mr->PoolId, mr->MediaId);
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {  
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {      
       bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
+      opr->NumVols--;
+      if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
+         bsendmsg(ua, "%s", db_strerror(ua->db));
+      }
+      pr.NumVols++;
+      if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
+         bsendmsg(ua, "%s", db_strerror(ua->db));
+      }
+      db_make_inchanger_unique(ua->jcr, ua->db, mr);
    }
+   db_unlock(ua->db);
+   free_pool_memory(query);
 }
 
+/*
+ * Refresh the Volume information from the Pool record
+ */
 static void update_volfrompool(UAContext *ua, MEDIA_DBR *mr)
 {
    POOL_DBR pr;
-   char VolStatus[50];
 
    memset(&pr, 0, sizeof(pr));
    pr.PoolId = mr->PoolId;
    if (!get_pool_dbr(ua, &pr)) {
       return;
    }
-   bstrncpy(VolStatus, mr->VolStatus, sizeof(VolStatus));
    set_pool_dbr_defaults_in_media_dbr(mr, &pr);
-   bstrncpy(mr->VolStatus, VolStatus, sizeof(mr->VolStatus));
-   if (!db_update_media_record(ua->jcr, ua->db, mr)) {
+   if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
       bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
    } else {
       bsendmsg(ua, _("Volume defaults updated from Pool record.\n"));
    }
 }
 
+/*
+ * Refresh the Volume information from the Pool record
+ *   for all Volumes
+ */
+static void update_all_vols_from_pool(UAContext *ua)
+{
+   POOL_DBR pr;
+   MEDIA_DBR mr;
+
+   memset(&pr, 0, sizeof(pr));
+   if (!get_pool_dbr(ua, &pr)) {
+      return;
+   }
+   memset(&mr, 0, sizeof(mr));
+   set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
+   mr.PoolId = pr.PoolId;
+   if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
+      bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("All Volume defaults updated from Pool record.\n"));
+   }
+}
+
+
 /*
  * Update a media record -- allows you to change the
  *  Volume status. E.g. if you want Bacula to stop
@@ -842,9 +889,9 @@ static int update_volume(UAContext *ua)
    MEDIA_DBR mr;
    POOL_DBR pr;
    POOLMEM *query;
-   char ed1[30];
+   char ed1[130];
    bool done = false;
-   char *kw[] = {
+   const char *kw[] = {
       N_("VolStatus"),                /* 0 */
       N_("VolRetention"),             /* 1 */
       N_("VolUse"),                   /* 2 */
@@ -854,12 +901,14 @@ static int update_volume(UAContext *ua)
       N_("Recycle"),                  /* 6 */
       N_("Pool"),                     /* 7 */
       N_("FromPool"),                 /* 8 */
+      N_("AllFromPool"),              /* 9 */
       NULL };
 
    for (int i=0; kw[i]; i++) {
       int j;
+      POOL_DBR pr;
       if ((j=find_arg_with_value(ua, kw[i])) > 0) {
-        if (!select_media_dbr(ua, &mr)) {
+        if (i != 9 && !select_media_dbr(ua, &mr)) {
            return 0;
         }
         switch (i) {
@@ -885,11 +934,19 @@ static int update_volume(UAContext *ua)
            update_volrecycle(ua, ua->argv[j], &mr);
            break;
         case 7:
-           update_volpool(ua, ua->argv[j], &mr);
+           memset(&pr, 0, sizeof(POOL_DBR));
+           pr.PoolId = mr.PoolId;
+           if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
+               bsendmsg(ua, "%s", db_strerror(ua->db));
+              break;
+           }
+           update_vol_pool(ua, ua->argv[j], &mr, &pr);
            break;
         case 8:
            update_volfrompool(ua, &mr);
            break;
+        case 9:
+           update_all_vols_from_pool(ua);
         }
         done = true;
       }
@@ -912,6 +969,8 @@ static int update_volume(UAContext *ua)
       add_prompt(ua, _("InChanger Flag"));
       add_prompt(ua, _("Volume Files"));
       add_prompt(ua, _("Pool"));
+      add_prompt(ua, _("Volume from Pool"));
+      add_prompt(ua, _("All Volumes from Pool"));
       add_prompt(ua, _("Done"));
       switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
       case 0:                        /* Volume Status */
@@ -934,8 +993,8 @@ static int update_volume(UAContext *ua)
         update_volstatus(ua, ua->cmd, &mr);
         break;
       case 1:                        /* Retention */
-         bsendmsg(ua, _("Current retention seconds is: %s\n"),
-           edit_utime(mr.VolRetention, ed1));
+         bsendmsg(ua, _("Current retention period is: %s\n"),
+           edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
          if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
            return 0;
         }
@@ -944,7 +1003,7 @@ static int update_volume(UAContext *ua)
 
       case 2:                        /* Use Duration */
          bsendmsg(ua, _("Current use duration is: %s\n"),
-           edit_utime(mr.VolUseDuration, ed1));
+           edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
          if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
            return 0;
         }
@@ -1050,7 +1109,7 @@ static int update_volume(UAContext *ua)
            }
         }
         query = get_pool_memory(PM_MESSAGE);
-         Mmsg(&query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%u",
+         Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%u",
            VolFiles, mr.MediaId);
         if (!db_sql_query(ua->db, query, NULL, NULL)) {  
             bsendmsg(ua, "%s", db_strerror(ua->db));
@@ -1071,9 +1130,15 @@ static int update_volume(UAContext *ua)
          if (!get_cmd(ua, _("Enter new Pool name: "))) {
            return 0;
         }
-        update_volpool(ua, ua->cmd, &mr);
+        update_vol_pool(ua, ua->cmd, &mr, &pr);
         return 1;
 
+      case 11:
+        update_volfrompool(ua, &mr);
+        break;
+      case 12:
+        update_all_vols_from_pool(ua);
+        break;
       default:                       /* Done or error */
          bsendmsg(ua, "Selection done.\n");
         return 1;
@@ -1111,7 +1176,7 @@ static int update_pool(UAContext *ua)
         id, db_strerror(ua->db));
    }
    query = get_pool_memory(PM_MESSAGE);
-   Mmsg(&query, list_pool, pr.PoolId);
+   Mmsg(query, list_pool, pr.PoolId);
    db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
    free_pool_memory(query);
    bsendmsg(ua, _("Pool DB record updated from resource.\n"));
@@ -1247,7 +1312,7 @@ static void do_all_setdebug(UAContext *ua, int level, int trace_flag)
 /*
  * setdebug level=nn all trace=1/0
  */
-static int setdebug_cmd(UAContext *ua, char *cmd)
+static int setdebug_cmd(UAContext *ua, const char *cmd)
 {
    STORE *store;
    CLIENT *client;
@@ -1366,7 +1431,7 @@ static int setdebug_cmd(UAContext *ua, char *cmd)
 /*
  * Turn debug tracing to file on/off
  */
-static int trace_cmd(UAContext *ua, char *cmd)
+static int trace_cmd(UAContext *ua, const char *cmd)
 {
    char *onoff;
 
@@ -1384,7 +1449,7 @@ static int trace_cmd(UAContext *ua, char *cmd)
 
 }
 
-static int var_cmd(UAContext *ua, char *cmd)
+static int var_cmd(UAContext *ua, const char *cmd)
 {
    POOLMEM *val = get_pool_memory(PM_FNAME);
    char *var;
@@ -1405,15 +1470,17 @@ static int var_cmd(UAContext *ua, char *cmd)
    return 1;
 }
 
-static int estimate_cmd(UAContext *ua, char *cmd)
+static int estimate_cmd(UAContext *ua, const char *cmd)
 {
    JOB *job = NULL;
    CLIENT *client = NULL;
    FILESET *fileset = NULL;
+   FILESET_DBR fsr;
    int listing = 0;
-   BSOCK *fd;
    char since[MAXSTRING];
+   JCR *jcr = ua->jcr;
 
+   jcr->JobLevel = L_FULL;
    for (int i=1; i<ua->argc; i++) {
       if (strcasecmp(ua->argk[i], _("client")) == 0 ||
           strcasecmp(ua->argk[i], _("fd")) == 0) {
@@ -1436,6 +1503,13 @@ static int estimate_cmd(UAContext *ua, char *cmd)
       }
       if (strcasecmp(ua->argk[i], _("listing")) == 0) {
         listing = 1;
+        continue;
+      }
+      if (strcasecmp(ua->argk[i], _("level")) == 0) {
+        if (!get_level_from_name(ua->jcr, ua->argv[i])) {
+            bsendmsg(ua, _("Level %s not valid.\n"), ua->argv[i]);
+        }
+        continue;
       }
    } 
    if (!job && !(client && fileset)) {
@@ -1445,6 +1519,10 @@ static int estimate_cmd(UAContext *ua, char *cmd)
    }
    if (!job) {
       job = (JOB *)GetResWithName(R_JOB, ua->argk[1]);
+      if (!job) {
+         bsendmsg(ua, _("No job specified.\n"));
+        return 1;
+      }
    }
    if (!client) {
       client = job->client;
@@ -1452,8 +1530,8 @@ static int estimate_cmd(UAContext *ua, char *cmd)
    if (!fileset) {
       fileset = job->fileset;
    }
-   ua->jcr->client = client;
-   ua->jcr->fileset = fileset;
+   jcr->client = client;
+   jcr->fileset = fileset;
    close_db(ua);
    ua->catalog = client->catalog;
 
@@ -1461,39 +1539,51 @@ static int estimate_cmd(UAContext *ua, char *cmd)
       return 1;
    }
 
+   jcr->job = job;
+   jcr->JobType = JT_BACKUP;
+   init_jcr_job_record(jcr);
+
+   if (!get_or_create_client_record(jcr)) {
+      return 1;
+   }
+   if (!get_or_create_fileset_record(jcr, &fsr)) {
+      return 1;
+   }
+   
    get_level_since_time(ua->jcr, since, sizeof(since));
 
    bsendmsg(ua, _("Connecting to Client %s at %s:%d\n"),
       job->client->hdr.name, job->client->address, job->client->FDport);
-   if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) {
+   if (!connect_to_file_daemon(jcr, 1, 15, 0)) {
       bsendmsg(ua, _("Failed to connect to Client.\n"));
       return 1;
    }
-   fd = ua->jcr->file_bsock;
 
-   if (!send_include_list(ua->jcr)) {
+   if (!send_include_list(jcr)) {
       bsendmsg(ua, _("Error sending include list.\n"));
-      return 1;
+      goto bail_out;
    }
 
-   if (!send_exclude_list(ua->jcr)) {
+   if (!send_exclude_list(jcr)) {
       bsendmsg(ua, _("Error sending exclude list.\n"));
-      return 1;
+      goto bail_out;
    }
 
-   if (!send_level_command(ua->jcr)) {
-      return 1;
+   if (!send_level_command(jcr)) {
+      goto bail_out;
    }
 
-   bnet_fsend(fd, "estimate listing=%d\n", listing);
-   while (bnet_recv(fd) >= 0) {
-      bsendmsg(ua, "%s", fd->msg);
+   bnet_fsend(jcr->file_bsock, "estimate listing=%d\n", listing);
+   while (bnet_recv(jcr->file_bsock) >= 0) {
+      bsendmsg(ua, "%s", jcr->file_bsock->msg);
    }
 
-   bnet_sig(fd, BNET_TERMINATE);
-   bnet_close(fd);
-   ua->jcr->file_bsock = NULL;
-
+bail_out:
+   if (jcr->file_bsock) {
+      bnet_sig(jcr->file_bsock, BNET_TERMINATE);
+      bnet_close(jcr->file_bsock);
+      jcr->file_bsock = NULL;
+   }
    return 1;
 }
 
@@ -1501,7 +1591,7 @@ static int estimate_cmd(UAContext *ua, char *cmd)
 /*
  * print time
  */
-static int time_cmd(UAContext *ua, char *cmd)
+static int time_cmd(UAContext *ua, const char *cmd)
 {
    char sdt[50];
    time_t ttime = time(NULL);
@@ -1515,11 +1605,12 @@ static int time_cmd(UAContext *ua, char *cmd)
 /*
  * reload the conf file
  */
-extern void reload_config(int sig);
+extern "C" void reload_config(int sig);
 
-static int reload_cmd(UAContext *ua, char *cmd)
+static int reload_cmd(UAContext *ua, const char *cmd)
 {
    reload_config(1);   
+   return 1;
 }
 
 
@@ -1531,9 +1622,9 @@ static int reload_cmd(UAContext *ua, char *cmd)
  *  delete volume pool=<pool-name> volume=<name>
  *  delete job jobid=xxx
  */
-static int delete_cmd(UAContext *ua, char *cmd)
+static int delete_cmd(UAContext *ua, const char *cmd)
 {
-   static char *keywords[] = {
+   static const char *keywords[] = {
       N_("volume"),
       N_("pool"),
       N_("job"),
@@ -1597,11 +1688,11 @@ static int delete_job(UAContext *ua)
    } else {
       JobId = ua->pint32_val; 
    }
-   Mmsg(&query, "DELETE FROM Job WHERE JobId=%u", JobId);
+   Mmsg(query, "DELETE FROM Job WHERE JobId=%u", JobId);
    db_sql_query(ua->db, query, NULL, (void *)NULL);
-   Mmsg(&query, "DELETE FROM File WHERE JobId=%u", JobId);
+   Mmsg(query, "DELETE FROM File WHERE JobId=%u", JobId);
    db_sql_query(ua->db, query, NULL, (void *)NULL);
-   Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%u", JobId);
+   Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%u", JobId);
    db_sql_query(ua->db, query, NULL, (void *)NULL);
    free_pool_memory(query);
    bsendmsg(ua, _("Job %u and associated records deleted from the catalog.\n"), JobId);
@@ -1653,7 +1744,7 @@ static int delete_pool(UAContext *ua)
 }
 
 
-static void do_mount_cmd(UAContext *ua, char *command)
+static void do_mount_cmd(UAContext *ua, const char *command)
 {
    STORE *store;
    BSOCK *sd;
@@ -1693,7 +1784,7 @@ static void do_mount_cmd(UAContext *ua, char *command)
 /*
  * mount [storage | device] <name>
  */
-static int mount_cmd(UAContext *ua, char *cmd)
+static int mount_cmd(UAContext *ua, const char *cmd)
 {
    do_mount_cmd(ua, "mount");          /* mount */
    return 1;
@@ -1703,7 +1794,7 @@ static int mount_cmd(UAContext *ua, char *cmd)
 /*
  * unmount [storage | device] <name>
  */
-static int unmount_cmd(UAContext *ua, char *cmd)
+static int unmount_cmd(UAContext *ua, const char *cmd)
 {
    do_mount_cmd(ua, "unmount");          /* unmount */
    return 1;
@@ -1713,7 +1804,7 @@ static int unmount_cmd(UAContext *ua, char *cmd)
 /*
  * release [storage | device] <name>
  */
-static int release_cmd(UAContext *ua, char *cmd)
+static int release_cmd(UAContext *ua, const char *cmd)
 {
    do_mount_cmd(ua, "release");          /* release */
    return 1;
@@ -1724,7 +1815,7 @@ static int release_cmd(UAContext *ua, char *cmd)
  * Switch databases
  *   use catalog=<name>
  */
-static int use_cmd(UAContext *ua, char *cmd)
+static int use_cmd(UAContext *ua, const char *cmd)
 {
    CAT *oldcatalog, *catalog;
 
@@ -1744,7 +1835,7 @@ static int use_cmd(UAContext *ua, char *cmd)
    return 1;
 }
 
-int quit_cmd(UAContext *ua, char *cmd) 
+int quit_cmd(UAContext *ua, const char *cmd) 
 {
    ua->quit = TRUE;
    return 1;
@@ -1753,7 +1844,7 @@ int quit_cmd(UAContext *ua, char *cmd)
 /*
  * Wait until no job is running 
  */
-int wait_cmd(UAContext *ua, char *cmd) 
+int wait_cmd(UAContext *ua, const char *cmd) 
 {
    JCR *jcr;
    bmicrosleep(0, 200000);           /* let job actually start */
@@ -1777,7 +1868,7 @@ int wait_cmd(UAContext *ua, char *cmd)
 }
 
 
-static int help_cmd(UAContext *ua, char *cmd)
+static int help_cmd(UAContext *ua, const char *cmd)
 {
    unsigned int i;
 
@@ -1789,7 +1880,17 @@ static int help_cmd(UAContext *ua, char *cmd)
    return 1;
 }
 
-static int version_cmd(UAContext *ua, char *cmd)
+int qhelp_cmd(UAContext *ua, const char *cmd)
+{
+   unsigned int i;
+
+   for (i=0; i<comsize; i++) {
+      bsendmsg(ua, _("%s %s\n"), _(commands[i].key), _(commands[i].help));
+   }
+   return 1;
+}
+
+static int version_cmd(UAContext *ua, const char *cmd)
 {
    bsendmsg(ua, "%s Version: " VERSION " (" BDATE ")\n", my_name);
    return 1;