]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/tray-monitor/tray_conf.c
AIX also supports setmntent/getmntent so use that instead of much more complicated...
[bacula/bacula] / bacula / src / tray-monitor / tray_conf.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2004-2008 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29 *   Main configuration file parser for Bacula Tray Monitor.
30 *
31 *   Adapted from dird_conf.c
32 *
33 *   Note, the configuration file parser consists of three parts
34 *
35 *   1. The generic lexical scanner in lib/lex.c and lib/lex.h
36 *
37 *   2. The generic config  scanner in lib/parse_config.c and
38 *       lib/parse_config.h.
39 *       These files contain the parser code, some utility
40 *       routines, and the common store routines (name, int,
41 *       string).
42 *
43 *   3. The daemon specific file, which contains the Resource
44 *       definitions as well as any specific store routines
45 *       for the resource records.
46 *
47 *     Nicolas Boichat, August MMIV
48 *
49 *     Version $Id$
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 int32_t r_first = R_FIRST;
60 int32_t 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 int32_t 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_bool,     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_pint32,   ITEM(res_dir.DIRport),  0, ITEM_DEFAULT, 9101},
98    {"address",     store_str,      ITEM(res_dir.address),  0, 0, 0},
99    {"enablessl",   store_bool,     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_pint32,     ITEM(res_client.FDport),   0, ITEM_DEFAULT, 9102},
114    {"password", store_password,   ITEM(res_client.password), 0, ITEM_REQUIRED, 0},
115    {"enablessl", store_bool,      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_pint32,   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_bool,     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
260    /* Common stuff again -- free the resource, recurse to next one */
261    if (res) {
262       free(res);
263    }
264    if (nres) {
265       free_resource(nres, type);
266    }
267 }
268
269 /*
270 * Save the new resource by chaining it into the head list for
271 * the resource. If this is pass 2, we update any resource
272 * pointers because they may not have been defined until
273 * later in pass 1.
274 */
275 void save_resource(int type, RES_ITEM *items, int pass)
276 {
277    URES *res;
278    int rindex = type - r_first;
279    int i, size;
280    int error = 0;
281
282    /*
283    * Ensure that all required items are present
284    */
285    for (i=0; items[i].name; i++) {
286       if (items[i].flags & ITEM_REQUIRED) {
287          if (!bit_is_set(i, res_all.res_monitor.hdr.item_present)) {
288                Emsg2(M_ERROR_TERM, 0, _("%s item is required in %s resource, but not found.\n"),
289                   items[i].name, resources[rindex]);
290          }
291       }
292       /* If this triggers, take a look at lib/parse_conf.h */
293       if (i >= MAX_RES_ITEMS) {
294          Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
295       }
296    }
297
298    /*
299    * During pass 2 in each "store" routine, we looked up pointers
300    * to all the resources referrenced in the current resource, now we
301    * must copy their addresses from the static record to the allocated
302    * record.
303    */
304    if (pass == 2) {
305       switch (type) {
306       /* Resources not containing a resource */
307       case R_MONITOR:
308       case R_CLIENT:
309       case R_STORAGE:
310       case R_DIRECTOR:
311       case R_CONSOLE_FONT:
312          break;
313       default:
314          Emsg1(M_ERROR, 0, _("Unknown resource type %d in save_resource.\n"), type);
315          error = 1;
316          break;
317       }
318       /* Note, the resource name was already saved during pass 1,
319       * so here, we can just release it.
320       */
321       if (res_all.res_monitor.hdr.name) {
322          free(res_all.res_monitor.hdr.name);
323          res_all.res_monitor.hdr.name = NULL;
324       }
325       if (res_all.res_monitor.hdr.desc) {
326          free(res_all.res_monitor.hdr.desc);
327          res_all.res_monitor.hdr.desc = NULL;
328       }
329       return;
330    }
331
332    /*
333    * The following code is only executed during pass 1
334    */
335    switch (type) {
336    case R_MONITOR:
337       size = sizeof(MONITOR);
338       break;
339    case R_DIRECTOR:
340       size = sizeof(DIRRES);
341       break;
342    case R_CLIENT:
343       size = sizeof(CLIENT);
344       break;
345    case R_STORAGE:
346       size = sizeof(STORE);
347       break;
348    case R_CONSOLE_FONT:
349       size = sizeof(CONFONTRES);
350       break;
351    default:
352       printf(_("Unknown resource type %d in save_resource.\n"), type);
353       error = 1;
354       size = 1;
355       break;
356    }
357    /* Common */
358    if (!error) {
359       res = (URES *)malloc(size);
360       memcpy(res, &res_all, size);
361       if (!res_head[rindex]) {
362         res_head[rindex] = (RES *)res; /* store first entry */
363          Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type),
364          res->res_monitor.hdr.name, rindex);
365       } else {
366          RES *next, *last;
367          /* Add new res to end of chain */
368          for (last=next=res_head[rindex]; next; next=next->next) {
369             last = next;
370             if (strcmp(next->name, res->res_monitor.hdr.name) == 0) {
371                Emsg2(M_ERROR_TERM, 0,
372                   _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
373                resources[rindex].name, res->res_monitor.hdr.name);
374             }
375          }
376          last->next = (RES *)res;
377          Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type),
378          res->res_monitor.hdr.name, rindex, pass);
379       }
380    }
381 }
382
383 bool parse_tmon_config(CONFIG *config, const char *configfile, int exit_code)
384 {
385    config->init(configfile, NULL, exit_code, (void *)&res_all, res_all_size,
386       r_first, r_last, resources, res_head);
387    return config->parse_config();
388 }