--- /dev/null
+
+ If you have an old version of PostgreSQL, for example,
+ version 7.3 or older, it may not properly build with the current
+ Bacula release due to incompatible changes in the PostgreSQL
+ header files between version. Only in the case that build fails,
+ you might try applying this patch with:
+
+ cd <bacula-2.2.7-source>
+ patch -p1 <2.2.7-old-postgresql.patch
+ ./configure <your-options>
+ make
+ ...
+ make install
+
+
+diff -uNr bacula-2.2.7/src/cats/postgresql.c bacula-2.2.7-fixed/src/cats/postgresql.c
+--- bacula-2.2.7/src/cats/postgresql.c 2007-12-08 04:54:55.000000000 -0500
++++ bacula-2.2.7-fixed/src/cats/postgresql.c 2007-12-29 08:34:10.000000000 -0500
+@@ -47,7 +47,6 @@
+ #ifdef HAVE_POSTGRESQL
+
+ #include "postgres_ext.h" /* needed for NAMEDATALEN */
+-#include "pg_config_manual.h" /* get NAMEDATALEN on version 8.3 or later */
+
+ /* -----------------------------------------------------------------------
+ *
init_reload();
daemon_start_time = time(NULL);
+ console_command = run_console_command;
+
while ((ch = getopt(argc, argv, "c:d:fg:r:stu:v?")) != -1) {
switch (ch) {
case 'c': /* specify config file */
scan_to_eol(lc);
}
-/* Store a runscript->command in a bit field
- *
+/*
+ * Store a runscript->command as a string
*/
static void store_runscript_cmd(LEX *lc, RES_ITEM *item, int index, int pass)
{
lex_get_token(lc, T_STRING);
if (pass == 2) {
- ((RUNSCRIPT*) item->value)->set_command(lc->str);
+ ((RUNSCRIPT*)item->value)->set_command(lc->str, item->code);
}
scan_to_eol(lc);
}
/*
* new RunScript items
- * name handler value code flags default_value
+ * name handler value code flags default_value
*/
static RES_ITEM runscript_items[] = {
- {"command", store_runscript_cmd, {(char **)&res_runscript}, 0, ITEM_REQUIRED, 0},
+ {"command", store_runscript_cmd, {(char **)&res_runscript}, SHELL_CMD, 0, 0},
+ {"console", store_runscript_cmd, {(char **)&res_runscript}, CONSOLE_CMD, 0, 0},
{"target", store_runscript_target,{(char **)&res_runscript}, 0, 0, 0},
{"runsonsuccess", store_runscript_bool, {(char **)&res_runscript.on_success},0, 0, 0},
{"runsonfailure", store_runscript_bool, {(char **)&res_runscript.on_failure},0, 0, 0},
jcr->needs_sd = true;
return true;
}
+
+bool run_console_command(JCR *jcr, const char *cmd){
+ UAContext *ua;
+ bool ok;
+
+ ua = new_ua_context(jcr);
+ Mmsg(ua->cmd, "%s", cmd);
+ Dmsg1(100, "Console command: %s\n", ua->cmd);
+ parse_ua_args(ua);
+ ok= do_a_command(ua);
+ free_ua_context(ua);
+ return ok;
+}
edit_uint64(jcr->MigrateJobId, ed1));
Dmsg1(dbglevel, "=============== Migration cmd=%s\n", ua->cmd);
parse_ua_args(ua); /* parse command */
- int jobid = run_cmd(ua, ua->cmd);
+ JobId_t jobid = run_cmd(ua, ua->cmd);
if (jobid == 0) {
Jmsg(jcr, M_ERROR, 0, _("Could not start migration job.\n"));
} else {
- Jmsg(jcr, M_INFO, 0, _("Migration JobId %d started.\n"), jobid);
+ Jmsg(jcr, M_INFO, 0, _("Migration JobId %d started.\n"), (int)jobid);
}
free_ua_context(ua);
}
extern void dird_free_jcr(JCR *jcr);
extern void dird_free_jcr_pointers(JCR *jcr);
extern void cancel_storage_daemon_job(JCR *jcr);
+extern bool run_console_command(JCR *jcr, const char *cmd);
/* migration.c */
extern bool do_migration(JCR *jcr);
bool acl_access_ok(UAContext *ua, int acl, const char *item, int len);
/* ua_cmds.c */
-int do_a_command(UAContext *ua, const char *cmd);
-int do_a_dot_command(UAContext *ua, const char *cmd);
+bool do_a_command(UAContext *ua);
+bool do_a_dot_command(UAContext *ua);
int qmessagescmd(UAContext *ua, const char *cmd);
bool open_client_db(UAContext *ua);
bool open_db(UAContext *ua);
/*
* Execute a command from the UA
*/
-int do_a_command(UAContext *ua, const char *cmd)
+bool do_a_command(UAContext *ua)
{
unsigned int i;
- int len, stat;
+ int len;
bool ok = false;
bool found = false;
BSOCK *user = ua->UA_sock;
- stat = 1;
Dmsg1(900, "Command: %s\n", ua->UA_sock->msg);
if (ua->argc == 0) {
- return 1;
+ return false;
}
while (ua->jcr->wstorage->size()) {
break;
}
if (ua->api) user->signal(BNET_CMD_BEGIN);
- ok = (*commands[i].func)(ua, cmd); /* go execute command */
+ ok = (*commands[i].func)(ua, ua->cmd); /* go execute command */
found = true;
break;
}
}
if (!found) {
- user->fsend(_("%s: is an invalid command.\n"), ua->argk[0]);
+ ua->error_msg(_("%s: is an invalid command.\n"), ua->argk[0]);
+ ok = false;
}
if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
return ok;
/*
* Execute a command from the UA
*/
-int do_a_dot_command(UAContext *ua, const char *cmd)
+bool do_a_dot_command(UAContext *ua)
{
int i;
int len;
Dmsg1(1400, "Dot command: %s\n", user->msg);
if (ua->argc == 0) {
- return 1;
+ return false;
}
len = strlen(ua->argk[0]);
if (len == 1) {
if (ua->api) user->signal(BNET_CMD_BEGIN);
if (ua->api) user->signal(BNET_CMD_OK);
- return 1; /* no op */
+ return true; /* no op */
}
for (i=0; i<comsize; i++) { /* search for command */
if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
!acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
break;
}
- Dmsg1(100, "Cmd: %s\n", cmd);
+ Dmsg1(100, "Cmd: %s\n", ua->cmd);
ua->gui = true;
if (ua->api) user->signal(BNET_CMD_BEGIN);
- ok = (*commands[i].func)(ua, cmd); /* go execute command */
+ ok = (*commands[i].func)(ua, ua->cmd); /* go execute command */
ua->gui = gui;
found = true;
break;
}
if (!found) {
pm_strcat(user->msg, _(": is an invalid command.\n"));
- user->msglen = strlen(user->msg);
- user->send();
+ ua->error_msg("%s", user->msg);
+ ok = false;
}
if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
- return 1;
+ return ok;
}
static bool dot_quit_cmd(UAContext *ua, const char *cmd)
pm_strcpy(ua->cmd, ua->UA_sock->msg);
parse_ua_args(ua);
if (ua->argc > 0 && ua->argk[0][0] == '.') {
- do_a_dot_command(ua, ua->cmd);
+ do_a_dot_command(ua);
} else {
- do_a_command(ua, ua->cmd);
+ do_a_command(ua);
}
dequeue_messages(ua->jcr);
if (!ua->quit) {
#include "bacula.h"
#include "jcr.h"
#include "runscript.h"
+
+/*
+ * This function pointer is set only by the Director (dird.c),
+ * and is not set in the File daemon, because the File
+ * daemon cannot run console commands.
+ */
+bool (*console_command)(JCR *jcr, const char *cmd) = NULL;
+
RUNSCRIPT *new_runscript()
{
dst->command = NULL;
dst->target = NULL;
- dst->set_command(src->command);
+ dst->set_command(src->command, src->cmd_type);
dst->set_target(src->target);
return dst;
}
/* set this->command to cmd */
-void RUNSCRIPT::set_command(const POOLMEM *cmd)
+void RUNSCRIPT::set_command(const POOLMEM *cmd, int acmd_type)
{
Dmsg1(500, "runscript: setting command = %s\n", NPRT(cmd));
}
pm_strcpy(command, cmd);
+ cmd_type = acmd_type;
}
/* set this->target to client_name */
bool RUNSCRIPT::run(JCR *jcr, const char *name)
{
- Dmsg0(200, "runscript: running a RUNSCRIPT object\n");
+ Dmsg1(100, "runscript: running a RUNSCRIPT object type=%d\n", cmd_type);
POOLMEM *ecmd = get_pool_memory(PM_FNAME);
int status;
BPIPE *bpipe;
ecmd = edit_job_codes(jcr, ecmd, this->command, "", this->job_code_callback);
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_ERROR, 0, _("Runscript: %s could not execute. ERR=%s\n"), name,
- be.bstrerror());
- goto bail_out;
- }
- 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: run %s \"%s\"\n"),
+ cmd_type==SHELL_CMD?"shell command":"console command", name, ecmd);
+
+ switch (cmd_type) {
+ case SHELL_CMD:
+ bpipe = open_bpipe(ecmd, 0, "r");
+ free_pool_memory(ecmd);
+ if (bpipe == NULL) {
+ berrno be;
+ Jmsg(jcr, M_ERROR, 0, _("Runscript: %s could not execute. ERR=%s\n"), name,
+ be.bstrerror());
+ goto bail_out;
}
- Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line);
- }
- status = close_bpipe(bpipe);
- if (status != 0) {
- berrno be;
- Jmsg(jcr, M_ERROR, 0, _("Runscript: %s returned non-zero status=%d. ERR=%s\n"), name,
- be.code(status), be.bstrerror(status));
- goto bail_out;
+ 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_ERROR, 0, _("Runscript: %s returned non-zero status=%d. ERR=%s\n"), name,
+ be.code(status), be.bstrerror(status));
+ goto bail_out;
+ }
+ Dmsg0(100, "runscript OK\n");
+ break;
+ case CONSOLE_CMD:
+ if (console_command) { /* can we run console command? */
+ if (!console_command(jcr, ecmd)) { /* yes, do so */
+ goto bail_out;
+ }
+ }
+ break;
}
- Dmsg0(100, "runscript OK\n");
return true;
bail_out:
}
void RUNSCRIPT::set_job_code_callback(job_code_callback_t arg_job_code_callback)
-
{
this->job_code_callback = arg_job_code_callback;
}
SCRIPT_Any = SCRIPT_Before | SCRIPT_After
};
+enum {
+ SHELL_CMD = 1,
+ CONSOLE_CMD = 2
+};
+
/*
* Structure for RunScript ressource
*/
POOLMEM *command; /* command string */
POOLMEM *target; /* host target */
int when; /* SCRIPT_Before|Script_After BEFORE/AFTER JOB*/
+ int cmd_type; /* Command type -- Shell, Console */
char level; /* Base|Full|Incr...|All (NYI) */
bool on_success; /* execute command on job success (After) */
bool on_failure; /* execute command on job failure (After) */
bool run(JCR *job, const char *name=""); /* name must contain "Before" or "After" keyword */
bool can_run_at_level(int JobLevel) { return true;}; /* TODO */
- void set_command(const POOLMEM *cmd);
+ void set_command(const POOLMEM *cmd, int cmd_type = SHELL_CMD);
void set_target(const POOLMEM *client_name);
void reset_default(bool free_string = false);
bool is_local(); /* true if running on local host */
/* foreach_alist free RUNSCRIPT */
void free_runscripts(alist *runscripts); /* you have to free alist */
+extern bool (*console_command)(JCR *jcr, const char *cmd);
+
#endif /* __RUNSCRIPT_H_ */
#undef VERSION
#define VERSION "2.3.8"
-#define BDATE "24 December 2007"
-#define LSMDATE "24Dec07"
+#define BDATE "31 December 2007"
+#define LSMDATE "31Dec07"
#define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n"
#define BYEAR "2007" /* year for copyright messages in progs */
Technical notes on version 2.3
General:
+31Dec07
+kes Implement first cut running console commands in a RunScript.
29Dec07
ebl Fixes #1028 where "Selection Type" option was not usable with JobDefs.
ebl Fixes #897 and #1005 where bacula doesn't display runscript