]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/runscript.c
o fix runscript bug on dird
[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 }
56
57 RUNSCRIPT *copy_runscript(RUNSCRIPT *src)
58 {
59    Dmsg0(500, "runscript: creating new RUNSCRIPT object from other\n");
60
61    RUNSCRIPT *dst = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
62    memcpy(dst, src, sizeof(RUNSCRIPT));
63
64    dst->command = NULL;
65    dst->target = NULL;
66
67    dst->set_command(src->command);
68    dst->set_target(src->target);
69
70    return dst;   
71 }
72
73 void free_runscript(RUNSCRIPT *script)
74 {
75    Dmsg0(500, "runscript: freeing RUNSCRIPT object\n");
76
77    if (script->command) {
78       free_pool_memory(script->command);
79    }
80    if (script->target) {
81       free_pool_memory(script->target);
82    }
83    free(script);
84 }
85
86 int run_scripts(JCR *jcr, alist *runscripts, const char *label)
87 {
88    Dmsg2(200, "runscript: running all RUNSCRIPT object (%s) JobStatus=%c\n", label, jcr->JobStatus);
89    
90    RUNSCRIPT *script;
91    bool runit;
92    bool status;
93
94    if (runscripts == NULL) {
95       Dmsg0(100, "runscript: WARNING RUNSCRIPTS list is NULL\n");
96       return 0;
97    }
98
99    foreach_alist(script, runscripts) {
100       Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(script->target), NPRT(script->command));
101       runit=false;
102
103       if ((script->when & SCRIPT_Before) && (jcr->JobStatus == JS_Created)) {
104         Dmsg0(200, "runscript: Run it because SCRIPT_Before\n");
105         runit = true;
106       }
107
108       if ((script->when & SCRIPT_Before) && (jcr->JobStatus == JS_Running)) {
109         Dmsg0(200, "runscript: Run it because SCRIPT_Before\n");
110         runit = true;
111       }
112
113       if (script->when & SCRIPT_After) {
114         if (  (script->on_success && (jcr->JobStatus == JS_Terminated))
115             ||
116               (script->on_failure && job_canceled(jcr))
117            )
118         {
119            Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n", script->command,
120                                                                                 script->on_success,
121                                                                                 script->on_failure,
122                                                                                 jcr->JobStatus );
123            runit = true;
124         }
125       }
126
127       if (!script->is_local()) {
128          runit=false;
129       }
130
131       /* we execute it */
132       if (runit) {
133         status = script->run(jcr, label);
134
135         /* cancel running job properly */
136         if (   script->abort_on_error 
137             && (status == false) 
138             && (jcr->JobStatus == JS_Created)
139            )
140         {
141            set_jcr_job_status(jcr, JS_ErrorTerminated);
142         }
143       }
144    }
145    return 1;
146 }
147
148 bool RUNSCRIPT::is_local()
149 {
150    if (!target || (strcmp(target, "") == 0)) {
151       return true;
152    } else {
153       return false;
154    }
155 }
156
157 /* set this->command to cmd */
158 void RUNSCRIPT::set_command(const POOLMEM *cmd)
159 {
160    Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd));
161
162    if (!cmd) {
163       return;
164    }
165
166    if (!command) {
167       command = get_pool_memory(PM_FNAME);
168    }
169
170    pm_strcpy(command, cmd);
171 }
172
173 /* set this->target to client_name */
174 void RUNSCRIPT::set_target(const POOLMEM *client_name)
175 {
176    Dmsg1(500, "runscript: setting target\n", NPRT(client_name));
177
178    if (!client_name) {
179       return;
180    }
181
182    if (!target) {
183       target = get_pool_memory(PM_FNAME);
184    }
185
186    pm_strcpy(target, client_name);
187 }
188
189 int RUNSCRIPT::run(JCR *jcr, const char *name)
190 {
191    Dmsg0(200, "runscript: running a RUNSCRIPT object\n");
192    POOLMEM *ecmd = get_pool_memory(PM_FNAME);
193    int status;
194    BPIPE *bpipe;
195    char line[MAXSTRING];
196
197    ecmd = edit_job_codes(jcr, ecmd, this->command, "");
198    Dmsg1(100, "runscript: running '%s'...\n", ecmd);
199    Jmsg(jcr, M_INFO, 0, _("%s: run command \"%s\"\n"), name, ecmd);
200
201    bpipe = open_bpipe(ecmd, 0, "r");
202    free_pool_memory(ecmd);
203    if (bpipe == NULL) {
204       berrno be;
205       Jmsg(jcr, M_FATAL, 0, _("%s could not execute. ERR=%s\n"), name,
206          be.strerror());
207       return false;
208    }
209    while (fgets(line, sizeof(line), bpipe->rfd)) {
210       int len = strlen(line);
211       if (len > 0 && line[len-1] == '\n') {
212          line[len-1] = 0;
213       }
214       Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line);
215    }
216    status = close_bpipe(bpipe);
217    if (status != 0) {
218       berrno be;
219       Jmsg(jcr, M_FATAL, 0, _("%s returned non-zero status=%d. ERR=%s\n"), name,
220          status, be.strerror(status));
221       return false;
222    }
223    return true;
224 }
225
226 void free_runscripts(alist *runscripts)
227 {
228    Dmsg0(500, "runscript: freeing all RUNSCRIPTS object\n");
229
230    RUNSCRIPT *elt;
231    foreach_alist(elt, runscripts) {
232       free_runscript(elt);
233    }
234 }
235
236 void RUNSCRIPT::debug()
237 {
238    Dmsg0(200, "runscript: debug\n");
239    Dmsg0(200,  _(" --> RunScript\n"));
240    Dmsg1(200,  _("  --> Command=%s\n"), NPRT(command));
241    Dmsg1(200,  _("  --> Target=%s\n"),  NPRT(target));
242    Dmsg1(200,  _("  --> RunOnSuccess=%u\n"),  on_success);
243    Dmsg1(200,  _("  --> RunOnFailure=%u\n"),  on_failure);
244    Dmsg1(200,  _("  --> AbortJobOnError=%u\n"),  abort_on_error);
245    Dmsg1(200,  _("  --> RunWhen=%u\n"),  when);
246 }