diff --git a/common/argparse.c b/common/argparse.c index fff720c19..fb2bc6556 100644 --- a/common/argparse.c +++ b/common/argparse.c @@ -722,7 +722,7 @@ assure_username (gnupg_argparse_t *arg) { if (!arg->internal->username) { - arg->internal->username = "dummyuser"; /*FIXMEgpgrt_getusername ();*/ + arg->internal->username = gnupg_getusername (); if (!arg->internal->username) { 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. * 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; size_t buflen = 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_count = 0; @@ -1105,12 +1134,8 @@ gnupg_argparse (estream_t fp, gnupg_argparse_t *arg, gnupg_opt_t *opts_orig) goto leave; } } - else if (state == Akeyword_spc) - { - /* Known option but need to scan for args. */ - state = Awaitarg; - } - else if (arg->internal->in_sysconf + else if (state != Akeyword_spc + && arg->internal->in_sysconf && arg->internal->user_seen && !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; 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 * 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 */ { - int set_ignore = 0; + set_ignore = 0; 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; if (arg->internal->explicit_ignore) 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 */ { /* 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; else { - state = Ainit; + state = state == Akeyword_eol? Ainit : Acomment; i = 0; goto nextstate; /* Ignore this one. */ } } } - arg->r_opt = opts[idx].short_opt; - 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 (state == Akeyword_spc) { - 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; + /* If we shall ignore but not set the option we skip + * the argument. Otherwise we would need to use a + * made-up but not used args in the conf file. */ + if (set_ignore || (opts[idx].ignore && !opts[idx].forced)) + { + 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) */ 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) { /* 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 - arg->r_opt = ARGPARSE_MISSING_ARG; - + prepare_arg_return (arg, opts, idx, in_alias, set_ignore); + set_ignore = 0; goto leave; } else if (state == Acopyarg) diff --git a/common/sysutils.c b/common/sysutils.c index 520aa56e4..fa036b1d5 100644 --- a/common/sysutils.c +++ b/common/sysutils.c @@ -40,6 +40,9 @@ #include #include #include +#ifdef HAVE_PWD_H +# include +#endif #include #include #ifdef HAVE_STAT @@ -1741,3 +1744,49 @@ gnupg_fd_valid (int fd) close (d); 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; +} diff --git a/common/sysutils.h b/common/sysutils.h index 63c259b0d..c637370d5 100644 --- a/common/sysutils.h +++ b/common/sysutils.h @@ -98,6 +98,7 @@ gnupg_dirent_t gnupg_readdir (gnupg_dir_t gdir); int gnupg_closedir (gnupg_dir_t gdir); char *gnupg_get_socket_name (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_socket (int *r_fd, const char *socket_name);