diff options
author | LRN <lrn1986@gmail.com> | 2014-01-08 14:14:41 +0000 |
---|---|---|
committer | LRN <lrn1986@gmail.com> | 2014-01-08 14:14:41 +0000 |
commit | 39d0485fb4ec8cb5b3142c86130b276ed455cb65 (patch) | |
tree | 3adbcbcb6581eb804b4cde216a077d987a91b64a | |
parent | 0d2a0bf33883e452dd988a5b173428161e38b4af (diff) | |
download | gnunet-39d0485fb4ec8cb5b3142c86130b276ed455cb65.tar.gz gnunet-39d0485fb4ec8cb5b3142c86130b276ed455cb65.zip |
Add console hackery for gnunet-conversation on W32
-rw-r--r-- | src/conversation/gnunet-conversation.c | 132 | ||||
-rw-r--r-- | src/util/Makefile.am | 12 | ||||
-rwxr-xr-x | src/util/gnunet-helper-w32-console.c | 318 | ||||
-rwxr-xr-x | src/util/gnunet-helper-w32-console.h | 72 |
4 files changed, 511 insertions, 23 deletions
diff --git a/src/conversation/gnunet-conversation.c b/src/conversation/gnunet-conversation.c index a042629cc..3cb6cc05f 100644 --- a/src/conversation/gnunet-conversation.c +++ b/src/conversation/gnunet-conversation.c | |||
@@ -29,13 +29,25 @@ | |||
29 | #include "gnunet_gnsrecord_lib.h" | 29 | #include "gnunet_gnsrecord_lib.h" |
30 | #include "gnunet_conversation_service.h" | 30 | #include "gnunet_conversation_service.h" |
31 | #include "gnunet_namestore_service.h" | 31 | #include "gnunet_namestore_service.h" |
32 | 32 | #ifdef WINDOWS | |
33 | #include "../util/gnunet-helper-w32-console.h" | ||
34 | #endif | ||
33 | 35 | ||
34 | /** | 36 | /** |
35 | * Maximum length allowed for the command line input. | 37 | * Maximum length allowed for the command line input. |
36 | */ | 38 | */ |
37 | #define MAX_MESSAGE_LENGTH 1024 | 39 | #define MAX_MESSAGE_LENGTH 1024 |
38 | 40 | ||
41 | #define XSTRINGIFY(x) STRINGIFY(x) | ||
42 | |||
43 | #define STRINGIFY(x) (#x) | ||
44 | |||
45 | #ifdef WINDOWS | ||
46 | /** | ||
47 | * Helper that reads the console for us. | ||
48 | */ | ||
49 | struct GNUNET_HELPER_Handle *stdin_hlp; | ||
50 | #endif | ||
39 | 51 | ||
40 | /** | 52 | /** |
41 | * Possible states of the phone. | 53 | * Possible states of the phone. |
@@ -997,6 +1009,13 @@ static void | |||
997 | do_stop_task (void *cls, | 1009 | do_stop_task (void *cls, |
998 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 1010 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
999 | { | 1011 | { |
1012 | #ifdef WINDOWS | ||
1013 | if (NULL != stdin_hlp) | ||
1014 | { | ||
1015 | GNUNET_HELPER_stop (stdin_hlp, GNUNET_NO); | ||
1016 | stdin_hlp = NULL; | ||
1017 | } | ||
1018 | #endif | ||
1000 | if (NULL != call) | 1019 | if (NULL != call) |
1001 | { | 1020 | { |
1002 | GNUNET_CONVERSATION_call_stop (call); | 1021 | GNUNET_CONVERSATION_call_stop (call); |
@@ -1027,6 +1046,60 @@ do_stop_task (void *cls, | |||
1027 | phone_state = PS_ERROR; | 1046 | phone_state = PS_ERROR; |
1028 | } | 1047 | } |
1029 | 1048 | ||
1049 | static void | ||
1050 | handle_command_string (char *message, size_t str_len) | ||
1051 | { | ||
1052 | size_t i; | ||
1053 | const char *ptr; | ||
1054 | |||
1055 | if (0 == str_len) | ||
1056 | return; | ||
1057 | if (message[str_len - 1] == '\n') | ||
1058 | message[str_len - 1] = '\0'; | ||
1059 | if (message[str_len - 2] == '\r') | ||
1060 | message[str_len - 2] = '\0'; | ||
1061 | if (0 == strlen (message)) | ||
1062 | return; | ||
1063 | i = 0; | ||
1064 | while ((NULL != commands[i].command) && | ||
1065 | (0 != strncasecmp (commands[i].command, message, | ||
1066 | strlen (commands[i].command)))) | ||
1067 | i++; | ||
1068 | ptr = &message[strlen (commands[i].command)]; | ||
1069 | while (isspace ((int) *ptr)) | ||
1070 | ptr++; | ||
1071 | if ('\0' == *ptr) | ||
1072 | ptr = NULL; | ||
1073 | commands[i].Action (ptr); | ||
1074 | } | ||
1075 | |||
1076 | |||
1077 | #ifdef WINDOWS | ||
1078 | int | ||
1079 | console_reader_chars (void *cls, void *client, | ||
1080 | const struct GNUNET_MessageHeader *message) | ||
1081 | { | ||
1082 | char *chars; | ||
1083 | size_t str_size; | ||
1084 | switch (ntohs (message->type)) | ||
1085 | { | ||
1086 | case GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS: | ||
1087 | chars = (char *) &message[1]; | ||
1088 | str_size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader); | ||
1089 | if (chars[str_size - 1] != '\0') | ||
1090 | return GNUNET_SYSERR; | ||
1091 | /* FIXME: is it ok that we pass part of a const struct to | ||
1092 | * this function that may mangle the contents? | ||
1093 | */ | ||
1094 | handle_command_string (chars, str_size - 1); | ||
1095 | break; | ||
1096 | default: | ||
1097 | GNUNET_break (0); | ||
1098 | break; | ||
1099 | } | ||
1100 | return GNUNET_OK; | ||
1101 | } | ||
1102 | #endif | ||
1030 | 1103 | ||
1031 | /** | 1104 | /** |
1032 | * Task to handle commands from the terminal. | 1105 | * Task to handle commands from the terminal. |
@@ -1039,8 +1112,6 @@ handle_command (void *cls, | |||
1039 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 1112 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
1040 | { | 1113 | { |
1041 | char message[MAX_MESSAGE_LENGTH + 1]; | 1114 | char message[MAX_MESSAGE_LENGTH + 1]; |
1042 | const char *ptr; | ||
1043 | size_t i; | ||
1044 | 1115 | ||
1045 | handle_cmd_task = | 1116 | handle_cmd_task = |
1046 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | 1117 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, |
@@ -1050,23 +1121,7 @@ handle_command (void *cls, | |||
1050 | memset (message, 0, MAX_MESSAGE_LENGTH + 1); | 1121 | memset (message, 0, MAX_MESSAGE_LENGTH + 1); |
1051 | if (NULL == fgets (message, MAX_MESSAGE_LENGTH, stdin)) | 1122 | if (NULL == fgets (message, MAX_MESSAGE_LENGTH, stdin)) |
1052 | return; | 1123 | return; |
1053 | if (0 == strlen (message)) | 1124 | handle_command_string (message, strlen (message)); |
1054 | return; | ||
1055 | if (message[strlen (message) - 1] == '\n') | ||
1056 | message[strlen (message) - 1] = '\0'; | ||
1057 | if (0 == strlen (message)) | ||
1058 | return; | ||
1059 | i = 0; | ||
1060 | while ((NULL != commands[i].command) && | ||
1061 | (0 != strncasecmp (commands[i].command, message, | ||
1062 | strlen (commands[i].command)))) | ||
1063 | i++; | ||
1064 | ptr = &message[strlen (commands[i].command)]; | ||
1065 | while (isspace ((int) *ptr)) | ||
1066 | ptr++; | ||
1067 | if ('\0' == *ptr) | ||
1068 | ptr = NULL; | ||
1069 | commands[i].Action (ptr); | ||
1070 | } | 1125 | } |
1071 | 1126 | ||
1072 | 1127 | ||
@@ -1144,6 +1199,30 @@ run (void *cls, | |||
1144 | id = GNUNET_IDENTITY_connect (cfg, | 1199 | id = GNUNET_IDENTITY_connect (cfg, |
1145 | &identity_cb, | 1200 | &identity_cb, |
1146 | NULL); | 1201 | NULL); |
1202 | #ifdef WINDOWS | ||
1203 | if (stdin_fh == NULL) | ||
1204 | { | ||
1205 | static char cpid[64]; | ||
1206 | static char *args[] = {"gnunet-helper-w32-console.exe", "chars", | ||
1207 | XSTRINGIFY (MAX_MESSAGE_LENGTH), cpid, NULL}; | ||
1208 | snprintf (cpid, 64, "%d", GetCurrentProcessId ()); | ||
1209 | stdin_hlp = GNUNET_HELPER_start ( | ||
1210 | GNUNET_NO, | ||
1211 | "gnunet-helper-w32-console", | ||
1212 | args, | ||
1213 | console_reader_chars, | ||
1214 | NULL, | ||
1215 | NULL); | ||
1216 | if (NULL == stdin_hlp) | ||
1217 | { | ||
1218 | FPRINTF (stderr, | ||
1219 | "%s", | ||
1220 | _("Failed to start gnunet-helper-w32-console\n")); | ||
1221 | return; | ||
1222 | } | ||
1223 | } | ||
1224 | else | ||
1225 | #endif | ||
1147 | handle_cmd_task = | 1226 | handle_cmd_task = |
1148 | GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_UI, | 1227 | GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_UI, |
1149 | &handle_command, NULL); | 1228 | &handle_command, NULL); |
@@ -1171,13 +1250,22 @@ main (int argc, char *const *argv) | |||
1171 | 1, &GNUNET_GETOPT_set_uint, &line}, | 1250 | 1, &GNUNET_GETOPT_set_uint, &line}, |
1172 | GNUNET_GETOPT_OPTION_END | 1251 | GNUNET_GETOPT_OPTION_END |
1173 | }; | 1252 | }; |
1174 | int flags; | ||
1175 | int ret; | 1253 | int ret; |
1176 | 1254 | #ifndef WINDOWS | |
1255 | int flags; | ||
1177 | flags = fcntl (0, F_GETFL, 0); | 1256 | flags = fcntl (0, F_GETFL, 0); |
1178 | flags |= O_NONBLOCK; | 1257 | flags |= O_NONBLOCK; |
1179 | fcntl (0, F_SETFL, flags); | 1258 | fcntl (0, F_SETFL, flags); |
1180 | stdin_fh = GNUNET_DISK_get_handle_from_int_fd (0); | 1259 | stdin_fh = GNUNET_DISK_get_handle_from_int_fd (0); |
1260 | #else | ||
1261 | if (FILE_TYPE_CHAR == GetFileType ((HANDLE) _get_osfhandle (0))) | ||
1262 | { | ||
1263 | stdin_fh = NULL; | ||
1264 | } | ||
1265 | else | ||
1266 | stdin_fh = GNUNET_DISK_get_handle_from_int_fd (0); | ||
1267 | #endif | ||
1268 | |||
1181 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | 1269 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) |
1182 | return 2; | 1270 | return 2; |
1183 | ret = GNUNET_PROGRAM_run (argc, argv, | 1271 | ret = GNUNET_PROGRAM_run (argc, argv, |
diff --git a/src/util/Makefile.am b/src/util/Makefile.am index dcd2f9121..f8f6e2ede 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am | |||
@@ -25,6 +25,7 @@ libgnunetutilwin_la_LIBADD = \ | |||
25 | -lcomdlg32 -lgdi32 -liphlpapi | 25 | -lcomdlg32 -lgdi32 -liphlpapi |
26 | WINLIB = libgnunetutilwin.la | 26 | WINLIB = libgnunetutilwin.la |
27 | W32CAT = w32cat | 27 | W32CAT = w32cat |
28 | W32CONSOLEHELPER = gnunet-helper-w32-console | ||
28 | endif | 29 | endif |
29 | 30 | ||
30 | if !MINGW | 31 | if !MINGW |
@@ -38,6 +39,14 @@ endif | |||
38 | 39 | ||
39 | w32cat_SOURCES = w32cat.c | 40 | w32cat_SOURCES = w32cat.c |
40 | 41 | ||
42 | gnunet_helper_w32_console_SOURCES = \ | ||
43 | gnunet-helper-w32-console.c \ | ||
44 | gnunet-helper-w32-console.h | ||
45 | gnunet_helper_w32_console_LDADD = \ | ||
46 | $(top_builddir)/src/util/libgnunetutil.la | ||
47 | gnunet_helper_w32_console_DEPENDENCIES = \ | ||
48 | libgnunetutil.la | ||
49 | |||
41 | noinst_PROGRAMS = \ | 50 | noinst_PROGRAMS = \ |
42 | gnunet-config-diff \ | 51 | gnunet-config-diff \ |
43 | $(W32CAT) \ | 52 | $(W32CAT) \ |
@@ -126,7 +135,8 @@ endif | |||
126 | 135 | ||
127 | 136 | ||
128 | libexec_PROGRAMS = \ | 137 | libexec_PROGRAMS = \ |
129 | gnunet-service-resolver | 138 | gnunet-service-resolver \ |
139 | $(W32CONSOLEHELPER) | ||
130 | 140 | ||
131 | bin_SCRIPTS =\ | 141 | bin_SCRIPTS =\ |
132 | gnunet-qr | 142 | gnunet-qr |
diff --git a/src/util/gnunet-helper-w32-console.c b/src/util/gnunet-helper-w32-console.c new file mode 100755 index 000000000..60ffbe018 --- /dev/null +++ b/src/util/gnunet-helper-w32-console.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2014 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | 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 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
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 | |||
33 | static unsigned long buffer_size; | ||
34 | |||
35 | static int chars; | ||
36 | |||
37 | static 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 | */ | ||
47 | static int | ||
48 | write_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 | } while ( (wr > 0) && (total < size) ); | ||
65 | if (wr <= 0) | ||
66 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
67 | "Failed to write to stdout: %s\n", | ||
68 | strerror (errno)); | ||
69 | return (total == size) ? GNUNET_OK : GNUNET_SYSERR; | ||
70 | } | ||
71 | |||
72 | |||
73 | /** | ||
74 | * Write message to the master process. | ||
75 | * | ||
76 | * @param output the descriptor to write into | ||
77 | * @param message_type message type to use | ||
78 | * @param data data to append, NULL for none | ||
79 | * @param data_length number of bytes in @a data | ||
80 | * @return #GNUNET_SYSERR to stop scanning (the pipe was broken somehow) | ||
81 | */ | ||
82 | static int | ||
83 | write_message (int output, | ||
84 | uint16_t message_type, | ||
85 | const char *data, | ||
86 | size_t data_length) | ||
87 | { | ||
88 | struct GNUNET_MessageHeader hdr; | ||
89 | |||
90 | #if 0 | ||
91 | fprintf (stderr, | ||
92 | "Helper sends %u-byte message of type %u\n", | ||
93 | (unsigned int) (sizeof (struct GNUNET_MessageHeader) + data_length), | ||
94 | (unsigned int) message_type); | ||
95 | #endif | ||
96 | hdr.type = htons (message_type); | ||
97 | hdr.size = htons (sizeof (struct GNUNET_MessageHeader) + data_length); | ||
98 | if (GNUNET_OK != write_all (output, &hdr, sizeof (hdr))) | ||
99 | return GNUNET_SYSERR; | ||
100 | if (GNUNET_OK != write_all (output, data, data_length)) | ||
101 | return GNUNET_SYSERR; | ||
102 | return GNUNET_OK; | ||
103 | } | ||
104 | |||
105 | |||
106 | /** | ||
107 | * Main function of the helper process. Reads input events from console, | ||
108 | * writes messages, into stdout. | ||
109 | * | ||
110 | * @param console a handle to a console to read from | ||
111 | * @param output_stream a stream to write messages to | ||
112 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
113 | */ | ||
114 | static int | ||
115 | read_events (HANDLE console, int output_stream) | ||
116 | { | ||
117 | DWORD rr; | ||
118 | BOOL b; | ||
119 | INPUT_RECORD *buf; | ||
120 | DWORD i; | ||
121 | int result; | ||
122 | |||
123 | result = GNUNET_SYSERR; | ||
124 | buf = malloc (sizeof (INPUT_RECORD) * buffer_size); | ||
125 | if (NULL == buf) | ||
126 | return result; | ||
127 | b = TRUE; | ||
128 | rr = 1; | ||
129 | 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 | { | ||
137 | int r; | ||
138 | r = write_message (output_stream, | ||
139 | GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_INPUT, | ||
140 | (const char *) &buf[i], | ||
141 | sizeof (INPUT_RECORD)); | ||
142 | if (GNUNET_OK != r) | ||
143 | break; | ||
144 | } | ||
145 | if (rr + 1 != i) | ||
146 | break; | ||
147 | } | ||
148 | return result; | ||
149 | } | ||
150 | |||
151 | |||
152 | /** | ||
153 | * Main function of the helper process. Reads chars from console, | ||
154 | * writes messages, into stdout. | ||
155 | * | ||
156 | * @param console a handle to a console to read from | ||
157 | * @param output_stream a stream to write messages to | ||
158 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
159 | */ | ||
160 | static int | ||
161 | read_chars (HANDLE console, int output_stream) | ||
162 | { | ||
163 | DWORD rr; | ||
164 | BOOL b; | ||
165 | wchar_t *buf; | ||
166 | char *small_ubuf; | ||
167 | char *large_ubuf; | ||
168 | char *ubuf; | ||
169 | int conv; | ||
170 | int r; | ||
171 | int result; | ||
172 | |||
173 | result = GNUNET_SYSERR; | ||
174 | buf = malloc (sizeof (wchar_t) * buffer_size); | ||
175 | if (NULL == buf) | ||
176 | return result; | ||
177 | small_ubuf = malloc (sizeof (char) * buffer_size * 2); | ||
178 | if (NULL == small_ubuf) | ||
179 | { | ||
180 | free (buf); | ||
181 | return result; | ||
182 | } | ||
183 | b = TRUE; | ||
184 | rr = 1; | ||
185 | 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 | { | ||
213 | large_ubuf = malloc (conv + 1); | ||
214 | if (NULL == large_ubuf) | ||
215 | continue; | ||
216 | memset (large_ubuf, 0, conv + 1); | ||
217 | conv = WideCharToMultiByte (CP_UTF8, 0, buf, rr, large_ubuf, conv, NULL, FALSE); | ||
218 | if (0 == conv || 0xFFFD == conv) | ||
219 | { | ||
220 | free (large_ubuf); | ||
221 | large_ubuf = NULL; | ||
222 | continue; | ||
223 | } | ||
224 | ubuf = large_ubuf; | ||
225 | } | ||
226 | r = write_message (output_stream, | ||
227 | GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS, | ||
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 | } | ||
239 | |||
240 | |||
241 | DWORD WINAPI | ||
242 | watch_parent (LPVOID param) | ||
243 | { | ||
244 | WaitForSingleObject (parent_handle, INFINITE); | ||
245 | ExitProcess (1); | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | /** | ||
250 | * Main function of the helper process to extract meta data. | ||
251 | * | ||
252 | * @param argc should be 3 | ||
253 | * @param argv [0] our binary name | ||
254 | * [1] name of the file or directory to process | ||
255 | * [2] "-" to disable extraction, NULL for defaults, | ||
256 | * otherwise custom plugins to load from LE | ||
257 | * @return 0 on success | ||
258 | */ | ||
259 | int | ||
260 | main (int argc, | ||
261 | char *const *argv) | ||
262 | { | ||
263 | HANDLE os_stdin; | ||
264 | DWORD parent_pid; | ||
265 | /* We're using stdout to communicate binary data back to the parent; use | ||
266 | * binary mode. | ||
267 | */ | ||
268 | _setmode (1, _O_BINARY); | ||
269 | |||
270 | if (argc != 4) | ||
271 | { | ||
272 | fprintf (stderr, | ||
273 | "Usage: gnunet-helper-w32-console <chars|events> <buffer size> <parent pid>\n"); | ||
274 | return 2; | ||
275 | } | ||
276 | |||
277 | if (0 == strcmp (argv[1], "chars")) | ||
278 | chars = GNUNET_YES; | ||
279 | else if (0 == strcmp (argv[1], "events")) | ||
280 | chars = GNUNET_NO; | ||
281 | else | ||
282 | return 3; | ||
283 | |||
284 | buffer_size = strtoul (argv[2], NULL, 10); | ||
285 | if (buffer_size <= 0) | ||
286 | return 4; | ||
287 | |||
288 | parent_pid = (DWORD) strtoul (argv[3], NULL, 10); | ||
289 | if (parent_pid == 0) | ||
290 | return 5; | ||
291 | parent_handle = OpenProcess (SYNCHRONIZE, FALSE, parent_pid); | ||
292 | if (NULL == parent_handle) | ||
293 | return 6; | ||
294 | |||
295 | CreateThread (NULL, 0, watch_parent, NULL, 0, NULL); | ||
296 | |||
297 | if (0 == AttachConsole (ATTACH_PARENT_PROCESS)) | ||
298 | { | ||
299 | if (ERROR_ACCESS_DENIED != GetLastError ()) | ||
300 | return 5; | ||
301 | } | ||
302 | |||
303 | /* Helper API overrides stdin, so we just attach to the console that we | ||
304 | * inherited. If we did. | ||
305 | */ | ||
306 | os_stdin = CreateFile ("CONIN$", GENERIC_READ | GENERIC_WRITE, | ||
307 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); | ||
308 | if (INVALID_HANDLE_VALUE == os_stdin) | ||
309 | return 1; | ||
310 | |||
311 | if (GNUNET_NO == chars) | ||
312 | return read_events (os_stdin, 1); | ||
313 | else | ||
314 | return read_chars (os_stdin, 1); | ||
315 | |||
316 | } | ||
317 | |||
318 | /* end of gnunet-helper-w32-console.c */ | ||
diff --git a/src/util/gnunet-helper-w32-console.h b/src/util/gnunet-helper-w32-console.h new file mode 100755 index 000000000..df5316cdf --- /dev/null +++ b/src/util/gnunet-helper-w32-console.h | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2014 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | 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 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @author LRN | ||
23 | * @file src/util/gnunet-helper-w32-console.h | ||
24 | */ | ||
25 | #ifndef GNUNET_HELPER_W32_CONSOLE_H | ||
26 | #define GNUNET_HELPER_W32_CONSOLE_H | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "gnunet_crypto_lib.h" | ||
30 | #include "gnunet_common.h" | ||
31 | |||
32 | /** | ||
33 | * Input event from the console | ||
34 | */ | ||
35 | #define GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_INPUT 60000 | ||
36 | |||
37 | /** | ||
38 | * Chars from the console | ||
39 | */ | ||
40 | #define GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS 60001 | ||
41 | |||
42 | GNUNET_NETWORK_STRUCT_BEGIN | ||
43 | |||
44 | /** | ||
45 | * This is just a dump of the INPUT_RECORD structure. | ||
46 | */ | ||
47 | struct GNUNET_W32_CONSOLE_input | ||
48 | { | ||
49 | /** | ||
50 | * Type: GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_INPUT | ||
51 | */ | ||
52 | struct GNUNET_MessageHeader header; | ||
53 | |||
54 | INPUT_RECORD input_record GNUNET_PACKED; | ||
55 | }; | ||
56 | |||
57 | /** | ||
58 | * A header, followed by UTF8-encoded, 0-terminated string | ||
59 | */ | ||
60 | struct GNUNET_W32_CONSOLE_chars | ||
61 | { | ||
62 | /** | ||
63 | * Type: GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS | ||
64 | */ | ||
65 | struct GNUNET_MessageHeader header; | ||
66 | |||
67 | /* followed by a string */ | ||
68 | }; | ||
69 | |||
70 | GNUNET_NETWORK_STRUCT_END | ||
71 | |||
72 | #endif | ||