]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_output.c
ff572affa4bf412ae64a52890f23641a1b24d4dd
[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
173 /*
174  *  List contents of database
175  *
176  *  list jobs           - lists all jobs run
177  *  list jobid=nnn      - list job data for jobid
178  *  list job=name       - list job data for job
179  *  list jobmedia jobid=<nn>
180  *  list jobmedia job=name
181  *  list files jobid=<nn> - list files saved for job nn
182  *  list files job=name
183  *  list pools          - list pool records
184  *  list jobtotals      - list totals for all jobs
185  *  list media          - list media for given pool
186  *
187  */
188 int listcmd(UAContext *ua, char *cmd) 
189 {
190    char *VolumeName;
191    int jobid, n;
192    int i, j;
193    JOB_DBR jr;
194    POOL_DBR pr;
195    MEDIA_DBR mr;
196
197    if (!open_db(ua))
198       return 1;
199
200    memset(&jr, 0, sizeof(jr));
201    memset(&pr, 0, sizeof(pr));
202    memset(&mr, 0, sizeof(mr));
203
204    Dmsg1(20, "list: %s\n", cmd);
205
206    if (!ua->db) {
207       bsendmsg(ua, _("Hey! DB is NULL\n"));
208    }
209
210    /* Scan arguments looking for things to do */
211    for (i=1; i<ua->argc; i++) {
212       /* List JOBS */
213       if (strcasecmp(ua->argk[i], _("jobs")) == 0) {
214          db_list_job_records(ua->db, &jr, prtit, ua);
215
216          /* List JOBTOTALS */
217       } else if (strcasecmp(ua->argk[i], _("jobtotals")) == 0) {
218          db_list_job_totals(ua->db, &jr, prtit, ua);
219
220       /* List JOBID */
221       } else if (strcasecmp(ua->argk[i], _("jobid")) == 0) {
222          if (ua->argv[i]) {
223             jobid = atoi(ua->argv[i]);
224             if (jobid > 0) {
225                jr.JobId = jobid;
226                db_list_job_records(ua->db, &jr, prtit, ua);
227             }
228          }
229
230       /* List JOB */
231       } else if (strcasecmp(ua->argk[i], _("job")) == 0 && ua->argv[i]) {
232          strncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH);
233          jr.Job[MAX_NAME_LENGTH-1] = 0;
234          jr.JobId = 0;
235          db_list_job_records(ua->db, &jr, prtit, ua);
236
237       /* List FILES */
238       } else if (strcasecmp(ua->argk[i], _("files")) == 0) {
239
240          for (j=i+1; j<ua->argc; j++) {
241             if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) {
242                strncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH);
243                jr.Job[MAX_NAME_LENGTH-1] = 0;
244                jr.JobId = 0;
245                db_get_job_record(ua->db, &jr);
246                jobid = jr.JobId;
247             } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) {
248                jobid = atoi(ua->argv[j]);
249             } else {
250                continue;
251             }
252             if (jobid > 0) {
253                db_list_files_for_job(ua->db, jobid, prtit, ua);
254             }
255          }
256       
257       /* List JOBMEDIA */
258       } else if (strcasecmp(ua->argk[i], _("jobmedia")) == 0) {
259          int done = FALSE;
260          for (j=i+1; j<ua->argc; j++) {
261             if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) {
262                strncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH);
263                jr.Job[MAX_NAME_LENGTH-1] = 0;
264                jr.JobId = 0;
265                db_get_job_record(ua->db, &jr);
266                jobid = jr.JobId;
267             } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) {
268                jobid = atoi(ua->argv[j]);
269             } else {
270                continue;
271             }
272             db_list_jobmedia_records(ua->db, jobid, prtit, ua);
273             done = TRUE;
274          }
275          if (!done) {
276             /* List for all jobs (jobid=0) */
277             db_list_jobmedia_records(ua->db, 0, prtit, ua);
278          }
279
280       /* List POOLS */
281       } else if (strcasecmp(ua->argk[i], _("pools")) == 0) {
282          db_list_pool_records(ua->db, prtit, ua);
283
284       /* List MEDIA */
285       } else if (strcasecmp(ua->argk[i], _("media")) == 0) {
286          int done = FALSE;
287          for (j=i+1; j<ua->argc; j++) {
288             if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) {
289                strncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH);
290                jr.Job[MAX_NAME_LENGTH-1] = 0;
291                jr.JobId = 0;
292                db_get_job_record(ua->db, &jr);
293                jobid = jr.JobId;
294             } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) {
295                jobid = atoi(ua->argv[j]);
296             } else {
297                continue;
298             }
299             VolumeName = (char *) get_pool_memory(PM_FNAME);
300             n = db_get_job_volume_names(ua->db, jobid, VolumeName);
301             bsendmsg(ua, _("Jobid %d used %d Volume(s): %s\n"), jobid, n, VolumeName);
302             free_memory(VolumeName);
303             done = TRUE;
304          }
305          /* if no job or jobid keyword found, then we list all media */
306          if (!done) {
307             if (!get_pool_dbr(ua, &pr)) {
308                return 1;
309             }
310             mr.PoolId = pr.PoolId;
311             db_list_media_records(ua->db, &mr, prtit, ua);
312          }
313       } else {
314          bsendmsg(ua, _("Unknown list keyword: %s\n"), ua->argk[i]);
315       }
316    }
317    return 1;
318 }
319
320 void do_messages(UAContext *ua, char *cmd)
321 {
322    char msg[2000];
323    int mlen; 
324
325    fcntl(fileno(con_fd), F_SETLKW);
326    rewind(con_fd);
327    while (fgets(msg, sizeof(msg), con_fd)) {
328       mlen = strlen(msg);
329       ua->UA_sock->msg = (char *) check_pool_memory_size(
330          ua->UA_sock->msg, mlen+1);
331       strcpy(ua->UA_sock->msg, msg);
332       ua->UA_sock->msglen = mlen;
333       bnet_send(ua->UA_sock);
334    }
335    ftruncate(fileno(con_fd), 0L);
336    console_msg_pending = FALSE;
337    fcntl(fileno(con_fd), F_UNLCK);
338    ua->user_notified_msg_pending = FALSE;
339 }
340
341
342 int qmessagescmd(UAContext *ua, char *cmd)
343 {
344    if (console_msg_pending && ua->auto_display_messages) {
345       do_messages(ua, cmd);
346    }
347    return 1;
348 }
349
350 int messagescmd(UAContext *ua, char *cmd)
351 {
352    if (console_msg_pending) {
353       do_messages(ua, cmd);
354    } else {
355       bnet_fsend(ua->UA_sock, _("You have no messages.\n"));
356    }
357    return 1;
358 }
359
360 /*
361  * Callback routine for "printing" database file listing
362  */
363 void prtit(void *ctx, char *msg)
364 {
365    UAContext *ua = (UAContext *)ctx;
366  
367    bnet_fsend(ua->UA_sock, "%s", msg);
368 }
369
370 /* 
371  * Format message and send to other end.  
372
373  * If the UA_sock is NULL, it means that there is no user
374  * agent, so we are being called from Bacula core. In
375  * that case direct the messages to the Job.
376  */
377 void bsendmsg(void *ctx, char *fmt, ...)
378 {
379    va_list arg_ptr;
380    UAContext *ua = (UAContext *)ctx;
381    BSOCK *bs = ua->UA_sock;
382    int maxlen, len;
383    char *msg;
384
385    if (bs) {
386       msg = bs->msg;
387    } else {
388       msg = (char *)get_pool_memory(PM_EMSG);
389    }
390
391 again:
392    maxlen = sizeof_pool_memory(msg) - 1;
393    va_start(arg_ptr, fmt);
394    len = bvsnprintf(msg, maxlen, fmt, arg_ptr);
395    va_end(arg_ptr);
396    if (len < 0 || len >= maxlen) {
397       msg = (char *) realloc_pool_memory(msg, maxlen + 200);
398       goto again;
399    }
400
401    if (bs) {
402       bs->msglen = len;
403       bnet_send(bs);
404    } else {                           /* No UA, send to Job */
405       Jmsg(ua->jcr, M_INFO, 0, msg);
406       free_memory(msg);
407    }
408
409 }