summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/argparse.c106
-rw-r--r--src/gpgrt-int.h3
-rw-r--r--src/sysutils.c22
-rw-r--r--tests/etc/t-argparse.conf30
4 files changed, 125 insertions, 36 deletions
diff --git a/src/argparse.c b/src/argparse.c
index 6b3488a..0c5ec58 100644
--- a/src/argparse.c
+++ b/src/argparse.c
@@ -109,9 +109,14 @@ struct _gpgrt_argparse_internal_s
unsigned int explicit_ignore:1; /* Option has explicitly been set
* to ignore or unignore. */
unsigned int ignore_all_seen:1; /* [ignore-all] has been seen. */
+ unsigned int user_seen:1; /* A [user] has been seen. */
+ unsigned int user_wildcard:1; /* A [user *] has been seen. */
+ unsigned int user_any_active:1; /* Any user section was active. */
+ unsigned int user_active:1; /* User section active. */
unsigned int explicit_confopt:1; /* A conffile option has been given. */
char *explicit_conffile; /* Malloced name of an explicit
* conffile. */
+ char *username; /* Malloced current user name. */
unsigned int opt_flags; /* Current option flags. */
enum argparser_states state; /* State of the gpgrt_argparser. */
const char *last;
@@ -256,6 +261,7 @@ deinitialize (gpgrt_argparse_t *arg)
{
if (arg->internal)
{
+ xfree (arg->internal->username);
xfree (arg->internal->explicit_conffile);
xfree (arg->internal->opts);
xfree (arg->internal);
@@ -306,6 +312,10 @@ initialize (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, estream_t fp)
arg->internal->inarg = 0;
arg->internal->stopped = 0;
arg->internal->in_sysconf = 0;
+ arg->internal->user_seen = 0;
+ arg->internal->user_wildcard = 0;
+ arg->internal->user_any_active = 0;
+ arg->internal->user_active = 0;
arg->internal->mark_forced = 0;
arg->internal->mark_ignore = 0;
arg->internal->explicit_ignore = 0;
@@ -652,19 +662,49 @@ ignore_invalid_option_clear (gpgrt_argparse_t *arg)
}
-/* Implementation of the "user" and "group" commands. ARG is the
- * context. A value of 0 for ALTERNATE requests the "user" command, a
- * value of "1" the "group" command. ARGS is a non-empty string which
- * this function is allowed to modify. */
+/* Implementation of the "user" command. ARG is the context. ARGS is
+ * a non-empty string which this function is allowed to modify. */
static int
handle_meta_user (gpgrt_argparse_t *arg, unsigned int alternate, char *args)
{
- (void)args;
+ (void)alternate;
+
+ if (!arg->internal->username)
+ {
+ arg->internal->username = _gpgrt_getusername ();
+ if (!arg->internal->username)
+ {
+ _gpgrt_log_error ("%s:%u: error getting current user's name: %s\n",
+ arg->internal->confname, arg->lineno,
+ _gpg_strerror (gpg_error_from_syserror ()));
+ /* Not necessary the correct error code but given that we
+ * either have a malloc error or some internal system error,
+ * it is the best we can do. */
+ return ARGPARSE_PERMISSION_ERROR;
+ }
+ }
- if (arg->internal->verbose)
- _gpgrt_log_info ("%s:%u: meta command %s is not yet supported\n",
- arg->internal->confname, arg->lineno,
- alternate? "group":"user");
+
+ arg->internal->user_seen = 1;
+ if (*args == '*' && !args[1])
+ {
+ arg->internal->user_wildcard = 1;
+ arg->internal->user_active = !arg->internal->user_any_active;
+ }
+ else if (arg->internal->user_wildcard)
+ {
+ /* All other user statements are ignored after a wildcard. */
+ arg->internal->user_active = 0;
+ }
+ else if (!strcasecmp (args, arg->internal->username))
+ {
+ arg->internal->user_any_active = 1;
+ arg->internal->user_active = 1;
+ }
+ else
+ {
+ arg->internal->user_active = 0;
+ }
return 0;
}
@@ -751,24 +791,26 @@ handle_metacmd (gpgrt_argparse_t *arg, char *keyword)
unsigned short alternate; /* Use alternate version of the command. */
unsigned short needarg:1; /* Command requires an argument. */
unsigned short always:1; /* Command allowed in all conf files. */
+ unsigned short noskip:1; /* Even done in non-active [user] mode. */
int (*func)(gpgrt_argparse_t *arg,
unsigned int alternate, char *args); /*handler*/
} cmds[] =
- {{ "user", 0, 1, 0, handle_meta_user },
- { "group", 1, 1, 0, handle_meta_user },
- { "force", 0, 0, 0, handle_meta_force },
- { "+force", 0, 0, 0, handle_meta_force },
- { "-force", 1, 0, 0, handle_meta_force },
- { "ignore", 0, 0, 0, handle_meta_ignore },
- { "+ignore", 0, 0, 0, handle_meta_ignore },
- { "-ignore", 1, 0, 0, handle_meta_ignore },
- { "ignore-all", 2, 0, 0, handle_meta_ignore },
- { "+ignore-all", 2, 0, 0, handle_meta_ignore },
- { "verbose", 0, 0, 1, handle_meta_verbose },
- { "+verbose", 0, 0, 1, handle_meta_verbose },
- { "-verbose", 1, 0, 1, handle_meta_verbose },
- { "echo", 0, 1, 1, handle_meta_echo },
- { "-echo", 1, 1, 1, handle_meta_echo }
+ {{ "user", 0, 1, 0, 1, handle_meta_user },
+ { "force", 0, 0, 0, 0, handle_meta_force },
+ { "+force", 0, 0, 0, 0, handle_meta_force },
+ { "-force", 1, 0, 0, 0, handle_meta_force },
+ { "ignore", 0, 0, 0, 0, handle_meta_ignore },
+ { "+ignore", 0, 0, 0, 0, handle_meta_ignore },
+ { "-ignore", 1, 0, 0, 0, handle_meta_ignore },
+ { "ignore-all", 2, 0, 0, 0, handle_meta_ignore },
+ { "+ignore-all", 2, 0, 0, 0, handle_meta_ignore },
+ { "verbose", 0, 0, 1, 1, handle_meta_verbose },
+ { "+verbose", 0, 0, 1, 1, handle_meta_verbose },
+ { "-verbose", 1, 0, 1, 1, handle_meta_verbose },
+ { "echo", 0, 1, 1, 1, handle_meta_echo },
+ { "-echo", 1, 1, 1, 1, handle_meta_echo },
+ { "info", 0, 1, 1, 0, handle_meta_echo },
+ { "-info", 1, 1, 1, 0, handle_meta_echo }
};
char *rest;
int i;
@@ -793,6 +835,12 @@ handle_metacmd (gpgrt_argparse_t *arg, char *keyword)
if (!arg->internal->in_sysconf && !cmds[i].always)
return ARGPARSE_UNEXPECTED_META;
+ if (!cmds[i].noskip
+ && arg->internal->in_sysconf
+ && arg->internal->user_seen
+ && !arg->internal->user_active)
+ return 0; /* Skip this meta command. */
+
return cmds[i].func (arg, cmds[i].alternate, rest);
}
@@ -944,6 +992,15 @@ _gpgrt_argparse (estream_t fp, gpgrt_argparse_t *arg, gpgrt_opt_t *opts_orig)
/* Known option but need to scan for args. */
state = Awaitarg;
}
+ else if (arg->internal->in_sysconf
+ && arg->internal->user_seen
+ && !arg->internal->user_active)
+ {
+ /* We are in a [user] meta command and it is not active.
+ * Skip the command. */
+ state = state == Akeyword_eol? Ainit : Acomment;
+ i = 0;
+ }
else if ((opts[idx].flags & ARGPARSE_OPT_IGNORE))
{
/* Known option is configured to be ignored. Start from
@@ -1384,6 +1441,7 @@ finish_read_sys (gpgrt_argparse_t *arg)
/* Reset all flags which pertain only to sysconf files. */
arg->internal->in_sysconf = 0;
+ arg->internal->user_active = 0;
arg->internal->mark_forced = 0;
arg->internal->mark_ignore = 0;
arg->internal->explicit_ignore = 0;
diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h
index cc22004..629f527 100644
--- a/src/gpgrt-int.h
+++ b/src/gpgrt-int.h
@@ -795,6 +795,9 @@ char *_gpgrt_getcwd (void);
/* Return the home directory of user NAME. */
char *_gpgrt_getpwdir (const char *name);
+/* Return the account name of the current user. */
+char *_gpgrt_getusername (void);
+
/* Expand and concat file name parts. */
char *_gpgrt_vfnameconcat (int want_abs, const char *first_part,
va_list arg_ptr);
diff --git a/src/sysutils.c b/src/sysutils.c
index 6bdd76f..112c8b5 100644
--- a/src/sysutils.c
+++ b/src/sysutils.c
@@ -343,7 +343,7 @@ _gpgrt_getcwd (void)
/* Get the standard home directory for user NAME. If NAME is NULL the
- * directory for the current user is retruned. Caller must release
+ * directory for the current user is returned. Caller must release
* the returned string. */
char *
_gpgrt_getpwdir (const char *name)
@@ -376,3 +376,23 @@ _gpgrt_getpwdir (const char *name)
#endif /*HAVE_PWD_H*/
return result;
}
+
+
+/* Return a malloced copy of the current user's account name; this may
+ * return NULL on memory failure. */
+char *
+_gpgrt_getusername (void)
+{
+ char *result = NULL;
+#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
+ struct passwd *pwd;
+
+ pwd = getpwuid (getuid());
+ if (pwd)
+ {
+ result = _gpgrt_strdup (pwd->pw_name);
+ }
+
+#endif /*HAVE_PWD_H*/
+ return result;
+}
diff --git a/tests/etc/t-argparse.conf b/tests/etc/t-argparse.conf
index 90b9935..4562c7c 100644
--- a/tests/etc/t-argparse.conf
+++ b/tests/etc/t-argparse.conf
@@ -3,11 +3,21 @@
# Options applied to all user's config files
#verbose
+# The meta comman decho simply prints the argument. With a hash
+# prefix it does not prepend the file name and line number. For
+# future compatibility do not use doallar signs.
[-echo Begin global config]
[verbose]
-[group :staff]
-# These option are applied to all users of the group staff up until
-# the next [group] or [user] statement.
+
+[user joy]
+# All the following options are applied only if the current user's
+# account name is "joy" (case-insensitive). This ends with the next
+# user statement. This does not affect "echo" and "verbose".
+
+# info is an alias for echo but only executed if a user secion is active.
+# For future compatibility do not use percent or dollar signs.
+[-info In user Joy]
+
[-verbose]
[+force]
# All following option are forced and thus ignored when set in user
@@ -37,8 +47,9 @@ not-my-option
#no-verbose
-[user john ]
-# Options for user john
+# Options applied only for user joy end here.
+[user wk ]
+[-info Options applied only for user wk follow]
# Change the immutable attribute back to mutable.
[-force]
@@ -47,13 +58,10 @@ not-my-option
# Default key for user john
my-option 42
-# Parsing stops for user WK here.
-
-[group * ]
-# Options for all group which have no specific group sections above
-
+# Options applied only for user joy end here.
[user *]
-# Options for all users which have no specific user sections above
+[-info All the following options are applied only if the]
+[-info current user has no specific section above.]
# The default algorithm for new keys is set to this.
a-long-option