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