/*
Bacula® - The Network Backup Solution
- Copyright (C) 2002-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2002-2009 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
This program is Free Software; you can redistribute it and/or
modify it under the terms of version two of the GNU General Public
- License as published by the Free Software Foundation plus additions
- that are listed in the file LICENSE.
+ License as published by the Free Software Foundation and included
+ in the file LICENSE.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Bacula® is a registered trademark of John Walker.
+ Bacula® is a registered trademark of Kern Sibbald.
The licensor of Bacula is the Free Software Foundation Europe
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
#include "dird.h"
/* Imported variables */
-extern int r_first;
-extern int r_last;
-extern struct s_res resources[];
/* Imported functions */
extern void do_messages(UAContext *ua, const char *cmd);
static bool dot_quit_cmd(UAContext *ua, const char *cmd);
static bool dot_help_cmd(UAContext *ua, const char *cmd);
-struct cmdstruct { const char *key; bool (*func)(UAContext *ua, const char *cmd); const char *help; };
-static struct cmdstruct commands[] = {
- { NT_(".api"), api_cmd, NULL},
- { NT_(".backups"), backupscmd, NULL},
- { NT_(".clients"), clientscmd, NULL},
- { NT_(".defaults"), defaultscmd, NULL},
- { NT_(".die"), diecmd, NULL},
- { NT_(".exit"), dot_quit_cmd, NULL},
- { NT_(".filesets"), filesetscmd, NULL},
- { NT_(".help"), dot_help_cmd, NULL},
- { NT_(".jobs"), jobscmd, NULL},
- { NT_(".levels"), levelscmd, NULL},
- { NT_(".messages"), getmsgscmd, NULL},
- { NT_(".msgs"), msgscmd, NULL},
- { NT_(".pools"), poolscmd, NULL},
- { NT_(".quit"), dot_quit_cmd, NULL},
- { NT_(".sql"), sql_cmd, NULL},
- { NT_(".status"), dot_status_cmd, NULL},
- { NT_(".storage"), storagecmd, NULL},
- { NT_(".types"), typescmd, NULL}
+struct cmdstruct { const char *key; bool (*func)(UAContext *ua, const char *cmd); const char *help;const bool use_in_rs;};
+static struct cmdstruct commands[] = { /* help */ /* can be used in runscript */
+ { NT_(".api"), api_cmd, NULL, false},
+ { NT_(".backups"), backupscmd, NULL, false},
+ { NT_(".clients"), clientscmd, NULL, true},
+ { NT_(".defaults"), defaultscmd, NULL, false},
+ { NT_(".die"), diecmd, NULL, false},
+ { NT_(".exit"), dot_quit_cmd, NULL, false},
+ { NT_(".filesets"), filesetscmd, NULL, false},
+ { NT_(".help"), dot_help_cmd, NULL, false},
+ { NT_(".jobs"), jobscmd, NULL, true},
+ { NT_(".levels"), levelscmd, NULL, false},
+ { NT_(".messages"), getmsgscmd, NULL, false},
+ { NT_(".msgs"), msgscmd, NULL, false},
+ { NT_(".pools"), poolscmd, NULL, true},
+ { NT_(".quit"), dot_quit_cmd, NULL, false},
+ { NT_(".sql"), sql_cmd, NULL, false},
+ { NT_(".status"), dot_status_cmd, NULL, false},
+ { NT_(".storage"), storagecmd, NULL, true},
+ { NT_(".types"), typescmd, NULL, false}
};
#define comsize ((int)(sizeof(commands)/sizeof(struct cmdstruct)))
/*
* 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) {
+ /* Check if this command is authorized in RunScript */
+ if (ua->runscript && !commands[i].use_in_rs) {
+ ua->error_msg(_("Can't use %s command in a runscript"), ua->argk[0]);
+ break;
+ }
bool gui = ua->gui;
/* Check if command permitted, but "quit" is always OK */
if (strcmp(ua->argk[0], NT_(".quit")) != 0 &&
!acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
break;
}
+ 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 */
+ if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
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)
return 1;
}
+#ifdef DEVELOPER
+static void do_storage_die(UAContext *ua, STORE *store)
+{
+ BSOCK *sd;
+ JCR *jcr = ua->jcr;
+ USTORE lstore;
+
+ lstore.store = store;
+ pm_strcpy(lstore.store_source, _("unknown source"));
+ set_wstorage(jcr, &lstore);
+ /* Try connecting for up to 15 seconds */
+ ua->send_msg(_("Connecting to Storage daemon %s at %s:%d\n"),
+ store->name(), store->address, store->SDport);
+ if (!connect_to_storage_daemon(jcr, 1, 15, 0)) {
+ ua->error_msg(_("Failed to connect to Storage daemon.\n"));
+ return;
+ }
+ Dmsg0(120, _("Connected to storage daemon\n"));
+ sd = jcr->store_bsock;
+ sd->fsend(".die");
+ if (sd->recv() >= 0) {
+ ua->send_msg("%s", sd->msg);
+ }
+ sd->signal(BNET_TERMINATE);
+ sd->close();
+ jcr->store_bsock = NULL;
+ return;
+}
+
+static void do_client_die(UAContext *ua, CLIENT *client)
+{
+ BSOCK *fd;
+
+ /* Connect to File daemon */
+
+ ua->jcr->client = client;
+ /* Try to connect for 15 seconds */
+ ua->send_msg(_("Connecting to Client %s at %s:%d\n"),
+ client->name(), client->address, client->FDport);
+ if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) {
+ ua->error_msg(_("Failed to connect to Client.\n"));
+ return;
+ }
+ Dmsg0(120, "Connected to file daemon\n");
+ fd = ua->jcr->file_bsock;
+ fd->fsend(".die");
+ if (fd->recv() >= 0) {
+ ua->send_msg("%s", fd->msg);
+ }
+ fd->signal(BNET_TERMINATE);
+ fd->close();
+ ua->jcr->file_bsock = NULL;
+ return;
+}
+
/*
* Create segmentation fault
*/
static bool diecmd(UAContext *ua, const char *cmd)
{
+ STORE *store;
+ CLIENT *client;
+ int i;
JCR *jcr = NULL;
int a;
- ua->send_msg(_("The Director will segment fault.\n"));
- a = jcr->JobId; /* ref NULL pointer */
- jcr->JobId = 1000; /* another ref NULL pointer */
+ Dmsg1(120, "diecmd:%s:\n", cmd);
+
+ /* General debug? */
+ for (i=1; i<ua->argc; i++) {
+ if (strcasecmp(ua->argk[i], "dir") == 0 ||
+ strcasecmp(ua->argk[i], "director") == 0) {
+ ua->send_msg(_("The Director will segment fault.\n"));
+ a = jcr->JobId; /* ref NULL pointer */
+ jcr->JobId = 1000; /* another ref NULL pointer */
+ return 1;
+ }
+ if (strcasecmp(ua->argk[i], "client") == 0 ||
+ strcasecmp(ua->argk[i], "fd") == 0) {
+ client = NULL;
+ if (ua->argv[i]) {
+ client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
+ if (client) {
+ do_client_die(ua, client);
+ return 1;
+ }
+ }
+ client = select_client_resource(ua);
+ if (client) {
+ do_client_die(ua, client);
+ return 1;
+ }
+ }
+
+ if (strcasecmp(ua->argk[i], NT_("store")) == 0 ||
+ strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
+ strcasecmp(ua->argk[i], NT_("sd")) == 0) {
+ store = NULL;
+ if (ua->argv[i]) {
+ store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]);
+ if (store) {
+ do_storage_die(ua, store);
+ return 1;
+ }
+ }
+ store = get_storage_resource(ua, false/*no default*/);
+ if (store) {
+ do_storage_die(ua, store);
+ return 1;
+ }
+ }
+ }
+ /*
+ * We didn't find an appropriate keyword above, so
+ * prompt the user.
+ */
+ start_prompt(ua, _("Available daemons are: \n"));
+ add_prompt(ua, _("Director"));
+ add_prompt(ua, _("Storage"));
+ add_prompt(ua, _("Client"));
+ switch(do_prompt(ua, "", _("Select daemon type to make die"), NULL, 0)) {
+ case 0: /* Director */
+ ua->send_msg(_("The Director will segment fault.\n"));
+ a = jcr->JobId; /* ref NULL pointer */
+ jcr->JobId = 1000; /* another ref NULL pointer */
+ break;
+ case 1:
+ store = get_storage_resource(ua, false/*no default*/);
+ if (store) {
+ do_storage_die(ua, store);
+ }
+ break;
+ case 2:
+ client = select_client_resource(ua);
+ if (client) {
+ do_client_die(ua, client);
+ }
+ break;
+ default:
+ break;
+ }
return true;
}
+#else
+
+/*
+ * Dummy routine for non-development version
+ */
+static bool diecmd(UAContext *ua, const char *cmd)
+{
+ return true;
+}
+
+#endif
+
static bool jobscmd(UAContext *ua, const char *cmd)
{
JOB *job;
UAContext *ua = (UAContext *)ctx;
POOL_MEM rows(PM_MESSAGE);
+ /* Check for nonsense */
+ if (num_field == 0 || row == NULL || row[0] == NULL) {
+ return 0; /* nothing returned */
+ }
for (int i=0; num_field--; i++) {
if (i == 0) {
- pm_strcpy(rows, row[0]);
+ pm_strcpy(rows, NPRT(row[0]));
} else {
- pm_strcat(rows, row[i]);
+ pm_strcat(rows, NPRT(row[i]));
}
pm_strcat(rows, "\t");
}
- ua->send_msg(rows.c_str());
+ if (!rows.c_str() || !*rows.c_str()) {
+ ua->send_msg("\t");
+ } else {
+ ua->send_msg("%s", rows.c_str());
+ }
return 0;
}
ua->send_msg("Incremental\n");
ua->send_msg("Full\n");
ua->send_msg("Differential\n");
+ ua->send_msg("VirtualFull\n");
ua->send_msg("Catalog\n");
ua->send_msg("InitCatalog\n");
ua->send_msg("VolumeToCatalog\n");