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 bsendmsg(ua, _("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 bsendmsg(ua, "%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 bsendmsg(ua, "%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 bsendmsg(ua, "%s\n", client->name());
218 static bool msgscmd(UAContext *ua, const char *cmd)
222 foreach_res(msgs, R_MSGS) {
223 bsendmsg(ua, "%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 bsendmsg(ua, "%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 bsendmsg(ua, "%s\n", store->name());
256 static bool typescmd(UAContext *ua, const char *cmd)
258 bsendmsg(ua, "Backup\n");
259 bsendmsg(ua, "Restore\n");
260 bsendmsg(ua, "Admin\n");
261 bsendmsg(ua, "Verify\n");
262 bsendmsg(ua, "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 bsendmsg(ua, "| %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])) {
312 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
313 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
314 bsendmsg(ua, _("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
320 static int sql_handler(void *ctx, int num_field, char **row)
322 UAContext *ua = (UAContext *)ctx;
323 POOL_MEM rows(PM_MESSAGE);
325 for (int i=0; num_field--; i++) {
327 pm_strcpy(rows, row[0]);
329 pm_strcat(rows, row[i]);
331 pm_strcat(rows, "\t");
333 bsendmsg(ua, rows.c_str());
337 static bool sql_cmd(UAContext *ua, const char *cmd)
339 if (!open_client_db(ua)) {
342 if (!db_sql_query(ua->db, ua->argk[1], sql_handler, (void *)ua)) {
343 bsendmsg(ua, _("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
351 static bool levelscmd(UAContext *ua, const char *cmd)
353 bsendmsg(ua, "Incremental\n");
354 bsendmsg(ua, "Full\n");
355 bsendmsg(ua, "Differential\n");
356 bsendmsg(ua, "Catalog\n");
357 bsendmsg(ua, "InitCatalog\n");
358 bsendmsg(ua, "VolumeToCatalog\n");
363 * Return default values for a job
365 static bool defaultscmd(UAContext *ua, const char *cmd)
372 if (ua->argc != 2 || !ua->argv[1]) {
377 if (strcmp(ua->argk[1], "job") == 0) {
378 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
381 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
384 bsendmsg(ua, "job=%s", job->name());
385 bsendmsg(ua, "pool=%s", job->pool->name());
386 bsendmsg(ua, "messages=%s", job->messages->name());
387 bsendmsg(ua, "client=%s", job->client->name());
388 get_job_storage(&store, job, NULL);
389 bsendmsg(ua, "storage=%s", store.store->name());
390 bsendmsg(ua, "where=%s", job->RestoreWhere?job->RestoreWhere:"");
391 bsendmsg(ua, "level=%s", level_to_str(job->JobLevel));
392 bsendmsg(ua, "type=%s", job_type_to_str(job->JobType));
393 bsendmsg(ua, "fileset=%s", job->fileset->name());
394 bsendmsg(ua, "enabled=%d", job->enabled);
395 bsendmsg(ua, "catalog=%s", job->client->catalog->name());
398 /* Client defaults */
399 else if (strcmp(ua->argk[1], "client") == 0) {
400 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
403 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
405 bsendmsg(ua, "client=%s", client->name());
406 bsendmsg(ua, "address=%s", client->address);
407 bsendmsg(ua, "fdport=%d", client->FDport);
408 bsendmsg(ua, "file_retention=%d", client->FileRetention);
409 bsendmsg(ua, "job_retention=%d", client->JobRetention);
410 bsendmsg(ua, "autoprune=%d", client->AutoPrune);
411 bsendmsg(ua, "catalog=%s", client->catalog->name());
414 /* Storage defaults */
415 else if (strcmp(ua->argk[1], "storage") == 0) {
416 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
419 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
422 bsendmsg(ua, "storage=%s", storage->name());
423 bsendmsg(ua, "address=%s", storage->address);
424 bsendmsg(ua, "enabled=%d", storage->enabled);
425 bsendmsg(ua, "media_type=%s", storage->media_type);
426 bsendmsg(ua, "sdport=%d", storage->SDport);
427 device = (DEVICE *)storage->device->first();
428 bsendmsg(ua, "device=%s", device->name());
429 if (storage->device->size() > 1) {
430 while ((device = (DEVICE *)storage->device->next())) {
431 bsendmsg(ua, ",%s", device->name());
437 else if (strcmp(ua->argk[1], "pool") == 0) {
438 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
441 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
443 bsendmsg(ua, "pool=%s", pool->name());
444 bsendmsg(ua, "pool_type=%s", pool->pool_type);
445 bsendmsg(ua, "label_format=%s", pool->label_format?pool->label_format:"");
446 bsendmsg(ua, "use_volume_once=%d", pool->use_volume_once);
447 bsendmsg(ua, "purge_oldest_volume=%d", pool->purge_oldest_volume);
448 bsendmsg(ua, "recycle_oldest_volume=%d", pool->recycle_oldest_volume);
449 bsendmsg(ua, "recycle_current_volume=%d", pool->recycle_current_volume);
450 bsendmsg(ua, "max_volumes=%d", pool->max_volumes);
451 bsendmsg(ua, "vol_retention=%d", pool->VolRetention);
452 bsendmsg(ua, "vol_use_duration=%d", pool->VolUseDuration);
453 bsendmsg(ua, "max_vol_jobs=%d", pool->MaxVolJobs);
454 bsendmsg(ua, "max_vol_files=%d", pool->MaxVolFiles);
455 bsendmsg(ua, "max_vol_bytes=%d", pool->MaxVolBytes);
456 bsendmsg(ua, "auto_prune=%d", pool->AutoPrune);
457 bsendmsg(ua, "recycle=%d", pool->Recycle);