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[];
36 /* Imported functions */
37 extern void do_messages(UAContext *ua, const char *cmd);
38 extern int quit_cmd(UAContext *ua, const char *cmd);
39 extern int qhelp_cmd(UAContext *ua, const char *cmd);
40 extern int qstatus_cmd(UAContext *ua, const char *cmd);
42 /* Forward referenced functions */
43 static int diecmd(UAContext *ua, const char *cmd);
44 static int jobscmd(UAContext *ua, const char *cmd);
45 static int filesetscmd(UAContext *ua, const char *cmd);
46 static int clientscmd(UAContext *ua, const char *cmd);
47 static int msgscmd(UAContext *ua, const char *cmd);
48 static int poolscmd(UAContext *ua, const char *cmd);
49 static int storagecmd(UAContext *ua, const char *cmd);
50 static int defaultscmd(UAContext *ua, const char *cmd);
51 static int typescmd(UAContext *ua, const char *cmd);
52 static int backupscmd(UAContext *ua, const char *cmd);
53 static int levelscmd(UAContext *ua, const char *cmd);
54 static int getmsgscmd(UAContext *ua, const char *cmd);
56 struct cmdstruct { const char *key; int (*func)(UAContext *ua, const char *cmd); const char *help; };
57 static struct cmdstruct commands[] = {
58 { NT_(".die"), diecmd, NULL},
59 { NT_(".jobs"), jobscmd, NULL},
60 { NT_(".filesets"), filesetscmd, NULL},
61 { NT_(".clients"), clientscmd, NULL},
62 { NT_(".msgs"), msgscmd, NULL},
63 { NT_(".pools"), poolscmd, NULL},
64 { NT_(".types"), typescmd, NULL},
65 { NT_(".backups"), backupscmd, NULL},
66 { NT_(".levels"), levelscmd, NULL},
67 { NT_(".status"), qstatus_cmd, NULL},
68 { NT_(".storage"), storagecmd, NULL},
69 { NT_(".defaults"), defaultscmd, NULL},
70 { NT_(".messages"), getmsgscmd, NULL},
71 { NT_(".help"), qhelp_cmd, NULL},
72 { NT_(".quit"), quit_cmd, NULL},
73 { NT_(".exit"), quit_cmd, NULL}
75 #define comsize (sizeof(commands)/sizeof(struct cmdstruct))
78 * Execute a command from the UA
80 int do_a_dot_command(UAContext *ua, const char *cmd)
88 Dmsg1(1400, "Dot command: %s\n", ua->UA_sock->msg);
93 len = strlen(ua->argk[0]);
97 for (i=0; i<(int)comsize; i++) { /* search for command */
98 if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
99 stat = (*commands[i].func)(ua, cmd); /* go execute command */
105 pm_strcat(ua->UA_sock->msg, _(": is an illegal command\n"));
106 ua->UA_sock->msglen = strlen(ua->UA_sock->msg);
107 bnet_send(ua->UA_sock);
112 static int getmsgscmd(UAContext *ua, const char *cmd)
114 if (console_msg_pending) {
115 do_messages(ua, cmd);
121 * Create segmentation fault
123 static int diecmd(UAContext *ua, const char *cmd)
128 bsendmsg(ua, _("The Director will segment fault.\n"));
129 a = jcr->JobId; /* ref NULL pointer */
130 jcr->JobId = 1000; /* another ref NULL pointer */
134 static int jobscmd(UAContext *ua, const char *cmd)
138 while ( (job = (JOB *)GetNextRes(R_JOB, (RES *)job)) ) {
139 if (acl_access_ok(ua, Job_ACL, job->hdr.name)) {
140 bsendmsg(ua, "%s\n", job->hdr.name);
147 static int filesetscmd(UAContext *ua, const char *cmd)
151 while ( (fs = (FILESET *)GetNextRes(R_FILESET, (RES *)fs)) ) {
152 if (acl_access_ok(ua, FileSet_ACL, fs->hdr.name)) {
153 bsendmsg(ua, "%s\n", fs->hdr.name);
160 static int clientscmd(UAContext *ua, const char *cmd)
162 CLIENT *client = NULL;
164 while ( (client = (CLIENT *)GetNextRes(R_CLIENT, (RES *)client)) ) {
165 if (acl_access_ok(ua, Client_ACL, client->hdr.name)) {
166 bsendmsg(ua, "%s\n", client->hdr.name);
173 static int msgscmd(UAContext *ua, const char *cmd)
177 while ( (msgs = (MSGS *)GetNextRes(R_MSGS, (RES *)msgs)) ) {
178 bsendmsg(ua, "%s\n", msgs->hdr.name);
184 static int poolscmd(UAContext *ua, const char *cmd)
188 while ( (pool = (POOL *)GetNextRes(R_POOL, (RES *)pool)) ) {
189 if (acl_access_ok(ua, Pool_ACL, pool->hdr.name)) {
190 bsendmsg(ua, "%s\n", pool->hdr.name);
197 static int storagecmd(UAContext *ua, const char *cmd)
201 while ( (store = (STORE *)GetNextRes(R_STORAGE, (RES *)store)) ) {
202 if (acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
203 bsendmsg(ua, "%s\n", store->hdr.name);
211 static int typescmd(UAContext *ua, const char *cmd)
213 bsendmsg(ua, "Backup\n");
214 bsendmsg(ua, "Restore\n");
215 bsendmsg(ua, "Admin\n");
216 bsendmsg(ua, "Verify\n");
220 static int client_backups_handler(void *ctx, int num_field, char **row)
222 UAContext *ua = (UAContext *)ctx;
223 bsendmsg(ua, "| %s | %s | %s | %s | %s | %s | %s |\n",
224 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7]);
228 static int backupscmd(UAContext *ua, const char *cmd)
233 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 || strcmp(ua->argk[2], "fileset") != 0) {
236 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
237 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
240 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
241 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
242 bsendmsg(ua, _("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
249 static int levelscmd(UAContext *ua, const char *cmd)
251 bsendmsg(ua, "Incremental\n");
252 bsendmsg(ua, "Full\n");
253 bsendmsg(ua, "Differential\n");
254 bsendmsg(ua, "Catalog\n");
255 bsendmsg(ua, "InitCatalog\n");
256 bsendmsg(ua, "VolumeToCatalog\n");
261 * Return default values for a job
263 static int defaultscmd(UAContext *ua, const char *cmd)
270 if (ua->argc != 2 || !ua->argv[1]) {
275 if (strcmp(ua->argk[1], "job") == 0) {
276 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
279 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
282 bsendmsg(ua, "job=%s", job->hdr.name);
283 bsendmsg(ua, "pool=%s", job->pool->hdr.name);
284 bsendmsg(ua, "messages=%s", job->messages->hdr.name);
285 bsendmsg(ua, "client=%s", job->client->hdr.name);
286 store = (STORE *)job->storage->first();
287 bsendmsg(ua, "storage=%s", store->hdr.name);
288 bsendmsg(ua, "where=%s", job->RestoreWhere?job->RestoreWhere:"");
289 bsendmsg(ua, "level=%s", level_to_str(job->JobLevel));
290 bsendmsg(ua, "type=%s", job_type_to_str(job->JobType));
291 bsendmsg(ua, "fileset=%s", job->fileset->hdr.name);
292 bsendmsg(ua, "enabled=%d", job->enabled);
295 /* Client defaults */
296 else if (strcmp(ua->argk[1], "client") == 0) {
297 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
300 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
302 bsendmsg(ua, "client=%s", client->hdr.name);
303 bsendmsg(ua, "address=%s", client->address);
304 bsendmsg(ua, "fdport=%d", client->FDport);
305 bsendmsg(ua, "file_retention=%d", client->FileRetention);
306 bsendmsg(ua, "job_retention=%d", client->JobRetention);
307 bsendmsg(ua, "autoprune=%d", client->AutoPrune);
310 /* Storage defaults */
311 else if (strcmp(ua->argk[1], "storage") == 0) {
312 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
315 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
318 bsendmsg(ua, "storage=%s", storage->hdr.name);
319 bsendmsg(ua, "address=%s", storage->address);
320 bsendmsg(ua, "enabled=%d", storage->enabled);
321 bsendmsg(ua, "media_type=%s", storage->media_type);
322 bsendmsg(ua, "sdport=%d", storage->SDport);
323 device = (DEVICE *)storage->device->first();
324 bsendmsg(ua, "device=%s", device->hdr.name);
325 if (storage->device->size() > 1) {
326 while ((device = (DEVICE *)storage->device->next()))
327 bsendmsg(ua, ",%s", device->hdr.name);
332 else if (strcmp(ua->argk[1], "pool") == 0) {
333 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
336 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
338 bsendmsg(ua, "pool=%s", pool->hdr.name);
339 bsendmsg(ua, "pool_type=%s", pool->pool_type);
340 bsendmsg(ua, "label_format=%s", pool->label_format?pool->label_format:"");
341 bsendmsg(ua, "use_volume_once=%d", pool->use_volume_once);
342 bsendmsg(ua, "purge_oldest_volume=%d", pool->purge_oldest_volume);
343 bsendmsg(ua, "recycle_oldest_volume=%d", pool->recycle_oldest_volume);
344 bsendmsg(ua, "recycle_current_volume=%d", pool->recycle_current_volume);
345 bsendmsg(ua, "max_volumes=%d", pool->max_volumes);
346 bsendmsg(ua, "vol_retention=%d", pool->VolRetention);
347 bsendmsg(ua, "vol_use_duration=%d", pool->VolUseDuration);
348 bsendmsg(ua, "max_vol_jobs=%d", pool->MaxVolJobs);
349 bsendmsg(ua, "max_vol_files=%d", pool->MaxVolFiles);
350 bsendmsg(ua, "max_vol_bytes=%d", pool->MaxVolBytes);
351 bsendmsg(ua, "auto_prune=%d", pool->AutoPrune);
352 bsendmsg(ua, "recycle=%d", pool->Recycle);