]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/tray-monitor/tray_conf.cpp
Backport from BEE
[bacula/bacula] / bacula / src / qt-console / tray-monitor / tray_conf.cpp
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2004-2014 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from many
7    others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    Bacula® is a registered trademark of Kern Sibbald.
15 */
16 /*
17 *   Main configuration file parser for Bacula Tray Monitor.
18 *
19 *   Adapted from dird_conf.c
20 *
21 *   Note, the configuration file parser consists of three parts
22 *
23 *   1. The generic lexical scanner in lib/lex.c and lib/lex.h
24 *
25 *   2. The generic config  scanner in lib/parse_config.c and
26 *       lib/parse_config.h.
27 *       These files contain the parser code, some utility
28 *       routines, and the common store routines (name, int,
29 *       string).
30 *
31 *   3. The daemon specific file, which contains the Resource
32 *       definitions as well as any specific store routines
33 *       for the resource records.
34 *
35 *     Nicolas Boichat, August MMIV
36 *
37 */
38
39 #include "bacula.h"
40 #include "tray_conf.h"
41
42 /* Define the first and last resource ID record
43 * types. Note, these should be unique for each
44 * daemon though not a requirement.
45 */
46 int32_t r_first = R_FIRST;
47 int32_t r_last  = R_LAST;
48 static RES *sres_head[R_LAST - R_FIRST + 1];
49 RES **res_head = sres_head;
50
51 /* We build the current resource here as we are
52 * scanning the resource configuration definition,
53 * then move it to allocated memory when the resource
54 * scan is complete.
55 */
56 URES res_all;
57 int32_t res_all_size = sizeof(res_all);
58
59
60 /* Definition of records permitted within each
61 * resource with the routine to process the record
62 * information.  NOTE! quoted names must be in lower case.
63 */
64 /*
65 *    Monitor Resource
66 *
67 *   name           handler     value                 code flags    default_value
68 */
69 static RES_ITEM mon_items[] = {
70    {"name",        store_name,     ITEM(res_monitor.hdr.name), 0, ITEM_REQUIRED, 0},
71    {"description", store_str,      ITEM(res_monitor.hdr.desc), 0, 0, 0},
72    {"requiressl",  store_bool,     ITEM(res_monitor.require_ssl), 1, ITEM_DEFAULT, 0},
73    {"password",    store_password, ITEM(res_monitor.password), 0, ITEM_REQUIRED, 0},
74    {"refreshinterval",  store_time,ITEM(res_monitor.RefreshInterval),    0, ITEM_DEFAULT, 60},
75    {"fdconnecttimeout", store_time,ITEM(res_monitor.FDConnectTimeout),   0, ITEM_DEFAULT, 10},
76    {"sdconnecttimeout", store_time,ITEM(res_monitor.SDConnectTimeout),   0, ITEM_DEFAULT, 10},
77    {"dirconnecttimeout", store_time,ITEM(res_monitor.DIRConnectTimeout), 0, ITEM_DEFAULT, 10},
78    {NULL, NULL, {0}, 0, 0, 0}
79 };
80
81 /*  Director's that we can contact */
82 static RES_ITEM dir_items[] = {
83    {"name",        store_name,     ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0},
84    {"description", store_str,      ITEM(res_dir.hdr.desc), 0, 0, 0},
85    {"dirport",     store_pint32,   ITEM(res_dir.DIRport),  0, ITEM_DEFAULT, 9101},
86    {"address",     store_str,      ITEM(res_dir.address),  0, ITEM_REQUIRED, 0},
87    {"enablessl",   store_bool,     ITEM(res_dir.enable_ssl), 1, ITEM_DEFAULT, 0},
88    {NULL, NULL, {0}, 0, 0, 0}
89 };
90
91 /*
92 *    Client or File daemon resource
93 *
94 *   name           handler     value                 code flags    default_value
95 */
96
97 static RES_ITEM cli_items[] = {
98    {"name",     store_name,       ITEM(res_client.hdr.name), 0, ITEM_REQUIRED, 0},
99    {"description", store_str,     ITEM(res_client.hdr.desc), 0, 0, 0},
100    {"address",  store_str,        ITEM(res_client.address),  0, ITEM_REQUIRED, 0},
101    {"fdport",   store_pint32,     ITEM(res_client.FDport),   0, ITEM_DEFAULT, 9102},
102    {"password", store_password,   ITEM(res_client.password), 0, ITEM_REQUIRED, 0},
103    {"enablessl", store_bool,      ITEM(res_client.enable_ssl), 1, ITEM_DEFAULT, 0},
104    {NULL, NULL, {0}, 0, 0, 0}
105 };
106
107 /* Storage daemon resource
108 *
109 *   name           handler     value                 code flags    default_value
110 */
111 static RES_ITEM store_items[] = {
112    {"name",        store_name,     ITEM(res_store.hdr.name),   0, ITEM_REQUIRED, 0},
113    {"description", store_str,      ITEM(res_store.hdr.desc),   0, 0, 0},
114    {"sdport",      store_pint32,   ITEM(res_store.SDport),     0, ITEM_DEFAULT, 9103},
115    {"address",     store_str,      ITEM(res_store.address),    0, ITEM_REQUIRED, 0},
116    {"sdaddress",   store_str,      ITEM(res_store.address),    0, 0, 0},
117    {"password",    store_password, ITEM(res_store.password),   0, ITEM_REQUIRED, 0},
118    {"sdpassword",  store_password, ITEM(res_store.password),   0, 0, 0},
119    {"enablessl",   store_bool,     ITEM(res_store.enable_ssl),  1, ITEM_DEFAULT, 0},
120    {NULL, NULL, {0}, 0, 0, 0}
121 };
122
123 static RES_ITEM con_font_items[] = {
124    {"name",        store_name,     ITEM(con_font.hdr.name), 0, ITEM_REQUIRED, 0},
125    {"description", store_str,      ITEM(con_font.hdr.desc), 0, 0, 0},
126    {"font",        store_str,      ITEM(con_font.fontface), 0, 0, 0},
127    {NULL, NULL, {0}, 0, 0, 0}
128 };
129
130 /*
131 * This is the master resource definition.
132 * It must have one item for each of the resources.
133 *
134 *  NOTE!!! keep it in the same order as the R_codes
135 *    or eliminate all resources[rindex].name
136 *
137 *  name      items        rcode        res_head
138 */
139 RES_TABLE resources[] = {
140    {"monitor",      mon_items,    R_MONITOR},
141    {"director",     dir_items,    R_DIRECTOR},
142    {"client",       cli_items,    R_CLIENT},
143    {"storage",      store_items,  R_STORAGE},
144    {"consolefont",   con_font_items, R_CONSOLE_FONT},
145    {NULL,           NULL,         0}
146 };
147
148 /* Dump contents of resource */
149 void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fmt, ...), void *sock)
150 {
151    URES *res = (URES *)reshdr;
152    bool recurse = true;
153    char ed1[100], ed2[100];
154
155    if (res == NULL) {
156       sendit(sock, _("No %s resource defined\n"), res_to_str(type));
157       return;
158    }
159    if (type < 0) {                    /* no recursion */
160       type = - type;
161       recurse = false;
162    }
163    switch (type) {
164    case R_MONITOR:
165       sendit(sock, _("Monitor: name=%s FDtimeout=%s SDtimeout=%s\n"),
166              reshdr->name,
167              edit_uint64(res->res_monitor.FDConnectTimeout, ed1),
168              edit_uint64(res->res_monitor.SDConnectTimeout, ed2));
169       break;
170    case R_DIRECTOR:
171       sendit(sock, _("Director: name=%s address=%s FDport=%d\n"),
172              res->res_dir.hdr.name, res->res_dir.address, res->res_dir.DIRport);
173       break;
174    case R_CLIENT:
175       sendit(sock, _("Client: name=%s address=%s FDport=%d\n"),
176              res->res_client.hdr.name, res->res_client.address, res->res_client.FDport);
177       break;
178    case R_STORAGE:
179       sendit(sock, _("Storage: name=%s address=%s SDport=%d\n"),
180              res->res_store.hdr.name, res->res_store.address, res->res_store.SDport);
181       break;
182    case R_CONSOLE_FONT:
183       sendit(sock, _("ConsoleFont: name=%s font face=%s\n"),
184              reshdr->name, NPRT(res->con_font.fontface));
185       break;
186    default:
187       sendit(sock, _("Unknown resource type %d in dump_resource.\n"), type);
188       break;
189    }
190    if (recurse && res->res_monitor.hdr.next) {
191       dump_resource(type, res->res_monitor.hdr.next, sendit, sock);
192    }
193 }
194
195
196 /*
197 * Free memory of resource -- called when daemon terminates.
198 * NB, we don't need to worry about freeing any references
199 * to other resources as they will be freed when that
200 * resource chain is traversed.  Mainly we worry about freeing
201 * allocated strings (names).
202 */
203 void free_resource(RES *sres, int type)
204 {
205    RES *nres;                         /* next resource if linked */
206    URES *res = (URES *)sres;
207
208    if (res == NULL)
209       return;
210
211    /* common stuff -- free the resource name and description */
212    nres = (RES *)res->res_monitor.hdr.next;
213    if (res->res_monitor.hdr.name) {
214       free(res->res_monitor.hdr.name);
215    }
216    if (res->res_monitor.hdr.desc) {
217       free(res->res_monitor.hdr.desc);
218    }
219
220    switch (type) {
221    case R_MONITOR:
222       break;
223    case R_CLIENT:
224       if (res->res_client.address) {
225          free(res->res_client.address);
226       }
227       if (res->res_client.password) {
228          free(res->res_client.password);
229       }
230       break;
231    case R_STORAGE:
232       if (res->res_store.address) {
233          free(res->res_store.address);
234       }
235       if (res->res_store.password) {
236          free(res->res_store.password);
237       }
238       break;
239    case R_CONSOLE_FONT:
240       if (res->con_font.fontface) {
241          free(res->con_font.fontface);
242       }
243       break;
244    default:
245       printf(_("Unknown resource type %d in free_resource.\n"), type);
246    }
247
248    /* Common stuff again -- free the resource, recurse to next one */
249    if (res) {
250       free(res);
251    }
252    if (nres) {
253       free_resource(nres, type);
254    }
255 }
256
257 /*
258 * Save the new resource by chaining it into the head list for
259 * the resource. If this is pass 2, we update any resource
260 * pointers because they may not have been defined until
261 * later in pass 1.
262 */
263 void save_resource(int type, RES_ITEM *items, int pass)
264 {
265    URES *res;
266    int rindex = type - r_first;
267    int i, size;
268    int error = 0;
269
270    /*
271    * Ensure that all required items are present
272    */
273    for (i=0; items[i].name; i++) {
274       if (items[i].flags & ITEM_REQUIRED) {
275          if (!bit_is_set(i, res_all.res_monitor.hdr.item_present)) {
276                Emsg2(M_ERROR_TERM, 0, _("%s item is required in %s resource, but not found.\n"),
277                   items[i].name, resources[rindex]);
278          }
279       }
280       /* If this triggers, take a look at lib/parse_conf.h */
281       if (i >= MAX_RES_ITEMS) {
282          Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
283       }
284    }
285
286    /*
287    * During pass 2 in each "store" routine, we looked up pointers
288    * to all the resources referrenced in the current resource, now we
289    * must copy their addresses from the static record to the allocated
290    * record.
291    */
292    if (pass == 2) {
293       switch (type) {
294       /* Resources not containing a resource */
295       case R_MONITOR:
296       case R_CLIENT:
297       case R_STORAGE:
298       case R_DIRECTOR:
299       case R_CONSOLE_FONT:
300          break;
301       default:
302          Emsg1(M_ERROR, 0, _("Unknown resource type %d in save_resource.\n"), type);
303          error = 1;
304          break;
305       }
306       /* Note, the resource name was already saved during pass 1,
307       * so here, we can just release it.
308       */
309       if (res_all.res_monitor.hdr.name) {
310          free(res_all.res_monitor.hdr.name);
311          res_all.res_monitor.hdr.name = NULL;
312       }
313       if (res_all.res_monitor.hdr.desc) {
314          free(res_all.res_monitor.hdr.desc);
315          res_all.res_monitor.hdr.desc = NULL;
316       }
317       return;
318    }
319
320    /*
321    * The following code is only executed during pass 1
322    */
323    switch (type) {
324    case R_MONITOR:
325       size = sizeof(MONITOR);
326       break;
327    case R_DIRECTOR:
328       size = sizeof(DIRRES);
329       break;
330    case R_CLIENT:
331       size = sizeof(CLIENT);
332       break;
333    case R_STORAGE:
334       size = sizeof(STORE);
335       break;
336    case R_CONSOLE_FONT:
337       size = sizeof(CONFONTRES);
338       break;
339    default:
340       printf(_("Unknown resource type %d in save_resource.\n"), type);
341       error = 1;
342       size = 1;
343       break;
344    }
345    /* Common */
346    if (!error) {
347       res = (URES *)malloc(size);
348       memcpy(res, &res_all, size);
349       if (!res_head[rindex]) {
350         res_head[rindex] = (RES *)res; /* store first entry */
351          Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type),
352          res->res_monitor.hdr.name, rindex);
353       } else {
354          RES *next, *last;
355          /* Add new res to end of chain */
356          for (last=next=res_head[rindex]; next; next=next->next) {
357             last = next;
358             if (strcmp(next->name, res->res_monitor.hdr.name) == 0) {
359                Emsg2(M_ERROR_TERM, 0,
360                   _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
361                resources[rindex].name, res->res_monitor.hdr.name);
362             }
363          }
364          last->next = (RES *)res;
365          Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type),
366          res->res_monitor.hdr.name, rindex, pass);
367       }
368    }
369 }
370
371 bool parse_tmon_config(CONFIG *config, const char *configfile, int exit_code)
372 {
373    config->init(configfile, NULL, exit_code, (void *)&res_all, res_all_size,
374       r_first, r_last, resources, res_head);
375    return config->parse_config();
376 }