2 This file is part of GNUnet.
3 Copyright (C) 2014 GNUnet e.V.
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.
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.
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/>.
20 * @file src/util/gnunet-helper-w32-console.c
21 * @brief Does blocking reads from the console, writes the results
22 * into stdout, turning blocking console I/O into non-blocking
23 * pipe I/O. For W32 only.
27 #include "gnunet_crypto_lib.h"
28 #include "gnunet_common.h"
29 #include "gnunet-helper-w32-console.h"
31 static unsigned long buffer_size;
35 static HANDLE parent_handle;
38 * Write @a size bytes from @a buf into @a output.
40 * @param output the descriptor to write into
41 * @param buf buffer with data to write
42 * @param size number of bytes to write
43 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
46 write_all (int output,
50 const char *cbuf = buf;
62 } while ( (wr > 0) && (total < size) );
64 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
65 "Failed to write to stdout: %s\n",
67 return (total == size) ? GNUNET_OK : GNUNET_SYSERR;
72 * Write message to the master process.
74 * @param output the descriptor to write into
75 * @param message_type message type to use
76 * @param data data to append, NULL for none
77 * @param data_length number of bytes in @a data
78 * @return #GNUNET_SYSERR to stop scanning (the pipe was broken somehow)
81 write_message (int output,
82 uint16_t message_type,
86 struct GNUNET_MessageHeader hdr;
90 "Helper sends %u-byte message of type %u\n",
91 (unsigned int) (sizeof (struct GNUNET_MessageHeader) + data_length),
92 (unsigned int) message_type);
94 hdr.type = htons (message_type);
95 hdr.size = htons (sizeof (struct GNUNET_MessageHeader) + data_length);
96 if (GNUNET_OK != write_all (output, &hdr, sizeof (hdr)))
98 if (GNUNET_OK != write_all (output, data, data_length))
105 * Main function of the helper process. Reads input events from console,
106 * writes messages, into stdout.
108 * @param console a handle to a console to read from
109 * @param output_stream a stream to write messages to
110 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
113 read_events (HANDLE console, int output_stream)
121 result = GNUNET_SYSERR;
122 buf = malloc (sizeof (INPUT_RECORD) * buffer_size);
127 while (TRUE == b && 0 < rr)
130 b = ReadConsoleInput (console, buf, buffer_size, &rr);
131 if (FALSE == b && ERROR_SUCCESS != GetLastError ())
133 for (i = 0; i < rr; i++)
136 r = write_message (output_stream,
137 GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_INPUT,
138 (const char *) &buf[i],
139 sizeof (INPUT_RECORD));
151 * Main function of the helper process. Reads chars from console,
152 * writes messages, into stdout.
154 * @param console a handle to a console to read from
155 * @param output_stream a stream to write messages to
156 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
159 read_chars (HANDLE console, int output_stream)
171 result = GNUNET_SYSERR;
172 buf = malloc (sizeof (wchar_t) * buffer_size);
175 small_ubuf = malloc (sizeof (char) * buffer_size * 2);
176 if (NULL == small_ubuf)
187 b = ReadConsoleW (console, buf, buffer_size, &rr, NULL);
188 if (FALSE == b && ERROR_SUCCESS != GetLastError ())
192 /* Caveat: if the UTF-16-encoded string is longer than BUFFER_SIZE,
193 * there's a possibility that we will read up to a word that constitutes
194 * a part of a multi-byte UTF-16 codepoint. Converting that to UTF-8
195 * will either drop invalid word (flags == 0) or bail out because of it
196 * (flags == WC_ERR_INVALID_CHARS).
198 conv = WideCharToMultiByte (CP_UTF8, 0, buf, rr, small_ubuf, 0, NULL, FALSE);
199 if (0 == conv || 0xFFFD == conv)
201 if (conv <= buffer_size * 2 - 1)
203 memset (small_ubuf, 0, buffer_size * 2);
204 conv = WideCharToMultiByte (CP_UTF8, 0, buf, rr, small_ubuf, buffer_size * 2 - 1, NULL, FALSE);
205 if (0 == conv || 0xFFFD == conv)
211 large_ubuf = malloc (conv + 1);
212 if (NULL == large_ubuf)
214 memset (large_ubuf, 0, conv + 1);
215 conv = WideCharToMultiByte (CP_UTF8, 0, buf, rr, large_ubuf, conv, NULL, FALSE);
216 if (0 == conv || 0xFFFD == conv)
224 r = write_message (output_stream,
225 GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS,
240 watch_parent (LPVOID param)
242 WaitForSingleObject (parent_handle, INFINITE);
248 * Main function of the helper process to extract meta data.
250 * @param argc should be 3
251 * @param argv [0] our binary name
252 * [1] name of the file or directory to process
253 * [2] "-" to disable extraction, NULL for defaults,
254 * otherwise custom plugins to load from LE
255 * @return 0 on success
263 /* We're using stdout to communicate binary data back to the parent; use
266 _setmode (1, _O_BINARY);
271 "Usage: gnunet-helper-w32-console <chars|events> <buffer size> <parent pid>\n");
275 if (0 == strcmp (argv[1], "chars"))
277 else if (0 == strcmp (argv[1], "events"))
282 buffer_size = strtoul (argv[2], NULL, 10);
283 if (buffer_size <= 0)
286 parent_pid = (DWORD) strtoul (argv[3], NULL, 10);
289 parent_handle = OpenProcess (SYNCHRONIZE, FALSE, parent_pid);
290 if (NULL == parent_handle)
293 CreateThread (NULL, 0, watch_parent, NULL, 0, NULL);
295 if (0 == AttachConsole (ATTACH_PARENT_PROCESS))
297 if (ERROR_ACCESS_DENIED != GetLastError ())
301 /* Helper API overrides stdin, so we just attach to the console that we
302 * inherited. If we did.
304 os_stdin = CreateFile ("CONIN$", GENERIC_READ | GENERIC_WRITE,
305 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
306 if (INVALID_HANDLE_VALUE == os_stdin)
309 if (GNUNET_NO == chars)
310 return read_events (os_stdin, 1);
312 return read_chars (os_stdin, 1);
316 /* end of gnunet-helper-w32-console.c */