]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/tray-monitor/tray_conf.c
2015f7c88ad913d59f2fcb38d5b87d41f97c25d3
[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    Copyright (C) 2000-2004 Kern Sibbald and John Walker
26
27    This program is free software; you can redistribute it and/or
28    modify it under the terms of the GNU General Public License as
29    published by the Free Software Foundation; either version 2 of
30    the License, or (at your option) any later version.
31
32    This program is distributed in the hope that it will be useful,
33    but WITHOUT ANY WARRANTY; without even the implied warranty of
34    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35    General Public License for more details.
36
37    You should have received a copy of the GNU General Public
38    License along with this program; if not, write to the Free
39    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
40    MA 02111-1307, USA.
41
42 */
43
44 #include "bacula.h"
45 #include "tray_conf.h"
46
47 /* Define the first and last resource ID record
48 * types. Note, these should be unique for each
49 * daemon though not a requirement.
50 */
51 int r_first = R_FIRST;
52 int r_last  = R_LAST;
53 static RES *sres_head[R_LAST - R_FIRST + 1];
54 RES **res_head = sres_head;
55
56 /* We build the current resource here as we are
57 * scanning the resource configuration definition,
58 * then move it to allocated memory when the resource
59 * scan is complete.
60 */
61 URES res_all;
62 int  res_all_size = sizeof(res_all);
63
64
65 /* Definition of records permitted within each
66 * resource with the routine to process the record 
67 * information.  NOTE! quoted names must be in lower case.
68 */ 
69 /* 
70 *    Monitor Resource
71 *
72 *   name           handler     value                 code flags    default_value
73 */
74 static RES_ITEM dir_items[] = {
75    {"name",        store_name,     ITEM(res_monitor.hdr.name), 0, ITEM_REQUIRED, 0},
76    {"description", store_str,      ITEM(res_monitor.hdr.desc), 0, 0, 0},
77    {"requiressl",  store_yesno,    ITEM(res_monitor.require_ssl), 1, ITEM_DEFAULT, 0},
78    {"fdconnecttimeout", store_time,ITEM(res_monitor.FDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30},
79    {"sdconnecttimeout", store_time,ITEM(res_monitor.SDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30},
80    {NULL, NULL, NULL, 0, 0, 0}
81 };
82
83 /* 
84 *    Client or File daemon resource
85 *
86 *   name           handler     value                 code flags    default_value
87 */
88
89 static RES_ITEM cli_items[] = {
90    {"name",     store_name,       ITEM(res_client.hdr.name), 0, ITEM_REQUIRED, 0},
91    {"description", store_str,     ITEM(res_client.hdr.desc), 0, 0, 0},
92    {"address",  store_str,        ITEM(res_client.address),  0, ITEM_REQUIRED, 0},
93    {"fdaddress",  store_str,      ITEM(res_client.address),  0, 0, 0},
94    {"fdport",   store_pint,       ITEM(res_client.FDport),   0, ITEM_DEFAULT, 9102},
95    {"password", store_password,   ITEM(res_client.password), 0, ITEM_REQUIRED, 0},
96    {"fdpassword", store_password,   ITEM(res_client.password), 0, 0, 0},
97    {"enablessl", store_yesno,     ITEM(res_client.enable_ssl), 1, ITEM_DEFAULT, 0},
98    {NULL, NULL, NULL, 0, 0, 0} 
99 };
100
101 /* Storage daemon resource
102 *
103 *   name           handler     value                 code flags    default_value
104 */
105 static RES_ITEM store_items[] = {
106    {"name",        store_name,     ITEM(res_store.hdr.name),   0, ITEM_REQUIRED, 0},
107    {"description", store_str,      ITEM(res_store.hdr.desc),   0, 0, 0},
108    {"sdport",      store_pint,     ITEM(res_store.SDport),     0, ITEM_DEFAULT, 9103},
109    {"address",     store_str,      ITEM(res_store.address),    0, ITEM_REQUIRED, 0},
110    {"sdaddress",   store_str,      ITEM(res_store.address),    0, 0, 0},
111    {"password",    store_password, ITEM(res_store.password),   0, ITEM_REQUIRED, 0},
112    {"sdpassword",  store_password, ITEM(res_store.password),   0, 0, 0},
113    {"enablessl",   store_yesno,    ITEM(res_store.enable_ssl),  1, ITEM_DEFAULT, 0},
114    {NULL, NULL, NULL, 0, 0, 0} 
115 };
116
117 /* 
118 * This is the master resource definition.  
119 * It must have one item for each of the resources.
120 *
121 *  NOTE!!! keep it in the same order as the R_codes
122 *    or eliminate all resources[rindex].name
123 *
124 *  name      items        rcode        res_head
125 */
126 RES_TABLE resources[] = {
127    {"monitor",      dir_items,    R_MONITOR},
128    {"client",        cli_items,   R_CLIENT},
129    {"storage",       store_items, R_STORAGE},
130    {NULL,            NULL,        0}
131 };
132
133 /* Dump contents of resource */
134 void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fmt, ...), void *sock)
135 {
136    URES *res = (URES *)reshdr;
137    bool recurse = true;
138    char ed1[100], ed2[100];
139
140    if (res == NULL) {
141       sendit(sock, "No %s resource defined\n", res_to_str(type));
142       return;
143    }
144    if (type < 0) {                    /* no recursion */
145       type = - type;
146       recurse = false;
147    }
148    switch (type) {
149    case R_MONITOR:
150       sendit(sock, "Director: name=%s FDtimeout=%s SDtimeout=%s\n", 
151    reshdr->name, 
152    edit_uint64(res->res_monitor.FDConnectTimeout, ed1),
153    edit_uint64(res->res_monitor.SDConnectTimeout, ed2));
154       break;
155    case R_CLIENT:
156       sendit(sock, "Client: name=%s address=%s FDport=%d\n",
157    res->res_client.hdr.name, res->res_client.address, res->res_client.FDport);
158       break;
159    case R_STORAGE:
160       sendit(sock, "Storage: name=%s address=%s SDport=%d\n",
161    res->res_store.hdr.name, res->res_store.address, res->res_store.SDport);
162       break;
163    default:
164       sendit(sock, "Unknown resource type %d in dump_resource.\n", type);
165       break;
166    }
167    if (recurse && res->res_monitor.hdr.next) {
168       dump_resource(type, res->res_monitor.hdr.next, sendit, sock);
169    }
170 }
171
172
173 /* 
174 * Free memory of resource -- called when daemon terminates.
175 * NB, we don't need to worry about freeing any references
176 * to other resources as they will be freed when that 
177 * resource chain is traversed.  Mainly we worry about freeing
178 * allocated strings (names).
179 */
180 void free_resource(RES *sres, int type)
181 {
182    RES *nres;                         /* next resource if linked */
183    URES *res = (URES *)sres;
184
185    if (res == NULL)
186       return;
187
188    /* common stuff -- free the resource name and description */
189    nres = (RES *)res->res_monitor.hdr.next;
190    if (res->res_monitor.hdr.name) {
191       free(res->res_monitor.hdr.name);
192    }
193    if (res->res_monitor.hdr.desc) {
194       free(res->res_monitor.hdr.desc);
195    }
196
197    switch (type) {
198    case R_MONITOR:
199       break;
200    case R_CLIENT:
201       if (res->res_client.address) {
202    free(res->res_client.address);
203       }
204       if (res->res_client.password) {
205    free(res->res_client.password);
206       }
207       break;
208    case R_STORAGE:
209       if (res->res_store.address) {
210    free(res->res_store.address);
211       }
212       if (res->res_store.password) {
213    free(res->res_store.password);
214       }
215       break;
216    default:
217       printf("Unknown resource type %d in free_resource.\n", type);
218    }
219    /* Common stuff again -- free the resource, recurse to next one */
220    if (res) {
221       free(res);
222    }
223    if (nres) {
224       free_resource(nres, type);
225    }
226 }
227
228 /*
229 * Save the new resource by chaining it into the head list for
230 * the resource. If this is pass 2, we update any resource
231 * pointers because they may not have been defined until 
232 * later in pass 1.
233 */
234 void save_resource(int type, RES_ITEM *items, int pass)
235 {
236    URES *res;
237    int rindex = type - r_first;
238    int i, size;
239    int error = 0;
240    
241    /* 
242    * Ensure that all required items are present
243    */
244    for (i=0; items[i].name; i++) {
245       if (items[i].flags & ITEM_REQUIRED) {
246          if (!bit_is_set(i, res_all.res_monitor.hdr.item_present)) {
247                Emsg2(M_ERROR_TERM, 0, "%s item is required in %s resource, but not found.\n",
248                   items[i].name, resources[rindex]);
249          }
250       }
251       /* If this triggers, take a look at lib/parse_conf.h */
252       if (i >= MAX_RES_ITEMS) {
253          Emsg1(M_ERROR_TERM, 0, "Too many items in %s resource\n", resources[rindex]);
254       }
255    }
256
257    /*
258    * During pass 2 in each "store" routine, we looked up pointers 
259    * to all the resources referrenced in the current resource, now we
260    * must copy their addresses from the static record to the allocated
261    * record.
262    */
263    if (pass == 2) {
264       switch (type) {
265       /* Resources not containing a resource */
266       case R_MONITOR:
267       case R_CLIENT:
268       case R_STORAGE:
269          break;
270       default:
271          Emsg1(M_ERROR, 0, "Unknown resource type %d in save_resource.\n", type);
272          error = 1;
273          break;
274       }
275       /* Note, the resource name was already saved during pass 1,
276       * so here, we can just release it.
277       */
278       if (res_all.res_monitor.hdr.name) {
279          free(res_all.res_monitor.hdr.name);
280          res_all.res_monitor.hdr.name = NULL;
281       }
282       if (res_all.res_monitor.hdr.desc) {
283          free(res_all.res_monitor.hdr.desc);
284          res_all.res_monitor.hdr.desc = NULL;
285       }
286       return;
287    }
288
289    /*
290    * The following code is only executed during pass 1   
291    */
292    switch (type) {
293    case R_MONITOR:
294       size = sizeof(MONITOR);
295       break;
296    case R_CLIENT:
297       size =sizeof(CLIENT);
298       break;
299    case R_STORAGE:
300       size = sizeof(STORE); 
301       break;
302    default:
303       printf("Unknown resource type %d in save_resrouce.\n", type);
304       error = 1;
305       size = 1;
306       break;
307    }
308    /* Common */
309    if (!error) {
310       res = (URES *)malloc(size);
311       memcpy(res, &res_all, size);
312       if (!res_head[rindex]) {
313    res_head[rindex] = (RES *)res; /* store first entry */
314          Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type),
315          res->res_monitor.hdr.name, rindex);
316       } else {
317    RES *next;
318    /* Add new res to end of chain */
319    for (next=res_head[rindex]; next->next; next=next->next) {
320       if (strcmp(next->name, res->res_monitor.hdr.name) == 0) {
321          Emsg2(M_ERROR_TERM, 0,
322                   _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
323          resources[rindex].name, res->res_monitor.hdr.name);
324       }
325    }
326    next->next = (RES *)res;
327          Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type),
328          res->res_monitor.hdr.name, rindex, pass);
329       }
330    }
331 }