]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_output.c
a7a97df109eaf41745904873c8b3cef97eb62675
[bacula/bacula] / bacula / src / dird / ua_output.c
1 /*
2  *
3  *   Bacula Director -- User Agent Output Commands
4  *     I.e. messages, listing database, showing resources, ...
5  *
6  *     Kern Sibbald, September MM
7  */
8
9 /*
10    Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License as
14    published by the Free Software Foundation; either version 2 of
15    the License, or (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20    General Public License for more details.
21
22    You should have received a copy of the GNU General Public
23    License along with this program; if not, write to the Free
24    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25    MA 02111-1307, USA.
26
27  */
28
29 #include "bacula.h"
30 #include "dird.h"
31 #include "ua.h"
32
33 /* Imported subroutines */
34 extern void run_job(JCR *jcr);
35
36 /* Imported variables */
37 extern int r_first;
38 extern int r_last;
39 extern struct s_res resources[];
40 extern int console_msg_pending;
41 extern FILE *con_fd;
42
43
44 /* Imported functions */
45
46 /* Forward referenced functions */
47
48
49 /*
50  * Turn auto display of console messages on/off
51  */
52 int autodisplaycmd(UAContext *ua, char *cmd)
53 {
54    static char *kw[] = {
55       N_("on"), 
56       N_("off"),
57       NULL};
58
59    switch (find_arg_keyword(ua, kw)) {
60       case 0:
61          ua->auto_display_messages = 1;
62          break;
63       case 1:
64          ua->auto_display_messages = 0;
65          break;
66       default:
67          bsendmsg(ua, _("ON or OFF keyword missing.\n"));
68          break;
69    }
70    return 1; 
71 }
72
73
74 struct showstruct {char *res_name; int type;};
75 static struct showstruct reses[] = {
76    {N_("directors"),  R_DIRECTOR},
77    {N_("clients"),    R_CLIENT},
78    {N_("jobs"),       R_JOB},
79    {N_("storages"),   R_STORAGE},
80    {N_("catalogs"),   R_CATALOG},
81    {N_("schedules"),  R_SCHEDULE},
82    {N_("filesets"),   R_FILESET},
83    {N_("groups"),     R_GROUP},
84    {N_("pools"),      R_POOL},
85    {N_("messages"),   R_MSGS},
86    {N_("all"),        -1},
87    {N_("help"),       -2},
88    {NULL,           0}
89 };
90
91
92 /*
93  *  Displays Resources
94  *
95  *  show all
96  *  show <resource-keyword-name>  e.g. show directors
97  *  show <resource-keyword-name>=<name> e.g. show director=HeadMan
98  *
99  */
100 int showcmd(UAContext *ua, char *cmd)
101 {
102    int i, j, type, len; 
103    int recurse;
104    char *res_name;
105    RES *res;
106
107    Dmsg1(20, "show: %s\n", ua->UA_sock->msg);
108
109
110    for (i=1; i<ua->argc; i++) {
111       type = 0;
112       res_name = ua->argk[i]; 
113       if (!ua->argv[i]) {             /* was a name given? */
114          /* No name, dump all resources of specified type */
115          recurse = 1;
116          len = strlen(res_name);
117          for (j=0; reses[j].res_name; j++) {
118             if (strncasecmp(res_name, _(reses[j].res_name), len) == 0) {
119                type = reses[j].type;
120                if (type > 0) {
121                   res = resources[type-r_first].res_head;
122                } else {
123                   res = NULL;
124                }
125                break;
126             }
127          }
128       } else {
129          /* Dump a single resource with specified name */
130          recurse = 0;
131          len = strlen(res_name);
132          for (j=0; reses[j].res_name; j++) {
133             if (strncasecmp(res_name, _(reses[j].res_name), len) == 0) {
134                type = reses[j].type;
135                res = (RES *)GetResWithName(type, ua->argv[i]);
136                if (!res) {
137                   type = -3;
138                }
139                break;
140             }
141          }
142       }
143
144       switch (type) {
145       case -1:                           /* all */
146          for (j=r_first; j<=r_last; j++) {
147             dump_resource(j, resources[j-r_first].res_head, bsendmsg, ua);     
148          }
149          break;
150       case -2:
151          bsendmsg(ua, _("Keywords for the show command are:\n"));
152          for (j=0; reses[j].res_name; j++) {
153             bsendmsg(ua, "%s\n", _(reses[j].res_name));
154          }
155          return 1;
156       case -3:
157          bsendmsg(ua, _("%s resource %s not found.\n"), res_name, ua->argv[i]);
158          return 1;
159       case 0:
160          bsendmsg(ua, _("Resource %s not found\n"), res_name);
161          return 1;
162       default:
163          dump_resource(recurse?type:-type, res, bsendmsg, ua);
164          break;
165       }
166    }
167    return 1;
168 }
169
170
171 /*
172  * Callback routine for "printing" database file listing
173  */
174 void prtit(void *ctx, char *msg)
175 {
176    UAContext *ua = (UAContext *)ctx;
177  
178    bnet_fsend(ua->UA_sock, "%s", msg);
179 }
180
181 /* Format message and send to other end */
182 void bsendmsg(void *ctx, char *fmt, ...)
183 {
184    va_list arg_ptr;
185    UAContext *ua = (UAContext *)ctx;
186    BSOCK *bs = ua->UA_sock;
187    int maxlen;
188
189 again:
190    maxlen = sizeof_pool_memory(bs->msg) - 1;
191    va_start(arg_ptr, fmt);
192    bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
193    va_end(arg_ptr);
194    if (bs->msglen < 0 || bs->msglen >= maxlen) {
195       bs->msg = (char *) realloc_pool_memory(bs->msg, maxlen + 200);
196       goto again;
197    }
198    bnet_send(bs);
199 }
200
201
202 /*
203  *  List contents of database
204  *
205  *  list jobs           - lists all jobs run
206  *  list jobid=nnn      - list job data for jobid
207  *  list job=name       - list job data for job
208  *  list jobmedia jobid=<nn>
209  *  list jobmedia job=name
210  *  list files jobid=<nn> - list files saved for job nn
211  *  list files job=name
212  *  list pools          - list pool records
213  *  list jobtotals      - list totals for all jobs
214  *  list media          - list media for given pool
215  *
216  */
217 int listcmd(UAContext *ua, char *cmd) 
218 {
219    char *VolumeName;
220    int jobid, n;
221    int i, j;
222    JOB_DBR jr;
223    POOL_DBR pr;
224    MEDIA_DBR mr;
225
226    if (!open_db(ua))
227       return 1;
228
229    memset(&jr, 0, sizeof(jr));
230    memset(&pr, 0, sizeof(pr));
231    memset(&mr, 0, sizeof(mr));
232
233    Dmsg1(20, "list: %s\n", cmd);
234
235    if (!ua->db) {
236       bsendmsg(ua, _("Hey! DB is NULL\n"));
237    }
238
239    /* Scan arguments looking for things to do */
240    for (i=1; i<ua->argc; i++) {
241       /* List JOBS */
242       if (strcasecmp(ua->argk[i], _("jobs")) == 0) {
243          db_list_job_records(ua->db, &jr, prtit, ua);
244
245          /* List JOBTOTALS */
246       } else if (strcasecmp(ua->argk[i], _("jobtotals")) == 0) {
247          db_list_job_totals(ua->db, &jr, prtit, ua);
248
249       /* List JOBID */
250       } else if (strcasecmp(ua->argk[i], _("jobid")) == 0) {
251          if (ua->argv[i]) {
252             jobid = atoi(ua->argv[i]);
253             if (jobid > 0) {
254                jr.JobId = jobid;
255                db_list_job_records(ua->db, &jr, prtit, ua);
256             }
257          }
258
259       /* List JOB */
260       } else if (strcasecmp(ua->argk[i], _("job")) == 0 && ua->argv[i]) {
261          strncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH);
262          jr.Job[MAX_NAME_LENGTH-1] = 0;
263          jr.JobId = 0;
264          db_list_job_records(ua->db, &jr, prtit, ua);
265
266       /* List FILES */
267       } else if (strcasecmp(ua->argk[i], _("files")) == 0) {
268
269          for (j=i+1; j<ua->argc; j++) {
270             if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) {
271                strncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH);
272                jr.Job[MAX_NAME_LENGTH-1] = 0;
273                jr.JobId = 0;
274                db_get_job_record(ua->db, &jr);
275                jobid = jr.JobId;
276             } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) {
277                jobid = atoi(ua->argv[j]);
278             } else {
279                continue;
280             }
281             if (jobid > 0) {
282                db_list_files_for_job(ua->db, jobid, prtit, ua);
283             }
284          }
285       
286       /* List JOBMEDIA */
287       } else if (strcasecmp(ua->argk[i], _("jobmedia")) == 0) {
288          int done = FALSE;
289          for (j=i+1; j<ua->argc; j++) {
290             if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) {
291                strncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH);
292                jr.Job[MAX_NAME_LENGTH-1] = 0;
293                jr.JobId = 0;
294                db_get_job_record(ua->db, &jr);
295                jobid = jr.JobId;
296             } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) {
297                jobid = atoi(ua->argv[j]);
298             } else {
299                continue;
300             }
301             db_list_jobmedia_records(ua->db, jobid, prtit, ua);
302             done = TRUE;
303          }
304          if (!done) {
305             /* List for all jobs (jobid=0) */
306             db_list_jobmedia_records(ua->db, 0, prtit, ua);
307          }
308
309       /* List POOLS */
310       } else if (strcasecmp(ua->argk[i], _("pools")) == 0) {
311          db_list_pool_records(ua->db, prtit, ua);
312
313       /* List MEDIA */
314       } else if (strcasecmp(ua->argk[i], _("media")) == 0) {
315          int done = FALSE;
316          for (j=i+1; j<ua->argc; j++) {
317             if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) {
318                strncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH);
319                jr.Job[MAX_NAME_LENGTH-1] = 0;
320                jr.JobId = 0;
321                db_get_job_record(ua->db, &jr);
322                jobid = jr.JobId;
323             } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) {
324                jobid = atoi(ua->argv[j]);
325             } else {
326                continue;
327             }
328             VolumeName = (char *) get_pool_memory(PM_FNAME);
329             n = db_get_job_volume_names(ua->db, jobid, VolumeName);
330             bsendmsg(ua, _("Jobid %d used %d Volume(s): %s\n"), jobid, n, VolumeName);
331             free_memory(VolumeName);
332             done = TRUE;
333          }
334          /* if no job or jobid keyword found, then we list all media */
335          if (!done) {
336             if (!get_pool_dbr(ua, &pr)) {
337                return 1;
338             }
339             mr.PoolId = pr.PoolId;
340             db_list_media_records(ua->db, &mr, prtit, ua);
341          }
342       } else {
343          bsendmsg(ua, _("Unknown list keyword: %s\n"), ua->argk[i]);
344       }
345    }
346    return 1;
347 }
348
349 void do_messages(UAContext *ua, char *cmd)
350 {
351    char msg[2000];
352    int mlen; 
353
354    fcntl(fileno(con_fd), F_SETLKW);
355    rewind(con_fd);
356    while (fgets(msg, sizeof(msg), con_fd)) {
357       mlen = strlen(msg);
358       ua->UA_sock->msg = (char *) check_pool_memory_size(
359          ua->UA_sock->msg, mlen+1);
360       strcpy(ua->UA_sock->msg, msg);
361       ua->UA_sock->msglen = mlen;
362       bnet_send(ua->UA_sock);
363    }
364    ftruncate(fileno(con_fd), 0L);
365    console_msg_pending = FALSE;
366    fcntl(fileno(con_fd), F_UNLCK);
367    ua->user_notified_msg_pending = FALSE;
368 }
369
370
371 int qmessagescmd(UAContext *ua, char *cmd)
372 {
373    if (console_msg_pending && ua->auto_display_messages) {
374       do_messages(ua, cmd);
375    }
376    return 1;
377 }
378
379 int messagescmd(UAContext *ua, char *cmd)
380 {
381    if (console_msg_pending) {
382       do_messages(ua, cmd);
383    } else {
384       bnet_fsend(ua->UA_sock, _("You have no messages.\n"));
385    }
386    return 1;
387 }