2 Bacula® - The Network Backup Solution
4 Copyright (C) 2006-2007 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 two of the GNU 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 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
40 #include "runscript.h"
43 * This function pointer is set only by the Director (dird.c),
44 * and is not set in the File daemon, because the File
45 * daemon cannot run console commands.
47 bool (*console_command)(JCR *jcr, const char *cmd) = NULL;
50 RUNSCRIPT *new_runscript()
52 Dmsg0(500, "runscript: creating new RUNSCRIPT object\n");
53 RUNSCRIPT *cmd = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
54 memset(cmd, 0, sizeof(RUNSCRIPT));
60 void RUNSCRIPT::reset_default(bool free_strings)
62 if (free_strings && command) {
63 free_pool_memory(command);
65 if (free_strings && target) {
66 free_pool_memory(target);
75 old_proto = false; /* TODO: drop this with bacula 1.42 */
76 job_code_callback = NULL;
79 RUNSCRIPT *copy_runscript(RUNSCRIPT *src)
81 Dmsg0(500, "runscript: creating new RUNSCRIPT object from other\n");
83 RUNSCRIPT *dst = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
84 memcpy(dst, src, sizeof(RUNSCRIPT));
89 dst->set_command(src->command, src->cmd_type);
90 dst->set_target(src->target);
95 void free_runscript(RUNSCRIPT *script)
97 Dmsg0(500, "runscript: freeing RUNSCRIPT object\n");
99 if (script->command) {
100 free_pool_memory(script->command);
102 if (script->target) {
103 free_pool_memory(script->target);
108 int run_scripts(JCR *jcr, alist *runscripts, const char *label)
110 Dmsg2(200, "runscript: running all RUNSCRIPT object (%s) JobStatus=%c\n", label, jcr->JobStatus);
117 if (strstr(label, NT_("Before"))) {
118 when = SCRIPT_Before;
119 } else if (bstrcmp(label, NT_("ClientAfterVSS"))) {
120 when = SCRIPT_AfterVSS;
125 if (runscripts == NULL) {
126 Dmsg0(100, "runscript: WARNING RUNSCRIPTS list is NULL\n");
130 foreach_alist(script, runscripts) {
131 Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(script->target), NPRT(script->command));
134 if ((script->when & SCRIPT_Before) && (when & SCRIPT_Before)) {
135 if ((script->on_success &&
136 (jcr->JobStatus == JS_Running || jcr->JobStatus == JS_Created))
137 || (script->on_failure &&
138 (job_canceled(jcr) || jcr->JobStatus == JS_Differences))
141 Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n",
142 script->command, script->on_success, script->on_failure,
148 if ((script->when & SCRIPT_AfterVSS) && (when & SCRIPT_AfterVSS)) {
149 if ((script->on_success && (jcr->JobStatus == JS_Blocked))
150 || (script->on_failure && job_canceled(jcr))
153 Dmsg4(200, "runscript: Run it because SCRIPT_AfterVSS (%s,%i,%i,%c)\n",
154 script->command, script->on_success, script->on_failure,
160 if ((script->when & SCRIPT_After) && (when & SCRIPT_After)) {
161 if ((script->on_success &&
162 (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
163 || (script->on_failure &&
164 (job_canceled(jcr) || jcr->JobStatus == JS_Differences))
167 Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n",
168 script->command, script->on_success, script->on_failure,
174 if (!script->is_local()) {
180 script->run(jcr, label);
186 bool RUNSCRIPT::is_local()
188 if (!target || (strcmp(target, "") == 0)) {
195 /* set this->command to cmd */
196 void RUNSCRIPT::set_command(const char *cmd, int acmd_type)
198 Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd));
205 command = get_pool_memory(PM_FNAME);
208 pm_strcpy(command, cmd);
209 cmd_type = acmd_type;
212 /* set this->target to client_name */
213 void RUNSCRIPT::set_target(const char *client_name)
215 Dmsg1(500, "runscript: setting target = %s\n", NPRT(client_name));
222 target = get_pool_memory(PM_FNAME);
225 pm_strcpy(target, client_name);
228 bool RUNSCRIPT::run(JCR *jcr, const char *name)
230 Dmsg1(100, "runscript: running a RUNSCRIPT object type=%d\n", cmd_type);
231 POOLMEM *ecmd = get_pool_memory(PM_FNAME);
234 char line[MAXSTRING];
236 ecmd = edit_job_codes(jcr, ecmd, this->command, "", this->job_code_callback);
237 Dmsg1(100, "runscript: running '%s'...\n", ecmd);
238 Jmsg(jcr, M_INFO, 0, _("%s: run %s \"%s\"\n"),
239 cmd_type==SHELL_CMD?"shell command":"console command", name, ecmd);
243 bpipe = open_bpipe(ecmd, 0, "r");
244 free_pool_memory(ecmd);
247 Jmsg(jcr, M_ERROR, 0, _("Runscript: %s could not execute. ERR=%s\n"), name,
251 while (fgets(line, sizeof(line), bpipe->rfd)) {
252 int len = strlen(line);
253 if (len > 0 && line[len-1] == '\n') {
256 Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line);
258 status = close_bpipe(bpipe);
261 Jmsg(jcr, M_ERROR, 0, _("Runscript: %s returned non-zero status=%d. ERR=%s\n"), name,
262 be.code(status), be.bstrerror(status));
265 Dmsg0(100, "runscript OK\n");
268 if (console_command) { /* can we run console command? */
269 if (!console_command(jcr, ecmd)) { /* yes, do so */
278 /* cancel running job properly */
280 set_jcr_job_status(jcr, JS_ErrorTerminated);
282 Dmsg1(100, "runscript failed. fail_on_error=%d\n", fail_on_error);
286 void free_runscripts(alist *runscripts)
288 Dmsg0(500, "runscript: freeing all RUNSCRIPTS object\n");
291 foreach_alist(elt, runscripts) {
296 void RUNSCRIPT::debug()
298 Dmsg0(200, "runscript: debug\n");
299 Dmsg0(200, _(" --> RunScript\n"));
300 Dmsg1(200, _(" --> Command=%s\n"), NPRT(command));
301 Dmsg1(200, _(" --> Target=%s\n"), NPRT(target));
302 Dmsg1(200, _(" --> RunOnSuccess=%u\n"), on_success);
303 Dmsg1(200, _(" --> RunOnFailure=%u\n"), on_failure);
304 Dmsg1(200, _(" --> FailJobOnError=%u\n"), fail_on_error);
305 Dmsg1(200, _(" --> RunWhen=%u\n"), when);
308 void RUNSCRIPT::set_job_code_callback(job_code_callback_t arg_job_code_callback)
310 this->job_code_callback = arg_job_code_callback;