Hi!

It took some time, but here is an implementation of feature request
#17. I named the command `Eval` instead of `IncludeCmd` because it seemed
clearer to me, but you're welcome to change that.

Patch 1 was necessary to print error line numbers correctly after adding
`Eval` without modifying every line where errors are printed. It might
be worthwhile to set `cfile->error` here too, and I'll gladly amend the
patch if you agree. On the other hand, it is a formatting function...

Patch 2 is where the actual work happens. I indeed tried to follow
`cred_from_cmd`. Nesting `Eval` statements is disallowed. Implementing
this would certainly be doable, but I don't really see the point.  

I was working on an extra patch, which would extend the parser to
allow multiline values for slightly longer commands. For example:

    Eval "\
        echo User $USER \
        echo Path $XDG_DATA_HOME/notmuch/default \
    "

Due to the way the `cfile->buf` buffer is aliased by `cfile->cmd` etc
this proved to be a little bit more difficult than I initially thought. I
have a few questions:

  - Do you see merit in this feature? I don't currently need it, but
    like configuration file formats which offer possibilities to split
    lines if they get too long.
  - If so, what would you think is the better implementation? Just make
    the buffer really large (what is large?) and error if a script is
    longer? The current line limit is 1024. The other option I see is
    dynamically reallocating the buffer (I have already played with this,
    but sadly that implementation was not aware of comments) and updating
    the pointers in `cfile` as needed. Maybe throw in a `restrict`.
  - Do you agree with the syntax? This still requires backslashes even
    when quoted, which I like due to the missing closing quote error
    which would otherwise be hard to correctly detect.
  - What should the behaviour be when not quoted? A literal newline
    (current implementation)? Read it as whitespace?

Anyway, valgrind was an issue on my end and is fixed. So it has been
tested with it, hopefully no leaks this time ;)

Once again, feedback is very welcome!

Kind regards,  
Michiel van den Heuvel
>From 1ef12e2b3f205af4324565183b700e27ecc88830 Mon Sep 17 00:00:00 2001
From: Michiel van den Heuvel <michielvdnheu...@gmail.com>
Date: Wed, 16 Aug 2023 20:36:48 +0200
Subject: [PATCH 2/2] Add Eval directive to config parser

---
 src/config.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++---
 src/config.h |  2 ++
 src/mbsync.1 | 10 +++++++
 3 files changed, 89 insertions(+), 4 deletions(-)

diff --git a/src/config.c b/src/config.c
index 3aa3f7c..6e08dd9 100644
--- a/src/config.c
+++ b/src/config.c
@@ -61,13 +61,23 @@ expand_strdup( const char *s, const conffile_t *cfile )
 	}
 }
 
+void
+conf_print_loc( const conffile_t *cfile )
+{
+	if (cfile->eval_fp != NULL) {
+		fprintf( stderr, "%s:%d:eval %d: ", cfile->file, cfile->line, cfile->eval_line );
+	} else {
+		fprintf( stderr, "%s:%d: ", cfile->file, cfile->line );
+	}
+}
+
 void
 conf_error( const conffile_t *cfile, const char* fmt, ... )
 {
 	va_list va;
 
 	flushn();
-	fprintf( stderr, "%s:%d: ", cfile->file, cfile->line );
+	conf_print_loc( cfile );
 	va_start( va, fmt );
 	vfprintf( stderr, fmt, va );
 	va_end( va );
@@ -78,7 +88,7 @@ conf_sys_error( const conffile_t *cfile, const char* msg, ... )
 {
 	va_list va;
 
-	fprintf( stderr, "%s:%d: ", cfile->file, cfile->line );
+	conf_print_loc( cfile );
 	va_start( va, msg );
 	vsys_error( msg, va );
 	va_end( va );
@@ -326,6 +336,58 @@ getopt_helper( conffile_t *cfile, int *cops, channel_conf_t *conf )
 	return 1;
 }
 
+void
+eval_popen( conffile_t *cfile, const char *cmd )
+{
+	if (*cmd == '+') {
+		flushn();
+		cmd++;
+	}
+	if (!(cfile->eval_fp = popen( cmd, "r" ))) {
+		sys_error( "%s failed", cmd );
+		return;
+	}
+	cfile->eval_line = 0;
+}
+
+void
+eval_pclose( conffile_t *cfile )
+{
+	int ret;
+
+	ret = pclose( cfile->eval_fp );
+	cfile->eval_fp = NULL;
+	if (ret) {
+		if (ret < 0)
+			conf_sys_error( cfile, "command failed" );
+		else if (WIFSIGNALED( ret ))
+			conf_error( cfile, "command crashed\n" );
+		else
+			conf_error( cfile, "command exited with status %d\n", WEXITSTATUS( ret ) );
+	}
+}
+
+char *
+read_cline( conffile_t *cfile )
+{
+	char *ret;
+
+	ret = cfile->buf;
+	if (cfile->eval_fp) {
+		ret = fgets( cfile->buf, cfile->bufl, cfile->eval_fp );
+		cfile->eval_line++;
+		if (!ret) {
+			eval_pclose( cfile );
+			ret = cfile->buf;
+		}
+	}
+	if (!cfile->eval_fp && ret) {
+		ret = fgets( cfile->buf, cfile->bufl, cfile->fp );
+		cfile->line++;
+	}
+	return ret;
+}
+
 int
 getcline( conffile_t *cfile )
 {
@@ -336,14 +398,24 @@ getcline( conffile_t *cfile )
 		conf_error( cfile, "excess token '%s'\n", arg );
 		cfile->err = 1;
 	}
-	while (fgets( cfile->buf, cfile->bufl, cfile->fp )) {
-		cfile->line++;
+	while (read_cline( cfile )) {
 		cfile->rest = cfile->buf;
 		if (!(cfile->cmd = get_arg( cfile, ARG_OPTIONAL, &comment ))) {
 			if (comment)
 				continue;
 			return 1;
 		}
+		if (!strcmp( cfile->cmd, "Eval" )) {
+			if ((arg = get_arg( cfile, ARG_REQUIRED, NULL ))) {
+				if (cfile->eval_fp) {
+					conf_error( cfile, "nested eval\n" );
+					cfile->err = 1;
+					continue;
+				}
+				eval_popen( cfile, arg );
+			}
+			continue;
+		}
 		if (!(cfile->val = get_arg( cfile, ARG_REQUIRED, NULL )))
 			continue;
 		return 1;
@@ -498,6 +570,7 @@ load_config( const char *where )
 		return 1;
 	}
 	buf[sizeof(buf) - 1] = 0;
+	cfile.eval_fp = NULL;
 	cfile.buf = buf;
 	cfile.bufl = sizeof(buf) - 1;
 	cfile.line = 0;
diff --git a/src/config.h b/src/config.h
index 6e38308..ffcfc92 100644
--- a/src/config.h
+++ b/src/config.h
@@ -13,9 +13,11 @@
 typedef struct {
 	const char *file;
 	FILE *fp;
+	FILE *eval_fp;
 	char *buf;
 	int bufl;
 	int line;
+	int eval_line;
 	int err;
 	int ms_warn, renew_warn, delete_warn;
 	int path_len;
diff --git a/src/mbsync.1 b/src/mbsync.1
index 939c8c5..abee422 100644
--- a/src/mbsync.1
+++ b/src/mbsync.1
@@ -152,6 +152,16 @@ even combinations thereof.
 Mailbox names, OTOH, always use canonical path separators, which are
 Unix-like forward slashes.
 .
+.SS Dynamic options
+.TP
+\fBEval\fR [\fB+\fR]\fIcommand\fR
+Specify a shell command to obtain options. The command can output zero
+or more lines which will be interpreted as if they appeared inline.
+.br
+Prepend \fB+\fR to the command to indicate that it produces TTY output
+(e.g., a prompt); failure to do so will merely produce messier output.
+Remember to backslash-escape double quotes and backslashes embedded into
+the command.
 .SS All Stores
 These options can be used in all supported Store types.
 .br
-- 
2.41.0

>From 9875fa10001e40c2a4adb0305250979ab3cbb1d7 Mon Sep 17 00:00:00 2001
From: Michiel van den Heuvel <michielvdnheu...@gmail.com>
Date: Thu, 10 Aug 2023 05:20:55 +0200
Subject: [PATCH 1/2] Refactor printing configuration errors

In preparation for adding the output of commands as configuration lines,
which will complicate printing.
---
 src/config.c      | 73 +++++++++++++++++++++++++++--------------------
 src/config.h      |  3 ++
 src/driver.c      |  4 +--
 src/drv_imap.c    | 33 +++++++++++----------
 src/drv_maildir.c |  6 ++--
 5 files changed, 66 insertions(+), 53 deletions(-)

diff --git a/src/config.c b/src/config.c
index 456bd47..3aa3f7c 100644
--- a/src/config.c
+++ b/src/config.c
@@ -61,6 +61,29 @@ expand_strdup( const char *s, const conffile_t *cfile )
 	}
 }
 
+void
+conf_error( const conffile_t *cfile, const char* fmt, ... )
+{
+	va_list va;
+
+	flushn();
+	fprintf( stderr, "%s:%d: ", cfile->file, cfile->line );
+	va_start( va, fmt );
+	vfprintf( stderr, fmt, va );
+	va_end( va );
+}
+
+void
+conf_sys_error( const conffile_t *cfile, const char* msg, ... )
+{
+	va_list va;
+
+	fprintf( stderr, "%s:%d: ", cfile->file, cfile->line );
+	va_start( va, msg );
+	vsys_error( msg, va );
+	va_end( va );
+}
+
 char *
 get_arg( conffile_t *cfile, int required, int *comment )
 {
@@ -76,7 +99,7 @@ get_arg( conffile_t *cfile, int required, int *comment )
 		if (comment)
 			*comment = (c == '#');
 		if (required) {
-			error( "%s:%d: parameter missing\n", cfile->file, cfile->line );
+			conf_error( cfile, "parameter missing\n" );
 			cfile->err = 1;
 		}
 		ret = NULL;
@@ -98,12 +121,12 @@ get_arg( conffile_t *cfile, int required, int *comment )
 		}
 		*t = 0;
 		if (escaped) {
-			error( "%s:%d: unterminated escape sequence\n", cfile->file, cfile->line );
+			conf_error( cfile, "unterminated escape sequence\n" );
 			cfile->err = 1;
 			ret = NULL;
 		}
 		if (quoted) {
-			error( "%s:%d: missing closing quote\n", cfile->file, cfile->line );
+			conf_error( cfile, "missing closing quote\n" );
 			cfile->err = 1;
 			ret = NULL;
 		}
@@ -124,8 +147,7 @@ parse_bool( conffile_t *cfile )
 	    strcasecmp( cfile->val, "false" ) &&
 	    strcasecmp( cfile->val, "off" ) &&
 	    strcmp( cfile->val, "0" )) {
-		error( "%s:%d: invalid boolean value '%s'\n",
-		       cfile->file, cfile->line, cfile->val );
+		conf_error( cfile, "invalid boolean value '%s'\n", cfile->val );
 		cfile->err = 1;
 	}
 	return 0;
@@ -139,8 +161,7 @@ parse_int( conffile_t *cfile )
 
 	ret = strtol( cfile->val, &p, 10 );
 	if (*p) {
-		error( "%s:%d: invalid integer value '%s'\n",
-		       cfile->file, cfile->line, cfile->val );
+		conf_error( cfile, "invalid integer value '%s'\n", cfile->val );
 		cfile->err = 1;
 		return 0;
 	}
@@ -161,8 +182,7 @@ parse_size( conffile_t *cfile )
 	if (*p == 'b' || *p == 'B')
 		p++;
 	if (*p) {
-		fprintf (stderr, "%s:%d: invalid size '%s'\n",
-		         cfile->file, cfile->line, cfile->val);
+		conf_error ( cfile, "invalid size '%s'\n", cfile->val);
 		cfile->err = 1;
 		return 0;
 	}
@@ -249,8 +269,7 @@ getopt_helper( conffile_t *cfile, int *cops, channel_conf_t *conf )
 			} else if (!strcasecmp( "None", arg ) || !strcasecmp( "Noop", arg )) {
 				conf->ops[F] |= XOP_TYPE_NOOP;
 			} else {
-				error( "%s:%d: invalid Sync arg '%s'\n",
-				       cfile->file, cfile->line, arg );
+				conf_error( cfile, "invalid Sync arg '%s'\n", arg );
 				cfile->err = 1;
 			}
 		} while ((arg = get_arg( cfile, ARG_OPTIONAL, NULL )));
@@ -268,8 +287,7 @@ getopt_helper( conffile_t *cfile, int *cops, channel_conf_t *conf )
 		} else if (!strcasecmp( "Near", arg )) {
 			conf->expire_side = N;
 		} else {
-			error( "%s:%d: invalid ExpireSide argument '%s'\n",
-			       cfile->file, cfile->line, arg );
+			conf_error( cfile, "invalid ExpireSide argument '%s'\n", arg );
 			cfile->err = 1;
 		}
 	} else if (!strcasecmp( "ExpireUnread", cfile->cmd )) {
@@ -295,8 +313,7 @@ getopt_helper( conffile_t *cfile, int *cops, channel_conf_t *conf )
 					} else if (!strcasecmp( "None", arg )) {
 						conf->ops[F] |= op * (XOP_EXPUNGE_NOOP / OP_EXPUNGE);
 					} else {
-						error( "%s:%d: invalid %s arg '%s'\n",
-						       cfile->file, cfile->line, boxOps[i].name, arg );
+						conf_error( cfile, "invalid %s arg '%s'\n", boxOps[i].name, arg );
 						cfile->err = 1;
 					}
 				} while ((arg = get_arg( cfile, ARG_OPTIONAL, NULL )));
@@ -316,7 +333,7 @@ getcline( conffile_t *cfile )
 	int comment;
 
 	if (cfile->rest && (arg = get_arg( cfile, ARG_OPTIONAL, NULL ))) {
-		error( "%s:%d: excess token '%s'\n", cfile->file, cfile->line, arg );
+		conf_error( cfile, "excess token '%s'\n", arg );
 		cfile->err = 1;
 	}
 	while (fgets( cfile->buf, cfile->bufl, cfile->fp )) {
@@ -546,8 +563,7 @@ load_config( const char *where )
 					cfile.ms_warn = 1;
 				  linkst:
 					if (*cfile.val != ':' || !(p = strchr( cfile.val + 1, ':' ))) {
-						error( "%s:%d: malformed mailbox spec\n",
-						       cfile.file, cfile.line );
+						conf_error( &cfile, "malformed mailbox spec\n" );
 						cfile.err = 1;
 						continue;
 					}
@@ -559,16 +575,14 @@ load_config( const char *where )
 						}
 					}
 					channel->stores[fn] = (void *)~0;
-					error( "%s:%d: unknown store '%s'\n",
-					       cfile.file, cfile.line, cfile.val + 1 );
+					conf_error( &cfile, "unknown store '%s'\n", cfile.val + 1 );
 					cfile.err = 1;
 					continue;
 				  stpcom:
 					if (*++p)
 						channel->boxes[fn] = nfstrdup( p );
 				} else if (!getopt_helper( &cfile, &cops, channel )) {
-					error( "%s:%d: keyword '%s' is not recognized in Channel sections\n",
-					       cfile.file, cfile.line, cfile.cmd );
+					conf_error( &cfile, "keyword '%s' is not recognized in Channel sections\n", cfile.cmd );
 					cfile.rest = NULL;
 					cfile.err = 1;
 				}
@@ -615,8 +629,7 @@ load_config( const char *where )
 					arg = cfile.val;
 					goto addone;
 				} else {
-					error( "%s:%d: keyword '%s' is not recognized in Group sections\n",
-					       cfile.file, cfile.line, cfile.cmd );
+					conf_error( &cfile, "keyword '%s' is not recognized in Group sections\n", cfile.cmd );
 					cfile.rest = NULL;
 					cfile.err = 1;
 				}
@@ -627,24 +640,23 @@ load_config( const char *where )
 			UseFSync = parse_bool( &cfile );
 		} else if (!strcasecmp( "FieldDelimiter", cfile.cmd )) {
 			if (strlen( cfile.val ) != 1) {
-				error( "%s:%d: Field delimiter must be exactly one character long\n", cfile.file, cfile.line );
+				conf_error( &cfile, "Field delimiter must be exactly one character long\n" );
 				cfile.err = 1;
 			} else {
 				FieldDelimiter = cfile.val[0];
 				if (!ispunct( FieldDelimiter )) {
-					error( "%s:%d: Field delimiter must be a punctuation character\n", cfile.file, cfile.line );
+					conf_error( &cfile, "Field delimiter must be a punctuation character\n" );
 					cfile.err = 1;
 				}
 			}
 		} else if (!strcasecmp( "BufferLimit", cfile.cmd )) {
 			BufferLimit = parse_size( &cfile );
 			if (!BufferLimit) {
-				error( "%s:%d: BufferLimit cannot be zero\n", cfile.file, cfile.line );
+				conf_error( &cfile, "BufferLimit cannot be zero\n" );
 				cfile.err = 1;
 			}
 		} else if (!getopt_helper( &cfile, &gcops, &global_conf )) {
-			error( "%s:%d: '%s' is not a recognized section-starting or global keyword\n",
-			       cfile.file, cfile.line, cfile.cmd );
+			conf_error( &cfile, "'%s' is not a recognized section-starting or global keyword\n", cfile.cmd );
 			cfile.err = 1;
 			cfile.rest = NULL;
 			while (getcline( &cfile ))
@@ -653,8 +665,7 @@ load_config( const char *where )
 			break;
 		}
 		if (!glob_ok) {
-			error( "%s:%d: global options may not follow sections\n",
-			       cfile.file, cfile.line );
+			conf_error( &cfile, "global options may not follow sections\n" );
 			cfile.err = 1;
 		}
 	}
diff --git a/src/config.h b/src/config.h
index 0762b58..6e38308 100644
--- a/src/config.h
+++ b/src/config.h
@@ -29,6 +29,9 @@ extern char FieldDelimiter;
 
 char *expand_strdup( const char *s, const conffile_t *cfile );
 
+void ATTR_PRINTFLIKE(2, 3) conf_error( const conffile_t *, const char *, ... );
+void ATTR_PRINTFLIKE(2, 3) conf_sys_error( const conffile_t *, const char *, ... );
+
 char *get_arg( conffile_t *cfile, int required, int *comment );
 
 char parse_bool( conffile_t *cfile );
diff --git a/src/driver.c b/src/driver.c
index 6b88dbb..fa5a954 100644
--- a/src/driver.c
+++ b/src/driver.c
@@ -83,14 +83,14 @@ parse_generic_store( store_conf_t *store, conffile_t *cfg, const char *type )
 		const char *p;
 		for (p = cfg->val; *p; p++) {
 			if (*p == '/') {
-				error( "%s:%d: flattened hierarchy delimiter cannot contain the canonical delimiter '/'\n", cfg->file, cfg->line );
+				conf_error( cfg, "flattened hierarchy delimiter cannot contain the canonical delimiter '/'\n" );
 				cfg->err = 1;
 				return;
 			}
 		}
 		store->flat_delim = nfstrdup( cfg->val );
 	} else {
-		error( "%s:%d: keyword '%s' is not recognized in %s sections\n", cfg->file, cfg->line, cfg->cmd, type );
+		conf_error( cfg, "keyword '%s' is not recognized in %s sections\n", cfg->cmd, type );
 		cfg->rest = NULL;
 		cfg->err = 1;
 	}
diff --git a/src/drv_imap.c b/src/drv_imap.c
index ad95e3d..4e849bf 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -3782,7 +3782,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 		} else if (!strcasecmp( "Port", cfg->cmd )) {
 			int port = parse_int( cfg );
 			if ((unsigned)port > 0xffff) {
-				error( "%s:%d: Invalid port number\n", cfg->file, cfg->line );
+				conf_error( cfg, "Invalid port number\n" );
 				cfg->err = 1;
 			} else {
 				server->sconf.port = (ushort)port;
@@ -3791,7 +3791,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 			server->sconf.timeout = parse_int( cfg ) * 1000;
 		} else if (!strcasecmp( "PipelineDepth", cfg->cmd )) {
 			if ((server->max_in_progress = parse_int( cfg )) < 1) {
-				error( "%s:%d: PipelineDepth must be at least 1\n", cfg->file, cfg->line );
+				conf_error( cfg, "PipelineDepth must be at least 1\n" );
 				cfg->err = 1;
 			}
 		} else if (!strcasecmp( "DisableExtension", cfg->cmd ) ||
@@ -3804,7 +3804,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 						goto gotcap;
 					}
 				}
-				error( "%s:%d: Unrecognized IMAP extension '%s'\n", cfg->file, cfg->line, arg );
+				conf_error( cfg, "Unrecognized IMAP extension '%s'\n", arg );
 				cfg->err = 1;
 			  gotcap: ;
 			} while ((arg = get_arg( cfg, ARG_OPTIONAL, NULL )));
@@ -3812,8 +3812,8 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 		} else if (!strcasecmp( "CertificateFile", cfg->cmd )) {
 			server->sconf.cert_file = expand_strdup( cfg->val, cfg );
 			if (access( server->sconf.cert_file, R_OK )) {
-				sys_error( "%s:%d: CertificateFile '%s'",
-				           cfg->file, cfg->line, server->sconf.cert_file );
+				conf_sys_error( cfg, "CertificateFile '%s'",
+				                server->sconf.cert_file );
 				cfg->err = 1;
 			}
 		} else if (!strcasecmp( "SystemCertificates", cfg->cmd )) {
@@ -3821,15 +3821,15 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 		} else if (!strcasecmp( "ClientCertificate", cfg->cmd )) {
 			server->sconf.client_certfile = expand_strdup( cfg->val, cfg );
 			if (access( server->sconf.client_certfile, R_OK )) {
-				sys_error( "%s:%d: ClientCertificate '%s'",
-				           cfg->file, cfg->line, server->sconf.client_certfile );
+				conf_sys_error( cfg, "ClientCertificate '%s'",
+				                server->sconf.client_certfile );
 				cfg->err = 1;
 			}
 		} else if (!strcasecmp( "ClientKey", cfg->cmd )) {
 			server->sconf.client_keyfile = expand_strdup( cfg->val, cfg );
 			if (access( server->sconf.client_keyfile, R_OK )) {
-				sys_error( "%s:%d: ClientKey '%s'",
-				           cfg->file, cfg->line, server->sconf.client_keyfile );
+				conf_sys_error( cfg, "ClientKey '%s'",
+				                server->sconf.client_keyfile );
 				cfg->err = 1;
 			}
 		} else if (!strcasecmp( "CipherString", cfg->cmd )) {
@@ -3843,7 +3843,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 				} else if (*arg == '-') {
 					and_mask = ~0;
 				} else {
-					error( "%s:%d: TLSVersions arguments must start with +/-\n", cfg->file, cfg->line );
+					conf_error( cfg, "TLSVersions arguments must start with +/-\n" );
 					cfg->err = 1;
 					continue;
 				}
@@ -3857,7 +3857,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 				} else if (!strcmp( "1.3", arg )) {
 					val = TLSv1_3;
 				} else {
-					error( "%s:%d: Unrecognized TLS version '%s'\n", cfg->file, cfg->line, arg );
+					conf_error( cfg, "Unrecognized TLS version '%s'\n", arg );
 					cfg->err = 1;
 					continue;
 				}
@@ -3888,7 +3888,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 				} else if (!strcasecmp( "TLSv1.3", arg )) {
 					server->sconf.ssl_versions |= TLSv1_3;
 				} else {
-					error( "%s:%d: Unrecognized SSL version\n", cfg->file, cfg->line );
+					conf_error( cfg, "Unrecognized SSL version\n" );
 					cfg->err = 1;
 				}
 			} while ((arg = get_arg( cfg, ARG_OPTIONAL, NULL )));
@@ -3927,7 +3927,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 				cfg->err = 1;
 #endif
 			} else {
-				error( "%s:%d: Invalid TLS type\n", cfg->file, cfg->line );
+				conf_error( cfg, "Invalid TLS type\n" );
 				cfg->err = 1;
 			}
 		} else if (!strcasecmp( "AuthMech", cfg->cmd ) ||
@@ -3946,7 +3946,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 					if (srv->name && !strcmp( srv->name, cfg->val ))
 						goto gotsrv;
 				store->server = (void *)~0;
-				error( "%s:%d: unknown IMAP account '%s'\n", cfg->file, cfg->line, cfg->val );
+				conf_error( cfg, "unknown IMAP account '%s'\n", cfg->val );
 				cfg->err = 1;
 				continue;
 			  gotsrv:
@@ -3959,7 +3959,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 				store->path = nfstrdup( cfg->val );
 			} else if (!strcasecmp( "PathDelimiter", cfg->cmd )) {
 				if (strlen( cfg->val ) != 1) {
-					error( "%s:%d: Path delimiter must be exactly one character long\n", cfg->file, cfg->line );
+					conf_error( cfg, "Path delimiter must be exactly one character long\n" );
 					cfg->err = 1;
 					continue;
 				}
@@ -3969,8 +3969,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 			}
 			continue;
 		} else {
-			error( "%s:%d: keyword '%s' is not recognized in IMAPAccount sections\n",
-			       cfg->file, cfg->line, cfg->cmd );
+			conf_error( cfg, "keyword '%s' is not recognized in IMAPAccount sections\n", cfg->cmd );
 			cfg->rest = NULL;
 			cfg->err = 1;
 			continue;
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index cdffc32..683ccaa 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -1899,13 +1899,13 @@ maildir_parse_store( conffile_t *cfg, store_conf_t **storep )
 #endif /* USE_DB */
 		} else if (!strcasecmp( "InfoDelimiter", cfg->cmd )) {
 			if (strlen( cfg->val ) != 1) {
-				error( "%s:%d: Info delimiter must be exactly one character long\n", cfg->file, cfg->line );
+				conf_error( cfg, "Info delimiter must be exactly one character long\n" );
 				cfg->err = 1;
 				continue;
 			}
 			store->info_delimiter = cfg->val[0];
 			if (!ispunct( store->info_delimiter )) {
-				error( "%s:%d: Info delimiter must be a punctuation character\n", cfg->file, cfg->line );
+				conf_error( cfg, "Info delimiter must be a punctuation character\n" );
 				cfg->err = 1;
 				continue;
 			}
@@ -1917,7 +1917,7 @@ maildir_parse_store( conffile_t *cfg, store_conf_t **storep )
 			} else if (!strcasecmp( "Legacy", cfg->val )) {
 				store->sub_style = SUB_LEGACY;
 			} else {
-				error( "%s:%d: Unrecognized SubFolders style\n", cfg->file, cfg->line );
+				conf_error( cfg, "Unrecognized SubFolders style\n" );
 				cfg->err = 1;
 			}
 		} else {
-- 
2.41.0

_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to