]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/tray-monitor/tray_conf.c
add src/tray-monitor directory
[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    int num;
183    RES *nres;                         /* next resource if linked */
184    URES *res = (URES *)sres;
185
186    if (res == NULL)
187       return;
188
189    /* common stuff -- free the resource name and description */
190    nres = (RES *)res->res_monitor.hdr.next;
191    if (res->res_monitor.hdr.name) {
192       free(res->res_monitor.hdr.name);
193    }
194    if (res->res_monitor.hdr.desc) {
195       free(res->res_monitor.hdr.desc);
196    }
197
198    switch (type) {
199    case R_MONITOR:
200       break;
201    case R_CLIENT:
202       if (res->res_client.address) {
203    free(res->res_client.address);
204       }
205       if (res->res_client.password) {
206    free(res->res_client.password);
207       }
208       break;
209    case R_STORAGE:
210       if (res->res_store.address) {
211    free(res->res_store.address);
212       }
213       if (res->res_store.password) {
214    free(res->res_store.password);
215       }
216       break;
217    default:
218       printf("Unknown resource type %d in free_resource.\n", type);
219    }
220    /* Common stuff again -- free the resource, recurse to next one */
221    if (res) {
222       free(res);
223    }
224    if (nres) {
225       free_resource(nres, type);
226    }
227 }
228
229 /*
230 * Save the new resource by chaining it into the head list for
231 * the resource. If this is pass 2, we update any resource
232 * pointers because they may not have been defined until 
233 * later in pass 1.
234 */
235 void save_resource(int type, RES_ITEM *items, int pass)
236 {
237    URES *res;
238    int rindex = type - r_first;
239    int i, size;
240    int error = 0;
241    
242    /* 
243    * Ensure that all required items are present
244    */
245    for (i=0; items[i].name; i++) {
246       if (items[i].flags & ITEM_REQUIRED) {
247          if (!bit_is_set(i, res_all.res_monitor.hdr.item_present)) {
248                Emsg2(M_ERROR_TERM, 0, "%s item is required in %s resource, but not found.\n",
249                   items[i].name, resources[rindex]);
250          }
251       }
252       /* If this triggers, take a look at lib/parse_conf.h */
253       if (i >= MAX_RES_ITEMS) {
254          Emsg1(M_ERROR_TERM, 0, "Too many items in %s resource\n", resources[rindex]);
255       }
256    }
257
258    /*
259    * During pass 2 in each "store" routine, we looked up pointers 
260    * to all the resources referrenced in the current resource, now we
261    * must copy their addresses from the static record to the allocated
262    * record.
263    */
264    if (pass == 2) {
265       switch (type) {
266       /* Resources not containing a resource */
267       case R_MONITOR:
268       case R_CLIENT:
269       case R_STORAGE:
270          break;
271       default:
272          Emsg1(M_ERROR, 0, "Unknown resource type %d in save_resource.\n", type);
273          error = 1;
274          break;
275       }
276       /* Note, the resource name was already saved during pass 1,
277       * so here, we can just release it.
278       */
279       if (res_all.res_monitor.hdr.name) {
280          free(res_all.res_monitor.hdr.name);
281          res_all.res_monitor.hdr.name = NULL;
282       }
283       if (res_all.res_monitor.hdr.desc) {
284          free(res_all.res_monitor.hdr.desc);
285          res_all.res_monitor.hdr.desc = NULL;
286       }
287       return;
288    }
289
290    /*
291    * The following code is only executed during pass 1   
292    */
293    switch (type) {
294    case R_MONITOR:
295       size = sizeof(MONITOR);
296       break;
297    case R_CLIENT:
298       size =sizeof(CLIENT);
299       break;
300    case R_STORAGE:
301       size = sizeof(STORE); 
302       break;
303    default:
304       printf("Unknown resource type %d in save_resrouce.\n", type);
305       error = 1;
306       size = 1;
307       break;
308    }
309    /* Common */
310    if (!error) {
311       res = (URES *)malloc(size);
312       memcpy(res, &res_all, size);
313       if (!res_head[rindex]) {
314    res_head[rindex] = (RES *)res; /* store first entry */
315          Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type),
316          res->res_monitor.hdr.name, rindex);
317       } else {
318    RES *next;
319    /* Add new res to end of chain */
320    for (next=res_head[rindex]; next->next; next=next->next) {
321       if (strcmp(next->name, res->res_monitor.hdr.name) == 0) {
322          Emsg2(M_ERROR_TERM, 0,
323                   _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
324          resources[rindex].name, res->res_monitor.hdr.name);
325       }
326    }
327    next->next = (RES *)res;
328          Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type),
329          res->res_monitor.hdr.name, rindex, pass);
330       }
331    }
332 }