---
src/config.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++------
src/config.h | 2 +-
src/mbsync.1 | 6 +++--
3 files changed, 61 insertions(+), 10 deletions(-)
diff --git a/src/config.c b/src/config.c
index 456bd47..0cc0d31 100644
--- a/src/config.c
+++ b/src/config.c
@@ -25,11 +25,57 @@ char FieldDelimiter = ':';
DEF_BIT_FORMATTER_FUNCTION(ops, OP)
char *
-expand_strdup( const char *s, const conffile_t *cfile )
+expand_env_strdup( const char *s, conffile_t *cfile )
+{
+ const char *e, *val;
+ char path[_POSIX_PATH_MAX];
+ char *r = path;
+ while (*s) {
+ if (*s == '$') {
+ s++;
+ e = s;
+ if (isalpha( *s ) || *s == '_') {
+ while (*e && (isalnum( *e ) || *e == '_')) {
+ e++;
+ }
+ val = getenv( nfstrndup( s, e - s ) );
+ } else if (*s == '{') {
+ s++;
+ e++;
+ while (*e && *e != '}') {
+ e++;
+ }
+ if (!*e || *e != '}') {
+ error( "%s:%d: unterminated variable
expansion\n", cfile->file, cfile->line );
+ cfile->err = 1;
+ }
+ e++;
+ val = getenv( nfstrndup( s, e - s - 1 ) );
+ } else {
+ if (*s == '$')
+ e++;
+ val = "$";
+ }
+ r += nfsnprintf( r, sizeof(path) - (r - path), "%s",
val );
+ s = e;
+ } else {
+ *r = *s;
+ r++;
+ s++;
+ }
+ if (r >= path + sizeof(path))
+ oob();
+ }
+ *r = 0;
+ return nfstrdup(path);
+}
+
+char *
+expand_strdup( const char *s, conffile_t *cfile )
{
struct passwd *pw;
const char *p, *q;
- char *r;
+ char *r, *t;
if (*s == '~') {
s++;
@@ -52,12 +98,15 @@ expand_strdup( const char *s, const conffile_t *cfile )
q = pw->pw_dir;
}
nfasprintf( &r, "%s%s", q, p ? p : "" );
- return r;
- } else if (*s != '/') {
- nfasprintf( &r, "%.*s%s", cfile->path_len, cfile->file, s );
- return r;
+ return expand_env_strdup( r, cfile );
} else {
- return nfstrdup( s );
+ r = expand_env_strdup( s, cfile );
+ if (*r != '/') {
+ nfasprintf( &t, "%.*s%s", cfile->path_len, cfile->file,
r );
+ free( r );
+ return t;
+ }
+ return r;
}
}
diff --git a/src/config.h b/src/config.h
index 0762b58..95c35aa 100644
--- a/src/config.h
+++ b/src/config.h
@@ -27,7 +27,7 @@ extern char FieldDelimiter;
#define ARG_OPTIONAL 0
#define ARG_REQUIRED 1
-char *expand_strdup( const char *s, const conffile_t *cfile );
+char *expand_strdup( const char *s, conffile_t *cfile );
char *get_arg( conffile_t *cfile, int required, int *comment );
diff --git a/src/mbsync.1 b/src/mbsync.1
index 939c8c5..2161eef 100644
--- a/src/mbsync.1
+++ b/src/mbsync.1
@@ -126,8 +126,10 @@ Configuration items are keywords followed by one or more
arguments;
arguments containing spaces must be enclosed in double quotes (\fB"\fR),
and literal double quotes and backslashes (\fB\\\fR) must be backslash-escaped.
All keywords (including those used as arguments) are case-insensitive.
-Bash-like home directory expansion using the tilde (\fB~\fR) is supported
-in all options which represent local paths.
+Bash-like home directory expansion using the tilde (\fB~\fR), and variable
+expansion using both \fB$VAR\fR and \fB${VAR}\fR is supported in all
+options which represent local paths. A literal \fB$\fR is represented
+by doubling it.
The reference point for relative local paths is the configuration file's
containing directory.
There are a few global options, the others apply to particular sections.
--
2.41.0
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel