Always pass correct name to argv[0]. Ignore GPG_AGENT_INFO for gpg2.
[gpgme.git] / src / dirinfo.c
1 /* dirinfo.c - Get directory information
2  * Copyright (C) 2009, 2013 g10 Code GmbH
3  *
4  * This file is part of GPGME.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "gpgme.h"
28 #include "util.h"
29 #include "priv-io.h"
30 #include "debug.h"
31 #include "sema.h"
32 #include "sys-util.h"
33
34 DEFINE_STATIC_LOCK (dirinfo_lock);
35
36 /* Constants used internally to select the data.  */
37 enum
38   {
39     WANT_HOMEDIR,
40     WANT_AGENT_SOCKET,
41     WANT_GPGCONF_NAME,
42     WANT_GPG_NAME,
43     WANT_GPGSM_NAME,
44     WANT_G13_NAME,
45     WANT_UISRV_SOCKET,
46     WANT_GPG_ONE_MODE
47   };
48
49 /* Values retrieved via gpgconf and cached here.  */
50 static struct {
51   int  valid;         /* Cached information is valid.  */
52   int  disable_gpgconf;
53   char *homedir;
54   char *agent_socket;
55   char *gpgconf_name;
56   char *gpg_name;
57   char *gpgsm_name;
58   char *g13_name;
59   char *uisrv_socket;
60   int  gpg_one_mode;  /* System is in gpg1 mode.  */
61 } dirinfo;
62
63
64 \f
65 /* Helper function to be used only by gpgme_set_global_flag.  */
66 void
67 _gpgme_dirinfo_disable_gpgconf (void)
68 {
69   dirinfo.disable_gpgconf = 1;
70 }
71
72
73 /* Parse the output of "gpgconf --list-dirs".  This function expects
74    that DIRINFO_LOCK is held by the caller.  If COMPONENTS is set, the
75    output of --list-components is expected. */
76 static void
77 parse_output (char *line, int components)
78 {
79   char *value, *p;
80
81   value = strchr (line, ':');
82   if (!value)
83     return;
84   *value++ = 0;
85   if (components)
86     {
87       /* Skip the second field.  */
88       value = strchr (value, ':');
89       if (!value)
90         return;
91       *value++ = 0;
92     }
93   p = strchr (value, ':');
94   if (p)
95     *p = 0;
96   if (_gpgme_decode_percent_string (value, &value, strlen (value)+1, 0))
97     return;
98   if (!*value)
99     return;
100
101   if (components)
102     {
103       if (!strcmp (line, "gpg") && !dirinfo.gpg_name)
104         dirinfo.gpg_name = strdup (value);
105       else if (!strcmp (line, "gpgsm") && !dirinfo.gpgsm_name)
106         dirinfo.gpgsm_name = strdup (value);
107       else if (!strcmp (line, "g13") && !dirinfo.g13_name)
108         dirinfo.g13_name = strdup (value);
109     }
110   else
111     {
112       if (!strcmp (line, "homedir") && !dirinfo.homedir)
113         {
114           const char name[] = "S.uiserver";
115
116           dirinfo.homedir = strdup (value);
117           if (dirinfo.homedir)
118             {
119               dirinfo.uisrv_socket = malloc (strlen (dirinfo
120                                                      .homedir)
121                                              + 1 + strlen (name) + 1);
122               if (dirinfo.uisrv_socket)
123                 strcpy (stpcpy (stpcpy (dirinfo.uisrv_socket, dirinfo.homedir),
124                                 DIRSEP_S), name);
125             }
126         }
127       else if (!strcmp (line, "agent-socket") && !dirinfo.agent_socket)
128         dirinfo.agent_socket = strdup (value);
129     }
130 }
131
132
133 /* Read the directory information from gpgconf.  This function expects
134    that DIRINFO_LOCK is held by the caller.  PGNAME is the name of the
135    gpgconf binary. If COMPONENTS is set, not the directories bit the
136    name of the componeNts are read. */
137 static void
138 read_gpgconf_dirs (const char *pgmname, int components)
139 {
140   char linebuf[1024] = {0};
141   int linelen = 0;
142   char * argv[3];
143   int rp[2];
144   struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */, -1, 0},
145                                    {-1, -1} };
146   int status;
147   int nread;
148   char *mark = NULL;
149
150   argv[0] = (char *)pgmname;
151   argv[1] = components? "--list-components" : "--list-dirs";
152   argv[2] = NULL;
153
154   if (_gpgme_io_pipe (rp, 1) < 0)
155     return;
156
157   cfd[0].fd = rp[1];
158
159   status = _gpgme_io_spawn (pgmname, argv, 0, cfd, NULL, NULL, NULL);
160   if (status < 0)
161     {
162       _gpgme_io_close (rp[0]);
163       _gpgme_io_close (rp[1]);
164       return;
165     }
166
167   do
168     {
169       nread = _gpgme_io_read (rp[0],
170                               linebuf + linelen,
171                               sizeof linebuf - linelen - 1);
172       if (nread > 0)
173         {
174           char *line;
175           const char *lastmark = NULL;
176           size_t nused;
177
178           linelen += nread;
179           linebuf[linelen] = '\0';
180
181           for (line=linebuf; (mark = strchr (line, '\n')); line = mark+1 )
182             {
183               lastmark = mark;
184               if (mark > line && mark[-1] == '\r')
185                 mark[-1] = '\0';
186               else
187                 mark[0] = '\0';
188
189               parse_output (line, components);
190             }
191
192           nused = lastmark? (lastmark + 1 - linebuf) : 0;
193           memmove (linebuf, linebuf + nused, linelen - nused);
194           linelen -= nused;
195         }
196     }
197   while (nread > 0 && linelen < sizeof linebuf - 1);
198
199   _gpgme_io_close (rp[0]);
200 }
201
202
203 static const char *
204 get_gpgconf_item (int what)
205 {
206   const char *result = NULL;
207
208   LOCK (dirinfo_lock);
209   if (!dirinfo.valid)
210     {
211       char *pgmname;
212
213       pgmname = dirinfo.disable_gpgconf? NULL : _gpgme_get_gpgconf_path ();
214       if (pgmname && access (pgmname, F_OK))
215         {
216           _gpgme_debug (DEBUG_INIT,
217                         "gpgme-dinfo: gpgconf='%s' [not installed]\n", pgmname);
218           free (pgmname);
219           pgmname = NULL; /* Not available.  */
220         }
221       else
222         _gpgme_debug (DEBUG_INIT, "gpgme-dinfo: gpgconf='%s'\n",
223                       pgmname? pgmname : "[null]");
224       if (!pgmname)
225         {
226           /* Probably gpgconf is not installed.  Assume we are using
227              GnuPG-1.  */
228           dirinfo.gpg_one_mode = 1;
229           pgmname = _gpgme_get_gpg_path ();
230           if (pgmname)
231             dirinfo.gpg_name = pgmname;
232         }
233       else
234         {
235           dirinfo.gpg_one_mode = 0;
236           read_gpgconf_dirs (pgmname, 0);
237           read_gpgconf_dirs (pgmname, 1);
238           dirinfo.gpgconf_name = pgmname;
239         }
240       /* Even if the reading of the directories failed (e.g. due to an
241          too old version gpgconf or no gpgconf at all), we need to
242          mark the entries as valid so that we won't try over and over
243          to read them.  Note further that we are not able to change
244          the read values later because they are practically statically
245          allocated.  */
246       dirinfo.valid = 1;
247       if (dirinfo.gpg_name)
248         _gpgme_debug (DEBUG_INIT, "gpgme-dinfo:     gpg='%s'\n",
249                       dirinfo.gpg_name);
250       if (dirinfo.g13_name)
251         _gpgme_debug (DEBUG_INIT, "gpgme-dinfo:     g13='%s'\n",
252                       dirinfo.g13_name);
253       if (dirinfo.gpgsm_name)
254         _gpgme_debug (DEBUG_INIT, "gpgme-dinfo:   gpgsm='%s'\n",
255                       dirinfo.gpgsm_name);
256       if (dirinfo.homedir)
257         _gpgme_debug (DEBUG_INIT, "gpgme-dinfo: homedir='%s'\n",
258                       dirinfo.homedir);
259       if (dirinfo.agent_socket)
260         _gpgme_debug (DEBUG_INIT, "gpgme-dinfo:   agent='%s'\n",
261                       dirinfo.agent_socket);
262       if (dirinfo.uisrv_socket)
263         _gpgme_debug (DEBUG_INIT, "gpgme-dinfo:   uisrv='%s'\n",
264                       dirinfo.uisrv_socket);
265     }
266   switch (what)
267     {
268     case WANT_HOMEDIR: result = dirinfo.homedir; break;
269     case WANT_AGENT_SOCKET: result = dirinfo.agent_socket; break;
270     case WANT_GPGCONF_NAME: result = dirinfo.gpgconf_name; break;
271     case WANT_GPG_NAME:   result = dirinfo.gpg_name; break;
272     case WANT_GPGSM_NAME: result = dirinfo.gpgsm_name; break;
273     case WANT_G13_NAME:   result = dirinfo.g13_name; break;
274     case WANT_UISRV_SOCKET:  result = dirinfo.uisrv_socket; break;
275     case WANT_GPG_ONE_MODE: result = dirinfo.gpg_one_mode? "1":NULL; break;
276     }
277   UNLOCK (dirinfo_lock);
278   return result;
279 }
280
281
282 /* Return the default home directory.   Returns NULL if not known.  */
283 const char *
284 _gpgme_get_default_homedir (void)
285 {
286   return get_gpgconf_item (WANT_HOMEDIR);
287 }
288
289 /* Return the default gpg-agent socket name.  Returns NULL if not known.  */
290 const char *
291 _gpgme_get_default_agent_socket (void)
292 {
293   return get_gpgconf_item (WANT_AGENT_SOCKET);
294 }
295
296 /* Return the default gpg file name.  Returns NULL if not known.  */
297 const char *
298 _gpgme_get_default_gpg_name (void)
299 {
300   return get_gpgconf_item (WANT_GPG_NAME);
301 }
302
303 /* Return the default gpgsm file name.  Returns NULL if not known.  */
304 const char *
305 _gpgme_get_default_gpgsm_name (void)
306 {
307   return get_gpgconf_item (WANT_GPGSM_NAME);
308 }
309
310 /* Return the default g13 file name.  Returns NULL if not known.  */
311 const char *
312 _gpgme_get_default_g13_name (void)
313 {
314   return get_gpgconf_item (WANT_G13_NAME);
315 }
316
317 /* Return the default gpgconf file name.  Returns NULL if not known.  */
318 const char *
319 _gpgme_get_default_gpgconf_name (void)
320 {
321   return get_gpgconf_item (WANT_GPGCONF_NAME);
322 }
323
324 /* Return the default UI-server socket name.  Returns NULL if not
325    known.  */
326 const char *
327 _gpgme_get_default_uisrv_socket (void)
328 {
329   return get_gpgconf_item (WANT_UISRV_SOCKET);
330 }
331
332 /* Return true if we are in GnuPG-1 mode - ie. no gpgconf and agent
333    being optional.  */
334 int
335 _gpgme_in_gpg_one_mode (void)
336 {
337   return !!get_gpgconf_item (WANT_GPG_ONE_MODE);
338 }
339
340
341
342 /* Helper function to return the basename of the passed filename.  */
343 const char *
344 _gpgme_get_basename (const char *name)
345 {
346   const char *s;
347
348   if (!name || !*name)
349     return name;
350   for (s = name + strlen (name) -1; s >= name; s--)
351     if (*s == '/'
352 #ifdef HAVE_W32_SYSTEM
353         || *s == '\\' || *s == ':'
354 #endif
355         )
356       return s+1;
357   return name;
358 }