]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/runscript.c
kes Fix tray-monitor by not requiring a timer interval in bnet_connect()
[bacula/bacula] / bacula / src / lib / runscript.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2006-2007 Free Software Foundation Europe e.V.
5
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 plus additions
11    that are listed in the file LICENSE.
12
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.
17
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
21    02110-1301, USA.
22
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.
27 */
28 /*
29  * Manipulation routines for RunScript list
30  *
31  *  Eric Bollengier, May 2006
32  *
33  *  Version $Id$
34  *
35  */
36
37
38 #include "bacula.h"
39 #include "jcr.h"
40
41 #include "runscript.h"
42
43 RUNSCRIPT *new_runscript()
44 {
45    Dmsg0(500, "runscript: creating new RUNSCRIPT object\n");
46    RUNSCRIPT *cmd = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
47    memset(cmd, 0, sizeof(RUNSCRIPT));
48    cmd->reset_default();
49    
50    return cmd;
51 }
52
53 void RUNSCRIPT::reset_default(bool free_strings)
54 {
55    if (free_strings && command) {
56      free_pool_memory(command);
57    }
58    if (free_strings && target) {
59      free_pool_memory(target);
60    }
61    
62    target = NULL;
63    command = NULL;
64    on_success = true;
65    on_failure = false;
66    abort_on_error = true;
67    when = SCRIPT_Never;
68    old_proto = false;        /* TODO: drop this with bacula 1.42 */
69 }
70
71 RUNSCRIPT *copy_runscript(RUNSCRIPT *src)
72 {
73    Dmsg0(500, "runscript: creating new RUNSCRIPT object from other\n");
74
75    RUNSCRIPT *dst = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
76    memcpy(dst, src, sizeof(RUNSCRIPT));
77
78    dst->command = NULL;
79    dst->target = NULL;
80
81    dst->set_command(src->command);
82    dst->set_target(src->target);
83
84    return dst;   
85 }
86
87 void free_runscript(RUNSCRIPT *script)
88 {
89    Dmsg0(500, "runscript: freeing RUNSCRIPT object\n");
90
91    if (script->command) {
92       free_pool_memory(script->command);
93    }
94    if (script->target) {
95       free_pool_memory(script->target);
96    }
97    free(script);
98 }
99
100 int run_scripts(JCR *jcr, alist *runscripts, const char *label)
101 {
102    Dmsg2(200, "runscript: running all RUNSCRIPT object (%s) JobStatus=%c\n", label, jcr->JobStatus);
103    
104    RUNSCRIPT *script;
105    bool runit;
106    bool status;
107
108    int when;
109
110    if (strstr(label, NT_("Before"))) {
111       when = SCRIPT_Before;
112    } else {
113       when = SCRIPT_After;
114    }
115
116    if (runscripts == NULL) {
117       Dmsg0(100, "runscript: WARNING RUNSCRIPTS list is NULL\n");
118       return 0;
119    }
120
121    foreach_alist(script, runscripts) {
122       Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(script->target), NPRT(script->command));
123       runit=false;
124
125       if ((script->when & SCRIPT_Before) && (when & SCRIPT_Before)) {
126          if (  (script->on_success && (jcr->JobStatus == JS_Running || jcr->JobStatus == JS_Created))
127                ||
128                (script->on_failure && job_canceled(jcr))
129             )
130          {
131             Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n", script->command,
132                                                                                   script->on_success,
133                                                                                   script->on_failure,
134                                                                                   jcr->JobStatus );
135
136             runit = true;
137          }
138       }
139
140       if ((script->when & SCRIPT_After) && (when & SCRIPT_After)) {
141          if (  (script->on_success && (jcr->JobStatus == JS_Terminated))
142                ||
143                (script->on_failure && job_canceled(jcr))
144             )
145          {
146             Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n", script->command,
147                                                                                  script->on_success,
148                                                                                  script->on_failure,
149                                                                                  jcr->JobStatus );
150             runit = true;
151          }
152       }
153
154       if (!script->is_local()) {
155          runit=false;
156       }
157
158       /* we execute it */
159       if (runit) {
160         status = script->run(jcr, label);
161
162         /* cancel running job properly */
163         if (   script->abort_on_error 
164             && (status == false) 
165             && (jcr->JobStatus == JS_Created || jcr->JobStatus == JS_Running)
166            )
167         {
168            set_jcr_job_status(jcr, JS_ErrorTerminated);
169         }
170       }
171    }
172    return 1;
173 }
174
175 bool RUNSCRIPT::is_local()
176 {
177    if (!target || (strcmp(target, "") == 0)) {
178       return true;
179    } else {
180       return false;
181    }
182 }
183
184 /* set this->command to cmd */
185 void RUNSCRIPT::set_command(const POOLMEM *cmd)
186 {
187    Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd));
188
189    if (!cmd) {
190       return;
191    }
192
193    if (!command) {
194       command = get_pool_memory(PM_FNAME);
195    }
196
197    pm_strcpy(command, cmd);
198 }
199
200 /* set this->target to client_name */
201 void RUNSCRIPT::set_target(const POOLMEM *client_name)
202 {
203    Dmsg1(500, "runscript: setting target = %s\n", NPRT(client_name));
204
205    if (!client_name) {
206       return;
207    }
208
209    if (!target) {
210       target = get_pool_memory(PM_FNAME);
211    }
212
213    pm_strcpy(target, client_name);
214 }
215
216 int RUNSCRIPT::run(JCR *jcr, const char *name)
217 {
218    Dmsg0(200, "runscript: running a RUNSCRIPT object\n");
219    POOLMEM *ecmd = get_pool_memory(PM_FNAME);
220    int status;
221    BPIPE *bpipe;
222    char line[MAXSTRING];
223
224    ecmd = edit_job_codes(jcr, ecmd, this->command, "");
225    Dmsg1(100, "runscript: running '%s'...\n", ecmd);
226    Jmsg(jcr, M_INFO, 0, _("%s: run command \"%s\"\n"), name, ecmd);
227
228    bpipe = open_bpipe(ecmd, 0, "r");
229    free_pool_memory(ecmd);
230    if (bpipe == NULL) {
231       berrno be;
232       Jmsg(jcr, M_ERROR, 0, _("Runscript: %s could not execute. ERR=%s\n"), name,
233          be.bstrerror());
234       return false;
235    }
236    while (fgets(line, sizeof(line), bpipe->rfd)) {
237       int len = strlen(line);
238       if (len > 0 && line[len-1] == '\n') {
239          line[len-1] = 0;
240       }
241       Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line);
242    }
243    status = close_bpipe(bpipe);
244    if (status != 0) {
245       berrno be;
246       Jmsg(jcr, M_ERROR, 0, _("Runscript: %s returned non-zero status=%d. ERR=%s\n"), name,
247          be.code(status), be.bstrerror(status));
248       return false;
249    }
250    return true;
251 }
252
253 void free_runscripts(alist *runscripts)
254 {
255    Dmsg0(500, "runscript: freeing all RUNSCRIPTS object\n");
256
257    RUNSCRIPT *elt;
258    foreach_alist(elt, runscripts) {
259       free_runscript(elt);
260    }
261 }
262
263 void RUNSCRIPT::debug()
264 {
265    Dmsg0(200, "runscript: debug\n");
266    Dmsg0(200,  _(" --> RunScript\n"));
267    Dmsg1(200,  _("  --> Command=%s\n"), NPRT(command));
268    Dmsg1(200,  _("  --> Target=%s\n"),  NPRT(target));
269    Dmsg1(200,  _("  --> RunOnSuccess=%u\n"),  on_success);
270    Dmsg1(200,  _("  --> RunOnFailure=%u\n"),  on_failure);
271    Dmsg1(200,  _("  --> AbortJobOnError=%u\n"),  abort_on_error);
272    Dmsg1(200,  _("  --> RunWhen=%u\n"),  when);
273 }