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