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.c249
1 files changed, 125 insertions, 124 deletions
diff --git a/src/util/gnunet-helper-w32-console.c b/src/util/gnunet-helper-w32-console.c
index fdebd9a49..b773e27d7 100644
--- a/src/util/gnunet-helper-w32-console.c
+++ b/src/util/gnunet-helper-w32-console.c
@@ -11,12 +11,12 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 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/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 17
18 SPDX-License-Identifier: AGPL3.0-or-later 18 SPDX-License-Identifier: AGPL3.0-or-later
19*/ 19 */
20 20
21/** 21/**
22 * @file src/util/gnunet-helper-w32-console.c 22 * @file src/util/gnunet-helper-w32-console.c
@@ -45,9 +45,9 @@ static HANDLE parent_handle;
45 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 45 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
46 */ 46 */
47static int 47static int
48write_all (int output, 48write_all(int output,
49 const void *buf, 49 const void *buf,
50 size_t size) 50 size_t size)
51{ 51{
52 const char *cbuf = buf; 52 const char *cbuf = buf;
53 size_t total; 53 size_t total;
@@ -55,17 +55,18 @@ write_all (int output,
55 55
56 total = 0; 56 total = 0;
57 do 57 do
58 { 58 {
59 wr = write (output, 59 wr = write(output,
60 &cbuf[total], 60 &cbuf[total],
61 size - total); 61 size - total);
62 if (wr > 0) 62 if (wr > 0)
63 total += wr; 63 total += wr;
64 } while ( (wr > 0) && (total < size) ); 64 }
65 while ((wr > 0) && (total < size));
65 if (wr <= 0) 66 if (wr <= 0)
66 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 67 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
67 "Failed to write to stdout: %s\n", 68 "Failed to write to stdout: %s\n",
68 strerror (errno)); 69 strerror(errno));
69 return (total == size) ? GNUNET_OK : GNUNET_SYSERR; 70 return (total == size) ? GNUNET_OK : GNUNET_SYSERR;
70} 71}
71 72
@@ -80,24 +81,24 @@ write_all (int output,
80 * @return #GNUNET_SYSERR to stop scanning (the pipe was broken somehow) 81 * @return #GNUNET_SYSERR to stop scanning (the pipe was broken somehow)
81 */ 82 */
82static int 83static int
83write_message (int output, 84write_message(int output,
84 uint16_t message_type, 85 uint16_t message_type,
85 const char *data, 86 const char *data,
86 size_t data_length) 87 size_t data_length)
87{ 88{
88 struct GNUNET_MessageHeader hdr; 89 struct GNUNET_MessageHeader hdr;
89 90
90#if 0 91#if 0
91 fprintf (stderr, 92 fprintf(stderr,
92 "Helper sends %u-byte message of type %u\n", 93 "Helper sends %u-byte message of type %u\n",
93 (unsigned int) (sizeof (struct GNUNET_MessageHeader) + data_length), 94 (unsigned int)(sizeof(struct GNUNET_MessageHeader) + data_length),
94 (unsigned int) message_type); 95 (unsigned int)message_type);
95#endif 96#endif
96 hdr.type = htons (message_type); 97 hdr.type = htons(message_type);
97 hdr.size = htons (sizeof (struct GNUNET_MessageHeader) + data_length); 98 hdr.size = htons(sizeof(struct GNUNET_MessageHeader) + data_length);
98 if (GNUNET_OK != write_all (output, &hdr, sizeof (hdr))) 99 if (GNUNET_OK != write_all(output, &hdr, sizeof(hdr)))
99 return GNUNET_SYSERR; 100 return GNUNET_SYSERR;
100 if (GNUNET_OK != write_all (output, data, data_length)) 101 if (GNUNET_OK != write_all(output, data, data_length))
101 return GNUNET_SYSERR; 102 return GNUNET_SYSERR;
102 return GNUNET_OK; 103 return GNUNET_OK;
103} 104}
@@ -112,7 +113,7 @@ write_message (int output,
112 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 113 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
113 */ 114 */
114static int 115static int
115read_events (HANDLE console, int output_stream) 116read_events(HANDLE console, int output_stream)
116{ 117{
117 DWORD rr; 118 DWORD rr;
118 BOOL b; 119 BOOL b;
@@ -121,30 +122,30 @@ read_events (HANDLE console, int output_stream)
121 int result; 122 int result;
122 123
123 result = GNUNET_SYSERR; 124 result = GNUNET_SYSERR;
124 buf = malloc (sizeof (INPUT_RECORD) * buffer_size); 125 buf = malloc(sizeof(INPUT_RECORD) * buffer_size);
125 if (NULL == buf) 126 if (NULL == buf)
126 return result; 127 return result;
127 b = TRUE; 128 b = TRUE;
128 rr = 1; 129 rr = 1;
129 while (TRUE == b && 0 < rr) 130 while (TRUE == b && 0 < rr)
130 {
131 rr = 0;
132 b = ReadConsoleInput (console, buf, buffer_size, &rr);
133 if (FALSE == b && ERROR_SUCCESS != GetLastError ())
134 break;
135 for (i = 0; i < rr; i++)
136 { 131 {
137 int r; 132 rr = 0;
138 r = write_message (output_stream, 133 b = ReadConsoleInput(console, buf, buffer_size, &rr);
139 GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_INPUT, 134 if (FALSE == b && ERROR_SUCCESS != GetLastError())
140 (const char *) &buf[i], 135 break;
141 sizeof (INPUT_RECORD)); 136 for (i = 0; i < rr; i++)
142 if (GNUNET_OK != r) 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)
143 break; 147 break;
144 } 148 }
145 if (rr + 1 != i)
146 break;
147 }
148 return result; 149 return result;
149} 150}
150 151
@@ -158,7 +159,7 @@ read_events (HANDLE console, int output_stream)
158 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error 159 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
159 */ 160 */
160static int 161static int
161read_chars (HANDLE console, int output_stream) 162read_chars(HANDLE console, int output_stream)
162{ 163{
163 DWORD rr; 164 DWORD rr;
164 BOOL b; 165 BOOL b;
@@ -171,78 +172,78 @@ read_chars (HANDLE console, int output_stream)
171 int result; 172 int result;
172 173
173 result = GNUNET_SYSERR; 174 result = GNUNET_SYSERR;
174 buf = malloc (sizeof (wchar_t) * buffer_size); 175 buf = malloc(sizeof(wchar_t) * buffer_size);
175 if (NULL == buf) 176 if (NULL == buf)
176 return result; 177 return result;
177 small_ubuf = malloc (sizeof (char) * buffer_size * 2); 178 small_ubuf = malloc(sizeof(char) * buffer_size * 2);
178 if (NULL == small_ubuf) 179 if (NULL == small_ubuf)
179 { 180 {
180 free (buf); 181 free(buf);
181 return result; 182 return result;
182 } 183 }
183 b = TRUE; 184 b = TRUE;
184 rr = 1; 185 rr = 1;
185 while (TRUE == b) 186 while (TRUE == b)
186 {
187 large_ubuf = NULL;
188 rr = 0;
189 b = ReadConsoleW (console, buf, buffer_size, &rr, NULL);
190 if (FALSE == b && ERROR_SUCCESS != GetLastError ())
191 break;
192 if (0 == rr)
193 continue;
194 /* Caveat: if the UTF-16-encoded string is longer than BUFFER_SIZE,
195 * there's a possibility that we will read up to a word that constitutes
196 * a part of a multi-byte UTF-16 codepoint. Converting that to UTF-8
197 * will either drop invalid word (flags == 0) or bail out because of it
198 * (flags == WC_ERR_INVALID_CHARS).
199 */
200 conv = WideCharToMultiByte (CP_UTF8, 0, buf, rr, small_ubuf, 0, NULL, FALSE);
201 if (0 == conv || 0xFFFD == conv)
202 continue;
203 if (conv <= buffer_size * 2 - 1)
204 {
205 memset (small_ubuf, 0, buffer_size * 2);
206 conv = WideCharToMultiByte (CP_UTF8, 0, buf, rr, small_ubuf, buffer_size * 2 - 1, NULL, FALSE);
207 if (0 == conv || 0xFFFD == conv)
208 continue;
209 ubuf = small_ubuf;
210 }
211 else
212 { 187 {
213 large_ubuf = malloc (conv + 1); 188 large_ubuf = NULL;
214 if (NULL == large_ubuf) 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)
215 continue; 194 continue;
216 memset (large_ubuf, 0, conv + 1); 195 /* Caveat: if the UTF-16-encoded string is longer than BUFFER_SIZE,
217 conv = WideCharToMultiByte (CP_UTF8, 0, buf, rr, large_ubuf, conv, NULL, FALSE); 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);
218 if (0 == conv || 0xFFFD == conv) 202 if (0 == conv || 0xFFFD == conv)
219 {
220 free (large_ubuf);
221 large_ubuf = NULL;
222 continue; 203 continue;
223 } 204 if (conv <= buffer_size * 2 - 1)
224 ubuf = large_ubuf; 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;
225 } 235 }
226 r = write_message (output_stream, 236 free(small_ubuf);
227 GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS, 237 free(buf);
228 ubuf,
229 conv + 1);
230 if (large_ubuf)
231 free (large_ubuf);
232 if (GNUNET_OK != r)
233 break;
234 }
235 free (small_ubuf);
236 free (buf);
237 return result; 238 return result;
238} 239}
239 240
240 241
241DWORD WINAPI 242DWORD WINAPI
242watch_parent (LPVOID param) 243watch_parent(LPVOID param)
243{ 244{
244 WaitForSingleObject (parent_handle, INFINITE); 245 WaitForSingleObject(parent_handle, INFINITE);
245 ExitProcess (1); 246 ExitProcess(1);
246 return 0; 247 return 0;
247} 248}
248 249
@@ -257,62 +258,62 @@ watch_parent (LPVOID param)
257 * @return 0 on success 258 * @return 0 on success
258 */ 259 */
259int 260int
260main (int argc, 261main(int argc,
261 char *const *argv) 262 char *const *argv)
262{ 263{
263 HANDLE os_stdin; 264 HANDLE os_stdin;
264 DWORD parent_pid; 265 DWORD parent_pid;
266
265 /* We're using stdout to communicate binary data back to the parent; use 267 /* We're using stdout to communicate binary data back to the parent; use
266 * binary mode. 268 * binary mode.
267 */ 269 */
268 _setmode (1, _O_BINARY); 270 _setmode(1, _O_BINARY);
269 271
270 if (argc != 4) 272 if (argc != 4)
271 { 273 {
272 fprintf (stderr, 274 fprintf(stderr,
273 "Usage: gnunet-helper-w32-console <chars|events> <buffer size> <parent pid>\n"); 275 "Usage: gnunet-helper-w32-console <chars|events> <buffer size> <parent pid>\n");
274 return 2; 276 return 2;
275 } 277 }
276 278
277 if (0 == strcmp (argv[1], "chars")) 279 if (0 == strcmp(argv[1], "chars"))
278 chars = GNUNET_YES; 280 chars = GNUNET_YES;
279 else if (0 == strcmp (argv[1], "events")) 281 else if (0 == strcmp(argv[1], "events"))
280 chars = GNUNET_NO; 282 chars = GNUNET_NO;
281 else 283 else
282 return 3; 284 return 3;
283 285
284 buffer_size = strtoul (argv[2], NULL, 10); 286 buffer_size = strtoul(argv[2], NULL, 10);
285 if (buffer_size <= 0) 287 if (buffer_size <= 0)
286 return 4; 288 return 4;
287 289
288 parent_pid = (DWORD) strtoul (argv[3], NULL, 10); 290 parent_pid = (DWORD)strtoul(argv[3], NULL, 10);
289 if (parent_pid == 0) 291 if (parent_pid == 0)
290 return 5; 292 return 5;
291 parent_handle = OpenProcess (SYNCHRONIZE, FALSE, parent_pid); 293 parent_handle = OpenProcess(SYNCHRONIZE, FALSE, parent_pid);
292 if (NULL == parent_handle) 294 if (NULL == parent_handle)
293 return 6; 295 return 6;
294 296
295 CreateThread (NULL, 0, watch_parent, NULL, 0, NULL); 297 CreateThread(NULL, 0, watch_parent, NULL, 0, NULL);
296 298
297 if (0 == AttachConsole (ATTACH_PARENT_PROCESS)) 299 if (0 == AttachConsole(ATTACH_PARENT_PROCESS))
298 { 300 {
299 if (ERROR_ACCESS_DENIED != GetLastError ()) 301 if (ERROR_ACCESS_DENIED != GetLastError())
300 return 5; 302 return 5;
301 } 303 }
302 304
303 /* Helper API overrides stdin, so we just attach to the console that we 305 /* Helper API overrides stdin, so we just attach to the console that we
304 * inherited. If we did. 306 * inherited. If we did.
305 */ 307 */
306 os_stdin = CreateFile ("CONIN$", GENERIC_READ | GENERIC_WRITE, 308 os_stdin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
307 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); 309 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
308 if (INVALID_HANDLE_VALUE == os_stdin) 310 if (INVALID_HANDLE_VALUE == os_stdin)
309 return 1; 311 return 1;
310 312
311 if (GNUNET_NO == chars) 313 if (GNUNET_NO == chars)
312 return read_events (os_stdin, 1); 314 return read_events(os_stdin, 1);
313 else 315 else
314 return read_chars (os_stdin, 1); 316 return read_chars(os_stdin, 1);
315
316} 317}
317 318
318/* end of gnunet-helper-w32-console.c */ 319/* end of gnunet-helper-w32-console.c */