Added missing files
[gnupg.git] / common / homedir.c
1 /* homedir.c - Setup the home directory.
2  *      Copyright (C) 2004, 2006 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <fcntl.h>
25
26 #ifdef HAVE_W32_SYSTEM
27 #include <shlobj.h>
28 #ifndef CSIDL_APPDATA
29 #define CSIDL_APPDATA 0x001a
30 #endif
31 #ifndef CSIDL_LOCAL_APPDATA
32 #define CSIDL_LOCAL_APPDATA 0x001c
33 #endif
34 #ifndef CSIDL_FLAG_CREATE
35 #define CSIDL_FLAG_CREATE 0x8000
36 #endif
37 #endif /*HAVE_W32_SYSTEM*/
38
39
40
41 #include "util.h"
42 #include "sysutils.h"
43
44
45 /* This is a helper function to load a Windows function from either of
46    one DLLs. */
47 #ifdef HAVE_W32_SYSTEM
48 static HRESULT
49 w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e)
50 {
51   static int initialized;
52   static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPSTR);
53
54   if (!initialized)
55     {
56       static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL };
57       void *handle;
58       int i;
59
60       initialized = 1;
61
62       for (i=0, handle = NULL; !handle && dllnames[i]; i++)
63         {
64           handle = dlopen (dllnames[i], RTLD_LAZY);
65           if (handle)
66             {
67               func = dlsym (handle, "SHGetFolderPathA");
68               if (!func)
69                 {
70                   dlclose (handle);
71                   handle = NULL;
72                 }
73             }
74         }
75     }
76
77   if (func)
78     return func (a,b,c,d,e);
79   else
80     return -1;
81 }
82 #endif /*HAVE_W32_SYSTEM*/
83
84
85 /* Set up the default home directory.  The usual --homedir option
86    should be parsed later. */
87 const char *
88 default_homedir (void)
89 {
90   const char *dir;
91
92   dir = getenv("GNUPGHOME");
93 #ifdef HAVE_W32_SYSTEM
94   if (!dir || !*dir)
95     dir = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", "HomeDir");
96   if (!dir || !*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
115              exists.  */
116           if (access (dir, F_OK))
117             CreateDirectory (dir, NULL);
118         }
119     }
120 #endif /*HAVE_W32_SYSTEM*/
121   if (!dir || !*dir)
122     dir = GNUPG_DEFAULT_HOMEDIR;
123
124   return dir;
125 }