diff options
Diffstat (limited to 'src/util/gnunet-helper-w32-console.c')
-rw-r--r-- | src/util/gnunet-helper-w32-console.c | 249 |
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 | */ |
47 | static int | 47 | static int |
48 | write_all (int output, | 48 | write_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 | */ |
82 | static int | 83 | static int |
83 | write_message (int output, | 84 | write_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 | */ |
114 | static int | 115 | static int |
115 | read_events (HANDLE console, int output_stream) | 116 | read_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 | */ |
160 | static int | 161 | static int |
161 | read_chars (HANDLE console, int output_stream) | 162 | read_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 | ||
241 | DWORD WINAPI | 242 | DWORD WINAPI |
242 | watch_parent (LPVOID param) | 243 | watch_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 | */ |
259 | int | 260 | int |
260 | main (int argc, | 261 | main(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 */ |