+Index: patches/testing/runscript_with_multiple_command.patch
+===================================================================
+--- patches/testing/runscript_with_multiple_command.patch	(rvision 6170)
++++ patches/testing/runscript_with_multiple_command.patch	(copie de travail)
+@@ -1,483 +0,0 @@
+-Index: src/dird/fd_cmds.c
+-===================================================================
+---- src/dird/fd_cmds.c	(rvision 6169)
+-+++ src/dird/fd_cmds.c	(copie de travail)
+-@@ -537,29 +537,35 @@
+-          Dmsg2(200, "bdird: runscript %s -> %s\n", cmd->target, ehost);
+- 
+-          if (strcmp(ehost, jcr->client->name()) == 0) {
+--            pm_strcpy(msg, cmd->command);
+--            bash_spaces(msg);
+-+            char *c;
+-+            char *command, cmd_type;
+-+            foreach_alist(c, cmd->commands) {
+-+               cmd->get_command(c, &cmd_type, &command);
+-+               if (cmd_type == SHELL_CMD) {
+-+                  pm_strcpy(msg, command);
+-+                  bash_spaces(msg);
+- 
+--            Dmsg1(120, "bdird: sending runscripts to fd '%s'\n", cmd->command);
+-+                  Dmsg1(120, "bdird: sending runscripts to fd '%s'\n", command);
+-             
+--            /* TODO: remove this with bacula 1.42 */
+--            if (cmd->old_proto) {
+--               result = send_runscript_with_old_proto(jcr, cmd->when, msg);
+-+                  /* TODO: remove this with bacula 1.42 */
+-+                  if (cmd->old_proto) {
+-+                     result = send_runscript_with_old_proto(jcr, cmd->when, msg);
+-+                     
+-+                  } else {
+-+                     fd->fsend(runscript, cmd->on_success, 
+-+                                          cmd->on_failure,
+-+                                          cmd->fail_on_error,
+-+                                          cmd->when,
+-+                                          msg);
+- 
+--            } else {
+--               fd->fsend(runscript, cmd->on_success, 
+--                                    cmd->on_failure,
+--                                    cmd->fail_on_error,
+--                                    cmd->when,
+--                                    msg);
+--
+--               result = response(jcr, fd, OKRunScript, "RunScript", DISPLAY_ERROR);
+--               launch_before_cmd = true;
+-+                     result = response(jcr, fd, OKRunScript, "RunScript", DISPLAY_ERROR);
+-+                     launch_before_cmd = true;
+-+                  }
+-+                  if (!result) {
+-+                     goto bail_out;
+-+                  }
+-+               }
+-             }
+--            
+--            if (!result) {
+--               goto bail_out;
+--            }
+-          }
+-          /* TODO : we have to play with other client */
+-          /*
+-@@ -567,7 +573,7 @@
+-            send command to an other client
+-            }
+-          */
+--      }        
+-+      }
+-    } 
+- 
+-    /* Tell the FD to execute the ClientRunBeforeJob */
+-Index: src/dird/dird_conf.c
+-===================================================================
+---- src/dird/dird_conf.c	(rvision 6169)
+-+++ src/dird/dird_conf.c	(copie de travail)
+-@@ -651,16 +651,19 @@
+-          }
+-       }
+-       if (res->res_job.RunScripts) {
+--        RUNSCRIPT *script;
+--        foreach_alist(script, res->res_job.RunScripts) {
+--           sendit(sock, _(" --> RunScript\n"));
+--           sendit(sock, _("  --> Command=%s\n"), NPRT(script->command));
+--           sendit(sock, _("  --> Target=%s\n"),  NPRT(script->target));
+--           sendit(sock, _("  --> RunOnSuccess=%u\n"),  script->on_success);
+--           sendit(sock, _("  --> RunOnFailure=%u\n"),  script->on_failure);
+--           sendit(sock, _("  --> FailJobOnError=%u\n"),  script->fail_on_error);
+--           sendit(sock, _("  --> RunWhen=%u\n"),  script->when);
+--        }
+-+         char *c;
+-+         RUNSCRIPT *script;
+-+         foreach_alist(script, res->res_job.RunScripts) {
+-+            sendit(sock, _(" --> RunScript\n"));
+-+            foreach_alist(c, script->commands) {
+-+               sendit(sock, _("  --> Command=%s\n"), NPRT(c));
+-+            }
+-+            sendit(sock, _("  --> Target=%s\n"),  NPRT(script->target));
+-+            sendit(sock, _("  --> RunOnSuccess=%u\n"),  script->on_success);
+-+            sendit(sock, _("  --> RunOnFailure=%u\n"),  script->on_failure);
+-+            sendit(sock, _("  --> FailJobOnError=%u\n"),  script->fail_on_error);
+-+            sendit(sock, _("  --> RunWhen=%u\n"),  script->when);
+-+         }
+-       }
+-       if (res->res_job.pool) {
+-          sendit(sock, _("  --> "));
+-@@ -1724,14 +1727,14 @@
+- }
+- 
+- /*
+-- * Store a runscript->command as a string
+-+ * Store a runscript->commands as a alist(char + string)
+-  */
+- static void store_runscript_cmd(LEX *lc, RES_ITEM *item, int index, int pass)
+- {
+-    lex_get_token(lc, T_STRING);
+- 
+-    if (pass == 2) {
+--      ((RUNSCRIPT*)item->value)->set_command(lc->str, item->code);
+-+      ((RUNSCRIPT*)item->value)->add_command(lc->str, item->code);
+-    }
+-    scan_to_eol(lc);
+- }
+-@@ -1745,7 +1748,7 @@
+-       RUNSCRIPT *script = new_runscript();
+-       script->set_job_code_callback(job_code_callback_filesetname);
+- 
+--      script->set_command(lc->str);
+-+      script->add_command(lc->str);
+- 
+-       /* TODO: remove all script->old_proto with bacula 1.42 */
+- 
+-@@ -1873,7 +1876,7 @@
+-    }
+- 
+-    if (pass == 2) {
+--      if (res_runscript.command == NULL) {
+-+      if (res_runscript.commands == NULL) {
+-          scan_err2(lc, _("%s item is required in %s resource, but not found.\n"),
+-                    "command", "runscript");
+-       }
+-@@ -1883,10 +1886,11 @@
+-          res_runscript.set_target("%c");
+-       }
+- 
+--      RUNSCRIPT *script = new_runscript();
+--      memcpy(script, &res_runscript, sizeof(RUNSCRIPT));
+-+      RUNSCRIPT *script = copy_runscript(&res_runscript);
+-+      res_runscript.reset_default(true);
+-+
+-       script->set_job_code_callback(job_code_callback_filesetname);
+--      
+-+
+-       if (*runscripts == NULL) {
+-         *runscripts = New(alist(10, not_owned_by_alist));
+-       }
+-Index: src/filed/job.c
+-===================================================================
+---- src/filed/job.c	(rvision 6169)
+-+++ src/filed/job.c	(copie de travail)
+-@@ -481,7 +481,7 @@
+- 
+-    /* Run the command now */
+-    script = new_runscript();
+--   script->set_command(cmd);
+-+   script->add_command(cmd);
+-    script->when = SCRIPT_Before;
+-    ok = script->run(jcr, "ClientRunBeforeJob");
+-    free_runscript(script);
+-@@ -529,7 +529,7 @@
+-    unbash_spaces(msg);
+- 
+-    cmd = new_runscript();
+--   cmd->set_command(msg);
+-+   cmd->add_command(msg);
+-    cmd->on_success = true;
+-    cmd->on_failure = false;
+-    cmd->when = SCRIPT_After;
+-@@ -567,7 +567,7 @@
+-    cmd->fail_on_error = fail_on_error;
+-    unbash_spaces(msg);
+- 
+--   cmd->set_command(msg);
+-+   cmd->add_command(msg);
+-    cmd->debug();
+-    jcr->RunScripts->append(cmd);
+- 
+-Index: src/lib/runscript.h
+-===================================================================
+---- src/lib/runscript.h	(rvision 6169)
+-+++ src/lib/runscript.h	(copie de travail)
+-@@ -62,8 +62,8 @@
+- };
+- 
+- enum {
+--   SHELL_CMD   = 1,
+--   CONSOLE_CMD = 2 
+-+   SHELL_CMD   = '|',
+-+   CONSOLE_CMD = '@' 
+- };
+- 
+- /*
+-@@ -71,10 +71,9 @@
+-  */
+- class RUNSCRIPT {
+- public:
+--   POOLMEM *command;            /* command string */
+-+   alist *commands;             /* list of command/console string */
+-    POOLMEM *target;             /* host target */
+-    int  when;                   /* SCRIPT_Before|Script_After BEFORE/AFTER JOB*/
+--   int  cmd_type;               /* Command type -- Shell, Console */
+-    char level;                  /* Base|Full|Incr...|All (NYI) */
+-    bool on_success;             /* execute command on job success (After) */
+-    bool on_failure;             /* execute command on job failure (After) */
+-@@ -85,8 +84,10 @@
+-                                 /* Optional callback function passed to edit_job_code */
+- 
+-    bool run(JCR *job, const char *name=""); /* name must contain "Before" or "After" keyword */
+-+   bool run_command(const char *cmd, JCR *job, const char *name="");
+-    bool can_run_at_level(int JobLevel) { return true;};        /* TODO */
+--   void set_command(const POOLMEM *cmd, int cmd_type = SHELL_CMD);
+-+   void add_command(const POOLMEM *cmd, char cmd_type = SHELL_CMD);
+-+   void get_command(const char *cmd, char *cmd_type, char **cmd);
+-    void set_target(const POOLMEM *client_name);
+-    void reset_default(bool free_string = false);
+-    bool is_local();             /* true if running on local host */
+-Index: src/lib/runscript.c
+-===================================================================
+---- src/lib/runscript.c	(rvision 6169)
+-+++ src/lib/runscript.c	(copie de travail)
+-@@ -59,15 +59,20 @@
+- 
+- void RUNSCRIPT::reset_default(bool free_strings)
+- {
+--   if (free_strings && command) {
+--     free_pool_memory(command);
+-+   char *c;
+-+   if (free_strings && commands) {
+-+      foreach_alist(c, commands) {
+-+         free_pool_memory(c);
+-+      }
+-    }
+-    if (free_strings && target) {
+-      free_pool_memory(target);
+-    }
+--   
+-    target = NULL;
+--   command = NULL;
+-+   if (commands) {
+-+      delete commands;
+-+      commands = NULL;
+-+   }
+-    on_success = true;
+-    on_failure = false;
+-    fail_on_error = true;
+-@@ -76,17 +81,23 @@
+-    job_code_callback = NULL;
+- }
+- 
+--RUNSCRIPT *copy_runscript(RUNSCRIPT *src)
+-+Runscript *copy_runscript(RUNSCRIPT *src)
+- {
+-    Dmsg0(500, "runscript: creating new RUNSCRIPT object from other\n");
+- 
+-    RUNSCRIPT *dst = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
+-    memcpy(dst, src, sizeof(RUNSCRIPT));
+- 
+--   dst->command = NULL;
+-+   dst->commands =  New(alist(5, not_owned_by_alist));
+-+   char *c;
+-+   POOLMEM *m;
+-+   foreach_alist(c, src->commands) {
+-+      m = get_pool_memory(PM_FNAME);
+-+      pm_strcpy(m, c);
+-+      dst->commands->append(m);
+-+   }
+-+
+-    dst->target = NULL;
+--
+--   dst->set_command(src->command, src->cmd_type);
+-    dst->set_target(src->target);
+- 
+-    return dst;   
+-@@ -95,9 +106,12 @@
+- void free_runscript(RUNSCRIPT *script)
+- {
+-    Dmsg0(500, "runscript: freeing RUNSCRIPT object\n");
+--
+--   if (script->command) {
+--      free_pool_memory(script->command);
+-+   POOLMEM *c;
+-+   if (script->commands) {
+-+      foreach_alist(c, script->commands) {
+-+         free_pool_memory(c);
+-+      }
+-+      delete script->commands;
+-    }
+-    if (script->target) {
+-       free_pool_memory(script->target);
+-@@ -108,60 +122,15 @@
+- int run_scripts(JCR *jcr, alist *runscripts, const char *label)
+- {
+-    Dmsg2(200, "runscript: running all RUNSCRIPT object (%s) JobStatus=%c\n", label, jcr->JobStatus);
+--   
+--   RUNSCRIPT *script;
+--   bool runit;
+- 
+--   int when;
+--
+--   if (strstr(label, NT_("Before"))) {
+--      when = SCRIPT_Before;
+--   } else {
+--      when = SCRIPT_After;
+--   }
+--
+-    if (runscripts == NULL) {
+-       Dmsg0(100, "runscript: WARNING RUNSCRIPTS list is NULL\n");
+-       return 0;
+-    }
+--
+-+   
+-+   RUNSCRIPT *script;
+-    foreach_alist(script, runscripts) {
+--      Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(script->target), NPRT(script->command));
+--      runit = false;
+--
+--      if ((script->when & SCRIPT_Before) && (when & SCRIPT_Before)) {
+--         if ((script->on_success 
+--            && (jcr->JobStatus == JS_Running || jcr->JobStatus == JS_Created))
+--            || (script->on_failure && job_canceled(jcr))
+--            )
+--         {
+--            Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n", 
+--                  script->command, script->on_success, script->on_failure,
+--                  jcr->JobStatus );
+--            runit = true;
+--         }
+--      }
+--
+--      if ((script->when & SCRIPT_After) && (when & SCRIPT_After)) {
+--         if ((script->on_success && (jcr->JobStatus == JS_Terminated))
+--             || (script->on_failure && job_canceled(jcr))
+--            )
+--         {
+--            Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n", 
+--                  script->command, script->on_success, script->on_failure,
+--                  jcr->JobStatus );
+--            runit = true;
+--         }
+--      }
+--
+--      if (!script->is_local()) {
+--         runit = false;
+--      }
+--
+--      /* we execute it */
+--      if (runit) {
+--         script->run(jcr, label);
+--      }
+-+      script->run(jcr, label);
+-    }
+-    return 1;
+- }
+-@@ -176,7 +145,7 @@
+- }
+- 
+- /* set this->command to cmd */
+--void RUNSCRIPT::set_command(const POOLMEM *cmd, int acmd_type)
+-+void RUNSCRIPT::add_command(const POOLMEM *cmd, char acmd_type)
+- {
+-    Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd));
+- 
+-@@ -184,14 +153,21 @@
+-       return;
+-    }
+- 
+--   if (!command) {
+--      command = get_pool_memory(PM_FNAME);
+-+   if (!commands) {
+-+      commands = New(alist(5, not_owned_by_alist)); 
+-    }
+- 
+--   pm_strcpy(command, cmd);
+--   cmd_type = acmd_type;
+-+   POOLMEM *c = get_pool_memory(PM_FNAME);
+-+   Mmsg(c, "%c%s", acmd_type, cmd);
+-+   commands->append(c);
+- }
+- 
+-+void RUNSCRIPT::get_command(const char* command, char *acmd_type, char **cmd)
+-+{
+-+   *acmd_type = command[0];
+-+   *cmd = (char *)command + 1;
+-+}
+-+
+- /* set this->target to client_name */
+- void RUNSCRIPT::set_target(const POOLMEM *client_name)
+- {
+-@@ -210,14 +186,71 @@
+- 
+- bool RUNSCRIPT::run(JCR *jcr, const char *name)
+- {
+--   Dmsg1(100, "runscript: running a RUNSCRIPT object type=%d\n", cmd_type);
+-+   char *c;
+-+   bool runit;
+-+
+-+   int when;
+-+
+-+   if (strstr(name, NT_("Before"))) {
+-+      when = SCRIPT_Before;
+-+   } else {
+-+      when = SCRIPT_After;
+-+   }
+-+
+-+   foreach_alist(c, this->commands) {
+-+      Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(this->target), NPRT(c));
+-+      runit = false;
+-+
+-+      if ((this->when & SCRIPT_Before) && (when & SCRIPT_Before)) {
+-+         if ((this->on_success 
+-+            && (jcr->JobStatus == JS_Running || jcr->JobStatus == JS_Created))
+-+            || (this->on_failure && job_canceled(jcr))
+-+            )
+-+         {
+-+            Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n", 
+-+                  c, this->on_success, this->on_failure,
+-+                  jcr->JobStatus );
+-+            runit = true;
+-+         }
+-+      }
+-+
+-+      if ((this->when & SCRIPT_After) && (when & SCRIPT_After)) {
+-+         if ((this->on_success && (jcr->JobStatus == JS_Terminated))
+-+             || (this->on_failure && job_canceled(jcr))
+-+            )
+-+         {
+-+            Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n", 
+-+                  c, this->on_success, this->on_failure,
+-+                  jcr->JobStatus );
+-+            runit = true;
+-+         }
+-+      }
+-+
+-+      if (!this->is_local()) {
+-+         runit = false;
+-+      }
+-+
+-+      /* we execute it */
+-+      if (runit) {
+-+         this->run_command(c, jcr, name);
+-+      }
+-+   }
+-+   return 1;
+-+}
+-+
+-+bool RUNSCRIPT::run_command(const char *command, JCR *jcr, const char *name)
+-+{
+-    POOLMEM *ecmd = get_pool_memory(PM_FNAME);
+-    int status;
+-    BPIPE *bpipe;
+-    char line[MAXSTRING];
+-+   char cmd_type;
+-+   char *cmd;
+- 
+--   ecmd = edit_job_codes(jcr, ecmd, this->command, "", this->job_code_callback);
+--   Dmsg1(100, "runscript: running '%s'...\n", ecmd);
+-+   this->get_command(command, &cmd_type, &cmd);
+-+   ecmd = edit_job_codes(jcr, ecmd, cmd, "", this->job_code_callback);
+-+
+-+   Dmsg2(100, "runscript: running '%s' object type=%c...\n", ecmd, cmd_type);
+-    Jmsg(jcr, M_INFO, 0, _("%s: run %s \"%s\"\n"), 
+-         cmd_type==SHELL_CMD?"shell command":"console command", name, ecmd);
+- 
+-@@ -278,9 +311,12 @@
+- 
+- void RUNSCRIPT::debug()
+- {
+-+   char *c;
+-    Dmsg0(200, "runscript: debug\n");
+-    Dmsg0(200,  _(" --> RunScript\n"));
+--   Dmsg1(200,  _("  --> Command=%s\n"), NPRT(command));
+-+   foreach_alist(c, commands) {
+-+      Dmsg1(200,  _("  --> Command=%s\n"), NPRT(c));
+-+   }
+-    Dmsg1(200,  _("  --> Target=%s\n"),  NPRT(target));
+-    Dmsg1(200,  _("  --> RunOnSuccess=%u\n"),  on_success);
+-    Dmsg1(200,  _("  --> RunOnFailure=%u\n"),  on_failure);
 Index: src/dird/fd_cmds.c
 ===================================================================
 --- src/dird/fd_cmds.c	(rvision 6169)
 +++ src/dird/fd_cmds.c	(copie de travail)
-@@ -537,29 +537,35 @@
+@@ -527,7 +527,8 @@
+    RUNSCRIPT *cmd;
+    bool launch_before_cmd = false;
+    POOLMEM *ehost = get_pool_memory(PM_FNAME);
+-   int result;
++   int result, cmd_type;
++   char *c, *command;
+ 
+    Dmsg0(120, "bdird: sending runscripts to fd\n");
+    
+@@ -537,29 +538,33 @@
           Dmsg2(200, "bdird: runscript %s -> %s\n", cmd->target, ehost);
  
           if (strcmp(ehost, jcr->client->name()) == 0) {
 -            pm_strcpy(msg, cmd->command);
 -            bash_spaces(msg);
-+            char *c;
-+            char *command, cmd_type;
 +            foreach_alist(c, cmd->commands) {
 +               cmd->get_command(c, &cmd_type, &command);
 +               if (cmd_type == SHELL_CMD) {

+   return 1;
+}
+
+bool RUNSCRIPT::run_command(const char *command, JCR *jcr, const char *name)
+{
    POOLMEM *ecmd = get_pool_memory(PM_FNAME);
    int status;
    BPIPE *bpipe;
    char line[MAXSTRING];
+   char cmd_type;
+   char *cmd;
 
-   ecmd = edit_job_codes(jcr, ecmd, this->command, "", this->job_code_callback);
-   Dmsg1(100, "runscript: running '%s'...\n", ecmd);

    }
    if (script->target) {
       free_pool_memory(script->target);
@@ -108,60 +120,15 @@
 int run_scripts(JCR *jcr, alist *runscripts, const char *label)
 {
    Dmsg2(200, "runscript: running all RUNSCRIPT object (%s) JobStatus=%c\n", label, jcr->JobStatus);
