2 Bacula® - The Network Backup Solution
4 Copyright (C) 2002-2007 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 plus additions
11 that are listed in the file LICENSE.
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 John Walker.
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 */
47 extern struct s_res resources[];
49 /* Imported functions */
50 extern void do_messages(UAContext *ua, const char *cmd);
51 extern int quit_cmd(UAContext *ua, const char *cmd);
52 extern int qhelp_cmd(UAContext *ua, const char *cmd);
53 extern bool dot_status_cmd(UAContext *ua, const char *cmd);
56 /* Forward referenced functions */
57 static bool diecmd(UAContext *ua, const char *cmd);
58 static bool jobscmd(UAContext *ua, const char *cmd);
59 static bool filesetscmd(UAContext *ua, const char *cmd);
60 static bool clientscmd(UAContext *ua, const char *cmd);
61 static bool msgscmd(UAContext *ua, const char *cmd);
62 static bool poolscmd(UAContext *ua, const char *cmd);
63 static bool storagecmd(UAContext *ua, const char *cmd);
64 static bool defaultscmd(UAContext *ua, const char *cmd);
65 static bool typescmd(UAContext *ua, const char *cmd);
66 static bool backupscmd(UAContext *ua, const char *cmd);
67 static bool levelscmd(UAContext *ua, const char *cmd);
68 static bool getmsgscmd(UAContext *ua, const char *cmd);
70 static bool api_cmd(UAContext *ua, const char *cmd);
71 static bool sql_cmd(UAContext *ua, const char *cmd);
72 static bool dot_quit_cmd(UAContext *ua, const char *cmd);
73 static bool dot_help_cmd(UAContext *ua, const char *cmd);
75 struct cmdstruct { const char *key; bool (*func)(UAContext *ua, const char *cmd); const char *help; };
76 static struct cmdstruct commands[] = {
77 { NT_(".api"), api_cmd, NULL},
78 { NT_(".backups"), backupscmd, NULL},
79 { NT_(".clients"), clientscmd, NULL},
80 { NT_(".defaults"), defaultscmd, NULL},
81 { NT_(".die"), diecmd, NULL},
82 { NT_(".exit"), dot_quit_cmd, NULL},
83 { NT_(".filesets"), filesetscmd, NULL},
84 { NT_(".help"), dot_help_cmd, NULL},
85 { NT_(".jobs"), jobscmd, NULL},
86 { NT_(".levels"), levelscmd, NULL},
87 { NT_(".messages"), getmsgscmd, NULL},
88 { NT_(".msgs"), msgscmd, NULL},
89 { NT_(".pools"), poolscmd, NULL},
90 { NT_(".quit"), dot_quit_cmd, NULL},
91 { NT_(".sql"), sql_cmd, NULL},
92 { NT_(".status"), dot_status_cmd, NULL},
93 { NT_(".storage"), storagecmd, NULL},
94 { NT_(".types"), typescmd, NULL}
96 #define comsize ((int)(sizeof(commands)/sizeof(struct cmdstruct)))
99 * Execute a command from the UA
101 int do_a_dot_command(UAContext *ua, const char *cmd)
107 BSOCK *user = ua->UA_sock;
109 Dmsg1(1400, "Dot command: %s\n", user->msg);
114 len = strlen(ua->argk[0]);
116 if (ua->api) user->signal(BNET_CMD_BEGIN);
117 if (ua->api) user->signal(BNET_CMD_OK);
118 return 1; /* no op */
120 for (i=0; i<comsize; i++) { /* search for command */
121 if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
123 /* Check if command permitted, but "quit" is always OK */
124 if (strcmp(ua->argk[0], NT_(".quit")) != 0 &&
125 !acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
129 if (ua->api) user->signal(BNET_CMD_BEGIN);
130 ok = (*commands[i].func)(ua, cmd); /* go execute command */
137 pm_strcat(user->msg, _(": is an invalid command.\n"));
138 user->msglen = strlen(user->msg);
141 if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
145 static bool dot_quit_cmd(UAContext *ua, const char *cmd)
151 static bool dot_help_cmd(UAContext *ua, const char *cmd)
157 static bool getmsgscmd(UAContext *ua, const char *cmd)
159 if (console_msg_pending) {
160 do_messages(ua, cmd);
166 * Create segmentation fault
168 static bool diecmd(UAContext *ua, const char *cmd)
173 ua->send_msg(_("The Director will segment fault.\n"));
174 a = jcr->JobId; /* ref NULL pointer */
175 jcr->JobId = 1000; /* another ref NULL pointer */
179 static bool jobscmd(UAContext *ua, const char *cmd)
183 foreach_res(job, R_JOB) {
184 if (acl_access_ok(ua, Job_ACL, job->name())) {
185 ua->send_msg("%s\n", job->name());
192 static bool filesetscmd(UAContext *ua, const char *cmd)
196 foreach_res(fs, R_FILESET) {
197 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
198 ua->send_msg("%s\n", fs->name());
205 static bool clientscmd(UAContext *ua, const char *cmd)
209 foreach_res(client, R_CLIENT) {
210 if (acl_access_ok(ua, Client_ACL, client->name())) {
211 ua->send_msg("%s\n", client->name());
218 static bool msgscmd(UAContext *ua, const char *cmd)
222 foreach_res(msgs, R_MSGS) {
223 ua->send_msg("%s\n", msgs->name());
229 static bool poolscmd(UAContext *ua, const char *cmd)
233 foreach_res(pool, R_POOL) {
234 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
235 ua->send_msg("%s\n", pool->name());
242 static bool storagecmd(UAContext *ua, const char *cmd)
246 foreach_res(store, R_STORAGE) {
247 if (acl_access_ok(ua, Storage_ACL, store->name())) {
248 ua->send_msg("%s\n", store->name());
256 static bool typescmd(UAContext *ua, const char *cmd)
258 ua->send_msg("Backup\n");
259 ua->send_msg("Restore\n");
260 ua->send_msg("Admin\n");
261 ua->send_msg("Verify\n");
262 ua->send_msg("Migrate\n");
268 * If this command is called, it tells the director that we
269 * are a program that wants a sort of API, and hence,
270 * we will probably suppress certain output, include more
271 * error codes, and most of all send back a good number
272 * of new signals that indicate whether or not the command
275 static bool api_cmd(UAContext *ua, const char *cmd)
278 ua->api = atoi(ua->argk[1]);
285 static int client_backups_handler(void *ctx, int num_field, char **row)
287 UAContext *ua = (UAContext *)ctx;
288 ua->send_msg("| %s | %s | %s | %s | %s | %s | %s | %s |\n",
289 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
294 * Return the backups for this client
296 * .backups client=xxx fileset=yyy
299 static bool backupscmd(UAContext *ua, const char *cmd)
301 if (!open_client_db(ua)) {
304 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 ||
305 strcmp(ua->argk[2], "fileset") != 0) {
308 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
309 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
310 ua->error_msg(_("Access to specified Client or FileSet not allowed.\n"));
313 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
314 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
315 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
321 static int sql_handler(void *ctx, int num_field, char **row)
323 UAContext *ua = (UAContext *)ctx;
324 POOL_MEM rows(PM_MESSAGE);
326 for (int i=0; num_field--; i++) {
328 pm_strcpy(rows, row[0]);
330 pm_strcat(rows, row[i]);
332 pm_strcat(rows, "\t");
334 ua->send_msg(rows.c_str());
338 static bool sql_cmd(UAContext *ua, const char *cmd)
341 if (!open_client_db(ua)) {
344 index = find_arg_with_value(ua, "query");
346 ua->error_msg(_("query keyword not found.\n"));
349 if (!db_sql_query(ua->db, ua->argv[index], sql_handler, (void *)ua)) {
350 Dmsg1(100, "Query failed: ERR=%s\n", db_strerror(ua->db));
351 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
359 static bool levelscmd(UAContext *ua, const char *cmd)
361 ua->send_msg("Incremental\n");
362 ua->send_msg("Full\n");
363 ua->send_msg("Differential\n");
364 ua->send_msg("Catalog\n");
365 ua->send_msg("InitCatalog\n");
366 ua->send_msg("VolumeToCatalog\n");
371 * Return default values for a job
373 static bool defaultscmd(UAContext *ua, const char *cmd)
381 if (ua->argc != 2 || !ua->argv[1]) {
386 if (strcmp(ua->argk[1], "job") == 0) {
387 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
390 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
393 ua->send_msg("job=%s", job->name());
394 ua->send_msg("pool=%s", job->pool->name());
395 ua->send_msg("messages=%s", job->messages->name());
396 ua->send_msg("client=%s", job->client->name());
397 get_job_storage(&store, job, NULL);
398 ua->send_msg("storage=%s", store.store->name());
399 ua->send_msg("where=%s", job->RestoreWhere?job->RestoreWhere:"");
400 ua->send_msg("level=%s", level_to_str(job->JobLevel));
401 ua->send_msg("type=%s", job_type_to_str(job->JobType));
402 ua->send_msg("fileset=%s", job->fileset->name());
403 ua->send_msg("enabled=%d", job->enabled);
404 ua->send_msg("catalog=%s", job->client->catalog->name());
407 /* Client defaults */
408 else if (strcmp(ua->argk[1], "client") == 0) {
409 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
412 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
414 ua->send_msg("client=%s", client->name());
415 ua->send_msg("address=%s", client->address);
416 ua->send_msg("fdport=%d", client->FDport);
417 ua->send_msg("file_retention=%s", edit_uint64(client->FileRetention, ed1));
418 ua->send_msg("job_retention=%s", edit_uint64(client->JobRetention, ed1));
419 ua->send_msg("autoprune=%d", client->AutoPrune);
420 ua->send_msg("catalog=%s", client->catalog->name());
423 /* Storage defaults */
424 else if (strcmp(ua->argk[1], "storage") == 0) {
425 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
428 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
431 ua->send_msg("storage=%s", storage->name());
432 ua->send_msg("address=%s", storage->address);
433 ua->send_msg("enabled=%d", storage->enabled);
434 ua->send_msg("media_type=%s", storage->media_type);
435 ua->send_msg("sdport=%d", storage->SDport);
436 device = (DEVICE *)storage->device->first();
437 ua->send_msg("device=%s", device->name());
438 if (storage->device->size() > 1) {
439 while ((device = (DEVICE *)storage->device->next())) {
440 ua->send_msg(",%s", device->name());
446 else if (strcmp(ua->argk[1], "pool") == 0) {
447 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
450 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
452 ua->send_msg("pool=%s", pool->name());
453 ua->send_msg("pool_type=%s", pool->pool_type);
454 ua->send_msg("label_format=%s", pool->label_format?pool->label_format:"");
455 ua->send_msg("use_volume_once=%d", pool->use_volume_once);
456 ua->send_msg("purge_oldest_volume=%d", pool->purge_oldest_volume);
457 ua->send_msg("recycle_oldest_volume=%d", pool->recycle_oldest_volume);
458 ua->send_msg("recycle_current_volume=%d", pool->recycle_current_volume);
459 ua->send_msg("max_volumes=%d", pool->max_volumes);
460 ua->send_msg("vol_retention=%s", edit_uint64(pool->VolRetention, ed1));
461 ua->send_msg("vol_use_duration=%s", edit_uint64(pool->VolUseDuration, ed1));
462 ua->send_msg("max_vol_jobs=%d", pool->MaxVolJobs);
463 ua->send_msg("max_vol_files=%d", pool->MaxVolFiles);
464 ua->send_msg("max_vol_bytes=%s", edit_uint64(pool->MaxVolBytes, ed1));
465 ua->send_msg("auto_prune=%d", pool->AutoPrune);
466 ua->send_msg("recycle=%d", pool->Recycle);