]> git.sur5r.net Git - bacula/bacula/commitdiff
Check FileSet & MediaType in restore -- kes12Aug02
authorKern Sibbald <kern@sibbald.com>
Wed, 14 Aug 2002 10:57:50 +0000 (10:57 +0000)
committerKern Sibbald <kern@sibbald.com>
Wed, 14 Aug 2002 10:57:50 +0000 (10:57 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@93 91ce42f0-d328-0410-95d8-f526ca767f89

13 files changed:
bacula/ChangeLog
bacula/platforms/irix/Makefile.in [new file with mode: 0644]
bacula/platforms/irix/bacula-dir.in [new file with mode: 0755]
bacula/platforms/irix/bacula-fd.in [new file with mode: 0755]
bacula/platforms/irix/bacula-sd.in [new file with mode: 0755]
bacula/src/count-lines
bacula/src/dird/sql_cmds.c
bacula/src/dird/ua_input.c
bacula/src/dird/ua_restore.c
bacula/src/dird/ua_run.c
bacula/src/dird/ua_select.c
bacula/src/tools/dbcheck.c
bacula/src/version.h

index 977f48957a43f118085fdc44d8e7a10ff91f6ae5..f1fd876b9348b8518e73dc0d321de94bad8a608b 100644 (file)
@@ -1,4 +1,28 @@
 2002-08-?? Version 1.24 (not yet released)
+  From kes12Aug02
+- Made a new tools directory.
+- Moved smtp into the tools directory.
+- Created a dbcheck program in the tools directory that
+  checks for certain database errors and if requested fixes them.
+- Put the database link flags on DB_LIBS so that it now only is
+  on binaries that actually need it.
+- Document dbcheck and testfind programs.
+- Move testfind to tools directory.
+- Check for FileSet after getting Client name in Restore command.
+  Modify all necessary SQL commands to accept FileSetId.
+- Add a db_get_fileset_record in cats directory.
+- Correct list last 20 files concatenation to be MySQL 
+  dependent. They aren't SQL standard. Use SQL standard || for
+  other SQL programs.
+- Modify dir command in file selection to produce a long form
+  listing of the file/directory name.
+- Add platforms/irix/*.in files to CVS
+- Make Console command scanner accept quoted value fields.
+- If after selecting Client to restore, there are multiple
+  FileSets, ask user to select one.
+- After obtaining JobIds for restore, ensure that there is only
+  one MediaType, and select a Storage resource to be used.
+
   From kes11Aug02
 - Made restore actually work.
 - Made console and gconsole be configured (requested by Chuck)
diff --git a/bacula/platforms/irix/Makefile.in b/bacula/platforms/irix/Makefile.in
new file mode 100644 (file)
index 0000000..0d49463
--- /dev/null
@@ -0,0 +1,80 @@
+# 
+# This file is used as the template to create the
+# Makefile for the Solaris specific installation.
+#
+#  15 November 2001 -- Kern Sibbald
+#
+#  for Bacula release @VERSION@ (@DATE@) -- @DISTNAME@
+#
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+
+nothing:
+
+install: install-autostart
+
+install-autostart: install-autostart-fd install-autostart-sd install-autostart-dir
+
+       
+install-autostart-fd:
+       @rm -f /etc/rc0.d/K20bacula-fd
+       @rm -f /etc/rc1.d/S99bacula-fd
+       @rm -f /etc/rc2.d/S99bacula-fd
+       @$(INSTALL_PROGRAM) -m 744 bacula-fd /etc/init.d/bacula-fd
+       # set symlinks for script at startup and shutdown
+       @ln -f -s /etc/init.d/bacula-fd /etc/rc0.d/K20bacula-fd
+       @ln -f -s /etc/init.d/bacula-fd /etc/rc1.d/S99bacula-fd
+       @ln -f -s /etc/init.d/bacula-fd /etc/rc2.d/S99bacula-fd
+
+
+install-autostart-sd:
+       @rm -f /etc/rc0.d/K20bacula-sd
+       @rm -f /etc/rc1.d/S99bacula-sd
+       @rm -f /etc/rc2.d/S99bacula-sd
+       @$(INSTALL_PROGRAM) -m 744 bacula-sd /etc/rc.d/init.d/bacula-sd
+       # set symlinks for script at startup and shutdown
+       @ln -f -s /etc/init.d/bacula-sd /etc/rc0.d/K20bacula-sd
+       @ln -f -s /etc/init.d/bacula-sd /etc/rc1.d/S99bacula-sd
+       @ln -f -s /etc/init.d/bacula-sd /etc/rc2.d/S99bacula-sd
+
+
+install-autostart-dir:
+       @rm -f /etc/rc0.d/K20bacula-dir
+       @rm -f /etc/rc1.d/S99bacula-dir
+       @rm -f /etc/rc2.d/S99bacula-dir
+       @$(INSTALL_PROGRAM) -m 744 bacula-dir /etc/rc.d/init.d/bacula-dir
+       # set symlinks for script at startup and shutdown
+       @ln -f -s /etc/init.d/bacula-dir /etc/rc0.d/K20bacula-dir
+       @ln -f -s /etc/init.d/bacula-dir /etc/rc1.d/S99bacula-dir
+       @ln -f -s /etc/init.d/bacula-dir /etc/rc2.d/S99bacula-dir
+
+
+uninstall: uninstall-autostart
+
+uninstall-autostart: uninstall-autostart-fd uninstall-autostart-sd uninstall-autostart-dir
+
+uninstall-autostart-fd:
+       @rm -f /etc/rc0.d/K20bacula-fd
+       @rm -f /etc/rc1.d/S99bacula-fd
+       @rm -f /etc/rc2.d/S99bacula-fd
+       @rm -f /etc/rc.d/init.d/bacula-fd
+
+
+uninstall-autostart-sd:
+       @rm -f /etc/rc0.d/K20bacula-sd
+       @rm -f /etc/rc1.d/S99bacula-sd
+       @rm -f /etc/rc2.d/S99bacula-sd
+       @rm -f /etc/rc.d/init.d/bacula-sd
+
+uninstall-autostart-dir:
+       @rm -f /etc/rc0.d/K20bacula-dir
+       @rm -f /etc/rc1.d/S99bacula-dir
+       @rm -f /etc/rc2.d/S99bacula-dir
+       @rm -f /etc/rc.d/init.d/bacula-dir
+
+clean:
+       @rm -f bacula-sd bacula-fd bacula-dir
+
+distclean: clean
+       @rm -f Makefile bacula-*.spec
diff --git a/bacula/platforms/irix/bacula-dir.in b/bacula/platforms/irix/bacula-dir.in
new file mode 100755 (executable)
index 0000000..8ff0919
--- /dev/null
@@ -0,0 +1,38 @@
+#! /bin/sh
+#
+# bacula       This shell script takes care of starting and stopping
+#             the bacula Director daemon
+#
+# chkconfig: 2345 20 99
+# description: It comes by night and sucks the vital essence from your computers.
+#
+#  For Bacula release @VERSION@ (@DATE@) -- @DISTNAME@
+#
+
+RETVAL=0
+case "$1" in
+    start)
+       echo "Starting the Bacula Director: "
+       @sbindir@/bacula-dir $2 -c @sysconfdir@/bacula-dir.conf
+       RETVAL=$?
+       echo
+       [ $RETVAL -eq 0 ] && touch @subsysdir@/bacula-dir
+       ;;
+    stop)
+       echo "Stopping the Director daemon: "
+#      killproc @sbindir@/bacula-dir
+       RETVAL=$?
+       echo
+       [ $RETVAL -eq 0 ] && rm -f @subsysdir@/bacula-dir
+       ;;
+    restart)
+       $0 stop
+       sleep 5
+       $0 start
+       ;;
+    *)
+       echo "Usage: $0 {start|stop|restart}"
+       exit 1
+       ;;
+esac
+exit 0
diff --git a/bacula/platforms/irix/bacula-fd.in b/bacula/platforms/irix/bacula-fd.in
new file mode 100755 (executable)
index 0000000..9f26ade
--- /dev/null
@@ -0,0 +1,37 @@
+#! /bin/sh
+#
+# bacula       This shell script takes care of starting and stopping
+#             the bacula File daemon.
+#
+# chkconfig: 2345 20 99
+# description: It comes by night and sucks the vital essence from your computers.
+#
+#  For Bacula release @VERSION@ (@DATE@) -- @DISTNAME@
+#
+
+case "$1" in
+    start)
+       echo "Starting the Bacula File daemon: "
+       @sbindir@/bacula-fd $2 -c @sysconfdir@/bacula-fd.conf
+       RETVAL=$?
+       echo
+       [ $RETVAL -eq 0 ] && touch @subsysdir@/bacula-fd
+       ;;
+    stop)
+       echo "Stopping the Bacula File daemon: "
+#      killproc @sbindir@/bacula-fd
+       RETVAL=$?
+       echo
+       [ $RETVAL -eq 0 ] && rm -f @subsysdir@/bacula-fd
+       ;;
+    restart)
+       $0 stop
+       sleep 5
+       $0 start
+       ;;
+    *)
+       echo "Usage: $0 {start|stop|restart}"
+       exit 1
+       ;;
+esac
+exit 0
diff --git a/bacula/platforms/irix/bacula-sd.in b/bacula/platforms/irix/bacula-sd.in
new file mode 100755 (executable)
index 0000000..79e1a91
--- /dev/null
@@ -0,0 +1,37 @@
+#! /bin/sh
+#
+# bacula       This shell script takes care of starting and stopping
+#             the bacula Storage daemon.
+#
+# chkconfig: 2345 20 99
+# description: It comes by night and sucks the vital essence from your computers.
+#
+#  For Bacula release @VERSION@ (@DATE@) -- @DISTNAME@
+#
+
+case "$1" in
+    start)
+       echo "Starting the Bacula Storage daemon: "
+       @sbindir@/bacula-sd $2 -c @sysconfdir@/bacula-sd.conf
+       RETVAL=$?
+       echo
+       [ $RETVAL -eq 0 ] && touch @subsysdir@/bacula-sd
+       ;;
+    stop)
+       echo "Stopping the Bacula Storage daemon: "
+#      killproc @sbindir@/bacula-sd
+       RETVAL=$?
+       echo
+       [ $RETVAL -eq 0 ] && rm -f @subsysdir@/bacula-sd
+       ;;
+    restart)
+       $0 stop
+       sleep 5
+       $0 start
+       ;;
+    *)
+       echo "Usage: $0 {start|stop|restart}"
+       exit 1
+       ;;
+esac
+exit 0
index 89850d6000311715fe5c0edd072e894f29d3fde5..c6019240b4d2149073641dde28a38f32f0075805 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 rm -f 1
 touch 1
-for i in . console gnome-console cats dird filed findlib lib stored; do
+for i in . console gnome-console cats dird filed findlib lib stored tools; do
   ls -1 $i/*.c $i/*.h $i/*.in >>1
 done
 cat 1 | $HOME/bin/lines
index a554a716ef9c21742f49f0b87b00540110fc07dd..61bf6daa289d6e1f3788fd238cd978b1ce018b45 100644 (file)
@@ -211,8 +211,14 @@ char *uar_sel_jobid_temp = "SELECT JobId FROM temp";
 
 char *uar_sel_all_temp1 = "SELECT * FROM temp1";
 
+/* Select filesets for this Client */
 char *uar_sel_fileset = 
    "SELECT FileSet.FileSetId,FileSet.FileSet FROM Job,"
    "Client,FileSet WHERE Job.FileSetId=FileSet.FileSetId "
    "AND Job.ClientId=Client.ClientId AND Client.Name='%s' "
    "GROUP BY FileSetId";
+
+/* Find MediaType used by this Job */
+char *uar_mediatype =
+   "SELECT MediaType FROM JobMedia,Media WHERE JobMedia.JobId=%u "
+   "AND JobMedia.MediaId=Media.MediaId";
index 9a9382d3d03b542823d2703861faedec876f3f06..8cd28d37b397256bc804d4c72561a9cdd0bf5d89 100644 (file)
@@ -131,7 +131,7 @@ char *next_arg(char **s)
 
 void parse_command_args(UAContext *ua)
 {
-   char *p, *n;
+   char *p, *q, *n;
    int i, len;
 
    len = strlen(ua->cmd) + 1;
@@ -154,6 +154,22 @@ void parse_command_args(UAContext *ua)
       p = strchr(ua->argk[i], '=');
       if (p) {
         *p++ = 0;                    /* terminate keyword and point to value */
+        /* Unquote quoted values */
+         if (*p == '"') {
+            Dmsg0(400, "Start with quote.\n");
+            for (n = q = ++p; *p && *p != '"'; ) {
+               if (*p == '\\') {
+                 p++;
+              }
+              *q++ = *p++;
+           }
+           p++;                            /* skip terminating quote */
+            for ( ; *p && *p != ' '; ) {
+              *q++ = *p++;
+           }
+           *q = 0;
+           p = n;
+        }
         if (strlen(p) > MAX_NAME_LENGTH-1) {
            p[MAX_NAME_LENGTH-1] = 0; /* truncate to max len */
         }
index 797fb2ff348793371ce0a630b01ab6fb0207ce2d..786d4dffdc046f9ddb472a3d63af41f9c5a8f0b0 100644 (file)
 extern int runcmd(UAContext *ua, char *cmd);
 
 /* Imported variables */
-extern char *uar_list_jobs, *uar_file, *uar_sel_files;
-extern char *uar_del_temp, *uar_del_temp1, *uar_create_temp;
-extern char *uar_create_temp1, *uar_last_full, *uar_full;
-extern char *uar_inc, *uar_list_temp, *uar_sel_jobid_temp;
-extern char *uar_sel_all_temp1, *uar_sel_fileset;
+extern char *uar_list_jobs,    *uar_file,        *uar_sel_files;
+extern char *uar_del_temp,     *uar_del_temp1,   *uar_create_temp;
+extern char *uar_create_temp1, *uar_last_full,   *uar_full;
+extern char *uar_inc,          *uar_list_temp,   *uar_sel_jobid_temp;
+extern char *uar_sel_all_temp1, *uar_sel_fileset, *uar_mediatype;
+
 
 /* Context for insert_tree_handler() */
 typedef struct s_tree_ctx {
@@ -54,12 +55,14 @@ typedef struct s_tree_ctx {
    UAContext *ua;
 } TREE_CTX;
 
+/* Main structure for obtaining JobIds */
 typedef struct s_jobids {
    btime_t JobTDate;
    uint32_t ClientId;
    uint32_t TotalFiles;
    char JobIds[200];
    CLIENT *client;
+   STORE  *store;
 } JobIds;
 
 
@@ -80,6 +83,17 @@ typedef struct s_rbsr {
    RBSR_FINDEX *fi;                  /* File indexes this JobId */
 } RBSR;
 
+typedef struct s_name_ctx {
+   char **name;                      /* list of names */
+   int num_ids;                      /* ids stored */
+   int max_ids;                      /* size of array */
+   int num_del;                      /* number deleted */
+   int tot_ids;                      /* total to process */
+} NAME_LIST;
+
+#define MAX_ID_LIST_LEN 1000000
+
+
 /* Forward referenced functions */
 static RBSR *new_bsr();
 static void free_bsr(RBSR *bsr);
@@ -95,6 +109,10 @@ static int next_jobid_from_list(char **p, uint32_t *JobId);
 static int user_select_jobids(UAContext *ua, JobIds *ji);
 static void user_select_files(TREE_CTX *tree);
 static int fileset_handler(void *ctx, int num_fields, char **row);
+static void print_name_list(UAContext *ua, NAME_LIST *name_list);
+static int unique_name_list_handler(void *ctx, int num_fields, char **row);
+static void free_name_list(NAME_LIST *name_list);
+static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, JobIds *ji);
 
 
 /*
@@ -113,12 +131,14 @@ int restorecmd(UAContext *ua, char *cmd)
    JOB *job = NULL;
    JOB *restore_job = NULL;
    int restore_jobs = 0;
+   NAME_LIST name_list;
 
    if (!open_db(ua)) {
       return 0;
    }
 
    memset(&tree, 0, sizeof(TREE_CTX));
+   memset(&name_list, 0, sizeof(name_list));
    memset(&ji, 0, sizeof(ji));
 
    /* Ensure there is at least one Restore Job */
@@ -157,19 +177,35 @@ int restorecmd(UAContext *ua, char *cmd)
     * appear more than once, however, we only insert it once.
     */
    for (p=ji.JobIds; next_jobid_from_list(&p, &JobId) > 0; ) {
+
       if (JobId == last_JobId) {            
         continue;                    /* eliminate duplicate JobIds */
       }
       last_JobId = JobId;
       bsendmsg(ua, _("Building directory tree for JobId %u ...\n"), JobId);
+      /*
+       * Find files for this JobId and insert them in the tree
+       */
       Mmsg(&query, uar_sel_files, JobId);
       if (!db_sql_query(ua->db, query, insert_tree_handler, (void *)&tree)) {
          bsendmsg(ua, "%s", db_strerror(ua->db));
       }
+      /*
+       * Find the FileSets for this JobId and add to the name_list
+       */
+      Mmsg(&query, uar_mediatype, JobId);
+      if (!db_sql_query(ua->db, query, unique_name_list_handler, (void *)&name_list)) {
+         bsendmsg(ua, "%s", db_strerror(ua->db));
+      }
+
    }
    bsendmsg(ua, "\n");
    free_pool_memory(query);
 
+   /* Check MediaType and select storage that corresponds */
+   get_storage_from_mediatype(ua, &name_list, &ji);
+   free_name_list(&name_list);
+
    /* Let the user select which files to restore */
    user_select_files(&tree);
 
@@ -208,12 +244,16 @@ int restorecmd(UAContext *ua, char *cmd)
    }
 
    if (ji.client) {
-      Mmsg(&ua->cmd, "run job=%s client=%s bootstrap=%s/restore.bsr",
-        job->hdr.name, ji.client->hdr.name, working_directory);
+      Mmsg(&ua->cmd, 
+         "run job=%s client=\"%s\" storage=\"%s\" bootstrap=\"%s/restore.bsr\"",
+         job->hdr.name, ji.client->hdr.name, ji.store?ji.store->hdr.name:"",
+        working_directory);
    } else {
-      Mmsg(&ua->cmd, "run job=%s bootstrap=%s/restore.bsr",
-        job->hdr.name, working_directory);
+      Mmsg(&ua->cmd, 
+         "run job=%s storage=\"%s\" bootstrap=\"%s/restore.bsr\"",
+         job->hdr.name, ji.store?ji.store->hdr.name:"", working_directory);
    }
+   
 
    Dmsg1(400, "Submitting: %s\n", ua->cmd);
    
@@ -492,7 +532,7 @@ static void user_select_files(TREE_CTX *tree)
    char cwd[2000];
 
    bsendmsg(tree->ua, _( 
-      "You are now entering file selection mode where you add and\n"
+      "\nYou are now entering file selection mode where you add and\n"
       "remove files to be restored. All files are initially added.\n"
       "Enter done to leave this mode.\n\n"));
    /*
@@ -534,7 +574,7 @@ static void user_select_files(TREE_CTX *tree)
  */
 static RBSR_FINDEX *new_findex() 
 {
-   RBSR_FINDEX *fi = (RBSR_FINDEX *)malloc(sizeof(RBSR_FINDEX));
+   RBSR_FINDEX *fi = (RBSR_FINDEX *)bmalloc(sizeof(RBSR_FINDEX));
    memset(fi, 0, sizeof(RBSR_FINDEX));
    return fi;
 }
@@ -576,7 +616,7 @@ static void print_findex(UAContext *ua, RBSR_FINDEX *fi)
 /* Create a new bootstrap record */
 static RBSR *new_bsr()
 {
-   RBSR *bsr = (RBSR *)malloc(sizeof(RBSR));
+   RBSR *bsr = (RBSR *)bmalloc(sizeof(RBSR));
    memset(bsr, 0, sizeof(RBSR));
    return bsr;
 }
@@ -645,7 +685,7 @@ static int write_bsr_file(UAContext *ua, RBSR *bsr)
    write_bsr(ua, bsr, fd);
    stat = !ferror(fd);
    fclose(fd);
-   bsendmsg(ua, _("Bootstrap records written to %s\n"), fname);
+// bsendmsg(ua, _("Bootstrap records written to %s\n"), fname);
    free_pool_memory(fname);
    return stat;
 }
@@ -1019,3 +1059,94 @@ static int quitcmd(UAContext *ua, TREE_CTX *tree)
 {
    return 0;
 }
+
+
+/*
+ * Called here with each name to be added to the list. The name is
+ *   added to the list if it is not already in the list.
+ */
+static int unique_name_list_handler(void *ctx, int num_fields, char **row)
+{
+   NAME_LIST *name = (NAME_LIST *)ctx;
+
+   if (name->num_ids == MAX_ID_LIST_LEN) {  
+      return 1;
+   }
+   if (name->num_ids == name->max_ids) {
+      if (name->max_ids == 0) {
+        name->max_ids = 1000;
+        name->name = (char **)bmalloc(sizeof(char *) * name->max_ids);
+      } else {
+        name->max_ids = (name->max_ids * 3) / 2;
+        name->name = (char **)brealloc(name->name, sizeof(char *) * name->max_ids);
+      }
+   }
+   for (int i=0; i<name->num_ids; i++) {
+      if (strcmp(name->name[i], row[0]) == 0) {
+        return 0;                    /* already in list, return */
+      }
+   }
+   /* Add new name to list */
+   name->name[name->num_ids++] = bstrdup(row[0]);
+   return 0;
+}
+
+
+/*
+ * Print names in the list
+ */
+static void print_name_list(UAContext *ua, NAME_LIST *name_list)
+{ 
+   int i;
+
+   for (i=0; i < name_list->num_ids; i++) {
+      bsendmsg(ua, "%s\n", name_list->name[i]);
+   }
+}
+
+
+/*
+ * Free names in the list
+ */
+static void free_name_list(NAME_LIST *name_list)
+{ 
+   int i;
+
+   for (i=0; i < name_list->num_ids; i++) {
+      free(name_list->name[i]);
+   }
+   free(name_list->name);
+   name_list->max_ids = 0;
+   name_list->num_ids = 0;
+}
+
+static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, JobIds *ji)
+{
+   char name[MAX_NAME_LENGTH];
+   STORE *store = NULL;
+
+   if (name_list->num_ids > 1) {
+      bsendmsg(ua, _("Warning, the JobIds that you selected refer to more than one MediaType.\n"
+         "Restore is not possible. The MediaTypes used are:\n"));
+      print_name_list(ua, name_list);
+      ji->store = select_storage_resource(ua);
+      return;
+   }
+
+   start_prompt(ua, _("The defined Storage resources are:\n"));
+   LockRes();
+   while ((store = (STORE *)GetNextRes(R_STORAGE, (RES *)store))) {
+      if (strcmp(store->hdr.name, name_list->name[0]) == 0) {
+        add_prompt(ua, store->hdr.name);
+      }
+   }
+   UnlockRes();
+   do_prompt(ua, _("Select Storage resource"), name);
+   ji->store = (STORE *)GetResWithName(R_STORAGE, name);
+   if (!ji->store) {
+      bsendmsg(ua, _("\nWarning. Unable to find Storage resource for\n"
+         "MediaType %s, needed by the Jobs you selected.\n"
+         "You will be allowed to select a Storage device later.\n"),
+        name_list->name[0]); 
+   }
+}
index a843de79666a94bf5d9f222b3c9e4c75b1382cda..aafd9e1bda5c9899a57bdc5f8e4943345055d570 100644 (file)
@@ -79,8 +79,6 @@ int runcmd(UAContext *ua, char *cmd)
    fileset_name = NULL;
    bootstrap = NULL;
 
-   Dmsg1(000, "run: %s\n", ua->UA_sock->msg);
-
    for (i=1; i<ua->argc; i++) {
       found = False;
       Dmsg2(200, "Doing arg %d = %s\n", i, ua->argk[i]);
index 3b4a6bb67b040d08604e8003d2dc18c514b259e7..ac3923a0fd251145f4a30b9ed90f5a458f89bdac 100644 (file)
@@ -487,7 +487,7 @@ void start_prompt(UAContext *ua, char *msg)
 {
   if (ua->max_prompts == 0) {
      ua->max_prompts = 10;
-     ua->prompt = (char **) bmalloc(sizeof(char *) * ua->max_prompts);
+     ua->prompt = (char **)bmalloc(sizeof(char *) * ua->max_prompts);
   }
   ua->num_prompts = 1;
   ua->prompt[0] = bstrdup(msg);
@@ -501,7 +501,7 @@ void add_prompt(UAContext *ua, char *prompt)
    int i;
    if (ua->num_prompts == ua->max_prompts) {
       ua->max_prompts *= 2;
-      ua->prompt = (char **) brealloc(ua->prompt, sizeof(char *) *
+      ua->prompt = (char **)brealloc(ua->prompt, sizeof(char *) *
         ua->max_prompts);
     }
     for (i=1; i < ua->num_prompts; i++) {
@@ -534,6 +534,11 @@ int do_prompt(UAContext *ua, char *msg, char *prompt)
    }
 
    for ( ;; ) {
+      /* First item is the prompt string, not the items */
+      if (ua->num_prompts == 1) { 
+        item = 0;                    /* list is empty ! */
+        break;
+      }
       if (ua->num_prompts == 2) {
         item = 1;
          bsendmsg(ua, _("Item 1 selected automatically.\n"));
index 5c8496a3d261e5a677c5f09782bac6ecb7077484..944549a2e4366050f683473d5b3060dc19e4eac0 100644 (file)
@@ -188,7 +188,7 @@ static int id_list_handler(void *ctx, int num_fields, char **row)
    if (lst->num_ids == lst->max_ids) {
       if (lst->max_ids == 0) {
         lst->max_ids = 1000;
-        lst->Id = (uint32_t *)malloc(sizeof(uint32_t) * lst->max_ids);
+        lst->Id = (uint32_t *)bmalloc(sizeof(uint32_t) * lst->max_ids);
       } else {
         lst->max_ids = (lst->max_ids * 3) / 2;
         lst->Id = (uint32_t *)brealloc(lst->Id, sizeof(uint32_t) * lst->max_ids);
@@ -241,7 +241,7 @@ static int name_list_handler(void *ctx, int num_fields, char **row)
    if (name->num_ids == name->max_ids) {
       if (name->max_ids == 0) {
         name->max_ids = 1000;
-        name->name = (char **)malloc(sizeof(char *) * name->max_ids);
+        name->name = (char **)bmalloc(sizeof(char *) * name->max_ids);
       } else {
         name->max_ids = (name->max_ids * 3) / 2;
         name->name = (char **)brealloc(name->name, sizeof(char *) * name->max_ids);
index bbd06d464c59987e8ca719a289a98c757c48655c..f83e270d8e4e1aa8dafaad90b33b58967277e643 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #define VERSION "1.24"
 #define VSTRING "1"
-#define DATE    "10 August 2002"
-#define LSMDATE "10Aug02"
+#define DATE    "14 August 2002"
+#define LSMDATE "14Aug02"
 
 /* Debug flags */
 #define DEBUG 1