]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_dotcmds.c
kes Extend new GUI api code to tree commands.
[bacula/bacula] / bacula / src / dird / ua_dotcmds.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2002-2007 Free Software Foundation Europe e.V.
5
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.
12
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.
17
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
21    02110-1301, USA.
22
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.
27 */
28 /*
29  *
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.
35  *
36  *     Kern Sibbald, April MMII
37  *
38  *   Version $Id$
39  */
40
41 #include "bacula.h"
42 #include "dird.h"
43
44 /* Imported variables */
45 extern int r_first;
46 extern int r_last;
47 extern struct s_res resources[];
48
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);
54
55
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);
69
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);
73
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} 
93              };
94 #define comsize ((int)(sizeof(commands)/sizeof(struct cmdstruct)))
95
96 /*
97  * Execute a command from the UA
98  */
99 int do_a_dot_command(UAContext *ua, const char *cmd)
100 {
101    int i;
102    int len;
103    bool ok = false;
104    bool found = false;
105    BSOCK *user = ua->UA_sock;
106
107    Dmsg1(1400, "Dot command: %s\n", user->msg);
108    if (ua->argc == 0) {
109       return 1;
110    }
111
112    len = strlen(ua->argk[0]);
113    if (len == 1) {
114       if (ua->api) user->signal(BNET_CMD_BEGIN);
115       if (ua->api) user->signal(BNET_CMD_OK);
116       return 1;                       /* no op */
117    }
118    for (i=0; i<comsize; i++) {     /* search for command */
119       if (strncasecmp(ua->argk[0],  _(commands[i].key), len) == 0) {
120          bool gui = ua->gui;
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)) {
124             break;
125          }
126          ua->gui = true;
127          if (ua->api) user->signal(BNET_CMD_BEGIN);
128          ok = (*commands[i].func)(ua, cmd);   /* go execute command */
129          ua->gui = gui;
130          found = true;
131          break;
132       }
133    }
134    if (!found) {
135       pm_strcat(user->msg, _(": is an invalid command.\n"));
136       user->msglen = strlen(user->msg);
137       user->send();
138    }
139    if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
140    return 1;
141 }
142
143 static bool dot_quit_cmd(UAContext *ua, const char *cmd)
144 {
145    quit_cmd(ua, cmd);
146    return true;
147 }
148
149 static bool dot_help_cmd(UAContext *ua, const char *cmd)
150 {
151    qhelp_cmd(ua, cmd);
152    return true;
153 }
154
155 static bool getmsgscmd(UAContext *ua, const char *cmd)
156 {
157    if (console_msg_pending) {
158       do_messages(ua, cmd);
159    }
160    return 1;
161 }
162
163 /*
164  * Create segmentation fault
165  */
166 static bool diecmd(UAContext *ua, const char *cmd)
167 {
168    JCR *jcr = NULL;
169    int a;
170
171    bsendmsg(ua, _("The Director will segment fault.\n"));
172    a = jcr->JobId; /* ref NULL pointer */
173    jcr->JobId = 1000; /* another ref NULL pointer */
174    return true;
175 }
176
177 static bool jobscmd(UAContext *ua, const char *cmd)
178 {
179    JOB *job = NULL;
180    LockRes();
181    while ( (job = (JOB *)GetNextRes(R_JOB, (RES *)job)) ) {
182       if (acl_access_ok(ua, Job_ACL, job->name())) {
183          bsendmsg(ua, "%s\n", job->name());
184       }
185    }
186    UnlockRes();
187    return true;
188 }
189
190 static bool filesetscmd(UAContext *ua, const char *cmd)
191 {
192    FILESET *fs = NULL;
193    LockRes();
194    while ( (fs = (FILESET *)GetNextRes(R_FILESET, (RES *)fs)) ) {
195       if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
196          bsendmsg(ua, "%s\n", fs->name());
197       }
198    }
199    UnlockRes();
200    return true;
201 }
202
203 static bool clientscmd(UAContext *ua, const char *cmd)
204 {
205    CLIENT *client = NULL;
206    LockRes();
207    while ( (client = (CLIENT *)GetNextRes(R_CLIENT, (RES *)client)) ) {
208       if (acl_access_ok(ua, Client_ACL, client->name())) {
209          bsendmsg(ua, "%s\n", client->name());
210       }
211    }
212    UnlockRes();
213    return true;
214 }
215
216 static bool msgscmd(UAContext *ua, const char *cmd)
217 {
218    MSGS *msgs = NULL;
219    LockRes();
220    while ( (msgs = (MSGS *)GetNextRes(R_MSGS, (RES *)msgs)) ) {
221       bsendmsg(ua, "%s\n", msgs->name());
222    }
223    UnlockRes();
224    return true;
225 }
226
227 static bool poolscmd(UAContext *ua, const char *cmd)
228 {
229    POOL *pool = NULL;
230    LockRes();
231    while ( (pool = (POOL *)GetNextRes(R_POOL, (RES *)pool)) ) {
232       if (acl_access_ok(ua, Pool_ACL, pool->name())) {
233          bsendmsg(ua, "%s\n", pool->name());
234       }
235    }
236    UnlockRes();
237    return true;
238 }
239
240 static bool storagecmd(UAContext *ua, const char *cmd)
241 {
242    STORE *store = NULL;
243    LockRes();
244    while ( (store = (STORE *)GetNextRes(R_STORAGE, (RES *)store)) ) {
245       if (acl_access_ok(ua, Storage_ACL, store->name())) {
246          bsendmsg(ua, "%s\n", store->name());
247       }
248    }
249    UnlockRes();
250    return true;
251 }
252
253
254 static bool typescmd(UAContext *ua, const char *cmd)
255 {
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");
261    return true;
262 }
263
264 static int client_backups_handler(void *ctx, int num_field, char **row)
265 {
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]);
269    return 0;
270 }
271
272 /*
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
278  *  succeeded.
279  */
280 static bool api_cmd(UAContext *ua, const char *cmd)
281 {
282    /* Eventually we will probably have several levels or
283     *  capabilities enabled by this.
284     */
285    ua->api = 1;
286    return true;
287 }
288
289 /*
290  * Return the backups for this client 
291  */
292 static bool backupscmd(UAContext *ua, const char *cmd)
293 {
294    if (!open_client_db(ua)) {
295       return true;
296    }
297    if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 || strcmp(ua->argk[2], "fileset") != 0) {
298       return true;
299    }
300    if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
301        !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
302       return true;
303    }
304    Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
305    if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
306       bsendmsg(ua, _("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
307       return true;
308    }
309    return true;
310 }
311
312
313
314 static bool levelscmd(UAContext *ua, const char *cmd)
315 {
316    bsendmsg(ua, "Incremental\n");
317    bsendmsg(ua, "Full\n");
318    bsendmsg(ua, "Differential\n");
319    bsendmsg(ua, "Catalog\n");
320    bsendmsg(ua, "InitCatalog\n");
321    bsendmsg(ua, "VolumeToCatalog\n");
322    return true;
323 }
324
325 /*
326  * Return default values for a job
327  */
328 static bool defaultscmd(UAContext *ua, const char *cmd)
329 {
330    JOB *job;
331    CLIENT *client;
332    STORE *storage;
333    POOL *pool;
334
335    if (ua->argc != 2 || !ua->argv[1]) {
336       return true;
337    }
338
339    /* Job defaults */   
340    if (strcmp(ua->argk[1], "job") == 0) {
341       if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
342          return true;
343       }
344       job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
345       if (job) {
346          USTORE store;
347          bsendmsg(ua, "job=%s", job->name());
348          bsendmsg(ua, "pool=%s", job->pool->name());
349          bsendmsg(ua, "messages=%s", job->messages->name());
350          bsendmsg(ua, "client=%s", job->client->name());
351          get_job_storage(&store, job, NULL);
352          bsendmsg(ua, "storage=%s", store.store->name());
353          bsendmsg(ua, "where=%s", job->RestoreWhere?job->RestoreWhere:"");
354          bsendmsg(ua, "level=%s", level_to_str(job->JobLevel));
355          bsendmsg(ua, "type=%s", job_type_to_str(job->JobType));
356          bsendmsg(ua, "fileset=%s", job->fileset->name());
357          bsendmsg(ua, "enabled=%d", job->enabled);
358          bsendmsg(ua, "catalog=%s", job->client->catalog->name());
359       }
360    } 
361    /* Client defaults */
362    else if (strcmp(ua->argk[1], "client") == 0) {
363       if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
364          return true;   
365       }
366       client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
367       if (client) {
368          bsendmsg(ua, "client=%s", client->name());
369          bsendmsg(ua, "address=%s", client->address);
370          bsendmsg(ua, "fdport=%d", client->FDport);
371          bsendmsg(ua, "file_retention=%d", client->FileRetention);
372          bsendmsg(ua, "job_retention=%d", client->JobRetention);
373          bsendmsg(ua, "autoprune=%d", client->AutoPrune);
374          bsendmsg(ua, "catalog=%s", client->catalog->name());
375       }
376    }
377    /* Storage defaults */
378    else if (strcmp(ua->argk[1], "storage") == 0) {
379       if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
380          return true;
381       }
382       storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
383       DEVICE *device;
384       if (storage) {
385          bsendmsg(ua, "storage=%s", storage->name());
386          bsendmsg(ua, "address=%s", storage->address);
387          bsendmsg(ua, "enabled=%d", storage->enabled);
388          bsendmsg(ua, "media_type=%s", storage->media_type);
389          bsendmsg(ua, "sdport=%d", storage->SDport);
390          device = (DEVICE *)storage->device->first();
391          bsendmsg(ua, "device=%s", device->name());
392          if (storage->device->size() > 1) {
393             while ((device = (DEVICE *)storage->device->next())) {
394                bsendmsg(ua, ",%s", device->name());
395             }
396          }
397       }
398    }
399    /* Pool defaults */
400    else if (strcmp(ua->argk[1], "pool") == 0) {
401       if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
402          return true;
403       }
404       pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
405       if (pool) {
406          bsendmsg(ua, "pool=%s", pool->name());
407          bsendmsg(ua, "pool_type=%s", pool->pool_type);
408          bsendmsg(ua, "label_format=%s", pool->label_format?pool->label_format:"");
409          bsendmsg(ua, "use_volume_once=%d", pool->use_volume_once);
410          bsendmsg(ua, "purge_oldest_volume=%d", pool->purge_oldest_volume);
411          bsendmsg(ua, "recycle_oldest_volume=%d", pool->recycle_oldest_volume);
412          bsendmsg(ua, "recycle_current_volume=%d", pool->recycle_current_volume);
413          bsendmsg(ua, "max_volumes=%d", pool->max_volumes);
414          bsendmsg(ua, "vol_retention=%d", pool->VolRetention);
415          bsendmsg(ua, "vol_use_duration=%d", pool->VolUseDuration);
416          bsendmsg(ua, "max_vol_jobs=%d", pool->MaxVolJobs);
417          bsendmsg(ua, "max_vol_files=%d", pool->MaxVolFiles);
418          bsendmsg(ua, "max_vol_bytes=%d", pool->MaxVolBytes);
419          bsendmsg(ua, "auto_prune=%d", pool->AutoPrune);
420          bsendmsg(ua, "recycle=%d", pool->Recycle);
421       }
422    }
423    return true;
424 }