> that depends on whose perspective you're assuming here.
> i'm likely not going to get it done anytime soon. pushing patches on me
> prompts me into action, so it's good for the project (not so much for my
> other projects, but the trade-off isn't that bad, as i'm actually much
> more efficient at reviewing than hacking myself).
> so if you think it would be a good use of *your* time, then go ahead.
After some somewhat more synchronous communication, it might be. This
project has been a nice refresher course on C.
> i implied that you need to do that anyway to handle things properly.
> also note that you'd save the duplicated check for the command.
>
> but looking at it again, duplication probably isn't even necessary: you
> can factor out check_excess_tokens() and make it also return a value.
I hope this is what you meant.
> the first patch is now Perfect (TM), so no need to re-send it.
Nice! Progress.
On the subject of more things I could do, is there a way to reproduce
the 2 regressions? I am not familiar with IMAP, but do know how to fix
a regression. I'm not in any hurry, and do not want to promise
anything. But I'd like to take a look.
Cheers, Michiel
>From 8f4c551449e90f80cdbf31fd6a0b207e9802c3e7 Mon Sep 17 00:00:00 2001
From: Michiel van den Heuvel <michielvdnheu...@gmail.com>
Date: Thu, 17 Aug 2023 20:25:51 +0200
Subject: [PATCH] Add IncludeCmd directive to config parser
---
src/config.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++----
src/config.h | 3 ++
src/mbsync.1 | 8 +++++
3 files changed, 93 insertions(+), 6 deletions(-)
diff --git a/src/config.c b/src/config.c
index ac90c25..a7476a9 100644
--- a/src/config.c
+++ b/src/config.c
@@ -61,12 +61,21 @@ expand_strdup( const char *s, const conffile_t *cfile )
}
}
+static void
+conf_print_loc( const conffile_t *cfile )
+{
+ if (cfile->eval_fp)
+ fprintf( stderr, "%s:%d:included:%d: ", cfile->file, cfile->line, cfile->eval_line );
+ else
+ fprintf( stderr, "%s:%d: ", cfile->file, cfile->line );
+}
+
void
conf_error( conffile_t *cfile, const char *fmt, ... )
{
va_list va;
- fprintf( stderr, "%s:%d: ", cfile->file, cfile->line );
+ conf_print_loc( cfile );
va_start( va, fmt );
vfprintf( stderr, fmt, va );
va_end( va );
@@ -79,7 +88,7 @@ conf_sys_error( conffile_t *cfile, const char *fmt, ... )
va_list va;
int errno_bak = errno;
- fprintf( stderr, "%s:%d: ", cfile->file, cfile->line );
+ conf_print_loc( cfile );
errno = errno_bak;
va_start( va, fmt );
vsys_error( fmt, va );
@@ -318,17 +327,72 @@ getopt_helper( conffile_t *cfile, int *cops, channel_conf_t *conf )
return 1;
}
+static void
+eval_cmd_popen( conffile_t *cfile, const char *cmd )
+{
+ if (!(cfile->eval_fp = popen( cmd, "r" ))) {
+ sys_error( "popen" );
+ cfile->err = 1;
+ return;
+ }
+ cfile->eval_line = 0;
+ cfile->eval_command = nfstrdup( cmd );
+}
+
+static void
+eval_cmd_pclose( conffile_t *cfile )
+{
+ int ret;
+
+ if ((ret = pclose( cfile->eval_fp ))) {
+ if (ret < 0) {
+ sys_error( "pclose" );
+ cfile->err = 1;
+ } else if (WIFSIGNALED( ret )) {
+ conf_error( cfile, "command \"%s\" crashed with signal %d\n",
+ cfile->eval_command, WTERMSIG( ret ) );
+ } else {
+ conf_error( cfile, "command \"%s\" exited with status %d\n",
+ cfile->eval_command, WEXITSTATUS( ret ) );
+ }
+ }
+ free( cfile->eval_command );
+ cfile->eval_fp = NULL;
+ cfile->eval_command = NULL;
+}
+
+static int
+read_cline( conffile_t *cfile )
+{
+ if (cfile->eval_fp) {
+ cfile->eval_line++;
+ if ((cfile->rest = fgets( cfile->buf, cfile->bufl, cfile->eval_fp )))
+ return 1;
+ eval_cmd_pclose( cfile );
+ }
+ cfile->line++;
+ return (cfile->rest = fgets( cfile->buf, cfile->bufl, cfile->fp )) != NULL;
+}
+
+static char *
+check_excess_tokens( conffile_t *cfile )
+{
+ char *arg = NULL;
+
+ if (cfile->rest)
+ arg = get_arg( cfile, ARG_OPTIONAL, NULL );
+ return arg;
+}
+
int
getcline( conffile_t *cfile )
{
char *arg;
int comment;
- if (cfile->rest && (arg = get_arg( cfile, ARG_OPTIONAL, NULL )))
+ if ((arg = check_excess_tokens( cfile )))
conf_error( cfile, "excess token '%s'\n", arg );
- while (fgets( cfile->buf, cfile->bufl, cfile->fp )) {
- cfile->line++;
- cfile->rest = cfile->buf;
+ while (read_cline( cfile )) {
if (!(cfile->cmd = get_arg( cfile, ARG_OPTIONAL, &comment ))) {
if (comment)
continue;
@@ -336,6 +400,16 @@ getcline( conffile_t *cfile )
}
if (!(cfile->val = get_arg( cfile, ARG_REQUIRED, NULL )))
continue;
+ if (!strcasecmp( cfile->cmd, "IncludeCmd" )) {
+ if (cfile->eval_fp)
+ conf_error( cfile, "nested IncludeCmd\n" );
+ else if ((arg = check_excess_tokens( cfile )))
+ conf_error( cfile, "excess token '%s', not executing "
+ "potentially malformed command\n", arg );
+ else
+ eval_cmd_popen( cfile, cfile->val );
+ continue;
+ }
return 1;
}
return 0;
@@ -488,6 +562,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;
@@ -495,6 +570,7 @@ load_config( const char *where )
cfile.ms_warn = 0;
cfile.renew_warn = 0;
cfile.delete_warn = 0;
+ cfile.cmd = NULL;
cfile.rest = NULL;
gcops = 0;
diff --git a/src/config.h b/src/config.h
index 2177fb4..c1642ef 100644
--- a/src/config.h
+++ b/src/config.h
@@ -12,10 +12,13 @@
typedef struct {
const char *file;
+ char *eval_command;
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..1a9e70e 100644
--- a/src/mbsync.1
+++ b/src/mbsync.1
@@ -786,6 +786,14 @@ absolute limit, as even a single message can consume more memory than
this.
(Default: \fI10M\fR)
.
+.SS Dynamic Configuration
+.TP
+\fBIncludeCmd\fR \fIcommand\fR
+Specify a shell command to obtain configuration file content from.
+This keyword can appear anywhere. The command's output will be
+interpreted as if it appeared inline; it can range from nothing at all
+to multiple sections.
+.
.SH CONSOLE OUTPUT
If \fBmbsync\fR's output is connected to a console, it will print progress
counters by default. The output will look like this:
--
2.42.0
_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel