]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/runscript.c
crypto: convert EVP_PKEY access and remainings bits for OpenSSL 1.1
[bacula/bacula] / bacula / src / lib / runscript.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2016 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is 
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  * Manipulation routines for RunScript list
21  *
22  *  Eric Bollengier, May 2006
23  *
24  */
25
26
27 #include "bacula.h"
28 #include "jcr.h"
29 #include "runscript.h"
30
31 /*
32  * This function pointer is set only by the Director (dird.c),
33  * and is not set in the File daemon, because the File
34  * daemon cannot run console commands.
35  */
36 bool (*console_command)(JCR *jcr, const char *cmd) = NULL;
37
38
39 RUNSCRIPT *new_runscript()
40 {
41    Dmsg0(500, "runscript: creating new RUNSCRIPT object\n");
42    RUNSCRIPT *cmd = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
43    memset(cmd, 0, sizeof(RUNSCRIPT));
44    cmd->reset_default();
45
46    return cmd;
47 }
48
49 void RUNSCRIPT::reset_default(bool free_strings)
50 {
51    if (free_strings && command) {
52      free_pool_memory(command);
53    }
54    if (free_strings && target) {
55      free_pool_memory(target);
56    }
57
58    target = NULL;
59    command = NULL;
60    on_success = true;
61    on_failure = false;
62    fail_on_error = true;
63    when = SCRIPT_Never;
64    old_proto = false;        /* TODO: drop this with bacula 1.42 */
65    job_code_callback = NULL;
66 }
67
68 RUNSCRIPT *copy_runscript(RUNSCRIPT *src)
69 {
70    Dmsg0(500, "runscript: creating new RUNSCRIPT object from other\n");
71
72    RUNSCRIPT *dst = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
73    memcpy(dst, src, sizeof(RUNSCRIPT));
74
75    dst->command = NULL;
76    dst->target = NULL;
77
78    dst->set_command(src->command, src->cmd_type);
79    dst->set_target(src->target);
80
81    return dst;
82 }
83
84 void free_runscript(RUNSCRIPT *script)
85 {
86    Dmsg0(500, "runscript: freeing RUNSCRIPT object\n");
87
88    if (script->command) {
89       free_pool_memory(script->command);
90    }
91    if (script->target) {
92       free_pool_memory(script->target);
93    }
94    free(script);
95 }
96
97 int run_scripts(JCR *jcr, alist *runscripts, const char *label)
98 {
99    Dmsg2(200, "runscript: running all RUNSCRIPT object (%s) JobStatus=%c\n", label, jcr->JobStatus);
100
101    RUNSCRIPT *script;
102    bool runit;
103
104    int when;
105
106    if (strstr(label, NT_("Before"))) {
107       when = SCRIPT_Before;
108    } else if (bstrcmp(label, NT_("ClientAfterVSS"))) {
109       when = SCRIPT_AfterVSS;
110    } else {
111       when = SCRIPT_After;
112    }
113
114    if (runscripts == NULL) {
115       Dmsg0(100, "runscript: WARNING RUNSCRIPTS list is NULL\n");
116       return 0;
117    }
118
119    foreach_alist(script, runscripts) {
120       Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(script->target), NPRT(script->command));
121       runit = false;
122
123       if ((script->when & SCRIPT_Before) && (when & SCRIPT_Before)) {
124          if ((script->on_success &&
125               (jcr->JobStatus == JS_Running || jcr->JobStatus == JS_Created))
126             || (script->on_failure &&
127                 (job_canceled(jcr) || jcr->JobStatus == JS_Differences))
128             )
129          {
130             Dmsg4(200, "runscript: Run it because SCRIPT_Before (%s,%i,%i,%c)\n",
131                   script->command, script->on_success, script->on_failure,
132                   jcr->JobStatus );
133             runit = true;
134          }
135       }
136
137       if ((script->when & SCRIPT_AfterVSS) && (when & SCRIPT_AfterVSS)) {
138          if ((script->on_success && (jcr->JobStatus == JS_Blocked))
139             || (script->on_failure && job_canceled(jcr))
140             )
141          {
142             Dmsg4(200, "runscript: Run it because SCRIPT_AfterVSS (%s,%i,%i,%c)\n",
143                   script->command, script->on_success, script->on_failure,
144                   jcr->JobStatus );
145             runit = true;
146          }
147       }
148
149       if ((script->when & SCRIPT_After) && (when & SCRIPT_After)) {
150          if ((script->on_success &&
151               (jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings))
152             || (script->on_failure &&
153                 (job_canceled(jcr) || jcr->JobStatus == JS_Differences))
154             )
155          {
156             Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n",
157                   script->command, script->on_success, script->on_failure,
158                   jcr->JobStatus );
159             runit = true;
160          }
161       }
162
163       if (!script->is_local()) {
164          runit = false;
165       }
166
167       /* we execute it */
168       if (runit) {
169          script->run(jcr, label);
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 char *cmd, int acmd_type)
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    cmd_type = acmd_type;
199 }
200
201 /* set this->target to client_name */
202 void RUNSCRIPT::set_target(const char *client_name)
203 {
204    Dmsg1(500, "runscript: setting target = %s\n", NPRT(client_name));
205
206    if (!client_name) {
207       return;
208    }
209
210    if (!target) {
211       target = get_pool_memory(PM_FNAME);
212    }
213
214    pm_strcpy(target, client_name);
215 }
216
217 bool RUNSCRIPT::run(JCR *jcr, const char *name)
218 {
219    Dmsg1(100, "runscript: running a RUNSCRIPT object type=%d\n", cmd_type);
220    POOLMEM *ecmd = get_pool_memory(PM_FNAME);
221    int status;
222    BPIPE *bpipe;
223    char line[MAXSTRING];
224
225    ecmd = edit_job_codes(jcr, ecmd, this->command, "", this->job_code_callback);
226    Dmsg1(100, "runscript: running '%s'...\n", ecmd);
227    Jmsg(jcr, M_INFO, 0, _("%s: run %s \"%s\"\n"),
228         cmd_type==SHELL_CMD?"shell command":"console command", name, ecmd);
229
230    switch (cmd_type) {
231    case SHELL_CMD:
232       bpipe = open_bpipe(ecmd, 0, "r");
233       free_pool_memory(ecmd);
234       if (bpipe == NULL) {
235          berrno be;
236          Jmsg(jcr, M_ERROR, 0, _("Runscript: %s could not execute. ERR=%s\n"), name,
237             be.bstrerror());
238          goto bail_out;
239       }
240       while (fgets(line, sizeof(line), bpipe->rfd)) {
241          int len = strlen(line);
242          if (len > 0 && line[len-1] == '\n') {
243             line[len-1] = 0;
244          }
245          Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line);
246       }
247       status = close_bpipe(bpipe);
248       if (status != 0) {
249          berrno be;
250          Jmsg(jcr, M_ERROR, 0, _("Runscript: %s returned non-zero status=%d. ERR=%s\n"), name,
251             be.code(status), be.bstrerror(status));
252          goto bail_out;
253       }
254       Dmsg0(100, "runscript OK\n");
255       break;
256    case CONSOLE_CMD:
257       if (console_command) {                 /* can we run console command? */
258          if (!console_command(jcr, ecmd)) {  /* yes, do so */
259             goto bail_out;
260          }
261       }
262       break;
263    }
264    return true;
265
266 bail_out:
267    /* cancel running job properly */
268    if (fail_on_error) {
269       jcr->setJobStatus(JS_ErrorTerminated);
270    }
271    Dmsg1(100, "runscript failed. fail_on_error=%d\n", fail_on_error);
272    return false;
273 }
274
275 void free_runscripts(alist *runscripts)
276 {
277    Dmsg0(500, "runscript: freeing all RUNSCRIPTS object\n");
278
279    RUNSCRIPT *elt;
280    foreach_alist(elt, runscripts) {
281       free_runscript(elt);
282    }
283 }
284
285 void RUNSCRIPT::debug()
286 {
287    Dmsg0(200, "runscript: debug\n");
288    Dmsg0(200,  _(" --> RunScript\n"));
289    Dmsg1(200,  _("  --> Command=%s\n"), NPRT(command));
290    Dmsg1(200,  _("  --> Target=%s\n"),  NPRT(target));
291    Dmsg1(200,  _("  --> RunOnSuccess=%u\n"),  on_success);
292    Dmsg1(200,  _("  --> RunOnFailure=%u\n"),  on_failure);
293    Dmsg1(200,  _("  --> FailJobOnError=%u\n"),  fail_on_error);
294    Dmsg1(200,  _("  --> RunWhen=%u\n"),  when);
295 }
296
297 void RUNSCRIPT::set_job_code_callback(job_code_callback_t arg_job_code_callback)
298 {
299    this->job_code_callback = arg_job_code_callback;
300 }