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: conffile.c,v 1.54.2.16.2.5.2.20.2.10 2005/09/30 19:13:36 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.
51 #define INT_MAX 2147483647
54 #define BIGINT 1000000000 /* 2 million yrs @ 1 per day */
56 /* internal types and variables */
59 * XXX - this is used by the krb4 stuff.
60 * Hopefully nobody will need this here. (not very likely). -kovert
62 #if defined(INTERFACE)
67 UNKNOWN, ANY, COMMA, LBRACE, RBRACE, NL, END,
68 IDENT, INT, LONG, BOOL, REAL, STRING, TIME,
70 /* config parameters */
72 ORG, MAILTO, DUMPUSER,
73 TAPECYCLE, TAPEDEV, CHNGRDEV, CHNGRFILE, LABELSTR,
74 BUMPPERCENT, BUMPSIZE, BUMPDAYS, BUMPMULT, ETIMEOUT, DTIMEOUT, CTIMEOUT,
75 TAPEBUFS, TAPELIST, DISKFILE, INFOFILE, LOGDIR, LOGFILE,
76 DISKDIR, DISKSIZE, INDEXDIR, NETUSAGE, INPARALLEL, DUMPORDER, TIMEOUT,
78 DEFINE, DUMPTYPE, TAPETYPE, INTERFACE,
79 PRINTER, AUTOFLUSH, RESERVE, MAXDUMPSIZE,
81 AMRECOVER_DO_FSF, AMRECOVER_CHECK_LABEL, AMRECOVER_CHANGER,
83 TAPERALGO, FIRST, FIRSTFIT, LARGEST, LARGESTFIT, SMALLEST, LAST,
87 COMMENT, DIRECTORY, USE, CHUNKSIZE,
90 /*COMMENT,*/ PROGRAM, DUMPCYCLE, RUNSPERCYCLE, MAXCYCLE, MAXDUMPS,
91 OPTIONS, PRIORITY, FREQUENCY, INDEX, MAXPROMOTEDAY,
92 STARTTIME, COMPRESS, AUTH, STRATEGY, ESTIMATE,
93 SKIP_INCR, SKIP_FULL, RECORD, HOLDING,
94 EXCLUDE, INCLUDE, KENCRYPT, IGNORE, COMPRATE,
97 /*COMMENT,*/ BLOCKSIZE, FILE_PAD, LBL_TEMPL, FILEMARK, LENGTH, SPEED,
99 /* network interface */
102 /* dump options (obsolete) */
103 EXCLUDE_FILE, EXCLUDE_LIST,
105 /* compress, estimate */
106 NONE, FAST, BEST, SERVER, CLIENT, CALCSIZE,
115 SKIP, STANDARD, NOFULL, NOINC, HANOI, INCRONLY,
118 LIST, EFILE, APPEND, OPTIONAL,
121 INFINITY, MULT1, MULT7, MULT1K, MULT1M, MULT1G,
129 typedef struct { /* token table entry */
143 /* this corresponds to the normal output of amanda, but may
144 * be adapted to any spacing as you like.
146 ColumnInfo ColumnData[] = {
147 { "HostName", 0, 12, 12, 0, "%-*.*s", "HOSTNAME" },
148 { "Disk", 1, 11, 11, 0, "%-*.*s", "DISK" },
149 { "Level", 1, 1, 1, 0, "%*.*d", "L" },
150 { "OrigKB", 1, 7, 0, 0, "%*.*f", "ORIG-KB" },
151 { "OutKB", 0, 7, 0, 0, "%*.*f", "OUT-KB" },
152 { "Compress", 0, 6, 1, 0, "%*.*f", "COMP%" },
153 { "DumpTime", 0, 7, 7, 0, "%*.*s", "MMM:SS" },
154 { "DumpRate", 0, 6, 1, 0, "%*.*f", "KB/s" },
155 { "TapeTime", 1, 6, 6, 0, "%*.*s", "MMM:SS" },
156 { "TapeRate", 0, 6, 1, 0, "%*.*f", "KB/s" },
157 { NULL, 0, 0, 0, 0, NULL, NULL }
160 char *config_name = NULL;
161 char *config_dir = NULL;
163 /* visible holding disk variables */
165 holdingdisk_t *holdingdisks;
166 int num_holdingdisks;
168 long int unit_divisor = 1;
170 /* configuration parameters */
173 static val_t conf_org;
174 static val_t conf_mailto;
175 static val_t conf_dumpuser;
176 static val_t conf_printer;
177 static val_t conf_tapedev;
178 static val_t conf_rawtapedev;
179 static val_t conf_tpchanger;
180 static val_t conf_chngrdev;
181 static val_t conf_chngrfile;
182 static val_t conf_labelstr;
183 static val_t conf_tapelist;
184 static val_t conf_infofile;
185 static val_t conf_logdir;
186 static val_t conf_diskfile;
187 static val_t conf_diskdir;
188 static val_t conf_tapetype;
189 static val_t conf_indexdir;
190 static val_t conf_columnspec;
191 static val_t conf_dumporder;
192 static val_t conf_amrecover_changer;
195 static val_t conf_dumpcycle;
196 static val_t conf_runspercycle;
197 static val_t conf_maxcycle;
198 static val_t conf_tapecycle;
199 static val_t conf_runtapes;
200 static val_t conf_disksize;
201 static val_t conf_netusage;
202 static val_t conf_inparallel;
203 static val_t conf_timeout;
204 static val_t conf_maxdumps;
205 static val_t conf_bumppercent;
206 static val_t conf_bumpsize;
207 static val_t conf_bumpdays;
208 static val_t conf_etimeout;
209 static val_t conf_dtimeout;
210 static val_t conf_ctimeout;
211 static val_t conf_tapebufs;
212 static val_t conf_autoflush;
213 static val_t conf_reserve;
214 static val_t conf_maxdumpsize;
215 static val_t conf_amrecover_do_fsf;
216 static val_t conf_amrecover_check_label;
217 static val_t conf_taperalgo;
218 static val_t conf_displayunit;
221 static val_t conf_bumpmult;
223 /* other internal variables */
224 static holdingdisk_t hdcur;
226 static tapetype_t tpcur;
228 static dumptype_t dpcur;
230 static interface_t ifcur;
233 static int seen_mailto;
234 static int seen_dumpuser;
235 static int seen_rawtapedev;
236 static int seen_printer;
237 static int seen_tapedev;
238 static int seen_tpchanger;
239 static int seen_chngrdev;
240 static int seen_chngrfile;
241 static int seen_labelstr;
242 static int seen_runtapes;
243 static int seen_maxdumps;
244 static int seen_tapelist;
245 static int seen_infofile;
246 static int seen_diskfile;
247 static int seen_diskdir;
248 static int seen_logdir;
249 static int seen_bumppercent;
250 static int seen_bumpsize;
251 static int seen_bumpmult;
252 static int seen_bumpdays;
253 static int seen_tapetype;
254 static int seen_dumpcycle;
255 static int seen_runspercycle;
256 static int seen_maxcycle;
257 static int seen_tapecycle;
258 static int seen_disksize;
259 static int seen_netusage;
260 static int seen_inparallel;
261 static int seen_dumporder;
262 static int seen_timeout;
263 static int seen_indexdir;
264 static int seen_etimeout;
265 static int seen_dtimeout;
266 static int seen_ctimeout;
267 static int seen_tapebufs;
268 static int seen_autoflush;
269 static int seen_reserve;
270 static int seen_maxdumpsize;
271 static int seen_columnspec;
272 static int seen_amrecover_do_fsf;
273 static int seen_amrecover_check_label;
274 static int seen_amrecover_changer;
275 static int seen_taperalgo;
276 static int seen_displayunit;
278 static int allow_overwrites;
279 static int token_pushed;
281 static tok_t tok, pushed_tok;
282 static val_t tokenval;
284 static int line_num, got_parserror;
285 static dumptype_t *dumplist = NULL;
286 static tapetype_t *tapelist = NULL;
287 static interface_t *interface_list = NULL;
288 static FILE *conf = (FILE *)NULL;
289 static char *confname = NULL;
291 /* predeclare local functions */
293 static void init_defaults P((void));
294 static void read_conffile_recursively P((char *filename));
296 static int read_confline P((void));
297 static void get_holdingdisk P((void));
298 static void init_holdingdisk_defaults P((void));
299 static void save_holdingdisk P((void));
300 static void get_dumptype P((void));
301 static void init_dumptype_defaults P((void));
302 static void save_dumptype P((void));
303 static void copy_dumptype P((void));
304 static void get_tapetype P((void));
305 static void init_tapetype_defaults P((void));
306 static void save_tapetype P((void));
307 static void copy_tapetype P((void));
308 static void get_interface P((void));
309 static void init_interface_defaults P((void));
310 static void save_interface P((void));
311 static void copy_interface P((void));
312 static void get_dumpopts P((void));
313 static void get_comprate P((void));
314 static void get_compress P((void));
315 static void get_priority P((void));
316 static void get_auth P((void));
317 static void get_strategy P((void));
318 static void get_estimate P((void));
319 static void get_exclude P((void));
320 static void get_include P((void));
321 static void get_taperalgo P((val_t *c_taperalgo, int *s_taperalgo));
323 static void get_simple P((val_t *var, int *seen, tok_t type));
324 static int get_time P((void));
325 static long get_number P((void));
326 static int get_bool P((void));
327 static void ckseen P((int *seen));
328 static void parserror P((char *format, ...))
329 __attribute__ ((format (printf, 1, 2)));
330 static tok_t lookup_keyword P((char *str));
331 static void unget_conftoken P((void));
332 static void get_conftoken P((tok_t exp));
335 ** ------------------------
336 ** External entry points
337 ** ------------------------
340 int read_conffile(filename)
347 /* We assume that confname & conf are initialized to NULL above */
348 read_conffile_recursively(filename);
350 if(got_parserror != -1 ) {
351 if(lookup_tapetype(conf_tapetype.s) == NULL) {
352 char *save_confname = confname;
356 parserror("default tapetype %s not defined", conf_tapetype.s);
358 line_num = seen_tapetype;
359 parserror("tapetype %s not defined", conf_tapetype.s);
361 confname = save_confname;
365 ip = alloc(sizeof(interface_t));
368 ip->seen = seen_netusage;
369 ip->comment = "implicit from NETUSAGE";
370 ip->maxusage = conf_netusage.i;
372 ip->next = interface_list;
375 return got_parserror;
382 } byname_table [] = {
383 { "ORG", CNF_ORG, STRING },
384 { "MAILTO", CNF_MAILTO, STRING },
385 { "DUMPUSER", CNF_DUMPUSER, STRING },
386 { "PRINTER", CNF_PRINTER, STRING },
387 { "TAPEDEV", CNF_TAPEDEV, STRING },
388 { "TPCHANGER", CNF_TPCHANGER, STRING },
389 { "CHANGERDEV", CNF_CHNGRDEV, STRING },
390 { "CHANGERFILE", CNF_CHNGRFILE, STRING },
391 { "LABELSTR", CNF_LABELSTR, STRING },
392 { "TAPELIST", CNF_TAPELIST, STRING },
393 { "DISKFILE", CNF_DISKFILE, STRING },
394 { "INFOFILE", CNF_INFOFILE, STRING },
395 { "LOGDIR", CNF_LOGDIR, STRING },
396 /*{ "LOGFILE", CNF_LOGFILE, STRING },*/
397 /*{ "DISKDIR", CNF_DISKDIR, STRING },*/
398 { "INDEXDIR", CNF_INDEXDIR, STRING },
399 { "TAPETYPE", CNF_TAPETYPE, STRING },
400 { "DUMPCYCLE", CNF_DUMPCYCLE, INT },
401 { "RUNSPERCYCLE", CNF_RUNSPERCYCLE, INT },
402 { "MINCYCLE", CNF_DUMPCYCLE, INT },
403 { "RUNTAPES", CNF_RUNTAPES, INT },
404 { "TAPECYCLE", CNF_TAPECYCLE, INT },
405 /*{ "DISKSIZE", CNF_DISKSIZE, INT },*/
406 { "BUMPDAYS", CNF_BUMPDAYS, INT },
407 { "BUMPSIZE", CNF_BUMPSIZE, INT },
408 { "BUMPPERCENT", CNF_BUMPPERCENT, INT },
409 { "BUMPMULT", CNF_BUMPMULT, REAL },
410 { "NETUSAGE", CNF_NETUSAGE, INT },
411 { "INPARALLEL", CNF_INPARALLEL, INT },
412 { "DUMPORDER", CNF_DUMPORDER, STRING },
413 /*{ "TIMEOUT", CNF_TIMEOUT, INT },*/
414 { "MAXDUMPS", CNF_MAXDUMPS, INT },
415 { "ETIMEOUT", CNF_ETIMEOUT, INT },
416 { "DTIMEOUT", CNF_DTIMEOUT, INT },
417 { "CTIMEOUT", CNF_CTIMEOUT, INT },
418 { "TAPEBUFS", CNF_TAPEBUFS, INT },
419 { "RAWTAPEDEV", CNF_RAWTAPEDEV, STRING },
420 { "COLUMNSPEC", CNF_COLUMNSPEC, STRING },
421 { "AMRECOVER_DO_FSF", CNF_AMRECOVER_DO_FSF, BOOL },
422 { "AMRECOVER_CHECK_LABEL", CNF_AMRECOVER_CHECK_LABEL, BOOL },
423 { "AMRECOVER_CHANGER", CNF_AMRECOVER_CHANGER, STRING },
424 { "TAPERALGO", CNF_TAPERALGO, INT },
425 { "DISPLAYUNIT", CNF_DISPLAYUNIT, STRING },
426 { "AUTOFLUSH", CNF_AUTOFLUSH, BOOL },
427 { "RESERVE", CNF_RESERVE, INT },
428 { "MAXDUMPSIZE", CNF_MAXDUMPSIZE, INT },
432 char *getconf_byname(str)
436 char number[NUM_STR_SIZE];
441 tmpstr = stralloc(str);
443 while((ch = *s++) != '\0') {
444 if(islower((int) ch)) s[-1] = toupper(ch);
447 for(np = byname_table; np->name != NULL; np++)
448 if(strcmp(np->name, tmpstr) == 0) break;
450 if(np->name == NULL) return NULL;
453 ap_snprintf(number, sizeof(number), "%d", getconf_int(np->parm));
454 tmpstr = newstralloc(tmpstr, number);
455 } else if(np->typ == BOOL) {
456 if(getconf_int(np->parm) == 0) {
457 tmpstr = newstralloc(tmpstr, "off");
460 tmpstr = newstralloc(tmpstr, "on");
462 } else if(np->typ == REAL) {
463 ap_snprintf(number, sizeof(number), "%f", getconf_real(np->parm));
464 tmpstr = newstralloc(tmpstr, number);
466 tmpstr = newstralloc(tmpstr, getconf_str(np->parm));
472 int getconf_seen(parm)
476 case CNF_ORG: return seen_org;
477 case CNF_MAILTO: return seen_mailto;
478 case CNF_DUMPUSER: return seen_dumpuser;
479 case CNF_PRINTER: return seen_printer;
480 case CNF_TAPEDEV: return seen_tapedev;
481 case CNF_TPCHANGER: return seen_tpchanger;
482 case CNF_CHNGRDEV: return seen_chngrdev;
483 case CNF_CHNGRFILE: return seen_chngrfile;
484 case CNF_LABELSTR: return seen_labelstr;
485 case CNF_RUNTAPES: return seen_runtapes;
486 case CNF_MAXDUMPS: return seen_maxdumps;
487 case CNF_TAPELIST: return seen_tapelist;
488 case CNF_INFOFILE: return seen_infofile;
489 case CNF_DISKFILE: return seen_diskfile;
490 /*case CNF_DISKDIR: return seen_diskdir;*/
491 case CNF_LOGDIR: return seen_logdir;
492 /*case CNF_LOGFILE: return seen_logfile;*/
493 case CNF_BUMPPERCENT: return seen_bumppercent;
494 case CNF_BUMPSIZE: return seen_bumpsize;
495 case CNF_BUMPMULT: return seen_bumpmult;
496 case CNF_BUMPDAYS: return seen_bumpdays;
497 case CNF_TAPETYPE: return seen_tapetype;
498 case CNF_DUMPCYCLE: return seen_dumpcycle;
499 case CNF_RUNSPERCYCLE: return seen_runspercycle;
500 /*case CNF_MAXCYCLE: return seen_maxcycle;*/
501 case CNF_TAPECYCLE: return seen_tapecycle;
502 /*case CNF_DISKSIZE: return seen_disksize;*/
503 case CNF_NETUSAGE: return seen_netusage;
504 case CNF_INPARALLEL: return seen_inparallel;
505 case CNF_DUMPORDER: return seen_dumporder;
506 /*case CNF_TIMEOUT: return seen_timeout;*/
507 case CNF_INDEXDIR: return seen_indexdir;
508 case CNF_ETIMEOUT: return seen_etimeout;
509 case CNF_DTIMEOUT: return seen_dtimeout;
510 case CNF_CTIMEOUT: return seen_ctimeout;
511 case CNF_TAPEBUFS: return seen_tapebufs;
512 case CNF_RAWTAPEDEV: return seen_rawtapedev;
513 case CNF_AUTOFLUSH: return seen_autoflush;
514 case CNF_RESERVE: return seen_reserve;
515 case CNF_MAXDUMPSIZE: return seen_maxdumpsize;
516 case CNF_AMRECOVER_DO_FSF: return seen_amrecover_do_fsf;
517 case CNF_AMRECOVER_CHECK_LABEL: return seen_amrecover_check_label;
518 case CNF_AMRECOVER_CHANGER: return seen_amrecover_changer;
519 case CNF_TAPERALGO: return seen_taperalgo;
520 case CNF_DISPLAYUNIT: return seen_displayunit;
525 int getconf_int(parm)
532 case CNF_DUMPCYCLE: r = conf_dumpcycle.i; break;
533 case CNF_RUNSPERCYCLE: r = conf_runspercycle.i; break;
534 case CNF_TAPECYCLE: r = conf_tapecycle.i; break;
535 case CNF_RUNTAPES: r = conf_runtapes.i; break;
536 /*case CNF_DISKSIZE: r = conf_disksize.i; break;*/
537 case CNF_BUMPPERCENT: r = conf_bumppercent.i; break;
538 case CNF_BUMPSIZE: r = conf_bumpsize.i; break;
539 case CNF_BUMPDAYS: r = conf_bumpdays.i; break;
540 case CNF_NETUSAGE: r = conf_netusage.i; break;
541 case CNF_INPARALLEL: r = conf_inparallel.i; break;
542 /*case CNF_TIMEOUT: r = conf_timeout.i; break;*/
543 case CNF_MAXDUMPS: r = conf_maxdumps.i; break;
544 case CNF_ETIMEOUT: r = conf_etimeout.i; break;
545 case CNF_DTIMEOUT: r = conf_dtimeout.i; break;
546 case CNF_CTIMEOUT: r = conf_ctimeout.i; break;
547 case CNF_TAPEBUFS: r = conf_tapebufs.i; break;
548 case CNF_AUTOFLUSH: r = conf_autoflush.i; break;
549 case CNF_RESERVE: r = conf_reserve.i; break;
550 case CNF_MAXDUMPSIZE: r = conf_maxdumpsize.i; break;
551 case CNF_AMRECOVER_DO_FSF: r = conf_amrecover_do_fsf.i; break;
552 case CNF_AMRECOVER_CHECK_LABEL: r = conf_amrecover_check_label.i; break;
553 case CNF_TAPERALGO: r = conf_taperalgo.i; break;
556 error("error [unknown getconf_int parm: %d]", parm);
562 double getconf_real(parm)
569 case CNF_BUMPMULT: r = conf_bumpmult.r; break;
572 error("error [unknown getconf_real parm: %d]", parm);
578 char *getconf_str(parm)
585 case CNF_ORG: r = conf_org.s; break;
586 case CNF_MAILTO: r = conf_mailto.s; break;
587 case CNF_DUMPUSER: r = conf_dumpuser.s; break;
588 case CNF_PRINTER: r = conf_printer.s; break;
589 case CNF_TAPEDEV: r = conf_tapedev.s; break;
590 case CNF_TPCHANGER: r = conf_tpchanger.s; break;
591 case CNF_CHNGRDEV: r = conf_chngrdev.s; break;
592 case CNF_CHNGRFILE: r = conf_chngrfile.s; break;
593 case CNF_LABELSTR: r = conf_labelstr.s; break;
594 case CNF_TAPELIST: r = conf_tapelist.s; break;
595 case CNF_INFOFILE: r = conf_infofile.s; break;
596 case CNF_DUMPORDER: r = conf_dumporder.s; break;
597 case CNF_LOGDIR: r = conf_logdir.s; break;
598 /*case CNF_LOGFILE: r = conf_logfile.s; break;*/
599 case CNF_DISKFILE: r = conf_diskfile.s; break;
600 /*case CNF_DISKDIR: r = conf_diskdir.s; break;*/
601 case CNF_TAPETYPE: r = conf_tapetype.s; break;
602 case CNF_INDEXDIR: r = conf_indexdir.s; break;
603 case CNF_RAWTAPEDEV: r = conf_rawtapedev.s; break;
604 case CNF_COLUMNSPEC: r = conf_columnspec.s; break;
605 case CNF_AMRECOVER_CHANGER: r = conf_amrecover_changer.s; break;
606 case CNF_DISPLAYUNIT: r = conf_displayunit.s; break;
609 error("error [unknown getconf_str parm: %d]", parm);
615 holdingdisk_t *getconf_holdingdisks()
620 dumptype_t *lookup_dumptype(str)
625 for(p = dumplist; p != NULL; p = p->next) {
626 if(strcmp(p->name, str) == 0) return p;
631 tapetype_t *lookup_tapetype(str)
636 for(p = tapelist; p != NULL; p = p->next) {
637 if(strcmp(p->name, str) == 0) return p;
642 interface_t *lookup_interface(str)
647 if(str == NULL) return interface_list;
648 for(p = interface_list; p != NULL; p = p->next) {
649 if(strcmp(p->name, str) == 0) return p;
656 ** ------------------------
658 ** ------------------------
662 static void init_defaults()
666 /* defaults for exported variables */
668 #ifdef DEFAULT_CONFIG
673 conf_org.s = stralloc(s);
674 malloc_mark(conf_org.s);
675 conf_mailto.s = stralloc("operators");
676 malloc_mark(conf_mailto.s);
677 conf_dumpuser.s = stralloc(CLIENT_LOGIN);
678 malloc_mark(conf_dumpuser.s);
679 #ifdef DEFAULT_TAPE_DEVICE
680 s = DEFAULT_TAPE_DEVICE;
684 conf_tapedev.s = stralloc(s);
685 malloc_mark(conf_tapedev.s);
686 #ifdef DEFAULT_RAW_TAPE_DEVICE
687 s = DEFAULT_RAW_TAPE_DEVICE;
691 conf_rawtapedev.s = stralloc(s);
692 malloc_mark(conf_rawtapedev.s);
693 conf_tpchanger.s = stralloc("");
694 malloc_mark(conf_tpchanger.s);
695 #ifdef DEFAULT_CHANGER_DEVICE
696 s = DEFAULT_CHANGER_DEVICE;
700 conf_chngrdev.s = stralloc(s);
701 malloc_mark(conf_chngrdev.s);
702 conf_chngrfile.s = stralloc("/usr/adm/amanda/changer-status");
703 malloc_mark(conf_chngrfile.s);
704 conf_labelstr.s = stralloc(".*");
705 malloc_mark(conf_labelstr.s);
706 conf_tapelist.s = stralloc("tapelist");
707 malloc_mark(conf_tapelist.s);
708 conf_infofile.s = stralloc("/usr/adm/amanda/curinfo");
709 malloc_mark(conf_infofile.s);
710 conf_logdir.s = stralloc("/usr/adm/amanda");
711 malloc_mark(conf_logdir.s);
712 conf_diskfile.s = stralloc("disklist");
713 malloc_mark(conf_diskfile.s);
714 conf_diskdir.s = stralloc("/dumps/amanda");
715 malloc_mark(conf_diskdir.s);
716 conf_tapetype.s = stralloc("EXABYTE");
717 malloc_mark(conf_tapetype.s);
718 conf_indexdir.s = stralloc("/usr/adm/amanda/index");
719 malloc_mark(conf_indexdir.s);
720 conf_columnspec.s = stralloc("");
721 malloc_mark(conf_columnspec.s);
722 conf_dumporder.s = stralloc("ttt");
723 malloc_mark(conf_dumporder.s);
724 conf_amrecover_changer.s = stralloc("");
725 conf_printer.s = stralloc("");
726 conf_displayunit.s = stralloc("k");
728 conf_dumpcycle.i = 10;
729 conf_runspercycle.i = 0;
730 conf_tapecycle.i = 15;
733 conf_netusage.i = 300;
734 conf_inparallel.i = 10;
737 conf_bumppercent.i = 0;
738 conf_bumpsize.i = 10*1024;
740 conf_bumpmult.r = 1.5;
741 conf_etimeout.i = 300;
742 conf_dtimeout.i = 1800;
743 conf_ctimeout.i = 30;
744 conf_tapebufs.i = 20;
745 conf_autoflush.i = 0;
746 conf_reserve.i = 100;
747 conf_maxdumpsize.i = -1;
748 conf_amrecover_do_fsf.i = 0;
749 conf_amrecover_check_label.i = 0;
750 conf_taperalgo.i = 0;
752 /* defaults for internal variables */
771 seen_bumppercent = 0;
777 seen_runspercycle = 0;
792 seen_maxdumpsize = 0;
794 seen_amrecover_do_fsf = 0;
795 seen_amrecover_check_label = 0;
796 seen_amrecover_changer = 0;
798 seen_displayunit = 0;
799 line_num = got_parserror = 0;
800 allow_overwrites = 0;
803 while(holdingdisks != NULL) {
807 holdingdisks = holdingdisks->next;
810 num_holdingdisks = 0;
812 /* free any previously declared dump, tape and interface types */
814 while(dumplist != NULL) {
818 dumplist = dumplist->next;
821 while(tapelist != NULL) {
825 tapelist = tapelist->next;
828 while(interface_list != NULL) {
832 interface_list = interface_list->next;
836 /* create some predefined dumptypes for backwards compatability */
837 init_dumptype_defaults();
838 dpcur.name = "NO-COMPRESS"; dpcur.seen = -1;
839 dpcur.compress = COMP_NONE; dpcur.s_compress = -1;
842 init_dumptype_defaults();
843 dpcur.name = "COMPRESS-FAST"; dpcur.seen = -1;
844 dpcur.compress = COMP_FAST; dpcur.s_compress = -1;
847 init_dumptype_defaults();
848 dpcur.name = "COMPRESS-BEST"; dpcur.seen = -1;
849 dpcur.compress = COMP_BEST; dpcur.s_compress = -1;
852 init_dumptype_defaults();
853 dpcur.name = "SRVCOMPRESS"; dpcur.seen = -1;
854 dpcur.compress = COMP_SERV_FAST; dpcur.s_compress = -1;
857 init_dumptype_defaults();
858 dpcur.name = "BSD-AUTH"; dpcur.seen = -1;
859 dpcur.auth = AUTH_BSD; dpcur.s_auth = -1;
862 init_dumptype_defaults();
863 dpcur.name = "KRB4-AUTH"; dpcur.seen = -1;
864 dpcur.auth = AUTH_KRB4; dpcur.s_auth = -1;
867 init_dumptype_defaults();
868 dpcur.name = "NO-RECORD"; dpcur.seen = -1;
869 dpcur.record = 0; dpcur.s_record = -1;
872 init_dumptype_defaults();
873 dpcur.name = "NO-HOLD"; dpcur.seen = -1;
874 dpcur.no_hold = 1; dpcur.s_no_hold = -1;
877 init_dumptype_defaults();
878 dpcur.name = "NO-FULL"; dpcur.seen = -1;
879 dpcur.strategy = DS_NOFULL; dpcur.s_strategy = -1;
883 static void read_conffile_recursively(filename)
888 /* Save globals used in read_confline(), elsewhere. */
889 int save_line_num = line_num;
890 FILE *save_conf = conf;
891 char *save_confname = confname;
893 if (*filename == '/' || config_dir == NULL) {
894 confname = stralloc(filename);
896 confname = stralloc2(config_dir, filename);
899 if((conf = fopen(confname, "r")) == NULL) {
900 fprintf(stderr, "could not open conf file \"%s\": %s\n", confname,
909 /* read_confline() can invoke us recursively via "includefile" */
910 while(read_confline());
915 /* Restore globals */
916 line_num = save_line_num;
918 confname = save_confname;
922 /* ------------------------ */
925 keytab_t main_keytable[] = {
926 { "BUMPDAYS", BUMPDAYS },
927 { "BUMPMULT", BUMPMULT },
928 { "BUMPSIZE", BUMPSIZE },
929 { "BUMPPERCENT", BUMPPERCENT },
930 { "DEFINE", DEFINE },
931 { "DISKDIR", DISKDIR }, /* XXX - historical */
932 { "DISKFILE", DISKFILE },
933 { "DISKSIZE", DISKSIZE }, /* XXX - historical */
934 { "DUMPCYCLE", DUMPCYCLE },
935 { "RUNSPERCYCLE", RUNSPERCYCLE },
936 { "DUMPTYPE", DUMPTYPE },
937 { "DUMPUSER", DUMPUSER },
938 { "PRINTER", PRINTER },
939 { "HOLDINGDISK", HOLDING },
940 { "INCLUDEFILE", INCLUDEFILE },
941 { "INDEXDIR", INDEXDIR },
942 { "INFOFILE", INFOFILE },
943 { "INPARALLEL", INPARALLEL },
944 { "DUMPORDER", DUMPORDER },
945 { "INTERFACE", INTERFACE },
946 { "LABELSTR", LABELSTR },
947 { "LOGDIR", LOGDIR },
948 { "LOGFILE", LOGFILE }, /* XXX - historical */
949 { "MAILTO", MAILTO },
950 { "MAXCYCLE", MAXCYCLE }, /* XXX - historical */
951 { "MAXDUMPS", MAXDUMPS },
952 { "MINCYCLE", DUMPCYCLE }, /* XXX - historical */
953 { "NETUSAGE", NETUSAGE }, /* XXX - historical */
955 { "RUNTAPES", RUNTAPES },
956 { "TAPECYCLE", TAPECYCLE },
957 { "TAPEDEV", TAPEDEV },
958 { "TAPELIST", TAPELIST },
959 { "TAPETYPE", TAPETYPE },
960 { "TIMEOUT", TIMEOUT }, /* XXX - historical */
961 { "TPCHANGER", TPCHANGER },
962 { "CHANGERDEV", CHNGRDEV },
963 { "CHANGERFILE", CHNGRFILE },
964 { "ETIMEOUT", ETIMEOUT },
965 { "DTIMEOUT", DTIMEOUT },
966 { "CTIMEOUT", CTIMEOUT },
967 { "TAPEBUFS", TAPEBUFS },
968 { "RAWTAPEDEV", RAWTAPEDEV },
969 { "AUTOFLUSH", AUTOFLUSH },
970 { "RESERVE", RESERVE },
971 { "MAXDUMPSIZE", MAXDUMPSIZE },
972 { "COLUMNSPEC", COLUMNSPEC },
973 { "AMRECOVER_DO_FSF", AMRECOVER_DO_FSF },
974 { "AMRECOVER_CHECK_LABEL", AMRECOVER_CHECK_LABEL },
975 { "AMRECOVER_CHANGER", AMRECOVER_CHANGER },
976 { "TAPERALGO", TAPERALGO },
977 { "DISPLAYUNIT", DISPLAYUNIT },
981 static int read_confline()
983 keytable = main_keytable;
992 get_conftoken(STRING);
994 read_conffile_recursively(fn);
998 case ORG: get_simple(&conf_org, &seen_org, STRING); break;
999 case MAILTO: get_simple(&conf_mailto, &seen_mailto, STRING); break;
1000 case DUMPUSER: get_simple(&conf_dumpuser, &seen_dumpuser, STRING); break;
1001 case PRINTER: get_simple(&conf_printer, &seen_printer, STRING); break;
1002 case DUMPCYCLE: get_simple(&conf_dumpcycle, &seen_dumpcycle, INT);
1003 if(conf_dumpcycle.i < 0) {
1004 parserror("dumpcycle must be positive");
1007 case RUNSPERCYCLE: get_simple(&conf_runspercycle, &seen_runspercycle, INT);
1008 if(conf_runspercycle.i < -1) {
1009 parserror("runspercycle must be >= -1");
1012 case MAXCYCLE: get_simple(&conf_maxcycle, &seen_maxcycle, INT); break;
1013 case TAPECYCLE: get_simple(&conf_tapecycle, &seen_tapecycle, INT);
1014 if(conf_tapecycle.i < 1) {
1015 parserror("tapecycle must be positive");
1018 case RUNTAPES: get_simple(&conf_runtapes, &seen_runtapes, INT);
1019 if(conf_runtapes.i < 1) {
1020 parserror("runtapes must be positive");
1023 case TAPEDEV: get_simple(&conf_tapedev, &seen_tapedev, STRING); break;
1024 case RAWTAPEDEV:get_simple(&conf_rawtapedev,&seen_rawtapedev,STRING); break;
1025 case TPCHANGER: get_simple(&conf_tpchanger, &seen_tpchanger, STRING); break;
1026 case CHNGRDEV: get_simple(&conf_chngrdev, &seen_chngrdev, STRING); break;
1027 case CHNGRFILE: get_simple(&conf_chngrfile, &seen_chngrfile, STRING); break;
1028 case LABELSTR: get_simple(&conf_labelstr, &seen_labelstr, STRING); break;
1029 case TAPELIST: get_simple(&conf_tapelist, &seen_tapelist, STRING); break;
1030 case INFOFILE: get_simple(&conf_infofile, &seen_infofile, STRING); break;
1031 case LOGDIR: get_simple(&conf_logdir, &seen_logdir, STRING); break;
1032 case DISKFILE: get_simple(&conf_diskfile, &seen_diskfile, STRING); break;
1033 case BUMPMULT: get_simple(&conf_bumpmult, &seen_bumpmult, REAL);
1034 if(conf_bumpmult.r < 0.999) {
1035 parserror("bumpmult must be positive");
1038 case BUMPPERCENT: get_simple(&conf_bumppercent, &seen_bumppercent, INT);
1039 if(conf_bumppercent.i < 0 || conf_bumppercent.i > 100) {
1040 parserror("bumppercent must be between 0 and 100");
1043 case BUMPSIZE: get_simple(&conf_bumpsize, &seen_bumpsize, INT);
1044 if(conf_bumpsize.i < 1) {
1045 parserror("bumpsize must be positive");
1048 case BUMPDAYS: get_simple(&conf_bumpdays, &seen_bumpdays, INT);
1049 if(conf_bumpdays.i < 1) {
1050 parserror("bumpdays must be positive");
1053 case NETUSAGE: get_simple(&conf_netusage, &seen_netusage, INT);
1054 if(conf_netusage.i < 1) {
1055 parserror("netusage must be positive");
1058 case INPARALLEL:get_simple(&conf_inparallel,&seen_inparallel,INT);
1059 if(conf_inparallel.i < 1 || conf_inparallel.i >MAX_DUMPERS){
1061 "inparallel must be between 1 and MAX_DUMPERS (%d)",
1065 case DUMPORDER: get_simple(&conf_dumporder, &seen_dumporder, STRING); break;
1066 case TIMEOUT: get_simple(&conf_timeout, &seen_timeout, INT); break;
1067 case MAXDUMPS: get_simple(&conf_maxdumps, &seen_maxdumps, INT);
1068 if(conf_maxdumps.i < 1) {
1069 parserror("maxdumps must be positive");
1072 case TAPETYPE: get_simple(&conf_tapetype, &seen_tapetype, IDENT); break;
1073 case INDEXDIR: get_simple(&conf_indexdir, &seen_indexdir, STRING); break;
1074 case ETIMEOUT: get_simple(&conf_etimeout, &seen_etimeout, INT); break;
1075 case DTIMEOUT: get_simple(&conf_dtimeout, &seen_dtimeout, INT);
1076 if(conf_dtimeout.i < 1) {
1077 parserror("dtimeout must be positive");
1080 case CTIMEOUT: get_simple(&conf_ctimeout, &seen_ctimeout, INT);
1081 if(conf_ctimeout.i < 1) {
1082 parserror("ctimeout must be positive");
1085 case TAPEBUFS: get_simple(&conf_tapebufs, &seen_tapebufs, INT);
1086 if(conf_tapebufs.i < 1) {
1087 parserror("tapebufs must be positive");
1090 case AUTOFLUSH: get_simple(&conf_autoflush, &seen_autoflush, BOOL); break;
1091 case RESERVE: get_simple(&conf_reserve, &seen_reserve, INT);
1092 if(conf_reserve.i < 0 || conf_reserve.i > 100) {
1093 parserror("reserve must be between 0 and 100");
1096 case MAXDUMPSIZE:get_simple(&conf_maxdumpsize,&seen_maxdumpsize,INT); break;
1097 case COLUMNSPEC:get_simple(&conf_columnspec,&seen_columnspec,STRING); break;
1099 case AMRECOVER_DO_FSF: get_simple(&conf_amrecover_do_fsf,&seen_amrecover_do_fsf, BOOL); break;
1100 case AMRECOVER_CHECK_LABEL: get_simple(&conf_amrecover_check_label,&seen_amrecover_check_label, BOOL); break;
1101 case AMRECOVER_CHANGER: get_simple(&conf_amrecover_changer,&seen_amrecover_changer, STRING); break;
1103 case TAPERALGO: get_taperalgo(&conf_taperalgo,&seen_taperalgo); break;
1104 case DISPLAYUNIT: get_simple(&conf_displayunit,&seen_displayunit, STRING);
1105 if(strcmp(conf_displayunit.s,"k") == 0 ||
1106 strcmp(conf_displayunit.s,"K") == 0) {
1107 conf_displayunit.s[0] = toupper(conf_displayunit.s[0]);
1110 else if(strcmp(conf_displayunit.s,"m") == 0 ||
1111 strcmp(conf_displayunit.s,"M") == 0) {
1112 conf_displayunit.s[0] = toupper(conf_displayunit.s[0]);
1115 else if(strcmp(conf_displayunit.s,"g") == 0 ||
1116 strcmp(conf_displayunit.s,"G") == 0) {
1117 conf_displayunit.s[0] = toupper(conf_displayunit.s[0]);
1118 unit_divisor=1024*1024;
1120 else if(strcmp(conf_displayunit.s,"t") == 0 ||
1121 strcmp(conf_displayunit.s,"T") == 0) {
1122 conf_displayunit.s[0] = toupper(conf_displayunit.s[0]);
1123 unit_divisor=1024*1024*1024;
1126 parserror("displayunit must be k,m,g or t.");
1130 case LOGFILE: /* XXX - historical */
1131 /* truncate the filename part and pretend he said "logdir" */
1135 get_simple(&conf_logdir, &seen_logdir, STRING);
1137 p = strrchr(conf_logdir.s, '/');
1138 if (p != (char *)0) *p = '\0';
1146 get_conftoken(STRING);
1150 conf_diskdir.s = newstralloc(conf_diskdir.s, s);
1151 seen_diskdir = line_num;
1154 init_holdingdisk_defaults();
1155 hdcur.name = "default from DISKDIR";
1156 hdcur.seen = line_num;
1157 hdcur.diskdir = stralloc(s);
1158 hdcur.s_disk = line_num;
1159 hdcur.disksize = conf_disksize.i;
1160 hdcur.s_size = seen_disksize;
1170 i = (i / DISK_BLOCK_KB) * DISK_BLOCK_KB;
1172 if(!seen_disksize) {
1173 conf_disksize.i = i;
1174 seen_disksize = line_num;
1177 if(holdingdisks != NULL)
1178 holdingdisks->disksize = i;
1189 if(tok == DUMPTYPE) get_dumptype();
1190 else if(tok == TAPETYPE) get_tapetype();
1191 else if(tok == INTERFACE) get_interface();
1192 else parserror("DUMPTYPE, INTERFACE or TAPETYPE expected");
1195 case NL: /* empty line */
1197 case END: /* end of file */
1200 parserror("configuration keyword expected");
1202 if(tok != NL) get_conftoken(NL);
1206 keytab_t holding_keytable[] = {
1207 { "DIRECTORY", DIRECTORY },
1208 { "COMMENT", COMMENT },
1210 { "CHUNKSIZE", CHUNKSIZE },
1214 static void get_holdingdisk()
1217 int save_overwrites;
1220 save_overwrites = allow_overwrites;
1221 allow_overwrites = 1;
1224 keytable = holding_keytable;
1226 init_holdingdisk_defaults();
1228 get_conftoken(IDENT);
1229 hdcur.name = stralloc(tokenval.s);
1230 malloc_mark(hdcur.name);
1231 hdcur.seen = line_num;
1233 get_conftoken(LBRACE);
1243 get_simple((val_t *)&hdcur.comment, &hdcur.s_comment, STRING);
1246 get_simple((val_t *)&hdcur.diskdir, &hdcur.s_disk, STRING);
1249 get_simple((val_t *)&hdcur.disksize, &hdcur.s_size, LONG);
1250 hdcur.disksize = am_floor(hdcur.disksize, DISK_BLOCK_KB);
1253 get_simple((val_t *)&hdcur.chunksize, &hdcur.s_csize, LONG);
1254 if(hdcur.chunksize == 0) {
1255 hdcur.chunksize = ((INT_MAX / 1024) - (2 * DISK_BLOCK_KB));
1256 } else if(hdcur.chunksize < 0) {
1257 parserror("Negative chunksize (%ld) is no longer supported",
1260 hdcur.chunksize = am_floor(hdcur.chunksize, DISK_BLOCK_KB);
1265 case NL: /* empty line */
1267 case END: /* end of file */
1270 parserror("holding disk parameter expected");
1272 if(tok != NL && tok != END) get_conftoken(NL);
1277 allow_overwrites = save_overwrites;
1281 static void init_holdingdisk_defaults()
1283 hdcur.comment = stralloc("");
1284 hdcur.diskdir = stralloc(conf_diskdir.s);
1285 malloc_mark(hdcur.diskdir);
1287 hdcur.chunksize = 1024*1024/**1024*/; /* 1 Gb = 1M counted in 1Kb blocks */
1289 hdcur.s_comment = 0;
1294 hdcur.up = (void *)0;
1297 static void save_holdingdisk()
1301 hp = alloc(sizeof(holdingdisk_t));
1304 hp->next = holdingdisks;
1311 keytab_t dumptype_keytable[] = {
1313 { "BUMPDAYS", BUMPDAYS },
1314 { "BUMPMULT", BUMPMULT },
1315 { "BUMPSIZE", BUMPSIZE },
1316 { "BUMPPERCENT", BUMPPERCENT },
1317 { "COMMENT", COMMENT },
1318 { "COMPRATE", COMPRATE },
1319 { "COMPRESS", COMPRESS },
1320 { "DUMPCYCLE", DUMPCYCLE },
1321 { "EXCLUDE", EXCLUDE },
1322 { "FREQUENCY", FREQUENCY }, /* XXX - historical */
1323 { "HOLDINGDISK", HOLDING },
1324 { "IGNORE", IGNORE },
1325 { "INCLUDE", INCLUDE },
1327 { "KENCRYPT", KENCRYPT },
1328 { "MAXCYCLE", MAXCYCLE }, /* XXX - historical */
1329 { "MAXDUMPS", MAXDUMPS },
1330 { "MAXPROMOTEDAY", MAXPROMOTEDAY },
1331 { "OPTIONS", OPTIONS }, /* XXX - historical */
1332 { "PRIORITY", PRIORITY },
1333 { "PROGRAM", PROGRAM },
1334 { "RECORD", RECORD },
1335 { "SKIP-FULL", SKIP_FULL },
1336 { "SKIP-INCR", SKIP_INCR },
1337 { "STARTTIME", STARTTIME },
1338 { "STRATEGY", STRATEGY },
1339 { "ESTIMATE", ESTIMATE },
1343 dumptype_t *read_dumptype(name, from, fname, linenum)
1350 int save_overwrites;
1353 FILE *saved_conf = NULL;
1354 char *saved_fname = NULL;
1362 saved_fname = confname;
1367 line_num = *linenum;
1369 save_overwrites = allow_overwrites;
1370 allow_overwrites = 1;
1373 keytable = dumptype_keytable;
1375 init_dumptype_defaults();
1380 get_conftoken(IDENT);
1381 dpcur.name = stralloc(tokenval.s);
1382 malloc_mark(dpcur.name);
1385 dpcur.seen = line_num;
1388 get_conftoken(LBRACE);
1402 get_simple((val_t *)&dpcur.comment, &dpcur.s_comment, STRING);
1411 get_simple((val_t *)&dpcur.dumpcycle, &dpcur.s_dumpcycle, INT);
1412 if(dpcur.dumpcycle < 0) {
1413 parserror("dumpcycle must be positive");
1420 get_simple((val_t *)&dpcur.frequency, &dpcur.s_frequency, INT);
1423 get_simple(&tmpval, &dpcur.s_no_hold, BOOL);
1424 dpcur.no_hold = (tmpval.i == 0);
1427 get_simple(&tmpval, &dpcur.s_ignore, BOOL);
1428 dpcur.ignore = (tmpval.i != 0);
1434 get_simple(&tmpval, &dpcur.s_index, BOOL);
1435 dpcur.index = (tmpval.i != 0);
1438 get_simple(&tmpval, &dpcur.s_kencrypt, BOOL);
1439 dpcur.kencrypt = (tmpval.i != 0);
1442 get_simple((val_t *)&conf_maxcycle, &dpcur.s_maxcycle, INT);
1445 get_simple((val_t *)&dpcur.maxdumps, &dpcur.s_maxdumps, INT);
1446 if(dpcur.maxdumps < 1) {
1447 parserror("maxdumps must be positive");
1451 get_simple((val_t *)&dpcur.maxpromoteday, &dpcur.s_maxpromoteday, INT);
1452 if(dpcur.maxpromoteday < 0) {
1453 parserror("dpcur.maxpromoteday must be >= 0");
1457 get_simple((val_t *)&dpcur.bumppercent, &dpcur.s_bumppercent, INT);
1458 if(dpcur.bumppercent < 0 || dpcur.bumppercent > 100) {
1459 parserror("bumppercent must be between 0 and 100");
1463 get_simple((val_t *)&dpcur.bumpsize, &dpcur.s_bumpsize, INT);
1464 if(dpcur.bumpsize < 1) {
1465 parserror("bumpsize must be positive");
1469 get_simple((val_t *)&dpcur.bumpdays, &dpcur.s_bumpdays, INT);
1470 if(dpcur.bumpdays < 1) {
1471 parserror("bumpdays must be positive");
1475 get_simple((val_t *)&dpcur.bumpmult, &dpcur.s_bumpmult, REAL);
1476 if(dpcur.bumpmult < 0.999) {
1477 parserror("bumpmult must be positive (%f)",dpcur.bumpmult);
1487 get_simple((val_t *)&dpcur.program, &dpcur.s_program, STRING);
1488 if(strcmp(dpcur.program, "DUMP")
1489 && strcmp(dpcur.program, "GNUTAR"))
1490 parserror("backup program \"%s\" unknown", dpcur.program);
1493 get_simple(&tmpval, &dpcur.s_record, BOOL);
1494 dpcur.record = (tmpval.i != 0);
1497 get_simple(&tmpval, &dpcur.s_skip_full, BOOL);
1498 dpcur.skip_full = (tmpval.i != 0);
1501 get_simple(&tmpval, &dpcur.s_skip_incr, BOOL);
1502 dpcur.skip_incr = (tmpval.i != 0);
1505 get_simple((val_t *)&dpcur.start_t, &dpcur.s_start_t, TIME);
1520 case NL: /* empty line */
1522 case END: /* end of file */
1525 parserror("dump type parameter expected");
1527 if(tok != NL && tok != END &&
1528 /* When a name is specified, we shouldn't consume the NL
1529 after the RBRACE. */
1530 (tok != RBRACE || name == 0))
1534 /* XXX - there was a stupidity check in here for skip-incr and
1535 ** skip-full. This check should probably be somewhere else. */
1539 allow_overwrites = save_overwrites;
1543 *linenum = line_num;
1546 confname = saved_fname;
1551 return lookup_dumptype(dpcur.name);
1554 static void get_dumptype()
1556 read_dumptype(NULL, NULL, NULL, NULL);
1559 static void init_dumptype_defaults()
1561 dpcur.comment = stralloc("");
1562 dpcur.program = stralloc("DUMP");
1563 dpcur.exclude_file = NULL;
1564 dpcur.exclude_list = NULL;
1565 dpcur.include_file = NULL;
1566 dpcur.include_list = NULL;
1568 dpcur.dumpcycle = conf_dumpcycle.i;
1569 dpcur.maxcycle = conf_maxcycle.i;
1570 dpcur.frequency = 1;
1571 dpcur.maxdumps = conf_maxdumps.i;
1572 dpcur.maxpromoteday = 10000;
1573 dpcur.bumppercent = conf_bumppercent.i;
1574 dpcur.bumpsize = conf_bumpsize.i;
1575 dpcur.bumpdays = conf_bumpdays.i;
1576 dpcur.bumpmult = conf_bumpmult.r;
1579 dpcur.auth = AUTH_BSD;
1583 dpcur.strategy = DS_STANDARD;
1584 dpcur.estimate = ES_CLIENT;
1585 dpcur.compress = COMP_FAST;
1586 dpcur.comprate[0] = dpcur.comprate[1] = 0.50;
1587 dpcur.skip_incr = dpcur.skip_full = 0;
1593 dpcur.s_comment = 0;
1594 dpcur.s_program = 0;
1595 dpcur.s_exclude_file = 0;
1596 dpcur.s_exclude_list = 0;
1597 dpcur.s_include_file = 0;
1598 dpcur.s_include_list = 0;
1599 dpcur.s_priority = 0;
1600 dpcur.s_dumpcycle = 0;
1601 dpcur.s_maxcycle = 0;
1602 dpcur.s_frequency = 0;
1603 dpcur.s_maxdumps = 0;
1604 dpcur.s_maxpromoteday = 0;
1605 dpcur.s_bumppercent = 0;
1606 dpcur.s_bumpsize = 0;
1607 dpcur.s_bumpdays = 0;
1608 dpcur.s_bumpmult = 0;
1609 dpcur.s_start_t = 0;
1612 dpcur.s_strategy = 0;
1613 dpcur.s_estimate = 0;
1614 dpcur.s_compress = 0;
1615 dpcur.s_comprate = 0;
1616 dpcur.s_skip_incr = 0;
1617 dpcur.s_skip_full = 0;
1618 dpcur.s_no_hold = 0;
1619 dpcur.s_kencrypt = 0;
1624 static void save_dumptype()
1628 dp = lookup_dumptype(dpcur.name);
1630 if(dp != (dumptype_t *)0) {
1631 parserror("dumptype %s already defined on line %d", dp->name, dp->seen);
1635 dp = alloc(sizeof(dumptype_t));
1638 dp->next = dumplist;
1642 static void copy_dumptype()
1646 dt = lookup_dumptype(tokenval.s);
1649 parserror("dump type parameter expected");
1653 #define dtcopy(v,s) if(dt->s) { dpcur.v = dt->v; dpcur.s = dt->s; }
1656 dpcur.comment = newstralloc(dpcur.comment, dt->comment);
1657 dpcur.s_comment = dt->s_comment;
1660 dpcur.program = newstralloc(dpcur.program, dt->program);
1661 dpcur.s_program = dt->s_program;
1663 if(dt->s_exclude_file) {
1664 dpcur.exclude_file = duplicate_sl(dt->exclude_file);
1665 dpcur.s_exclude_file = dt->s_exclude_file;
1667 if(dt->s_exclude_list) {
1668 dpcur.exclude_list = duplicate_sl(dt->exclude_list);
1669 dpcur.s_exclude_list = dt->s_exclude_list;
1671 if(dt->s_include_file) {
1672 dpcur.include_file = duplicate_sl(dt->include_file);
1673 dpcur.s_include_file = dt->s_include_file;
1675 if(dt->s_include_list) {
1676 dpcur.include_list = duplicate_sl(dt->include_list);
1677 dpcur.s_include_list = dt->s_include_list;
1679 dtcopy(priority, s_priority);
1680 dtcopy(dumpcycle, s_dumpcycle);
1681 dtcopy(maxcycle, s_maxcycle);
1682 dtcopy(frequency, s_frequency);
1683 dtcopy(maxdumps, s_maxdumps);
1684 dtcopy(maxpromoteday, s_maxpromoteday);
1685 dtcopy(bumppercent, s_bumppercent);
1686 dtcopy(bumpsize, s_bumpsize);
1687 dtcopy(bumpdays, s_bumpdays);
1688 dtcopy(bumpmult, s_bumpmult);
1689 dtcopy(start_t, s_start_t);
1690 dtcopy(auth, s_auth);
1691 dtcopy(record, s_record);
1692 dtcopy(strategy, s_strategy);
1693 dtcopy(estimate, s_estimate);
1694 dtcopy(compress, s_compress);
1695 dtcopy(comprate[0], s_comprate);
1696 dtcopy(comprate[1], s_comprate);
1697 dtcopy(skip_incr, s_skip_incr);
1698 dtcopy(skip_full, s_skip_full);
1699 dtcopy(no_hold, s_no_hold);
1700 dtcopy(kencrypt, s_kencrypt);
1701 dtcopy(ignore, s_ignore);
1702 dtcopy(index, s_index);
1705 keytab_t tapetype_keytable[] = {
1706 { "COMMENT", COMMENT },
1707 { "LBL-TEMPL", LBL_TEMPL },
1708 { "BLOCKSIZE", BLOCKSIZE },
1709 { "FILE-PAD", FILE_PAD },
1710 { "FILEMARK", FILEMARK },
1711 { "LENGTH", LENGTH },
1716 static void get_tapetype()
1719 int save_overwrites;
1724 save_overwrites = allow_overwrites;
1725 allow_overwrites = 1;
1728 keytable = tapetype_keytable;
1730 init_tapetype_defaults();
1732 get_conftoken(IDENT);
1733 tpcur.name = stralloc(tokenval.s);
1734 malloc_mark(tpcur.name);
1735 tpcur.seen = line_num;
1737 get_conftoken(LBRACE);
1750 get_simple((val_t *)&tpcur.comment, &tpcur.s_comment, STRING);
1753 get_simple((val_t *)&tpcur.lbl_templ, &tpcur.s_lbl_templ, STRING);
1756 get_simple((val_t *)&tpcur.blocksize, &tpcur.s_blocksize, LONG);
1757 if(tpcur.blocksize < DISK_BLOCK_KB) {
1758 parserror("Tape blocksize must be at least %d KBytes",
1760 } else if(tpcur.blocksize > MAX_TAPE_BLOCK_KB) {
1761 parserror("Tape blocksize must not be larger than %d KBytes",
1766 get_simple(&value, &tpcur.s_file_pad, BOOL);
1767 tpcur.file_pad = (value.i != 0);
1770 get_simple(&value, &tpcur.s_length, LONG);
1772 parserror("Tape length must be positive");
1775 tpcur.length = (unsigned long) value.l;
1779 get_simple(&value, &tpcur.s_filemark, LONG);
1781 parserror("Tape file mark size must be positive");
1784 tpcur.filemark = (unsigned long) value.l;
1788 get_simple((val_t *)&tpcur.speed, &tpcur.s_speed, INT);
1789 if(tpcur.speed < 0) {
1790 parserror("Speed must be positive");
1796 case NL: /* empty line */
1798 case END: /* end of file */
1801 parserror("tape type parameter expected");
1803 if(tok != NL && tok != END) get_conftoken(NL);
1808 allow_overwrites = save_overwrites;
1812 static void init_tapetype_defaults()
1814 tpcur.comment = stralloc("");
1815 tpcur.lbl_templ = stralloc("");
1816 tpcur.blocksize = (DISK_BLOCK_KB);
1818 tpcur.length = 2000 * 1024;
1819 tpcur.filemark = 1000;
1822 tpcur.s_comment = 0;
1823 tpcur.s_lbl_templ = 0;
1824 tpcur.s_blocksize = 0;
1825 tpcur.s_file_pad = 0;
1827 tpcur.s_filemark = 0;
1831 static void save_tapetype()
1835 tp = lookup_tapetype(tpcur.name);
1837 if(tp != (tapetype_t *)0) {
1839 parserror("tapetype %s already defined on line %d", tp->name, tp->seen);
1843 tp = alloc(sizeof(tapetype_t));
1846 tp->next = tapelist;
1850 static void copy_tapetype()
1854 tp = lookup_tapetype(tokenval.s);
1857 parserror("tape type parameter expected");
1861 #define ttcopy(v,s) if(tp->s) { tpcur.v = tp->v; tpcur.s = tp->s; }
1864 tpcur.comment = newstralloc(tpcur.comment, tp->comment);
1865 tpcur.s_comment = tp->s_comment;
1867 if(tp->s_lbl_templ) {
1868 tpcur.lbl_templ = newstralloc(tpcur.lbl_templ, tp->lbl_templ);
1869 tpcur.s_lbl_templ = tp->s_lbl_templ;
1871 ttcopy(blocksize, s_blocksize);
1872 ttcopy(file_pad, s_file_pad);
1873 ttcopy(length, s_length);
1874 ttcopy(filemark, s_filemark);
1875 ttcopy(speed, s_speed);
1878 keytab_t interface_keytable[] = {
1879 { "COMMENT", COMMENT },
1884 static void get_interface()
1887 int save_overwrites;
1890 save_overwrites = allow_overwrites;
1891 allow_overwrites = 1;
1894 keytable = interface_keytable;
1896 init_interface_defaults();
1898 get_conftoken(IDENT);
1899 ifcur.name = stralloc(tokenval.s);
1900 malloc_mark(ifcur.name);
1901 ifcur.seen = line_num;
1903 get_conftoken(LBRACE);
1916 get_simple((val_t *)&ifcur.comment, &ifcur.s_comment, STRING);
1919 get_simple((val_t *)&ifcur.maxusage, &ifcur.s_maxusage, INT);
1920 if(ifcur.maxusage <1) {
1921 parserror("use must bbe positive");
1927 case NL: /* empty line */
1929 case END: /* end of file */
1932 parserror("interface parameter expected");
1934 if(tok != NL && tok != END) get_conftoken(NL);
1939 allow_overwrites = save_overwrites;
1945 static void init_interface_defaults()
1947 ifcur.comment = stralloc("");
1948 ifcur.maxusage = 300;
1950 ifcur.s_comment = 0;
1951 ifcur.s_maxusage = 0;
1956 static void save_interface()
1960 ip = lookup_interface(ifcur.name);
1962 if(ip != (interface_t *)0) {
1963 parserror("interface %s already defined on line %d", ip->name, ip->seen);
1967 ip = alloc(sizeof(interface_t));
1970 ip->next = interface_list;
1971 interface_list = ip;
1974 static void copy_interface()
1978 ip = lookup_interface(tokenval.s);
1981 parserror("interface parameter expected");
1985 #define ifcopy(v,s) if(ip->s) { ifcur.v = ip->v; ifcur.s = ip->s; }
1988 ifcur.comment = newstralloc(ifcur.comment, ip->comment);
1989 ifcur.s_comment = ip->s_comment;
1991 ifcopy(maxusage, s_maxusage);
1994 keytab_t dumpopts_keytable[] = {
1995 { "COMPRESS", COMPRESS },
1997 { "EXCLUDE-FILE", EXCLUDE_FILE },
1998 { "EXCLUDE-LIST", EXCLUDE_LIST },
1999 { "KENCRYPT", KENCRYPT },
2000 { "SKIP-FULL", SKIP_FULL },
2001 { "SKIP-INCR", SKIP_INCR },
2005 static void get_dumpopts() /* XXX - for historical compatability */
2011 keytable = dumpopts_keytable;
2017 case COMPRESS: ckseen(&dpcur.s_compress); dpcur.compress = COMP_FAST; break;
2019 ckseen(&dpcur.s_exclude_file);
2020 get_conftoken(STRING);
2021 dpcur.exclude_file = append_sl(dpcur.exclude_file, stralloc(tokenval.s));
2024 ckseen(&dpcur.s_exclude_list);
2025 get_conftoken(STRING);
2026 dpcur.exclude_list = append_sl(dpcur.exclude_list, stralloc(tokenval.s));
2028 case KENCRYPT: ckseen(&dpcur.s_kencrypt); dpcur.kencrypt = 1; break;
2029 case SKIP_INCR: ckseen(&dpcur.s_skip_incr); dpcur.skip_incr= 1; break;
2030 case SKIP_FULL: ckseen(&dpcur.s_skip_full); dpcur.skip_full= 1; break;
2031 case INDEX: ckseen(&dpcur.s_index); dpcur.index = 1; break;
2035 case NL: done = 1; break;
2040 parserror("dump option expected");
2047 static void get_comprate()
2051 get_simple(&var, &dpcur.s_comprate, REAL);
2052 dpcur.comprate[0] = dpcur.comprate[1] = var.r;
2053 if(dpcur.comprate[0] < 0) {
2054 parserror("full compression rate must be >= 0");
2067 get_conftoken(REAL);
2068 dpcur.comprate[1] = tokenval.r;
2069 if(dpcur.comprate[1] < 0) {
2070 parserror("incremental compression rate must be >= 0");
2074 keytab_t compress_keytable[] = {
2076 { "CLIENT", CLIENT },
2079 { "SERVER", SERVER },
2083 static void get_compress()
2086 int serv, clie, none, fast, best;
2091 keytable = compress_keytable;
2093 ckseen(&dpcur.s_compress);
2095 serv = clie = none = fast = best = 0;
2101 case NONE: none = 1; break;
2102 case FAST: fast = 1; break;
2103 case BEST: best = 1; break;
2104 case CLIENT: clie = 1; break;
2105 case SERVER: serv = 1; break;
2106 case NL: done = 1; break;
2109 serv = clie = 1; /* force an error */
2113 if(serv + clie == 0) clie = 1; /* default to client */
2114 if(none + fast + best == 0) fast = 1; /* default to fast */
2119 if(none && !fast && !best) comp = COMP_NONE;
2120 if(!none && fast && !best) comp = COMP_FAST;
2121 if(!none && !fast && best) comp = COMP_BEST;
2125 if(none && !fast && !best) comp = COMP_NONE;
2126 if(!none && fast && !best) comp = COMP_SERV_FAST;
2127 if(!none && !fast && best) comp = COMP_SERV_BEST;
2131 parserror("NONE, CLIENT FAST, CLIENT BEST, SERVER FAST or SERVER BEST expected");
2135 dpcur.compress = comp;
2140 keytab_t taperalgo_keytable[] = {
2142 { "FIRSTFIT", FIRSTFIT },
2143 { "LARGEST", LARGEST },
2144 { "LARGESTFIT", LARGESTFIT },
2145 { "SMALLEST", SMALLEST },
2150 static void get_taperalgo(c_taperalgo, s_taperalgo)
2157 keytable = taperalgo_keytable;
2159 ckseen(s_taperalgo);
2163 case FIRST: c_taperalgo->i = ALGO_FIRST; break;
2164 case FIRSTFIT: c_taperalgo->i = ALGO_FIRSTFIT; break;
2165 case LARGEST: c_taperalgo->i = ALGO_LARGEST; break;
2166 case LARGESTFIT: c_taperalgo->i = ALGO_LARGESTFIT; break;
2167 case SMALLEST: c_taperalgo->i = ALGO_SMALLEST; break;
2168 case LAST: c_taperalgo->i = ALGO_LAST; break;
2170 parserror("FIRST, FIRSTFIT, LARGEST, LARGESTFIT, SMALLEST or LAST expected");
2176 keytab_t priority_keytable[] = {
2179 { "MEDIUM", MEDIUM },
2183 static void get_priority()
2189 keytable = priority_keytable;
2191 ckseen(&dpcur.s_priority);
2195 case LOW: pri = 0; break;
2196 case MEDIUM: pri = 1; break;
2197 case HIGH: pri = 2; break;
2198 case INT: pri = tokenval.i; break;
2200 parserror("LOW, MEDIUM, HIGH or integer expected");
2203 dpcur.priority = pri;
2208 keytab_t auth_keytable[] = {
2209 { "BSD", BSD_AUTH },
2210 { "KRB4", KRB4_AUTH },
2214 static void get_auth()
2220 keytable = auth_keytable;
2222 ckseen(&dpcur.s_auth);
2233 parserror("BSD or KRB4 expected");
2241 keytab_t strategy_keytable[] = {
2243 { "NOFULL", NOFULL },
2246 { "STANDARD", STANDARD },
2247 { "INCRONLY", INCRONLY },
2251 static void get_strategy()
2257 keytable = strategy_keytable;
2259 ckseen(&dpcur.s_strategy);
2267 strat = DS_STANDARD;
2279 strat = DS_INCRONLY;
2282 parserror("STANDARD or NOFULL expected");
2283 strat = DS_STANDARD;
2285 dpcur.strategy = strat;
2290 keytab_t estimate_keytable[] = {
2291 { "CLIENT", CLIENT },
2292 { "SERVER", SERVER },
2293 { "CALCSIZE", CALCSIZE }
2296 static void get_estimate()
2302 keytable = estimate_keytable;
2304 ckseen(&dpcur.s_estimate);
2315 estime = ES_CALCSIZE;
2318 parserror("CLIENT, SERVER or CALCSIZE expected");
2321 dpcur.estimate = estime;
2326 keytab_t exclude_keytable[] = {
2329 { "APPEND", APPEND },
2330 { "OPTIONAL", OPTIONAL },
2334 static void get_exclude()
2336 int list, got_one = 0;
2343 keytable = exclude_keytable;
2348 exclude = dpcur.exclude_list;
2349 ckseen(&dpcur.s_exclude_list);
2354 exclude = dpcur.exclude_file;
2355 ckseen(&dpcur.s_exclude_file);
2356 if(tok == EFILE) get_conftoken(ANY);
2359 if(tok == OPTIONAL) {
2374 while(tok == STRING) {
2375 exclude = append_sl(exclude, tokenval.s);
2381 if(got_one == 0) { free_sl(exclude); exclude = NULL; }
2384 dpcur.exclude_file = exclude;
2386 dpcur.exclude_list = exclude;
2387 if(!append || optional)
2388 dpcur.exclude_optional = optional;
2395 static void get_include()
2397 int list, got_one = 0;
2404 keytable = exclude_keytable;
2409 include = dpcur.include_list;
2410 ckseen(&dpcur.s_include_list);
2415 include = dpcur.include_file;
2416 ckseen(&dpcur.s_include_file);
2417 if(tok == EFILE) get_conftoken(ANY);
2420 if(tok == OPTIONAL) {
2435 while(tok == STRING) {
2436 include = append_sl(include, tokenval.s);
2442 if(got_one == 0) { free_sl(include); include = NULL; }
2445 dpcur.include_file = include;
2447 dpcur.include_list = include;
2448 if(!append || optional)
2449 dpcur.include_optional = optional;
2456 /* ------------------------ */
2459 static void get_simple(var, seen, type)
2469 get_conftoken(type);
2470 var->s = newstralloc(var->s, tokenval.s);
2471 malloc_mark(var->s);
2474 var->i = get_number();
2477 var->l = get_number();
2480 var->i = get_bool();
2483 get_conftoken(REAL);
2484 var->r = tokenval.r;
2487 var->i = get_time();
2490 error("error [unknown get_simple type: %d]", type);
2496 static int get_time()
2498 time_t st = start_time.r.tv_sec;
2505 stm = localtime(&st);
2506 st -= stm->tm_sec + 60 * (stm->tm_min + 60 * stm->tm_hour);
2507 st += ((hhmm/100*60) + hhmm%100)*60;
2509 if (st-start_time.r.tv_sec<-43200)
2515 keytab_t numb_keytable[] = {
2522 { "INF", INFINITY },
2526 { "KBYTE", MULT1K },
2527 { "KBYTES", MULT1K },
2528 { "KILOBYTE", MULT1K },
2529 { "KILOBYTES", MULT1K },
2534 { "MBYTE", MULT1M },
2535 { "MBYTES", MULT1M },
2537 { "MEGABYTE", MULT1M },
2538 { "MEGABYTES", MULT1M },
2542 { "GBYTE", MULT1G },
2543 { "GBYTES", MULT1G },
2545 { "GIGABYTE", MULT1G },
2546 { "GIGABYTES", MULT1G },
2555 static long get_number()
2561 keytable = numb_keytable;
2567 val = (long) tokenval.i;
2570 val = (long) BIGINT;
2573 parserror("an integer expected");
2577 /* get multiplier, if any */
2581 case NL: /* multiply by one */
2594 default: /* it was not a multiplier */
2603 keytab_t bool_keytable[] = {
2612 { "FALSE", AFALSE },
2617 static int get_bool()
2623 keytable = bool_keytable;
2629 val = tokenval.i ? 1 : 0;
2640 val = 2; /* no argument - most likely TRUE */
2648 static void ckseen(seen)
2651 if(*seen && !allow_overwrites) {
2652 parserror("duplicate parameter, prev def on line %d", *seen);
2657 printf_arglist_function(static void parserror, char *, format)
2661 /* print error message */
2663 fprintf(stderr, "\"%s\", line %d: ", confname, line_num);
2664 arglist_start(argp, format);
2665 vfprintf(stderr, format, argp);
2667 fputc('\n', stderr);
2672 static tok_t lookup_keyword(str)
2677 /* switch to binary search if performance warrants */
2679 for(kwp = keytable; kwp->keyword != NULL; kwp++) {
2680 if(strcmp(kwp->keyword, str) == 0) break;
2685 static char tkbuf[4096];
2687 /* push the last token back (can only unget ANY tokens) */
2688 static void unget_conftoken()
2696 static void get_conftoken(exp)
2707 /* If it looked like a key word before then look it
2708 ** up again in the current keyword table. */
2710 case INT: case REAL: case STRING:
2711 case LBRACE: case RBRACE: case COMMA:
2712 case NL: case END: case UNKNOWN:
2715 if(exp == IDENT) tok = IDENT;
2716 else tok = lookup_keyword(tokenval.s);
2722 while(ch != EOF && ch != '\n' && isspace(ch)) ch = getc(conf);
2723 if(ch == '#') { /* comment - eat everything but eol/eof */
2724 while((ch = getc(conf)) != EOF && ch != '\n') {}
2727 if(isalpha(ch)) { /* identifier */
2731 if(islower(ch)) ch = toupper(ch);
2732 if(buf < tkbuf+sizeof(tkbuf)-1) {
2736 if(!token_overflow) {
2737 parserror("token too long: %.20s...", tkbuf);
2742 } while(isalnum(ch) || ch == '_' || ch == '-');
2749 if(token_overflow) tok = UNKNOWN;
2750 else if(exp == IDENT) tok = IDENT;
2751 else tok = lookup_keyword(tokenval.s);
2753 else if(isdigit(ch)) { /* integer */
2758 negative_number: /* look for goto negative_number below */
2763 tokenval.i = tokenval.i * 10 + (ch - '0');
2765 } while(isdigit(ch));
2771 /* automatically convert to real when expected */
2773 tokenval.r = sign * (double) i;
2778 /* got a real number, not an int */
2780 tokenval.r = sign * (double) i;
2783 while(isdigit(ch)) {
2784 i = i * 10 + (ch - '0');
2788 tokenval.r += sign * ((double)i)/d;
2795 case '"': /* string */
2799 while(ch != '"' && ch != '\n' && ch != EOF) {
2800 if(buf < tkbuf+sizeof(tkbuf)-1) {
2804 if(!token_overflow) {
2805 parserror("string too long: %.20s...", tkbuf);
2812 parserror("missing end quote");
2817 if(token_overflow) tok = UNKNOWN;
2824 goto negative_number;
2830 case ',': tok = COMMA; break;
2831 case '{': tok = LBRACE; break;
2832 case '}': tok = RBRACE; break;
2833 case '\n': tok = NL; break;
2834 case EOF: tok = END; break;
2835 default: tok = UNKNOWN;
2839 if(exp != ANY && tok != exp) {
2844 case LBRACE: str = "\"{\""; break;
2845 case RBRACE: str = "\"}\""; break;
2846 case COMMA: str = "\",\""; break;
2848 case NL: str = "end of line"; break;
2849 case END: str = "end of file"; break;
2850 case INT: str = "an integer"; break;
2851 case REAL: str = "a real number"; break;
2852 case STRING: str = "a quoted string"; break;
2853 case IDENT: str = "an identifier"; break;
2855 for(kwp = keytable; kwp->keyword != NULL; kwp++)
2856 if(exp == kwp->token) break;
2857 if(kwp->keyword == NULL) str = "token not";
2858 else str = kwp->keyword;
2860 parserror("%s expected", str);
2862 if(tok == INT) tokenval.i = 0;
2863 else tokenval.s = "";
2869 int ColumnDataCount()
2871 return sizeof(ColumnData) / sizeof(ColumnData[0]);
2874 /* conversion from string to table index
2876 int StringToColumn(char *s) {
2878 for (cn=0; ColumnData[cn].Name != NULL; cn++) {
2879 if (strcasecmp(s, ColumnData[cn].Name) == 0) {
2886 char LastChar(char *s) {
2887 return s[strlen(s)-1];
2890 int SetColumDataFromString(ColumnInfo* ci, char *s, char **errstr) {
2891 /* Convert from a Columspec string to our internal format
2892 * of columspec. The purpose is to provide this string
2893 * as configuration paramter in the amanda.conf file or
2894 * (maybe) as environment variable.
2896 * This text should go as comment into the sample amanda.conf
2898 * The format for such a ColumnSpec string s is a ',' seperated
2899 * list of triples. Each triple consists of
2900 * -the name of the column (as in ColumnData.Name)
2901 * -prefix before the column
2902 * -the width of the column
2903 * if set to -1 it will be recalculated
2904 * to the maximum length of a line to print.
2906 * "Disk=1:17,HostName=1:10,OutKB=1:7"
2908 * "Disk=1:-1,HostName=1:10,OutKB=1:7"
2910 * You need only specify those colums that should be changed from
2911 * the default. If nothing is specified in the configfile, the
2912 * above compiled in values will be in effect, resulting in an
2913 * output as it was all the time.
2917 char *myname= "SetColumDataFromString";
2923 char *eon= strchr(s, '=');
2926 *errstr = stralloc2("invalid columnspec: ", s);
2928 fprintf(stderr, "%s: %s\n", myname, *errstr);
2933 cn=StringToColumn(s);
2934 if (ColumnData[cn].Name == NULL) {
2935 *errstr = stralloc2("invalid column name: ", s);
2937 fprintf(stderr, "%s: %s\n", myname, *errstr);
2941 if (sscanf(eon+1, "%d:%d", &Space, &Width) != 2) {
2942 *errstr = stralloc2("invalid format: ", eon + 1);
2944 fprintf(stderr, "%s: %s\n", myname, *errstr);
2948 ColumnData[cn].Width= Width;
2949 ColumnData[cn].PrefixSpace= Space;
2950 if (LastChar(ColumnData[cn].Format) == 's') {
2952 ColumnData[cn].MaxWidth= 1;
2954 if (Width > ColumnData[cn].Precision)
2955 ColumnData[cn].Precision= Width;
2957 else if (Width < ColumnData[cn].Precision)
2958 ColumnData[cn].Precision= Width;
2959 s= strchr(eon+1, ',');
2967 char *taperalgo2str(taperalgo)
2970 if(taperalgo == ALGO_FIRST) return "FIRST";
2971 if(taperalgo == ALGO_FIRSTFIT) return "FIRSTFIT";
2972 if(taperalgo == ALGO_LARGEST) return "LARGEST";
2973 if(taperalgo == ALGO_LARGESTFIT) return "LARGESTFIT";
2974 if(taperalgo == ALGO_SMALLEST) return "SMALLEST";
2975 if(taperalgo == ALGO_LAST) return "LAST";
2979 long int getconf_unit_divisor()
2981 return unit_divisor;
2984 /* ------------------------ */
2990 dump_configuration(filename)
3000 printf("AMANDA CONFIGURATION FROM FILE \"%s\":\n\n", filename);
3002 printf("conf_org = \"%s\"\n", getconf_str(CNF_ORG));
3003 printf("conf_mailto = \"%s\"\n", getconf_str(CNF_MAILTO));
3004 printf("conf_dumpuser = \"%s\"\n", getconf_str(CNF_DUMPUSER));
3005 printf("conf_printer = \"%s\"\n", getconf_str(CNF_PRINTER));
3006 printf("conf_tapedev = \"%s\"\n", getconf_str(CNF_TAPEDEV));
3007 printf("conf_rawtapedev = \"%s\"\n", getconf_str(CNF_RAWTAPEDEV));
3008 printf("conf_tpchanger = \"%s\"\n", getconf_str(CNF_TPCHANGER));
3009 printf("conf_chngrdev = \"%s\"\n", getconf_str(CNF_CHNGRDEV));
3010 printf("conf_chngrfile = \"%s\"\n", getconf_str(CNF_CHNGRFILE));
3011 printf("conf_labelstr = \"%s\"\n", getconf_str(CNF_LABELSTR));
3012 printf("conf_tapelist = \"%s\"\n", getconf_str(CNF_TAPELIST));
3013 printf("conf_infofile = \"%s\"\n", getconf_str(CNF_INFOFILE));
3014 printf("conf_logdir = \"%s\"\n", getconf_str(CNF_LOGDIR));
3015 printf("conf_diskfile = \"%s\"\n", getconf_str(CNF_DISKFILE));
3016 printf("conf_tapetype = \"%s\"\n", getconf_str(CNF_TAPETYPE));
3018 printf("conf_dumpcycle = %d\n", getconf_int(CNF_DUMPCYCLE));
3019 printf("conf_runspercycle = %d\n", getconf_int(CNF_RUNSPERCYCLE));
3020 printf("conf_runtapes = %d\n", getconf_int(CNF_RUNTAPES));
3021 printf("conf_tapecycle = %d\n", getconf_int(CNF_TAPECYCLE));
3022 printf("conf_bumppercent = %d\n", getconf_int(CNF_BUMPPERCENT));
3023 printf("conf_bumpsize = %d\n", getconf_int(CNF_BUMPSIZE));
3024 printf("conf_bumpdays = %d\n", getconf_int(CNF_BUMPDAYS));
3025 printf("conf_bumpmult = %f\n", getconf_real(CNF_BUMPMULT));
3026 printf("conf_netusage = %d\n", getconf_int(CNF_NETUSAGE));
3027 printf("conf_inparallel = %d\n", getconf_int(CNF_INPARALLEL));
3028 printf("conf_dumporder = \"%s\"\n", getconf_str(CNF_DUMPORDER));
3029 /*printf("conf_timeout = %d\n", getconf_int(CNF_TIMEOUT));*/
3030 printf("conf_maxdumps = %d\n", getconf_int(CNF_MAXDUMPS));
3031 printf("conf_etimeout = %d\n", getconf_int(CNF_ETIMEOUT));
3032 printf("conf_dtimeout = %d\n", getconf_int(CNF_DTIMEOUT));
3033 printf("conf_ctimeout = %d\n", getconf_int(CNF_CTIMEOUT));
3034 printf("conf_tapebufs = %d\n", getconf_int(CNF_TAPEBUFS));
3035 printf("conf_autoflush = %d\n", getconf_int(CNF_AUTOFLUSH));
3036 printf("conf_reserve = %d\n", getconf_int(CNF_RESERVE));
3037 printf("conf_maxdumpsize = %d\n", getconf_int(CNF_MAXDUMPSIZE));
3038 printf("conf_amrecover_do_fsf = %d\n", getconf_int(CNF_AMRECOVER_DO_FSF));
3039 printf("conf_amrecover_check_label = %d\n", getconf_int(CNF_AMRECOVER_CHECK_LABEL));
3040 printf("conf_amrecover_changer = \"%s\"\n", getconf_str(CNF_AMRECOVER_CHANGER));
3041 printf("conf_taperalgo = %s\n", taperalgo2str(getconf_int(CNF_TAPERALGO)));
3042 printf("conf_displayunit = %s\n", getconf_str(CNF_DISPLAYUNIT));
3044 /*printf("conf_diskdir = \"%s\"\n", getconf_str(CNF_DISKDIR));*/
3045 /*printf("conf_disksize = %d\n", getconf_int(CNF_DISKSIZE));*/
3046 printf("conf_columnspec = \"%s\"\n", getconf_str(CNF_COLUMNSPEC));
3047 printf("conf_indexdir = \"%s\"\n", getconf_str(CNF_INDEXDIR));
3048 printf("num_holdingdisks = %d\n", num_holdingdisks);
3049 for(hp = holdingdisks; hp != NULL; hp = hp->next) {
3050 printf("\nHOLDINGDISK %s:\n", hp->name);
3051 printf(" COMMENT \"%s\"\n", hp->comment);
3052 printf(" DISKDIR \"%s\"\n", hp->diskdir);
3053 printf(" SIZE %ld\n", (long)hp->disksize);
3054 printf(" CHUNKSIZE %ld\n", (long)hp->chunksize);
3057 for(tp = tapelist; tp != NULL; tp = tp->next) {
3058 printf("\nTAPETYPE %s:\n", tp->name);
3059 printf(" COMMENT \"%s\"\n", tp->comment);
3060 printf(" LBL_TEMPL %s\n", tp->lbl_templ);
3061 printf(" BLOCKSIZE %ld\n", (long)tp->blocksize);
3062 printf(" FILE_PAD %s\n", (tp->file_pad) ? "YES" : "NO");
3063 printf(" LENGTH %lu\n", (unsigned long)tp->length);
3064 printf(" FILEMARK %lu\n", (unsigned long)tp->filemark);
3065 printf(" SPEED %ld\n", (long)tp->speed);
3068 for(dp = dumplist; dp != NULL; dp = dp->next) {
3069 printf("\nDUMPTYPE %s:\n", dp->name);
3070 printf(" COMMENT \"%s\"\n", dp->comment);
3071 printf(" PROGRAM \"%s\"\n", dp->program);
3072 printf(" PRIORITY %ld\n", (long)dp->priority);
3073 printf(" DUMPCYCLE %ld\n", (long)dp->dumpcycle);
3076 stm = localtime(&st);
3077 printf(" STARTTIME %d:%02d:%02d\n",
3078 stm->tm_hour, stm->tm_min, stm->tm_sec);
3080 if(dp->exclude_file) {
3082 printf(" EXCLUDE FILE");
3083 for(excl = dp->exclude_file->first; excl != NULL; excl =excl->next){
3084 printf(" \"%s\"", excl->name);
3088 if(dp->exclude_list) {
3090 printf(" EXCLUDE LIST");
3091 for(excl = dp->exclude_list->first; excl != NULL; excl =excl->next){
3092 printf(" \"%s\"", excl->name);
3096 if(dp->include_file) {
3098 printf(" INCLUDE FILE");
3099 for(incl = dp->include_file->first; incl != NULL; incl =incl->next){
3100 printf(" \"%s\"", incl->name);
3104 if(dp->include_list) {
3106 printf(" INCLUDE LIST");
3107 for(incl = dp->include_list->first; incl != NULL; incl =incl->next){
3108 printf(" \"%s\"", incl->name);
3112 printf(" FREQUENCY %ld\n", (long)dp->frequency);
3113 printf(" MAXDUMPS %d\n", dp->maxdumps);
3114 printf(" MAXPROMOTEDAY %d\n", dp->maxpromoteday);
3115 printf(" STRATEGY ");
3116 switch(dp->strategy) {
3137 printf(" ESTIMATE ");
3138 switch(dp->estimate) {
3150 printf(" COMPRATE %f, %f\n", dp->comprate[0], dp->comprate[1]);
3152 printf(" OPTIONS: ");
3154 switch(dp->compress) {
3156 printf("NO-COMPRESS ");
3159 printf("COMPRESS-FAST ");
3162 printf("COMPRESS-BEST ");
3164 case COMP_SERV_FAST:
3165 printf("SRVCOMP-FAST ");
3167 case COMP_SERV_BEST:
3168 printf("SRVCOMP-BEST ");
3172 if(!dp->record) printf("NO-");
3174 if(dp->auth == AUTH_BSD) printf(" BSD-AUTH");
3175 else if(dp->auth == AUTH_KRB4) printf(" KRB4-AUTH");
3176 else printf(" UNKNOWN-AUTH");
3177 if(dp->skip_incr) printf(" SKIP-INCR");
3178 if(dp->skip_full) printf(" SKIP-FULL");
3179 if(dp->no_hold) printf(" NO-HOLD");
3180 if(dp->kencrypt) printf(" KENCRYPT");
3181 /* an ignored disk will never reach this point */
3182 assert(!dp->ignore);
3183 if(dp->index) printf(" INDEX");
3187 for(ip = interface_list; ip != NULL; ip = ip->next) {
3188 printf("\nINTERFACE %s:\n", ip->name);
3189 printf(" COMMENT \"%s\"\n", ip->comment);
3190 printf(" USE %d\n", ip->maxusage);
3202 unsigned long malloc_hist_1, malloc_size_1;
3203 unsigned long malloc_hist_2, malloc_size_2;
3207 set_pname("conffile");
3209 malloc_size_1 = malloc_inuse(&malloc_hist_1);
3214 if (argv[1][0] == '/') {
3215 config_dir = stralloc(argv[1]);
3216 config_name = strrchr(config_dir, '/') + 1;
3217 config_name[-1] = '\0';
3218 config_dir = newstralloc2(config_dir, config_dir, "/");
3220 config_name = stralloc(argv[1]);
3221 config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
3224 char my_cwd[STR_SIZE];
3226 if (getcwd(my_cwd, sizeof(my_cwd)) == NULL) {
3227 error("cannot determine current working directory");
3229 config_dir = stralloc2(my_cwd, "/");
3230 if ((config_name = strrchr(my_cwd, '/')) != NULL) {
3231 config_name = stralloc(config_name + 1);
3235 conffile = stralloc2(config_dir, CONFFILE_NAME);
3236 result = read_conffile(conffile);
3238 diskfile = getconf_str(CNF_DISKFILE);
3239 if (diskfile != NULL && access(diskfile, R_OK) == 0) {
3240 result = (read_diskfile(diskfile) == NULL);
3243 dump_configuration(CONFFILE_NAME);
3246 malloc_size_2 = malloc_inuse(&malloc_hist_2);
3248 if(malloc_size_1 != malloc_size_2) {
3249 malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);