X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Flib%2Frunscript.c;h=39e10a0117037fc49517bc9498c45d081ed15c53;hb=4715eed45b57fd37557fc0ccd65207c835d47080;hp=4b851ed5767e7252e8a73c308f3c9eea6225ab26;hpb=db47ec2b6c1177591b6ee81329ccd97aab96ce44;p=bacula%2Fbacula diff --git a/bacula/src/lib/runscript.c b/bacula/src/lib/runscript.c index 4b851ed576..39e10a0117 100644 --- a/bacula/src/lib/runscript.c +++ b/bacula/src/lib/runscript.c @@ -1,3 +1,30 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2006-2007 Free Software Foundation Europe e.V. + + 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 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 + 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. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ /* * Manipulation routines for RunScript list * @@ -6,26 +33,19 @@ * Version $Id$ * */ -/* - Copyright (C) 2000-2006 Kern Sibbald - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - version 2 as amended with additional clauses defined in the - file LICENSE in the main source directory. - - 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 - the file LICENSE for additional details. - - */ #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() { @@ -50,8 +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) @@ -64,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; @@ -89,7 +111,16 @@ 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; + } if (runscripts == NULL) { Dmsg0(100, "runscript: WARNING RUNSCRIPTS list is NULL\n"); @@ -98,48 +129,52 @@ 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; - - if ((script->when & SCRIPT_Before) && (jcr->JobStatus == JS_Created)) { - Dmsg0(200, "runscript: Run it because SCRIPT_Before\n"); - runit = true; + 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_Before) && (jcr->JobStatus == JS_Running)) { - Dmsg0(200, "runscript: Run it because SCRIPT_Before\n"); - 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) { - 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->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; + 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) - ) - { - set_jcr_job_status(jcr, JS_ErrorTerminated); - } + script->run(jcr, label); } } return 1; @@ -155,7 +190,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)); @@ -168,12 +203,13 @@ 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\n", NPRT(client_name)); + Dmsg1(500, "runscript: setting target = %s\n", NPRT(client_name)); if (!client_name) { return; @@ -186,41 +222,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_FATAL, 0, _("%s could not execute. ERR=%s\n"), name, - be.strerror()); - 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_FATAL, 0, _("%s returned non-zero status=%d. ERR=%s\n"), name, - status, be.strerror(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) @@ -241,6 +298,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; +}