summaryrefslogtreecommitdiff
path: root/src/util/gnunet-helper-w32-console.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/gnunet-helper-w32-console.c')
-rw-r--r--src/util/gnunet-helper-w32-console.c319
1 files changed, 0 insertions, 319 deletions
diff --git a/src/util/gnunet-helper-w32-console.c b/src/util/gnunet-helper-w32-console.c
deleted file mode 100644
index b773e27d7..000000000
--- a/src/util/gnunet-helper-w32-console.c
+++ /dev/null
@@ -1,319 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2014 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file src/util/gnunet-helper-w32-console.c
23 * @brief Does blocking reads from the console, writes the results
24 * into stdout, turning blocking console I/O into non-blocking
25 * pipe I/O. For W32 only.
26 * @author LRN
27 */
28#include "platform.h"
29#include "gnunet_crypto_lib.h"
30#include "gnunet_common.h"
31#include "gnunet-helper-w32-console.h"
32
33static unsigned long buffer_size;
34
35static int chars;
36
37static HANDLE parent_handle;
38
39/**
40 * Write @a size bytes from @a buf into @a output.
41 *
42 * @param output the descriptor to write into
43 * @param buf buffer with data to write
44 * @param size number of bytes to write
45 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
46 */
47static int
48write_all(int output,
49 const void *buf,
50 size_t size)
51{
52 const char *cbuf = buf;
53 size_t total;
54 ssize_t wr;
55
56 total = 0;
57 do
58 {
59 wr = write(output,
60 &cbuf[total],
61 size - total);
62 if (wr > 0)
63 total += wr;
64 }
65 while ((wr > 0) && (total < size));
66 if (wr <= 0)
67 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
68 "Failed to write to stdout: %s\n",
69 strerror(errno));
70 return (total == size) ? GNUNET_OK : GNUNET_SYSERR;
71}
72
73
74/**
75 * Write message to the master process.
76 *
77 * @param output the descriptor to write into
78 * @param message_type message type to use
79 * @param data data to append, NULL for none
80 * @param data_length number of bytes in @a data
81 * @return #GNUNET_SYSERR to stop scanning (the pipe was broken somehow)
82 */
83static int
84write_message(int output,
85 uint16_t message_type,
86 const char *data,
87 size_t data_length)
88{
89 struct GNUNET_MessageHeader hdr;
90
91#if 0
92 fprintf(stderr,
93 "Helper sends %u-byte message of type %u\n",
94 (unsigned int)(sizeof(struct GNUNET_MessageHeader) + data_length),
95 (unsigned int)message_type);
96#endif
97 hdr.type = htons(message_type);
98 hdr.size = htons(sizeof(struct GNUNET_MessageHeader) + data_length);
99 if (GNUNET_OK != write_all(output, &hdr, sizeof(hdr)))
100 return GNUNET_SYSERR;
101 if (GNUNET_OK != write_all(output, data, data_length))
102 return GNUNET_SYSERR;
103 return GNUNET_OK;
104}
105
106
107/**
108 * Main function of the helper process. Reads input events from console,
109 * writes messages, into stdout.
110 *
111 * @param console a handle to a console to read from
112 * @param output_stream a stream to write messages to
113 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
114 */
115static int
116read_events(HANDLE console, int output_stream)
117{
118 DWORD rr;
119 BOOL b;
120 INPUT_RECORD *buf;
121 DWORD i;
122 int result;
123
124 result = GNUNET_SYSERR;
125 buf = malloc(sizeof(INPUT_RECORD) * buffer_size);
126 if (NULL == buf)
127 return result;
128 b = TRUE;
129 rr = 1;
130 while (TRUE == b && 0 < rr)
131 {
132 rr = 0;
133 b = ReadConsoleInput(console, buf, buffer_size, &rr);
134 if (FALSE == b && ERROR_SUCCESS != GetLastError())
135 break;
136 for (i = 0; i < rr; i++)
137 {
138 int r;
139 r = write_message(output_stream,
140 GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_INPUT,
141 (const char *)&buf[i],
142 sizeof(INPUT_RECORD));
143 if (GNUNET_OK != r)
144 break;
145 }
146 if (rr + 1 != i)
147 break;
148 }
149 return result;
150}
151
152
153/**
154 * Main function of the helper process. Reads chars from console,
155 * writes messages, into stdout.
156 *
157 * @param console a handle to a console to read from
158 * @param output_stream a stream to write messages to
159 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
160 */
161static int
162read_chars(HANDLE console, int output_stream)
163{
164 DWORD rr;
165 BOOL b;
166 wchar_t *buf;
167 char *small_ubuf;
168 char *large_ubuf;
169 char *ubuf;
170 int conv;
171 int r;
172 int result;
173
174 result = GNUNET_SYSERR;
175 buf = malloc(sizeof(wchar_t) * buffer_size);
176 if (NULL == buf)
177 return result;
178 small_ubuf = malloc(sizeof(char) * buffer_size * 2);
179 if (NULL == small_ubuf)
180 {
181 free(buf);
182 return result;
183 }
184 b = TRUE;
185 rr = 1;
186 while (TRUE == b)
187 {
188 large_ubuf = NULL;
189 rr = 0;
190 b = ReadConsoleW(console, buf, buffer_size, &rr, NULL);
191 if (FALSE == b && ERROR_SUCCESS != GetLastError())
192 break;
193 if (0 == rr)
194 continue;
195 /* Caveat: if the UTF-16-encoded string is longer than BUFFER_SIZE,
196 * there's a possibility that we will read up to a word that constitutes
197 * a part of a multi-byte UTF-16 codepoint. Converting that to UTF-8
198 * will either drop invalid word (flags == 0) or bail out because of it
199 * (flags == WC_ERR_INVALID_CHARS).
200 */
201 conv = WideCharToMultiByte(CP_UTF8, 0, buf, rr, small_ubuf, 0, NULL, FALSE);
202 if (0 == conv || 0xFFFD == conv)
203 continue;
204 if (conv <= buffer_size * 2 - 1)
205 {
206 memset(small_ubuf, 0, buffer_size * 2);
207 conv = WideCharToMultiByte(CP_UTF8, 0, buf, rr, small_ubuf, buffer_size * 2 - 1, NULL, FALSE);
208 if (0 == conv || 0xFFFD == conv)
209 continue;
210 ubuf = small_ubuf;
211 }
212 else
213 {
214 large_ubuf = malloc(conv + 1);
215 if (NULL == large_ubuf)
216 continue;
217 memset(large_ubuf, 0, conv + 1);
218 conv = WideCharToMultiByte(CP_UTF8, 0, buf, rr, large_ubuf, conv, NULL, FALSE);
219 if (0 == conv || 0xFFFD == conv)
220 {
221 free(large_ubuf);
222 large_ubuf = NULL;
223 continue;
224 }
225 ubuf = large_ubuf;
226 }
227 r = write_message(output_stream,
228 GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS,
229 ubuf,
230 conv + 1);
231 if (large_ubuf)
232 free(large_ubuf);
233 if (GNUNET_OK != r)
234 break;
235 }
236 free(small_ubuf);
237 free(buf);
238 return result;
239}
240
241
242DWORD WINAPI
243watch_parent(LPVOID param)
244{
245 WaitForSingleObject(parent_handle, INFINITE);
246 ExitProcess(1);
247 return 0;
248}
249
250/**
251 * Main function of the helper process to extract meta data.
252 *
253 * @param argc should be 3
254 * @param argv [0] our binary name
255 * [1] name of the file or directory to process
256 * [2] "-" to disable extraction, NULL for defaults,
257 * otherwise custom plugins to load from LE
258 * @return 0 on success
259 */
260int
261main(int argc,
262 char *const *argv)
263{
264 HANDLE os_stdin;
265 DWORD parent_pid;
266
267 /* We're using stdout to communicate binary data back to the parent; use
268 * binary mode.
269 */
270 _setmode(1, _O_BINARY);
271
272 if (argc != 4)
273 {
274 fprintf(stderr,
275 "Usage: gnunet-helper-w32-console <chars|events> <buffer size> <parent pid>\n");
276 return 2;
277 }
278
279 if (0 == strcmp(argv[1], "chars"))
280 chars = GNUNET_YES;
281 else if (0 == strcmp(argv[1], "events"))
282 chars = GNUNET_NO;
283 else
284 return 3;
285
286 buffer_size = strtoul(argv[2], NULL, 10);
287 if (buffer_size <= 0)
288 return 4;
289
290 parent_pid = (DWORD)strtoul(argv[3], NULL, 10);
291 if (parent_pid == 0)
292 return 5;
293 parent_handle = OpenProcess(SYNCHRONIZE, FALSE, parent_pid);
294 if (NULL == parent_handle)
295 return 6;
296
297 CreateThread(NULL, 0, watch_parent, NULL, 0, NULL);
298
299 if (0 == AttachConsole(ATTACH_PARENT_PROCESS))
300 {
301 if (ERROR_ACCESS_DENIED != GetLastError())
302 return 5;
303 }
304
305 /* Helper API overrides stdin, so we just attach to the console that we
306 * inherited. If we did.
307 */
308 os_stdin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
309 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
310 if (INVALID_HANDLE_VALUE == os_stdin)
311 return 1;
312
313 if (GNUNET_NO == chars)
314 return read_events(os_stdin, 1);
315 else
316 return read_chars(os_stdin, 1);
317}
318
319/* end of gnunet-helper-w32-console.c */