]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_dotcmds.c
ebl add message log to identify the device which will be used
[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;
180    LockRes();
181    foreach_res(job, R_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;
193    LockRes();
194    foreach_res(fs, R_FILESET) {
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;       
206    LockRes();
207    foreach_res(client, R_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    foreach_res(msgs, R_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;       
230    LockRes();
231    foreach_res(pool, R_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;
243    LockRes();
244    foreach_res(store, R_STORAGE) {
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    if (ua->argc == 2) {
283       ua->api = atoi(ua->argk[1]);
284    } else {
285       ua->api = 1;
286    }
287    return true;
288 }
289
290 /*
291  * Return the backups for this client 
292  *
293  *  .backups client=xxx fileset=yyy
294  *
295  */
296 static bool backupscmd(UAContext *ua, const char *cmd)
297 {
298    if (!open_client_db(ua)) {
299       return true;
300    }
301    if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 || 
302        strcmp(ua->argk[2], "fileset") != 0) {
303       return true;
304    }
305    if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
306        !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
307       return true;
308    }
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));
312       return true;
313    }
314    return true;
315 }
316
317
318
319 static bool levelscmd(UAContext *ua, const char *cmd)
320 {
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");
327    return true;
328 }
329
330 /*
331  * Return default values for a job
332  */
333 static bool defaultscmd(UAContext *ua, const char *cmd)
334 {
335    JOB *job;
336    CLIENT *client;
337    STORE *storage;
338    POOL *pool;
339
340    if (ua->argc != 2 || !ua->argv[1]) {
341       return true;
342    }
343
344    /* Job defaults */   
345    if (strcmp(ua->argk[1], "job") == 0) {
346       if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
347          return true;
348       }
349       job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
350       if (job) {
351          USTORE store;
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());
364       }
365    } 
366    /* Client defaults */
367    else if (strcmp(ua->argk[1], "client") == 0) {
368       if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
369          return true;   
370       }
371       client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
372       if (client) {
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());
380       }
381    }
382    /* Storage defaults */
383    else if (strcmp(ua->argk[1], "storage") == 0) {
384       if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
385          return true;
386       }
387       storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
388       DEVICE *device;
389       if (storage) {
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());
400             }
401          }
402       }
403    }
404    /* Pool defaults */
405    else if (strcmp(ua->argk[1], "pool") == 0) {
406       if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
407          return true;
408       }
409       pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
410       if (pool) {
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);
426       }
427    }
428    return true;
429 }