1 /* dirinfo.c - Get directory information
2 * Copyright (C) 2009 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/>.
33 DEFINE_STATIC_LOCK (dirinfo_lock);
35 /* Constants used internally to select the data. */
42 /* Values retrieved via gpgconf and cached here. */
44 int valid; /* Cached information is valid. */
50 /* Parse the output of "gpgconf --list-dirs". This function expects
51 that DIRINFO_LOCK is held by the caller. */
53 parse_output (char *line)
57 value = strchr (line, ':');
61 p = strchr (value, ':');
64 if (_gpgme_decode_percent_string (value, &value, strlen (value)+1, 0))
69 if (!strcmp (line, "homedir") && !dirinfo.homedir)
70 dirinfo.homedir = strdup (value);
71 else if (!strcmp (line, "agent-socket") && !dirinfo.agent_socket)
72 dirinfo.agent_socket = strdup (value);
76 /* Read the directory information from gpgconf. This function expects
77 that DIRINFO_LOCK is held by the caller. */
79 read_gpgconf_dirs (void)
82 char linebuf[1024] = {0};
86 struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */, -1, 0},
92 pgmname = _gpgme_get_gpgconf_path ();
96 argv[0] = (char *)pgmname;
97 argv[1] = "--list-dirs";
100 if (_gpgme_io_pipe (rp, 1) < 0)
105 status = _gpgme_io_spawn (pgmname, argv, 0, cfd, NULL, NULL, NULL);
108 _gpgme_io_close (rp[0]);
109 _gpgme_io_close (rp[1]);
115 nread = _gpgme_io_read (rp[0],
117 sizeof linebuf - linelen - 1);
121 const char *lastmark = NULL;
125 linebuf[linelen] = '\0';
127 for (line=linebuf; (mark = strchr (line, '\n')); line = mark+1 )
130 if (mark > line && mark[-1] == '\r')
138 nused = lastmark? (lastmark + 1 - linebuf) : 0;
139 memmove (linebuf, linebuf + nused, linelen - nused);
143 while (nread > 0 && linelen < sizeof linebuf - 1);
145 _gpgme_io_close (rp[0]);
150 get_gpgconf_dir (int what)
152 const char *result = NULL;
157 read_gpgconf_dirs ();
158 /* Even if the reading of the directories failed (e.g. due to an
159 too old version gpgconf or no gpgconf at all), we need to
160 mark the entries as valid so that we won't try over and over
161 to read them. Note further that we are not able to change
162 the read values later because they are practically statically
168 case WANT_HOMEDIR: result = dirinfo.homedir; break;
169 case WANT_AGENT_SOCKET: result = dirinfo.agent_socket; break;
171 UNLOCK (dirinfo_lock);
176 /* Return the default home directory. Returns NULL if not known. */
178 _gpgme_get_default_homedir (void)
180 return get_gpgconf_dir (WANT_HOMEDIR);
183 /* Return the default gpg-agent socket name. Returns NULL if not known. */
185 _gpgme_get_default_agent_socket (void)
187 return get_gpgconf_dir (WANT_AGENT_SOCKET);