2 Bacula® - The Network Backup Solution
4 Copyright (C) 2002-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
30 * Bacula Director -- User Agent Commands
31 * These are "dot" commands, i.e. commands preceded
32 * by a period. These commands are meant to be used
33 * by a program, so there is no prompting, and the
34 * returned results are (supposed to be) predictable.
36 * Kern Sibbald, April MMII
44 /* Imported variables */
46 /* Imported functions */
47 extern void do_messages(UAContext *ua, const char *cmd);
48 extern int quit_cmd(UAContext *ua, const char *cmd);
49 extern int qhelp_cmd(UAContext *ua, const char *cmd);
50 extern bool dot_status_cmd(UAContext *ua, const char *cmd);
53 /* Forward referenced functions */
54 static bool diecmd(UAContext *ua, const char *cmd);
55 static bool jobscmd(UAContext *ua, const char *cmd);
56 static bool filesetscmd(UAContext *ua, const char *cmd);
57 static bool clientscmd(UAContext *ua, const char *cmd);
58 static bool msgscmd(UAContext *ua, const char *cmd);
59 static bool poolscmd(UAContext *ua, const char *cmd);
60 static bool storagecmd(UAContext *ua, const char *cmd);
61 static bool defaultscmd(UAContext *ua, const char *cmd);
62 static bool typescmd(UAContext *ua, const char *cmd);
63 static bool backupscmd(UAContext *ua, const char *cmd);
64 static bool levelscmd(UAContext *ua, const char *cmd);
65 static bool getmsgscmd(UAContext *ua, const char *cmd);
67 static bool api_cmd(UAContext *ua, const char *cmd);
68 static bool sql_cmd(UAContext *ua, const char *cmd);
69 static bool dot_quit_cmd(UAContext *ua, const char *cmd);
70 static bool dot_help_cmd(UAContext *ua, const char *cmd);
72 struct cmdstruct { const char *key; bool (*func)(UAContext *ua, const char *cmd); const char *help;const bool use_in_rs;};
73 static struct cmdstruct commands[] = { /* help */ /* can be used in runscript */
74 { NT_(".api"), api_cmd, NULL, false},
75 { NT_(".backups"), backupscmd, NULL, false},
76 { NT_(".clients"), clientscmd, NULL, true},
77 { NT_(".defaults"), defaultscmd, NULL, false},
78 { NT_(".die"), diecmd, NULL, false},
79 { NT_(".exit"), dot_quit_cmd, NULL, false},
80 { NT_(".filesets"), filesetscmd, NULL, false},
81 { NT_(".help"), dot_help_cmd, NULL, false},
82 { NT_(".jobs"), jobscmd, NULL, true},
83 { NT_(".levels"), levelscmd, NULL, false},
84 { NT_(".messages"), getmsgscmd, NULL, false},
85 { NT_(".msgs"), msgscmd, NULL, false},
86 { NT_(".pools"), poolscmd, NULL, true},
87 { NT_(".quit"), dot_quit_cmd, NULL, false},
88 { NT_(".sql"), sql_cmd, NULL, false},
89 { NT_(".status"), dot_status_cmd, NULL, false},
90 { NT_(".storage"), storagecmd, NULL, true},
91 { NT_(".types"), typescmd, NULL, false}
93 #define comsize ((int)(sizeof(commands)/sizeof(struct cmdstruct)))
96 * Execute a command from the UA
98 bool do_a_dot_command(UAContext *ua)
104 BSOCK *user = ua->UA_sock;
106 Dmsg1(1400, "Dot command: %s\n", user->msg);
111 len = strlen(ua->argk[0]);
113 if (ua->api) user->signal(BNET_CMD_BEGIN);
114 if (ua->api) user->signal(BNET_CMD_OK);
115 return true; /* no op */
117 for (i=0; i<comsize; i++) { /* search for command */
118 if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
119 /* Check if this command is authorized in RunScript */
120 if (ua->runscript && !commands[i].use_in_rs) {
121 ua->error_msg(_("Can't use %s command in a runscript"), ua->argk[0]);
125 /* Check if command permitted, but "quit" is always OK */
126 if (strcmp(ua->argk[0], NT_(".quit")) != 0 &&
127 !acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
130 Dmsg1(100, "Cmd: %s\n", ua->cmd);
132 if (ua->api) user->signal(BNET_CMD_BEGIN);
133 ok = (*commands[i].func)(ua, ua->cmd); /* go execute command */
140 pm_strcat(user->msg, _(": is an invalid command.\n"));
141 ua->error_msg("%s", user->msg);
144 if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
148 static bool dot_quit_cmd(UAContext *ua, const char *cmd)
154 static bool dot_help_cmd(UAContext *ua, const char *cmd)
160 static bool getmsgscmd(UAContext *ua, const char *cmd)
162 if (console_msg_pending) {
163 do_messages(ua, cmd);
169 static void do_storage_die(UAContext *ua, STORE *store)
175 lstore.store = store;
176 pm_strcpy(lstore.store_source, _("unknown source"));
177 set_wstorage(jcr, &lstore);
178 /* Try connecting for up to 15 seconds */
179 ua->send_msg(_("Connecting to Storage daemon %s at %s:%d\n"),
180 store->name(), store->address, store->SDport);
181 if (!connect_to_storage_daemon(jcr, 1, 15, 0)) {
182 ua->error_msg(_("Failed to connect to Storage daemon.\n"));
185 Dmsg0(120, _("Connected to storage daemon\n"));
186 sd = jcr->store_bsock;
188 if (sd->recv() >= 0) {
189 ua->send_msg("%s", sd->msg);
191 sd->signal(BNET_TERMINATE);
193 jcr->store_bsock = NULL;
197 static void do_client_die(UAContext *ua, CLIENT *client)
201 /* Connect to File daemon */
203 ua->jcr->client = client;
204 /* Try to connect for 15 seconds */
205 ua->send_msg(_("Connecting to Client %s at %s:%d\n"),
206 client->name(), client->address, client->FDport);
207 if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) {
208 ua->error_msg(_("Failed to connect to Client.\n"));
211 Dmsg0(120, "Connected to file daemon\n");
212 fd = ua->jcr->file_bsock;
214 if (fd->recv() >= 0) {
215 ua->send_msg("%s", fd->msg);
217 fd->signal(BNET_TERMINATE);
219 ua->jcr->file_bsock = NULL;
224 * Create segmentation fault
226 static bool diecmd(UAContext *ua, const char *cmd)
234 Dmsg1(120, "diecmd:%s:\n", cmd);
237 for (i=1; i<ua->argc; i++) {
238 if (strcasecmp(ua->argk[i], "dir") == 0 ||
239 strcasecmp(ua->argk[i], "director") == 0) {
240 ua->send_msg(_("The Director will segment fault.\n"));
241 a = jcr->JobId; /* ref NULL pointer */
242 jcr->JobId = 1000; /* another ref NULL pointer */
245 if (strcasecmp(ua->argk[i], "client") == 0 ||
246 strcasecmp(ua->argk[i], "fd") == 0) {
249 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
251 do_client_die(ua, client);
255 client = select_client_resource(ua);
257 do_client_die(ua, client);
262 if (strcasecmp(ua->argk[i], NT_("store")) == 0 ||
263 strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
264 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
267 store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]);
269 do_storage_die(ua, store);
273 store = get_storage_resource(ua, false/*no default*/);
275 do_storage_die(ua, store);
281 * We didn't find an appropriate keyword above, so
284 start_prompt(ua, _("Available daemons are: \n"));
285 add_prompt(ua, _("Director"));
286 add_prompt(ua, _("Storage"));
287 add_prompt(ua, _("Client"));
288 switch(do_prompt(ua, "", _("Select daemon type to make die"), NULL, 0)) {
289 case 0: /* Director */
290 ua->send_msg(_("The Director will segment fault.\n"));
291 a = jcr->JobId; /* ref NULL pointer */
292 jcr->JobId = 1000; /* another ref NULL pointer */
295 store = get_storage_resource(ua, false/*no default*/);
297 do_storage_die(ua, store);
301 client = select_client_resource(ua);
303 do_client_die(ua, client);
315 * Dummy routine for non-development version
317 static bool diecmd(UAContext *ua, const char *cmd)
324 static bool jobscmd(UAContext *ua, const char *cmd)
328 foreach_res(job, R_JOB) {
329 if (acl_access_ok(ua, Job_ACL, job->name())) {
330 ua->send_msg("%s\n", job->name());
337 static bool filesetscmd(UAContext *ua, const char *cmd)
341 foreach_res(fs, R_FILESET) {
342 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
343 ua->send_msg("%s\n", fs->name());
350 static bool clientscmd(UAContext *ua, const char *cmd)
354 foreach_res(client, R_CLIENT) {
355 if (acl_access_ok(ua, Client_ACL, client->name())) {
356 ua->send_msg("%s\n", client->name());
363 static bool msgscmd(UAContext *ua, const char *cmd)
367 foreach_res(msgs, R_MSGS) {
368 ua->send_msg("%s\n", msgs->name());
374 static bool poolscmd(UAContext *ua, const char *cmd)
378 foreach_res(pool, R_POOL) {
379 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
380 ua->send_msg("%s\n", pool->name());
387 static bool storagecmd(UAContext *ua, const char *cmd)
391 foreach_res(store, R_STORAGE) {
392 if (acl_access_ok(ua, Storage_ACL, store->name())) {
393 ua->send_msg("%s\n", store->name());
401 static bool typescmd(UAContext *ua, const char *cmd)
403 ua->send_msg("Backup\n");
404 ua->send_msg("Restore\n");
405 ua->send_msg("Admin\n");
406 ua->send_msg("Verify\n");
407 ua->send_msg("Migrate\n");
413 * If this command is called, it tells the director that we
414 * are a program that wants a sort of API, and hence,
415 * we will probably suppress certain output, include more
416 * error codes, and most of all send back a good number
417 * of new signals that indicate whether or not the command
420 static bool api_cmd(UAContext *ua, const char *cmd)
423 ua->api = atoi(ua->argk[1]);
430 static int client_backups_handler(void *ctx, int num_field, char **row)
432 UAContext *ua = (UAContext *)ctx;
433 ua->send_msg("| %s | %s | %s | %s | %s | %s | %s | %s |\n",
434 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
439 * Return the backups for this client
441 * .backups client=xxx fileset=yyy
444 static bool backupscmd(UAContext *ua, const char *cmd)
446 if (!open_client_db(ua)) {
449 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 ||
450 strcmp(ua->argk[2], "fileset") != 0) {
453 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
454 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
455 ua->error_msg(_("Access to specified Client or FileSet not allowed.\n"));
458 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
459 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
460 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
466 static int sql_handler(void *ctx, int num_field, char **row)
468 UAContext *ua = (UAContext *)ctx;
469 POOL_MEM rows(PM_MESSAGE);
471 for (int i=0; num_field--; i++) {
473 pm_strcpy(rows, NPRT(row[0]));
475 pm_strcat(rows, NPRT(row[i]));
477 pm_strcat(rows, "\t");
479 if (!rows.c_str() || !*rows.c_str()) {
482 ua->send_msg("%s", rows.c_str());
487 static bool sql_cmd(UAContext *ua, const char *cmd)
490 if (!open_client_db(ua)) {
493 index = find_arg_with_value(ua, "query");
495 ua->error_msg(_("query keyword not found.\n"));
498 if (!db_sql_query(ua->db, ua->argv[index], sql_handler, (void *)ua)) {
499 Dmsg1(100, "Query failed: ERR=%s\n", db_strerror(ua->db));
500 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
508 static bool levelscmd(UAContext *ua, const char *cmd)
510 ua->send_msg("Incremental\n");
511 ua->send_msg("Full\n");
512 ua->send_msg("Differential\n");
513 ua->send_msg("VirtualFull\n");
514 ua->send_msg("Catalog\n");
515 ua->send_msg("InitCatalog\n");
516 ua->send_msg("VolumeToCatalog\n");
521 * Return default values for a job
523 static bool defaultscmd(UAContext *ua, const char *cmd)
531 if (ua->argc != 2 || !ua->argv[1]) {
536 if (strcmp(ua->argk[1], "job") == 0) {
537 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
540 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
543 ua->send_msg("job=%s", job->name());
544 ua->send_msg("pool=%s", job->pool->name());
545 ua->send_msg("messages=%s", job->messages->name());
546 ua->send_msg("client=%s", job->client->name());
547 get_job_storage(&store, job, NULL);
548 ua->send_msg("storage=%s", store.store->name());
549 ua->send_msg("where=%s", job->RestoreWhere?job->RestoreWhere:"");
550 ua->send_msg("level=%s", level_to_str(job->JobLevel));
551 ua->send_msg("type=%s", job_type_to_str(job->JobType));
552 ua->send_msg("fileset=%s", job->fileset->name());
553 ua->send_msg("enabled=%d", job->enabled);
554 ua->send_msg("catalog=%s", job->client->catalog->name());
557 /* Client defaults */
558 else if (strcmp(ua->argk[1], "client") == 0) {
559 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
562 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
564 ua->send_msg("client=%s", client->name());
565 ua->send_msg("address=%s", client->address);
566 ua->send_msg("fdport=%d", client->FDport);
567 ua->send_msg("file_retention=%s", edit_uint64(client->FileRetention, ed1));
568 ua->send_msg("job_retention=%s", edit_uint64(client->JobRetention, ed1));
569 ua->send_msg("autoprune=%d", client->AutoPrune);
570 ua->send_msg("catalog=%s", client->catalog->name());
573 /* Storage defaults */
574 else if (strcmp(ua->argk[1], "storage") == 0) {
575 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
578 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
581 ua->send_msg("storage=%s", storage->name());
582 ua->send_msg("address=%s", storage->address);
583 ua->send_msg("enabled=%d", storage->enabled);
584 ua->send_msg("media_type=%s", storage->media_type);
585 ua->send_msg("sdport=%d", storage->SDport);
586 device = (DEVICE *)storage->device->first();
587 ua->send_msg("device=%s", device->name());
588 if (storage->device->size() > 1) {
589 while ((device = (DEVICE *)storage->device->next())) {
590 ua->send_msg(",%s", device->name());
596 else if (strcmp(ua->argk[1], "pool") == 0) {
597 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
600 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
602 ua->send_msg("pool=%s", pool->name());
603 ua->send_msg("pool_type=%s", pool->pool_type);
604 ua->send_msg("label_format=%s", pool->label_format?pool->label_format:"");
605 ua->send_msg("use_volume_once=%d", pool->use_volume_once);
606 ua->send_msg("purge_oldest_volume=%d", pool->purge_oldest_volume);
607 ua->send_msg("recycle_oldest_volume=%d", pool->recycle_oldest_volume);
608 ua->send_msg("recycle_current_volume=%d", pool->recycle_current_volume);
609 ua->send_msg("max_volumes=%d", pool->max_volumes);
610 ua->send_msg("vol_retention=%s", edit_uint64(pool->VolRetention, ed1));
611 ua->send_msg("vol_use_duration=%s", edit_uint64(pool->VolUseDuration, ed1));
612 ua->send_msg("max_vol_jobs=%d", pool->MaxVolJobs);
613 ua->send_msg("max_vol_files=%d", pool->MaxVolFiles);
614 ua->send_msg("max_vol_bytes=%s", edit_uint64(pool->MaxVolBytes, ed1));
615 ua->send_msg("auto_prune=%d", pool->AutoPrune);
616 ua->send_msg("recycle=%d", pool->Recycle);