More W32 related changes
[gnupg.git] / common / homedir.c
1 /* homedir.c - Setup the home directory.
2  *      Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #include <config.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <fcntl.h>
26
27 #ifdef HAVE_W32_SYSTEM
28 #include <shlobj.h>
29 #ifndef CSIDL_APPDATA
30 #define CSIDL_APPDATA 0x001a
31 #endif
32 #ifndef CSIDL_LOCAL_APPDATA
33 #define CSIDL_LOCAL_APPDATA 0x001c
34 #endif
35 #ifndef CSIDL_FLAG_CREATE
36 #define CSIDL_FLAG_CREATE 0x8000
37 #endif
38 #endif /*HAVE_W32_SYSTEM*/
39
40
41
42 #include "util.h"
43 #include "sysutils.h"
44
45
46 /* This is a helper function to load a Windows function from either of
47    one DLLs. */
48 #ifdef HAVE_W32_SYSTEM
49 static HRESULT
50 w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e)
51 {
52   static int initialized;
53   static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPSTR);
54
55   if (!initialized)
56     {
57       static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL };
58       void *handle;
59       int i;
60
61       initialized = 1;
62
63       for (i=0, handle = NULL; !handle && dllnames[i]; i++)
64         {
65           handle = dlopen (dllnames[i], RTLD_LAZY);
66           if (handle)
67             {
68               func = dlsym (handle, "SHGetFolderPathA");
69               if (!func)
70                 {
71                   dlclose (handle);
72                   handle = NULL;
73                 }
74             }
75         }
76     }
77
78   if (func)
79     return func (a,b,c,d,e);
80   else
81     return -1;
82 }
83 #endif /*HAVE_W32_SYSTEM*/
84
85
86 /* Get the standard home directory.  In general this function should
87    not be used as it does not consider a registry value (under W32) or
88    the GNUPGHOME encironment variable.  It is better to use
89    default_homedir(). */
90 const char *
91 standard_homedir (void)
92 {
93 #ifdef HAVE_W32_SYSTEM
94   static const char *dir;
95
96   if (!dir)
97     {
98       char path[MAX_PATH];
99       
100       /* It might be better to use LOCAL_APPDATA because this is
101          defined as "non roaming" and thus more likely to be kept
102          locally.  For private keys this is desired.  However, given
103          that many users copy private keys anyway forth and back,
104          using a system roaming services might be better than to let
105          them do it manually.  A security conscious user will anyway
106          use the registry entry to have better control.  */
107       if (w32_shgetfolderpath (NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, 
108                                NULL, 0, path) >= 0) 
109         {
110           char *tmp = xmalloc (strlen (path) + 6 +1);
111           strcpy (stpcpy (tmp, path), "\\gnupg");
112           dir = tmp;
113           
114           /* Try to create the directory if it does not yet exists.  */
115           if (access (dir, F_OK))
116             CreateDirectory (dir, NULL);
117         }
118       else
119         dir = GNUPG_DEFAULT_HOMEDIR;
120     }
121   return dir;
122 #else/*!HAVE_W32_SYSTEM*/
123   return GNUPG_DEFAULT_HOMEDIR;
124 #endif /*!HAVE_W32_SYSTEM*/
125 }
126
127 /* Set up the default home directory.  The usual --homedir option
128    should be parsed later. */
129 const char *
130 default_homedir (void)
131 {
132   const char *dir;
133
134   dir = getenv ("GNUPGHOME");
135 #ifdef HAVE_W32_SYSTEM
136   if (!dir || !*dir)
137     {
138       static const char *saved_dir;
139       
140       if (!saved_dir)
141         {
142           if (!dir || !*dir)
143             {
144               char *tmp;
145
146               tmp = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG",
147                                               "HomeDir");
148               if (tmp && *tmp)
149                 {
150                   xfree (tmp);
151                   tmp = NULL;
152                 }
153               if (tmp)
154                 saved_dir = tmp;
155             }
156           
157           if (!saved_dir)
158             saved_dir = standard_homedir ();
159         }
160       dir = saved_dir;
161     }
162 #endif /*HAVE_W32_SYSTEM*/
163   if (!dir || !*dir)
164     dir = GNUPG_DEFAULT_HOMEDIR;
165
166   return dir;
167 }
168
169
170 #ifdef HAVE_W32_SYSTEM
171 static const char *
172 w32_rootdir (void)
173 {
174   static int got_dir;
175   static char dir[MAX_PATH+5];
176
177   if (!got_dir)
178     {
179       char *p;
180
181       if ( !GetModuleFileName ( NULL, dir, MAX_PATH) )
182         {
183           log_debug ("GetModuleFileName failed: %s\n", w32_strerror (0));
184           *dir = 0;
185         }
186       got_dir = 1;
187       p = strrchr (dir, DIRSEP_C);
188       if (p)
189         *p = 0;
190       else
191         {
192           log_debug ("bad filename `%s' returned for this process\n", dir);
193           *dir = 0; 
194         }
195     }
196
197   if (*dir)
198     return dir;
199   /* Fallback to the hardwired value. */
200   return GNUPG_LIBEXECDIR;
201 }
202 #endif /*HAVE_W32_SYSTEM*/
203
204
205
206
207 /* Return the name of the sysconfdir.  This is a static string.  This
208    function is required because under Windows we can't simply compile
209    it in.  */
210 const char *
211 gnupg_sysconfdir (void)
212 {
213 #ifdef HAVE_W32_SYSTEM
214   static char *name;
215
216   if (!name)
217     {
218       const char *s1, *s2;
219       s1 = w32_rootdir ();
220       s2 = DIRSEP_S "etc" DIRSEP_S "gnupg";
221       name = xmalloc (strlen (s1) + strlen (s2) + 1);
222       strcpy (stpcpy (name, s1), s2);
223     }
224   return name;
225 #else /*!HAVE_W32_SYSTEM*/
226   return GNUPG_SYSCONFDIR;
227 #endif /*!HAVE_W32_SYSTEM*/
228 }
229
230
231 const char *
232 gnupg_bindir (void)
233 {
234 #ifdef HAVE_W32_SYSTEM
235   return w32_rootdir ();
236 #else /*!HAVE_W32_SYSTEM*/
237   return GNUPG_BINDIR;
238 #endif /*!HAVE_W32_SYSTEM*/
239 }
240
241
242 /* Return the name of the libexec directory.  The name is allocated in
243    a static area on the first use.  This function won't fail. */
244 const char *
245 gnupg_libexecdir (void)
246 {
247 #ifdef HAVE_W32_SYSTEM
248   return w32_rootdir ();
249 #else /*!HAVE_W32_SYSTEM*/
250   return GNUPG_LIBEXECDIR;
251 #endif /*!HAVE_W32_SYSTEM*/
252 }
253
254 const char *
255 gnupg_libdir (void)
256 {
257 #ifdef HAVE_W32_SYSTEM
258   static char *name;
259
260   if (!name)
261     {
262       const char *s1, *s2;
263       s1 = w32_rootdir ();
264       s2 = DIRSEP_S "lib" DIRSEP_S "gnupg";
265       name = xmalloc (strlen (s1) + strlen (s2) + 1);
266       strcpy (stpcpy (name, s1), s2);
267     }
268   return name;
269 #else /*!HAVE_W32_SYSTEM*/
270   return GNUPG_LIBDIR;
271 #endif /*!HAVE_W32_SYSTEM*/
272 }
273
274 const char *
275 gnupg_datadir (void)
276 {
277 #ifdef HAVE_W32_SYSTEM
278   static char *name;
279
280   if (!name)
281     {
282       const char *s1, *s2;
283       s1 = w32_rootdir ();
284       s2 = DIRSEP_S "share" DIRSEP_S "gnupg";
285       name = xmalloc (strlen (s1) + strlen (s2) + 1);
286       strcpy (stpcpy (name, s1), s2);
287     }
288   return name;
289 #else /*!HAVE_W32_SYSTEM*/
290   return GNUPG_DATADIR;
291 #endif /*!HAVE_W32_SYSTEM*/
292 }
293
294
295 /* Return the file name of a helper tool.  WHICH is one of the
296    GNUPG_MODULE_NAME_foo constants.  */
297 const char *
298 gnupg_module_name (int which)
299 {
300   const char *s, *s2;
301
302 #define X(a,b) do {                                          \
303         static char *name;                                   \
304         if (!name)                                           \
305           {                                                  \
306             s = gnupg_ ## a ();                              \
307             s2 = DIRSEP_S b EXEEXT_S;                        \
308             name = xmalloc (strlen (s) + strlen (s2) + 1);   \
309             strcpy (stpcpy (name, s), s2);                   \
310           }                                                  \
311         return name;                                         \
312       } while (0)                                                     
313
314   switch (which)
315     {
316     case GNUPG_MODULE_NAME_AGENT:
317 #ifdef GNUPG_DEFAULT_AGENT
318       return GNUPG_DEFAULT_AGENT;
319 #else 
320       X(bindir, "gpg-agent");
321 #endif
322       
323     case GNUPG_MODULE_NAME_PINENTRY:
324 #ifdef GNUPG_DEFAULT_PINENTRY
325       return GNUPG_DEFAULT_PINENTRY;
326 #else 
327       X(bindir, "pinentry");
328 #endif
329
330     case GNUPG_MODULE_NAME_SCDAEMON:
331 #ifdef GNUPG_DEFAULT_SCDAEMON
332       return GNUPG_DEFAULT_SCDAEMON;
333 #else 
334       X(bindir, "scdaemon");
335 #endif
336
337     case GNUPG_MODULE_NAME_DIRMNGR:
338 #ifdef GNUPG_DEFAULT_DIRMNGR
339       return GNUPG_DEFAULT_DIRMNGR;
340 #else 
341       X(bindir, "dirmngr");
342 #endif
343
344     case GNUPG_MODULE_NAME_PROTECT_TOOL:
345 #ifdef GNUPG_DEFAULT_PROTECT_TOOL
346       return GNUPG_DEFAULT_PROTECT_TOOL;
347 #else 
348       X(libexecdir, "gpg-protect-tool");
349 #endif
350
351     default: 
352       BUG ();
353     }
354 #undef X
355 }