X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Flib%2Frunscript.c;h=47a55c631bafa35069becc5dba1b2dc4d88f4d37;hb=4132c9f33642f579d89700f36caced609d374d51;hp=300b8a7b68f1d6394a92c7aede8bfee8fc358a1b;hpb=46e1296ea745c94d0116f851e2cb847d9e1b849a;p=bacula%2Fbacula diff --git a/bacula/src/lib/runscript.c b/bacula/src/lib/runscript.c index 300b8a7b68..47a55c631b 100644 --- a/bacula/src/lib/runscript.c +++ b/bacula/src/lib/runscript.c @@ -6,21 +6,21 @@ 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 - License as published by the Free Software Foundation plus additions - that are listed in the file LICENSE. + 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 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() { @@ -63,9 +70,10 @@ void RUNSCRIPT::reset_default(bool free_strings) command = NULL; on_success = true; on_failure = false; - abort_on_error = true; + 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; @@ -103,12 +111,13 @@ int run_scripts(JCR *jcr, alist *runscripts, const char *label) RUNSCRIPT *script; bool runit; - bool status; int when; if (strstr(label, NT_("Before"))) { when = SCRIPT_Before; + } else if (bstrcmp(label, NT_("ClientAfterVSS"))) { + when = SCRIPT_AfterVSS; } else { when = SCRIPT_After; } @@ -120,53 +129,55 @@ int run_scripts(JCR *jcr, alist *runscripts, const char *label) foreach_alist(script, runscripts) { Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(script->target), NPRT(script->command)); - runit=false; + 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", script->command, - script->on_success, - script->on_failure, - jcr->JobStatus ); + 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_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", script->command, - script->on_success, - script->on_failure, - jcr->JobStatus ); + 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; + runit = false; } /* we execute it */ if (runit) { - status = script->run(jcr, label); - - /* cancel running job properly */ - if ( script->abort_on_error - && (status == false) - && (jcr->JobStatus == JS_Created || jcr->JobStatus == JS_Running) - ) - { - set_jcr_job_status(jcr, JS_ErrorTerminated); - } + script->run(jcr, label); } } return 1; @@ -182,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)); @@ -195,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)); @@ -213,41 +225,62 @@ void RUNSCRIPT::set_target(const POOLMEM *client_name) pm_strcpy(target, client_name); } -int RUNSCRIPT::run(JCR *jcr, const char *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()); - return false; - } - 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)); - return false; + 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); + } + Dmsg1(100, "runscript failed. fail_on_error=%d\n", fail_on_error); + return false; } void free_runscripts(alist *runscripts) @@ -268,6 +301,11 @@ void RUNSCRIPT::debug() Dmsg1(200, _(" --> Target=%s\n"), NPRT(target)); Dmsg1(200, _(" --> RunOnSuccess=%u\n"), on_success); Dmsg1(200, _(" --> RunOnFailure=%u\n"), on_failure); - Dmsg1(200, _(" --> AbortJobOnError=%u\n"), abort_on_error); + 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; +}