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.2.2 2007/01/24 18:33:29 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 #ifndef AMANDATES_FILE
45 #define AMANDATES_FILE "/var/lib/amandates"
48 /* configuration parameters */
49 static char *cln_config_dir = NULL;
51 val_t client_conf[CLN_CLN];
53 command_option_t *client_options = NULL;
54 int client_options_size = 0;
56 /* predeclare local functions */
58 static void init_defaults(void);
59 static void read_conffile_recursively(char *filename);
61 static int read_confline(void);
63 keytab_t client_keytab[] = {
64 { "CONF", CONF_CONF },
65 { "INDEX_SERVER", CONF_INDEX_SERVER },
66 { "TAPE_SERVER", CONF_TAPE_SERVER },
67 { "TAPEDEV", CONF_TAPEDEV },
68 { "AUTH", CONF_AUTH },
69 { "SSH_KEYS", CONF_SSH_KEYS },
70 { "AMANDAD_PATH", CONF_AMANDAD_PATH },
71 { "CLIENT_USERNAME", CONF_CLIENT_USERNAME },
72 { "GNUTAR_LIST_DIR", CONF_GNUTAR_LIST_DIR },
73 { "AMANDATES", CONF_AMANDATES },
74 { "INCLUDEFILE", CONF_INCLUDEFILE },
75 { NULL, CONF_UNKNOWN },
78 t_conf_var client_var [] = {
79 { CONF_CONF , CONFTYPE_STRING, read_string, CLN_CONF , NULL },
80 { CONF_INDEX_SERVER , CONFTYPE_STRING, read_string, CLN_INDEX_SERVER , NULL },
81 { CONF_TAPE_SERVER , CONFTYPE_STRING, read_string, CLN_TAPE_SERVER , NULL },
82 { CONF_TAPEDEV , CONFTYPE_STRING, read_string, CLN_TAPEDEV , NULL },
83 { CONF_AUTH , CONFTYPE_STRING, read_string, CLN_AUTH , NULL },
84 { CONF_SSH_KEYS , CONFTYPE_STRING, read_string, CLN_SSH_KEYS , NULL },
85 { CONF_AMANDAD_PATH , CONFTYPE_STRING, read_string, CLN_AMANDAD_PATH , NULL },
86 { CONF_CLIENT_USERNAME, CONFTYPE_STRING, read_string, CLN_CLIENT_USERNAME, NULL },
87 { CONF_GNUTAR_LIST_DIR, CONFTYPE_STRING, read_string, CLN_GNUTAR_LIST_DIR, NULL },
88 { CONF_AMANDATES , CONFTYPE_STRING, read_string, CLN_AMANDATES , NULL },
89 { CONF_UNKNOWN , CONFTYPE_INT , NULL , CLN_CLN , NULL }
92 static int first_file = 1;
95 ** ------------------------
96 ** External entry points
97 ** ------------------------
100 /* return 0 on success */
101 /* return 1 on error */
102 /* return -1 if file not found */
107 if(first_file == 1) {
111 allow_overwrites = 1;
114 /* We assume that conf_confname & conf are initialized to NULL above */
115 read_conffile_recursively(filename);
117 command_overwrite(client_options, client_var, client_keytab, client_conf,
120 return got_parserror;
125 client_getconf_byname(
129 char number[NUM_STR_SIZE];
135 tmpstr = stralloc(str);
137 while((ch = *s++) != '\0') {
139 s[-1] = (char)toupper(ch);
142 for(kt = client_keytab; kt->token != CONF_UNKNOWN; kt++)
143 if(kt->keyword && strcmp(kt->keyword, tmpstr) == 0) break;
145 if(kt->token == CONF_UNKNOWN) return NULL;
147 for(np = client_var; np->token != CONF_UNKNOWN; np++)
148 if(np->token == kt->token) break;
150 if(np->type == CONFTYPE_INT) {
151 snprintf(number, SIZEOF(number), "%d", client_getconf_int(np->parm));
152 tmpstr = newstralloc(tmpstr, number);
153 } else if(np->type == CONFTYPE_BOOL) {
154 if(client_getconf_boolean(np->parm) == 0) {
155 tmpstr = newstralloc(tmpstr, "off");
158 tmpstr = newstralloc(tmpstr, "on");
160 } else if(np->type == CONFTYPE_REAL) {
161 snprintf(number, SIZEOF(number), "%lf", client_getconf_real(np->parm));
162 tmpstr = newstralloc(tmpstr, number);
164 tmpstr = newstralloc(tmpstr, client_getconf_str(np->parm));
175 np = get_np(client_var, parm);
176 return(client_conf[np->parm].seen);
180 client_getconf_boolean(
184 np = get_np(client_var, parm);
185 if (np->type != CONFTYPE_BOOL) {
186 error("client_getconf_boolean: np is not a CONFTYPE_BOOL");
189 return(client_conf[np->parm].v.i != 0);
197 np = get_np(client_var, parm);
198 if (np->type != CONFTYPE_INT) {
199 error("client_getconf_int: np is not a CONFTYPE_INT");
203 return(client_conf[np->parm].v.i);
211 np = get_np(client_var, parm);
212 if (np->type != CONFTYPE_AM64) {
213 error("client_getconf_am64: np is not a CONFTYPE_AM64");
216 return(client_conf[np->parm].v.am64);
224 np = get_np(client_var, parm);
225 if (np->type != CONFTYPE_REAL) {
226 error("client_getconf_real: np is not a CONFTYPE_REAL");
229 return(client_conf[np->parm].v.r);
237 np = get_np(client_var, parm);
238 if (np->type != CONFTYPE_STRING) {
239 error("client_getconf_string: np is not a CONFTYPE_STRING");
242 return(client_conf[np->parm].v.s);
246 ** ------------------------
248 ** ------------------------
257 /* defaults for exported variables */
259 #ifdef DEFAULT_CONFIG
264 conf_init_string(&client_conf[CLN_CONF], s);
266 #ifdef DEFAULT_SERVER
271 conf_init_string(&client_conf[CLN_INDEX_SERVER], s);
274 #ifdef DEFAULT_TAPE_SERVER
275 s = DEFAULT_TAPE_SERVER;
277 #ifdef DEFAULT_SERVER
283 conf_init_string(&client_conf[CLN_TAPE_SERVER], s);
285 #ifdef DEFAULT_TAPE_DEVICE
286 s = DEFAULT_TAPE_DEVICE;
290 conf_init_string(&client_conf[CLN_TAPEDEV], s);
292 conf_init_string(&client_conf[CLN_AUTH], "bsd");
293 conf_init_string(&client_conf[CLN_SSH_KEYS], "");
294 conf_init_string(&client_conf[CLN_AMANDAD_PATH], "");
295 conf_init_string(&client_conf[CLN_CLIENT_USERNAME], "");
296 #ifdef GNUTAR_LISTED_INCREMENTAL_DIR
297 conf_init_string(&client_conf[CLN_GNUTAR_LIST_DIR],
298 GNUTAR_LISTED_INCREMENTAL_DIR);
300 conf_init_string(&client_conf[CLN_GNUTAR_LIST_DIR], NULL);
302 conf_init_string(&client_conf[CLN_AMANDATES], AMANDATES_FILE);
303 /* defaults for internal variables */
305 conf_line_num = got_parserror = 0;
306 allow_overwrites = 0;
312 read_conffile_recursively(
315 /* Save globals used in read_confline(), elsewhere. */
316 int save_line_num = conf_line_num;
317 FILE *save_conf = conf_conf;
318 char *save_confname = conf_confname;
321 if (*filename == '/' || cln_config_dir == NULL) {
322 conf_confname = stralloc(filename);
324 conf_confname = stralloc2(cln_config_dir, filename);
327 if((conf_conf = fopen(conf_confname, "r")) == NULL) {
328 dbprintf(("Could not open conf file \"%s\": %s\n", conf_confname,
330 amfree(conf_confname);
334 dbprintf(("Reading conf file \"%s\".\n", conf_confname));
338 /* read_confline() can invoke us recursively via "includefile" */
340 rc = read_confline();
344 amfree(conf_confname);
346 /* Restore globals */
347 conf_line_num = save_line_num;
348 conf_conf = save_conf;
349 conf_confname = save_confname;
353 /* ------------------------ */
361 keytable = client_keytab;
364 get_conftoken(CONF_ANY);
366 case CONF_INCLUDEFILE:
370 get_conftoken(CONF_STRING);
372 read_conffile_recursively(fn);
376 case CONF_NL: /* empty line */
379 case CONF_END: /* end of file */
384 for(np = client_var; np->token != CONF_UNKNOWN; np++)
385 if(np->token == tok) break;
387 if(np->token == CONF_UNKNOWN) {
388 conf_parserror("configuration keyword expected");
390 np->read_function(np, &client_conf[np->parm]);
392 np->validate(np, &client_conf[np->parm]);
397 get_conftoken(CONF_NL);
403 /* ------------------------ */
407 static char *cln_config_name = NULL;
408 static char *cln_config_dir = NULL;
411 dump_client_configuration(
414 printf("AMANDA CLIENT CONFIGURATION FROM FILE \"%s\":\n\n", filename);
416 printf("cln_conf = \"%s\"\n", client_getconf_str(CLN_CONF));
417 printf("cln_index_server = \"%s\"\n", client_getconf_str(CLN_INDEX_SERVER));
418 printf("cln_tape_server = \"%s\"\n", client_getconf_str(CLN_TAPE_SERVER));
419 printf("cln_tapedev = \"%s\"\n", client_getconf_str(CLN_TAPEDEV));
420 printf("cln_auth = \"%s\"\n", client_getconf_str(CLN_AUTH));
421 printf("cln_ssh_keys = \"%s\"\n", client_getconf_str(CLN_SSH_KEYS));
433 unsigned long malloc_hist_1, malloc_size_1;
434 unsigned long malloc_hist_2, malloc_size_2;
438 set_pname("conffile");
440 /* Don't die when child closes pipe */
441 signal(SIGPIPE, SIG_IGN);
443 malloc_size_1 = malloc_inuse(&malloc_hist_1);
448 if (argv[1][0] == '/') {
449 cln_config_dir = stralloc(argv[1]);
450 cln_config_name = strrchr(cln_config_dir, '/') + 1;
451 cln_config_name[-1] = '\0';
452 cln_config_dir = newstralloc2(cln_config_dir, cln_config_dir, "/");
454 cln_config_name = stralloc(argv[1]);
455 cln_config_dir = vstralloc(CONFIG_DIR, "/", cln_config_name, "/", NULL);
458 char my_cwd[STR_SIZE];
460 if (getcwd(my_cwd, SIZEOF(my_cwd)) == NULL) {
461 error("cannot determine current working directory");
463 cln_config_dir = stralloc2(my_cwd, "/");
464 if ((cln_config_name = strrchr(my_cwd, '/')) != NULL) {
465 cln_config_name = stralloc(cln_config_name + 1);
469 conffile = stralloc2(cln_config_dir, CONFFILE_NAME);
470 result = read_conffile(conffile);
472 diskfile = client_getconf_str(CNF_DISKFILE);
473 if (diskfile != NULL && access(diskfile, R_OK) == 0) {
474 result = read_diskfile(diskfile, &lst);
477 dump_client_configuration(CONFFILE_NAME);
480 malloc_size_2 = malloc_inuse(&malloc_hist_2);
482 if(malloc_size_1 != malloc_size_2) {
483 malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
492 generic_client_get_security_conf(
496 (void)arg; /* Quiet unused parameter warning */
498 if(!string || !*string)
501 if(strcmp(string, "conf")==0) {
502 return(client_getconf_str(CLN_CONF));
503 } else if(strcmp(string, "index_server")==0) {
504 return(client_getconf_str(CLN_INDEX_SERVER));
505 } else if(strcmp(string, "tape_server")==0) {
506 return(client_getconf_str(CLN_TAPE_SERVER));
507 } else if(strcmp(string, "tapedev")==0) {
508 return(client_getconf_str(CLN_TAPEDEV));
509 } else if(strcmp(string, "auth")==0) {
510 return(client_getconf_str(CLN_AUTH));
511 } else if(strcmp(string, "ssh_keys")==0) {
512 return(client_getconf_str(CLN_SSH_KEYS));
513 } else if(strcmp(string, "amandad_path")==0) {
514 return(client_getconf_str(CLN_AMANDAD_PATH));
515 } else if(strcmp(string, "client_username")==0) {
516 return(client_getconf_str(CLN_CLIENT_USERNAME));
517 } else if(strcmp(string, "gnutar_list_dir")==0) {
518 return(client_getconf_str(CLN_GNUTAR_LIST_DIR));
519 } else if(strcmp(string, "amandates")==0) {
520 return(client_getconf_str(CLN_AMANDATES));
522 } else if(strcmp(string, "krb5principal")==0) {
523 return(client_getconf_str(CNF_KRB5PRINCIPAL));
524 } else if(strcmp(string, "krb5keytab")==0) {
525 return(client_getconf_str(CNF_KRB5KEYTAB));
542 command_option_t *client_option;
544 client_options = alloc((size_t)(parse_argc+1) * SIZEOF(*client_options));
545 client_options_size = parse_argc+1;
546 client_option = client_options;
547 client_option->name = NULL;
549 my_argv = alloc((size_t)parse_argc * SIZEOF(char *));
553 while(i<parse_argc) {
554 if(strncmp(parse_argv[i],"-o",2) == 0) {
555 if(strlen(parse_argv[i]) > 2)
556 myarg = &parse_argv[i][2];
560 error("expect something after -o");
561 myarg = parse_argv[i];
563 value = index(myarg,'=');
565 conf_parserror("Must specify a value for %s.\n", myarg);
569 client_option->used = 0;
570 client_option->name = stralloc(myarg);
571 client_option->value = stralloc(value);
573 client_option->name = NULL;
577 my_argv[*new_argc] = stralloc(parse_argv[i]);
584 /* return 0 on success */
585 /* return -1 if it is already there */
586 /* return -2 if other failure */
594 command_option_t *command_option;
597 for(np = client_var; np->token != CONF_UNKNOWN; np++)
598 if(np->parm == (int)parm) break;
600 if(np->token == CONF_UNKNOWN) return -2;
602 for(kt = client_keytab; kt->token != CONF_UNKNOWN; kt++)
603 if(kt->token == np->token) break;
605 if(kt->token == CONF_UNKNOWN) return -2;
609 for(command_option = client_options; command_option->name != NULL;
614 /* Increase size of client_options if needed */
615 if(nb_option >= client_options_size-1) {
616 client_options_size *= 2;
617 client_options = realloc(client_options,
618 client_options_size * SIZEOF(*client_options));
619 if (client_options == NULL) {
620 error("Can't realloc client_options: %s\n", strerror(errno));
623 for(command_option = client_options; command_option->name != NULL;
629 command_option->used = 0;
630 command_option->name = stralloc(kt->keyword);
631 command_option->value = stralloc(value);
633 command_option->name = NULL;
638 report_bad_client_arg(void)
640 command_option_t *command_option;
642 for(command_option = client_options; command_option->name != NULL;
644 if(command_option->used == 0) {
645 fprintf(stderr,"argument -o%s=%s not used\n",
646 command_option->name, command_option->value);