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 "util.h"
51 :
52 : /* This object is used to register memory cleanup functions.
53 : Technically they are not needed but they can avoid frequent
54 : questions about un-released memory. Note that we use the system
55 : malloc and not any wrappers. */
56 : struct mem_cleanup_item_s;
57 : typedef struct mem_cleanup_item_s *mem_cleanup_item_t;
58 :
59 : struct mem_cleanup_item_s
60 : {
61 : mem_cleanup_item_t next;
62 : void (*func) (void);
63 : };
64 :
65 : static mem_cleanup_item_t mem_cleanup_list;
66 :
67 :
68 : /* The default error source of the application. This is different
69 : from GPG_ERR_SOURCE_DEFAULT in that it does not depend on the
70 : source file and thus is usable in code shared by applications.
71 : Note that we need to initialize it because otherwise some linkers
72 : (OS X at least) won't find the symbol when linking the t-*.c
73 : files. */
74 : gpg_err_source_t default_errsource = 0;
75 :
76 :
77 : #ifdef HAVE_W32CE_SYSTEM
78 : static void parse_std_file_handles (int *argcp, char ***argvp);
79 : static void
80 : sleep_on_exit (void)
81 : {
82 : /* The sshd on CE swallows some of the command output. Sleeping a
83 : while usually helps. */
84 : Sleep (400);
85 : }
86 : #endif /*HAVE_W32CE_SYSTEM*/
87 :
88 :
89 : static void
90 1350 : run_mem_cleanup (void)
91 : {
92 : mem_cleanup_item_t next;
93 :
94 3729 : while (mem_cleanup_list)
95 : {
96 1029 : next = mem_cleanup_list->next;
97 1029 : mem_cleanup_list->func ();
98 1029 : free (mem_cleanup_list);
99 1029 : mem_cleanup_list = next;
100 : }
101 1350 : }
102 :
103 :
104 : void
105 1030 : register_mem_cleanup_func (void (*func)(void))
106 : {
107 : mem_cleanup_item_t item;
108 :
109 1030 : item = malloc (sizeof *item);
110 1030 : if (item)
111 : {
112 1030 : item->func = func;
113 1030 : item->next = mem_cleanup_list;
114 1030 : mem_cleanup_list = item;
115 : }
116 1030 : }
117 :
118 :
119 : /* If STRING is not NULL write string to es_stdout or es_stderr. MODE
120 : must be 1 or 2. If STRING is NULL flush the respective stream. */
121 : static int
122 33205 : writestring_via_estream (int mode, const char *string)
123 : {
124 33205 : if (mode == 1 || mode == 2)
125 : {
126 33205 : if (string)
127 33182 : return es_fputs (string, mode == 1? es_stdout : es_stderr);
128 : else
129 23 : return es_fflush (mode == 1? es_stdout : es_stderr);
130 : }
131 : else
132 0 : return -1;
133 : }
134 :
135 :
136 : /* This function should be the first called after main. */
137 : void
138 1349 : early_system_init (void)
139 : {
140 1349 : }
141 :
142 :
143 : /* This function is to be used early at program startup to make sure
144 : that some subsystems are initialized. This is in particular
145 : important for W32 to initialize the sockets so that our socket
146 : emulation code used directly as well as in libassuan may be used.
147 : It should best be called before any I/O is done so that setup
148 : required for logging is ready. ARGCP and ARGVP are the addresses
149 : of the parameters given to main. This function may modify them.
150 :
151 : This function should be called only via the macro
152 : init_common_subsystems.
153 :
154 : CAUTION: This might be called while running suid(root). */
155 : void
156 1349 : _init_common_subsystems (gpg_err_source_t errsource, int *argcp, char ***argvp)
157 : {
158 : /* Store the error source in a global variable. */
159 1349 : default_errsource = errsource;
160 :
161 1349 : atexit (run_mem_cleanup);
162 :
163 : /* Try to auto set the character set. */
164 1349 : set_native_charset (NULL);
165 :
166 : #ifdef HAVE_W32_SYSTEM
167 : /* For W32 we need to initialize the socket layer. This is because
168 : we use recv and send in libassuan as well as at some other
169 : places. */
170 : {
171 : WSADATA wsadat;
172 :
173 : WSAStartup (0x202, &wsadat);
174 : }
175 : #endif
176 :
177 : #ifdef HAVE_W32CE_SYSTEM
178 : /* Register the sleep exit function before the estream init so that
179 : the sleep will be called after the estream registered atexit
180 : function which flushes the left open estream streams and in
181 : particular es_stdout. */
182 : atexit (sleep_on_exit);
183 : #endif
184 :
185 : /* Initialize the Estream library. */
186 1349 : gpgrt_init ();
187 1349 : gpgrt_set_alloc_func (gcry_realloc);
188 : #ifdef USE_NPTH
189 3 : gpgrt_set_syscall_clamp (npth_unprotect, npth_protect);
190 : #endif
191 :
192 : /* Special hack for Windows CE: We extract some options from arg
193 : to setup the standard handles. */
194 : #ifdef HAVE_W32CE_SYSTEM
195 : parse_std_file_handles (argcp, argvp);
196 : #else
197 : (void)argcp;
198 : (void)argvp;
199 : #endif
200 :
201 : /* Access the standard estreams as early as possible. If we don't
202 : do this the original stdio streams may have been closed when
203 : _es_get_std_stream is first use and in turn it would connect to
204 : the bit bucket. */
205 : {
206 : int i;
207 5396 : for (i=0; i < 3; i++)
208 4047 : (void)_gpgrt_get_std_stream (i);
209 : }
210 :
211 : /* --version et al shall use estream as well. */
212 1349 : argparse_register_outfnc (writestring_via_estream);
213 1349 : }
214 :
215 :
216 :
217 : /* WindowsCE uses a very strange way of handling the standard streams.
218 : There is a function SetStdioPath to associate a standard stream
219 : with a file or a device but what we really want is to use pipes as
220 : standard streams. Despite that we implement pipes using a device,
221 : we would have some limitations on the number of open pipes due to
222 : the 3 character limit of device file name. Thus we don't take this
223 : path. Another option would be to install a file system driver with
224 : support for pipes; this would allow us to get rid of the device
225 : name length limitation. However, with GnuPG we can get away be
226 : redefining the standard streams and passing the handles to be used
227 : on the command line. This has also the advantage that it makes
228 : creating a process much easier and does not require the
229 : SetStdioPath set and restore game. The caller needs to pass the
230 : rendezvous ids using up to three options:
231 :
232 : -&S0=<rvid> -&S1=<rvid> -&S2=<rvid>
233 :
234 : They are all optional but they must be the first arguments on the
235 : command line. Parsing stops as soon as an invalid option is found.
236 : These rendezvous ids are then used to finish the pipe creation.*/
237 : #ifdef HAVE_W32CE_SYSTEM
238 : static void
239 : parse_std_file_handles (int *argcp, char ***argvp)
240 : {
241 : int argc = *argcp;
242 : char **argv = *argvp;
243 : const char *s;
244 : assuan_fd_t fd;
245 : int i;
246 : int fixup = 0;
247 :
248 : if (!argc)
249 : return;
250 :
251 : for (argc--, argv++; argc; argc--, argv++)
252 : {
253 : s = *argv;
254 : if (*s == '-' && s[1] == '&' && s[2] == 'S'
255 : && (s[3] == '0' || s[3] == '1' || s[3] == '2')
256 : && s[4] == '='
257 : && (strchr ("-01234567890", s[5]) || !strcmp (s+5, "null")))
258 : {
259 : if (s[5] == 'n')
260 : fd = ASSUAN_INVALID_FD;
261 : else
262 : fd = _assuan_w32ce_finish_pipe (atoi (s+5), s[3] != '0');
263 : _es_set_std_fd (s[3] - '0', (int)fd);
264 : fixup++;
265 : }
266 : else
267 : break;
268 : }
269 :
270 : if (fixup)
271 : {
272 : argc = *argcp;
273 : argc -= fixup;
274 : *argcp = argc;
275 :
276 : argv = *argvp;
277 : for (i=1; i < argc; i++)
278 : argv[i] = argv[i + fixup];
279 : for (; i < argc + fixup; i++)
280 : argv[i] = NULL;
281 : }
282 :
283 :
284 : }
285 : #endif /*HAVE_W32CE_SYSTEM*/
|