]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/tray-monitor/tray_conf.c
Fix bug # 746 - Windows FD crashes when job canceled
[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 /*
136 * This is the master resource definition.
137 * It must have one item for each of the resources.
138 *
139 *  NOTE!!! keep it in the same order as the R_codes
140 *    or eliminate all resources[rindex].name
141 *
142 *  name      items        rcode        res_head
143 */
144 RES_TABLE resources[] = {
145    {"monitor",      mon_items,    R_MONITOR},
146    {"director",     dir_items,    R_DIRECTOR},
147    {"client",       cli_items,    R_CLIENT},
148    {"storage",      store_items,  R_STORAGE},
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    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    default:
240       printf(_("Unknown resource type %d in free_resource.\n"), type);
241    }
242    /* Common stuff again -- free the resource, recurse to next one */
243    if (res) {
244       free(res);
245    }
246    if (nres) {
247       free_resource(nres, type);
248    }
249 }
250
251 /*
252 * Save the new resource by chaining it into the head list for
253 * the resource. If this is pass 2, we update any resource
254 * pointers because they may not have been defined until
255 * later in pass 1.
256 */
257 void save_resource(int type, RES_ITEM *items, int pass)
258 {
259    URES *res;
260    int rindex = type - r_first;
261    int i, size;
262    int error = 0;
263
264    /*
265    * Ensure that all required items are present
266    */
267    for (i=0; items[i].name; i++) {
268       if (items[i].flags & ITEM_REQUIRED) {
269          if (!bit_is_set(i, res_all.res_monitor.hdr.item_present)) {
270                Emsg2(M_ERROR_TERM, 0, _("%s item is required in %s resource, but not found.\n"),
271                   items[i].name, resources[rindex]);
272          }
273       }
274       /* If this triggers, take a look at lib/parse_conf.h */
275       if (i >= MAX_RES_ITEMS) {
276          Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
277       }
278    }
279
280    /*
281    * During pass 2 in each "store" routine, we looked up pointers
282    * to all the resources referrenced in the current resource, now we
283    * must copy their addresses from the static record to the allocated
284    * record.
285    */
286    if (pass == 2) {
287       switch (type) {
288       /* Resources not containing a resource */
289       case R_MONITOR:
290       case R_CLIENT:
291       case R_STORAGE:
292       case R_DIRECTOR:
293          break;
294       default:
295          Emsg1(M_ERROR, 0, _("Unknown resource type %d in save_resource.\n"), type);
296          error = 1;
297          break;
298       }
299       /* Note, the resource name was already saved during pass 1,
300       * so here, we can just release it.
301       */
302       if (res_all.res_monitor.hdr.name) {
303          free(res_all.res_monitor.hdr.name);
304          res_all.res_monitor.hdr.name = NULL;
305       }
306       if (res_all.res_monitor.hdr.desc) {
307          free(res_all.res_monitor.hdr.desc);
308          res_all.res_monitor.hdr.desc = NULL;
309       }
310       return;
311    }
312
313    /*
314    * The following code is only executed during pass 1
315    */
316    switch (type) {
317    case R_MONITOR:
318       size = sizeof(MONITOR);
319       break;
320    case R_DIRECTOR:
321       size = sizeof(DIRRES);
322       break;
323    case R_CLIENT:
324       size = sizeof(CLIENT);
325       break;
326    case R_STORAGE:
327       size = sizeof(STORE);
328       break;
329    default:
330       printf(_("Unknown resource type %d in save_resource.\n"), type);
331       error = 1;
332       size = 1;
333       break;
334    }
335    /* Common */
336    if (!error) {
337       res = (URES *)malloc(size);
338       memcpy(res, &res_all, size);
339       if (!res_head[rindex]) {
340         res_head[rindex] = (RES *)res; /* store first entry */
341          Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type),
342          res->res_monitor.hdr.name, rindex);
343       } else {
344          RES *next, *last;
345          /* Add new res to end of chain */
346          for (last=next=res_head[rindex]; next; next=next->next) {
347             last = next;
348             if (strcmp(next->name, res->res_monitor.hdr.name) == 0) {
349                Emsg2(M_ERROR_TERM, 0,
350                   _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
351                resources[rindex].name, res->res_monitor.hdr.name);
352             }
353          }
354          last->next = (RES *)res;
355          Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type),
356          res->res_monitor.hdr.name, rindex, pass);
357       }
358    }
359 }