Line data Source code
1 : /* init.c - Various initializations
2 : * Copyright (C) 2007 Free Software Foundation, Inc.
3 : *
4 : * This file is part of GnuPG.
5 : *
6 : * This file is free software; you can redistribute it and/or modify
7 : * it under the terms of either
8 : *
9 : * - the GNU Lesser General Public License as published by the Free
10 : * Software Foundation; either version 3 of the License, or (at
11 : * your option) any later version.
12 : *
13 : * or
14 : *
15 : * - the GNU General Public License as published by the Free
16 : * Software Foundation; either version 2 of the License, or (at
17 : * your option) any later version.
18 : *
19 : * or both in parallel, as here.
20 : *
21 : * This file is distributed in the hope that it will be useful,
22 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 : * GNU General Public License for more details.
25 : *
26 : * You should have received a copy of the GNU General Public License
27 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
28 : */
29 :
30 : #include <config.h>
31 :
32 : #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */
33 : #undef HAVE_NPTH
34 : #undef USE_NPTH
35 : #endif
36 :
37 : #ifdef HAVE_W32_SYSTEM
38 : # ifdef HAVE_WINSOCK2_H
39 : # include <winsock2.h>
40 : # endif
41 : # include <windows.h>
42 : #endif
43 : #ifdef HAVE_NPTH
44 : # include <npth.h>
45 : #endif
46 : #ifdef HAVE_W32CE_SYSTEM
47 : # include <assuan.h> /* For _assuan_w32ce_finish_pipe. */
48 : #endif
49 :
50 : #include <gcrypt.h>
51 : #include "util.h"
52 : #include "i18n.h"
53 :
54 : /* This object is used to register memory cleanup functions.
55 : Technically they are not needed but they can avoid frequent
56 : questions about un-released memory. Note that we use the system
57 : malloc and not any wrappers. */
58 : struct mem_cleanup_item_s;
59 : typedef struct mem_cleanup_item_s *mem_cleanup_item_t;
60 :
61 : struct mem_cleanup_item_s
62 : {
63 : mem_cleanup_item_t next;
64 : void (*func) (void);
65 : };
66 :
67 : static mem_cleanup_item_t mem_cleanup_list;
68 :
69 :
70 : /* The default error source of the application. This is different
71 : from GPG_ERR_SOURCE_DEFAULT in that it does not depend on the
72 : source file and thus is usable in code shared by applications.
73 : Note that we need to initialize it because otherwise some linkers
74 : (OS X at least) won't find the symbol when linking the t-*.c
75 : files. */
76 : gpg_err_source_t default_errsource = 0;
77 :
78 :
79 : #ifdef HAVE_W32CE_SYSTEM
80 : static void parse_std_file_handles (int *argcp, char ***argvp);
81 : static void
82 : sleep_on_exit (void)
83 : {
84 : /* The sshd on CE swallows some of the command output. Sleeping a
85 : while usually helps. */
86 : Sleep (400);
87 : }
88 : #endif /*HAVE_W32CE_SYSTEM*/
89 :
90 :
91 : static void
92 2386 : run_mem_cleanup (void)
93 : {
94 : mem_cleanup_item_t next;
95 :
96 5833 : while (mem_cleanup_list)
97 : {
98 1061 : next = mem_cleanup_list->next;
99 1061 : mem_cleanup_list->func ();
100 1061 : free (mem_cleanup_list);
101 1061 : mem_cleanup_list = next;
102 : }
103 2386 : }
104 :
105 :
106 : void
107 1063 : register_mem_cleanup_func (void (*func)(void))
108 : {
109 : mem_cleanup_item_t item;
110 :
111 1063 : for (item = mem_cleanup_list; item; item = item->next)
112 0 : if (item->func == func)
113 1063 : return; /* Function has already been registered. */
114 :
115 1063 : item = malloc (sizeof *item);
116 1063 : if (item)
117 : {
118 1063 : item->func = func;
119 1063 : item->next = mem_cleanup_list;
120 1063 : mem_cleanup_list = item;
121 : }
122 : }
123 :
124 :
125 : /* If STRING is not NULL write string to es_stdout or es_stderr. MODE
126 : must be 1 or 2. If STRING is NULL flush the respective stream. */
127 : static int
128 136663 : writestring_via_estream (int mode, const char *string)
129 : {
130 136663 : if (mode == 1 || mode == 2)
131 : {
132 136663 : if (string)
133 136654 : return es_fputs (string, mode == 1? es_stdout : es_stderr);
134 : else
135 9 : return es_fflush (mode == 1? es_stdout : es_stderr);
136 : }
137 : else
138 0 : return -1;
139 : }
140 :
141 :
142 : /* This function should be the first called after main. */
143 : void
144 2135 : early_system_init (void)
145 : {
146 2135 : }
147 :
148 :
149 : /* This function is to be used early at program startup to make sure
150 : that some subsystems are initialized. This is in particular
151 : important for W32 to initialize the sockets so that our socket
152 : emulation code used directly as well as in libassuan may be used.
153 : It should best be called before any I/O is done so that setup
154 : required for logging is ready. ARGCP and ARGVP are the addresses
155 : of the parameters given to main. This function may modify them.
156 :
157 : This function should be called only via the macro
158 : init_common_subsystems.
159 :
160 : CAUTION: This might be called while running suid(root). */
161 : void
162 2340 : _init_common_subsystems (gpg_err_source_t errsource, int *argcp, char ***argvp)
163 : {
164 : /* Store the error source in a global variable. */
165 2340 : default_errsource = errsource;
166 :
167 2340 : atexit (run_mem_cleanup);
168 :
169 : /* Try to auto set the character set. */
170 2340 : set_native_charset (NULL);
171 :
172 : #ifdef HAVE_W32_SYSTEM
173 : /* For W32 we need to initialize the socket layer. This is because
174 : we use recv and send in libassuan as well as at some other
175 : places. */
176 : {
177 : WSADATA wsadat;
178 :
179 : WSAStartup (0x202, &wsadat);
180 : }
181 : #endif
182 :
183 : #ifdef HAVE_W32CE_SYSTEM
184 : /* Register the sleep exit function before the estream init so that
185 : the sleep will be called after the estream registered atexit
186 : function which flushes the left open estream streams and in
187 : particular es_stdout. */
188 : atexit (sleep_on_exit);
189 : #endif
190 :
191 2340 : if (!gcry_check_version (NEED_LIBGCRYPT_VERSION))
192 : {
193 0 : log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
194 : NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL));
195 : }
196 :
197 : /* Initialize the Estream library. */
198 2340 : gpgrt_init ();
199 2340 : gpgrt_set_alloc_func (gcry_realloc);
200 : #ifdef USE_NPTH
201 48 : gpgrt_set_syscall_clamp (npth_unprotect, npth_protect);
202 : #endif
203 :
204 : /* Special hack for Windows CE: We extract some options from arg
205 : to setup the standard handles. */
206 : #ifdef HAVE_W32CE_SYSTEM
207 : parse_std_file_handles (argcp, argvp);
208 : #else
209 : (void)argcp;
210 : (void)argvp;
211 : #endif
212 :
213 : /* Access the standard estreams as early as possible. If we don't
214 : do this the original stdio streams may have been closed when
215 : _es_get_std_stream is first use and in turn it would connect to
216 : the bit bucket. */
217 : {
218 : int i;
219 9360 : for (i=0; i < 3; i++)
220 7020 : (void)_gpgrt_get_std_stream (i);
221 : }
222 :
223 : /* --version et al shall use estream as well. */
224 2340 : argparse_register_outfnc (writestring_via_estream);
225 :
226 : /* Logging shall use the standard socket directory as fallback. */
227 2340 : log_set_socket_dir_cb (gnupg_socketdir);
228 2340 : }
229 :
230 :
231 :
232 : /* WindowsCE uses a very strange way of handling the standard streams.
233 : There is a function SetStdioPath to associate a standard stream
234 : with a file or a device but what we really want is to use pipes as
235 : standard streams. Despite that we implement pipes using a device,
236 : we would have some limitations on the number of open pipes due to
237 : the 3 character limit of device file name. Thus we don't take this
238 : path. Another option would be to install a file system driver with
239 : support for pipes; this would allow us to get rid of the device
240 : name length limitation. However, with GnuPG we can get away be
241 : redefining the standard streams and passing the handles to be used
242 : on the command line. This has also the advantage that it makes
243 : creating a process much easier and does not require the
244 : SetStdioPath set and restore game. The caller needs to pass the
245 : rendezvous ids using up to three options:
246 :
247 : -&S0=<rvid> -&S1=<rvid> -&S2=<rvid>
248 :
249 : They are all optional but they must be the first arguments on the
250 : command line. Parsing stops as soon as an invalid option is found.
251 : These rendezvous ids are then used to finish the pipe creation.*/
252 : #ifdef HAVE_W32CE_SYSTEM
253 : static void
254 : parse_std_file_handles (int *argcp, char ***argvp)
255 : {
256 : int argc = *argcp;
257 : char **argv = *argvp;
258 : const char *s;
259 : assuan_fd_t fd;
260 : int i;
261 : int fixup = 0;
262 :
263 : if (!argc)
264 : return;
265 :
266 : for (argc--, argv++; argc; argc--, argv++)
267 : {
268 : s = *argv;
269 : if (*s == '-' && s[1] == '&' && s[2] == 'S'
270 : && (s[3] == '0' || s[3] == '1' || s[3] == '2')
271 : && s[4] == '='
272 : && (strchr ("-01234567890", s[5]) || !strcmp (s+5, "null")))
273 : {
274 : if (s[5] == 'n')
275 : fd = ASSUAN_INVALID_FD;
276 : else
277 : fd = _assuan_w32ce_finish_pipe (atoi (s+5), s[3] != '0');
278 : _es_set_std_fd (s[3] - '0', (int)fd);
279 : fixup++;
280 : }
281 : else
282 : break;
283 : }
284 :
285 : if (fixup)
286 : {
287 : argc = *argcp;
288 : argc -= fixup;
289 : *argcp = argc;
290 :
291 : argv = *argvp;
292 : for (i=1; i < argc; i++)
293 : argv[i] = argv[i + fixup];
294 : for (; i < argc + fixup; i++)
295 : argv[i] = NULL;
296 : }
297 :
298 :
299 : }
300 : #endif /*HAVE_W32CE_SYSTEM*/
|