X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Flib%2Frunscript.c;h=47a55c631bafa35069becc5dba1b2dc4d88f4d37;hb=4d90a54f244499151f1c2451d420c624524a3ba9;hp=7d031aeb70897337a7d52b18adab4827e16d03e6;hpb=5276c9218ee038e74a508dccf3d9ab3f7d9ac056;p=bacula%2Fbacula diff --git a/bacula/src/lib/runscript.c b/bacula/src/lib/runscript.c index 7d031aeb70..47a55c631b 100644 --- a/bacula/src/lib/runscript.c +++ b/bacula/src/lib/runscript.c @@ -6,7 +6,7 @@ The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. This program is Free Software; you can redistribute it and/or - modify it under the terms of version two of the GNU General Public + modify it under the terms of version three of the GNU Affero General Public License as published by the Free Software Foundation and included in the file LICENSE. @@ -15,12 +15,12 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Affero General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - Bacula® is a registered trademark of John Walker. + Bacula® is a registered trademark of Kern Sibbald. The licensor of Bacula is the Free Software Foundation Europe (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. @@ -37,8 +37,15 @@ #include "bacula.h" #include "jcr.h" - #include "runscript.h" + +/* + * This function pointer is set only by the Director (dird.c), + * and is not set in the File daemon, because the File + * daemon cannot run console commands. + */ +bool (*console_command)(JCR *jcr, const char *cmd) = NULL; + RUNSCRIPT *new_runscript() { @@ -66,6 +73,7 @@ void RUNSCRIPT::reset_default(bool free_strings) fail_on_error = true; when = SCRIPT_Never; old_proto = false; /* TODO: drop this with bacula 1.42 */ + job_code_callback = NULL; } RUNSCRIPT *copy_runscript(RUNSCRIPT *src) @@ -78,7 +86,7 @@ RUNSCRIPT *copy_runscript(RUNSCRIPT *src) dst->command = NULL; dst->target = NULL; - dst->set_command(src->command); + dst->set_command(src->command, src->cmd_type); dst->set_target(src->target); return dst; @@ -108,6 +116,8 @@ int run_scripts(JCR *jcr, alist *runscripts, const char *label) if (strstr(label, NT_("Before"))) { when = SCRIPT_Before; + } else if (bstrcmp(label, NT_("ClientAfterVSS"))) { + when = SCRIPT_AfterVSS; } else { when = SCRIPT_After; } @@ -122,9 +132,10 @@ int run_scripts(JCR *jcr, alist *runscripts, const char *label) 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)) + if ((script->on_success && + (jcr->JobStatus == JS_Running || jcr->JobStatus == JS_Created)) + || (script->on_failure && + (job_canceled(jcr) || jcr->JobStatus == JS_Differences)) ) { Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n", @@ -134,9 +145,23 @@ int run_scripts(JCR *jcr, alist *runscripts, const char *label) } } + if ((script->when & SCRIPT_AfterVSS) && (when & SCRIPT_AfterVSS)) { + if ((script->on_success && (jcr->JobStatus == JS_Blocked)) + || (script->on_failure && job_canceled(jcr)) + ) + { + Dmsg4(200, "runscript: Run it because SCRIPT_AfterVSS (%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)) + if ((script->on_success && + (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)) + || (script->on_failure && + (job_canceled(jcr) || jcr->JobStatus == JS_Differences)) ) { Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n", @@ -168,7 +193,7 @@ bool RUNSCRIPT::is_local() } /* set this->command to cmd */ -void RUNSCRIPT::set_command(const POOLMEM *cmd) +void RUNSCRIPT::set_command(const char *cmd, int acmd_type) { Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd)); @@ -181,10 +206,11 @@ void RUNSCRIPT::set_command(const POOLMEM *cmd) } pm_strcpy(command, cmd); + cmd_type = acmd_type; } /* set this->target to client_name */ -void RUNSCRIPT::set_target(const POOLMEM *client_name) +void RUNSCRIPT::set_target(const char *client_name) { Dmsg1(500, "runscript: setting target = %s\n", NPRT(client_name)); @@ -201,46 +227,60 @@ void RUNSCRIPT::set_target(const POOLMEM *client_name) bool RUNSCRIPT::run(JCR *jcr, const char *name) { - Dmsg0(200, "runscript: running a RUNSCRIPT object\n"); + Dmsg1(100, "runscript: running a RUNSCRIPT object type=%d\n", cmd_type); POOLMEM *ecmd = get_pool_memory(PM_FNAME); int status; BPIPE *bpipe; char line[MAXSTRING]; - ecmd = edit_job_codes(jcr, ecmd, this->command, ""); + ecmd = edit_job_codes(jcr, ecmd, this->command, "", this->job_code_callback); Dmsg1(100, "runscript: running '%s'...\n", ecmd); - Jmsg(jcr, M_INFO, 0, _("%s: run command \"%s\"\n"), name, ecmd); - - bpipe = open_bpipe(ecmd, 0, "r"); - free_pool_memory(ecmd); - if (bpipe == NULL) { - berrno be; - Jmsg(jcr, M_ERROR, 0, _("Runscript: %s could not execute. ERR=%s\n"), name, - be.bstrerror()); - goto bail_out; - } - while (fgets(line, sizeof(line), bpipe->rfd)) { - int len = strlen(line); - if (len > 0 && line[len-1] == '\n') { - line[len-1] = 0; + Jmsg(jcr, M_INFO, 0, _("%s: run %s \"%s\"\n"), + cmd_type==SHELL_CMD?"shell command":"console command", name, ecmd); + + switch (cmd_type) { + case SHELL_CMD: + bpipe = open_bpipe(ecmd, 0, "r"); + free_pool_memory(ecmd); + if (bpipe == NULL) { + berrno be; + Jmsg(jcr, M_ERROR, 0, _("Runscript: %s could not execute. ERR=%s\n"), name, + be.bstrerror()); + goto bail_out; } - Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line); - } - status = close_bpipe(bpipe); - if (status != 0) { - berrno be; - Jmsg(jcr, M_ERROR, 0, _("Runscript: %s returned non-zero status=%d. ERR=%s\n"), name, - be.code(status), be.bstrerror(status)); - goto bail_out; + while (fgets(line, sizeof(line), bpipe->rfd)) { + int len = strlen(line); + if (len > 0 && line[len-1] == '\n') { + line[len-1] = 0; + } + Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line); + } + status = close_bpipe(bpipe); + if (status != 0) { + berrno be; + Jmsg(jcr, M_ERROR, 0, _("Runscript: %s returned non-zero status=%d. ERR=%s\n"), name, + be.code(status), be.bstrerror(status)); + goto bail_out; + } + Dmsg0(100, "runscript OK\n"); + break; + case CONSOLE_CMD: + if (console_command) { /* can we run console command? */ + if (!console_command(jcr, ecmd)) { /* yes, do so */ + goto bail_out; + } + } + break; } return true; bail_out: - /* cancel running job properly */ - if (fail_on_error) { - set_jcr_job_status(jcr, JS_ErrorTerminated); - } - return false; + /* cancel running job properly */ + if (fail_on_error) { + set_jcr_job_status(jcr, JS_ErrorTerminated); + } + Dmsg1(100, "runscript failed. fail_on_error=%d\n", fail_on_error); + return false; } void free_runscripts(alist *runscripts) @@ -264,3 +304,8 @@ void RUNSCRIPT::debug() Dmsg1(200, _(" --> FailJobOnError=%u\n"), fail_on_error); Dmsg1(200, _(" --> RunWhen=%u\n"), when); } + +void RUNSCRIPT::set_job_code_callback(job_code_callback_t arg_job_code_callback) +{ + this->job_code_callback = arg_job_code_callback; +}