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