3 * Bacula Director -- User Agent Commands
4 * These are "dot" commands, i.e. commands preceded
5 * by a period. These commands are meant to be used
6 * by a program, so there is no prompting, and the
7 * returned results are (supposed to be) predictable.
9 * Kern Sibbald, April MMII
14 Copyright (C) 2002-2006 Kern Sibbald
16 This program is free software; you can redistribute it and/or
17 modify it under the terms of the GNU General Public License
18 version 2 as amended with additional clauses defined in the
19 file LICENSE in the main source directory.
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 the file LICENSE for additional details.
31 /* Imported variables */
34 extern struct s_res resources[];
35 extern const char *client_backups;
37 /* Imported functions */
38 extern void do_messages(UAContext *ua, const char *cmd);
39 extern int quit_cmd(UAContext *ua, const char *cmd);
40 extern int qhelp_cmd(UAContext *ua, const char *cmd);
41 extern int qstatus_cmd(UAContext *ua, const char *cmd);
43 /* Forward referenced functions */
44 static int diecmd(UAContext *ua, const char *cmd);
45 static int jobscmd(UAContext *ua, const char *cmd);
46 static int filesetscmd(UAContext *ua, const char *cmd);
47 static int clientscmd(UAContext *ua, const char *cmd);
48 static int msgscmd(UAContext *ua, const char *cmd);
49 static int poolscmd(UAContext *ua, const char *cmd);
50 static int storagecmd(UAContext *ua, const char *cmd);
51 static int defaultscmd(UAContext *ua, const char *cmd);
52 static int typescmd(UAContext *ua, const char *cmd);
53 static int backupscmd(UAContext *ua, const char *cmd);
54 static int levelscmd(UAContext *ua, const char *cmd);
55 static int getmsgscmd(UAContext *ua, const char *cmd);
57 struct cmdstruct { const char *key; int (*func)(UAContext *ua, const char *cmd); const char *help; };
58 static struct cmdstruct commands[] = {
59 { NT_(".die"), diecmd, NULL},
60 { NT_(".jobs"), jobscmd, NULL},
61 { NT_(".filesets"), filesetscmd, NULL},
62 { NT_(".clients"), clientscmd, NULL},
63 { NT_(".msgs"), msgscmd, NULL},
64 { NT_(".pools"), poolscmd, NULL},
65 { NT_(".types"), typescmd, NULL},
66 { NT_(".backups"), backupscmd, NULL},
67 { NT_(".levels"), levelscmd, NULL},
68 { NT_(".status"), qstatus_cmd, NULL},
69 { NT_(".storage"), storagecmd, NULL},
70 { NT_(".defaults"), defaultscmd, NULL},
71 { NT_(".messages"), getmsgscmd, NULL},
72 { NT_(".help"), qhelp_cmd, NULL},
73 { NT_(".quit"), quit_cmd, NULL},
74 { NT_(".exit"), quit_cmd, NULL}
76 #define comsize (sizeof(commands)/sizeof(struct cmdstruct))
79 * Execute a command from the UA
81 int do_a_dot_command(UAContext *ua, const char *cmd)
89 Dmsg1(1400, "Dot command: %s\n", ua->UA_sock->msg);
94 len = strlen(ua->argk[0]);
98 for (i=0; i<(int)comsize; i++) { /* search for command */
99 if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
100 stat = (*commands[i].func)(ua, cmd); /* go execute command */
106 pm_strcat(ua->UA_sock->msg, _(": is an illegal command\n"));
107 ua->UA_sock->msglen = strlen(ua->UA_sock->msg);
108 bnet_send(ua->UA_sock);
113 static int getmsgscmd(UAContext *ua, const char *cmd)
115 if (console_msg_pending) {
116 do_messages(ua, cmd);
122 * Create segmentation fault
124 static int diecmd(UAContext *ua, const char *cmd)
129 bsendmsg(ua, _("The Director will segment fault.\n"));
130 a = jcr->JobId; /* ref NULL pointer */
131 jcr->JobId = 1000; /* another ref NULL pointer */
135 static int jobscmd(UAContext *ua, const char *cmd)
139 while ( (job = (JOB *)GetNextRes(R_JOB, (RES *)job)) ) {
140 if (acl_access_ok(ua, Job_ACL, job->hdr.name)) {
141 bsendmsg(ua, "%s\n", job->hdr.name);
148 static int filesetscmd(UAContext *ua, const char *cmd)
152 while ( (fs = (FILESET *)GetNextRes(R_FILESET, (RES *)fs)) ) {
153 if (acl_access_ok(ua, FileSet_ACL, fs->hdr.name)) {
154 bsendmsg(ua, "%s\n", fs->hdr.name);
161 static int clientscmd(UAContext *ua, const char *cmd)
163 CLIENT *client = NULL;
165 while ( (client = (CLIENT *)GetNextRes(R_CLIENT, (RES *)client)) ) {
166 if (acl_access_ok(ua, Client_ACL, client->hdr.name)) {
167 bsendmsg(ua, "%s\n", client->hdr.name);
174 static int msgscmd(UAContext *ua, const char *cmd)
178 while ( (msgs = (MSGS *)GetNextRes(R_MSGS, (RES *)msgs)) ) {
179 bsendmsg(ua, "%s\n", msgs->hdr.name);
185 static int poolscmd(UAContext *ua, const char *cmd)
189 while ( (pool = (POOL *)GetNextRes(R_POOL, (RES *)pool)) ) {
190 if (acl_access_ok(ua, Pool_ACL, pool->hdr.name)) {
191 bsendmsg(ua, "%s\n", pool->hdr.name);
198 static int storagecmd(UAContext *ua, const char *cmd)
202 while ( (store = (STORE *)GetNextRes(R_STORAGE, (RES *)store)) ) {
203 if (acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
204 bsendmsg(ua, "%s\n", store->hdr.name);
212 static int typescmd(UAContext *ua, const char *cmd)
214 bsendmsg(ua, "Backup\n");
215 bsendmsg(ua, "Restore\n");
216 bsendmsg(ua, "Admin\n");
217 bsendmsg(ua, "Verify\n");
221 static int client_backups_handler(void *ctx, int num_field, char **row)
223 UAContext *ua = (UAContext *)ctx;
224 bsendmsg(ua, "| %s | %s | %s | %s | %s | %s | %s |\n",
225 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7]);
229 static int backupscmd(UAContext *ua, const char *cmd)
234 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 || strcmp(ua->argk[2], "fileset") != 0) {
237 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
238 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
241 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
242 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
243 bsendmsg(ua, _("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
250 static int levelscmd(UAContext *ua, const char *cmd)
252 bsendmsg(ua, "Incremental\n");
253 bsendmsg(ua, "Full\n");
254 bsendmsg(ua, "Differential\n");
255 bsendmsg(ua, "Catalog\n");
256 bsendmsg(ua, "InitCatalog\n");
257 bsendmsg(ua, "VolumeToCatalog\n");
262 * Return default values for a job
264 static int defaultscmd(UAContext *ua, const char *cmd)
271 if (ua->argc != 2 || !ua->argv[1]) {
276 if (strcmp(ua->argk[1], "job") == 0) {
277 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
280 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
283 bsendmsg(ua, "job=%s", job->hdr.name);
284 bsendmsg(ua, "pool=%s", job->pool->hdr.name);
285 bsendmsg(ua, "messages=%s", job->messages->hdr.name);
286 bsendmsg(ua, "client=%s", job->client->hdr.name);
287 store = (STORE *)job->storage->first();
288 bsendmsg(ua, "storage=%s", store->hdr.name);
289 bsendmsg(ua, "where=%s", job->RestoreWhere?job->RestoreWhere:"");
290 bsendmsg(ua, "level=%s", level_to_str(job->JobLevel));
291 bsendmsg(ua, "type=%s", job_type_to_str(job->JobType));
292 bsendmsg(ua, "fileset=%s", job->fileset->hdr.name);
293 bsendmsg(ua, "enabled=%d", job->enabled);
296 /* Client defaults */
297 else if (strcmp(ua->argk[1], "client") == 0) {
298 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
301 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
303 bsendmsg(ua, "client=%s", client->hdr.name);
304 bsendmsg(ua, "address=%s", client->address);
305 bsendmsg(ua, "fdport=%d", client->FDport);
306 bsendmsg(ua, "file_retention=%d", client->FileRetention);
307 bsendmsg(ua, "job_retention=%d", client->JobRetention);
308 bsendmsg(ua, "autoprune=%d", client->AutoPrune);
311 /* Storage defaults */
312 else if (strcmp(ua->argk[1], "storage") == 0) {
313 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
316 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
319 bsendmsg(ua, "storage=%s", storage->hdr.name);
320 bsendmsg(ua, "address=%s", storage->address);
321 bsendmsg(ua, "enabled=%d", storage->enabled);
322 bsendmsg(ua, "media_type=%s", storage->media_type);
323 bsendmsg(ua, "sdport=%d", storage->SDport);
324 device = (DEVICE *)storage->device->first();
325 bsendmsg(ua, "device=%s", device->hdr.name);
326 if (storage->device->size() > 1) {
327 while ((device = (DEVICE *)storage->device->next()))
328 bsendmsg(ua, ",%s", device->hdr.name);
333 else if (strcmp(ua->argk[1], "pool") == 0) {
334 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
337 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
339 bsendmsg(ua, "pool=%s", pool->hdr.name);
340 bsendmsg(ua, "pool_type=%s", pool->pool_type);
341 bsendmsg(ua, "label_format=%s", pool->label_format?pool->label_format:"");
342 bsendmsg(ua, "use_volume_once=%d", pool->use_volume_once);
343 bsendmsg(ua, "purge_oldest_volume=%d", pool->purge_oldest_volume);
344 bsendmsg(ua, "recycle_oldest_volume=%d", pool->recycle_oldest_volume);
345 bsendmsg(ua, "recycle_current_volume=%d", pool->recycle_current_volume);
346 bsendmsg(ua, "max_volumes=%d", pool->max_volumes);
347 bsendmsg(ua, "vol_retention=%d", pool->VolRetention);
348 bsendmsg(ua, "vol_use_duration=%d", pool->VolUseDuration);
349 bsendmsg(ua, "max_vol_jobs=%d", pool->MaxVolJobs);
350 bsendmsg(ua, "max_vol_files=%d", pool->MaxVolFiles);
351 bsendmsg(ua, "max_vol_bytes=%d", pool->MaxVolBytes);
352 bsendmsg(ua, "auto_prune=%d", pool->AutoPrune);
353 bsendmsg(ua, "recycle=%d", pool->Recycle);