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 && job_canceled(jcr))
140 Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n",
141 script->command, script->on_success, script->on_failure,
147 if ((script->when & SCRIPT_AfterVSS) && (when & SCRIPT_AfterVSS)) {
148 if ((script->on_success && (jcr->JobStatus == JS_Blocked))
149 || (script->on_failure && job_canceled(jcr))
152 Dmsg4(200, "runscript: Run it because SCRIPT_AfterVSS (%s,%i,%i,%c)\n",
153 script->command, script->on_success, script->on_failure,
159 if ((script->when & SCRIPT_After) && (when & SCRIPT_After)) {
160 if ((script->on_success && (jcr->JobStatus == JS_Terminated))
161 || (script->on_failure && job_canceled(jcr))
164 Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n",
165 script->command, script->on_success, script->on_failure,
171 if (!script->is_local()) {
177 script->run(jcr, label);
183 bool RUNSCRIPT::is_local()
185 if (!target || (strcmp(target, "") == 0)) {
192 /* set this->command to cmd */
193 void RUNSCRIPT::set_command(const char *cmd, int acmd_type)
195 Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd));
202 command = get_pool_memory(PM_FNAME);
205 pm_strcpy(command, cmd);
206 cmd_type = acmd_type;
209 /* set this->target to client_name */
210 void RUNSCRIPT::set_target(const char *client_name)
212 Dmsg1(500, "runscript: setting target = %s\n", NPRT(client_name));
219 target = get_pool_memory(PM_FNAME);
222 pm_strcpy(target, client_name);
225 bool RUNSCRIPT::run(JCR *jcr, const char *name)
227 Dmsg1(100, "runscript: running a RUNSCRIPT object type=%d\n", cmd_type);
228 POOLMEM *ecmd = get_pool_memory(PM_FNAME);
231 char line[MAXSTRING];
233 ecmd = edit_job_codes(jcr, ecmd, this->command, "", this->job_code_callback);
234 Dmsg1(100, "runscript: running '%s'...\n", ecmd);
235 Jmsg(jcr, M_INFO, 0, _("%s: run %s \"%s\"\n"),
236 cmd_type==SHELL_CMD?"shell command":"console command", name, ecmd);
240 bpipe = open_bpipe(ecmd, 0, "r");
241 free_pool_memory(ecmd);
244 Jmsg(jcr, M_ERROR, 0, _("Runscript: %s could not execute. ERR=%s\n"), name,
248 while (fgets(line, sizeof(line), bpipe->rfd)) {
249 int len = strlen(line);
250 if (len > 0 && line[len-1] == '\n') {
253 Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line);
255 status = close_bpipe(bpipe);
258 Jmsg(jcr, M_ERROR, 0, _("Runscript: %s returned non-zero status=%d. ERR=%s\n"), name,
259 be.code(status), be.bstrerror(status));
262 Dmsg0(100, "runscript OK\n");
265 if (console_command) { /* can we run console command? */
266 if (!console_command(jcr, ecmd)) { /* yes, do so */
275 /* cancel running job properly */
277 set_jcr_job_status(jcr, JS_ErrorTerminated);
279 Dmsg1(100, "runscript failed. fail_on_error=%d\n", fail_on_error);
283 void free_runscripts(alist *runscripts)
285 Dmsg0(500, "runscript: freeing all RUNSCRIPTS object\n");
288 foreach_alist(elt, runscripts) {
293 void RUNSCRIPT::debug()
295 Dmsg0(200, "runscript: debug\n");
296 Dmsg0(200, _(" --> RunScript\n"));
297 Dmsg1(200, _(" --> Command=%s\n"), NPRT(command));
298 Dmsg1(200, _(" --> Target=%s\n"), NPRT(target));
299 Dmsg1(200, _(" --> RunOnSuccess=%u\n"), on_success);
300 Dmsg1(200, _(" --> RunOnFailure=%u\n"), on_failure);
301 Dmsg1(200, _(" --> FailJobOnError=%u\n"), fail_on_error);
302 Dmsg1(200, _(" --> RunWhen=%u\n"), when);
305 void RUNSCRIPT::set_job_code_callback(job_code_callback_t arg_job_code_callback)
307 this->job_code_callback = arg_job_code_callback;