1 /* dirinfo.c - Get directory information
2 * Copyright (C) 2009, 2013 g10 Code GmbH
4 * This file is part of GPGME.
6 * GPGME is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
11 * GPGME is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
34 DEFINE_STATIC_LOCK (dirinfo_lock);
36 /* Constants used internally to select the data. */
48 /* Values retrieved via gpgconf and cached here. */
50 int valid; /* Cached information is valid. */
63 /* Helper function to be used only by gpgme_set_global_flag. */
65 _gpgme_dirinfo_disable_gpgconf (void)
67 dirinfo.disable_gpgconf = 1;
71 /* Parse the output of "gpgconf --list-dirs". This function expects
72 that DIRINFO_LOCK is held by the caller. If COMPONENTS is set, the
73 output of --list-components is expected. */
75 parse_output (char *line, int components)
79 value = strchr (line, ':');
85 /* Skip the second field. */
86 value = strchr (value, ':');
91 p = strchr (value, ':');
94 if (_gpgme_decode_percent_string (value, &value, strlen (value)+1, 0))
101 if (!strcmp (line, "gpg") && !dirinfo.gpg_name)
102 dirinfo.gpg_name = strdup (value);
103 else if (!strcmp (line, "gpgsm") && !dirinfo.gpgsm_name)
104 dirinfo.gpgsm_name = strdup (value);
105 else if (!strcmp (line, "g13") && !dirinfo.g13_name)
106 dirinfo.g13_name = strdup (value);
110 if (!strcmp (line, "homedir") && !dirinfo.homedir)
112 const char name[] = "S.uiserver";
114 dirinfo.homedir = strdup (value);
117 dirinfo.uisrv_socket = malloc (strlen (dirinfo
119 + 1 + strlen (name) + 1);
120 if (dirinfo.uisrv_socket)
121 strcpy (stpcpy (stpcpy (dirinfo.uisrv_socket, dirinfo.homedir),
125 else if (!strcmp (line, "agent-socket") && !dirinfo.agent_socket)
126 dirinfo.agent_socket = strdup (value);
131 /* Read the directory information from gpgconf. This function expects
132 that DIRINFO_LOCK is held by the caller. PGNAME is the name of the
133 gpgconf binary. If COMPONENTS is set, not the directories bit the
134 name of the componeNts are read. */
136 read_gpgconf_dirs (const char *pgmname, int components)
138 char linebuf[1024] = {0};
142 struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */, -1, 0},
148 argv[0] = (char *)pgmname;
149 argv[1] = components? "--list-components" : "--list-dirs";
152 if (_gpgme_io_pipe (rp, 1) < 0)
157 status = _gpgme_io_spawn (pgmname, argv, 0, cfd, NULL, NULL, NULL);
160 _gpgme_io_close (rp[0]);
161 _gpgme_io_close (rp[1]);
167 nread = _gpgme_io_read (rp[0],
169 sizeof linebuf - linelen - 1);
173 const char *lastmark = NULL;
177 linebuf[linelen] = '\0';
179 for (line=linebuf; (mark = strchr (line, '\n')); line = mark+1 )
182 if (mark > line && mark[-1] == '\r')
187 parse_output (line, components);
190 nused = lastmark? (lastmark + 1 - linebuf) : 0;
191 memmove (linebuf, linebuf + nused, linelen - nused);
195 while (nread > 0 && linelen < sizeof linebuf - 1);
197 _gpgme_io_close (rp[0]);
202 get_gpgconf_item (int what)
204 const char *result = NULL;
211 pgmname = dirinfo.disable_gpgconf? NULL : _gpgme_get_gpgconf_path ();
212 if (pgmname && access (pgmname, F_OK))
214 _gpgme_debug (DEBUG_INIT,
215 "gpgme-dinfo: gpgconf='%s' [not installed]\n", pgmname);
217 pgmname = NULL; /* Not available. */
220 _gpgme_debug (DEBUG_INIT, "gpgme-dinfo: gpgconf='%s'\n",
221 pgmname? pgmname : "[null]");
224 /* Probably gpgconf is not installed. Assume we are using
226 pgmname = _gpgme_get_gpg_path ();
228 dirinfo.gpg_name = pgmname;
232 read_gpgconf_dirs (pgmname, 0);
233 read_gpgconf_dirs (pgmname, 1);
234 dirinfo.gpgconf_name = pgmname;
236 /* Even if the reading of the directories failed (e.g. due to an
237 too old version gpgconf or no gpgconf at all), we need to
238 mark the entries as valid so that we won't try over and over
239 to read them. Note further that we are not able to change
240 the read values later because they are practically statically
243 if (dirinfo.gpg_name)
244 _gpgme_debug (DEBUG_INIT, "gpgme-dinfo: gpg='%s'\n",
246 if (dirinfo.g13_name)
247 _gpgme_debug (DEBUG_INIT, "gpgme-dinfo: g13='%s'\n",
249 if (dirinfo.gpgsm_name)
250 _gpgme_debug (DEBUG_INIT, "gpgme-dinfo: gpgsm='%s'\n",
253 _gpgme_debug (DEBUG_INIT, "gpgme-dinfo: homedir='%s'\n",
255 if (dirinfo.agent_socket)
256 _gpgme_debug (DEBUG_INIT, "gpgme-dinfo: agent='%s'\n",
257 dirinfo.agent_socket);
258 if (dirinfo.uisrv_socket)
259 _gpgme_debug (DEBUG_INIT, "gpgme-dinfo: uisrv='%s'\n",
260 dirinfo.uisrv_socket);
264 case WANT_HOMEDIR: result = dirinfo.homedir; break;
265 case WANT_AGENT_SOCKET: result = dirinfo.agent_socket; break;
266 case WANT_GPGCONF_NAME: result = dirinfo.gpgconf_name; break;
267 case WANT_GPG_NAME: result = dirinfo.gpg_name; break;
268 case WANT_GPGSM_NAME: result = dirinfo.gpgsm_name; break;
269 case WANT_G13_NAME: result = dirinfo.g13_name; break;
270 case WANT_UISRV_SOCKET: result = dirinfo.uisrv_socket; break;
272 UNLOCK (dirinfo_lock);
277 /* Return the default home directory. Returns NULL if not known. */
279 _gpgme_get_default_homedir (void)
281 return get_gpgconf_item (WANT_HOMEDIR);
284 /* Return the default gpg-agent socket name. Returns NULL if not known. */
286 _gpgme_get_default_agent_socket (void)
288 return get_gpgconf_item (WANT_AGENT_SOCKET);
291 /* Return the default gpg file name. Returns NULL if not known. */
293 _gpgme_get_default_gpg_name (void)
295 return get_gpgconf_item (WANT_GPG_NAME);
298 /* Return the default gpgsm file name. Returns NULL if not known. */
300 _gpgme_get_default_gpgsm_name (void)
302 return get_gpgconf_item (WANT_GPGSM_NAME);
305 /* Return the default g13 file name. Returns NULL if not known. */
307 _gpgme_get_default_g13_name (void)
309 return get_gpgconf_item (WANT_G13_NAME);
312 /* Return the default gpgconf file name. Returns NULL if not known. */
314 _gpgme_get_default_gpgconf_name (void)
316 return get_gpgconf_item (WANT_GPGCONF_NAME);
319 /* Return the default UI-server socket name. Returns NULL if not
322 _gpgme_get_default_uisrv_socket (void)
324 return get_gpgconf_item (WANT_UISRV_SOCKET);