common: Fix the "ignore" meta command in argparse.c

* src/argparse.c (gnupg_argparse): Factor some code out to ...
(prepare_arg_return): new.
(gnupg_argparse): No missing arg error in ignore sections.
* common/sysutils.c: Include pwd.h.
(gnupg_getusername): New.
--

Options in an [ignore] section do not anymore lead to an error if an
argument is missing.  However, if the option is also in a force
section the error is thrown.

This is a port of the fix from libgpg-error.  Also fixes the
username fixme.
This commit is contained in:
Werner Koch 2020-12-21 17:23:52 +01:00
parent 8a2e5025eb
commit 09dc59f6d4
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
3 changed files with 123 additions and 37 deletions

View File

@ -722,7 +722,7 @@ assure_username (gnupg_argparse_t *arg)
{ {
if (!arg->internal->username) if (!arg->internal->username)
{ {
arg->internal->username = "dummyuser"; /*FIXMEgpgrt_getusername ();*/ arg->internal->username = gnupg_getusername ();
if (!arg->internal->username) if (!arg->internal->username)
{ {
log_error ("%s:%u: error getting current user's name: %s\n", log_error ("%s:%u: error getting current user's name: %s\n",
@ -963,6 +963,34 @@ handle_metacmd (gnupg_argparse_t *arg, char *keyword)
} }
/* Helper for gnupg_argparse. */
static void
prepare_arg_return (gnupg_argparse_t *arg, opttable_t *opts,
int idx, int in_alias, int set_ignore)
{
/* No argument found at the end of the line. */
if (in_alias)
arg->r_opt = ARGPARSE_MISSING_ARG;
else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
arg->r_type = ARGPARSE_TYPE_NONE; /* Does not take an arg. */
else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL))
arg->r_type = ARGPARSE_TYPE_NONE; /* No optional argument. */
else if (!(opts[idx].ignore && !opts[idx].forced) && !set_ignore)
arg->r_opt = ARGPARSE_MISSING_ARG;
/* If the caller wants us to return the attributes or
* ignored options, or these flags in. */
if ((arg->flags & ARGPARSE_FLAG_WITHATTR))
{
if (opts[idx].ignore)
arg->r_type |= ARGPARSE_ATTR_IGNORE;
if (opts[idx].forced)
arg->r_type |= ARGPARSE_ATTR_FORCE;
if (set_ignore)
arg->r_type |= ARGPARSE_OPT_IGNORE;
}
}
/**************** /****************
* Get options from a file. * Get options from a file.
* Lines starting with '#' are comment lines. * Lines starting with '#' are comment lines.
@ -1008,6 +1036,7 @@ gnupg_argparse (estream_t fp, gnupg_argparse_t *arg, gnupg_opt_t *opts_orig)
char *buffer = NULL; char *buffer = NULL;
size_t buflen = 0; size_t buflen = 0;
int in_alias=0; int in_alias=0;
int set_ignore = 0;
int unread_buf[3]; /* We use an int so that we can store EOF. */ int unread_buf[3]; /* We use an int so that we can store EOF. */
int unread_buf_count = 0; int unread_buf_count = 0;
@ -1105,12 +1134,8 @@ gnupg_argparse (estream_t fp, gnupg_argparse_t *arg, gnupg_opt_t *opts_orig)
goto leave; goto leave;
} }
} }
else if (state == Akeyword_spc) else if (state != Akeyword_spc
{ && arg->internal->in_sysconf
/* Known option but need to scan for args. */
state = Awaitarg;
}
else if (arg->internal->in_sysconf
&& arg->internal->user_seen && arg->internal->user_seen
&& !arg->internal->user_active) && !arg->internal->user_active)
{ {
@ -1119,7 +1144,8 @@ gnupg_argparse (estream_t fp, gnupg_argparse_t *arg, gnupg_opt_t *opts_orig)
state = state == Akeyword_eol? Ainit : Acomment; state = state == Akeyword_eol? Ainit : Acomment;
i = 0; i = 0;
} }
else if ((opts[idx].flags & ARGPARSE_OPT_IGNORE)) else if (state != Akeyword_spc
&& (opts[idx].flags & ARGPARSE_OPT_IGNORE))
{ {
/* Known option is configured to be ignored. Start from /* Known option is configured to be ignored. Start from
* scratch (new line) or process like a comment. */ * scratch (new line) or process like a comment. */
@ -1128,7 +1154,7 @@ gnupg_argparse (estream_t fp, gnupg_argparse_t *arg, gnupg_opt_t *opts_orig)
} }
else /* Known option */ else /* Known option */
{ {
int set_ignore = 0; set_ignore = 0;
if (arg->internal->in_sysconf) if (arg->internal->in_sysconf)
{ {
@ -1139,6 +1165,23 @@ gnupg_argparse (estream_t fp, gnupg_argparse_t *arg, gnupg_opt_t *opts_orig)
opts[idx].ignore = 1; opts[idx].ignore = 1;
if (arg->internal->explicit_ignore) if (arg->internal->explicit_ignore)
opts[idx].explicit_ignore = 1; opts[idx].explicit_ignore = 1;
if (opts[idx].ignore && !opts[idx].forced)
{
if (arg->internal->verbose)
log_info ("%s:%u: ignoring option \"--%s\"\n",
arg->internal->confname,
arg->lineno,
opts[idx].long_opt);
if ((arg->flags & ARGPARSE_FLAG_WITHATTR))
set_ignore = 1;
else
{
state = state == Akeyword_eol? Ainit : Acomment;
i = 0;
goto nextstate; /* Ignore this one. */
}
}
} }
else /* Non-sysconf file */ else /* Non-sysconf file */
{ /* Act upon the forced and ignored attributes. */ { /* Act upon the forced and ignored attributes. */
@ -1156,34 +1199,34 @@ gnupg_argparse (estream_t fp, gnupg_argparse_t *arg, gnupg_opt_t *opts_orig)
set_ignore = 1; set_ignore = 1;
else else
{ {
state = Ainit; state = state == Akeyword_eol? Ainit : Acomment;
i = 0; i = 0;
goto nextstate; /* Ignore this one. */ goto nextstate; /* Ignore this one. */
} }
} }
} }
arg->r_opt = opts[idx].short_opt; if (state == Akeyword_spc)
if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
arg->r_type = ARGPARSE_TYPE_NONE; /* Does not take an arg. */
else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL) )
arg->r_type = ARGPARSE_TYPE_NONE; /* Arg is optional. */
else
arg->r_opt = ARGPARSE_MISSING_ARG;
/* If the caller wants us to return the attributes or
* ignored options, or the flags in. */
if ((arg->flags & ARGPARSE_FLAG_WITHATTR))
{ {
if (opts[idx].ignore) /* If we shall ignore but not set the option we skip
arg->r_type |= ARGPARSE_ATTR_IGNORE; * the argument. Otherwise we would need to use a
if (opts[idx].forced) * made-up but not used args in the conf file. */
arg->r_type |= ARGPARSE_ATTR_FORCE; if (set_ignore || (opts[idx].ignore && !opts[idx].forced))
if (set_ignore) {
arg->r_type |= ARGPARSE_OPT_IGNORE; prepare_arg_return (arg, opts, idx, 0, set_ignore);
set_ignore = 0;
state = Askipandleave;
}
else
state = Awaitarg;
}
else
{
prepare_arg_return (arg, opts, idx, 0, set_ignore);
set_ignore = 0;
goto leave;
} }
goto leave;
} }
} /* (end state Akeyword_eol/Akeyword_spc) */ } /* (end state Akeyword_eol/Akeyword_spc) */
else if (state == Ametacmd) else if (state == Ametacmd)
@ -1237,15 +1280,8 @@ gnupg_argparse (estream_t fp, gnupg_argparse_t *arg, gnupg_opt_t *opts_orig)
else if (state == Awaitarg) else if (state == Awaitarg)
{ {
/* No argument found at the end of the line. */ /* No argument found at the end of the line. */
if (in_alias) prepare_arg_return (arg, opts, idx, in_alias, set_ignore);
arg->r_opt = ARGPARSE_MISSING_ARG; set_ignore = 0;
else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
arg->r_type = ARGPARSE_TYPE_NONE; /* Does not take an arg. */
else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL))
arg->r_type = ARGPARSE_TYPE_NONE; /* No optional argument. */
else
arg->r_opt = ARGPARSE_MISSING_ARG;
goto leave; goto leave;
} }
else if (state == Acopyarg) else if (state == Acopyarg)

View File

@ -40,6 +40,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#ifdef HAVE_STAT #ifdef HAVE_STAT
@ -1741,3 +1744,49 @@ gnupg_fd_valid (int fd)
close (d); close (d);
return 1; return 1;
} }
/* Return a malloced copy of the current user's account name; this may
* return NULL on memory failure. Note that this should eventually be
* replaced by a gpgrt function. */
char *
gnupg_getusername (void)
{
char *result = NULL;
#ifdef HAVE_W32_SYSTEM
wchar_t wtmp[1];
wchar_t *wbuf;
DWORD wsize = 1;
GetUserNameW (wtmp, &wsize);
wbuf = xtrymalloc (wsize * sizeof *wbuf);
if (!wbuf)
{
gpg_err_set_errno (ENOMEM);
return NULL;
}
if (!GetUserNameW (wbuf, &wsize))
{
gpg_err_set_errno (EINVAL);
xfree (wbuf);
return NULL;
}
result= wchar_to_utf8 (wbuf);
xfree (wbuf);
#else /* !HAVE_W32_SYSTEM */
# if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
struct passwd *pwd;
pwd = getpwuid (getuid());
if (pwd)
result = xtrystrdup (pwd->pw_name);
# endif /*HAVE_PWD_H*/
#endif /* !HAVE_W32_SYSTEM */
return result;
}

View File

@ -98,6 +98,7 @@ gnupg_dirent_t gnupg_readdir (gnupg_dir_t gdir);
int gnupg_closedir (gnupg_dir_t gdir); int gnupg_closedir (gnupg_dir_t gdir);
char *gnupg_get_socket_name (int fd); char *gnupg_get_socket_name (int fd);
int gnupg_fd_valid (int fd); int gnupg_fd_valid (int fd);
char *gnupg_getusername (void);
gpg_error_t gnupg_inotify_watch_delete_self (int *r_fd, const char *fname); gpg_error_t gnupg_inotify_watch_delete_self (int *r_fd, const char *fname);
gpg_error_t gnupg_inotify_watch_socket (int *r_fd, const char *socket_name); gpg_error_t gnupg_inotify_watch_socket (int *r_fd, const char *socket_name);