[svn] GnuPG - r5064 - in trunk: . agent common doc g10 sm tools
svn author wk
cvs at cvs.gnupg.org
Tue Jul 7 12:02:43 CEST 2009
Author: wk
Date: 2009-07-07 12:02:41 +0200 (Tue, 07 Jul 2009)
New Revision: 5064
Added:
trunk/common/session-env.c
trunk/common/session-env.h
trunk/common/t-session-env.c
Modified:
trunk/NEWS
trunk/agent/ChangeLog
trunk/agent/agent.h
trunk/agent/call-pinentry.c
trunk/agent/command-ssh.c
trunk/agent/command.c
trunk/agent/gpg-agent.c
trunk/agent/protect-tool.c
trunk/common/ChangeLog
trunk/common/Makefile.am
trunk/common/asshelp.c
trunk/common/asshelp.h
trunk/common/get-passphrase.c
trunk/common/get-passphrase.h
trunk/common/t-exechelp.c
trunk/doc/gpgsm.texi
trunk/g10/ChangeLog
trunk/g10/call-agent.c
trunk/g10/gpg.c
trunk/g10/options.h
trunk/sm/ChangeLog
trunk/sm/call-agent.c
trunk/sm/gpgsm.c
trunk/sm/gpgsm.h
trunk/sm/misc.c
trunk/sm/server.c
trunk/tools/ChangeLog
trunk/tools/gpg-connect-agent.c
Log:
Reworked passing of envars to Pinentry.
[The diff below has been truncated]
Modified: trunk/agent/ChangeLog
===================================================================
--- trunk/agent/ChangeLog 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/agent/ChangeLog 2009-07-07 10:02:41 UTC (rev 5064)
@@ -1,3 +1,21 @@
+2009-07-06 Werner Koch <wk at g10code.com>
+
+ * agent.h: Include session-env.h.
+ (opt): Replace most of the startup_xxx fields by a session_env_t.
+ (struct server_control_s): Likewise.
+ * gpg-agent.c (main): Rewrite setting of the startup fields.
+ (handle_connections, main): Allocate SESSION_ENV.
+ (agent_init_default_ctrl, agent_deinit_default_ctrl): Change
+ accordingly.
+ * command.c (option_handler): Ditto.
+ (cmd_updatestartuptty): Change accordingly. Protect old values
+ from out of core failures.
+ * command-ssh.c (start_command_handler_ssh): Ditto.
+ (start_command_handler_ssh): Replace strdup by xtrystrdup.
+ * call-pinentry.c (atfork_cb): Pass new envrinmnet variables.
+ (start_pinentry): Use session_env stuff.
+ * protect-tool.c (main): Adjust call to gnupg_prepare_get_passphrase.
+
2009-06-24 Werner Koch <wk at g10code.com>
* genkey.c (agent_protect_and_store): Return RC and not 0.
Modified: trunk/common/ChangeLog
===================================================================
--- trunk/common/ChangeLog 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/common/ChangeLog 2009-07-07 10:02:41 UTC (rev 5064)
@@ -1,3 +1,20 @@
+2009-07-06 Werner Koch <wk at g10code.com>
+
+ * get-passphrase.c (struct agentargs): Add SESSION_ENV and remove
+ obsolete args.
+ (gnupg_prepare_get_passphrase): Ditto.
+
+ * session-env.c, session-env.h: New.
+ * t-session-env.c: New.
+ * Makefile.am (common_sources, module_tests): Add them.
+ * asshelp.h: Include "session-env.h"
+ * asshelp.c (send_one_option): Add arg PUTENV.
+ (send_pinentry_environment): Replace most args by SESSION_ENV and
+ rewrite fucntion.
+ (start_new_gpg_agent): Likewise.
+
+ * t-exechelp.c (test_close_all_fds): Remove debug code.
+
2009-07-01 Werner Koch <wk at g10code.com>
* sexputil.c (get_pk_algo_from_canon_sexp): New.
Modified: trunk/g10/ChangeLog
===================================================================
--- trunk/g10/ChangeLog 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/g10/ChangeLog 2009-07-07 10:02:41 UTC (rev 5064)
@@ -1,6 +1,18 @@
+2009-07-07 Werner Koch <wk at g10code.com>
+
+ * gpg.c (set_opt_session_env): New.
+ (main): Allocate opt.session_env. Use it for oDisplay, oTTYname,
+ oTTYtype and oXauthority.
+
+ * options.h: Include session_env.h.
+ (opt): Add field SESSION_ENV, remove obsolete fields.
+
+ * call-agent.c (start_agent): Adjust start_new_gpg_agent for
+ changed args.
+
2009-06-24 Werner Koch <wk at g10code.com>
- * keyedit.c (menu_select_key): Renmove dead assign to I.
+ * keyedit.c (menu_select_key): Remove dead assign to I.
(menu_select_uid): Ditto.
* keyring.c (keyring_search): Remove dead assign to NAME.
* card-util.c (card_edit): Remove useless DID_CHECKPIN.
Modified: trunk/sm/ChangeLog
===================================================================
--- trunk/sm/ChangeLog 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/sm/ChangeLog 2009-07-07 10:02:41 UTC (rev 5064)
@@ -1,3 +1,15 @@
+2009-07-07 Werner Koch <wk at g10code.com>
+
+ * gpgsm.h: Include session-env.h.
+ (opt): Add field SESSION_ENV. Remove obsolete fields.
+ * server.c (option_handler): Rewrite setting of option fields.
+ Replace strdup by xtrystrdup.
+ * gpgsm.c (set_opt_session_env): New.
+ (main): Use it for oDisplay, oTTYname, oTTYtype and oXauthority.
+ * call-agent.c (start_agent): Adjust start_new_gpg_agent for
+ changed args.
+ * misc.c (setup_pinentry_env): Use new session_env stuff.
+
2009-07-02 Werner Koch <wk at g10code.com>
* certreqgen-ui.c (gpgsm_gencertreq_tty): Allow using a key from a
Modified: trunk/tools/ChangeLog
===================================================================
--- trunk/tools/ChangeLog 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/tools/ChangeLog 2009-07-07 10:02:41 UTC (rev 5064)
@@ -1,3 +1,8 @@
+2009-07-07 Werner Koch <wk at g10code.com>
+
+ * gpg-connect-agent.c (start_agent): Adjust for changed args of
+ send_pinentry_environment.
+
2009-06-30 Werner Koch <wk at g10code.com>
* ccidmon.c (parse_line_sniffusb): Take also TAB as delimiter.
@@ -1022,7 +1027,8 @@
* watchgnupg.c: New.
- Copyright 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright 2003, 2004, 2005, 2006, 2007, 2008,
+ 2009 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/NEWS 2009-07-07 10:02:41 UTC (rev 5064)
@@ -1,15 +1,16 @@
Noteworthy changes in version 2.0.13
-------------------------------------------------
- This is a BETA version!
+ * The envvars XMODIFIERS, GTK_IM_MODULE and QT_IM_MODULE are now
+ passed to the Pinentry to make SCIM work.
- * Minor bug fixes.
-
* gpgsm --gen-key implements a --batch mode.
* gpgsm --gen-key implements all features of gpgsm-gencert.sh.
+ * Minor bug fixes.
+
Noteworthy changes in version 2.0.12 (2009-06-17)
-------------------------------------------------
Modified: trunk/agent/agent.h
===================================================================
--- trunk/agent/agent.h 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/agent/agent.h 2009-07-07 10:02:41 UTC (rev 5064)
@@ -33,6 +33,7 @@
#include "../common/util.h"
#include "../common/membuf.h"
#include "../common/sysutils.h" /* (gnupg_fd_t) */
+#include "../common/session-env.h"
/* To convey some special hash algorithms we use algorithm numbers
reserved for application use. */
@@ -56,13 +57,9 @@
/* Environment setting gathered at program start or changed using the
Assuan command UPDATESTARTUPTTY. */
- char *startup_display;
- char *startup_ttyname;
- char *startup_ttytype;
+ session_env_t startup_env;
char *startup_lc_ctype;
char *startup_lc_messages;
- char *startup_xauthority;
- char *startup_pinentry_user_data;
const char *pinentry_program; /* Filename of the program to start as
@@ -142,13 +139,10 @@
/* Private data of the SCdaemon (call-scd.c). */
struct scd_local_s *scd_local;
- char *display;
- char *ttyname;
- char *ttytype;
+ session_env_t session_env;
char *lc_ctype;
char *lc_messages;
- char *xauthority;
- char *pinentry_user_data;
+
struct {
int algo;
unsigned char value[MAX_DIGEST_LEN];
Modified: trunk/agent/call-pinentry.c
===================================================================
--- trunk/agent/call-pinentry.c 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/agent/call-pinentry.c 2009-07-07 10:02:41 UTC (rev 5064)
@@ -172,14 +172,30 @@
if (!where)
{
+ int iterator = 0;
+ const char *name, *assname, *value;
+
gcry_control (GCRYCTL_TERM_SECMEM);
- if (ctrl->xauthority)
- setenv ("XAUTHORITY", ctrl->xauthority, 1);
- if (ctrl->pinentry_user_data)
- setenv ("PINENTRY_USER_DATA", ctrl->pinentry_user_data, 1 );
+
+ while ((name = session_env_list_stdenvnames (&iterator, &assname)))
+ {
+ /* For all new envvars (!ASSNAME) and the two medium old
+ ones which do have an assuan name but are conveyed using
+ environment variables, update the environment of the
+ forked process. */
+ if (!assname
+ || !strcmp (name, "XAUTHORITY")
+ || !strcmp (name, "PINENTRY_USER_DATA"))
+ {
+ value = session_env_getenv (ctrl->session_env, name);
+ if (value)
+ setenv (name, value, 1);
+ }
+ }
}
}
+
static int
getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
{
@@ -214,6 +230,7 @@
pth_event_t evt;
const char *tmpstr;
unsigned long pinentry_pid;
+ const char *value;
evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
if (!pth_mutex_acquire (&entry_lock, 0, evt))
@@ -273,10 +290,11 @@
argv[0] = pgmname;
#endif /*__APPLE__*/
- if (ctrl->display && !opt.keep_display)
+ if (!opt.keep_display
+ && (value = session_env_getenv (ctrl->session_env, "DISPLAY")))
{
argv[1] = "--display";
- argv[2] = ctrl->display;
+ argv[2] = value;
argv[3] = NULL;
}
else
@@ -313,10 +331,12 @@
NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return unlock_pinentry (rc);
- if (ctrl->ttyname)
+
+ value = session_env_getenv (ctrl->session_env, "GPG_TTY");
+ if (value)
{
char *optstr;
- if (asprintf (&optstr, "OPTION ttyname=%s", ctrl->ttyname) < 0 )
+ if (asprintf (&optstr, "OPTION ttyname=%s", value) < 0 )
return unlock_pinentry (out_of_core ());
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
@@ -324,10 +344,11 @@
if (rc)
return unlock_pinentry (rc);
}
- if (ctrl->ttytype)
+ value = session_env_getenv (ctrl->session_env, "TERM");
+ if (value)
{
char *optstr;
- if (asprintf (&optstr, "OPTION ttytype=%s", ctrl->ttytype) < 0 )
+ if (asprintf (&optstr, "OPTION ttytype=%s", value) < 0 )
return unlock_pinentry (out_of_core ());
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
NULL);
Modified: trunk/agent/command-ssh.c
===================================================================
--- trunk/agent/command-ssh.c 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/agent/command-ssh.c 2009-07-07 10:02:41 UTC (rev 5064)
@@ -2906,29 +2906,41 @@
void
start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
{
- estream_t stream_sock;
- gpg_error_t err;
+ estream_t stream_sock = NULL;
+ gpg_error_t err = 0;
int ret;
/* Because the ssh protocol does not send us information about the
the current TTY setting, we resort here to use those from startup
or those explictly set. */
- if (!ctrl->display && opt.startup_display)
- ctrl->display = strdup (opt.startup_display);
- if (!ctrl->ttyname && opt.startup_ttyname)
- ctrl->ttyname = strdup (opt.startup_ttyname);
- if (!ctrl->ttytype && opt.startup_ttytype)
- ctrl->ttytype = strdup (opt.startup_ttytype);
- if (!ctrl->lc_ctype && opt.startup_lc_ctype)
- ctrl->lc_ctype = strdup (opt.startup_lc_ctype);
- if (!ctrl->lc_messages && opt.startup_lc_messages)
- ctrl->lc_messages = strdup (opt.startup_lc_messages);
- if (!ctrl->xauthority && opt.startup_xauthority)
- ctrl->xauthority = strdup (opt.startup_xauthority);
- if (!ctrl->pinentry_user_data && opt.startup_pinentry_user_data)
- ctrl->pinentry_user_data = strdup (opt.startup_pinentry_user_data);
+ {
+ static const char *names[] =
+ {"GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL};
+ int idx;
+ const char *value;
+ for (idx=0; !err && names[idx]; idx++)
+ if (!session_env_getenv (ctrl->session_env, names[idx])
+ && (value = session_env_getenv (opt.startup_env, names[idx])))
+ err = session_env_setenv (ctrl->session_env, names[idx], value);
+
+ if (!err && !ctrl->lc_ctype && opt.startup_lc_ctype)
+ if (!(ctrl->lc_ctype = xtrystrdup (opt.startup_lc_ctype)))
+ err = gpg_error_from_syserror ();
+ if (!err && !ctrl->lc_messages && opt.startup_lc_messages)
+ if (!(ctrl->lc_messages = xtrystrdup (opt.startup_lc_messages)))
+ err = gpg_error_from_syserror ();
+
+ if (err)
+ {
+ log_error ("error setting default session environment: %s\n",
+ gpg_strerror (err));
+ goto out;
+ }
+ }
+
+
/* Create stream from socket. */
stream_sock = es_fdopen (FD2INT(sock_client), "r+");
if (!stream_sock)
Modified: trunk/agent/command.c
===================================================================
--- trunk/agent/command.c 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/agent/command.c 2009-07-07 10:02:41 UTC (rev 5064)
@@ -1520,33 +1520,53 @@
static int
cmd_updatestartuptty (assuan_context_t ctx, char *line)
{
+ static const char *names[] =
+ { "GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL };
ctrl_t ctrl = assuan_get_pointer (ctx);
-
+ gpg_error_t err = 0;
+ session_env_t se;
+ int idx;
+ char *lc_ctype = NULL;
+ char *lc_messages = NULL;
+
(void)line;
- xfree (opt.startup_display); opt.startup_display = NULL;
- xfree (opt.startup_ttyname); opt.startup_ttyname = NULL;
- xfree (opt.startup_ttytype); opt.startup_ttytype = NULL;
- xfree (opt.startup_lc_ctype); opt.startup_lc_ctype = NULL;
- xfree (opt.startup_lc_messages); opt.startup_lc_messages = NULL;
- xfree (opt.startup_xauthority); opt.startup_xauthority = NULL;
+ se = session_env_new ();
+ if (!se)
+ err = gpg_error_from_syserror ();
- if (ctrl->display)
- opt.startup_display = xtrystrdup (ctrl->display);
- if (ctrl->ttyname)
- opt.startup_ttyname = xtrystrdup (ctrl->ttyname);
- if (ctrl->ttytype)
- opt.startup_ttytype = xtrystrdup (ctrl->ttytype);
- if (ctrl->lc_ctype)
- opt.startup_lc_ctype = xtrystrdup (ctrl->lc_ctype);
- if (ctrl->lc_messages)
- opt.startup_lc_messages = xtrystrdup (ctrl->lc_messages);
- if (ctrl->xauthority)
- opt.startup_xauthority = xtrystrdup (ctrl->xauthority);
- if (ctrl->pinentry_user_data)
- opt.startup_pinentry_user_data = xtrystrdup (ctrl->pinentry_user_data);
+ for (idx=0; !err && names[idx]; idx++)
+ {
+ const char *value = session_env_getenv (ctrl->session_env, names[idx]);
+ if (value)
+ err = session_env_setenv (se, names[idx], value);
+ }
- return 0;
+ if (!err && ctrl->lc_ctype)
+ if (!(lc_ctype = xtrystrdup (ctrl->lc_ctype)))
+ err = gpg_error_from_syserror ();
+
+ if (!err && ctrl->lc_messages)
+ if (!(lc_messages = xtrystrdup (ctrl->lc_messages)))
+ err = gpg_error_from_syserror ();
+
+ if (err)
+ {
+ session_env_release (se);
+ xfree (lc_ctype);
+ xfree (lc_messages);
+ }
+ else
+ {
+ session_env_release (opt.startup_env);
+ opt.startup_env = se;
+ xfree (opt.startup_lc_ctype);
+ opt.startup_lc_ctype = lc_ctype;
+ xfree (opt.startup_lc_messages);
+ opt.startup_lc_messages = lc_messages;
+ }
+
+ return err;
}
@@ -1680,36 +1700,31 @@
option_handler (assuan_context_t ctx, const char *key, const char *value)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
+ gpg_error_t err = 0;
- if (!strcmp (key, "display"))
+ if (!strcmp (key, "putenv"))
{
- if (ctrl->display)
- xfree (ctrl->display);
- ctrl->display = xtrystrdup (value);
- if (!ctrl->display)
- return out_of_core ();
+ /* Change the session's environment to be used for the
+ Pinentry. Valid values are:
+ <NAME> Delete envvar NAME
+ <KEY>= Set envvar NAME to the empty string
+ <KEY>=<VALUE> Set envvar NAME to VALUE
+ */
+ err = session_env_putenv (ctrl->session_env, value);
}
+ else if (!strcmp (key, "display"))
+ {
+ err = session_env_setenv (ctrl->session_env, "DISPLAY", value);
+ }
else if (!strcmp (key, "ttyname"))
{
if (!opt.keep_tty)
- {
- if (ctrl->ttyname)
- xfree (ctrl->ttyname);
- ctrl->ttyname = xtrystrdup (value);
- if (!ctrl->ttyname)
- return out_of_core ();
- }
+ err = session_env_setenv (ctrl->session_env, "GPG_TTY", value);
}
else if (!strcmp (key, "ttytype"))
{
if (!opt.keep_tty)
- {
- if (ctrl->ttytype)
- xfree (ctrl->ttytype);
- ctrl->ttytype = xtrystrdup (value);
- if (!ctrl->ttytype)
- return out_of_core ();
- }
+ err = session_env_setenv (ctrl->session_env, "TERM", value);
}
else if (!strcmp (key, "lc-ctype"))
{
@@ -1729,28 +1744,20 @@
}
else if (!strcmp (key, "xauthority"))
{
- if (ctrl->xauthority)
- xfree (ctrl->xauthority);
- ctrl->xauthority = xtrystrdup (value);
- if (!ctrl->xauthority)
- return out_of_core ();
+ err = session_env_setenv (ctrl->session_env, "XAUTHORITY", value);
}
else if (!strcmp (key, "pinentry-user-data"))
{
- if (ctrl->pinentry_user_data)
- xfree (ctrl->pinentry_user_data);
- ctrl->pinentry_user_data = xtrystrdup (value);
- if (!ctrl->pinentry_user_data)
- return out_of_core ();
+ err = session_env_setenv (ctrl->session_env, "PINENTRY_USER_DATA", value);
}
else if (!strcmp (key, "use-cache-for-signing"))
ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
else if (!strcmp (key, "allow-pinentry-notify"))
ctrl->server_local->allow_pinentry_notify = 1;
else
- return gpg_error (GPG_ERR_UNKNOWN_OPTION);
+ err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
- return 0;
+ return err;
}
Modified: trunk/agent/gpg-agent.c
===================================================================
--- trunk/agent/gpg-agent.c 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/agent/gpg-agent.c 2009-07-07 10:02:41 UTC (rev 5064)
@@ -609,29 +609,41 @@
opt.homedir = default_homedir ();
/* Record some of the original environment strings. */
- opt.startup_display = getenv ("DISPLAY");
- if (opt.startup_display)
- opt.startup_display = xstrdup (opt.startup_display);
- opt.startup_ttyname = ttyname (0);
- if (opt.startup_ttyname)
- opt.startup_ttyname = xstrdup (opt.startup_ttyname);
- opt.startup_ttytype = getenv ("TERM");
- if (opt.startup_ttytype)
- opt.startup_ttytype = xstrdup (opt.startup_ttytype);
- /* Fixme: Better use the locale function here. */
- opt.startup_lc_ctype = getenv ("LC_CTYPE");
- if (opt.startup_lc_ctype)
- opt.startup_lc_ctype = xstrdup (opt.startup_lc_ctype);
- opt.startup_lc_messages = getenv ("LC_MESSAGES");
- if (opt.startup_lc_messages)
- opt.startup_lc_messages = xstrdup (opt.startup_lc_messages);
- opt.startup_xauthority = getenv ("XAUTHORITY");
- if (opt.startup_xauthority)
- opt.startup_xauthority = xstrdup (opt.startup_xauthority);
- opt.startup_pinentry_user_data = getenv ("PINENTRY_USER_DATA");
- if (opt.startup_pinentry_user_data)
- opt.startup_pinentry_user_data = xstrdup (opt.startup_pinentry_user_data);
+ {
+ const char *s;
+ int idx;
+ static const char *names[] =
+ { "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL };
+ err = 0;
+ opt.startup_env = session_env_new ();
+ if (!opt.startup_env)
+ err = gpg_error_from_syserror ();
+ for (idx=0; !err && names[idx]; idx++)
+ {
+ s = getenv (names[idx]);
+ if (s)
+ err = session_env_setenv (opt.startup_env, names[idx], s);
+ }
+ if (!err)
+ {
+ s = ttyname (0);
+ if (s)
+ err = session_env_setenv (opt.startup_env, "GPG_TTY", s);
+ }
+ if (err)
+ log_fatal ("error recording startup environment: %s\n",
+ gpg_strerror (err));
+
+ /* Fixme: Better use the locale function here. */
+ opt.startup_lc_ctype = getenv ("LC_CTYPE");
+ if (opt.startup_lc_ctype)
+ opt.startup_lc_ctype = xstrdup (opt.startup_lc_ctype);
+ opt.startup_lc_messages = getenv ("LC_MESSAGES");
+ if (opt.startup_lc_messages)
+ opt.startup_lc_messages = xstrdup (opt.startup_lc_messages);
+ }
+
/* Check whether we have a config file on the commandline */
orig_argc = argc;
orig_argv = argv;
@@ -924,6 +936,14 @@
strerror (errno) );
agent_exit (1);
}
+ ctrl->session_env = session_env_new ();
+ if (!ctrl->session_env)
+ {
+ log_error ("error allocating session environment block: %s\n",
+ strerror (errno) );
+ xfree (ctrl);
+ agent_exit (1);
+ }
agent_init_default_ctrl (ctrl);
start_command_handler (ctrl, GNUPG_INVALID_FD, GNUPG_INVALID_FD);
agent_deinit_default_ctrl (ctrl);
@@ -1218,63 +1238,43 @@
exit (rc);
}
+
static void
agent_init_default_ctrl (ctrl_t ctrl)
{
/* Note we ignore malloc errors because we can't do much about it
and the request will fail anyway shortly after this
initialization. */
- if (ctrl->display)
- xfree (ctrl->display);
- ctrl->display = default_display? xtrystrdup (default_display) : NULL;
-
- if (ctrl->ttyname)
- xfree (ctrl->ttyname);
- ctrl->ttyname = default_ttyname? xtrystrdup (default_ttyname) : NULL;
-
- if (ctrl->ttytype)
- xfree (ctrl->ttytype);
- ctrl->ttytype = default_ttytype? xtrystrdup (default_ttytype) : NULL;
-
+ session_env_setenv (ctrl->session_env, "DISPLAY", default_display);
+ session_env_setenv (ctrl->session_env, "GPG_TTY", default_ttyname);
+ session_env_setenv (ctrl->session_env, "TERM", default_ttytype);
+ session_env_setenv (ctrl->session_env, "XAUTHORITY", default_xauthority);
+ session_env_setenv (ctrl->session_env, "PINENTRY_USER_DATA", NULL);
+
if (ctrl->lc_ctype)
xfree (ctrl->lc_ctype);
ctrl->lc_ctype = default_lc_ctype? xtrystrdup (default_lc_ctype) : NULL;
-
+
if (ctrl->lc_messages)
xfree (ctrl->lc_messages);
ctrl->lc_messages = default_lc_messages? xtrystrdup (default_lc_messages)
/**/ : NULL;
- if (ctrl->xauthority)
- xfree (ctrl->xauthority);
- ctrl->xauthority = default_xauthority? xtrystrdup (default_xauthority)
- /**/: NULL;
-
- if (ctrl->pinentry_user_data)
- xfree (ctrl->pinentry_user_data);
- ctrl->pinentry_user_data = NULL;
}
static void
agent_deinit_default_ctrl (ctrl_t ctrl)
{
- if (ctrl->display)
- xfree (ctrl->display);
- if (ctrl->ttyname)
- xfree (ctrl->ttyname);
- if (ctrl->ttytype)
- xfree (ctrl->ttytype);
+ session_env_release (ctrl->session_env);
+
if (ctrl->lc_ctype)
xfree (ctrl->lc_ctype);
if (ctrl->lc_messages)
xfree (ctrl->lc_messages);
- if (ctrl->xauthority)
- xfree (ctrl->xauthority);
- if (ctrl->pinentry_user_data)
- xfree (ctrl->pinentry_user_data);
}
+
/* Reread parts of the configuration. Note, that this function is
obviously not thread-safe and should only be called from the PTH
signal handler.
@@ -1961,6 +1961,13 @@
strerror (errno) );
assuan_sock_close (fd);
}
+ else if ( !(ctrl->session_env = session_env_new ()) )
+ {
+ log_error ("error allocating session environment block: %s\n",
+ strerror (errno) );
+ xfree (ctrl);
+ assuan_sock_close (fd);
+ }
else
{
char threadname[50];
@@ -1999,6 +2006,13 @@
strerror (errno) );
assuan_sock_close (fd);
}
+ else if ( !(ctrl->session_env = session_env_new ()) )
+ {
+ log_error ("error allocating session environment block: %s\n",
+ strerror (errno) );
+ xfree (ctrl);
+ assuan_sock_close (fd);
+ }
else
{
char threadname[50];
Modified: trunk/agent/protect-tool.c
===================================================================
--- trunk/agent/protect-tool.c 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/agent/protect-tool.c 2009-07-07 10:02:41 UTC (rev 5064)
@@ -1086,7 +1086,7 @@
opt.verbose,
opt_homedir,
opt_agent_program,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL);
if (opt_prompt)
opt_prompt = percent_plus_unescape (opt_prompt, 0);
Modified: trunk/common/Makefile.am
===================================================================
--- trunk/common/Makefile.am 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/common/Makefile.am 2009-07-07 10:02:41 UTC (rev 5064)
@@ -69,6 +69,7 @@
pka.c pka.h \
http.c http.h \
localename.c \
+ session-env.c session-env.h \
helpfile.c
# Sources only useful without PTH.
@@ -111,7 +112,8 @@
#
# Module tests
#
-module_tests = t-convert t-percent t-gettime t-sysutils t-sexputil t-exechelp
+module_tests = t-convert t-percent t-gettime t-sysutils t-sexputil t-exechelp \
+ t-session-env
module_maint_tests = t-helpfile t-b64
t_common_ldadd = libcommon.a ../jnlib/libjnlib.a ../gl/libgnu.a \
@@ -125,6 +127,5 @@
t_sexputil_LDADD = $(t_common_ldadd)
t_b64_LDADD = $(t_common_ldadd)
t_exechelp_LDADD = $(t_common_ldadd)
+t_session_env_LDADD = $(t_common_ldadd)
-
-
Modified: trunk/common/asshelp.c
===================================================================
--- trunk/common/asshelp.c 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/common/asshelp.c 2009-07-07 10:02:41 UTC (rev 5064)
@@ -1,5 +1,5 @@
/* asshelp.c - Helper functions for Assuan
- * Copyright (C) 2002, 2004, 2007 Free Software Foundation, Inc.
+ * Copyright (C) 2002, 2004, 2007, 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -34,10 +34,9 @@
#include "status.h"
#include "asshelp.h"
-
static gpg_error_t
send_one_option (assuan_context_t ctx, gpg_err_source_t errsource,
- const char *name, const char *value)
+ const char *name, const char *value, int use_putenv)
{
gpg_error_t err;
char *optstr;
@@ -46,7 +45,8 @@
if (!value || !*value)
err = 0; /* Avoid sending empty strings. */
- else if (asprintf (&optstr, "OPTION %s=%s", name, value ) < 0)
+ else if (asprintf (&optstr, "OPTION %s%s=%s",
+ use_putenv? "putenv=":"", name, value) < 0)
err = gpg_error_from_syserror ();
else
{
@@ -64,58 +64,44 @@
gpg_error_t
send_pinentry_environment (assuan_context_t ctx,
gpg_err_source_t errsource,
- const char *opt_display,
- const char *opt_ttyname,
- const char *opt_ttytype,
const char *opt_lc_ctype,
const char *opt_lc_messages,
- const char *opt_xauthority,
- const char *opt_pinentry_user_data)
+ session_env_t session_env)
+
{
gpg_error_t err = 0;
- char *dft_display = NULL;
- char *dft_ttyname = NULL;
- char *dft_ttytype = NULL;
char *old_lc = NULL;
char *dft_lc = NULL;
- char *dft_xauthority = NULL;
- char *dft_pinentry_user_data = NULL;
+ const char *dft_ttyname;
+ int iterator;
+ const char *name, *assname, *value;
+ int is_default;
- /* Send the DISPLAY variable. */
- dft_display = getenv ("DISPLAY");
- if (opt_display || dft_display)
+ iterator = 0;
+ while ((name = session_env_list_stdenvnames (&iterator, &assname)))
{
- err = send_one_option (ctx, errsource, "display",
- opt_display ? opt_display : dft_display);
- if (err)
- return err;
- }
+ value = session_env_getenv_or_default (session_env, name, NULL);
+ if (!value)
+ continue;
- /* Send the name of the TTY. */
- if (!opt_ttyname)
- {
- dft_ttyname = getenv ("GPG_TTY");
- if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
- dft_ttyname = ttyname (0);
- }
- if (opt_ttyname || dft_ttyname)
- {
- err = send_one_option (ctx, errsource, "ttyname",
- opt_ttyname ? opt_ttyname : dft_ttyname);
+ if (assname)
+ err = send_one_option (ctx, errsource, assname, value, 0);
+ else
+ {
+ err = send_one_option (ctx, errsource, name, value, 1);
+ if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
+ err = 0; /* Server too old; can't pass the new envvars. */
+ }
if (err)
return err;
}
- /* Send the type of the TTY. */
- dft_ttytype = getenv ("TERM");
- if (opt_ttytype || (dft_ttyname && dft_ttytype))
- {
- err = send_one_option (ctx, errsource, "ttytype",
- opt_ttyname ? opt_ttytype : dft_ttytype);
- if (err)
- return err;
- }
+ dft_ttyname = session_env_getenv_or_default (session_env, "GPG_TTY",
+ &is_default);
+ if (dft_ttyname && !is_default)
+ dft_ttyname = NULL; /* We need the default value. */
+
/* Send the value for LC_CTYPE. */
#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
old_lc = setlocale (LC_CTYPE, NULL);
@@ -130,7 +116,7 @@
if (opt_lc_ctype || (dft_ttyname && dft_lc))
{
err = send_one_option (ctx, errsource, "lc-ctype",
- opt_lc_ctype ? opt_lc_ctype : dft_lc);
+ opt_lc_ctype ? opt_lc_ctype : dft_lc, 0);
}
#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
if (old_lc)
@@ -156,7 +142,7 @@
if (opt_lc_messages || (dft_ttyname && dft_lc))
{
err = send_one_option (ctx, errsource, "lc-messages",
- opt_lc_messages ? opt_lc_messages : dft_lc);
+ opt_lc_messages ? opt_lc_messages : dft_lc, 0);
}
#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
if (old_lc)
@@ -168,31 +154,6 @@
if (err)
return err;
- /* Send the XAUTHORITY variable. */
- dft_xauthority = getenv ("XAUTHORITY");
- if (opt_xauthority || dft_xauthority)
- {
- err = send_one_option (ctx, errsource, "xauthority",
- opt_xauthority ? opt_xauthority : dft_xauthority);
- if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
- err = 0;
- if (err)
- return err;
- }
-
- /* Send the PINENTRY_USER_DATA variable. */
- dft_pinentry_user_data = getenv ("PINENTRY_USER_DATA");
- if (opt_pinentry_user_data || dft_pinentry_user_data)
- {
- err = send_one_option (ctx, errsource, "pinentry-user-data",
- opt_pinentry_user_data ?
- opt_pinentry_user_data : dft_pinentry_user_data);
- if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
- err = 0;
- if (err)
- return err;
- }
-
return 0;
}
@@ -205,13 +166,9 @@
gpg_err_source_t errsource,
const char *homedir,
const char *agent_program,
- const char *opt_display,
- const char *opt_ttyname,
- const char *opt_ttytype,
const char *opt_lc_ctype,
const char *opt_lc_messages,
- const char *opt_xauthority,
- const char *opt_pinentry_user_data,
+ session_env_t session_env,
int verbose, int debug,
gpg_error_t (*status_cb)(ctrl_t, int, ...),
ctrl_t status_cb_arg)
@@ -365,10 +322,8 @@
NULL, NULL, NULL, NULL, NULL, NULL);
if (!rc)
rc = send_pinentry_environment (ctx, errsource,
- opt_display, opt_ttyname, opt_ttytype,
opt_lc_ctype, opt_lc_messages,
- opt_xauthority,
- opt_pinentry_user_data);
+ session_env);
if (rc)
{
assuan_disconnect (ctx);
Modified: trunk/common/asshelp.h
===================================================================
--- trunk/common/asshelp.h 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/common/asshelp.h 2009-07-07 10:02:41 UTC (rev 5064)
@@ -23,31 +23,25 @@
#include <assuan.h>
#include <gpg-error.h>
+#include "session-env.h"
+
gpg_error_t
send_pinentry_environment (assuan_context_t ctx,
gpg_err_source_t errsource,
- const char *opt_display,
- const char *opt_ttyname,
- const char *opt_ttytype,
const char *opt_lc_ctype,
const char *opt_lc_messages,
- const char *opt_xauthority,
- const char *opt_pinentry_user_data);
+ session_env_t session_env);
/* This fucntion is used by the call-agent.c modules to fire up a new
- agent. What a parameter list ;-). */
+ agent. */
gpg_error_t
start_new_gpg_agent (assuan_context_t *r_ctx,
gpg_err_source_t errsource,
const char *homedir,
const char *agent_program,
- const char *opt_display,
- const char *opt_ttyname,
- const char *opt_ttytype,
const char *opt_lc_ctype,
const char *opt_lc_messages,
- const char *opt_xauthority,
- const char *opt_pinentry_user_data,
+ session_env_t session_env,
int verbose, int debug,
gpg_error_t (*status_cb)(ctrl_t, int, ...),
ctrl_t status_cb_arg);
Modified: trunk/common/get-passphrase.c
===================================================================
--- trunk/common/get-passphrase.c 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/common/get-passphrase.c 2009-07-07 10:02:41 UTC (rev 5064)
@@ -39,12 +39,9 @@
int verbosity;
const char *homedir;
const char *agent_program;
- const char *display;
- const char *ttyname;
- const char *ttytype;
const char *lc_ctype;
const char *lc_messages;
- const char *xauthority;
+ session_env_t session_env;
const char *pinentry_user_data;
} agentargs;
@@ -57,25 +54,17 @@
int verbosity,
const char *homedir,
const char *agent_program,
- const char *opt_display,
- const char *opt_ttyname,
- const char *opt_ttytype,
const char *opt_lc_ctype,
const char *opt_lc_messages,
- const char *opt_xauthority,
- const char *opt_pinentry_user_data)
+ session_env_t session_env)
{
agentargs.errsource = errsource;
agentargs.verbosity = verbosity;
agentargs.homedir = homedir;
agentargs.agent_program = agent_program;
- agentargs.display = opt_display;
- agentargs.ttyname = opt_ttyname;
- agentargs.ttytype = opt_ttytype;
agentargs.lc_ctype = opt_lc_ctype;
agentargs.lc_messages = opt_lc_messages;
- agentargs.xauthority = opt_xauthority;
- agentargs.pinentry_user_data = opt_pinentry_user_data;
+ agentargs.session_env = session_env;
}
@@ -96,13 +85,9 @@
agentargs.errsource,
agentargs.homedir,
agentargs.agent_program,
- agentargs.display,
- agentargs.ttyname,
- agentargs.ttytype,
agentargs.lc_ctype,
agentargs.lc_messages,
- agentargs.xauthority,
- agentargs.pinentry_user_data,
+ agentargs.session_env,
agentargs.verbosity, 0, NULL, NULL);
if (!err)
{
Modified: trunk/common/get-passphrase.h
===================================================================
--- trunk/common/get-passphrase.h 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/common/get-passphrase.h 2009-07-07 10:02:41 UTC (rev 5064)
@@ -20,17 +20,15 @@
#ifndef GNUPG_COMMON_GET_PASSPHRASE_H
#define GNUPG_COMMON_GET_PASSPHRASE_H
+#include "session-env.h"
+
void gnupg_prepare_get_passphrase (gpg_err_source_t errsource,
int verbosity,
const char *homedir,
const char *agent_program,
- const char *opt_display,
- const char *opt_ttyname,
- const char *opt_ttytype,
const char *opt_lc_ctype,
const char *opt_lc_messages,
- const char *opt_xauthority,
- const char *opt_pinentry_user_data);
+ session_env_t session_env);
gpg_error_t gnupg_get_passphrase (const char *cache_id,
const char *err_msg,
Added: trunk/common/session-env.c
===================================================================
--- trunk/common/session-env.c (rev 0)
+++ trunk/common/session-env.c 2009-07-07 10:02:41 UTC (rev 5064)
@@ -0,0 +1,384 @@
+/* se4ssiobn-env.c - session environment helper functions.
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include "util.h"
+#include "session-env.h"
+
+
+struct variable_s
+{
+ char *value; /* Pointer into NAME to the Nul terminated value. */
+ int is_default; /* The value is a default one. */
+ char name[1]; /* Nul terminated Name and space for the value. */
+};
+
+
+
+/* The session environment object. */
+struct session_environment_s
+{
+ size_t arraysize; /* Allocated size or ARRAY. */
+ size_t arrayused; /* Used size of ARRAY. */
+ struct variable_s **array; /* Array of variables. NULL slots are unused. */
+};
+
+
+/* A list of environment vribales we pass from the acual user
+ (e.g. gpgme) down to the pinentry. We do not handle the locale
+ settings because they do not only depend on envvars. */
+static struct
+{
+ const char *name;
+ const char *assname; /* Name used by Assuan or NULL. */
+} stdenvnames[] = {
+ { "GPG_TTY", "ttyname" }, /* GnuPG specific envvar. */
+ { "TERM", "ttytype" }, /* Used to set ttytype. */
+ { "DISPLAY", "display" }, /* The X-Display. */
+ { "XAUTHORITY","xauthority"}, /* Xlib Authentication. */
+ { "XMODIFIERS" }, /* Used by Xlib to select X input
+ modules (eg "@im=SCIM"). */
+ { "GTK_IM_MODULE" }, /* Used by gtk to select gtk input
+ modules (eg "scim-bridge"). */
+ { "QT_IM_MODULE" }, /* Used by Qt to select qt input
+ modules (eg "xim"). */
+ { "PINENTRY_USER_DATA", "pinentry-user-data"}
+ /* Used for communication with
+ non-standard Pinentries. */
+};
+
+
+/* Track last allocated arraysize of all objects ever created. If
+ nothing has ever been allocated we use INITIAL_ARRAYSIZE and we
+ will never use more than MAXDEFAULT_ARRAYSIZE for initial
+ allocation. Note that this is not reentrant if used with a
+ preemptive thread model. */
+static size_t lastallocatedarraysize;
+#define INITIAL_ARRAYSIZE 8 /* Let's use the number of stdenvnames. */
+#define CHUNK_ARRAYSIZE 10
+#define MAXDEFAULT_ARRAYSIZE (INITIAL_ARRAYSIZE + CHUNK_ARRAYSIZE * 5)
+
+
+/* Return the names of standard environment variables one after the
+ other. The caller needs to set the value at the address of
+ ITERATOR initally to 0 and then call this function until it returns
+ NULL. */
+const char *
+session_env_list_stdenvnames (int *iterator, const char **r_assname)
+{
+ int idx = *iterator;
+
+ if (idx < 0 || idx >= DIM (stdenvnames))
+ return NULL;
+ *iterator = idx + 1;
+ if (r_assname)
+ *r_assname = stdenvnames[idx].assname;
+ return stdenvnames[idx].name;
+}
+
+
+/* Create a new session environment object. Return NULL and sets
+ ERRNO on failure. */
+session_env_t
+session_env_new (void)
+{
+ session_env_t se;
+
+ se = xtrycalloc (1, sizeof *se);
+ if (se)
+ {
+ se->arraysize = (lastallocatedarraysize?
+ lastallocatedarraysize : INITIAL_ARRAYSIZE);
+ se->array = xtrycalloc (se->arraysize, sizeof *se->array);
+ if (!se->array)
+ {
+ xfree (se);
+ se = NULL;
+ }
+ }
+
+ return se;
+}
+
+
+/* Release a session environment object. */
+void
+session_env_release (session_env_t se)
+{
+ int idx;
+
+ if (!se)
+ return;
+
+ if (se->arraysize > INITIAL_ARRAYSIZE
+ && se->arraysize <= MAXDEFAULT_ARRAYSIZE
+ && se->arraysize > lastallocatedarraysize)
+ lastallocatedarraysize = se->arraysize;
+
+ for (idx=0; idx < se->arrayused; idx++)
+ if (se->array[idx])
+ xfree (se->array[idx]);
+ xfree (se->array);
+ xfree (se);
+}
+
+
+static gpg_error_t
+delete_var (session_env_t se, const char *name)
+{
+ int idx;
+
+ for (idx=0; idx < se->arrayused; idx++)
+ if (se->array[idx] && !strcmp (se->array[idx]->name, name))
+ {
+ xfree (se->array[idx]);
+ se->array[idx] = NULL;
+ }
+ return 0;
+}
+
+
+static gpg_error_t
+update_var (session_env_t se, const char *string, size_t namelen,
+ const char *explicit_value, int set_default)
+{
+ int idx;
+ int freeidx = -1;
+ const char *value;
+ size_t valuelen;
+ struct variable_s *var;
+
+ if (explicit_value)
+ value = explicit_value;
+ else
+ value = string + namelen + 1;
+ valuelen = strlen (value);
+
+ for (idx=0; idx < se->arrayused; idx++)
+ {
+ if (!se->array[idx])
+ freeidx = idx;
+ else if (!strncmp (se->array[idx]->name, string, namelen)
+ && strlen (se->array[idx]->name) == namelen)
+ {
+ /* Check if the value is the same; no need to update it,
+ except for updating the default flag. */
+ if (strlen (se->array[idx]->value) == valuelen)
+ {
+ se->array[idx]->is_default = !!set_default;
+ return 0;
+ }
+ /* Prepare for update. */
+ freeidx = idx;
+ }
+ }
+
+ if (freeidx == -1)
+ {
+ if (se->arrayused == se->arraysize)
+ {
+ /* Reallocate the array. */
+ size_t newsize;
+ struct variable_s **newarray;
+
+ newsize = se->arraysize + CHUNK_ARRAYSIZE;
+ newarray = xtrycalloc (newsize, sizeof *newarray);
+ if (!newarray)
+ return gpg_error_from_syserror ();
+ for (idx=0; idx < se->arrayused; idx++)
+ newarray[idx] = se->array[idx];
+ se->arraysize = newsize;
+ xfree (se->array);
+ se->array = newarray;
+ }
+ freeidx = se->arrayused++;
+ }
+
+ /* Allocate new memory and return an error if that didn't worked.
+ Allocating it first allows us to keep the old value; it doesn't
+ matter that arrayused has already been incremented in case of a
+ new entry - it will then pint to a NULL slot. */
+ var = xtrymalloc (sizeof *var + namelen + 1 + valuelen);
+ if (!var)
+ return gpg_error_from_syserror ();
+ var->is_default = !!set_default;
+ memcpy (var->name, string, namelen);
+ var->name[namelen] = '\0';
+ var->value = var->name + namelen + 1;
+ strcpy (var->value, value);
+
+ xfree (se->array[freeidx]);
+ se->array[freeidx] = var;
+ return 0;
+}
+
+
+/* Set or update an environment variable of the session environment.
+ String is similar to the putval(3) function but it is reentrant and
+ takes a copy. In particular it exhibits this behaviour:
+
+ <NAME> Delete envvar NAME
+ <KEY>= Set envvar NAME to the empty string
+ <KEY>=<VALUE> Set envvar NAME to VALUE
+
+ On success 0 is returned; on error an gpg-error code. */
+gpg_error_t
+session_env_putenv (session_env_t se, const char *string)
+{
+ const char *s;
+
+ if (!string || !*string)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ s = strchr (string, '=');
+ if (s == string)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (!s)
+ return delete_var (se, string);
+ else
+ return update_var (se, string, s - string, NULL, 0);
+}
+
+
+/* Same as session_env_putenv but with name and value given as distict
+ values. */
+gpg_error_t
+session_env_setenv (session_env_t se, const char *name, const char *value)
+{
+ if (!name || !*name)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ if (!value)
+ return delete_var (se, name);
+ else
+ return update_var (se, name, strlen (name), value, 0);
+}
+
+
+
+
+/* Return the value of the environment variable NAME from the SE
+ object. If the variable does not exist, NULL is returned. The
+ returned value is valid as long as SE is valid and as long it has
+ not been removed or updated by a call to session_env_putenv. The
+ caller MUST not change the returned value. */
+char *
+session_env_getenv (session_env_t se, const char *name)
+{
+ int idx;
+
+ if (!se || !name || !*name)
+ return NULL;
+
+ for (idx=0; idx < se->arrayused; idx++)
+ if (se->array[idx] && !strcmp (se->array[idx]->name, name))
+ return se->array[idx]->is_default? NULL : se->array[idx]->value;
+ return NULL;
+}
+
+
+/* Return the value of the environment variable NAME from the SE
+ object. The returned value is valid as long as SE is valid and as
+ long it has not been removed or updated by a call to
+ session_env_putenv. If the variable does not exist, the fucntion
+ tries to return the value trough a call to getenv; if that returns
+ a value, this value is recorded and and used. If no value could be
+ found, returns NULL. The caller must not change the returned
+ value. */
+char *
+session_env_getenv_or_default (session_env_t se, const char *name,
+ int *r_default)
+{
+ int idx;
+ char *defvalue;
+
+ if (r_default)
+ *r_default = 0;
+ if (!se || !name || !*name)
+ return NULL;
+
+ for (idx=0; idx < se->arrayused; idx++)
+ if (se->array[idx] && !strcmp (se->array[idx]->name, name))
+ {
+ if (r_default && se->array[idx]->is_default)
+ *r_default = 1;
+ return se->array[idx]->value;
+ }
+
+ /* Get the default value with and additional fallback for GPG_TTY. */
+ defvalue = getenv (name);
+ if ((!defvalue || !*defvalue) && !strcmp (name, "GPG_TTY") && ttyname (0))
+ defvalue = ttyname (0);
+ if (defvalue)
+ {
+ /* Record the default value for later use so that we are safe
+ from later modifications of the environment. We need to take
+ a copy to better cope with the rules of putenv(3). We ignore
+ the error of the update function because we can't return an
+ explicit error anyway and the following scan would then fail
+ anyway. */
+ update_var (se, name, strlen (name), defvalue, 1);
+
+ for (idx=0; idx < se->arrayused; idx++)
+ if (se->array[idx] && !strcmp (se->array[idx]->name, name))
+ {
+ if (r_default && se->array[idx]->is_default)
+ *r_default = 1;
+ return se->array[idx]->value;
+ }
+ }
+
+ return NULL;
+}
+
+
+/* List the entire environment stored in SE. The caller initially
+ needs to set the value of ITERATOR to 0 and then call this function
+ until it returns NULL. The value is retruned at R_VALUE. If
+ R_DEFAULT is not NULL, the default flag is stored on return. The
+ default flag indicates that the value has been taken from the
+ process' environment. The caller must not change the returned
+ name or value. */
+char *
+session_env_listenv (session_env_t se, int *iterator,
+ const char **r_value, int *r_default)
+{
+ int idx = *iterator;
+
+ if (!se || idx < 0)
+ return NULL;
+
+ for (; idx < se->arrayused; idx++)
+ if (se->array[idx])
+ {
+ *iterator = idx+1;
+ if (r_default)
+ *r_default = se->array[idx]->is_default;
+ if (r_value)
+ *r_value = se->array[idx]->value;
+ return se->array[idx]->name;
+ }
+ return NULL;
+}
+
+
Added: trunk/common/session-env.h
===================================================================
--- trunk/common/session-env.h (rev 0)
+++ trunk/common/session-env.h 2009-07-07 10:02:41 UTC (rev 5064)
@@ -0,0 +1,43 @@
+/* session-env.h - Definitions for session environment functions
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GNUPG_COMMON_SESSION_ENV_H
+#define GNUPG_COMMON_SESSION_ENV_H
+
+struct session_environment_s;
+typedef struct session_environment_s *session_env_t;
+
+const char *session_env_list_stdenvnames (int *iterator,
+ const char **r_assname);
+
+session_env_t session_env_new (void);
+void session_env_release (session_env_t se);
+
+gpg_error_t session_env_putenv (session_env_t se, const char *string);
+gpg_error_t session_env_setenv (session_env_t se,
+ const char *name, const char *value);
+
+char *session_env_getenv (session_env_t se, const char *name);
+char *session_env_getenv_or_default (session_env_t se, const char *name,
+ int *r_default);
+char *session_env_listenv (session_env_t se, int *iterator,
+ const char **r_value, int *r_default);
+
+
+#endif /*GNUPG_COMMON_SESSION_ENV_H*/
Modified: trunk/common/t-exechelp.c
===================================================================
--- trunk/common/t-exechelp.c 2009-07-06 21:33:34 UTC (rev 5063)
+++ trunk/common/t-exechelp.c 2009-07-07 10:02:41 UTC (rev 5064)
@@ -69,7 +69,7 @@
/* That is a very crude test. To do a proper test we would need to
fork a test process and best return information by some other means
- that file descriptors. */
+ than file descriptors. */
static void
test_close_all_fds (void)
{
@@ -77,7 +77,7 @@
int *array;
int fd;
int initial_count, count, n;
-#if 1
+#if 0
char buffer[100];
snprintf (buffer, sizeof buffer, "/bin/ls -l /proc/%d/fd", (int)getpid ());
Added: trunk/common/t-session-env.c
===================================================================
--- trunk/common/t-session-env.c (rev 0)
+++ trunk/common/t-session-env.c 2009-07-07 10:02:41 UTC (rev 5064)
@@ -0,0 +1,294 @@
+/* t-session-env.c - Module test for session-env.c
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "util.h"
+#include "session-env.h"
+
+#define pass() do { ; } while(0)
+#define fail(e) do { fprintf (stderr, "%s:%d: function failed: %s\n", \
+ __FILE__,__LINE__, gpg_strerror (e)); \
+ exit (1); \
+ } while(0)
+
+static int verbose;
+
+static void
+listall (session_env_t se)
+{
+ int iterator = 0;
+ const char *name, *value;
+ int def;
+
+ if (verbose)
+ printf ("environment of %p\n", se);
+ while ( (name = session_env_listenv (se, &iterator, &value, &def)) )
+ if (verbose)
+ printf (" %s%s=%s\n", def? "[def] ":" ", name, value);
+
+}
+
+
+static void
+show_stdnames (void)
+{
+ const char *name, *assname;
+ int iterator = 0;
+
+ printf ("Known envvars:");
+ while ((name = session_env_list_stdenvnames (&iterator, &assname)))
+ {
+ printf ( " %s", name);
+ if (assname)
+ printf ( "(%s)", assname);
+ }
+ putchar('\n');
+}
+
+
+static void
+test_all (void)
+{
+ gpg_error_t err;
+ session_env_t se_0, se;
+ const char *s, *s2;
+ int idx;
+
+ se_0 = session_env_new ();
+ if (!se_0)
+ fail (gpg_error_from_syserror ());
+ se = session_env_new ();
+ if (!se)
+ fail (gpg_error_from_syserror ());
+
+ err = session_env_putenv (se, NULL);
+ if (gpg_err_code (err) != GPG_ERR_INV_VALUE)
+ fail (err);
+ err = session_env_putenv (se, "");
More information about the Gnupg-commits
mailing list