[W32] Change location of /etc.
[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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdlib.h>
22 #include <errno.h>
23 #include <fcntl.h>
24
25 #ifdef HAVE_W32_SYSTEM
26 #include <shlobj.h>
27 #ifndef CSIDL_APPDATA
28 #define CSIDL_APPDATA 0x001a
29 #endif
30 #ifndef CSIDL_LOCAL_APPDATA
31 #define CSIDL_LOCAL_APPDATA 0x001c
32 #endif
33 #ifndef CSIDL_FLAG_CREATE
34 #define CSIDL_FLAG_CREATE 0x8000
35 #endif
36 #endif /*HAVE_W32_SYSTEM*/
37
38
39
40 #include "util.h"
41 #include "sysutils.h"
42
43
44 /* This is a helper function to load a Windows function from either of
45    one DLLs. */
46 #ifdef HAVE_W32_SYSTEM
47 static HRESULT
48 w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e)
49 {
50   static int initialized;
51   static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPSTR);
52
53   if (!initialized)
54     {
55       static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL };
56       void *handle;
57       int i;
58
59       initialized = 1;
60
61       for (i=0, handle = NULL; !handle && dllnames[i]; i++)
62         {
63           handle = dlopen (dllnames[i], RTLD_LAZY);
64           if (handle)
65             {
66               func = dlsym (handle, "SHGetFolderPathA");
67               if (!func)
68                 {
69                   dlclose (handle);
70                   handle = NULL;
71                 }
72             }
73         }
74     }
75
76   if (func)
77     return func (a,b,c,d,e);
78   else
79     return -1;
80 }
81 #endif /*HAVE_W32_SYSTEM*/
82
83
84 /* Get the standard home directory.  In general this function should
85    not be used as it does not consider a registry value (under W32) or
86    the GNUPGHOME encironment variable.  It is better to use
87    default_homedir(). */
88 const char *
89 standard_homedir (void)
90 {
91 #ifdef HAVE_W32_SYSTEM
92   static const char *dir;
93
94   if (!dir)
95     {
96       char path[MAX_PATH];
97       
98       /* It might be better to use LOCAL_APPDATA because this is
99          defined as "non roaming" and thus more likely to be kept
100          locally.  For private keys this is desired.  However, given
101          that many users copy private keys anyway forth and back,
102          using a system roaming services might be better than to let
103          them do it manually.  A security conscious user will anyway
104          use the registry entry to have better control.  */
105       if (w32_shgetfolderpath (NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, 
106                                NULL, 0, path) >= 0) 
107         {
108           char *tmp = xmalloc (strlen (path) + 6 +1);
109           strcpy (stpcpy (tmp, path), "\\gnupg");
110           dir = tmp;
111           
112           /* Try to create the directory if it does not yet exists.  */
113           if (access (dir, F_OK))
114             CreateDirectory (dir, NULL);
115         }
116       else
117         dir = GNUPG_DEFAULT_HOMEDIR;
118     }
119   return dir;
120 #else/*!HAVE_W32_SYSTEM*/
121   return GNUPG_DEFAULT_HOMEDIR;
122 #endif /*!HAVE_W32_SYSTEM*/
123 }
124
125 /* Set up the default home directory.  The usual --homedir option
126    should be parsed later. */
127 const char *
128 default_homedir (void)
129 {
130   const char *dir;
131
132   dir = getenv ("GNUPGHOME");
133 #ifdef HAVE_W32_SYSTEM
134   if (!dir || !*dir)
135     {
136       static const char *saved_dir;
137       
138       if (!saved_dir)
139         {
140           if (!dir || !*dir)
141             {
142               char *tmp;
143
144               tmp = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG",
145                                               "HomeDir");
146               if (tmp && !*tmp)
147                 {
148                   xfree (tmp);
149                   tmp = NULL;
150                 }
151               if (tmp)
152                 saved_dir = tmp;
153             }
154           
155           if (!saved_dir)
156             saved_dir = standard_homedir ();
157         }
158       dir = saved_dir;
159     }
160 #endif /*HAVE_W32_SYSTEM*/
161   if (!dir || !*dir)
162     dir = GNUPG_DEFAULT_HOMEDIR;
163
164   return dir;
165 }
166
167
168 #ifdef HAVE_W32_SYSTEM
169 static const char *
170 w32_rootdir (void)
171 {
172   static int got_dir;
173   static char dir[MAX_PATH+5];
174
175   if (!got_dir)
176     {
177       char *p;
178
179       if ( !GetModuleFileName ( NULL, dir, MAX_PATH) )
180         {
181           log_debug ("GetModuleFileName failed: %s\n", w32_strerror (0));
182           *dir = 0;
183         }
184       got_dir = 1;
185       p = strrchr (dir, DIRSEP_C);
186       if (p)
187         *p = 0;
188       else
189         {
190           log_debug ("bad filename `%s' returned for this process\n", dir);
191           *dir = 0; 
192         }
193     }
194
195   if (*dir)
196     return dir;
197   /* Fallback to the hardwired value. */
198   return GNUPG_LIBEXECDIR;
199 }
200
201 static const char *
202 w32_commondir (void)
203 {
204   static char *dir;
205
206   if (!dir)
207     {
208       char path[MAX_PATH];
209
210       if (w32_shgetfolderpath (NULL, CSIDL_COMMON_APPDATA, 
211                                NULL, 0, path) >= 0) 
212         {
213           char *tmp = xmalloc (strlen (path) + 4 +1);
214           strcpy (stpcpy (tmp, path), "\\GNU");
215           dir = tmp;
216           /* No auto create of the directory.  Either the installer or
217              the admin has to create these directories.  */
218         }
219       else
220         {
221           /* Ooops: Not defined - probably an old Windows version.
222              Use the installation directory instead.  */
223           dir = xstrdup (w32_rootdir ());
224         }
225     }
226   
227   return dir;
228 }
229 #endif /*HAVE_W32_SYSTEM*/
230
231
232
233
234 /* Return the name of the sysconfdir.  This is a static string.  This
235    function is required because under Windows we can't simply compile
236    it in.  */
237 const char *
238 gnupg_sysconfdir (void)
239 {
240 #ifdef HAVE_W32_SYSTEM
241   static char *name;
242
243   if (!name)
244     {
245       const char *s1, *s2;
246       s1 = w32_commondir ();
247       s2 = DIRSEP_S "etc" DIRSEP_S "gnupg";
248       name = xmalloc (strlen (s1) + strlen (s2) + 1);
249       strcpy (stpcpy (name, s1), s2);
250     }
251   return name;
252 #else /*!HAVE_W32_SYSTEM*/
253   return GNUPG_SYSCONFDIR;
254 #endif /*!HAVE_W32_SYSTEM*/
255 }
256
257
258 const char *
259 gnupg_bindir (void)
260 {
261 #ifdef HAVE_W32_SYSTEM
262   return w32_rootdir ();
263 #else /*!HAVE_W32_SYSTEM*/
264   return GNUPG_BINDIR;
265 #endif /*!HAVE_W32_SYSTEM*/
266 }
267
268
269 /* Return the name of the libexec directory.  The name is allocated in
270    a static area on the first use.  This function won't fail. */
271 const char *
272 gnupg_libexecdir (void)
273 {
274 #ifdef HAVE_W32_SYSTEM
275   return w32_rootdir ();
276 #else /*!HAVE_W32_SYSTEM*/
277   return GNUPG_LIBEXECDIR;
278 #endif /*!HAVE_W32_SYSTEM*/
279 }
280
281 const char *
282 gnupg_libdir (void)
283 {
284 #ifdef HAVE_W32_SYSTEM
285   static char *name;
286
287   if (!name)
288     {
289       const char *s1, *s2;
290       s1 = w32_rootdir ();
291       s2 = DIRSEP_S "lib" DIRSEP_S "gnupg";
292       name = xmalloc (strlen (s1) + strlen (s2) + 1);
293       strcpy (stpcpy (name, s1), s2);
294     }
295   return name;
296 #else /*!HAVE_W32_SYSTEM*/
297   return GNUPG_LIBDIR;
298 #endif /*!HAVE_W32_SYSTEM*/
299 }
300
301 const char *
302 gnupg_datadir (void)
303 {
304 #ifdef HAVE_W32_SYSTEM
305   static char *name;
306
307   if (!name)
308     {
309       const char *s1, *s2;
310       s1 = w32_rootdir ();
311       s2 = DIRSEP_S "share" DIRSEP_S "gnupg";
312       name = xmalloc (strlen (s1) + strlen (s2) + 1);
313       strcpy (stpcpy (name, s1), s2);
314     }
315   return name;
316 #else /*!HAVE_W32_SYSTEM*/
317   return GNUPG_DATADIR;
318 #endif /*!HAVE_W32_SYSTEM*/
319 }
320
321
322 /* Return the default socket name used by DirMngr. */
323 const char *
324 dirmngr_socket_name (void)
325 {
326 #ifdef HAVE_W32_SYSTEM
327   static char *name;
328
329   if (!name)
330     {
331       char s1[MAX_PATH];
332       const char *s2;
333
334       /* We need something akin CSIDL_COMMON_PROGRAMS, but local
335          (non-roaming).  */
336       if (w32_shgetfolderpath (NULL, CSIDL_WINDOWS, NULL, 0, s1) < 0)
337         strcpy (s1, "C:\\WINDOWS");
338       s2 = DIRSEP_S "S.dirmngr";
339       name = xmalloc (strlen (s1) + strlen (s2) + 1);
340       strcpy (stpcpy (name, s1), s2);
341     }
342   return name;
343 #else /*!HAVE_W32_SYSTEM*/
344   return "/var/run/dirmngr/socket";
345 #endif /*!HAVE_W32_SYSTEM*/
346 }
347
348
349
350 /* Return the file name of a helper tool.  WHICH is one of the
351    GNUPG_MODULE_NAME_foo constants.  */
352 const char *
353 gnupg_module_name (int which)
354 {
355   const char *s, *s2;
356
357 #define X(a,b) do {                                          \
358         static char *name;                                   \
359         if (!name)                                           \
360           {                                                  \
361             s = gnupg_ ## a ();                              \
362             s2 = DIRSEP_S b EXEEXT_S;                        \
363             name = xmalloc (strlen (s) + strlen (s2) + 1);   \
364             strcpy (stpcpy (name, s), s2);                   \
365           }                                                  \
366         return name;                                         \
367       } while (0)                                                     
368
369   switch (which)
370     {
371     case GNUPG_MODULE_NAME_AGENT:
372 #ifdef GNUPG_DEFAULT_AGENT
373       return GNUPG_DEFAULT_AGENT;
374 #else 
375       X(bindir, "gpg-agent");
376 #endif
377       
378     case GNUPG_MODULE_NAME_PINENTRY:
379 #ifdef GNUPG_DEFAULT_PINENTRY
380       return GNUPG_DEFAULT_PINENTRY;
381 #else 
382       X(bindir, "pinentry");
383 #endif
384
385     case GNUPG_MODULE_NAME_SCDAEMON:
386 #ifdef GNUPG_DEFAULT_SCDAEMON
387       return GNUPG_DEFAULT_SCDAEMON;
388 #else 
389       X(bindir, "scdaemon");
390 #endif
391
392     case GNUPG_MODULE_NAME_DIRMNGR:
393 #ifdef GNUPG_DEFAULT_DIRMNGR
394       return GNUPG_DEFAULT_DIRMNGR;
395 #else 
396       X(bindir, "dirmngr");
397 #endif
398
399     case GNUPG_MODULE_NAME_PROTECT_TOOL:
400 #ifdef GNUPG_DEFAULT_PROTECT_TOOL
401       return GNUPG_DEFAULT_PROTECT_TOOL;
402 #else 
403       X(libexecdir, "gpg-protect-tool");
404 #endif
405
406     case GNUPG_MODULE_NAME_CHECK_PATTERN:
407       X(libexecdir, "gpg-check-pattern");
408
409     case GNUPG_MODULE_NAME_GPGSM:
410       X(bindir, "gpgsm");
411
412     case GNUPG_MODULE_NAME_GPG:
413       X(bindir, "gpg2");
414
415     case GNUPG_MODULE_NAME_CONNECT_AGENT:
416       X(bindir, "gpg-connect-agent");
417
418     case GNUPG_MODULE_NAME_GPGCONF:
419       X(bindir, "gpgconf");
420
421     default: 
422       BUG ();
423     }
424 #undef X
425 }