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