GNUnet  0.10.x
Functions | Variables
gnunet-helper-w32-console.c File Reference

Does blocking reads from the console, writes the results into stdout, turning blocking console I/O into non-blocking pipe I/O. More...

#include "platform.h"
#include "gnunet_crypto_lib.h"
#include "gnunet_common.h"
#include "gnunet-helper-w32-console.h"
Include dependency graph for gnunet-helper-w32-console.c:

Go to the source code of this file.

Functions

static int write_all (int output, const void *buf, size_t size)
 Write size bytes from buf into output. More...
 
static int write_message (int output, uint16_t message_type, const char *data, size_t data_length)
 Write message to the master process. More...
 
static int read_events (HANDLE console, int output_stream)
 Main function of the helper process. More...
 
static int read_chars (HANDLE console, int output_stream)
 Main function of the helper process. More...
 
DWORD WINAPI watch_parent (LPVOID param)
 
int main (int argc, char *const *argv)
 Main function of the helper process to extract meta data. More...
 

Variables

static unsigned long buffer_size
 
static int chars
 
static HANDLE parent_handle
 

Detailed Description

Does blocking reads from the console, writes the results into stdout, turning blocking console I/O into non-blocking pipe I/O.

For W32 only.

Author
LRN

Definition in file gnunet-helper-w32-console.c.

Function Documentation

◆ write_all()

static int write_all ( int  output,
const void *  buf,
size_t  size 
)
static

Write size bytes from buf into output.

Parameters
outputthe descriptor to write into
bufbuffer with data to write
sizenumber of bytes to write
Returns
GNUNET_OK on success, GNUNET_SYSERR on error

Definition at line 48 of file gnunet-helper-w32-console.c.

References buf, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_OK, and GNUNET_SYSERR.

Referenced by write_message().

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)
68  "Failed to write to stdout: %s\n",
69  strerror(errno));
70  return (total == size) ? GNUNET_OK : GNUNET_SYSERR;
71 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
static char buf[2048]
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static unsigned int size
Size of the "table".
Definition: peer.c:66
#define GNUNET_log(kind,...)
Here is the caller graph for this function:

◆ write_message()

static int write_message ( int  output,
uint16_t  message_type,
const char *  data,
size_t  data_length 
)
static

Write message to the master process.

Parameters
outputthe descriptor to write into
message_typemessage type to use
datadata to append, NULL for none
data_lengthnumber of bytes in data
Returns
GNUNET_SYSERR to stop scanning (the pipe was broken somehow)

Definition at line 84 of file gnunet-helper-w32-console.c.

References GNUNET_OK, GNUNET_SYSERR, GNUNET_MessageHeader::size, GNUNET_MessageHeader::type, and write_all().

Referenced by read_chars(), and read_events().

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 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static int write_all(int output, const void *buf, size_t size)
Write size bytes from buf into output.
Header for all communications.
uint32_t data
The data value.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_events()

static int read_events ( HANDLE  console,
int  output_stream 
)
static

Main function of the helper process.

Reads input events from console, writes messages, into stdout.

Parameters
consolea handle to a console to read from
output_streama stream to write messages to
Returns
GNUNET_OK on success, GNUNET_SYSERR on error

Definition at line 116 of file gnunet-helper-w32-console.c.

References buf, buffer_size, GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_INPUT, GNUNET_OK, GNUNET_SYSERR, result, and write_message().

Referenced by main().

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;
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 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_INPUT
Input event from the console.
static char buf[2048]
static int result
Global testing status.
static int write_message(int output, uint16_t message_type, const char *data, size_t data_length)
Write message to the master process.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static int output_stream
File descriptor we use for IPC with the parent.
static unsigned long buffer_size
Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_chars()

static int read_chars ( HANDLE  console,
int  output_stream 
)
static

Main function of the helper process.

Reads chars from console, writes messages, into stdout.

Parameters
consolea handle to a console to read from
output_streama stream to write messages to
Returns
GNUNET_OK on success, GNUNET_SYSERR on error

Definition at line 162 of file gnunet-helper-w32-console.c.

References buf, buffer_size, conv, GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS, GNUNET_OK, GNUNET_SYSERR, result, and write_message().

Referenced by main().

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  }
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 }
static GstElement * conv
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
static char buf[2048]
static int result
Global testing status.
#define GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS
Chars from the console.
static int write_message(int output, uint16_t message_type, const char *data, size_t data_length)
Write message to the master process.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static int output_stream
File descriptor we use for IPC with the parent.
static unsigned long buffer_size
Here is the call graph for this function:
Here is the caller graph for this function:

◆ watch_parent()

DWORD WINAPI watch_parent ( LPVOID  param)

Definition at line 243 of file gnunet-helper-w32-console.c.

References parent_handle.

Referenced by main().

244 {
245  WaitForSingleObject(parent_handle, INFINITE);
246  ExitProcess(1);
247  return 0;
248 }
static HANDLE parent_handle
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char *const *  argv 
)

Main function of the helper process to extract meta data.

Parameters
argcshould be 3
argv[0] our binary name [1] name of the file or directory to process [2] "-" to disable extraction, NULL for defaults, otherwise custom plugins to load from LE
Returns
0 on success

Definition at line 261 of file gnunet-helper-w32-console.c.

References buffer_size, chars, GNUNET_NO, GNUNET_YES, parent_handle, read_chars(), read_events(), and watch_parent().

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 }
#define GNUNET_NO
Definition: gnunet_common.h:81
static int read_events(HANDLE console, int output_stream)
Main function of the helper process.
static unsigned long buffer_size
static int read_chars(HANDLE console, int output_stream)
Main function of the helper process.
#define GNUNET_YES
Definition: gnunet_common.h:80
static HANDLE parent_handle
DWORD WINAPI watch_parent(LPVOID param)
static int chars
Here is the call graph for this function:

Variable Documentation

◆ buffer_size

unsigned long buffer_size
static

Definition at line 33 of file gnunet-helper-w32-console.c.

Referenced by main(), read_chars(), and read_events().

◆ chars

int chars
static

Definition at line 35 of file gnunet-helper-w32-console.c.

Referenced by handle_command_string(), and main().

◆ parent_handle

HANDLE parent_handle
static

Definition at line 37 of file gnunet-helper-w32-console.c.

Referenced by main(), and watch_parent().