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