]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_query.c
Re-enable the new job code editing (%f).
[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    Bacula® - The Network Backup Solution
11
12    Copyright (C) 2001-2006 Free Software Foundation Europe e.V.
13
14    The main author of Bacula is Kern Sibbald, with contributions from
15    many others, a complete list can be found in the file AUTHORS.
16    This program is Free Software; you can redistribute it and/or
17    modify it under the terms of version two of the GNU General Public
18    License as published by the Free Software Foundation and included
19    in the file LICENSE.
20
21    This program is distributed in the hope that it will be useful, but
22    WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24    General Public License for more details.
25
26    You should have received a copy of the GNU General Public License
27    along with this program; if not, write to the Free Software
28    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29    02110-1301, USA.
30
31    Bacula® is a registered trademark of John Walker.
32    The licensor of Bacula is the Free Software Foundation Europe
33    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
34    Switzerland, email:ftf@fsfeurope.org.
35 */
36
37 #include "bacula.h"
38 #include "dird.h"
39
40 extern DIRRES *director;
41
42 static POOLMEM *substitute_prompts(UAContext *ua,
43                        POOLMEM *query, char **prompt, int nprompt);
44
45 /*
46  * Read a file containing SQL queries and prompt
47  *  the user to select which one.
48  *
49  *   File format:
50  *   #  => comment
51  *   :prompt for query
52  *   *prompt for subst %1
53  *   *prompt for subst %2
54  *   ...
55  *   SQL statement possibly terminated by ;
56  *   :next query prompt
57  */
58 int querycmd(UAContext *ua, const char *cmd)
59 {
60    FILE *fd = NULL;
61    POOLMEM *query = get_pool_memory(PM_MESSAGE);
62    char line[1000];
63    int i, item, len;
64    char *prompt[9];
65    int nprompt = 0;;
66    char *query_file = director->query_file;
67
68    if (!open_client_db(ua)) {
69       goto bail_out;
70    }
71    if ((fd=fopen(query_file, "rb")) == NULL) {
72       berrno be;
73       ua->error_msg(_("Could not open %s: ERR=%s\n"), query_file,
74          be.bstrerror());
75       goto bail_out;
76    }
77
78    start_prompt(ua, _("Available queries:\n"));
79    while (fgets(line, sizeof(line), fd) != NULL) {
80       if (line[0] == ':') {
81          strip_trailing_junk(line);
82          add_prompt(ua, line+1);
83       }
84    }
85    if ((item=do_prompt(ua, "", _("Choose a query"), NULL, 0)) < 0) {
86       goto bail_out;
87    }
88    rewind(fd);
89    i = -1;
90    while (fgets(line, sizeof(line), fd) != NULL) {
91       if (line[0] == ':') {
92          i++;
93       }
94       if (i == item) {
95          break;
96       }
97    }
98    if (i != item) {
99       ua->error_msg(_("Could not find query.\n"));
100       goto bail_out;
101    }
102    query[0] = 0;
103    for (i=0; i<9; i++) {
104       prompt[i] = NULL;
105    }
106    while (fgets(line, sizeof(line), fd) != NULL) {
107       if (line[0] == '#') {
108          continue;
109       }
110       if (line[0] == ':') {
111          break;
112       }
113       strip_trailing_junk(line);
114       len = strlen(line);
115       if (line[0] == '*') {            /* prompt */
116          if (nprompt >= 9) {
117             ua->error_msg(_("Too many prompts in query, max is 9.\n"));
118          } else {
119             line[len++] = ' ';
120             line[len] = 0;
121             prompt[nprompt++] = bstrdup(line+1);
122             continue;
123          }
124       }
125       if (*query != 0) {
126          pm_strcat(query, " ");
127       }
128       pm_strcat(query, line);
129       if (line[len-1] != ';') {
130          continue;
131       }
132       line[len-1] = 0;             /* zap ; */
133       if (query[0] != 0) {
134          query = substitute_prompts(ua, query, prompt, nprompt);
135          Dmsg1(100, "Query2=%s\n", query);
136          if (query[0] == '!') {
137             db_list_sql_query(ua->jcr, ua->db, query+1, prtit, ua, 0, VERT_LIST);
138          } else if (!db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST)) {
139             ua->send_msg("%s\n", query);
140          }
141          query[0] = 0;
142       }
143    } /* end while */
144
145    if (query[0] != 0) {
146       query = substitute_prompts(ua, query, prompt, nprompt);
147       Dmsg1(100, "Query2=%s\n", query);
148          if (query[0] == '!') {
149             db_list_sql_query(ua->jcr, ua->db, query+1, prtit, ua, 0, VERT_LIST);
150          } else if (!db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST)) {
151             ua->error_msg("%s\n", query);
152          }
153    }
154
155 bail_out:
156    if (fd) {
157       fclose(fd);
158    }
159    free_pool_memory(query);
160    for (i=0; i<nprompt; i++) {
161       free(prompt[i]);
162    }
163    return 1;
164 }
165
166 static POOLMEM *substitute_prompts(UAContext *ua,
167                        POOLMEM *query, char **prompt, int nprompt)
168 {
169    char *p, *q, *o;
170    POOLMEM *new_query;
171    int i, n, len, olen;
172    char *subst[9];
173
174    if (nprompt == 0) {
175       return query;
176    }
177    for (i=0; i<9; i++) {
178       subst[i] = NULL;
179    }
180    new_query = get_pool_memory(PM_FNAME);
181    o = new_query;
182    for (q=query; (p=strchr(q, '%')); ) {
183       if (p) {
184         olen = o - new_query;
185         new_query = check_pool_memory_size(new_query, olen + p - q + 10);
186         o = new_query + olen;
187          while (q < p) {              /* copy up to % */
188             *o++ = *q++;
189          }
190          p++;
191          switch (*p) {
192          case '1':
193          case '2':
194          case '3':
195          case '4':
196          case '5':
197          case '6':
198          case '7':
199          case '8':
200          case '9':
201             n = (int)(*p) - (int)'1';
202             if (prompt[n]) {
203                if (!subst[n]) {
204                   if (!get_cmd(ua, prompt[n])) {
205                      q += 2;
206                      break;
207                   }
208                }
209                len = strlen(ua->cmd);
210                p = (char *)malloc(len * 2 + 1);
211                db_escape_string(ua->jcr, ua->db, p, ua->cmd, len);
212                subst[n] = p;
213                olen = o - new_query;
214                new_query = check_pool_memory_size(new_query, olen + strlen(p) + 10);
215                o = new_query + olen;
216                while (*p) {
217                   *o++ = *p++;
218                }
219             } else {
220                ua->error_msg(_("Warning prompt %d missing.\n"), n+1);
221             }
222             q += 2;
223             break;
224          case '%':
225             *o++ = '%';
226             q += 2;
227             break;
228          default:
229             *o++ = '%';
230             q++;
231             break;
232          }
233       }
234    }
235    olen = o - new_query;
236    new_query = check_pool_memory_size(new_query, olen + strlen(q) + 10);
237    o = new_query + olen;
238    while (*q) {
239       *o++ = *q++;
240    }
241    *o = 0;
242    for (i=0; i<9; i++) {
243       if (subst[i]) {
244          free(subst[i]);
245       }
246    }
247    free_pool_memory(query);
248    return new_query;
249 }
250
251 /*
252  * Get general SQL query for Catalog
253  */
254 int sqlquerycmd(UAContext *ua, const char *cmd)
255 {
256    POOL_MEM query(PM_MESSAGE);
257    int len;
258    const char *msg;
259
260    if (!open_client_db(ua)) {
261       return 1;
262    }
263    *query.c_str() = 0;
264
265    ua->send_msg(_("Entering SQL query mode.\n"
266 "Terminate each query with a semicolon.\n"
267 "Terminate query mode with a blank line.\n"));
268    msg = _("Enter SQL query: ");
269    while (get_cmd(ua, msg)) {
270       len = strlen(ua->cmd);
271       Dmsg2(400, "len=%d cmd=%s:\n", len, ua->cmd);
272       if (len == 0) {
273          break;
274       }
275       if (*query.c_str() != 0) {
276          pm_strcat(query, " ");
277       }
278       pm_strcat(query, ua->cmd);
279       if (ua->cmd[len-1] == ';') {
280          ua->cmd[len-1] = 0;          /* zap ; */
281          /* Submit query */
282          db_list_sql_query(ua->jcr, ua->db, query.c_str(), prtit, ua, 1, HORZ_LIST);
283          *query.c_str() = 0;         /* start new query */
284          msg = _("Enter SQL query: ");
285       } else {
286          msg = _("Add to SQL query: ");
287       }
288    }
289    ua->send_msg(_("End query mode.\n"));
290    return 1;
291 }