Add qemu 2.4.0
[kvmfornfv.git] / qemu / libcacard / vscclient.c
1 /*
2  * Tester for VSCARD protocol, client side.
3  *
4  * Can be used with ccid-card-passthru.
5  *
6  * Copyright (c) 2011 Red Hat.
7  * Written by Alon Levy.
8  *
9  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10  * See the COPYING.LIB file in the top-level directory.
11  */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #ifndef _WIN32
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <netdb.h>
20 #include <unistd.h>
21 #define closesocket(x) close(x)
22 #else
23 #include <getopt.h>
24 #endif
25
26 #include "glib-compat.h"
27
28 #include "vscard_common.h"
29
30 #include "vreader.h"
31 #include "vcard_emul.h"
32 #include "vevent.h"
33
34 static int verbose;
35
36 static void
37 print_byte_array(
38     uint8_t *arrBytes,
39     unsigned int nSize
40 ) {
41     int i;
42     for (i = 0; i < nSize; i++) {
43         printf("%02X ", arrBytes[i]);
44     }
45     printf("\n");
46 }
47
48 static void
49 print_usage(void) {
50     printf("vscclient [-c <certname> .. -e <emul_args> -d <level>%s] "
51             "<host> <port>\n",
52 #ifdef USE_PASSTHRU
53     " -p");
54     printf(" -p use passthrough mode\n");
55 #else
56    "");
57 #endif
58     vcard_emul_usage();
59 }
60
61 static GIOChannel *channel_socket;
62 static GByteArray *socket_to_send;
63 static CompatGMutex socket_to_send_lock;
64 static guint socket_tag;
65
66 static void
67 update_socket_watch(void);
68
69 static gboolean
70 do_socket_send(GIOChannel *source,
71                GIOCondition condition,
72                gpointer data)
73 {
74     gsize bw;
75     GError *err = NULL;
76
77     g_return_val_if_fail(socket_to_send->len != 0, FALSE);
78     g_return_val_if_fail(condition & G_IO_OUT, FALSE);
79
80     g_io_channel_write_chars(channel_socket,
81         (gchar *)socket_to_send->data, socket_to_send->len, &bw, &err);
82     if (err != NULL) {
83         g_error("Error while sending socket %s", err->message);
84         return FALSE;
85     }
86     g_byte_array_remove_range(socket_to_send, 0, bw);
87
88     if (socket_to_send->len == 0) {
89         update_socket_watch();
90         return FALSE;
91     }
92     return TRUE;
93 }
94
95 static gboolean
96 socket_prepare_sending(gpointer user_data)
97 {
98     update_socket_watch();
99
100     return FALSE;
101 }
102
103 static int
104 send_msg(
105     VSCMsgType type,
106     uint32_t reader_id,
107     const void *msg,
108     unsigned int length
109 ) {
110     VSCMsgHeader mhHeader;
111
112     g_mutex_lock(&socket_to_send_lock);
113
114     if (verbose > 10) {
115         printf("sending type=%d id=%u, len =%u (0x%x)\n",
116                type, reader_id, length, length);
117     }
118
119     mhHeader.type = htonl(type);
120     mhHeader.reader_id = 0;
121     mhHeader.length = htonl(length);
122     g_byte_array_append(socket_to_send, (guint8 *)&mhHeader, sizeof(mhHeader));
123     g_byte_array_append(socket_to_send, (guint8 *)msg, length);
124     g_idle_add(socket_prepare_sending, NULL);
125
126     g_mutex_unlock(&socket_to_send_lock);
127
128     return 0;
129 }
130
131 static VReader *pending_reader;
132 static CompatGMutex pending_reader_lock;
133 static CompatGCond pending_reader_condition;
134
135 #define MAX_ATR_LEN 40
136 static gpointer
137 event_thread(gpointer arg)
138 {
139     unsigned char atr[MAX_ATR_LEN];
140     int atr_len;
141     VEvent *event;
142     unsigned int reader_id;
143
144
145     while (1) {
146         const char *reader_name;
147
148         event = vevent_wait_next_vevent();
149         if (event == NULL) {
150             break;
151         }
152         reader_id = vreader_get_id(event->reader);
153         if (reader_id == VSCARD_UNDEFINED_READER_ID &&
154             event->type != VEVENT_READER_INSERT) {
155             /* ignore events from readers qemu has rejected */
156             /* if qemu is still deciding on this reader, wait to see if need to
157              * forward this event */
158             g_mutex_lock(&pending_reader_lock);
159             if (!pending_reader || (pending_reader != event->reader)) {
160                 /* wasn't for a pending reader, this reader has already been
161                  * rejected by qemu */
162                 g_mutex_unlock(&pending_reader_lock);
163                 vevent_delete(event);
164                 continue;
165             }
166             /* this reader hasn't been told its status from qemu yet, wait for
167              * that status */
168             while (pending_reader != NULL) {
169                 g_cond_wait(&pending_reader_condition, &pending_reader_lock);
170             }
171             g_mutex_unlock(&pending_reader_lock);
172             /* now recheck the id */
173             reader_id = vreader_get_id(event->reader);
174             if (reader_id == VSCARD_UNDEFINED_READER_ID) {
175                 /* this reader was rejected */
176                 vevent_delete(event);
177                 continue;
178             }
179             /* reader was accepted, now forward the event */
180         }
181         switch (event->type) {
182         case VEVENT_READER_INSERT:
183             /* tell qemu to insert a new CCID reader */
184             /* wait until qemu has responded to our first reader insert
185              * before we send a second. That way we won't confuse the responses
186              * */
187             g_mutex_lock(&pending_reader_lock);
188             while (pending_reader != NULL) {
189                 g_cond_wait(&pending_reader_condition, &pending_reader_lock);
190             }
191             pending_reader = vreader_reference(event->reader);
192             g_mutex_unlock(&pending_reader_lock);
193             reader_name = vreader_get_name(event->reader);
194             if (verbose > 10) {
195                 printf(" READER INSERT: %s\n", reader_name);
196             }
197             send_msg(VSC_ReaderAdd,
198                 reader_id, /* currerntly VSCARD_UNDEFINED_READER_ID */
199                 NULL, 0 /* TODO reader_name, strlen(reader_name) */);
200             break;
201         case VEVENT_READER_REMOVE:
202             /* future, tell qemu that an old CCID reader has been removed */
203             if (verbose > 10) {
204                 printf(" READER REMOVE: %u\n", reader_id);
205             }
206             send_msg(VSC_ReaderRemove, reader_id, NULL, 0);
207             break;
208         case VEVENT_CARD_INSERT:
209             /* get the ATR (intended as a response to a power on from the
210              * reader */
211             atr_len = MAX_ATR_LEN;
212             vreader_power_on(event->reader, atr, &atr_len);
213             /* ATR call functions as a Card Insert event */
214             if (verbose > 10) {
215                 printf(" CARD INSERT %u: ", reader_id);
216                 print_byte_array(atr, atr_len);
217             }
218             send_msg(VSC_ATR, reader_id, atr, atr_len);
219             break;
220         case VEVENT_CARD_REMOVE:
221             /* Card removed */
222             if (verbose > 10) {
223                 printf(" CARD REMOVE %u:\n", reader_id);
224             }
225             send_msg(VSC_CardRemove, reader_id, NULL, 0);
226             break;
227         default:
228             break;
229         }
230         vevent_delete(event);
231     }
232     return NULL;
233 }
234
235
236 static unsigned int
237 get_id_from_string(char *string, unsigned int default_id)
238 {
239     unsigned int id = atoi(string);
240
241     /* don't accidentally swith to zero because no numbers have been supplied */
242     if ((id == 0) && *string != '0') {
243         return default_id;
244     }
245     return id;
246 }
247
248 static int
249 on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
250 {
251     uint32_t *capabilities = (incoming->capabilities);
252     int num_capabilities =
253         1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
254     int i;
255
256     incoming->version = ntohl(incoming->version);
257     if (incoming->version != VSCARD_VERSION) {
258         if (verbose > 0) {
259             printf("warning: host has version %d, we have %d\n",
260                 verbose, VSCARD_VERSION);
261         }
262     }
263     if (incoming->magic != VSCARD_MAGIC) {
264         printf("unexpected magic: got %d, expected %d\n",
265             incoming->magic, VSCARD_MAGIC);
266         return -1;
267     }
268     for (i = 0 ; i < num_capabilities; ++i) {
269         capabilities[i] = ntohl(capabilities[i]);
270     }
271     /* Future: check capabilities */
272     /* remove whatever reader might be left in qemu,
273      * in case of an unclean previous exit. */
274     send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
275     /* launch the event_thread. This will trigger reader adds for all the
276      * existing readers */
277     g_thread_new("vsc/event", event_thread, NULL);
278     return 0;
279 }
280
281
282 enum {
283     STATE_HEADER,
284     STATE_MESSAGE,
285 };
286
287 #define APDUBufSize 270
288
289 static gboolean
290 do_socket_read(GIOChannel *source,
291                GIOCondition condition,
292                gpointer data)
293 {
294     int rv;
295     int dwSendLength;
296     int dwRecvLength;
297     uint8_t pbRecvBuffer[APDUBufSize];
298     static uint8_t pbSendBuffer[APDUBufSize];
299     VReaderStatus reader_status;
300     VReader *reader = NULL;
301     static VSCMsgHeader mhHeader;
302     VSCMsgError *error_msg;
303     GError *err = NULL;
304
305     static gchar *buf;
306     static gsize br, to_read;
307     static int state = STATE_HEADER;
308
309     if (state == STATE_HEADER && to_read == 0) {
310         buf = (gchar *)&mhHeader;
311         to_read = sizeof(mhHeader);
312     }
313
314     if (to_read > 0) {
315         g_io_channel_read_chars(source, (gchar *)buf, to_read, &br, &err);
316         if (err != NULL) {
317             g_error("error while reading: %s", err->message);
318         }
319         buf += br;
320         to_read -= br;
321         if (to_read != 0) {
322             return TRUE;
323         }
324     }
325
326     if (state == STATE_HEADER) {
327         mhHeader.type = ntohl(mhHeader.type);
328         mhHeader.reader_id = ntohl(mhHeader.reader_id);
329         mhHeader.length = ntohl(mhHeader.length);
330         if (verbose) {
331             printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
332                    mhHeader.type, mhHeader.reader_id, mhHeader.length,
333                    mhHeader.length);
334         }
335         switch (mhHeader.type) {
336         case VSC_APDU:
337         case VSC_Flush:
338         case VSC_Error:
339         case VSC_Init:
340             buf = (gchar *)pbSendBuffer;
341             to_read = mhHeader.length;
342             state = STATE_MESSAGE;
343             return TRUE;
344         default:
345             fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
346             return FALSE;
347         }
348     }
349
350     if (state == STATE_MESSAGE) {
351         switch (mhHeader.type) {
352         case VSC_APDU:
353             if (verbose) {
354                 printf(" recv APDU: ");
355                 print_byte_array(pbSendBuffer, mhHeader.length);
356             }
357             /* Transmit received APDU */
358             dwSendLength = mhHeader.length;
359             dwRecvLength = sizeof(pbRecvBuffer);
360             reader = vreader_get_reader_by_id(mhHeader.reader_id);
361             reader_status = vreader_xfr_bytes(reader,
362                                               pbSendBuffer, dwSendLength,
363                                               pbRecvBuffer, &dwRecvLength);
364             if (reader_status == VREADER_OK) {
365                 mhHeader.length = dwRecvLength;
366                 if (verbose) {
367                     printf(" send response: ");
368                     print_byte_array(pbRecvBuffer, mhHeader.length);
369                 }
370                 send_msg(VSC_APDU, mhHeader.reader_id,
371                          pbRecvBuffer, dwRecvLength);
372             } else {
373                 rv = reader_status; /* warning: not meaningful */
374                 send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
375             }
376             vreader_free(reader);
377             reader = NULL; /* we've freed it, don't use it by accident
378                               again */
379             break;
380         case VSC_Flush:
381             /* TODO: actually flush */
382             send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
383             break;
384         case VSC_Error:
385             error_msg = (VSCMsgError *) pbSendBuffer;
386             if (error_msg->code == VSC_SUCCESS) {
387                 g_mutex_lock(&pending_reader_lock);
388                 if (pending_reader) {
389                     vreader_set_id(pending_reader, mhHeader.reader_id);
390                     vreader_free(pending_reader);
391                     pending_reader = NULL;
392                     g_cond_signal(&pending_reader_condition);
393                 }
394                 g_mutex_unlock(&pending_reader_lock);
395                 break;
396             }
397             printf("warning: qemu refused to add reader\n");
398             if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
399                 /* clear pending reader, qemu can't handle any more */
400                 g_mutex_lock(&pending_reader_lock);
401                 if (pending_reader) {
402                     pending_reader = NULL;
403                     /* make sure the event loop doesn't hang */
404                     g_cond_signal(&pending_reader_condition);
405                 }
406                 g_mutex_unlock(&pending_reader_lock);
407             }
408             break;
409         case VSC_Init:
410             if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
411                 return FALSE;
412             }
413             break;
414         default:
415             g_assert_not_reached();
416             return FALSE;
417         }
418
419         state = STATE_HEADER;
420     }
421
422
423     return TRUE;
424 }
425
426 static gboolean
427 do_socket(GIOChannel *source,
428           GIOCondition condition,
429           gpointer data)
430 {
431     /* not sure if two watches work well with a single win32 sources */
432     if (condition & G_IO_OUT) {
433         if (!do_socket_send(source, condition, data)) {
434             return FALSE;
435         }
436     }
437
438     if (condition & G_IO_IN) {
439         if (!do_socket_read(source, condition, data)) {
440             return FALSE;
441         }
442     }
443
444     return TRUE;
445 }
446
447 static void
448 update_socket_watch(void)
449 {
450     gboolean out = socket_to_send->len > 0;
451
452     if (socket_tag != 0) {
453         g_source_remove(socket_tag);
454     }
455
456     socket_tag = g_io_add_watch(channel_socket,
457         G_IO_IN | (out ? G_IO_OUT : 0), do_socket, NULL);
458 }
459
460 static gboolean
461 do_command(GIOChannel *source,
462            GIOCondition condition,
463            gpointer data)
464 {
465     char *string;
466     VCardEmulError error;
467     static unsigned int default_reader_id;
468     unsigned int reader_id;
469     VReader *reader = NULL;
470     GError *err = NULL;
471
472     g_assert(condition & G_IO_IN);
473
474     reader_id = default_reader_id;
475     g_io_channel_read_line(source, &string, NULL, NULL, &err);
476     if (err != NULL) {
477         g_error("Error while reading command: %s", err->message);
478     }
479
480     if (string != NULL) {
481         if (strncmp(string, "exit", 4) == 0) {
482             /* remove all the readers */
483             VReaderList *list = vreader_get_reader_list();
484             VReaderListEntry *reader_entry;
485             printf("Active Readers:\n");
486             for (reader_entry = vreader_list_get_first(list); reader_entry;
487                  reader_entry = vreader_list_get_next(reader_entry)) {
488                 VReader *reader = vreader_list_get_reader(reader_entry);
489                 vreader_id_t reader_id;
490                 reader_id = vreader_get_id(reader);
491                 if (reader_id == -1) {
492                     continue;
493                 }
494                 /* be nice and signal card removal first (qemu probably should
495                  * do this itself) */
496                 if (vreader_card_is_present(reader) == VREADER_OK) {
497                     send_msg(VSC_CardRemove, reader_id, NULL, 0);
498                 }
499                 send_msg(VSC_ReaderRemove, reader_id, NULL, 0);
500             }
501             exit(0);
502         } else if (strncmp(string, "insert", 6) == 0) {
503             if (string[6] == ' ') {
504                 reader_id = get_id_from_string(&string[7], reader_id);
505             }
506             reader = vreader_get_reader_by_id(reader_id);
507             if (reader != NULL) {
508                 error = vcard_emul_force_card_insert(reader);
509                 printf("insert %s, returned %d\n",
510                        vreader_get_name(reader), error);
511             } else {
512                 printf("no reader by id %u found\n", reader_id);
513             }
514         } else if (strncmp(string, "remove", 6) == 0) {
515             if (string[6] == ' ') {
516                 reader_id = get_id_from_string(&string[7], reader_id);
517             }
518             reader = vreader_get_reader_by_id(reader_id);
519             if (reader != NULL) {
520                 error = vcard_emul_force_card_remove(reader);
521                 printf("remove %s, returned %d\n",
522                        vreader_get_name(reader), error);
523             } else {
524                 printf("no reader by id %u found\n", reader_id);
525             }
526         } else if (strncmp(string, "select", 6) == 0) {
527             if (string[6] == ' ') {
528                 reader_id = get_id_from_string(&string[7],
529                                                VSCARD_UNDEFINED_READER_ID);
530             }
531             if (reader_id != VSCARD_UNDEFINED_READER_ID) {
532                 reader = vreader_get_reader_by_id(reader_id);
533             }
534             if (reader) {
535                 printf("Selecting reader %u, %s\n", reader_id,
536                         vreader_get_name(reader));
537                 default_reader_id = reader_id;
538             } else {
539                 printf("Reader with id %u not found\n", reader_id);
540             }
541         } else if (strncmp(string, "debug", 5) == 0) {
542             if (string[5] == ' ') {
543                 verbose = get_id_from_string(&string[6], 0);
544             }
545             printf("debug level = %d\n", verbose);
546         } else if (strncmp(string, "list", 4) == 0) {
547             VReaderList *list = vreader_get_reader_list();
548             VReaderListEntry *reader_entry;
549             printf("Active Readers:\n");
550             for (reader_entry = vreader_list_get_first(list); reader_entry;
551                  reader_entry = vreader_list_get_next(reader_entry)) {
552                 VReader *reader = vreader_list_get_reader(reader_entry);
553                 vreader_id_t reader_id;
554                 reader_id = vreader_get_id(reader);
555                 if (reader_id == -1) {
556                     continue;
557                 }
558                 printf("%3u %s %s\n", reader_id,
559                        vreader_card_is_present(reader) == VREADER_OK ?
560                        "CARD_PRESENT" : "            ",
561                        vreader_get_name(reader));
562             }
563             printf("Inactive Readers:\n");
564             for (reader_entry = vreader_list_get_first(list); reader_entry;
565                  reader_entry = vreader_list_get_next(reader_entry)) {
566                 VReader *reader = vreader_list_get_reader(reader_entry);
567                 vreader_id_t reader_id;
568                 reader_id = vreader_get_id(reader);
569                 if (reader_id != -1) {
570                     continue;
571                 }
572
573                 printf("INA %s %s\n",
574                        vreader_card_is_present(reader) == VREADER_OK ?
575                        "CARD_PRESENT" : "            ",
576                        vreader_get_name(reader));
577             }
578             vreader_list_delete(list);
579         } else if (*string != 0) {
580             printf("valid commands:\n");
581             printf("insert [reader_id]\n");
582             printf("remove [reader_id]\n");
583             printf("select reader_id\n");
584             printf("list\n");
585             printf("debug [level]\n");
586             printf("exit\n");
587         }
588     }
589     vreader_free(reader);
590     printf("> ");
591     fflush(stdout);
592
593     return TRUE;
594 }
595
596
597 /* just for ease of parsing command line arguments. */
598 #define MAX_CERTS 100
599
600 static int
601 connect_to_qemu(
602     const char *host,
603     const char *port
604 ) {
605     struct addrinfo hints;
606     struct addrinfo *server = NULL;
607     int ret, sock;
608
609     sock = socket(AF_INET, SOCK_STREAM, 0);
610     if (sock < 0) {
611         /* Error */
612         fprintf(stderr, "Error opening socket!\n");
613         return -1;
614     }
615
616     memset(&hints, 0, sizeof(struct addrinfo));
617     hints.ai_family = AF_UNSPEC;
618     hints.ai_socktype = SOCK_STREAM;
619     hints.ai_flags = 0;
620     hints.ai_protocol = 0;          /* Any protocol */
621
622     ret = getaddrinfo(host, port, &hints, &server);
623
624     if (ret != 0) {
625         /* Error */
626         fprintf(stderr, "getaddrinfo failed\n");
627         goto cleanup_socket;
628     }
629
630     if (connect(sock, server->ai_addr, server->ai_addrlen) < 0) {
631         /* Error */
632         fprintf(stderr, "Could not connect\n");
633         goto cleanup_socket;
634     }
635     if (verbose) {
636         printf("Connected (sizeof Header=%zd)!\n", sizeof(VSCMsgHeader));
637     }
638
639     freeaddrinfo(server);
640     return sock;
641
642 cleanup_socket:
643     if (server) {
644         freeaddrinfo(server);
645     }
646     closesocket(sock);
647     return -1;
648 }
649
650 int
651 main(
652     int argc,
653     char *argv[]
654 ) {
655     GMainLoop *loop;
656     GIOChannel *channel_stdin;
657     char *qemu_host;
658     char *qemu_port;
659
660     VCardEmulOptions *command_line_options = NULL;
661
662     char *cert_names[MAX_CERTS];
663     char *emul_args = NULL;
664     int cert_count = 0;
665     int c, sock;
666
667 #ifdef _WIN32
668     WSADATA Data;
669
670     if (WSAStartup(MAKEWORD(2, 2), &Data) != 0) {
671         c = WSAGetLastError();
672         fprintf(stderr, "WSAStartup: %d\n", c);
673         return 1;
674     }
675 #endif
676 #if !GLIB_CHECK_VERSION(2, 31, 0)
677     if (!g_thread_supported()) {
678          g_thread_init(NULL);
679     }
680 #endif
681
682     while ((c = getopt(argc, argv, "c:e:pd:")) != -1) {
683         switch (c) {
684         case 'c':
685             if (cert_count >= MAX_CERTS) {
686                 printf("too many certificates (max = %d)\n", MAX_CERTS);
687                 exit(5);
688             }
689             cert_names[cert_count++] = optarg;
690             break;
691         case 'e':
692             emul_args = optarg;
693             break;
694         case 'p':
695             print_usage();
696             exit(4);
697             break;
698         case 'd':
699             verbose = get_id_from_string(optarg, 1);
700             break;
701         }
702     }
703
704     if (argc - optind != 2) {
705         print_usage();
706         exit(4);
707     }
708
709     if (cert_count > 0) {
710         char *new_args;
711         int len, i;
712         /* if we've given some -c options, we clearly we want do so some
713          * software emulation.  add that emulation now. this is NSS Emulator
714          * specific */
715         if (emul_args == NULL) {
716             emul_args = (char *)"db=\"/etc/pki/nssdb\"";
717         }
718 #define SOFT_STRING ",soft=(,Virtual Reader,CAC,,"
719              /* 2 == close paren & null */
720         len = strlen(emul_args) + strlen(SOFT_STRING) + 2;
721         for (i = 0; i < cert_count; i++) {
722             len += strlen(cert_names[i])+1; /* 1 == comma */
723         }
724         new_args = g_malloc(len);
725         strcpy(new_args, emul_args);
726         strcat(new_args, SOFT_STRING);
727         for (i = 0; i < cert_count; i++) {
728             strcat(new_args, cert_names[i]);
729             strcat(new_args, ",");
730         }
731         strcat(new_args, ")");
732         emul_args = new_args;
733     }
734     if (emul_args) {
735         command_line_options = vcard_emul_options(emul_args);
736     }
737
738     qemu_host = g_strdup(argv[argc - 2]);
739     qemu_port = g_strdup(argv[argc - 1]);
740     sock = connect_to_qemu(qemu_host, qemu_port);
741     if (sock == -1) {
742         fprintf(stderr, "error opening socket, exiting.\n");
743         exit(5);
744     }
745
746     socket_to_send = g_byte_array_new();
747     vcard_emul_init(command_line_options);
748     loop = g_main_loop_new(NULL, TRUE);
749
750     printf("> ");
751     fflush(stdout);
752
753 #ifdef _WIN32
754     channel_stdin = g_io_channel_win32_new_fd(STDIN_FILENO);
755 #else
756     channel_stdin = g_io_channel_unix_new(STDIN_FILENO);
757 #endif
758     g_io_add_watch(channel_stdin, G_IO_IN, do_command, NULL);
759 #ifdef _WIN32
760     channel_socket = g_io_channel_win32_new_socket(sock);
761 #else
762     channel_socket = g_io_channel_unix_new(sock);
763 #endif
764     g_io_channel_set_encoding(channel_socket, NULL, NULL);
765     /* we buffer ourself for thread safety reasons */
766     g_io_channel_set_buffered(channel_socket, FALSE);
767
768     /* Send init message, Host responds (and then we send reader attachments) */
769     VSCMsgInit init = {
770         .version = htonl(VSCARD_VERSION),
771         .magic = VSCARD_MAGIC,
772         .capabilities = {0}
773     };
774     send_msg(VSC_Init, 0, &init, sizeof(init));
775
776     g_main_loop_run(loop);
777     g_main_loop_unref(loop);
778
779     g_io_channel_unref(channel_stdin);
780     g_io_channel_unref(channel_socket);
781     g_byte_array_free(socket_to_send, TRUE);
782
783     closesocket(sock);
784     return 0;
785 }