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 dot_quit_cmd(UAContext *ua, const char *cmd);
72 static bool dot_help_cmd(UAContext *ua, const char *cmd);
74 struct cmdstruct { const char *key; bool (*func)(UAContext *ua, const char *cmd); const char *help; };
75 static struct cmdstruct commands[] = {
76 { NT_(".api"), api_cmd, NULL},
77 { NT_(".backups"), backupscmd, NULL},
78 { NT_(".clients"), clientscmd, NULL},
79 { NT_(".defaults"), defaultscmd, NULL},
80 { NT_(".die"), diecmd, NULL},
81 { NT_(".exit"), dot_quit_cmd, NULL},
82 { NT_(".filesets"), filesetscmd, NULL},
83 { NT_(".help"), dot_help_cmd, NULL},
84 { NT_(".jobs"), jobscmd, NULL},
85 { NT_(".levels"), levelscmd, NULL},
86 { NT_(".messages"), getmsgscmd, NULL},
87 { NT_(".msgs"), msgscmd, NULL},
88 { NT_(".pools"), poolscmd, NULL},
89 { NT_(".quit"), dot_quit_cmd, NULL},
90 { NT_(".status"), dot_status_cmd, NULL},
91 { NT_(".storage"), storagecmd, NULL},
92 { NT_(".types"), typescmd, NULL}
94 #define comsize ((int)(sizeof(commands)/sizeof(struct cmdstruct)))
97 * Execute a command from the UA
99 int do_a_dot_command(UAContext *ua, const char *cmd)
105 BSOCK *user = ua->UA_sock;
107 Dmsg1(1400, "Dot command: %s\n", user->msg);
112 len = strlen(ua->argk[0]);
114 if (ua->api) user->signal(BNET_CMD_BEGIN);
115 if (ua->api) user->signal(BNET_CMD_OK);
116 return 1; /* no op */
118 for (i=0; i<comsize; i++) { /* search for command */
119 if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
121 /* Check if command permitted, but "quit" is always OK */
122 if (strcmp(ua->argk[0], NT_(".quit")) != 0 &&
123 !acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
127 if (ua->api) user->signal(BNET_CMD_BEGIN);
128 ok = (*commands[i].func)(ua, cmd); /* go execute command */
135 pm_strcat(user->msg, _(": is an invalid command.\n"));
136 user->msglen = strlen(user->msg);
139 if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
143 static bool dot_quit_cmd(UAContext *ua, const char *cmd)
149 static bool dot_help_cmd(UAContext *ua, const char *cmd)
155 static bool getmsgscmd(UAContext *ua, const char *cmd)
157 if (console_msg_pending) {
158 do_messages(ua, cmd);
164 * Create segmentation fault
166 static bool diecmd(UAContext *ua, const char *cmd)
171 bsendmsg(ua, _("The Director will segment fault.\n"));
172 a = jcr->JobId; /* ref NULL pointer */
173 jcr->JobId = 1000; /* another ref NULL pointer */
177 static bool jobscmd(UAContext *ua, const char *cmd)
181 foreach_res(job, R_JOB) {
182 if (acl_access_ok(ua, Job_ACL, job->name())) {
183 bsendmsg(ua, "%s\n", job->name());
190 static bool filesetscmd(UAContext *ua, const char *cmd)
194 foreach_res(fs, R_FILESET) {
195 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
196 bsendmsg(ua, "%s\n", fs->name());
203 static bool clientscmd(UAContext *ua, const char *cmd)
207 foreach_res(client, R_CLIENT) {
208 if (acl_access_ok(ua, Client_ACL, client->name())) {
209 bsendmsg(ua, "%s\n", client->name());
216 static bool msgscmd(UAContext *ua, const char *cmd)
220 foreach_res(msgs, R_MSGS) {
221 bsendmsg(ua, "%s\n", msgs->name());
227 static bool poolscmd(UAContext *ua, const char *cmd)
231 foreach_res(pool, R_POOL) {
232 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
233 bsendmsg(ua, "%s\n", pool->name());
240 static bool storagecmd(UAContext *ua, const char *cmd)
244 foreach_res(store, R_STORAGE) {
245 if (acl_access_ok(ua, Storage_ACL, store->name())) {
246 bsendmsg(ua, "%s\n", store->name());
254 static bool typescmd(UAContext *ua, const char *cmd)
256 bsendmsg(ua, "Backup\n");
257 bsendmsg(ua, "Restore\n");
258 bsendmsg(ua, "Admin\n");
259 bsendmsg(ua, "Verify\n");
260 bsendmsg(ua, "Migrate\n");
264 static int client_backups_handler(void *ctx, int num_field, char **row)
266 UAContext *ua = (UAContext *)ctx;
267 bsendmsg(ua, "| %s | %s | %s | %s | %s | %s | %s | %s |\n",
268 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
273 * If this command is called, it tells the director that we
274 * are a program that wants a sort of API, and hence,
275 * we will probably suppress certain output, include more
276 * error codes, and most of all send back a good number
277 * of new signals that indicate whether or not the command
280 static bool api_cmd(UAContext *ua, const char *cmd)
283 ua->api = atoi(ua->argk[1]);
291 * Return the backups for this client
293 * .backups client=xxx fileset=yyy
296 static bool backupscmd(UAContext *ua, const char *cmd)
298 if (!open_client_db(ua)) {
301 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 ||
302 strcmp(ua->argk[2], "fileset") != 0) {
305 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
306 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
309 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
310 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
311 bsendmsg(ua, _("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
319 static bool levelscmd(UAContext *ua, const char *cmd)
321 bsendmsg(ua, "Incremental\n");
322 bsendmsg(ua, "Full\n");
323 bsendmsg(ua, "Differential\n");
324 bsendmsg(ua, "Catalog\n");
325 bsendmsg(ua, "InitCatalog\n");
326 bsendmsg(ua, "VolumeToCatalog\n");
331 * Return default values for a job
333 static bool defaultscmd(UAContext *ua, const char *cmd)
340 if (ua->argc != 2 || !ua->argv[1]) {
345 if (strcmp(ua->argk[1], "job") == 0) {
346 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
349 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
352 bsendmsg(ua, "job=%s", job->name());
353 bsendmsg(ua, "pool=%s", job->pool->name());
354 bsendmsg(ua, "messages=%s", job->messages->name());
355 bsendmsg(ua, "client=%s", job->client->name());
356 get_job_storage(&store, job, NULL);
357 bsendmsg(ua, "storage=%s", store.store->name());
358 bsendmsg(ua, "where=%s", job->RestoreWhere?job->RestoreWhere:"");
359 bsendmsg(ua, "level=%s", level_to_str(job->JobLevel));
360 bsendmsg(ua, "type=%s", job_type_to_str(job->JobType));
361 bsendmsg(ua, "fileset=%s", job->fileset->name());
362 bsendmsg(ua, "enabled=%d", job->enabled);
363 bsendmsg(ua, "catalog=%s", job->client->catalog->name());
366 /* Client defaults */
367 else if (strcmp(ua->argk[1], "client") == 0) {
368 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
371 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
373 bsendmsg(ua, "client=%s", client->name());
374 bsendmsg(ua, "address=%s", client->address);
375 bsendmsg(ua, "fdport=%d", client->FDport);
376 bsendmsg(ua, "file_retention=%d", client->FileRetention);
377 bsendmsg(ua, "job_retention=%d", client->JobRetention);
378 bsendmsg(ua, "autoprune=%d", client->AutoPrune);
379 bsendmsg(ua, "catalog=%s", client->catalog->name());
382 /* Storage defaults */
383 else if (strcmp(ua->argk[1], "storage") == 0) {
384 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
387 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
390 bsendmsg(ua, "storage=%s", storage->name());
391 bsendmsg(ua, "address=%s", storage->address);
392 bsendmsg(ua, "enabled=%d", storage->enabled);
393 bsendmsg(ua, "media_type=%s", storage->media_type);
394 bsendmsg(ua, "sdport=%d", storage->SDport);
395 device = (DEVICE *)storage->device->first();
396 bsendmsg(ua, "device=%s", device->name());
397 if (storage->device->size() > 1) {
398 while ((device = (DEVICE *)storage->device->next())) {
399 bsendmsg(ua, ",%s", device->name());
405 else if (strcmp(ua->argk[1], "pool") == 0) {
406 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
409 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
411 bsendmsg(ua, "pool=%s", pool->name());
412 bsendmsg(ua, "pool_type=%s", pool->pool_type);
413 bsendmsg(ua, "label_format=%s", pool->label_format?pool->label_format:"");
414 bsendmsg(ua, "use_volume_once=%d", pool->use_volume_once);
415 bsendmsg(ua, "purge_oldest_volume=%d", pool->purge_oldest_volume);
416 bsendmsg(ua, "recycle_oldest_volume=%d", pool->recycle_oldest_volume);
417 bsendmsg(ua, "recycle_current_volume=%d", pool->recycle_current_volume);
418 bsendmsg(ua, "max_volumes=%d", pool->max_volumes);
419 bsendmsg(ua, "vol_retention=%d", pool->VolRetention);
420 bsendmsg(ua, "vol_use_duration=%d", pool->VolUseDuration);
421 bsendmsg(ua, "max_vol_jobs=%d", pool->MaxVolJobs);
422 bsendmsg(ua, "max_vol_files=%d", pool->MaxVolFiles);
423 bsendmsg(ua, "max_vol_bytes=%d", pool->MaxVolBytes);
424 bsendmsg(ua, "auto_prune=%d", pool->AutoPrune);
425 bsendmsg(ua, "recycle=%d", pool->Recycle);