]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_query.c
ba8cd815343298edf1fa2cf161791c2825931d96
[bacula/bacula] / bacula / src / dird / ua_query.c
1 /*
2  *
3  *   Bacula Director -- User Agent Database Query Commands
4  *
5  *     Kern Sibbald, December MMI
6  *
7  *   Version $Id$
8  */
9 /*
10    Copyright (C) 2001-2005 Kern Sibbald
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
14    version 2 as amended with additional clauses defined in the
15    file LICENSE in the main source directory.
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 
20    the file LICENSE for additional details.
21
22  */
23
24 #include "bacula.h"
25 #include "dird.h"
26
27 extern DIRRES *director;
28
29 static POOLMEM *substitute_prompts(UAContext *ua,
30                        POOLMEM *query, char **prompt, int nprompt);
31
32 /*
33  * Read a file containing SQL queries and prompt
34  *  the user to select which one.
35  *
36  *   File format:
37  *   #  => comment
38  *   :prompt for query
39  *   *prompt for subst %1
40  *   *prompt for subst %2
41  *   ...
42  *   SQL statement possibly terminated by ;
43  *   :next query prompt
44  */
45 int querycmd(UAContext *ua, const char *cmd)
46 {
47    FILE *fd = NULL;
48    POOLMEM *query = get_pool_memory(PM_MESSAGE);
49    char line[1000];
50    int i, item, len;
51    char *prompt[9];
52    int nprompt = 0;;
53    char *query_file = director->query_file;
54
55    if (!open_db(ua)) {
56       goto bail_out;
57    }
58    if ((fd=fopen(query_file, "r")) == NULL) {
59       bsendmsg(ua, _("Could not open %s: ERR=%s\n"), query_file,
60          strerror(errno));
61       goto bail_out;
62    }
63
64    start_prompt(ua, _("Available queries:\n"));
65    while (fgets(line, sizeof(line), fd) != NULL) {
66       if (line[0] == ':') {
67          strip_trailing_junk(line);
68          add_prompt(ua, line+1);
69       }
70    }
71    if ((item=do_prompt(ua, "", _("Choose a query"), NULL, 0)) < 0) {
72       goto bail_out;
73    }
74    rewind(fd);
75    i = -1;
76    while (fgets(line, sizeof(line), fd) != NULL) {
77       if (line[0] == ':') {
78          i++;
79       }
80       if (i == item) {
81          break;
82       }
83    }
84    if (i != item) {
85       bsendmsg(ua, _("Could not find query.\n"));
86       goto bail_out;
87    }
88    query[0] = 0;
89    for (i=0; i<9; i++) {
90       prompt[i] = NULL;
91    }
92    while (fgets(line, sizeof(line), fd) != NULL) {
93       if (line[0] == '#') {
94          continue;
95       }
96       if (line[0] == ':') {
97          break;
98       }
99       strip_trailing_junk(line);
100       len = strlen(line);
101       if (line[0] == '*') {            /* prompt */
102          if (nprompt >= 9) {
103             bsendmsg(ua, _("Too many prompts in query, max is 9.\n"));
104          } else {
105             line[len++] = ' ';
106             line[len] = 0;
107             prompt[nprompt++] = bstrdup(line+1);
108             continue;
109          }
110       }
111       if (*query != 0) {
112          pm_strcat(query, " ");
113       }
114       pm_strcat(query, line);
115       if (line[len-1] != ';') {
116          continue;
117       }
118       line[len-1] = 0;             /* zap ; */
119       if (query[0] != 0) {
120          query = substitute_prompts(ua, query, prompt, nprompt);
121          Dmsg1(100, "Query2=%s\n", query);
122          if (query[0] == '!') {
123             db_list_sql_query(ua->jcr, ua->db, query+1, prtit, ua, 0, VERT_LIST);
124          } else if (!db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST)) {
125             bsendmsg(ua, "%s\n", query);
126          }
127          query[0] = 0;
128       }
129    } /* end while */
130
131    if (query[0] != 0) {
132       query = substitute_prompts(ua, query, prompt, nprompt);
133       Dmsg1(100, "Query2=%s\n", query);
134          if (query[0] == '!') {
135             db_list_sql_query(ua->jcr, ua->db, query+1, prtit, ua, 0, VERT_LIST);
136          } else if (!db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST)) {
137             bsendmsg(ua, "%s\n", query);
138          }
139    }
140
141 bail_out:
142    if (fd) {
143       fclose(fd);
144    }
145    free_pool_memory(query);
146    for (i=0; i<nprompt; i++) {
147       free(prompt[i]);
148    }
149    return 1;
150 }
151
152 static POOLMEM *substitute_prompts(UAContext *ua,
153                        POOLMEM *query, char **prompt, int nprompt)
154 {
155    char *p, *q, *o;
156    POOLMEM *new_query;
157    int i, n, len, olen;
158    char *subst[9];
159
160    if (nprompt == 0) {
161       return query;
162    }
163    for (i=0; i<9; i++) {
164       subst[i] = NULL;
165    }
166    new_query = get_pool_memory(PM_FNAME);
167    o = new_query;
168    for (q=query; (p=strchr(q, '%')); ) {
169       if (p) {
170         olen = o - new_query;
171         new_query = check_pool_memory_size(new_query, olen + p - q + 10);
172         o = new_query + olen;
173          while (q < p) {              /* copy up to % */
174             *o++ = *q++;
175          }
176          p++;
177          switch (*p) {
178          case '1':
179          case '2':
180          case '3':
181          case '4':
182          case '5':
183          case '6':
184          case '7':
185          case '8':
186          case '9':
187             n = (int)(*p) - (int)'1';
188             if (prompt[n]) {
189                if (!subst[n]) {
190                   if (!get_cmd(ua, prompt[n])) {
191                      q += 2;
192                      break;
193                   }
194                }
195                len = strlen(ua->cmd);
196                p = (char *)malloc(len * 2 + 1);
197                db_escape_string(p, ua->cmd, len);
198                subst[n] = p;
199                olen = o - new_query;
200                new_query = check_pool_memory_size(new_query, olen + strlen(p) + 10);
201                o = new_query + olen;
202                while (*p) {
203                   *o++ = *p++;
204                }
205             } else {
206                bsendmsg(ua, _("Warning prompt %d missing.\n"), n+1);
207             }
208             q += 2;
209             break;
210          case '%':
211             *o++ = '%';
212             q += 2;
213             break;
214          default:
215             *o++ = '%';
216             q++;
217             break;
218          }
219       }
220    }
221    olen = o - new_query;
222    new_query = check_pool_memory_size(new_query, olen + strlen(q) + 10);
223    o = new_query + olen;
224    while (*q) {
225       *o++ = *q++;
226    }
227    *o = 0;
228    for (i=0; i<9; i++) {
229       if (subst[i]) {
230          free(subst[i]);
231       }
232    }
233    free_pool_memory(query);
234    return new_query;
235 }
236
237 /*
238  * Get general SQL query for Catalog
239  */
240 int sqlquerycmd(UAContext *ua, const char *cmd)
241 {
242    POOLMEM *query = get_pool_memory(PM_MESSAGE);
243    int len;
244    const char *msg;
245
246    if (!open_db(ua)) {
247       free_pool_memory(query);
248       return 1;
249    }
250    *query = 0;
251
252    bsendmsg(ua, _("Entering SQL query mode.\n"
253 "Terminate each query with a semicolon.\n"
254 "Terminate query mode with a blank line.\n"));
255    msg = _("Enter SQL query: ");
256    while (get_cmd(ua, msg)) {
257       len = strlen(ua->cmd);
258       Dmsg2(400, "len=%d cmd=%s:\n", len, ua->cmd);
259       if (len == 0) {
260          break;
261       }
262       query = check_pool_memory_size(query, len + 1);
263       if (*query != 0) {
264          pm_strcat(query, " ");
265       }
266       pm_strcat(query, ua->cmd);
267       if (ua->cmd[len-1] == ';') {
268          ua->cmd[len-1] = 0;          /* zap ; */
269          /* Submit query */
270          db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
271          *query = 0;                  /* start new query */
272          msg = _("Enter SQL query: ");
273       } else {
274          msg = _("Add to SQL query: ");
275       }
276    }
277    free_pool_memory(query);
278    bsendmsg(ua, _("End query mode.\n"));
279    return 1;
280 }