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 John Walker.
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;
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 && job_canceled(jcr))
138 Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n",
139 script->command, script->on_success, script->on_failure,
145 if ((script->when & SCRIPT_After) && (when & SCRIPT_After)) {
146 if ((script->on_success && (jcr->JobStatus == JS_Terminated))
147 || (script->on_failure && job_canceled(jcr))
150 Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n",
151 script->command, script->on_success, script->on_failure,
157 if (!script->is_local()) {
163 script->run(jcr, label);
169 bool RUNSCRIPT::is_local()
171 if (!target || (strcmp(target, "") == 0)) {
178 /* set this->command to cmd */
179 void RUNSCRIPT::set_command(const POOLMEM *cmd, int acmd_type)
181 Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd));
188 command = get_pool_memory(PM_FNAME);
191 pm_strcpy(command, cmd);
192 cmd_type = acmd_type;
195 /* set this->target to client_name */
196 void RUNSCRIPT::set_target(const POOLMEM *client_name)
198 Dmsg1(500, "runscript: setting target = %s\n", NPRT(client_name));
205 target = get_pool_memory(PM_FNAME);
208 pm_strcpy(target, client_name);
211 bool RUNSCRIPT::run(JCR *jcr, const char *name)
213 Dmsg1(100, "runscript: running a RUNSCRIPT object type=%d\n", cmd_type);
214 POOLMEM *ecmd = get_pool_memory(PM_FNAME);
217 char line[MAXSTRING];
219 ecmd = edit_job_codes(jcr, ecmd, this->command, "", this->job_code_callback);
220 Dmsg1(100, "runscript: running '%s'...\n", ecmd);
221 Jmsg(jcr, M_INFO, 0, _("%s: run %s \"%s\"\n"),
222 cmd_type==SHELL_CMD?"shell command":"console command", name, ecmd);
226 bpipe = open_bpipe(ecmd, 0, "r");
227 free_pool_memory(ecmd);
230 Jmsg(jcr, M_ERROR, 0, _("Runscript: %s could not execute. ERR=%s\n"), name,
234 while (fgets(line, sizeof(line), bpipe->rfd)) {
235 int len = strlen(line);
236 if (len > 0 && line[len-1] == '\n') {
239 Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line);
241 status = close_bpipe(bpipe);
244 Jmsg(jcr, M_ERROR, 0, _("Runscript: %s returned non-zero status=%d. ERR=%s\n"), name,
245 be.code(status), be.bstrerror(status));
248 Dmsg0(100, "runscript OK\n");
251 if (console_command) { /* can we run console command? */
252 if (!console_command(jcr, ecmd)) { /* yes, do so */
261 /* cancel running job properly */
263 set_jcr_job_status(jcr, JS_ErrorTerminated);
265 Dmsg1(100, "runscript failed. fail_on_error=%d\n", fail_on_error);
269 void free_runscripts(alist *runscripts)
271 Dmsg0(500, "runscript: freeing all RUNSCRIPTS object\n");
274 foreach_alist(elt, runscripts) {
279 void RUNSCRIPT::debug()
281 Dmsg0(200, "runscript: debug\n");
282 Dmsg0(200, _(" --> RunScript\n"));
283 Dmsg1(200, _(" --> Command=%s\n"), NPRT(command));
284 Dmsg1(200, _(" --> Target=%s\n"), NPRT(target));
285 Dmsg1(200, _(" --> RunOnSuccess=%u\n"), on_success);
286 Dmsg1(200, _(" --> RunOnFailure=%u\n"), on_failure);
287 Dmsg1(200, _(" --> FailJobOnError=%u\n"), fail_on_error);
288 Dmsg1(200, _(" --> RunWhen=%u\n"), when);
291 void RUNSCRIPT::set_job_code_callback(job_code_callback_t arg_job_code_callback)
293 this->job_code_callback = arg_job_code_callback;