3 * Bacula Director -- User Agent Output Commands
4 * I.e. messages, listing database, showing resources, ...
6 * Kern Sibbald, September MM
10 Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
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.
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.
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,
33 /* Imported subroutines */
34 extern void run_job(JCR *jcr);
36 /* Imported variables */
37 extern struct s_jl joblevels[];
40 extern struct s_res resources[];
41 extern int console_msg_pending;
45 /* Imported functions */
47 /* Forward referenced functions */
51 * Turn auto display of console messages on/off
53 int autodisplaycmd(UAContext *ua, char *cmd)
60 switch (find_arg_keyword(ua, kw)) {
62 ua->auto_display_messages = 1;
65 ua->auto_display_messages = 0;
68 bsendmsg(ua, _("ON or OFF keyword missing.\n"));
75 struct showstruct {char *res_name; int type;};
76 static struct showstruct reses[] = {
77 {N_("directors"), R_DIRECTOR},
78 {N_("clients"), R_CLIENT},
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},
97 * show <resource-keyword-name> e.g. show directors
98 * show <resource-keyword-name>=<name> e.g. show director=HeadMan
101 int showcmd(UAContext *ua, char *cmd)
108 Dmsg1(20, "show: %s\n", ua->UA_sock->msg);
111 for (i=1; i<ua->argc; i++) {
113 res_name = ua->argk[i];
114 if (!ua->argv[i]) { /* was a name given? */
115 /* No name, dump all resources of specified type */
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;
122 res = resources[type-r_first].res_head;
130 /* Dump a single resource with specified name */
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]);
147 for (j=r_first; j<=r_last; j++) {
148 dump_resource(j, resources[j-r_first].res_head, bsendmsg, ua);
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));
158 bsendmsg(ua, _("%s resource %s not found.\n"), res_name, ua->argv[i]);
161 bsendmsg(ua, _("Resource %s not found\n"), res_name);
164 dump_resource(recurse?type:-type, res, bsendmsg, ua);
173 * Callback routine for "printing" database file listing
175 void prtit(void *ctx, char *msg)
177 UAContext *ua = (UAContext *)ctx;
179 bnet_fsend(ua->UA_sock, "%s", msg);
182 /* Format message and send to other end */
183 void bsendmsg(void *ctx, char *fmt, ...)
186 UAContext *ua = (UAContext *)ctx;
187 BSOCK *bs = ua->UA_sock;
191 maxlen = sizeof_pool_memory(bs->msg) - 1;
192 va_start(arg_ptr, fmt);
193 bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
195 if (bs->msglen < 0 || bs->msglen >= maxlen) {
196 bs->msg = (char *) realloc_pool_memory(bs->msg, maxlen + 200);
204 * List contents of database
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
218 int listcmd(UAContext *ua, char *cmd)
230 memset(&jr, 0, sizeof(jr));
231 memset(&pr, 0, sizeof(pr));
232 memset(&mr, 0, sizeof(mr));
234 Dmsg1(20, "list: %s\n", cmd);
237 bsendmsg(ua, _("Hey! DB is NULL\n"));
240 /* Scan arguments looking for things to do */
241 for (i=1; i<ua->argc; i++) {
243 if (strcasecmp(ua->argk[i], _("jobs")) == 0) {
244 db_list_job_records(ua->db, &jr, prtit, ua);
247 } else if (strcasecmp(ua->argk[i], _("jobtotals")) == 0) {
248 db_list_job_totals(ua->db, &jr, prtit, ua);
251 } else if (strcasecmp(ua->argk[i], _("jobid")) == 0) {
253 jobid = atoi(ua->argv[i]);
256 db_list_job_records(ua->db, &jr, prtit, ua);
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;
265 db_list_job_records(ua->db, &jr, prtit, ua);
268 } else if (strcasecmp(ua->argk[i], _("files")) == 0) {
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;
275 db_get_job_record(ua->db, &jr);
277 } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) {
278 jobid = atoi(ua->argv[j]);
283 db_list_files_for_job(ua->db, jobid, prtit, ua);
288 } else if (strcasecmp(ua->argk[i], _("jobmedia")) == 0) {
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;
295 db_get_job_record(ua->db, &jr);
297 } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) {
298 jobid = atoi(ua->argv[j]);
302 db_list_jobmedia_records(ua->db, jobid, prtit, ua);
306 /* List for all jobs (jobid=0) */
307 db_list_jobmedia_records(ua->db, 0, prtit, ua);
311 } else if (strcasecmp(ua->argk[i], _("pools")) == 0) {
312 db_list_pool_records(ua->db, prtit, ua);
315 } else if (strcasecmp(ua->argk[i], _("media")) == 0) {
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;
322 db_get_job_record(ua->db, &jr);
324 } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) {
325 jobid = atoi(ua->argv[j]);
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);
335 /* if no job or jobid keyword found, then we list all media */
337 if (!get_pool_dbr(ua, &pr)) {
340 mr.PoolId = pr.PoolId;
341 db_list_media_records(ua->db, &mr, prtit, ua);
344 bsendmsg(ua, _("Unknown list keyword: %s\n"), ua->argk[i]);
350 void do_messages(UAContext *ua, char *cmd)
355 fcntl(fileno(con_fd), F_SETLKW);
357 while (fgets(msg, sizeof(msg), con_fd)) {
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);
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;
372 int qmessagescmd(UAContext *ua, char *cmd)
374 if (console_msg_pending && ua->auto_display_messages) {
375 do_messages(ua, cmd);
380 int messagescmd(UAContext *ua, char *cmd)
382 if (console_msg_pending) {
383 do_messages(ua, cmd);
385 bnet_fsend(ua->UA_sock, _("You have no messages.\n"));