--- /dev/null
+/*
+ * Manipulation routines for RunScript list
+ *
+ * Eric Bollengier, May 2006
+ *
+ * Version $Id$
+ *
+ */
+/*
+ Copyright (C) 2000-2006 Kern Sibbald
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as amended with additional clauses defined in the
+ file LICENSE in the main source directory.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ the file LICENSE for additional details.
+
+ */
+
+
+#include "bacula.h"
+#include "jcr.h"
+
+#define USE_RUNSCRIPT
+
+#include "runscript.h"
+
+RUNSCRIPT *new_runscript()
+{
+ Dmsg0(500, "runscript: creating new RUNSCRIPT object\n");
+ RUNSCRIPT *cmd = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
+ memset(cmd, 0, sizeof(RUNSCRIPT));
+ cmd->reset_default();
+
+ return cmd;
+}
+
+void RUNSCRIPT::reset_default(bool free_strings)
+{
+ if (free_strings && command) {
+ free_pool_memory(command);
+ }
+ if (free_strings && target) {
+ free_pool_memory(target);
+ }
+
+ target = NULL;
+ command = NULL;
+ on_success = true;
+ on_failure = false;
+ abort_on_error = true;
+ when = SCRIPT_Never;
+}
+
+RUNSCRIPT *copy_runscript(RUNSCRIPT *src)
+{
+ Dmsg0(500, "runscript: creating new RUNSCRIPT object from other\n");
+
+ RUNSCRIPT *dst = (RUNSCRIPT *)malloc(sizeof(RUNSCRIPT));
+ memcpy(dst, src, sizeof(RUNSCRIPT));
+
+ dst->command = NULL;
+ dst->target = NULL;
+
+ dst->set_command(src->command);
+ dst->set_target(src->target);
+
+ return dst;
+}
+
+void free_runscript(RUNSCRIPT *script)
+{
+ Dmsg0(500, "runscript: freeing RUNSCRIPT object\n");
+
+ if (script->command) {
+ free_pool_memory(script->command);
+ }
+ if (script->target) {
+ free_pool_memory(script->target);
+ }
+ free(script);
+}
+
+int run_scripts(JCR *jcr, alist *runscripts, const char *label)
+{
+ Dmsg2(200, "runscript: running all RUNSCRIPT object (%s) JobStatus=%c\n", label, jcr->JobStatus);
+
+ RUNSCRIPT *script;
+ bool runit;
+ bool status;
+
+ if (runscripts == NULL) {
+ Dmsg0(100, "runscript: WARNING RUNSCRIPTS list is NULL\n");
+ return 0;
+ }
+
+ foreach_alist(script, runscripts) {
+ Dmsg2(200, "runscript: try to run %s:%s\n", NPRT(script->target), NPRT(script->command));
+ runit=false;
+
+ if ((script->when & SCRIPT_Before) && (jcr->JobStatus == JS_Created)) {
+ Dmsg0(200, "runscript: Run it because SCRIPT_Before\n");
+ runit = true;
+ }
+
+ if ((script->when & SCRIPT_Before) && (jcr->JobStatus == JS_Running)) {
+ Dmsg0(200, "runscript: Run it because SCRIPT_Before\n");
+ runit = true;
+ }
+
+ if (script->when & SCRIPT_After) {
+ if ( (script->on_success && (jcr->JobStatus == JS_Terminated))
+ ||
+ (script->on_failure && job_canceled(jcr))
+ )
+ {
+ Dmsg4(200, "runscript: Run it because SCRIPT_After (%s,%i,%i,%c)\n", script->command,
+ script->on_success,
+ script->on_failure,
+ jcr->JobStatus );
+ script->when ^= SCRIPT_After; /* reset SCRIPT_After bit */
+ runit = true;
+ }
+ }
+
+ if (!script->is_local()) {
+ runit=false;
+ }
+
+ /* we execute it */
+ if (runit) {
+ status = script->run(jcr, label);
+
+ /* cancel running job properly */
+ if ( script->abort_on_error
+ && (status == false)
+ && (jcr->JobStatus == JS_Created)
+ )
+ {
+ set_jcr_job_status(jcr, JS_ErrorTerminated);
+ }
+ }
+ }
+ return 1;
+}
+
+bool RUNSCRIPT::is_local()
+{
+ if (!target || (strcmp(target, "") == 0)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/* set this->command to cmd */
+void RUNSCRIPT::set_command(const POOLMEM *cmd)
+{
+ Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd));
+
+ if (!cmd) {
+ return;
+ }
+
+ if (!command) {
+ command = get_pool_memory(PM_FNAME);
+ }
+
+ pm_strcpy(command, cmd);
+}
+
+/* set this->target to client_name */
+void RUNSCRIPT::set_target(const POOLMEM *client_name)
+{
+ Dmsg1(500, "runscript: setting target\n", NPRT(client_name));
+
+ if (!client_name) {
+ return;
+ }
+
+ if (!target) {
+ target = get_pool_memory(PM_FNAME);
+ }
+
+ pm_strcpy(target, client_name);
+}
+
+int RUNSCRIPT::run(JCR *jcr, const char *name)
+{
+ Dmsg0(200, "runscript: running a RUNSCRIPT object\n");
+ POOLMEM *ecmd = get_pool_memory(PM_FNAME);
+ int status;
+ BPIPE *bpipe;
+ char line[MAXSTRING];
+
+ ecmd = edit_job_codes(jcr, ecmd, this->command, "");
+ Dmsg1(100, "runscript: running '%s'...\n", ecmd);
+ Jmsg(jcr, M_INFO, 0, _("%s: run command \"%s\"\n"), name, ecmd);
+
+ bpipe = open_bpipe(ecmd, 0, "r");
+ free_pool_memory(ecmd);
+ if (bpipe == NULL) {
+ berrno be;
+ Jmsg(jcr, M_FATAL, 0, _("%s could not execute. ERR=%s\n"), name,
+ be.strerror());
+ return false;
+ }
+ while (fgets(line, sizeof(line), bpipe->rfd)) {
+ int len = strlen(line);
+ if (len > 0 && line[len-1] == '\n') {
+ line[len-1] = 0;
+ }
+ Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line);
+ }
+ status = close_bpipe(bpipe);
+ if (status != 0) {
+ berrno be;
+ Jmsg(jcr, M_FATAL, 0, _("%s returned non-zero status=%d. ERR=%s\n"), name,
+ status, be.strerror(status));
+ return false;
+ }
+ return true;
+}
+
+void free_runscripts(alist *runscripts)
+{
+ Dmsg0(500, "runscript: freeing all RUNSCRIPTS object\n");
+
+ RUNSCRIPT *elt;
+ foreach_alist(elt, runscripts) {
+ free_runscript(elt);
+ }
+}
+
+void RUNSCRIPT::debug()
+{
+ Dmsg0(200, "runscript: debug\n");
+ Dmsg0(200, _(" --> RunScript\n"));
+ Dmsg1(200, _(" --> Command=%s\n"), NPRT(command));
+ Dmsg1(200, _(" --> Target=%s\n"), NPRT(target));
+ Dmsg1(200, _(" --> RunOnSuccess=%u\n"), on_success);
+ Dmsg1(200, _(" --> RunOnFailure=%u\n"), on_failure);
+ Dmsg1(200, _(" --> AbortJobOnError=%u\n"), abort_on_error);
+ Dmsg1(200, _(" --> RunWhen=%u\n"), when);
+}
--- /dev/null
+/*
+ * Bacula RUNSCRIPT Structure definition for FileDaemon and Director
+ * Eric Bollengier May 2006
+ * Version $Id$
+ */
+/*
+ Copyright (C) 2000-2006 Kern Sibbald
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ version 2 as amended with additional clauses defined in the
+ file LICENSE in the main source directory.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ the file LICENSE for additional details.
+
+ */
+
+
+#ifndef __RUNSCRIPT_H_
+#define __RUNSCRIPT_H_ 1
+
+#if defined(FILE_DAEMON) || defined(DIRECTOR_DAEMON)
+# define USE_RUNSCRIPT
+#endif
+
+#ifdef USE_RUNSCRIPT
+
+/* Usage:
+ *
+ * #define USE_RUNSCRIPT
+ * #include "lib/runscript.h"
+ *
+ * RUNSCRIPT *script = new_runscript();
+ * script->set_command("/bin/sleep 20");
+ * script->on_failure = true;
+ * script->when = SCRIPT_After;
+ *
+ * script->run("Label");
+ * free_runscript(script);
+ */
+
+/*
+ * RUNSCRIPT->when can take following value :
+ */
+enum {
+ SCRIPT_Never = 0,
+ SCRIPT_After = 1, /* AfterJob */
+ SCRIPT_Before = 2, /* BeforeJob */
+ SCRIPT_Any = 3 /* Before and After */
+};
+
+/*
+ * Structure for RunScript ressource
+ */
+class RUNSCRIPT {
+public:
+ POOLMEM *command; /* command string */
+ POOLMEM *target; /* host target */
+ char level; /* Base|Full|Incr...|All (NYI) */
+ bool on_success; /* executre command on job success (After) */
+ bool on_failure; /* executre command on job failure (After) */
+ bool abort_on_error; /* abort job on error (Before) */
+ int when; /* SCRIPT_Before|Script_After BEFORE/AFTER JOB*/
+
+ int run(JCR *job, const char *name="");
+ bool can_run_at_level(int JobLevel) { return true;}; /* TODO */
+ void set_command(const POOLMEM *cmd);
+ void set_target(const POOLMEM *client_name);
+ void reset_default(bool free_string = false);
+ bool is_local(); /* true if running on local host */
+ void debug();
+};
+
+/* create new RUNSCRIPT (set all value to 0) */
+RUNSCRIPT *new_runscript();
+
+/* create new RUNSCRIPT from an other */
+RUNSCRIPT *copy_runscript(RUNSCRIPT *src);
+
+/* launch each script from runscripts*/
+int run_scripts(JCR *jcr, alist *runscripts, const char *name);
+
+/* free RUNSCRIPT (and all POOLMEM) */
+void free_runscript(RUNSCRIPT *script);
+
+/* foreach_alist free RUNSCRIPT */
+void free_runscripts(alist *runscripts); /* you have to free alist */
+
+#endif /* USE_RUNSCRIPT */
+
+#endif /* __RUNSCRIPT_H_ */