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 char my_name[];
36 extern const char *client_backups;
37 extern int console_msg_pending;
39 /* Imported functions */
40 extern void do_messages(UAContext *ua, const char *cmd);
41 extern int quit_cmd(UAContext *ua, const char *cmd);
42 extern int qhelp_cmd(UAContext *ua, const char *cmd);
43 extern int qstatus_cmd(UAContext *ua, const char *cmd);
45 /* Forward referenced functions */
46 static int diecmd(UAContext *ua, const char *cmd);
47 static int jobscmd(UAContext *ua, const char *cmd);
48 static int filesetscmd(UAContext *ua, const char *cmd);
49 static int clientscmd(UAContext *ua, const char *cmd);
50 static int msgscmd(UAContext *ua, const char *cmd);
51 static int poolscmd(UAContext *ua, const char *cmd);
52 static int storagecmd(UAContext *ua, const char *cmd);
53 static int defaultscmd(UAContext *ua, const char *cmd);
54 static int typescmd(UAContext *ua, const char *cmd);
55 static int backupscmd(UAContext *ua, const char *cmd);
56 static int levelscmd(UAContext *ua, const char *cmd);
57 static int getmsgscmd(UAContext *ua, const char *cmd);
59 struct cmdstruct { const char *key; int (*func)(UAContext *ua, const char *cmd); const char *help; };
60 static struct cmdstruct commands[] = {
61 { NT_(".die"), diecmd, NULL},
62 { NT_(".jobs"), jobscmd, NULL},
63 { NT_(".filesets"), filesetscmd, NULL},
64 { NT_(".clients"), clientscmd, NULL},
65 { NT_(".msgs"), msgscmd, NULL},
66 { NT_(".pools"), poolscmd, NULL},
67 { NT_(".types"), typescmd, NULL},
68 { NT_(".backups"), backupscmd, NULL},
69 { NT_(".levels"), levelscmd, NULL},
70 { NT_(".status"), qstatus_cmd, NULL},
71 { NT_(".storage"), storagecmd, NULL},
72 { NT_(".defaults"), defaultscmd, NULL},
73 { NT_(".messages"), getmsgscmd, NULL},
74 { NT_(".help"), qhelp_cmd, NULL},
75 { NT_(".quit"), quit_cmd, NULL},
76 { NT_(".exit"), quit_cmd, NULL}
78 #define comsize (sizeof(commands)/sizeof(struct cmdstruct))
81 * Execute a command from the UA
83 int do_a_dot_command(UAContext *ua, const char *cmd)
91 Dmsg1(1400, "Dot command: %s\n", ua->UA_sock->msg);
96 len = strlen(ua->argk[0]);
100 for (i=0; i<(int)comsize; i++) { /* search for command */
101 if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
102 stat = (*commands[i].func)(ua, cmd); /* go execute command */
108 pm_strcat(ua->UA_sock->msg, _(": is an illegal command\n"));
109 ua->UA_sock->msglen = strlen(ua->UA_sock->msg);
110 bnet_send(ua->UA_sock);
115 static int getmsgscmd(UAContext *ua, const char *cmd)
117 if (console_msg_pending) {
118 do_messages(ua, cmd);
124 * Create segmentation fault
126 static int diecmd(UAContext *ua, const char *cmd)
131 bsendmsg(ua, _("The Director will segment fault.\n"));
132 a = jcr->JobId; /* ref NULL pointer */
133 jcr->JobId = 1000; /* another ref NULL pointer */
137 static int jobscmd(UAContext *ua, const char *cmd)
141 while ( (job = (JOB *)GetNextRes(R_JOB, (RES *)job)) ) {
142 if (acl_access_ok(ua, Job_ACL, job->hdr.name)) {
143 bsendmsg(ua, "%s\n", job->hdr.name);
150 static int filesetscmd(UAContext *ua, const char *cmd)
154 while ( (fs = (FILESET *)GetNextRes(R_FILESET, (RES *)fs)) ) {
155 if (acl_access_ok(ua, FileSet_ACL, fs->hdr.name)) {
156 bsendmsg(ua, "%s\n", fs->hdr.name);
163 static int clientscmd(UAContext *ua, const char *cmd)
165 CLIENT *client = NULL;
167 while ( (client = (CLIENT *)GetNextRes(R_CLIENT, (RES *)client)) ) {
168 if (acl_access_ok(ua, Client_ACL, client->hdr.name)) {
169 bsendmsg(ua, "%s\n", client->hdr.name);
176 static int msgscmd(UAContext *ua, const char *cmd)
180 while ( (msgs = (MSGS *)GetNextRes(R_MSGS, (RES *)msgs)) ) {
181 bsendmsg(ua, "%s\n", msgs->hdr.name);
187 static int poolscmd(UAContext *ua, const char *cmd)
191 while ( (pool = (POOL *)GetNextRes(R_POOL, (RES *)pool)) ) {
192 if (acl_access_ok(ua, Pool_ACL, pool->hdr.name)) {
193 bsendmsg(ua, "%s\n", pool->hdr.name);
200 static int storagecmd(UAContext *ua, const char *cmd)
204 while ( (store = (STORE *)GetNextRes(R_STORAGE, (RES *)store)) ) {
205 if (acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
206 bsendmsg(ua, "%s\n", store->hdr.name);
214 static int typescmd(UAContext *ua, const char *cmd)
216 bsendmsg(ua, "Backup\n");
217 bsendmsg(ua, "Restore\n");
218 bsendmsg(ua, "Admin\n");
219 bsendmsg(ua, "Verify\n");
223 static int client_backups_handler(void *ctx, int num_field, char **row)
225 UAContext *ua = (UAContext *)ctx;
226 bsendmsg(ua, "| %s | %s | %s | %s | %s | %s | %s |\n",
227 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7]);
231 static int backupscmd(UAContext *ua, const char *cmd)
236 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 || strcmp(ua->argk[2], "fileset") != 0) {
239 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
240 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
243 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
244 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
245 bsendmsg(ua, _("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
252 static int levelscmd(UAContext *ua, const char *cmd)
254 bsendmsg(ua, "Incremental\n");
255 bsendmsg(ua, "Full\n");
256 bsendmsg(ua, "Differential\n");
257 bsendmsg(ua, "Catalog\n");
258 bsendmsg(ua, "InitCatalog\n");
259 bsendmsg(ua, "VolumeToCatalog\n");
264 * Return default values for a job
266 static int defaultscmd(UAContext *ua, const char *cmd)
273 if (ua->argc != 2 || !ua->argv[1]) {
278 if (strcmp(ua->argk[1], "job") == 0) {
279 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
282 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
285 bsendmsg(ua, "job=%s", job->hdr.name);
286 bsendmsg(ua, "pool=%s", job->pool->hdr.name);
287 bsendmsg(ua, "messages=%s", job->messages->hdr.name);
288 bsendmsg(ua, "client=%s", job->client->hdr.name);
289 store = (STORE *)job->storage->first();
290 bsendmsg(ua, "storage=%s", store->hdr.name);
291 bsendmsg(ua, "where=%s", job->RestoreWhere?job->RestoreWhere:"");
292 bsendmsg(ua, "level=%s", level_to_str(job->JobLevel));
293 bsendmsg(ua, "type=%s", job_type_to_str(job->JobType));
294 bsendmsg(ua, "fileset=%s", job->fileset->hdr.name);
295 bsendmsg(ua, "enabled=%d", job->enabled);
298 /* Client defaults */
299 else if (strcmp(ua->argk[1], "client") == 0) {
300 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
303 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
305 bsendmsg(ua, "client=%s", client->hdr.name);
306 bsendmsg(ua, "address=%s", client->address);
307 bsendmsg(ua, "fdport=%d", client->FDport);
308 bsendmsg(ua, "file_retention=%d", client->FileRetention);
309 bsendmsg(ua, "job_retention=%d", client->JobRetention);
310 bsendmsg(ua, "autoprune=%d", client->AutoPrune);
313 /* Storage defaults */
314 else if (strcmp(ua->argk[1], "storage") == 0) {
315 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
318 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
321 bsendmsg(ua, "storage=%s", storage->hdr.name);
322 bsendmsg(ua, "address=%s", storage->address);
323 bsendmsg(ua, "enabled=%d", storage->enabled);
324 bsendmsg(ua, "media_type=%s", storage->media_type);
325 bsendmsg(ua, "sdport=%d", storage->SDport);
326 device = (DEVICE *)storage->device->first();
327 bsendmsg(ua, "device=%s", device->hdr.name);
328 if (storage->device->size() > 1) {
329 while ((device = (DEVICE *)storage->device->next()))
330 bsendmsg(ua, ",%s", device->hdr.name);
335 else if (strcmp(ua->argk[1], "pool") == 0) {
336 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
339 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
341 bsendmsg(ua, "pool=%s", pool->hdr.name);
342 bsendmsg(ua, "pool_type=%s", pool->pool_type);
343 bsendmsg(ua, "label_format=%s", pool->label_format?pool->label_format:"");
344 bsendmsg(ua, "use_volume_once=%d", pool->use_volume_once);
345 bsendmsg(ua, "accept_any_volume=%d", pool->accept_any_volume);
346 bsendmsg(ua, "purge_oldest_volume=%d", pool->purge_oldest_volume);
347 bsendmsg(ua, "recycle_oldest_volume=%d", pool->recycle_oldest_volume);
348 bsendmsg(ua, "recycle_current_volume=%d", pool->recycle_current_volume);
349 bsendmsg(ua, "max_volumes=%d", pool->max_volumes);
350 bsendmsg(ua, "vol_retention=%d", pool->VolRetention);
351 bsendmsg(ua, "vol_use_duration=%d", pool->VolUseDuration);
352 bsendmsg(ua, "max_vol_jobs=%d", pool->MaxVolJobs);
353 bsendmsg(ua, "max_vol_files=%d", pool->MaxVolFiles);
354 bsendmsg(ua, "max_vol_bytes=%d", pool->MaxVolBytes);
355 bsendmsg(ua, "auto_prune=%d", pool->AutoPrune);
356 bsendmsg(ua, "recycle=%d", pool->Recycle);