Imported Upstream version 2.6.1
[debian/amanda] / common-src / conffile.h
index 8873cec75292b3d659bae70148c72d098d6319c0..a61edd9d2f3c7c9ae5b53761bbc36a7146047bde 100644 (file)
 /* Getting Configuration Values
  * ============================
  *
- * Amanda configurations consist of a number of "global" parameters, as well as named
- * subsections of four types: dumptypes, interfaces, holdingdisks, and tapetypes.  The
- * global parameters are fetched with the getconf_CONFTYPE functions, keyed by a
- * confparam_t constant (with prefix CNF_).  The subsection parameters are fetched with
- * SUBSEC_get_PARAM() macros, e.g., tapetype_get_blocksize(ttyp), where the argument
- * comes from lookup_SUBSEC(), in this case lookup_tapetype(name).
+ * Amanda configurations consist of a number of "global" parameters, as well as
+ * named subsections of several types.  The global parameters are fetched with
+ * the getconf_CONFTYPE functions, keyed by a confparam_t constant (with prefix
+ * CNF_).  The subsection parameters are fetched with SUBSEC_get_PARAM()
+ * macros, e.g., tapetype_get_blocksize(ttyp), where the argument comes from
+ * lookup_SUBSEC(), in this case lookup_tapetype(name).
  *
  * Types
  * =====
  * ======
  * Note that, unless specified, all memory in this module is managed by the module
  * itself; return strings should not be freed by the caller.
+ *
+ * Error Handling
+ * ==============
+ * All errors and warnings generated by this module are available from get_config_errors().
+ * It is up to the caller to route these messages to the user.  The function
+ * config_print_errors() will print the errors to stderr, as a convenience.
  */
 
 /*
@@ -131,19 +137,55 @@ typedef enum {
     ALGO_ALGO /* sentinel */
 } taperalgo_t;
 
+/* execute_on types */
+#define EXECUTE_ON_PRE_DLE_AMCHECK     1<<0
+#define EXECUTE_ON_PRE_HOST_AMCHECK    1<<1
+#define EXECUTE_ON_POST_DLE_AMCHECK    1<<2
+#define EXECUTE_ON_POST_HOST_AMCHECK   1<<3
+#define EXECUTE_ON_PRE_DLE_ESTIMATE    1<<4
+#define EXECUTE_ON_PRE_HOST_ESTIMATE   1<<5
+#define EXECUTE_ON_POST_DLE_ESTIMATE   1<<6
+#define EXECUTE_ON_POST_HOST_ESTIMATE  1<<7
+#define EXECUTE_ON_PRE_DLE_BACKUP      1<<8
+#define EXECUTE_ON_PRE_HOST_BACKUP     1<<9
+#define EXECUTE_ON_POST_DLE_BACKUP     1<<10
+#define EXECUTE_ON_POST_HOST_BACKUP    1<<11
+#define EXECUTE_ON_PRE_RECOVER         1<<12
+#define EXECUTE_ON_POST_RECOVER        1<<13
+#define EXECUTE_ON_PRE_LEVEL_RECOVER   1<<14
+#define EXECUTE_ON_POST_LEVEL_RECOVER  1<<15
+#define EXECUTE_ON_INTER_LEVEL_RECOVER 1<<16
+typedef int execute_on_t;
+
+typedef int execute_where_t;
+
+typedef enum {
+    SEND_AMREPORT_ALL,
+    SEND_AMREPORT_STRANGE,
+    SEND_AMREPORT_ERROR,
+    SEND_AMREPORT_NEVER
+} send_amreport_t;
+
 typedef struct exinclude_s {
     sl_t *sl_list;
     sl_t *sl_file;
     int  optional;
 } exinclude_t;
 
+typedef struct {
+    int append;
+    int priority;
+    GSList* values;
+} property_t;
+
 typedef GHashTable* proplist_t;
+typedef GSList* pp_scriptlist_t;
 
 /* Names for the type of value in a val_t.  Mostly for internal use, but useful
  * for wrapping val_t's, too. */
 typedef enum {
     CONFTYPE_INT,
-    CONFTYPE_AM64,
+    CONFTYPE_INT64,
     CONFTYPE_REAL,
     CONFTYPE_STR,
     CONFTYPE_IDENT,
@@ -160,16 +202,29 @@ typedef enum {
     CONFTYPE_RATE,
     CONFTYPE_INTRANGE,
     CONFTYPE_EXINCLUDE,
-    CONFTYPE_PROPLIST
+    CONFTYPE_PROPLIST,
+    CONFTYPE_APPLICATION,
+    CONFTYPE_EXECUTE_ON,
+    CONFTYPE_EXECUTE_WHERE,
+    CONFTYPE_SEND_AMREPORT_ON,
+    CONFTYPE_PP_SCRIPTLIST
 } conftype_t;
 
+/* A "seen" struct.  Rather than allocate strings all over the place, this
+ * string is in the "parsed_filenames" GSList and will be freed when that
+ * GSList is freed.  This struct should be opaque to other modules. */
+typedef struct seen_s {
+    char *filename;
+    int linenum;
+} seen_t;
+
 /* This should be considered an opaque type for any other modules.  The complete
  * struct is included here to allow quick access via macros. Access it *only* through
  * those macros. */
 typedef struct val_s {
     union {
         int            i;
-        off_t          am64;
+        gint64         int64;
         double         r;
         char           *s;
         ssize_t                size;
@@ -178,40 +233,47 @@ typedef struct val_s {
         exinclude_t    exinclude;
         int            intrange[2];
         proplist_t      proplist;
+       struct application_s  *application;
+       pp_scriptlist_t pp_scriptlist;
     } v;
-    int seen;
+    seen_t seen;
     conftype_t type;
 } val_t;
 
 /* Functions to typecheck and extract a particular type of
  * value from a val_t.  All call error() if the type is incorrect,
  * as this is a programming error.  */
-int                 val_t_to_int      (val_t *);
-off_t               val_t_to_am64     (val_t *);
-float               val_t_to_real     (val_t *);
-char               *val_t_to_str      (val_t *); /* (also converts CONFTYPE_IDENT) */
-char               *val_t_to_ident    (val_t *); /* (also converts CONFTYPE_STR) */
-time_t              val_t_to_time     (val_t *);
-ssize_t             val_t_to_size     (val_t *);
-int                 val_t_to_boolean  (val_t *);
-comp_t              val_t_to_compress (val_t *);
-encrypt_t           val_t_to_encrypt  (val_t *);
-dump_holdingdisk_t  val_t_to_holding  (val_t *);
-estimate_t          val_t_to_estimate (val_t *);
-strategy_t          val_t_to_strategy (val_t *);
-taperalgo_t         val_t_to_taperalgo(val_t *);
-int                 val_t_to_priority (val_t *);
-float              *val_t_to_rate     (val_t *); /* array of two floats */
-exinclude_t         val_t_to_exinclude(val_t *);
-int                *val_t_to_intrange (val_t *); /* array of two ints */
-proplist_t          val_t_to_proplist (val_t *);
+int                   val_t_to_int      (val_t *);
+gint64                val_t_to_int64    (val_t *);
+float                 val_t_to_real     (val_t *);
+char                 *val_t_to_str      (val_t *); /* (also converts CONFTYPE_IDENT) */
+char                 *val_t_to_ident    (val_t *); /* (also converts CONFTYPE_STR) */
+time_t                val_t_to_time     (val_t *);
+ssize_t               val_t_to_size     (val_t *);
+int                   val_t_to_boolean  (val_t *);
+comp_t                val_t_to_compress (val_t *);
+encrypt_t             val_t_to_encrypt  (val_t *);
+dump_holdingdisk_t    val_t_to_holding  (val_t *);
+estimate_t            val_t_to_estimate (val_t *);
+strategy_t            val_t_to_strategy (val_t *);
+taperalgo_t           val_t_to_taperalgo(val_t *);
+int                   val_t_to_priority (val_t *);
+float                *val_t_to_rate     (val_t *); /* array of two floats */
+exinclude_t           val_t_to_exinclude(val_t *);
+int                  *val_t_to_intrange (val_t *); /* array of two ints */
+proplist_t            val_t_to_proplist (val_t *);
+struct application_s *val_t_to_application(val_t *);
+pp_scriptlist_t       val_t_to_pp_scriptlist(val_t *);
+execute_on_t          val_t_to_execute_on(val_t *);
+execute_where_t       val_t_to_execute_where(val_t *);
+send_amreport_t       val_t_to_send_amreport(val_t *);
 
 /* Has the given val_t been seen in a configuration file or config overwrite?
  *
  * @param val: val_t* to examine
  * @returns: boolean
  */
-#define val_t_seen(val) ((val)->seen)
+#define val_t_seen(val) ((val)->seen.linenum)
 
 /* What is the underlying type of this val_t?
  *
@@ -227,26 +289,31 @@ proplist_t          val_t_to_proplist (val_t *);
  * (in the macro name) to the corresponding union field.  The macros work
  * as lvalues, too.
  */
-#define val_t__seen(val)        ((val)->seen)
-#define val_t__int(val)         ((val)->v.i)
-#define val_t__am64(val)        ((val)->v.am64)
-#define val_t__real(val)        ((val)->v.r)
-#define val_t__str(val)         ((val)->v.s)
-#define val_t__ident(val)       ((val)->v.s)
-#define val_t__time(val)        ((val)->v.t)
-#define val_t__size(val)        ((val)->v.size)
-#define val_t__boolean(val)     ((val)->v.i)
-#define val_t__compress(val)    ((val)->v.i)
-#define val_t__encrypt(val)     ((val)->v.i)
-#define val_t__holding(val)     ((val)->v.i)
-#define val_t__estimate(val)    ((val)->v.i)
-#define val_t__strategy(val)    ((val)->v.i)
-#define val_t__taperalgo(val)   ((val)->v.i)
-#define val_t__priority(val)    ((val)->v.i)
-#define val_t__rate(val)        ((val)->v.rate)
-#define val_t__exinclude(val)   ((val)->v.exinclude)
-#define val_t__intrange(val)    ((val)->v.intrange)
-#define val_t__proplist(val)    ((val)->v.proplist)
+#define val_t__seen(val)          ((val)->seen)
+#define val_t__int(val)           ((val)->v.i)
+#define val_t__int64(val)         ((val)->v.int64)
+#define val_t__real(val)          ((val)->v.r)
+#define val_t__str(val)           ((val)->v.s)
+#define val_t__ident(val)         ((val)->v.s)
+#define val_t__time(val)          ((val)->v.t)
+#define val_t__size(val)          ((val)->v.size)
+#define val_t__boolean(val)       ((val)->v.i)
+#define val_t__compress(val)      ((val)->v.i)
+#define val_t__encrypt(val)       ((val)->v.i)
+#define val_t__holding(val)       ((val)->v.i)
+#define val_t__estimate(val)      ((val)->v.i)
+#define val_t__strategy(val)      ((val)->v.i)
+#define val_t__taperalgo(val)     ((val)->v.i)
+#define val_t__send_amreport(val) ((val)->v.i)
+#define val_t__priority(val)      ((val)->v.i)
+#define val_t__rate(val)          ((val)->v.rate)
+#define val_t__exinclude(val)     ((val)->v.exinclude)
+#define val_t__intrange(val)      ((val)->v.intrange)
+#define val_t__proplist(val)      ((val)->v.proplist)
+#define val_t__pp_scriptlist(val) ((val)->v.pp_scriptlist)
+#define val_t__application(val)   ((val)->v.application)
+#define val_t__execute_on(val)    ((val)->v.i)
+#define val_t__execute_where(val) ((val)->v.i)
 /*
  * Parameters
  *
@@ -272,7 +339,15 @@ typedef enum {
     CNF_MAILTO,
     CNF_DUMPUSER,
     CNF_TAPEDEV,
+    CNF_RAWTAPEDEV,
     CNF_DEVICE_PROPERTY,
+    CNF_PROPERTY,
+    CNF_APPLICATION,
+    CNF_APPLICATION_TOOL,
+    CNF_EXECUTE_ON,
+    CNF_PP_SCRIPT,
+    CNF_PP_SCRIPT_TOOL,
+    CNF_PLUGIN,
     CNF_CHANGERDEV,
     CNF_CHANGERFILE,
     CNF_LABELSTR,
@@ -301,6 +376,7 @@ typedef enum {
     CNF_TAPEBUFS,
     CNF_DEVICE_OUTPUT_BUFFER_SIZE,
     CNF_PRINTER,
+    CNF_MAILER,
     CNF_AUTOFLUSH,
     CNF_RESERVE,
     CNF_MAXDUMPSIZE,
@@ -309,6 +385,7 @@ typedef enum {
     CNF_AMRECOVER_CHECK_LABEL,
     CNF_AMRECOVER_CHANGER,
     CNF_TAPERALGO,
+    CNF_SEND_AMREPORT_ON,
     CNF_FLUSH_THRESHOLD_DUMPED,
     CNF_FLUSH_THRESHOLD_SCHEDULED,
     CNF_TAPERFLUSH,
@@ -366,7 +443,7 @@ val_t *getconf(confparm_key key);
  * @returns: various
  */
 #define getconf_int(key)          (val_t_to_int(getconf((key))))
-#define getconf_am64(key)         (val_t_to_am64(getconf((key))))
+#define getconf_int64(key)        (val_t_to_int64(getconf((key))))
 #define getconf_real(key)         (val_t_to_real(getconf((key))))
 #define getconf_str(key)         (val_t_to_str(getconf((key))))
 #define getconf_ident(key)        (val_t_to_ident(getconf((key))))
@@ -384,6 +461,7 @@ val_t *getconf(confparm_key key);
 #define getconf_exinclude(key)    (val_t_to_exinclude(getconf((key))))
 #define getconf_intrange(key)     (val_t_to_intrange(getconf((key))))
 #define getconf_proplist(key)     (val_t_to_proplist(getconf((key))))
+#define getconf_send_amreport(key) (val_t_to_send_amreport(getconf((key))))
 
 /* Get a list of names for subsections of the given type
  *
@@ -494,8 +572,8 @@ char *tapetype_name(tapetype_t *ttyp);
 #define tapetype_get_lbl_templ(ttyp)       (val_t_to_str(tapetype_getconf((ttyp), TAPETYPE_LBL_TEMPL)))
 #define tapetype_get_blocksize(ttyp)       (val_t_to_size(tapetype_getconf((ttyp), TAPETYPE_BLOCKSIZE)))
 #define tapetype_get_readblocksize(ttyp)   (val_t_to_size(tapetype_getconf((ttyp), TAPETYPE_READBLOCKSIZE)))
-#define tapetype_get_length(ttyp)          (val_t_to_am64(tapetype_getconf((ttyp), TAPETYPE_LENGTH)))
-#define tapetype_get_filemark(ttyp)        (val_t_to_am64(tapetype_getconf((ttyp), TAPETYPE_FILEMARK)))
+#define tapetype_get_length(ttyp)          (val_t_to_int64(tapetype_getconf((ttyp), TAPETYPE_LENGTH)))
+#define tapetype_get_filemark(ttyp)        (val_t_to_int64(tapetype_getconf((ttyp), TAPETYPE_FILEMARK)))
 #define tapetype_get_speed(ttyp)           (val_t_to_int(tapetype_getconf((ttyp), TAPETYPE_SPEED)))
 #define tapetype_get_file_pad(ttyp)        (val_t_to_boolean(tapetype_getconf((ttyp), TAPETYPE_FILE_PAD)))
 
@@ -542,6 +620,9 @@ typedef enum {
     DUMPTYPE_KENCRYPT,
     DUMPTYPE_IGNORE,
     DUMPTYPE_INDEX,
+    DUMPTYPE_APPLICATION,
+    DUMPTYPE_PP_SCRIPTLIST,
+    DUMPTYPE_PROPERTY,
     DUMPTYPE_DUMPTYPE /* sentinel */
 } dumptype_key;
 
@@ -604,7 +685,7 @@ char *dumptype_name(dumptype_t *dtyp);
 #define dumptype_get_maxdumps(dtyp)            (val_t_to_int(dumptype_getconf((dtyp), DUMPTYPE_MAXDUMPS)))
 #define dumptype_get_maxpromoteday(dtyp)       (val_t_to_int(dumptype_getconf((dtyp), DUMPTYPE_MAXPROMOTEDAY)))
 #define dumptype_get_bumppercent(dtyp)         (val_t_to_int(dumptype_getconf((dtyp), DUMPTYPE_BUMPPERCENT)))
-#define dumptype_get_bumpsize(dtyp)            (val_t_to_am64(dumptype_getconf((dtyp), DUMPTYPE_BUMPSIZE)))
+#define dumptype_get_bumpsize(dtyp)            (val_t_to_int64(dumptype_getconf((dtyp), DUMPTYPE_BUMPSIZE)))
 #define dumptype_get_bumpdays(dtyp)            (val_t_to_int(dumptype_getconf((dtyp), DUMPTYPE_BUMPDAYS)))
 #define dumptype_get_bumpmult(dtyp)            (val_t_to_real(dumptype_getconf((dtyp), DUMPTYPE_BUMPMULT)))
 #define dumptype_get_starttime(dtyp)           (val_t_to_time(dumptype_getconf((dtyp), DUMPTYPE_STARTTIME)))
@@ -615,8 +696,8 @@ char *dumptype_name(dumptype_t *dtyp);
 #define dumptype_get_srv_decrypt_opt(dtyp)     (val_t_to_str(dumptype_getconf((dtyp), DUMPTYPE_SRV_DECRYPT_OPT)))
 #define dumptype_get_clnt_decrypt_opt(dtyp)    (val_t_to_str(dumptype_getconf((dtyp), DUMPTYPE_CLNT_DECRYPT_OPT)))
 #define dumptype_get_comprate(dtyp)            (val_t_to_rate(dumptype_getconf((dtyp), DUMPTYPE_COMPRATE)))
-#define dumptype_get_tape_splitsize(dtyp)      (val_t_to_am64(dumptype_getconf((dtyp), DUMPTYPE_TAPE_SPLITSIZE)))
-#define dumptype_get_fallback_splitsize(dtyp)  (val_t_to_am64(dumptype_getconf((dtyp), DUMPTYPE_FALLBACK_SPLITSIZE)))
+#define dumptype_get_tape_splitsize(dtyp)      (val_t_to_int64(dumptype_getconf((dtyp), DUMPTYPE_TAPE_SPLITSIZE)))
+#define dumptype_get_fallback_splitsize(dtyp)  (val_t_to_int64(dumptype_getconf((dtyp), DUMPTYPE_FALLBACK_SPLITSIZE)))
 #define dumptype_get_split_diskbuffer(dtyp)    (val_t_to_str(dumptype_getconf((dtyp), DUMPTYPE_SPLIT_DISKBUFFER)))
 #define dumptype_get_record(dtyp)              (val_t_to_boolean(dumptype_getconf((dtyp), DUMPTYPE_RECORD)))
 #define dumptype_get_skip_incr(dtyp)           (val_t_to_boolean(dumptype_getconf((dtyp), DUMPTYPE_SKIP_INCR)))
@@ -625,6 +706,9 @@ char *dumptype_name(dumptype_t *dtyp);
 #define dumptype_get_kencrypt(dtyp)            (val_t_to_boolean(dumptype_getconf((dtyp), DUMPTYPE_KENCRYPT)))
 #define dumptype_get_ignore(dtyp)              (val_t_to_boolean(dumptype_getconf((dtyp), DUMPTYPE_IGNORE)))
 #define dumptype_get_index(dtyp)               (val_t_to_boolean(dumptype_getconf((dtyp), DUMPTYPE_INDEX)))
+#define dumptype_get_application(dtyp)         (val_t_to_application(dumptype_getconf((dtyp), DUMPTYPE_APPLICATION)))
+#define dumptype_get_pp_scriptlist(dtyp)       (val_t_to_pp_scriptlist(dumptype_getconf((dtyp), DUMPTYPE_PP_SCRIPTLIST)))
+#define dumptype_get_property(dtyp)            (val_t_to_proplist(dumptype_getconf((dtyp), DUMPTYPE_PROPERTY)))
 
 /*
  * Interface parameter access
@@ -748,8 +832,290 @@ char *holdingdisk_name(holdingdisk_t *hdisk);
  */
 #define holdingdisk_get_comment(hdisk)   (val_t_to_str(holdingdisk_getconf((hdisk), HOLDING_COMMENT)))
 #define holdingdisk_get_diskdir(hdisk)   (val_t_to_str(holdingdisk_getconf((hdisk), HOLDING_DISKDIR)))
-#define holdingdisk_get_disksize(hdisk)  (val_t_to_am64(holdingdisk_getconf((hdisk), HOLDING_DISKSIZE)))
-#define holdingdisk_get_chunksize(hdisk) (val_t_to_am64(holdingdisk_getconf((hdisk), HOLDING_CHUNKSIZE)))
+#define holdingdisk_get_disksize(hdisk)  (val_t_to_int64(holdingdisk_getconf((hdisk), HOLDING_DISKSIZE)))
+#define holdingdisk_get_chunksize(hdisk) (val_t_to_int64(holdingdisk_getconf((hdisk), HOLDING_CHUNKSIZE)))
+
+/* A application-tool interface */
+typedef enum application_e  {
+    APPLICATION_COMMENT,
+    APPLICATION_PLUGIN,
+    APPLICATION_PROPERTY,
+    APPLICATION_APPLICATION
+} application_key;
+
+/* opaque object */
+typedef struct application_s application_t;
+
+/* Given the name of the application, return a application object.  Returns NULL
+ * if no matching application exists.  Note that the match is case-insensitive.
+ *
+ * @param identifier: name of the desired application
+ * @returns: object or NULL
+ */
+
+application_t *lookup_application(char *identifier);
+
+/* Given a application and a key, return a pointer to the corresponding val_t.
+ *
+ * @param ttyp: the application to examine
+ * @param key: application (one of the APPLICATION_* constants)
+ * @returns: pointer to value
+ */
+val_t *application_getconf(application_t *app, application_key key);
+
+/* Get the name of this application.
+ *
+ * @param ttyp: the application to examine
+ * @returns: name of the application
+ */
+char *application_name(application_t *app);
+
+/* (convenience macro) has this parameter been seen in this application?  This
+ * applies to the specific parameter *within* the application.
+ *
+ * @param key: application_key
+ * @returns: boolean
+ */
+#define application_seen(app, key)       (val_t_seen(application_getconf((app), (key))))
+
+/* (convenience macros)
+ * fetch a particular parameter; caller must know the correct type.
+ *
+ * @param ttyp: the application to examine
+ * @returns: various
+ */
+#define application_get_comment(application)  (val_t_to_str(application_getconf((application), APPLICATION_COMMENT))
+#define application_get_plugin(application)   (val_t_to_str(application_getconf((application), APPLICATION_PLUGIN)))
+#define application_get_property(application) (val_t_to_proplist(application_getconf((application), APPLICATION_PROPERTY)))
+
+application_t *read_application(char *name, FILE *from, char *fname, int *linenum);
+
+/* A pp-script-tool interface */
+typedef enum pp_script_e  {
+    PP_SCRIPT_COMMENT,
+    PP_SCRIPT_PLUGIN,
+    PP_SCRIPT_PROPERTY,
+    PP_SCRIPT_EXECUTE_ON,
+    PP_SCRIPT_EXECUTE_WHERE,
+    PP_SCRIPT_PP_SCRIPT
+} pp_script_key;
+
+/* opaque object */
+typedef struct pp_script_s pp_script_t;
+
+/* Given the name of the pp_script, return a pp_script object.  Returns NULL
+ * if no matching pp_script exists.  Note that the match is case-insensitive.
+ *
+ * @param identifier: name of the desired pp_script
+ * @returns: object or NULL
+ */
+
+pp_script_t *lookup_pp_script(char *identifier);
+
+/* Given a pp_script and a key, return a pointer to the corresponding val_t.
+ *
+ * @param ttyp: the pp_script to examine
+ * @param key: pp_script (one of the PP_SCRIPT_* constants)
+ * @returns: pointer to value
+ */
+val_t *pp_script_getconf(pp_script_t *pps, pp_script_key key);
+
+/* Get the name of this pp_script.
+ *
+ * @param ttyp: the pp_script to examine
+ * @returns: name of the pp_script
+ */
+char *pp_script_name(pp_script_t *pps);
+
+/* (convenience macro) has this parameter been seen in this pp_script?  This
+ * applies to the specific parameter *within* the pp_script.
+ *
+ * @param key: pp_script_key
+ * @returns: boolean
+ */
+#define pp_script_seen(pps, key)       (val_t_seen(pp_script_getconf((pps), (key))))
+
+/* (convenience macros)
+ * fetch a particular parameter; caller must know the correct type.
+ *
+ * @param ttyp: the pp_script to examine
+ * @returns: various
+ */
+
+#define pp_script_get_comment(pp_script)   (val_t_to_str(pp_script_getconf((pp_script), PP_SCRIPT_COMMENT)))
+#define pp_script_get_plugin(pp_script)   (val_t_to_str(pp_script_getconf((pp_script), PP_SCRIPT_PLUGIN)))
+#define pp_script_get_property(pp_script)   (val_t_to_proplist(pp_script_getconf((pp_script), PP_SCRIPT_PROPERTY)))
+#define pp_script_get_execute_on(pp_script)   (val_t_to_execute_on(pp_script_getconf((pp_script), PP_SCRIPT_EXECUTE_ON)))
+#define pp_script_get_execute_where(pp_script)   (val_t_to_execute_where(pp_script_getconf((pp_script), PP_SCRIPT_EXECUTE_WHERE)))
+
+pp_script_t *read_pp_script(char *name, FILE *from, char *fname, int *linenum);
+pp_script_t *lookup_pp_script(char *identifier);
+
+/* A device definition */
+typedef enum {
+    DEVICE_CONFIG_COMMENT,
+    DEVICE_CONFIG_TAPEDEV,
+    DEVICE_CONFIG_DEVICE_PROPERTY,
+    DEVICE_CONFIG_DEVICE_CONFIG
+} device_config_key;
+
+/* opaque object */
+typedef struct device_config_s device_config_t;
+
+/* Given the name of the device, return a device_config_t object.  Returns NULL
+ * if no matching device exists.  Note that the match is case-insensitive.
+ *
+ * @param identifier: name of the desired device
+ * @returns: object or NULL
+ */
+
+device_config_t *lookup_device_config(char *identifier);
+
+/* Given a device_config and a key, return a pointer to the corresponding val_t.
+ *
+ * @param ttyp: the device_config to examine
+ * @param key: device_config (one of the DEVICE_CONFIG_* constants)
+ * @returns: pointer to value
+ */
+val_t *device_config_getconf(device_config_t *devconf, device_config_key key);
+
+/* Get the name of this device_config.
+ *
+ * @param ttyp: the device_config to examine
+ * @returns: name of the device_config
+ */
+char *device_config_name(device_config_t *devconf);
+
+/* (convenience macro) has this parameter been seen in this device_config?  This
+ * applies to the specific parameter *within* the device_config.
+ *
+ * @param key: device_config_key
+ * @returns: boolean
+ */
+#define device_config_seen(devconf, key)       (val_t_seen(device_config_getconf((devconf), (key))))
+
+/* (convenience macros)
+ * fetch a particular parameter; caller must know the correct type.
+ *
+ * @param devconf: the device_config to examine
+ * @returns: various
+ */
+
+#define device_config_get_comment(devconf)   (val_t_to_str(device_config_getconf((devconf), DEVICE_CONFIG_COMMENT)))
+#define device_config_get_tapedev(devconf)   (val_t_to_str(device_config_getconf((devconf), DEVICE_CONFIG_TAPEDEV)))
+#define device_config_get_property(devconf)   (val_t_to_proplist(device_config_getconf((devconf), DEVICE_CONFIG_DEVICE_PROPERTY)))
+
+device_config_t *read_device_config(char *name, FILE *from, char *fname, int *linenum);
+device_config_t *lookup_device_config(char *identifier);
+
+/* A changer definition */
+typedef enum {
+    CHANGER_CONFIG_COMMENT,
+    CHANGER_CONFIG_TAPEDEV,
+    CHANGER_CONFIG_TPCHANGER,
+    CHANGER_CONFIG_CHANGERDEV,
+    CHANGER_CONFIG_CHANGERFILE,
+    CHANGER_CONFIG_CHANGER_CONFIG
+} changer_config_key;
+
+/* opaque object */
+typedef struct changer_config_s changer_config_t;
+
+/* Given the name of the changer, return a changer_config_t object.  Returns NULL
+ * if no matching changer exists.  Note that the match is case-insensitive.
+ *
+ * @param identifier: name of the desired changer
+ * @returns: object or NULL
+ */
+
+changer_config_t *lookup_changer_config(char *identifier);
+
+/* Given a changer_config and a key, return a pointer to the corresponding val_t.
+ *
+ * @param ttyp: the changer_config to examine
+ * @param key: changer_config (one of the DEVICE_CONFIG_* constants)
+ * @returns: pointer to value
+ */
+val_t *changer_config_getconf(changer_config_t *devconf, changer_config_key key);
+
+/* Get the name of this changer_config.
+ *
+ * @param ttyp: the changer_config to examine
+ * @returns: name of the changer_config
+ */
+char *changer_config_name(changer_config_t *devconf);
+
+/* (convenience macro) has this parameter been seen in this changer_config?  This
+ * applies to the specific parameter *within* the changer_config.
+ *
+ * @param key: changer_config_key
+ * @returns: boolean
+ */
+#define changer_config_seen(devconf, key)       (val_t_seen(changer_config_getconf((devconf), (key))))
+
+/* (convenience macros)
+ * fetch a particular parameter; caller must know the correct type.
+ *
+ * @param devconf: the changer_config to examine
+ * @returns: various
+ */
+
+#define changer_config_get_comment(devconf)   (val_t_to_str(changer_config_getconf((devconf), DEVICE_CONFIG_COMMENT)))
+#define changer_config_get_tapedev(devconf)   (val_t_to_str(changer_config_getconf((devconf), DEVICE_CONFIG_TAPEDEV)))
+#define changer_config_get_tpchanger(devconf)   (val_t_to_str(changer_config_getconf((devconf), DEVICE_CONFIG_TPCHANGER)))
+#define changer_config_get_changerdev(devconf)   (val_t_to_str(changer_config_getconf((devconf), DEVICE_CONFIG_CHANGERDEV)))
+#define changer_config_get_changerfile(devconf)   (val_t_to_str(changer_config_getconf((devconf), DEVICE_CONFIG_CHANGERFILE)))
+
+changer_config_t *read_changer_config(char *name, FILE *from, char *fname, int *linenum);
+changer_config_t *lookup_changer_config(char *identifier);
+
+/*
+ * Error Handling
+ */
+
+typedef enum {
+    /* No errors or warnings */
+    CFGERR_OK = 0,
+
+    /* warnings were encountered */
+    CFGERR_WARNINGS = 1,
+
+    /* errors (and maybe some warnings too, who knows) were encountered */
+    CFGERR_ERRORS = 2,
+} cfgerr_level_t;
+
+/*
+ * Errors
+ */
+
+/* Get a GSList of all error and warning messages accumulated so far.
+ *
+ * @param (output) errlist: pointer to the list of error strings; allocated
+ * memory remains the responsibility of the config module.  If errlist is
+ * NULL, the list is not returned.
+ * @returns: current error level
+ */
+cfgerr_level_t config_errors(GSList **errlist);
+
+/* Clear any error conditions.
+ */
+void config_clear_errors(void);
+
+/* Print the list of current error and warning messages, one per line,
+ * to stderr. This is a convenience function for command-line
+ * applications.
+ */
+void config_print_errors(void);
+
+/* Add an error message to the list of errors, and make sure tha the
+ * error level is at least LEVEL.  This is used by the diskfile module
+ * to insert its errors into this module's error list.
+ *
+ * @param level: level for this error
+ * @param errmsg: error message; conffile takes responsibility for freeing
+ *   this string.
+ */
+void config_add_error(cfgerr_level_t level, char *errmsg);
 
 /*
  * Command-line handling
@@ -809,15 +1175,13 @@ extract_commandline_config_overwrites(int *argc,
                                      char ***argv);
 
 /* Apply configuration overwrites to the current configuration and take
- * ownership of the config_overwrites object.
- *
- * If any parameters are not matched in the current symbol table, or
- * correspond to named subsections which do not exist, this function calls
- * error() and does not return.
+ * ownership of the config_overwrites object.  It is the caller's
+ * responsibility to handle any errors.
  *
  * @param co: the config_overwrites object
+ * @returns: current error level
  */
-void apply_config_overwrites(config_overwrites_t *co);
+cfgerr_level_t apply_config_overwrites(config_overwrites_t *co);
 
 /*
  * Initialization
@@ -837,9 +1201,6 @@ typedef enum {
     /* New configuration should "overlay" existing configuration; this
      * is used by clients to load multiple amanda-client.conf files. */
     CONFIG_INIT_OVERLAY = 1 << 3,
-
-    /* If the file doesn't exist, halt with an error. */
-    CONFIG_INIT_FATAL = 1 << 4,
 } config_init_flags;
 
 /* Initialize this application's configuration, with the specific actions
@@ -855,15 +1216,14 @@ typedef enum {
  *  - otherwise, for the client only, se config_dir to CONFIG_DIR and
  *    config_name to NULL.
  *  - depending on CONFIG_INIT_CLIENT, read amanda.conf or amanda-client.conf
- *  - in the event of an error, call error() if CONFIG_INIT_FATAL, otherwise
- *    record a message in the debug log and return false.
  *
  * @param flags: flags indicating desired behavior, as above
  * @param arg_config_name: config name to use (from e.g., argv[1])
- * @returns: true on success, false on failure, unless CONFIG_INIT_FATAL
+ * @returns: current error level
  */
-gboolean config_init(config_init_flags flags,
-                    char *arg_config_name);
+cfgerr_level_t config_init(
+        config_init_flags flags,
+        char *arg_config_name);
 
 /* Free all memory allocated for the configuration.  This effectively
  * reverses the effects of config_init().
@@ -891,21 +1251,14 @@ void config_uninit(void);
  */
 char **get_config_options(int first);
 
-/* The name of the configuration under which this application is running.
- * This variable is initialized by config_init, and should be treated as
- * read-only.
- */
-extern char *config_name;
+/* Get the config name */
+char *get_config_name(void);
 
-/* The directory containing the configuration for this application.  This
- * variable is initialized by config_init, and should be treated as read-only.
- */
-extern char *config_dir;
+/* Get the config directory */
+char *get_config_dir(void);
 
-/* The most recently read top-level configuration file.  This variable is
- * initialized by config_init, and should be treated as read-only.
- */
-extern char *config_filename;
+/* Get the config filename */
+char *get_config_filename(void);
 
 /*
  * Utilities
@@ -956,6 +1309,15 @@ char **val_t_display_strs(val_t *val, int str_needs_quotes);
  */
 dumptype_t *read_dumptype(char *name, FILE *from, char *fname, int *linenum);
 
+/* Every call return a pointer to a string with an increasing number; this is
+ * used by this module as well as by diskfile.c to read the disklist.
+ *
+ * Nobody else should use this function.  Seriously.
+ *
+ * @returns: a pointer to a static string.
+ */
+char *anonymous_value(void);
+
 /* Extend a relative filename with the current config_dir; if filename is already
  * absolute, this is equivalent to stralloc.
  *
@@ -983,4 +1345,18 @@ char *taperalgo2str(taperalgo_t taperalgo);
  */
 gint64 find_multiplier(char * casestr);
 
+/* Compute the size needed in an ARGV to pass all properties
+ *
+ * @param proplist: The property list
+ * @returns: The size required for an ARGV
+ */
+int property_argv_size(proplist_t proplist);
+
+/* Add all properties to an ARGV
+ *
+ * @param argvchild: Pointer to the ARGV.
+ * @param proplist: The property list
+ */
+int property_add_to_argv(char **argvchild, proplist_t proplist);
+
 #endif /* ! CONFFILE_H */