]> git.sur5r.net Git - bacula/bacula/blob - bacula/patches/testing/runscript_with_multiple_command.patch
ebl Permit to mix console and command when runsonclient=yes
[bacula/bacula] / bacula / patches / testing / runscript_with_multiple_command.patch
1 Index: patches/testing/runscript_with_multiple_command.patch
2 ===================================================================
3 --- patches/testing/runscript_with_multiple_command.patch       (révision 6171)
4 +++ patches/testing/runscript_with_multiple_command.patch       (copie de travail)
5 @@ -1,982 +0,0 @@
6 -Index: patches/testing/runscript_with_multiple_command.patch
7 -===================================================================
8 ---- patches/testing/runscript_with_multiple_command.patch      (révision 6170)
9 -+++ patches/testing/runscript_with_multiple_command.patch      (copie de travail)
10 -@@ -1,483 +0,0 @@
11 --Index: src/dird/fd_cmds.c
12 --===================================================================
13 ----- src/dird/fd_cmds.c        (révision 6169)
14 --+++ src/dird/fd_cmds.c        (copie de travail)
15 --@@ -537,29 +537,35 @@
16 --          Dmsg2(200, "bdird: runscript %s -> %s\n", cmd->target, ehost);
17 -- 
18 --          if (strcmp(ehost, jcr->client->name()) == 0) {
19 ---            pm_strcpy(msg, cmd->command);
20 ---            bash_spaces(msg);
21 --+            char *c;
22 --+            char *command, cmd_type;
23 --+            foreach_alist(c, cmd->commands) {
24 --+               cmd->get_command(c, &cmd_type, &command);
25 --+               if (cmd_type == SHELL_CMD) {
26 --+                  pm_strcpy(msg, command);
27 --+                  bash_spaces(msg);
28 -- 
29 ---            Dmsg1(120, "bdird: sending runscripts to fd '%s'\n", cmd->command);
30 --+                  Dmsg1(120, "bdird: sending runscripts to fd '%s'\n", command);
31 --             
32 ---            /* TODO: remove this with bacula 1.42 */
33 ---            if (cmd->old_proto) {
34 ---               result = send_runscript_with_old_proto(jcr, cmd->when, msg);
35 --+                  /* TODO: remove this with bacula 1.42 */
36 --+                  if (cmd->old_proto) {
37 --+                     result = send_runscript_with_old_proto(jcr, cmd->when, msg);
38 --+                     
39 --+                  } else {
40 --+                     fd->fsend(runscript, cmd->on_success, 
41 --+                                          cmd->on_failure,
42 --+                                          cmd->fail_on_error,
43 --+                                          cmd->when,
44 --+                                          msg);
45 -- 
46 ---            } else {
47 ---               fd->fsend(runscript, cmd->on_success, 
48 ---                                    cmd->on_failure,
49 ---                                    cmd->fail_on_error,
50 ---                                    cmd->when,
51 ---                                    msg);
52 ---
53 ---               result = response(jcr, fd, OKRunScript, "RunScript", DISPLAY_ERROR);
54 ---               launch_before_cmd = true;
55 --+                     result = response(jcr, fd, OKRunScript, "RunScript", DISPLAY_ERROR);
56 --+                     launch_before_cmd = true;
57 --+                  }
58 --+                  if (!result) {
59 --+                     goto bail_out;
60 --+                  }
61 --+               }
62 --             }
63 ---            
64 ---            if (!result) {
65 ---               goto bail_out;
66 ---            }
67 --          }
68 --          /* TODO : we have to play with other client */
69 --          /*
70 --@@ -567,7 +573,7 @@
71 --            send command to an other client
72 --            }
73 --          */
74 ---      }        
75 --+      }
76 --    } 
77 -- 
78 --    /* Tell the FD to execute the ClientRunBeforeJob */
79 --Index: src/dird/dird_conf.c
80 --===================================================================
81 ----- src/dird/dird_conf.c      (révision 6169)
82 --+++ src/dird/dird_conf.c      (copie de travail)
83 --@@ -651,16 +651,19 @@
84 --          }
85 --       }
86 --       if (res->res_job.RunScripts) {
87 ---        RUNSCRIPT *script;
88 ---        foreach_alist(script, res->res_job.RunScripts) {
89 ---           sendit(sock, _(" --> RunScript\n"));
90 ---           sendit(sock, _("  --> Command=%s\n"), NPRT(script->command));
91 ---           sendit(sock, _("  --> Target=%s\n"),  NPRT(script->target));
92 ---           sendit(sock, _("  --> RunOnSuccess=%u\n"),  script->on_success);
93 ---           sendit(sock, _("  --> RunOnFailure=%u\n"),  script->on_failure);
94 ---           sendit(sock, _("  --> FailJobOnError=%u\n"),  script->fail_on_error);
95 ---           sendit(sock, _("  --> RunWhen=%u\n"),  script->when);
96 ---        }
97 --+         char *c;
98 --+         RUNSCRIPT *script;
99 --+         foreach_alist(script, res->res_job.RunScripts) {
100 --+            sendit(sock, _(" --> RunScript\n"));
101 --+            foreach_alist(c, script->commands) {
102 --+               sendit(sock, _("  --> Command=%s\n"), NPRT(c));
103 --+            }
104 --+            sendit(sock, _("  --> Target=%s\n"),  NPRT(script->target));
105 --+            sendit(sock, _("  --> RunOnSuccess=%u\n"),  script->on_success);
106 --+            sendit(sock, _("  --> RunOnFailure=%u\n"),  script->on_failure);
107 --+            sendit(sock, _("  --> FailJobOnError=%u\n"),  script->fail_on_error);
108 --+            sendit(sock, _("  --> RunWhen=%u\n"),  script->when);
109 --+         }
110 --       }
111 --       if (res->res_job.pool) {
112 --          sendit(sock, _("  --> "));
113 --@@ -1724,14 +1727,14 @@
114 -- }
115 -- 
116 -- /*
117 --- * Store a runscript->command as a string
118 --+ * Store a runscript->commands as a alist(char + string)
119 --  */
120 -- static void store_runscript_cmd(LEX *lc, RES_ITEM *item, int index, int pass)
121 -- {
122 --    lex_get_token(lc, T_STRING);
123 -- 
124 --    if (pass == 2) {
125 ---      ((RUNSCRIPT*)item->value)->set_command(lc->str, item->code);
126 --+      ((RUNSCRIPT*)item->value)->add_command(lc->str, item->code);
127 --    }
128 --    scan_to_eol(lc);
129 -- }
130 --@@ -1745,7 +1748,7 @@
131 --       RUNSCRIPT *script = new_runscript();
132 --       script->set_job_code_callback(job_code_callback_filesetname);
133 -- 
134 ---      script->set_command(lc->str);
135 --+      script->add_command(lc->str);
136 -- 
137 --       /* TODO: remove all script->old_proto with bacula 1.42 */
138 -- 
139 --@@ -1873,7 +1876,7 @@
140 --    }
141 -- 
142 --    if (pass == 2) {
143 ---      if (res_runscript.command == NULL) {
144 --+      if (res_runscript.commands == NULL) {
145 --          scan_err2(lc, _("%s item is required in %s resource, but not found.\n"),
146 --                    "command", "runscript");
147 --       }
148 --@@ -1883,10 +1886,11 @@
149 --          res_runscript.set_target("%c");
150 --       }
151 -- 
152 ---      RUNSCRIPT *script = new_runscript();
153 ---      memcpy(script, &res_runscript, sizeof(RUNSCRIPT));
154 --+      RUNSCRIPT *script = copy_runscript(&res_runscript);
155 --+      res_runscript.reset_default(true);
156 --+
157 --       script->set_job_code_callback(job_code_callback_filesetname);
158 ---      
159 --+
160 --       if (*runscripts == NULL) {
161 --         *runscripts = New(alist(10, not_owned_by_alist));
162 --       }
163 --Index: src/filed/job.c
164 --===================================================================
165 ----- src/filed/job.c   (révision 6169)
166 --+++ src/filed/job.c   (copie de travail)
167 --@@ -481,7 +481,7 @@
168 -- 
169 --    /* Run the command now */
170 --    script = new_runscript();
171 ---   script->set_command(cmd);
172 --+   script->add_command(cmd);
173 --    script->when = SCRIPT_Before;
174 --    ok = script->run(jcr, "ClientRunBeforeJob");
175 --    free_runscript(script);
176 --@@ -529,7 +529,7 @@
177 --    unbash_spaces(msg);
178 -- 
179 --    cmd = new_runscript();
180 ---   cmd->set_command(msg);
181 --+   cmd->add_command(msg);
182 --    cmd->on_success = true;
183 --    cmd->on_failure = false;
184 --    cmd->when = SCRIPT_After;
185 --@@ -567,7 +567,7 @@
186 --    cmd->fail_on_error = fail_on_error;
187 --    unbash_spaces(msg);
188 -- 
189 ---   cmd->set_command(msg);
190 --+   cmd->add_command(msg);
191 --    cmd->debug();
192 --    jcr->RunScripts->append(cmd);
193 -- 
194 --Index: src/lib/runscript.h
195 --===================================================================
196 ----- src/lib/runscript.h       (révision 6169)
197 --+++ src/lib/runscript.h       (copie de travail)
198 --@@ -62,8 +62,8 @@
199 -- };
200 -- 
201 -- enum {
202 ---   SHELL_CMD   = 1,
203 ---   CONSOLE_CMD = 2 
204 --+   SHELL_CMD   = '|',
205 --+   CONSOLE_CMD = '@' 
206 -- };
207 -- 
208 -- /*
209 --@@ -71,10 +71,9 @@
210 --  */
211 -- class RUNSCRIPT {
212 -- public:
213 ---   POOLMEM *command;            /* command string */
214 --+   alist *commands;             /* list of command/console string */
215 --    POOLMEM *target;             /* host target */
216 --    int  when;                   /* SCRIPT_Before|Script_After BEFORE/AFTER JOB*/
217 ---   int  cmd_type;               /* Command type -- Shell, Console */
218 --    char level;                  /* Base|Full|Incr...|All (NYI) */
219 --    bool on_success;             /* execute command on job success (After) */
220 --    bool on_failure;             /* execute command on job failure (After) */
221 --@@ -85,8 +84,10 @@
222 --                                 /* Optional callback function passed to edit_job_code */
223 -- 
224 --    bool run(JCR *job, const char *name=""); /* name must contain "Before" or "After" keyword */
225 --+   bool run_command(const char *cmd, JCR *job, const char *name="");
226 --    bool can_run_at_level(int JobLevel) { return true;};        /* TODO */
227 ---   void set_command(const POOLMEM *cmd, int cmd_type = SHELL_CMD);
228 --+   void add_command(const POOLMEM *cmd, char cmd_type = SHELL_CMD);
229 --+   void get_command(const char *cmd, char *cmd_type, char **cmd);
230 --    void set_target(const POOLMEM *client_name);
231 --    void reset_default(bool free_string = false);
232 --    bool is_local();             /* true if running on local host */
233 --Index: src/lib/runscript.c
234 --===================================================================
235 ----- src/lib/runscript.c       (révision 6169)
236 --+++ src/lib/runscript.c       (copie de travail)
237 --@@ -59,15 +59,20 @@
238 -- 
239 -- void RUNSCRIPT::reset_default(bool free_strings)
240 -- {
241 ---   if (free_strings && command) {
242 ---     free_pool_memory(command);
243 --+   char *c;
244 --+   if (free_strings && commands) {
245 --+      foreach_alist(c, commands) {
246 --+         free_pool_memory(c);
247 --+      }
248 --    }
249 --    if (free_strings && target) {
250 --      free_pool_memory(target);
251 --    }
252 ---   
253 --    target = NULL;
254 ---   command = NULL;
255 --+   if (commands) {
256 --+      delete commands;
257 --+      commands = NULL;
258 --+   }
259 --    on_success = true;
260 --    on_failure = false;
261 --    fail_on_error = true;
262 --@@ -76,17 +81,23 @@
263 --    job_code_callback = NULL;
264 -- }
265 -- 
266 ---RUNSCRIPT *copy_runscript(RUNSCRIPT *src)
267 --+Runscript *copy_runscript(RUNSCRIPT *src)
268 -- {
269 --    Dmsg0(500, "runscript: creating new RUNSCRIPT object from other\n");
270 -- 
271 --    RUNSCRIPT *dst = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
272 --    memcpy(dst, src, sizeof(RUNSCRIPT));
273 -- 
274 ---   dst->command = NULL;
275 --+   dst->commands =  New(alist(5, not_owned_by_alist));
276 --+   char *c;
277 --+   POOLMEM *m;
278 --+   foreach_alist(c, src->commands) {
279 --+      m = get_pool_memory(PM_FNAME);
280 --+      pm_strcpy(m, c);
281 --+      dst->commands->append(m);
282 --+   }
283 --+
284 --    dst->target = NULL;
285 ---
286 ---   dst->set_command(src->command, src->cmd_type);
287 --    dst->set_target(src->target);
288 -- 
289 --    return dst;   
290 --@@ -95,9 +106,12 @@
291 -- void free_runscript(RUNSCRIPT *script)
292 -- {
293 --    Dmsg0(500, "runscript: freeing RUNSCRIPT object\n");
294 ---
295 ---   if (script->command) {
296 ---      free_pool_memory(script->command);
297 --+   POOLMEM *c;
298 --+   if (script->commands) {
299 --+      foreach_alist(c, script->commands) {
300 --+         free_pool_memory(c);
301 --+      }
302 --+      delete script->commands;
303 --    }
304 --    if (script->target) {
305 --       free_pool_memory(script->target);
306 --@@ -108,60 +122,15 @@
307 -- int run_scripts(JCR *jcr, alist *runscripts, const char *label)
308 -- {
309 --    Dmsg2(200, "runscript: running all RUNSCRIPT object (%s) JobStatus=%c\n", label, jcr->JobStatus);
310 ---   
311 ---   RUNSCRIPT *script;
312 ---   bool runit;
313 -- 
314 ---   int when;
315 ---
316 ---   if (strstr(label, NT_("Before"))) {
317 ---      when = SCRIPT_Before;
318 ---   } else {
319 ---      when = SCRIPT_After;
320 ---   }
321 ---
322 --    if (runscripts == NULL) {
323 --       Dmsg0(100, "runscript: WARNING RUNSCRIPTS list is NULL\n");
324 --       return 0;
325 --    }
326 ---
327 --+   
328 --+   RUNSCRIPT *script;
329 --    foreach_alist(script, runscripts) {
330 ---      Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(script->target), NPRT(script->command));
331 ---      runit = false;
332 ---
333 ---      if ((script->when & SCRIPT_Before) && (when & SCRIPT_Before)) {
334 ---         if ((script->on_success 
335 ---            && (jcr->JobStatus == JS_Running || jcr->JobStatus == JS_Created))
336 ---            || (script->on_failure && job_canceled(jcr))
337 ---            )
338 ---         {
339 ---            Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n", 
340 ---                  script->command, script->on_success, script->on_failure,
341 ---                  jcr->JobStatus );
342 ---            runit = true;
343 ---         }
344 ---      }
345 ---
346 ---      if ((script->when & SCRIPT_After) && (when & SCRIPT_After)) {
347 ---         if ((script->on_success && (jcr->JobStatus == JS_Terminated))
348 ---             || (script->on_failure && job_canceled(jcr))
349 ---            )
350 ---         {
351 ---            Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n", 
352 ---                  script->command, script->on_success, script->on_failure,
353 ---                  jcr->JobStatus );
354 ---            runit = true;
355 ---         }
356 ---      }
357 ---
358 ---      if (!script->is_local()) {
359 ---         runit = false;
360 ---      }
361 ---
362 ---      /* we execute it */
363 ---      if (runit) {
364 ---         script->run(jcr, label);
365 ---      }
366 --+      script->run(jcr, label);
367 --    }
368 --    return 1;
369 -- }
370 --@@ -176,7 +145,7 @@
371 -- }
372 -- 
373 -- /* set this->command to cmd */
374 ---void RUNSCRIPT::set_command(const POOLMEM *cmd, int acmd_type)
375 --+void RUNSCRIPT::add_command(const POOLMEM *cmd, char acmd_type)
376 -- {
377 --    Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd));
378 -- 
379 --@@ -184,14 +153,21 @@
380 --       return;
381 --    }
382 -- 
383 ---   if (!command) {
384 ---      command = get_pool_memory(PM_FNAME);
385 --+   if (!commands) {
386 --+      commands = New(alist(5, not_owned_by_alist)); 
387 --    }
388 -- 
389 ---   pm_strcpy(command, cmd);
390 ---   cmd_type = acmd_type;
391 --+   POOLMEM *c = get_pool_memory(PM_FNAME);
392 --+   Mmsg(c, "%c%s", acmd_type, cmd);
393 --+   commands->append(c);
394 -- }
395 -- 
396 --+void RUNSCRIPT::get_command(const char* command, char *acmd_type, char **cmd)
397 --+{
398 --+   *acmd_type = command[0];
399 --+   *cmd = (char *)command + 1;
400 --+}
401 --+
402 -- /* set this->target to client_name */
403 -- void RUNSCRIPT::set_target(const POOLMEM *client_name)
404 -- {
405 --@@ -210,14 +186,71 @@
406 -- 
407 -- bool RUNSCRIPT::run(JCR *jcr, const char *name)
408 -- {
409 ---   Dmsg1(100, "runscript: running a RUNSCRIPT object type=%d\n", cmd_type);
410 --+   char *c;
411 --+   bool runit;
412 --+
413 --+   int when;
414 --+
415 --+   if (strstr(name, NT_("Before"))) {
416 --+      when = SCRIPT_Before;
417 --+   } else {
418 --+      when = SCRIPT_After;
419 --+   }
420 --+
421 --+   foreach_alist(c, this->commands) {
422 --+      Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(this->target), NPRT(c));
423 --+      runit = false;
424 --+
425 --+      if ((this->when & SCRIPT_Before) && (when & SCRIPT_Before)) {
426 --+         if ((this->on_success 
427 --+            && (jcr->JobStatus == JS_Running || jcr->JobStatus == JS_Created))
428 --+            || (this->on_failure && job_canceled(jcr))
429 --+            )
430 --+         {
431 --+            Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n", 
432 --+                  c, this->on_success, this->on_failure,
433 --+                  jcr->JobStatus );
434 --+            runit = true;
435 --+         }
436 --+      }
437 --+
438 --+      if ((this->when & SCRIPT_After) && (when & SCRIPT_After)) {
439 --+         if ((this->on_success && (jcr->JobStatus == JS_Terminated))
440 --+             || (this->on_failure && job_canceled(jcr))
441 --+            )
442 --+         {
443 --+            Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n", 
444 --+                  c, this->on_success, this->on_failure,
445 --+                  jcr->JobStatus );
446 --+            runit = true;
447 --+         }
448 --+      }
449 --+
450 --+      if (!this->is_local()) {
451 --+         runit = false;
452 --+      }
453 --+
454 --+      /* we execute it */
455 --+      if (runit) {
456 --+         this->run_command(c, jcr, name);
457 --+      }
458 --+   }
459 --+   return 1;
460 --+}
461 --+
462 --+bool RUNSCRIPT::run_command(const char *command, JCR *jcr, const char *name)
463 --+{
464 --    POOLMEM *ecmd = get_pool_memory(PM_FNAME);
465 --    int status;
466 --    BPIPE *bpipe;
467 --    char line[MAXSTRING];
468 --+   char cmd_type;
469 --+   char *cmd;
470 -- 
471 ---   ecmd = edit_job_codes(jcr, ecmd, this->command, "", this->job_code_callback);
472 ---   Dmsg1(100, "runscript: running '%s'...\n", ecmd);
473 --+   this->get_command(command, &cmd_type, &cmd);
474 --+   ecmd = edit_job_codes(jcr, ecmd, cmd, "", this->job_code_callback);
475 --+
476 --+   Dmsg2(100, "runscript: running '%s' object type=%c...\n", ecmd, cmd_type);
477 --    Jmsg(jcr, M_INFO, 0, _("%s: run %s \"%s\"\n"), 
478 --         cmd_type==SHELL_CMD?"shell command":"console command", name, ecmd);
479 -- 
480 --@@ -278,9 +311,12 @@
481 -- 
482 -- void RUNSCRIPT::debug()
483 -- {
484 --+   char *c;
485 --    Dmsg0(200, "runscript: debug\n");
486 --    Dmsg0(200,  _(" --> RunScript\n"));
487 ---   Dmsg1(200,  _("  --> Command=%s\n"), NPRT(command));
488 --+   foreach_alist(c, commands) {
489 --+      Dmsg1(200,  _("  --> Command=%s\n"), NPRT(c));
490 --+   }
491 --    Dmsg1(200,  _("  --> Target=%s\n"),  NPRT(target));
492 --    Dmsg1(200,  _("  --> RunOnSuccess=%u\n"),  on_success);
493 --    Dmsg1(200,  _("  --> RunOnFailure=%u\n"),  on_failure);
494 -Index: src/dird/fd_cmds.c
495 -===================================================================
496 ---- src/dird/fd_cmds.c (révision 6169)
497 -+++ src/dird/fd_cmds.c (copie de travail)
498 -@@ -527,7 +527,8 @@
499 -    RUNSCRIPT *cmd;
500 -    bool launch_before_cmd = false;
501 -    POOLMEM *ehost = get_pool_memory(PM_FNAME);
502 --   int result;
503 -+   int result, cmd_type;
504 -+   char *c, *command;
505
506 -    Dmsg0(120, "bdird: sending runscripts to fd\n");
507 -    
508 -@@ -537,29 +538,33 @@
509 -          Dmsg2(200, "bdird: runscript %s -> %s\n", cmd->target, ehost);
510
511 -          if (strcmp(ehost, jcr->client->name()) == 0) {
512 --            pm_strcpy(msg, cmd->command);
513 --            bash_spaces(msg);
514 -+            foreach_alist(c, cmd->commands) {
515 -+               cmd->get_command(c, &cmd_type, &command);
516 -+               if (cmd_type == SHELL_CMD) {
517 -+                  pm_strcpy(msg, command);
518 -+                  bash_spaces(msg);
519
520 --            Dmsg1(120, "bdird: sending runscripts to fd '%s'\n", cmd->command);
521 -+                  Dmsg1(120, "bdird: sending runscripts to fd '%s'\n", command);
522 -             
523 --            /* TODO: remove this with bacula 1.42 */
524 --            if (cmd->old_proto) {
525 --               result = send_runscript_with_old_proto(jcr, cmd->when, msg);
526 -+                  /* TODO: remove this with bacula 1.42 */
527 -+                  if (cmd->old_proto) {
528 -+                     result = send_runscript_with_old_proto(jcr, cmd->when, msg);
529 -+                     
530 -+                  } else {
531 -+                     fd->fsend(runscript, cmd->on_success, 
532 -+                                          cmd->on_failure,
533 -+                                          cmd->fail_on_error,
534 -+                                          cmd->when,
535 -+                                          msg);
536
537 --            } else {
538 --               fd->fsend(runscript, cmd->on_success, 
539 --                                    cmd->on_failure,
540 --                                    cmd->fail_on_error,
541 --                                    cmd->when,
542 --                                    msg);
543 --
544 --               result = response(jcr, fd, OKRunScript, "RunScript", DISPLAY_ERROR);
545 --               launch_before_cmd = true;
546 -+                     result = response(jcr, fd, OKRunScript, "RunScript", DISPLAY_ERROR);
547 -+                     launch_before_cmd = true;
548 -+                  }
549 -+                  if (!result) {
550 -+                     goto bail_out;
551 -+                  }
552 -+               }
553 -             }
554 --            
555 --            if (!result) {
556 --               goto bail_out;
557 --            }
558 -          }
559 -          /* TODO : we have to play with other client */
560 -          /*
561 -@@ -567,7 +572,7 @@
562 -            send command to an other client
563 -            }
564 -          */
565 --      }        
566 -+      }
567 -    } 
568
569 -    /* Tell the FD to execute the ClientRunBeforeJob */
570 -Index: src/dird/dird_conf.c
571 -===================================================================
572 ---- src/dird/dird_conf.c       (révision 6169)
573 -+++ src/dird/dird_conf.c       (copie de travail)
574 -@@ -651,16 +651,19 @@
575 -          }
576 -       }
577 -       if (res->res_job.RunScripts) {
578 --        RUNSCRIPT *script;
579 --        foreach_alist(script, res->res_job.RunScripts) {
580 --           sendit(sock, _(" --> RunScript\n"));
581 --           sendit(sock, _("  --> Command=%s\n"), NPRT(script->command));
582 --           sendit(sock, _("  --> Target=%s\n"),  NPRT(script->target));
583 --           sendit(sock, _("  --> RunOnSuccess=%u\n"),  script->on_success);
584 --           sendit(sock, _("  --> RunOnFailure=%u\n"),  script->on_failure);
585 --           sendit(sock, _("  --> FailJobOnError=%u\n"),  script->fail_on_error);
586 --           sendit(sock, _("  --> RunWhen=%u\n"),  script->when);
587 --        }
588 -+         char *c;
589 -+         RUNSCRIPT *script;
590 -+         foreach_alist(script, res->res_job.RunScripts) {
591 -+            sendit(sock, _(" --> RunScript\n"));
592 -+            foreach_alist(c, script->commands) {
593 -+               sendit(sock, _("  --> Command=%s\n"), NPRT(c));
594 -+            }
595 -+            sendit(sock, _("  --> Target=%s\n"),  NPRT(script->target));
596 -+            sendit(sock, _("  --> RunOnSuccess=%u\n"),  script->on_success);
597 -+            sendit(sock, _("  --> RunOnFailure=%u\n"),  script->on_failure);
598 -+            sendit(sock, _("  --> FailJobOnError=%u\n"),  script->fail_on_error);
599 -+            sendit(sock, _("  --> RunWhen=%u\n"),  script->when);
600 -+         }
601 -       }
602 -       if (res->res_job.pool) {
603 -          sendit(sock, _("  --> "));
604 -@@ -1724,14 +1727,14 @@
605 - }
606
607 - /*
608 -- * Store a runscript->command as a string
609 -+ * Store a runscript->commands as a alist(char + string)
610 -  */
611 - static void store_runscript_cmd(LEX *lc, RES_ITEM *item, int index, int pass)
612 - {
613 -    lex_get_token(lc, T_STRING);
614
615 -    if (pass == 2) {
616 --      ((RUNSCRIPT*)item->value)->set_command(lc->str, item->code);
617 -+      ((RUNSCRIPT*)item->value)->add_command(lc->str, item->code);
618 -    }
619 -    scan_to_eol(lc);
620 - }
621 -@@ -1745,7 +1748,7 @@
622 -       RUNSCRIPT *script = new_runscript();
623 -       script->set_job_code_callback(job_code_callback_filesetname);
624
625 --      script->set_command(lc->str);
626 -+      script->add_command(lc->str);
627
628 -       /* TODO: remove all script->old_proto with bacula 1.42 */
629
630 -@@ -1873,7 +1876,7 @@
631 -    }
632
633 -    if (pass == 2) {
634 --      if (res_runscript.command == NULL) {
635 -+      if (res_runscript.commands == NULL) {
636 -          scan_err2(lc, _("%s item is required in %s resource, but not found.\n"),
637 -                    "command", "runscript");
638 -       }
639 -@@ -1886,7 +1889,7 @@
640 -       RUNSCRIPT *script = new_runscript();
641 -       memcpy(script, &res_runscript, sizeof(RUNSCRIPT));
642 -       script->set_job_code_callback(job_code_callback_filesetname);
643 --      
644 -+
645 -       if (*runscripts == NULL) {
646 -         *runscripts = New(alist(10, not_owned_by_alist));
647 -       }
648 -Index: src/filed/job.c
649 -===================================================================
650 ---- src/filed/job.c    (révision 6169)
651 -+++ src/filed/job.c    (copie de travail)
652 -@@ -481,7 +481,7 @@
653
654 -    /* Run the command now */
655 -    script = new_runscript();
656 --   script->set_command(cmd);
657 -+   script->add_command(cmd);
658 -    script->when = SCRIPT_Before;
659 -    ok = script->run(jcr, "ClientRunBeforeJob");
660 -    free_runscript(script);
661 -@@ -529,7 +529,7 @@
662 -    unbash_spaces(msg);
663
664 -    cmd = new_runscript();
665 --   cmd->set_command(msg);
666 -+   cmd->add_command(msg);
667 -    cmd->on_success = true;
668 -    cmd->on_failure = false;
669 -    cmd->when = SCRIPT_After;
670 -@@ -567,7 +567,7 @@
671 -    cmd->fail_on_error = fail_on_error;
672 -    unbash_spaces(msg);
673
674 --   cmd->set_command(msg);
675 -+   cmd->add_command(msg);
676 -    cmd->debug();
677 -    jcr->RunScripts->append(cmd);
678
679 -Index: src/lib/runscript.h
680 -===================================================================
681 ---- src/lib/runscript.h        (révision 6169)
682 -+++ src/lib/runscript.h        (copie de travail)
683 -@@ -62,8 +62,8 @@
684 - };
685
686 - enum {
687 --   SHELL_CMD   = 1,
688 --   CONSOLE_CMD = 2 
689 -+   SHELL_CMD   = '|',
690 -+   CONSOLE_CMD = '@' 
691 - };
692
693 - /*
694 -@@ -71,10 +71,9 @@
695 -  */
696 - class RUNSCRIPT {
697 - public:
698 --   POOLMEM *command;            /* command string */
699 -+   alist *commands;             /* list of command/console string */
700 -    POOLMEM *target;             /* host target */
701 -    int  when;                   /* SCRIPT_Before|Script_After BEFORE/AFTER JOB*/
702 --   int  cmd_type;               /* Command type -- Shell, Console */
703 -    char level;                  /* Base|Full|Incr...|All (NYI) */
704 -    bool on_success;             /* execute command on job success (After) */
705 -    bool on_failure;             /* execute command on job failure (After) */
706 -@@ -86,19 +85,22 @@
707
708 -    bool run(JCR *job, const char *name=""); /* name must contain "Before" or "After" keyword */
709 -    bool can_run_at_level(int JobLevel) { return true;};        /* TODO */
710 --   void set_command(const POOLMEM *cmd, int cmd_type = SHELL_CMD);
711 -+   void add_command(const POOLMEM *cmd, char cmd_type = SHELL_CMD);
712 -+   void get_command(const char *cmd, int *cmd_type, char **cmd);
713 -    void set_target(const POOLMEM *client_name);
714 -    void reset_default(bool free_string = false);
715 -    bool is_local();             /* true if running on local host */
716 -    void debug();
717 -+   void set_job_code_callback(job_code_callback_t job_code_callback);
718
719 --   void set_job_code_callback(job_code_callback_t job_code_callback);
720 -+private:
721 -+   bool run_command(const char *cmd, JCR *job, const char *name="");
722 - };
723
724 - /* create new RUNSCRIPT (set all value to 0) */
725 - RUNSCRIPT *new_runscript();           
726
727 --/* create new RUNSCRIPT from an other */
728 -+/* create new RUNSCRIPT from an other (deep copy) */
729 - RUNSCRIPT *copy_runscript(RUNSCRIPT *src);
730
731 - /* launch each script from runscripts*/
732 -Index: src/lib/runscript.c
733 -===================================================================
734 ---- src/lib/runscript.c        (révision 6169)
735 -+++ src/lib/runscript.c        (copie de travail)
736 -@@ -59,15 +59,18 @@
737
738 - void RUNSCRIPT::reset_default(bool free_strings)
739 - {
740 --   if (free_strings && command) {
741 --     free_pool_memory(command);
742 -+   char *c;
743 -+   if (free_strings && commands) {
744 -+      foreach_alist(c, commands) {
745 -+         free_pool_memory(c);
746 -+      }
747 -+      delete commands;
748 -    }
749 -    if (free_strings && target) {
750 -      free_pool_memory(target);
751 -    }
752 --   
753 -    target = NULL;
754 --   command = NULL;
755 -+   commands = NULL;
756 -    on_success = true;
757 -    on_failure = false;
758 -    fail_on_error = true;
759 -@@ -83,10 +86,16 @@
760 -    RUNSCRIPT *dst = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
761 -    memcpy(dst, src, sizeof(RUNSCRIPT));
762
763 --   dst->command = NULL;
764 -+   dst->commands =  New(alist(5, not_owned_by_alist));
765 -+   char *c;
766 -+   POOLMEM *m;
767 -+   foreach_alist(c, src->commands) {
768 -+      m = get_pool_memory(PM_FNAME);
769 -+      pm_strcpy(m, c);
770 -+      dst->commands->append(m);
771 -+   }
772 -+
773 -    dst->target = NULL;
774 --
775 --   dst->set_command(src->command, src->cmd_type);
776 -    dst->set_target(src->target);
777
778 -    return dst;   
779 -@@ -95,9 +104,12 @@
780 - void free_runscript(RUNSCRIPT *script)
781 - {
782 -    Dmsg0(500, "runscript: freeing RUNSCRIPT object\n");
783 --
784 --   if (script->command) {
785 --      free_pool_memory(script->command);
786 -+   POOLMEM *c;
787 -+   if (script->commands) {
788 -+      foreach_alist(c, script->commands) {
789 -+         free_pool_memory(c);
790 -+      }
791 -+      delete script->commands;
792 -    }
793 -    if (script->target) {
794 -       free_pool_memory(script->target);
795 -@@ -108,60 +120,15 @@
796 - int run_scripts(JCR *jcr, alist *runscripts, const char *label)
797 - {
798 -    Dmsg2(200, "runscript: running all RUNSCRIPT object (%s) JobStatus=%c\n", label, jcr->JobStatus);
799 --   
800 --   RUNSCRIPT *script;
801 --   bool runit;
802
803 --   int when;
804 --
805 --   if (strstr(label, NT_("Before"))) {
806 --      when = SCRIPT_Before;
807 --   } else {
808 --      when = SCRIPT_After;
809 --   }
810 --
811 -    if (runscripts == NULL) {
812 -       Dmsg0(100, "runscript: WARNING RUNSCRIPTS list is NULL\n");
813 -       return 0;
814 -    }
815 --
816 -+   
817 -+   RUNSCRIPT *script;
818 -    foreach_alist(script, runscripts) {
819 --      Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(script->target), NPRT(script->command));
820 --      runit = false;
821 --
822 --      if ((script->when & SCRIPT_Before) && (when & SCRIPT_Before)) {
823 --         if ((script->on_success 
824 --            && (jcr->JobStatus == JS_Running || jcr->JobStatus == JS_Created))
825 --            || (script->on_failure && job_canceled(jcr))
826 --            )
827 --         {
828 --            Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n", 
829 --                  script->command, script->on_success, script->on_failure,
830 --                  jcr->JobStatus );
831 --            runit = true;
832 --         }
833 --      }
834 --
835 --      if ((script->when & SCRIPT_After) && (when & SCRIPT_After)) {
836 --         if ((script->on_success && (jcr->JobStatus == JS_Terminated))
837 --             || (script->on_failure && job_canceled(jcr))
838 --            )
839 --         {
840 --            Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n", 
841 --                  script->command, script->on_success, script->on_failure,
842 --                  jcr->JobStatus );
843 --            runit = true;
844 --         }
845 --      }
846 --
847 --      if (!script->is_local()) {
848 --         runit = false;
849 --      }
850 --
851 --      /* we execute it */
852 --      if (runit) {
853 --         script->run(jcr, label);
854 --      }
855 -+      script->run(jcr, label);
856 -    }
857 -    return 1;
858 - }
859 -@@ -175,23 +142,31 @@
860 -    }
861 - }
862
863 --/* set this->command to cmd */
864 --void RUNSCRIPT::set_command(const POOLMEM *cmd, int acmd_type)
865 -+/* set add cmd to this->commands alist */
866 -+void RUNSCRIPT::add_command(const POOLMEM *cmd, char acmd_type)
867 - {
868 --   Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd));
869 -+   Dmsg2(500, "runscript: setting command = %s type=%i\n", NPRT(cmd), acmd_type);
870
871 -    if (!cmd) {
872 -       return;
873 -    }
874
875 --   if (!command) {
876 --      command = get_pool_memory(PM_FNAME);
877 -+   if (!commands) {
878 -+      commands = New(alist(5, not_owned_by_alist)); 
879 -    }
880
881 --   pm_strcpy(command, cmd);
882 --   cmd_type = acmd_type;
883 -+   POOLMEM *c = get_pool_memory(PM_FNAME);
884 -+   Mmsg(c, "%c%s", acmd_type, cmd);
885 -+   commands->append(c);
886 - }
887
888 -+/* command = ( SHELL_CMD | CONSOLE_CMD ) command */
889 -+void RUNSCRIPT::get_command(const char* command, int *acmd_type, char **cmd)
890 -+{
891 -+   *acmd_type = (int) command[0];
892 -+   *cmd = (char *)command + 1;
893 -+}
894 -+
895 - /* set this->target to client_name */
896 - void RUNSCRIPT::set_target(const POOLMEM *client_name)
897 - {
898 -@@ -210,14 +185,70 @@
899
900 - bool RUNSCRIPT::run(JCR *jcr, const char *name)
901 - {
902 --   Dmsg1(100, "runscript: running a RUNSCRIPT object type=%d\n", cmd_type);
903 -+   char *c;
904 -+   bool runit;
905 -+
906 -+   int when;
907 -+
908 -+   if (strstr(name, NT_("Before"))) {
909 -+      when = SCRIPT_Before;
910 -+   } else {
911 -+      when = SCRIPT_After;
912 -+   }
913 -+
914 -+   foreach_alist(c, this->commands) {
915 -+      Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(this->target), NPRT(c));
916 -+      runit = false;
917 -+
918 -+      if ((this->when & SCRIPT_Before) && (when & SCRIPT_Before)) {
919 -+         if ((this->on_success 
920 -+            && (jcr->JobStatus == JS_Running || jcr->JobStatus == JS_Created))
921 -+            || (this->on_failure && job_canceled(jcr))
922 -+            )
923 -+         {
924 -+            Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n", 
925 -+                  c, this->on_success, this->on_failure,
926 -+                  jcr->JobStatus );
927 -+            runit = true;
928 -+         }
929 -+      }
930 -+
931 -+      if ((this->when & SCRIPT_After) && (when & SCRIPT_After)) {
932 -+         if ((this->on_success && (jcr->JobStatus == JS_Terminated))
933 -+             || (this->on_failure && job_canceled(jcr))
934 -+            )
935 -+         {
936 -+            Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n", 
937 -+                  c, this->on_success, this->on_failure,
938 -+                  jcr->JobStatus );
939 -+            runit = true;
940 -+         }
941 -+      }
942 -+
943 -+      if (!this->is_local()) {
944 -+         runit = false;
945 -+      }
946 -+
947 -+      /* we execute it */
948 -+      if (runit) {
949 -+         this->run_command(c, jcr, name);
950 -+      }
951 -+   }
952 -+   return 1;
953 -+}
954 -+
955 -+/* run a command from the list */
956 -+bool RUNSCRIPT::run_command(const char *command, JCR *jcr, const char *name)
957 -+{
958 -    POOLMEM *ecmd = get_pool_memory(PM_FNAME);
959 --   int status;
960 -+   int status, cmd_type;
961 -    BPIPE *bpipe;
962 --   char line[MAXSTRING];
963 -+   char line[MAXSTRING], *cmd;
964
965 --   ecmd = edit_job_codes(jcr, ecmd, this->command, "", this->job_code_callback);
966 --   Dmsg1(100, "runscript: running '%s'...\n", ecmd);
967 -+   this->get_command(command, &cmd_type, &cmd);
968 -+   ecmd = edit_job_codes(jcr, ecmd, cmd, "", this->job_code_callback);
969 -+
970 -+   Dmsg2(100, "runscript: running '%s' object type=%c...\n", ecmd, cmd_type);
971 -    Jmsg(jcr, M_INFO, 0, _("%s: run %s \"%s\"\n"), 
972 -         cmd_type==SHELL_CMD?"shell command":"console command", name, ecmd);
973
974 -@@ -278,9 +309,12 @@
975
976 - void RUNSCRIPT::debug()
977 - {
978 -+   char *c;
979 -    Dmsg0(200, "runscript: debug\n");
980 -    Dmsg0(200,  _(" --> RunScript\n"));
981 --   Dmsg1(200,  _("  --> Command=%s\n"), NPRT(command));
982 -+   foreach_alist(c, commands) {
983 -+      Dmsg1(200,  _("  --> Command=%s\n"), NPRT(c));
984 -+   }
985 -    Dmsg1(200,  _("  --> Target=%s\n"),  NPRT(target));
986 -    Dmsg1(200,  _("  --> RunOnSuccess=%u\n"),  on_success);
987 -    Dmsg1(200,  _("  --> RunOnFailure=%u\n"),  on_failure);
988 Index: src/dird/fd_cmds.c
989 ===================================================================
990 --- src/dird/fd_cmds.c  (révision 6169)
991 +++ src/dird/fd_cmds.c  (copie de travail)
992 @@ -527,7 +527,8 @@
993     RUNSCRIPT *cmd;
994     bool launch_before_cmd = false;
995     POOLMEM *ehost = get_pool_memory(PM_FNAME);
996 -   int result;
997 +   int result, cmd_type;
998 +   char *c, *command;
999  
1000     Dmsg0(120, "bdird: sending runscripts to fd\n");
1001     
1002 @@ -537,29 +538,33 @@
1003           Dmsg2(200, "bdird: runscript %s -> %s\n", cmd->target, ehost);
1004  
1005           if (strcmp(ehost, jcr->client->name()) == 0) {
1006 -            pm_strcpy(msg, cmd->command);
1007 -            bash_spaces(msg);
1008 +            foreach_alist(c, cmd->commands) {
1009 +               cmd->get_command(c, &cmd_type, &command);
1010 +               if (cmd_type == SHELL_CMD) {
1011 +                  pm_strcpy(msg, command);
1012 +                  bash_spaces(msg);
1013  
1014 -            Dmsg1(120, "bdird: sending runscripts to fd '%s'\n", cmd->command);
1015 +                  Dmsg1(120, "bdird: sending runscripts to fd '%s'\n", command);
1016              
1017 -            /* TODO: remove this with bacula 1.42 */
1018 -            if (cmd->old_proto) {
1019 -               result = send_runscript_with_old_proto(jcr, cmd->when, msg);
1020 +                  /* TODO: remove this with bacula 1.42 */
1021 +                  if (cmd->old_proto) {
1022 +                     result = send_runscript_with_old_proto(jcr, cmd->when, msg);
1023 +                     
1024 +                  } else {
1025 +                     fd->fsend(runscript, cmd->on_success, 
1026 +                                          cmd->on_failure,
1027 +                                          cmd->fail_on_error,
1028 +                                          cmd->when,
1029 +                                          msg);
1030  
1031 -            } else {
1032 -               fd->fsend(runscript, cmd->on_success, 
1033 -                                    cmd->on_failure,
1034 -                                    cmd->fail_on_error,
1035 -                                    cmd->when,
1036 -                                    msg);
1037 -
1038 -               result = response(jcr, fd, OKRunScript, "RunScript", DISPLAY_ERROR);
1039 -               launch_before_cmd = true;
1040 +                     result = response(jcr, fd, OKRunScript, "RunScript", DISPLAY_ERROR);
1041 +                     launch_before_cmd = true;
1042 +                  }
1043 +                  if (!result) {
1044 +                     goto bail_out;
1045 +                  }
1046 +               }
1047              }
1048 -            
1049 -            if (!result) {
1050 -               goto bail_out;
1051 -            }
1052           }
1053           /* TODO : we have to play with other client */
1054           /*
1055 @@ -567,7 +572,7 @@
1056             send command to an other client
1057             }
1058           */
1059 -      }        
1060 +      }
1061     } 
1062  
1063     /* Tell the FD to execute the ClientRunBeforeJob */
1064 Index: src/dird/dird_conf.c
1065 ===================================================================
1066 --- src/dird/dird_conf.c        (révision 6169)
1067 +++ src/dird/dird_conf.c        (copie de travail)
1068 @@ -651,16 +651,19 @@
1069           }
1070        }
1071        if (res->res_job.RunScripts) {
1072 -        RUNSCRIPT *script;
1073 -        foreach_alist(script, res->res_job.RunScripts) {
1074 -           sendit(sock, _(" --> RunScript\n"));
1075 -           sendit(sock, _("  --> Command=%s\n"), NPRT(script->command));
1076 -           sendit(sock, _("  --> Target=%s\n"),  NPRT(script->target));
1077 -           sendit(sock, _("  --> RunOnSuccess=%u\n"),  script->on_success);
1078 -           sendit(sock, _("  --> RunOnFailure=%u\n"),  script->on_failure);
1079 -           sendit(sock, _("  --> FailJobOnError=%u\n"),  script->fail_on_error);
1080 -           sendit(sock, _("  --> RunWhen=%u\n"),  script->when);
1081 -        }
1082 +         char *c;
1083 +         RUNSCRIPT *script;
1084 +         foreach_alist(script, res->res_job.RunScripts) {
1085 +            sendit(sock, _(" --> RunScript\n"));
1086 +            foreach_alist(c, script->commands) {
1087 +               sendit(sock, _("  --> Command=%s\n"), NPRT(c));
1088 +            }
1089 +            sendit(sock, _("  --> Target=%s\n"),  NPRT(script->target));
1090 +            sendit(sock, _("  --> RunOnSuccess=%u\n"),  script->on_success);
1091 +            sendit(sock, _("  --> RunOnFailure=%u\n"),  script->on_failure);
1092 +            sendit(sock, _("  --> FailJobOnError=%u\n"),  script->fail_on_error);
1093 +            sendit(sock, _("  --> RunWhen=%u\n"),  script->when);
1094 +         }
1095        }
1096        if (res->res_job.pool) {
1097           sendit(sock, _("  --> "));
1098 @@ -1724,14 +1727,14 @@
1099  }
1100  
1101  /*
1102 - * Store a runscript->command as a string
1103 + * Store a runscript->commands as a alist(char + string)
1104   */
1105  static void store_runscript_cmd(LEX *lc, RES_ITEM *item, int index, int pass)
1106  {
1107     lex_get_token(lc, T_STRING);
1108  
1109     if (pass == 2) {
1110 -      ((RUNSCRIPT*)item->value)->set_command(lc->str, item->code);
1111 +      ((RUNSCRIPT*)item->value)->add_command(lc->str, item->code);
1112     }
1113     scan_to_eol(lc);
1114  }
1115 @@ -1745,7 +1748,7 @@
1116        RUNSCRIPT *script = new_runscript();
1117        script->set_job_code_callback(job_code_callback_filesetname);
1118  
1119 -      script->set_command(lc->str);
1120 +      script->add_command(lc->str);
1121  
1122        /* TODO: remove all script->old_proto with bacula 1.42 */
1123  
1124 @@ -1873,7 +1876,7 @@
1125     }
1126  
1127     if (pass == 2) {
1128 -      if (res_runscript.command == NULL) {
1129 +      if (res_runscript.commands == NULL) {
1130           scan_err2(lc, _("%s item is required in %s resource, but not found.\n"),
1131                     "command", "runscript");
1132        }
1133 @@ -1886,7 +1889,7 @@
1134        RUNSCRIPT *script = new_runscript();
1135        memcpy(script, &res_runscript, sizeof(RUNSCRIPT));
1136        script->set_job_code_callback(job_code_callback_filesetname);
1137 -      
1138 +
1139        if (*runscripts == NULL) {
1140          *runscripts = New(alist(10, not_owned_by_alist));
1141        }
1142 Index: src/filed/job.c
1143 ===================================================================
1144 --- src/filed/job.c     (révision 6169)
1145 +++ src/filed/job.c     (copie de travail)
1146 @@ -481,7 +481,7 @@
1147  
1148     /* Run the command now */
1149     script = new_runscript();
1150 -   script->set_command(cmd);
1151 +   script->add_command(cmd);
1152     script->when = SCRIPT_Before;
1153     ok = script->run(jcr, "ClientRunBeforeJob");
1154     free_runscript(script);
1155 @@ -529,7 +529,7 @@
1156     unbash_spaces(msg);
1157  
1158     cmd = new_runscript();
1159 -   cmd->set_command(msg);
1160 +   cmd->add_command(msg);
1161     cmd->on_success = true;
1162     cmd->on_failure = false;
1163     cmd->when = SCRIPT_After;
1164 @@ -567,7 +567,7 @@
1165     cmd->fail_on_error = fail_on_error;
1166     unbash_spaces(msg);
1167  
1168 -   cmd->set_command(msg);
1169 +   cmd->add_command(msg);
1170     cmd->debug();
1171     jcr->RunScripts->append(cmd);
1172  
1173 Index: src/lib/runscript.h
1174 ===================================================================
1175 --- src/lib/runscript.h (révision 6169)
1176 +++ src/lib/runscript.h (copie de travail)
1177 @@ -62,8 +62,8 @@
1178  };
1179  
1180  enum {
1181 -   SHELL_CMD   = 1,
1182 -   CONSOLE_CMD = 2 
1183 +   SHELL_CMD   = '|',
1184 +   CONSOLE_CMD = '@' 
1185  };
1186  
1187  /*
1188 @@ -71,10 +71,9 @@
1189   */
1190  class RUNSCRIPT {
1191  public:
1192 -   POOLMEM *command;            /* command string */
1193 +   alist *commands;             /* list of command/console string */
1194     POOLMEM *target;             /* host target */
1195     int  when;                   /* SCRIPT_Before|Script_After BEFORE/AFTER JOB*/
1196 -   int  cmd_type;               /* Command type -- Shell, Console */
1197     char level;                  /* Base|Full|Incr...|All (NYI) */
1198     bool on_success;             /* execute command on job success (After) */
1199     bool on_failure;             /* execute command on job failure (After) */
1200 @@ -86,19 +85,22 @@
1201  
1202     bool run(JCR *job, const char *name=""); /* name must contain "Before" or "After" keyword */
1203     bool can_run_at_level(int JobLevel) { return true;};        /* TODO */
1204 -   void set_command(const POOLMEM *cmd, int cmd_type = SHELL_CMD);
1205 +   void add_command(const POOLMEM *cmd, char cmd_type = SHELL_CMD);
1206 +   void get_command(const char *cmd, int *cmd_type, char **cmd);
1207     void set_target(const POOLMEM *client_name);
1208     void reset_default(bool free_string = false);
1209 -   bool is_local();             /* true if running on local host */
1210 +   bool is_local(const char *cmd); /* true if running on local host */
1211     void debug();
1212 +   void set_job_code_callback(job_code_callback_t job_code_callback);
1213  
1214 -   void set_job_code_callback(job_code_callback_t job_code_callback);
1215 +private:
1216 +   bool run_command(const char *cmd, JCR *job, const char *name="");
1217  };
1218  
1219  /* create new RUNSCRIPT (set all value to 0) */
1220  RUNSCRIPT *new_runscript();           
1221  
1222 -/* create new RUNSCRIPT from an other */
1223 +/* create new RUNSCRIPT from an other (deep copy) */
1224  RUNSCRIPT *copy_runscript(RUNSCRIPT *src);
1225  
1226  /* launch each script from runscripts*/
1227 Index: src/lib/runscript.c
1228 ===================================================================
1229 --- src/lib/runscript.c (révision 6169)
1230 +++ src/lib/runscript.c (copie de travail)
1231 @@ -59,15 +59,18 @@
1232  
1233  void RUNSCRIPT::reset_default(bool free_strings)
1234  {
1235 -   if (free_strings && command) {
1236 -     free_pool_memory(command);
1237 +   char *c;
1238 +   if (free_strings && commands) {
1239 +      foreach_alist(c, commands) {
1240 +         free_pool_memory(c);
1241 +      }
1242 +      delete commands;
1243     }
1244     if (free_strings && target) {
1245       free_pool_memory(target);
1246     }
1247 -   
1248     target = NULL;
1249 -   command = NULL;
1250 +   commands = NULL;
1251     on_success = true;
1252     on_failure = false;
1253     fail_on_error = true;
1254 @@ -83,10 +86,16 @@
1255     RUNSCRIPT *dst = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
1256     memcpy(dst, src, sizeof(RUNSCRIPT));
1257  
1258 -   dst->command = NULL;
1259 +   dst->commands =  New(alist(5, not_owned_by_alist));
1260 +   char *c;
1261 +   POOLMEM *m;
1262 +   foreach_alist(c, src->commands) {
1263 +      m = get_pool_memory(PM_FNAME);
1264 +      pm_strcpy(m, c);
1265 +      dst->commands->append(m);
1266 +   }
1267 +
1268     dst->target = NULL;
1269 -
1270 -   dst->set_command(src->command, src->cmd_type);
1271     dst->set_target(src->target);
1272  
1273     return dst;   
1274 @@ -95,9 +104,12 @@
1275  void free_runscript(RUNSCRIPT *script)
1276  {
1277     Dmsg0(500, "runscript: freeing RUNSCRIPT object\n");
1278 -
1279 -   if (script->command) {
1280 -      free_pool_memory(script->command);
1281 +   POOLMEM *c;
1282 +   if (script->commands) {
1283 +      foreach_alist(c, script->commands) {
1284 +         free_pool_memory(c);
1285 +      }
1286 +      delete script->commands;
1287     }
1288     if (script->target) {
1289        free_pool_memory(script->target);
1290 @@ -108,66 +120,25 @@
1291  int run_scripts(JCR *jcr, alist *runscripts, const char *label)
1292  {
1293     Dmsg2(200, "runscript: running all RUNSCRIPT object (%s) JobStatus=%c\n", label, jcr->JobStatus);
1294 -   
1295 -   RUNSCRIPT *script;
1296 -   bool runit;
1297  
1298 -   int when;
1299 -
1300 -   if (strstr(label, NT_("Before"))) {
1301 -      when = SCRIPT_Before;
1302 -   } else {
1303 -      when = SCRIPT_After;
1304 -   }
1305 -
1306     if (runscripts == NULL) {
1307        Dmsg0(100, "runscript: WARNING RUNSCRIPTS list is NULL\n");
1308        return 0;
1309     }
1310 -
1311 +   
1312 +   RUNSCRIPT *script;
1313     foreach_alist(script, runscripts) {
1314 -      Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(script->target), NPRT(script->command));
1315 -      runit = false;
1316 -
1317 -      if ((script->when & SCRIPT_Before) && (when & SCRIPT_Before)) {
1318 -         if ((script->on_success 
1319 -            && (jcr->JobStatus == JS_Running || jcr->JobStatus == JS_Created))
1320 -            || (script->on_failure && job_canceled(jcr))
1321 -            )
1322 -         {
1323 -            Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n", 
1324 -                  script->command, script->on_success, script->on_failure,
1325 -                  jcr->JobStatus );
1326 -            runit = true;
1327 -         }
1328 -      }
1329 -
1330 -      if ((script->when & SCRIPT_After) && (when & SCRIPT_After)) {
1331 -         if ((script->on_success && (jcr->JobStatus == JS_Terminated))
1332 -             || (script->on_failure && job_canceled(jcr))
1333 -            )
1334 -         {
1335 -            Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n", 
1336 -                  script->command, script->on_success, script->on_failure,
1337 -                  jcr->JobStatus );
1338 -            runit = true;
1339 -         }
1340 -      }
1341 -
1342 -      if (!script->is_local()) {
1343 -         runit = false;
1344 -      }
1345 -
1346 -      /* we execute it */
1347 -      if (runit) {
1348 -         script->run(jcr, label);
1349 -      }
1350 +      script->run(jcr, label);
1351     }
1352     return 1;
1353  }
1354  
1355 -bool RUNSCRIPT::is_local()
1356 +bool RUNSCRIPT::is_local(const char *c)
1357  {
1358 +   if (c[0] == CONSOLE_CMD) {
1359 +      return true;
1360 +   }
1361 +
1362     if (!target || (strcmp(target, "") == 0)) {
1363        return true;
1364     } else {
1365 @@ -175,23 +146,31 @@
1366     }
1367  }
1368  
1369 -/* set this->command to cmd */
1370 -void RUNSCRIPT::set_command(const POOLMEM *cmd, int acmd_type)
1371 +/* set add cmd to this->commands alist */
1372 +void RUNSCRIPT::add_command(const POOLMEM *cmd, char acmd_type)
1373  {
1374 -   Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd));
1375 +   Dmsg2(500, "runscript: setting command = %s type=%i\n", NPRT(cmd), acmd_type);
1376  
1377     if (!cmd) {
1378        return;
1379     }
1380  
1381 -   if (!command) {
1382 -      command = get_pool_memory(PM_FNAME);
1383 +   if (!commands) {
1384 +      commands = New(alist(5, not_owned_by_alist)); 
1385     }
1386  
1387 -   pm_strcpy(command, cmd);
1388 -   cmd_type = acmd_type;
1389 +   POOLMEM *c = get_pool_memory(PM_FNAME);
1390 +   Mmsg(c, "%c%s", acmd_type, cmd);
1391 +   commands->append(c);
1392  }
1393  
1394 +/* command = ( SHELL_CMD | CONSOLE_CMD ) command */
1395 +void RUNSCRIPT::get_command(const char* command, int *acmd_type, char **cmd)
1396 +{
1397 +   *acmd_type = (int) command[0];
1398 +   *cmd = (char *)command + 1;
1399 +}
1400 +
1401  /* set this->target to client_name */
1402  void RUNSCRIPT::set_target(const POOLMEM *client_name)
1403  {
1404 @@ -210,14 +189,70 @@
1405  
1406  bool RUNSCRIPT::run(JCR *jcr, const char *name)
1407  {
1408 -   Dmsg1(100, "runscript: running a RUNSCRIPT object type=%d\n", cmd_type);
1409 +   char *c;
1410 +   bool runit;
1411 +
1412 +   int when;
1413 +
1414 +   if (strstr(name, NT_("Before"))) {
1415 +      when = SCRIPT_Before;
1416 +   } else {
1417 +      when = SCRIPT_After;
1418 +   }
1419 +
1420 +   foreach_alist(c, this->commands) {
1421 +      Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(this->target), NPRT(c));
1422 +      runit = false;
1423 +
1424 +      if ((this->when & SCRIPT_Before) && (when & SCRIPT_Before)) {
1425 +         if ((this->on_success 
1426 +            && (jcr->JobStatus == JS_Running || jcr->JobStatus == JS_Created))
1427 +            || (this->on_failure && job_canceled(jcr))
1428 +            )
1429 +         {
1430 +            Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n", 
1431 +                  c, this->on_success, this->on_failure,
1432 +                  jcr->JobStatus );
1433 +            runit = true;
1434 +         }
1435 +      }
1436 +
1437 +      if ((this->when & SCRIPT_After) && (when & SCRIPT_After)) {
1438 +         if ((this->on_success && (jcr->JobStatus == JS_Terminated))
1439 +             || (this->on_failure && job_canceled(jcr))
1440 +            )
1441 +         {
1442 +            Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n", 
1443 +                  c, this->on_success, this->on_failure,
1444 +                  jcr->JobStatus );
1445 +            runit = true;
1446 +         }
1447 +      }
1448 +
1449 +      if (!this->is_local(c)) {
1450 +         runit = false;
1451 +      }
1452 +
1453 +      /* we execute it */
1454 +      if (runit) {
1455 +         this->run_command(c, jcr, name);
1456 +      }
1457 +   }
1458 +   return 1;
1459 +}
1460 +
1461 +/* run a command from the list */
1462 +bool RUNSCRIPT::run_command(const char *command, JCR *jcr, const char *name)
1463 +{
1464     POOLMEM *ecmd = get_pool_memory(PM_FNAME);
1465 -   int status;
1466 +   int status, cmd_type;
1467     BPIPE *bpipe;
1468 -   char line[MAXSTRING];
1469 +   char line[MAXSTRING], *cmd;
1470  
1471 -   ecmd = edit_job_codes(jcr, ecmd, this->command, "", this->job_code_callback);
1472 -   Dmsg1(100, "runscript: running '%s'...\n", ecmd);
1473 +   this->get_command(command, &cmd_type, &cmd);
1474 +   ecmd = edit_job_codes(jcr, ecmd, cmd, "", this->job_code_callback);
1475 +
1476 +   Dmsg2(100, "runscript: running '%s' object type=%c...\n", ecmd, cmd_type);
1477     Jmsg(jcr, M_INFO, 0, _("%s: run %s \"%s\"\n"), 
1478          cmd_type==SHELL_CMD?"shell command":"console command", name, ecmd);
1479  
1480 @@ -278,9 +313,12 @@
1481  
1482  void RUNSCRIPT::debug()
1483  {
1484 +   char *c;
1485     Dmsg0(200, "runscript: debug\n");
1486     Dmsg0(200,  _(" --> RunScript\n"));
1487 -   Dmsg1(200,  _("  --> Command=%s\n"), NPRT(command));
1488 +   foreach_alist(c, commands) {
1489 +      Dmsg1(200,  _("  --> Command=%s\n"), NPRT(c));
1490 +   }
1491     Dmsg1(200,  _("  --> Target=%s\n"),  NPRT(target));
1492     Dmsg1(200,  _("  --> RunOnSuccess=%u\n"),  on_success);
1493     Dmsg1(200,  _("  --> RunOnFailure=%u\n"),  on_failure);