2 Bacula® - The Network Backup Solution
4 Copyright (C) 2006-2011 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU Affero General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Manipulation routines for RunScript list
31 * Eric Bollengier, May 2006
38 #include "runscript.h"
41 * This function pointer is set only by the Director (dird.c),
42 * and is not set in the File daemon, because the File
43 * daemon cannot run console commands.
45 bool (*console_command)(JCR *jcr, const char *cmd) = NULL;
48 RUNSCRIPT *new_runscript()
50 Dmsg0(500, "runscript: creating new RUNSCRIPT object\n");
51 RUNSCRIPT *cmd = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
52 memset(cmd, 0, sizeof(RUNSCRIPT));
58 void RUNSCRIPT::reset_default(bool free_strings)
60 if (free_strings && command) {
61 free_pool_memory(command);
63 if (free_strings && target) {
64 free_pool_memory(target);
73 old_proto = false; /* TODO: drop this with bacula 1.42 */
74 job_code_callback = NULL;
77 RUNSCRIPT *copy_runscript(RUNSCRIPT *src)
79 Dmsg0(500, "runscript: creating new RUNSCRIPT object from other\n");
81 RUNSCRIPT *dst = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
82 memcpy(dst, src, sizeof(RUNSCRIPT));
87 dst->set_command(src->command, src->cmd_type);
88 dst->set_target(src->target);
93 void free_runscript(RUNSCRIPT *script)
95 Dmsg0(500, "runscript: freeing RUNSCRIPT object\n");
97 if (script->command) {
98 free_pool_memory(script->command);
100 if (script->target) {
101 free_pool_memory(script->target);
106 int run_scripts(JCR *jcr, alist *runscripts, const char *label)
108 Dmsg2(200, "runscript: running all RUNSCRIPT object (%s) JobStatus=%c\n", label, jcr->JobStatus);
115 if (strstr(label, NT_("Before"))) {
116 when = SCRIPT_Before;
117 } else if (bstrcmp(label, NT_("ClientAfterVSS"))) {
118 when = SCRIPT_AfterVSS;
123 if (runscripts == NULL) {
124 Dmsg0(100, "runscript: WARNING RUNSCRIPTS list is NULL\n");
128 foreach_alist(script, runscripts) {
129 Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(script->target), NPRT(script->command));
132 if ((script->when & SCRIPT_Before) && (when & SCRIPT_Before)) {
133 if ((script->on_success &&
134 (jcr->JobStatus == JS_Running || jcr->JobStatus == JS_Created))
135 || (script->on_failure &&
136 (job_canceled(jcr) || jcr->JobStatus == JS_Differences))
139 Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n",
140 script->command, script->on_success, script->on_failure,
146 if ((script->when & SCRIPT_AfterVSS) && (when & SCRIPT_AfterVSS)) {
147 if ((script->on_success && (jcr->JobStatus == JS_Blocked))
148 || (script->on_failure && job_canceled(jcr))
151 Dmsg4(200, "runscript: Run it because SCRIPT_AfterVSS (%s,%i,%i,%c)\n",
152 script->command, script->on_success, script->on_failure,
158 if ((script->when & SCRIPT_After) && (when & SCRIPT_After)) {
159 if ((script->on_success &&
160 (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
161 || (script->on_failure &&
162 (job_canceled(jcr) || jcr->JobStatus == JS_Differences))
165 Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n",
166 script->command, script->on_success, script->on_failure,
172 if (!script->is_local()) {
178 script->run(jcr, label);
184 bool RUNSCRIPT::is_local()
186 if (!target || (strcmp(target, "") == 0)) {
193 /* set this->command to cmd */
194 void RUNSCRIPT::set_command(const char *cmd, int acmd_type)
196 Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd));
203 command = get_pool_memory(PM_FNAME);
206 pm_strcpy(command, cmd);
207 cmd_type = acmd_type;
210 /* set this->target to client_name */
211 void RUNSCRIPT::set_target(const char *client_name)
213 Dmsg1(500, "runscript: setting target = %s\n", NPRT(client_name));
220 target = get_pool_memory(PM_FNAME);
223 pm_strcpy(target, client_name);
226 bool RUNSCRIPT::run(JCR *jcr, const char *name)
228 Dmsg1(100, "runscript: running a RUNSCRIPT object type=%d\n", cmd_type);
229 POOLMEM *ecmd = get_pool_memory(PM_FNAME);
232 char line[MAXSTRING];
234 ecmd = edit_job_codes(jcr, ecmd, this->command, "", this->job_code_callback);
235 Dmsg1(100, "runscript: running '%s'...\n", ecmd);
236 Jmsg(jcr, M_INFO, 0, _("%s: run %s \"%s\"\n"),
237 cmd_type==SHELL_CMD?"shell command":"console command", name, ecmd);
241 bpipe = open_bpipe(ecmd, 0, "r");
242 free_pool_memory(ecmd);
245 Jmsg(jcr, M_ERROR, 0, _("Runscript: %s could not execute. ERR=%s\n"), name,
249 while (fgets(line, sizeof(line), bpipe->rfd)) {
250 int len = strlen(line);
251 if (len > 0 && line[len-1] == '\n') {
254 Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line);
256 status = close_bpipe(bpipe);
259 Jmsg(jcr, M_ERROR, 0, _("Runscript: %s returned non-zero status=%d. ERR=%s\n"), name,
260 be.code(status), be.bstrerror(status));
263 Dmsg0(100, "runscript OK\n");
266 if (console_command) { /* can we run console command? */
267 if (!console_command(jcr, ecmd)) { /* yes, do so */
276 /* cancel running job properly */
278 jcr->setJobStatus(JS_ErrorTerminated);
280 Dmsg1(100, "runscript failed. fail_on_error=%d\n", fail_on_error);
284 void free_runscripts(alist *runscripts)
286 Dmsg0(500, "runscript: freeing all RUNSCRIPTS object\n");
289 foreach_alist(elt, runscripts) {
294 void RUNSCRIPT::debug()
296 Dmsg0(200, "runscript: debug\n");
297 Dmsg0(200, _(" --> RunScript\n"));
298 Dmsg1(200, _(" --> Command=%s\n"), NPRT(command));
299 Dmsg1(200, _(" --> Target=%s\n"), NPRT(target));
300 Dmsg1(200, _(" --> RunOnSuccess=%u\n"), on_success);
301 Dmsg1(200, _(" --> RunOnFailure=%u\n"), on_failure);
302 Dmsg1(200, _(" --> FailJobOnError=%u\n"), fail_on_error);
303 Dmsg1(200, _(" --> RunWhen=%u\n"), when);
306 void RUNSCRIPT::set_job_code_callback(job_code_callback_t arg_job_code_callback)
308 this->job_code_callback = arg_job_code_callback;