]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/runscript.c
ebl fix RunBefore must AbortJobOnError
[bacula/bacula] / bacula / src / lib / runscript.c
1 /*
2  * Manipulation routines for RunScript list
3  *
4  *  Eric Bollengier, May 2006
5  *
6  *  Version $Id$
7  *
8  */
9 /*
10    Copyright (C) 2000-2006 Kern Sibbald
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License
14    version 2 as amended with additional clauses defined in the
15    file LICENSE in the main source directory.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
20    the file LICENSE for additional details.
21
22  */
23
24
25 #include "bacula.h"
26 #include "jcr.h"
27
28 #include "runscript.h"
29
30 RUNSCRIPT *new_runscript()
31 {
32    Dmsg0(500, "runscript: creating new RUNSCRIPT object\n");
33    RUNSCRIPT *cmd = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
34    memset(cmd, 0, sizeof(RUNSCRIPT));
35    cmd->reset_default();
36    
37    return cmd;
38 }
39
40 void RUNSCRIPT::reset_default(bool free_strings)
41 {
42    if (free_strings && command) {
43      free_pool_memory(command);
44    }
45    if (free_strings && target) {
46      free_pool_memory(target);
47    }
48    
49    target = NULL;
50    command = NULL;
51    on_success = true;
52    on_failure = false;
53    abort_on_error = true;
54    when = SCRIPT_Never;
55    old_proto = false;        /* TODO: drop this with bacula 1.42 */
56 }
57
58 RUNSCRIPT *copy_runscript(RUNSCRIPT *src)
59 {
60    Dmsg0(500, "runscript: creating new RUNSCRIPT object from other\n");
61
62    RUNSCRIPT *dst = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
63    memcpy(dst, src, sizeof(RUNSCRIPT));
64
65    dst->command = NULL;
66    dst->target = NULL;
67
68    dst->set_command(src->command);
69    dst->set_target(src->target);
70
71    return dst;   
72 }
73
74 void free_runscript(RUNSCRIPT *script)
75 {
76    Dmsg0(500, "runscript: freeing RUNSCRIPT object\n");
77
78    if (script->command) {
79       free_pool_memory(script->command);
80    }
81    if (script->target) {
82       free_pool_memory(script->target);
83    }
84    free(script);
85 }
86
87 int run_scripts(JCR *jcr, alist *runscripts, const char *label)
88 {
89    Dmsg2(200, "runscript: running all RUNSCRIPT object (%s) JobStatus=%c\n", label, jcr->JobStatus);
90    
91    RUNSCRIPT *script;
92    bool runit;
93    bool status;
94
95    if (runscripts == NULL) {
96       Dmsg0(100, "runscript: WARNING RUNSCRIPTS list is NULL\n");
97       return 0;
98    }
99
100    foreach_alist(script, runscripts) {
101       Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(script->target), NPRT(script->command));
102       runit=false;
103
104       if ((script->when & SCRIPT_Before) && (jcr->JobStatus == JS_Created)) {
105         Dmsg0(200, "runscript: Run it because SCRIPT_Before\n");
106         runit = true;
107       }
108
109       if ((script->when & SCRIPT_Before) && (jcr->JobStatus == JS_Running)) {
110         Dmsg0(200, "runscript: Run it because SCRIPT_Before\n");
111         runit = true;
112       }
113
114       if (script->when & SCRIPT_After) {
115         if (  (script->on_success && (jcr->JobStatus == JS_Terminated))
116             ||
117               (script->on_failure && job_canceled(jcr))
118            )
119         {
120            Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n", script->command,
121                                                                                 script->on_success,
122                                                                                 script->on_failure,
123                                                                                 jcr->JobStatus );
124            runit = true;
125         }
126       }
127
128       if (!script->is_local()) {
129          runit=false;
130       }
131
132       /* we execute it */
133       if (runit) {
134         status = script->run(jcr, label);
135
136         /* cancel running job properly */
137         if (   script->abort_on_error 
138             && (status == false) 
139             && (jcr->JobStatus == JS_Created || jcr->JobStatus == JS_Running)
140            )
141         {
142            set_jcr_job_status(jcr, JS_ErrorTerminated);
143         }
144       }
145    }
146    return 1;
147 }
148
149 bool RUNSCRIPT::is_local()
150 {
151    if (!target || (strcmp(target, "") == 0)) {
152       return true;
153    } else {
154       return false;
155    }
156 }
157
158 /* set this->command to cmd */
159 void RUNSCRIPT::set_command(const POOLMEM *cmd)
160 {
161    Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd));
162
163    if (!cmd) {
164       return;
165    }
166
167    if (!command) {
168       command = get_pool_memory(PM_FNAME);
169    }
170
171    pm_strcpy(command, cmd);
172 }
173
174 /* set this->target to client_name */
175 void RUNSCRIPT::set_target(const POOLMEM *client_name)
176 {
177    Dmsg1(500, "runscript: setting target\n", NPRT(client_name));
178
179    if (!client_name) {
180       return;
181    }
182
183    if (!target) {
184       target = get_pool_memory(PM_FNAME);
185    }
186
187    pm_strcpy(target, client_name);
188 }
189
190 int RUNSCRIPT::run(JCR *jcr, const char *name)
191 {
192    Dmsg0(200, "runscript: running a RUNSCRIPT object\n");
193    POOLMEM *ecmd = get_pool_memory(PM_FNAME);
194    int status;
195    BPIPE *bpipe;
196    char line[MAXSTRING];
197
198    ecmd = edit_job_codes(jcr, ecmd, this->command, "");
199    Dmsg1(100, "runscript: running '%s'...\n", ecmd);
200    Jmsg(jcr, M_INFO, 0, _("%s: run command \"%s\"\n"), name, ecmd);
201
202    bpipe = open_bpipe(ecmd, 0, "r");
203    free_pool_memory(ecmd);
204    if (bpipe == NULL) {
205       berrno be;
206       Jmsg(jcr, M_ERROR, 0, _("Runscript: %s could not execute. ERR=%s\n"), name,
207          be.strerror());
208       return false;
209    }
210    while (fgets(line, sizeof(line), bpipe->rfd)) {
211       int len = strlen(line);
212       if (len > 0 && line[len-1] == '\n') {
213          line[len-1] = 0;
214       }
215       Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line);
216    }
217    status = close_bpipe(bpipe);
218    if (status != 0) {
219       berrno be;
220       Jmsg(jcr, M_ERROR, 0, _("Runscript: %s returned non-zero status=%d. ERR=%s\n"), name,
221          be.code(status), be.strerror(status));
222       return false;
223    }
224    return true;
225 }
226
227 void free_runscripts(alist *runscripts)
228 {
229    Dmsg0(500, "runscript: freeing all RUNSCRIPTS object\n");
230
231    RUNSCRIPT *elt;
232    foreach_alist(elt, runscripts) {
233       free_runscript(elt);
234    }
235 }
236
237 void RUNSCRIPT::debug()
238 {
239    Dmsg0(200, "runscript: debug\n");
240    Dmsg0(200,  _(" --> RunScript\n"));
241    Dmsg1(200,  _("  --> Command=%s\n"), NPRT(command));
242    Dmsg1(200,  _("  --> Target=%s\n"),  NPRT(target));
243    Dmsg1(200,  _("  --> RunOnSuccess=%u\n"),  on_success);
244    Dmsg1(200,  _("  --> RunOnFailure=%u\n"),  on_failure);
245    Dmsg1(200,  _("  --> AbortJobOnError=%u\n"),  abort_on_error);
246    Dmsg1(200,  _("  --> RunWhen=%u\n"),  when);
247 }