]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_dotcmds.c
kes Expand new BSOCK class adding signal() and new BNET signals.
[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 (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 *sock = ua->UA_sock;
106
107    Dmsg1(1400, "Dot command: %s\n", ua->UA_sock->msg);
108    if (ua->argc == 0) {
109       return 1;
110    }
111
112    len = strlen(ua->argk[0]);
113    if (len == 1) {
114       return 1;                       /* no op */
115    }
116    for (i=0; i<(int)comsize; i++) {     /* search for command */
117       if (strncasecmp(ua->argk[0],  _(commands[i].key), len) == 0) {
118          bool gui = ua->gui;
119          ua->gui = true;
120          if (ua->api) {
121             sock->signal(BNET_CMD_BEGIN);
122          }
123          ok = (*commands[i].func)(ua, cmd);   /* go execute command */
124          ua->gui = gui;
125          found = true;
126          break;
127       }
128    }
129    if (!found) {
130       pm_strcat(sock->msg, _(": is an invalid command\n"));
131       sock->msglen = strlen(sock->msg);
132       sock->send();
133       sock->signal(BNET_INVALID_CMD);
134    }
135    sock->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
136    return 1;
137 }
138
139 static bool dot_quit_cmd(UAContext *ua, const char *cmd)
140 {
141    quit_cmd(ua, cmd);
142    return true;
143 }
144
145 static bool dot_help_cmd(UAContext *ua, const char *cmd)
146 {
147    qhelp_cmd(ua, cmd);
148    return true;
149 }
150
151 static bool getmsgscmd(UAContext *ua, const char *cmd)
152 {
153    if (console_msg_pending) {
154       do_messages(ua, cmd);
155    }
156    return 1;
157 }
158
159 /*
160  * Create segmentation fault
161  */
162 static bool diecmd(UAContext *ua, const char *cmd)
163 {
164    JCR *jcr = NULL;
165    int a;
166
167    bsendmsg(ua, _("The Director will segment fault.\n"));
168    a = jcr->JobId; /* ref NULL pointer */
169    jcr->JobId = 1000; /* another ref NULL pointer */
170    return true;
171 }
172
173 static bool jobscmd(UAContext *ua, const char *cmd)
174 {
175    JOB *job = NULL;
176    LockRes();
177    while ( (job = (JOB *)GetNextRes(R_JOB, (RES *)job)) ) {
178       if (acl_access_ok(ua, Job_ACL, job->name())) {
179          bsendmsg(ua, "%s\n", job->name());
180       }
181    }
182    UnlockRes();
183    return true;
184 }
185
186 static bool filesetscmd(UAContext *ua, const char *cmd)
187 {
188    FILESET *fs = NULL;
189    LockRes();
190    while ( (fs = (FILESET *)GetNextRes(R_FILESET, (RES *)fs)) ) {
191       if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
192          bsendmsg(ua, "%s\n", fs->name());
193       }
194    }
195    UnlockRes();
196    return true;
197 }
198
199 static bool clientscmd(UAContext *ua, const char *cmd)
200 {
201    CLIENT *client = NULL;
202    LockRes();
203    while ( (client = (CLIENT *)GetNextRes(R_CLIENT, (RES *)client)) ) {
204       if (acl_access_ok(ua, Client_ACL, client->name())) {
205          bsendmsg(ua, "%s\n", client->name());
206       }
207    }
208    UnlockRes();
209    return true;
210 }
211
212 static bool msgscmd(UAContext *ua, const char *cmd)
213 {
214    MSGS *msgs = NULL;
215    LockRes();
216    while ( (msgs = (MSGS *)GetNextRes(R_MSGS, (RES *)msgs)) ) {
217       bsendmsg(ua, "%s\n", msgs->name());
218    }
219    UnlockRes();
220    return true;
221 }
222
223 static bool poolscmd(UAContext *ua, const char *cmd)
224 {
225    POOL *pool = NULL;
226    LockRes();
227    while ( (pool = (POOL *)GetNextRes(R_POOL, (RES *)pool)) ) {
228       if (acl_access_ok(ua, Pool_ACL, pool->name())) {
229          bsendmsg(ua, "%s\n", pool->name());
230       }
231    }
232    UnlockRes();
233    return true;
234 }
235
236 static bool storagecmd(UAContext *ua, const char *cmd)
237 {
238    STORE *store = NULL;
239    LockRes();
240    while ( (store = (STORE *)GetNextRes(R_STORAGE, (RES *)store)) ) {
241       if (acl_access_ok(ua, Storage_ACL, store->name())) {
242          bsendmsg(ua, "%s\n", store->name());
243       }
244    }
245    UnlockRes();
246    return true;
247 }
248
249
250 static bool typescmd(UAContext *ua, const char *cmd)
251 {
252    bsendmsg(ua, "Backup\n");
253    bsendmsg(ua, "Restore\n");
254    bsendmsg(ua, "Admin\n");
255    bsendmsg(ua, "Verify\n");
256    bsendmsg(ua, "Migrate\n");
257    return true;
258 }
259
260 static int client_backups_handler(void *ctx, int num_field, char **row)
261 {
262    UAContext *ua = (UAContext *)ctx;
263    bsendmsg(ua, "| %s | %s | %s | %s | %s | %s | %s | %s |\n",
264       row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
265    return 0;
266 }
267
268 /*
269  * If this command is called, it tells the director that we
270  *  are a program that wants a sort of API, and hence,
271  *  we will probably suppress certain output, include more
272  *  error codes, and most of all send back a good number
273  *  of new signals that indicate whether or not the command
274  *  succeeded.
275  */
276 static bool api_cmd(UAContext *ua, const char *cmd)
277 {
278    /* Eventually we will probably have several levels or
279     *  capabilities enabled by this.
280     */
281    ua->api = 1;
282    return true;
283 }
284
285 /*
286  * Return the backups for this client 
287  */
288 static bool backupscmd(UAContext *ua, const char *cmd)
289 {
290    if (!open_client_db(ua)) {
291       return true;
292    }
293    if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 || strcmp(ua->argk[2], "fileset") != 0) {
294       return true;
295    }
296    if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
297        !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
298       return true;
299    }
300    Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
301    if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
302       bsendmsg(ua, _("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
303       return true;
304    }
305    return true;
306 }
307
308
309
310 static bool levelscmd(UAContext *ua, const char *cmd)
311 {
312    bsendmsg(ua, "Incremental\n");
313    bsendmsg(ua, "Full\n");
314    bsendmsg(ua, "Differential\n");
315    bsendmsg(ua, "Catalog\n");
316    bsendmsg(ua, "InitCatalog\n");
317    bsendmsg(ua, "VolumeToCatalog\n");
318    return true;
319 }
320
321 /*
322  * Return default values for a job
323  */
324 static bool defaultscmd(UAContext *ua, const char *cmd)
325 {
326    JOB *job;
327    CLIENT *client;
328    STORE *storage;
329    POOL *pool;
330
331    if (ua->argc != 2 || !ua->argv[1]) {
332       return true;
333    }
334
335    /* Job defaults */   
336    if (strcmp(ua->argk[1], "job") == 0) {
337       if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
338          return true;
339       }
340       job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
341       if (job) {
342          USTORE store;
343          bsendmsg(ua, "job=%s", job->name());
344          bsendmsg(ua, "pool=%s", job->pool->name());
345          bsendmsg(ua, "messages=%s", job->messages->name());
346          bsendmsg(ua, "client=%s", job->client->name());
347          get_job_storage(&store, job, NULL);
348          bsendmsg(ua, "storage=%s", store.store->name());
349          bsendmsg(ua, "where=%s", job->RestoreWhere?job->RestoreWhere:"");
350          bsendmsg(ua, "level=%s", level_to_str(job->JobLevel));
351          bsendmsg(ua, "type=%s", job_type_to_str(job->JobType));
352          bsendmsg(ua, "fileset=%s", job->fileset->name());
353          bsendmsg(ua, "enabled=%d", job->enabled);
354          bsendmsg(ua, "catalog=%s", job->client->catalog->name());
355       }
356    } 
357    /* Client defaults */
358    else if (strcmp(ua->argk[1], "client") == 0) {
359       if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
360          return true;   
361       }
362       client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
363       if (client) {
364          bsendmsg(ua, "client=%s", client->name());
365          bsendmsg(ua, "address=%s", client->address);
366          bsendmsg(ua, "fdport=%d", client->FDport);
367          bsendmsg(ua, "file_retention=%d", client->FileRetention);
368          bsendmsg(ua, "job_retention=%d", client->JobRetention);
369          bsendmsg(ua, "autoprune=%d", client->AutoPrune);
370          bsendmsg(ua, "catalog=%s", client->catalog->name());
371       }
372    }
373    /* Storage defaults */
374    else if (strcmp(ua->argk[1], "storage") == 0) {
375       if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
376          return true;
377       }
378       storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
379       DEVICE *device;
380       if (storage) {
381          bsendmsg(ua, "storage=%s", storage->name());
382          bsendmsg(ua, "address=%s", storage->address);
383          bsendmsg(ua, "enabled=%d", storage->enabled);
384          bsendmsg(ua, "media_type=%s", storage->media_type);
385          bsendmsg(ua, "sdport=%d", storage->SDport);
386          device = (DEVICE *)storage->device->first();
387          bsendmsg(ua, "device=%s", device->name());
388          if (storage->device->size() > 1) {
389             while ((device = (DEVICE *)storage->device->next())) {
390                bsendmsg(ua, ",%s", device->name());
391             }
392          }
393       }
394    }
395    /* Pool defaults */
396    else if (strcmp(ua->argk[1], "pool") == 0) {
397       if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
398          return true;
399       }
400       pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
401       if (pool) {
402          bsendmsg(ua, "pool=%s", pool->name());
403          bsendmsg(ua, "pool_type=%s", pool->pool_type);
404          bsendmsg(ua, "label_format=%s", pool->label_format?pool->label_format:"");
405          bsendmsg(ua, "use_volume_once=%d", pool->use_volume_once);
406          bsendmsg(ua, "purge_oldest_volume=%d", pool->purge_oldest_volume);
407          bsendmsg(ua, "recycle_oldest_volume=%d", pool->recycle_oldest_volume);
408          bsendmsg(ua, "recycle_current_volume=%d", pool->recycle_current_volume);
409          bsendmsg(ua, "max_volumes=%d", pool->max_volumes);
410          bsendmsg(ua, "vol_retention=%d", pool->VolRetention);
411          bsendmsg(ua, "vol_use_duration=%d", pool->VolUseDuration);
412          bsendmsg(ua, "max_vol_jobs=%d", pool->MaxVolJobs);
413          bsendmsg(ua, "max_vol_files=%d", pool->MaxVolFiles);
414          bsendmsg(ua, "max_vol_bytes=%d", pool->MaxVolBytes);
415          bsendmsg(ua, "auto_prune=%d", pool->AutoPrune);
416          bsendmsg(ua, "recycle=%d", pool->Recycle);
417       }
418    }
419    return true;
420 }