2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-2000 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Author: James da Silva, Systems Design and Analysis Group
24 * Computer Science Department
25 * University of Maryland at College Park
28 * $Id: clientconf.c,v 1.17 2006/07/25 19:36:48 martinea Exp $
30 * read configuration file
34 * XXX - I'm not happy *at all* with this implementation, but I don't
35 * think YACC would be any easier. A more table based implementation
36 * would be better. Also clean up memory leaks.
41 #include "clientconf.h"
44 /* configuration parameters */
45 static char *cln_config_dir = NULL;
47 val_t client_conf[CLN_CLN];
49 command_option_t *client_options = NULL;
50 int client_options_size = 0;
52 /* predeclare local functions */
54 static void init_defaults(void);
55 static void read_conffile_recursively(char *filename);
57 static int read_confline(void);
59 keytab_t client_keytab[] = {
60 { "CONF", CONF_CONF },
61 { "INDEX_SERVER", CONF_INDEX_SERVER },
62 { "TAPE_SERVER", CONF_TAPE_SERVER },
63 { "TAPEDEV", CONF_TAPEDEV },
64 { "AUTH", CONF_AUTH },
65 { "SSH_KEYS", CONF_SSH_KEYS },
66 { "AMANDAD_PATH", CONF_AMANDAD_PATH },
67 { "CLIENT_USERNAME", CONF_CLIENT_USERNAME },
68 { "GNUTAR_LIST_DIR", CONF_GNUTAR_LIST_DIR },
69 { "AMANDATES", CONF_AMANDATES },
70 { "INCLUDEFILE", CONF_INCLUDEFILE },
71 { NULL, CONF_UNKNOWN },
74 t_conf_var client_var [] = {
75 { CONF_CONF , CONFTYPE_STRING, read_string, CLN_CONF , NULL },
76 { CONF_INDEX_SERVER , CONFTYPE_STRING, read_string, CLN_INDEX_SERVER , NULL },
77 { CONF_TAPE_SERVER , CONFTYPE_STRING, read_string, CLN_TAPE_SERVER , NULL },
78 { CONF_TAPEDEV , CONFTYPE_STRING, read_string, CLN_TAPEDEV , NULL },
79 { CONF_AUTH , CONFTYPE_STRING, read_string, CLN_AUTH , NULL },
80 { CONF_SSH_KEYS , CONFTYPE_STRING, read_string, CLN_SSH_KEYS , NULL },
81 { CONF_AMANDAD_PATH , CONFTYPE_STRING, read_string, CLN_AMANDAD_PATH , NULL },
82 { CONF_CLIENT_USERNAME, CONFTYPE_STRING, read_string, CLN_CLIENT_USERNAME, NULL },
83 { CONF_GNUTAR_LIST_DIR, CONFTYPE_STRING, read_string, CLN_GNUTAR_LIST_DIR, NULL },
84 { CONF_AMANDATES , CONFTYPE_STRING, read_string, CLN_AMANDATES , NULL },
85 { CONF_UNKNOWN , CONFTYPE_INT , NULL , CLN_CLN , NULL }
88 static int first_file = 1;
91 ** ------------------------
92 ** External entry points
93 ** ------------------------
96 /* return 0 on success */
97 /* return 1 on error */
98 /* return -1 if file not found */
103 if(first_file == 1) {
107 allow_overwrites = 1;
110 /* We assume that conf_confname & conf are initialized to NULL above */
111 read_conffile_recursively(filename);
113 command_overwrite(client_options, client_var, client_keytab, client_conf,
116 return got_parserror;
121 client_getconf_byname(
125 char number[NUM_STR_SIZE];
131 tmpstr = stralloc(str);
133 while((ch = *s++) != '\0') {
135 s[-1] = (char)toupper(ch);
138 for(kt = client_keytab; kt->token != CONF_UNKNOWN; kt++)
139 if(kt->keyword && strcmp(kt->keyword, tmpstr) == 0) break;
141 if(kt->token == CONF_UNKNOWN) return NULL;
143 for(np = client_var; np->token != CONF_UNKNOWN; np++)
144 if(np->token == kt->token) break;
146 if(np->type == CONFTYPE_INT) {
147 snprintf(number, SIZEOF(number), "%d", client_getconf_int(np->parm));
148 tmpstr = newstralloc(tmpstr, number);
149 } else if(np->type == CONFTYPE_BOOL) {
150 if(client_getconf_boolean(np->parm) == 0) {
151 tmpstr = newstralloc(tmpstr, "off");
154 tmpstr = newstralloc(tmpstr, "on");
156 } else if(np->type == CONFTYPE_REAL) {
157 snprintf(number, SIZEOF(number), "%lf", client_getconf_real(np->parm));
158 tmpstr = newstralloc(tmpstr, number);
160 tmpstr = newstralloc(tmpstr, client_getconf_str(np->parm));
171 np = get_np(client_var, parm);
172 return(client_conf[np->parm].seen);
176 client_getconf_boolean(
180 np = get_np(client_var, parm);
181 if (np->type != CONFTYPE_BOOL) {
182 error("client_getconf_boolean: np is not a CONFTYPE_BOOL");
185 return(client_conf[np->parm].v.i != 0);
193 np = get_np(client_var, parm);
194 if (np->type != CONFTYPE_INT) {
195 error("client_getconf_int: np is not a CONFTYPE_INT");
199 return(client_conf[np->parm].v.i);
207 np = get_np(client_var, parm);
208 if (np->type != CONFTYPE_AM64) {
209 error("client_getconf_am64: np is not a CONFTYPE_AM64");
212 return(client_conf[np->parm].v.am64);
220 np = get_np(client_var, parm);
221 if (np->type != CONFTYPE_REAL) {
222 error("client_getconf_real: np is not a CONFTYPE_REAL");
225 return(client_conf[np->parm].v.r);
233 np = get_np(client_var, parm);
234 if (np->type != CONFTYPE_STRING) {
235 error("client_getconf_string: np is not a CONFTYPE_STRING");
238 return(client_conf[np->parm].v.s);
242 ** ------------------------
244 ** ------------------------
253 /* defaults for exported variables */
255 #ifdef DEFAULT_CONFIG
260 conf_init_string(&client_conf[CLN_CONF], s);
262 #ifdef DEFAULT_SERVER
267 conf_init_string(&client_conf[CLN_INDEX_SERVER], s);
270 #ifdef DEFAULT_TAPE_SERVER
271 s = DEFAULT_TAPE_SERVER;
273 #ifdef DEFAULT_SERVER
279 conf_init_string(&client_conf[CLN_TAPE_SERVER], s);
281 #ifdef DEFAULT_TAPE_DEVICE
282 s = DEFAULT_TAPE_DEVICE;
286 conf_init_string(&client_conf[CLN_TAPEDEV], s);
288 conf_init_string(&client_conf[CLN_AUTH], "bsd");
289 conf_init_string(&client_conf[CLN_SSH_KEYS], "");
290 conf_init_string(&client_conf[CLN_AMANDAD_PATH], "");
291 conf_init_string(&client_conf[CLN_CLIENT_USERNAME], "");
292 #ifdef GNUTAR_LISTED_INCREMENTAL_DIR
293 conf_init_string(&client_conf[CLN_GNUTAR_LIST_DIR],
294 GNUTAR_LISTED_INCREMENTAL_DIR);
296 conf_init_string(&client_conf[CLN_GNUTAR_LIST_DIR], NULL);
298 conf_init_string(&client_conf[CLN_AMANDATES], "/etc/amandates");
299 /* defaults for internal variables */
301 conf_line_num = got_parserror = 0;
302 allow_overwrites = 0;
308 read_conffile_recursively(
311 /* Save globals used in read_confline(), elsewhere. */
312 int save_line_num = conf_line_num;
313 FILE *save_conf = conf_conf;
314 char *save_confname = conf_confname;
317 if (*filename == '/' || cln_config_dir == NULL) {
318 conf_confname = stralloc(filename);
320 conf_confname = stralloc2(cln_config_dir, filename);
323 if((conf_conf = fopen(conf_confname, "r")) == NULL) {
324 dbprintf(("Could not open conf file \"%s\": %s\n", conf_confname,
326 amfree(conf_confname);
330 dbprintf(("Reading conf file \"%s\".\n", conf_confname));
334 /* read_confline() can invoke us recursively via "includefile" */
336 rc = read_confline();
340 amfree(conf_confname);
342 /* Restore globals */
343 conf_line_num = save_line_num;
344 conf_conf = save_conf;
345 conf_confname = save_confname;
349 /* ------------------------ */
357 keytable = client_keytab;
360 get_conftoken(CONF_ANY);
362 case CONF_INCLUDEFILE:
366 get_conftoken(CONF_STRING);
368 read_conffile_recursively(fn);
372 case CONF_NL: /* empty line */
375 case CONF_END: /* end of file */
380 for(np = client_var; np->token != CONF_UNKNOWN; np++)
381 if(np->token == tok) break;
383 if(np->token == CONF_UNKNOWN) {
384 conf_parserror("configuration keyword expected");
386 np->read_function(np, &client_conf[np->parm]);
388 np->validate(np, &client_conf[np->parm]);
393 get_conftoken(CONF_NL);
399 /* ------------------------ */
403 static char *cln_config_name = NULL;
404 static char *cln_config_dir = NULL;
407 dump_client_configuration(
410 printf("AMANDA CLIENT CONFIGURATION FROM FILE \"%s\":\n\n", filename);
412 printf("cln_conf = \"%s\"\n", client_getconf_str(CLN_CONF));
413 printf("cln_index_server = \"%s\"\n", client_getconf_str(CLN_INDEX_SERVER));
414 printf("cln_tape_server = \"%s\"\n", client_getconf_str(CLN_TAPE_SERVER));
415 printf("cln_tapedev = \"%s\"\n", client_getconf_str(CLN_TAPEDEV));
416 printf("cln_auth = \"%s\"\n", client_getconf_str(CLN_AUTH));
417 printf("cln_ssh_keys = \"%s\"\n", client_getconf_str(CLN_SSH_KEYS));
429 unsigned long malloc_hist_1, malloc_size_1;
430 unsigned long malloc_hist_2, malloc_size_2;
434 set_pname("conffile");
436 /* Don't die when child closes pipe */
437 signal(SIGPIPE, SIG_IGN);
439 malloc_size_1 = malloc_inuse(&malloc_hist_1);
444 if (argv[1][0] == '/') {
445 cln_config_dir = stralloc(argv[1]);
446 cln_config_name = strrchr(cln_config_dir, '/') + 1;
447 cln_config_name[-1] = '\0';
448 cln_config_dir = newstralloc2(cln_config_dir, cln_config_dir, "/");
450 cln_config_name = stralloc(argv[1]);
451 cln_config_dir = vstralloc(CONFIG_DIR, "/", cln_config_name, "/", NULL);
454 char my_cwd[STR_SIZE];
456 if (getcwd(my_cwd, SIZEOF(my_cwd)) == NULL) {
457 error("cannot determine current working directory");
459 cln_config_dir = stralloc2(my_cwd, "/");
460 if ((cln_config_name = strrchr(my_cwd, '/')) != NULL) {
461 cln_config_name = stralloc(cln_config_name + 1);
465 conffile = stralloc2(cln_config_dir, CONFFILE_NAME);
466 result = read_conffile(conffile);
468 diskfile = client_getconf_str(CNF_DISKFILE);
469 if (diskfile != NULL && access(diskfile, R_OK) == 0) {
470 result = read_diskfile(diskfile, &lst);
473 dump_client_configuration(CONFFILE_NAME);
476 malloc_size_2 = malloc_inuse(&malloc_hist_2);
478 if(malloc_size_1 != malloc_size_2) {
479 malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
488 generic_client_get_security_conf(
492 (void)arg; /* Quiet unused parameter warning */
494 if(!string || !*string)
497 if(strcmp(string, "conf")==0) {
498 return(client_getconf_str(CLN_CONF));
499 } else if(strcmp(string, "index_server")==0) {
500 return(client_getconf_str(CLN_INDEX_SERVER));
501 } else if(strcmp(string, "tape_server")==0) {
502 return(client_getconf_str(CLN_TAPE_SERVER));
503 } else if(strcmp(string, "tapedev")==0) {
504 return(client_getconf_str(CLN_TAPEDEV));
505 } else if(strcmp(string, "auth")==0) {
506 return(client_getconf_str(CLN_AUTH));
507 } else if(strcmp(string, "ssh_keys")==0) {
508 return(client_getconf_str(CLN_SSH_KEYS));
509 } else if(strcmp(string, "amandad_path")==0) {
510 return(client_getconf_str(CLN_AMANDAD_PATH));
511 } else if(strcmp(string, "client_username")==0) {
512 return(client_getconf_str(CLN_CLIENT_USERNAME));
513 } else if(strcmp(string, "gnutar_list_dir")==0) {
514 return(client_getconf_str(CLN_GNUTAR_LIST_DIR));
515 } else if(strcmp(string, "amandates")==0) {
516 return(client_getconf_str(CLN_AMANDATES));
518 } else if(strcmp(string, "krb5principal")==0) {
519 return(client_getconf_str(CNF_KRB5PRINCIPAL));
520 } else if(strcmp(string, "krb5keytab")==0) {
521 return(client_getconf_str(CNF_KRB5KEYTAB));
538 command_option_t *client_option;
540 client_options = alloc((size_t)(parse_argc+1) * SIZEOF(*client_options));
541 client_options_size = parse_argc+1;
542 client_option = client_options;
543 client_option->name = NULL;
545 my_argv = alloc((size_t)parse_argc * SIZEOF(char *));
549 while(i<parse_argc) {
550 if(strncmp(parse_argv[i],"-o",2) == 0) {
551 if(strlen(parse_argv[i]) > 2)
552 myarg = &parse_argv[i][2];
556 error("expect something after -o");
557 myarg = parse_argv[i];
559 value = index(myarg,'=');
561 conf_parserror("Must specify a value for %s.\n", myarg);
565 client_option->used = 0;
566 client_option->name = stralloc(myarg);
567 client_option->value = stralloc(value);
569 client_option->name = NULL;
573 my_argv[*new_argc] = stralloc(parse_argv[i]);
580 /* return 0 on success */
581 /* return -1 if it is already there */
582 /* return -2 if other failure */
590 command_option_t *command_option;
593 for(np = client_var; np->token != CONF_UNKNOWN; np++)
594 if(np->parm == (int)parm) break;
596 if(np->token == CONF_UNKNOWN) return -2;
598 for(kt = client_keytab; kt->token != CONF_UNKNOWN; kt++)
599 if(kt->token == np->token) break;
601 if(kt->token == CONF_UNKNOWN) return -2;
605 for(command_option = client_options; command_option->name != NULL;
607 if(strcasecmp(command_option->name, kt->keyword) == 0) {
613 /* Increase size of client_options if needed */
614 if(nb_option >= client_options_size-1) {
615 client_options_size *= 2;
616 client_options = realloc(client_options,
617 client_options_size * SIZEOF(*client_options));
618 if (client_options == NULL) {
619 error("Can't realloc client_options: %s\n", strerror(errno));
622 for(command_option = client_options; command_option->name != NULL;
628 command_option->used = 0;
629 command_option->name = stralloc(kt->keyword);
630 command_option->value = stralloc(value);
632 command_option->name = NULL;
637 report_bad_client_arg(void)
639 command_option_t *command_option;
641 for(command_option = client_options; command_option->name != NULL;
643 if(command_option->used == 0) {
644 fprintf(stderr,"argument -o%s=%s not used\n",
645 command_option->name, command_option->value);