File: | qemu-char.c |
Location: | line 885, column 9 |
Description: | Access to field 'fd_in' results in a dereference of a null pointer (loaded from variable 's') |
1 | /* | |||
2 | * QEMU System Emulator | |||
3 | * | |||
4 | * Copyright (c) 2003-2008 Fabrice Bellard | |||
5 | * | |||
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
7 | * of this software and associated documentation files (the "Software"), to deal | |||
8 | * in the Software without restriction, including without limitation the rights | |||
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
10 | * copies of the Software, and to permit persons to whom the Software is | |||
11 | * furnished to do so, subject to the following conditions: | |||
12 | * | |||
13 | * The above copyright notice and this permission notice shall be included in | |||
14 | * all copies or substantial portions of the Software. | |||
15 | * | |||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
22 | * THE SOFTWARE. | |||
23 | */ | |||
24 | #include "qemu-common.h" | |||
25 | #include "monitor/monitor.h" | |||
26 | #include "ui/console.h" | |||
27 | #include "sysemu/sysemu.h" | |||
28 | #include "qemu/timer.h" | |||
29 | #include "sysemu/char.h" | |||
30 | #include "hw/usb.h" | |||
31 | #include "qmp-commands.h" | |||
32 | ||||
33 | #include <unistd.h> | |||
34 | #include <fcntl.h> | |||
35 | #include <time.h> | |||
36 | #include <errno(*__errno_location ()).h> | |||
37 | #include <sys/time.h> | |||
38 | #include <zlib.h> | |||
39 | ||||
40 | #ifndef _WIN32 | |||
41 | #include <sys/times.h> | |||
42 | #include <sys/wait.h> | |||
43 | #include <termios.h> | |||
44 | #include <sys/mman.h> | |||
45 | #include <sys/ioctl.h> | |||
46 | #include <sys/resource.h> | |||
47 | #include <sys/socket.h> | |||
48 | #include <netinet/in.h> | |||
49 | #include <net/if.h> | |||
50 | #include <arpa/inet.h> | |||
51 | #include <dirent.h> | |||
52 | #include <netdb.h> | |||
53 | #include <sys/select.h> | |||
54 | #ifdef CONFIG_BSD | |||
55 | #include <sys/stat.h> | |||
56 | #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) | |||
57 | #include <dev/ppbus/ppi.h> | |||
58 | #include <dev/ppbus/ppbconf.h> | |||
59 | #elif defined(__DragonFly__) | |||
60 | #include <dev/misc/ppi/ppi.h> | |||
61 | #include <bus/ppbus/ppbconf.h> | |||
62 | #endif | |||
63 | #else | |||
64 | #ifdef __linux__1 | |||
65 | #include <linux1/ppdev.h> | |||
66 | #include <linux1/parport.h> | |||
67 | #endif | |||
68 | #ifdef __sun__ | |||
69 | #include <sys/stat.h> | |||
70 | #include <sys/ethernet.h> | |||
71 | #include <sys/sockio.h> | |||
72 | #include <netinet/arp.h> | |||
73 | #include <netinet/in.h> | |||
74 | #include <netinet/in_systm.h> | |||
75 | #include <netinet/ip.h> | |||
76 | #include <netinet/ip_icmp.h> // must come after ip.h | |||
77 | #include <netinet/udp.h> | |||
78 | #include <netinet/tcp.h> | |||
79 | #endif | |||
80 | #endif | |||
81 | #endif | |||
82 | ||||
83 | #include "qemu/sockets.h" | |||
84 | #include "ui/qemu-spice.h" | |||
85 | ||||
86 | #define READ_BUF_LEN4096 4096 | |||
87 | ||||
88 | /***********************************************************/ | |||
89 | /* character device */ | |||
90 | ||||
91 | static QTAILQ_HEAD(CharDriverStateHead, CharDriverState)struct CharDriverStateHead { struct CharDriverState *tqh_first ; struct CharDriverState * *tqh_last; } chardevs = | |||
92 | QTAILQ_HEAD_INITIALIZER(chardevs){ ((void*)0), &(chardevs).tqh_first }; | |||
93 | ||||
94 | void qemu_chr_be_event(CharDriverState *s, int event) | |||
95 | { | |||
96 | /* Keep track if the char device is open */ | |||
97 | switch (event) { | |||
98 | case CHR_EVENT_OPENED2: | |||
99 | s->be_open = 1; | |||
100 | break; | |||
101 | case CHR_EVENT_CLOSED5: | |||
102 | s->be_open = 0; | |||
103 | break; | |||
104 | } | |||
105 | ||||
106 | if (!s->chr_event) | |||
107 | return; | |||
108 | s->chr_event(s->handler_opaque, event); | |||
109 | } | |||
110 | ||||
111 | void qemu_chr_be_generic_open(CharDriverState *s) | |||
112 | { | |||
113 | qemu_chr_be_event(s, CHR_EVENT_OPENED2); | |||
114 | } | |||
115 | ||||
116 | int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len) | |||
117 | { | |||
118 | return s->chr_write(s, buf, len); | |||
119 | } | |||
120 | ||||
121 | int qemu_chr_fe_write_all(CharDriverState *s, const uint8_t *buf, int len) | |||
122 | { | |||
123 | int offset = 0; | |||
124 | int res; | |||
125 | ||||
126 | while (offset < len) { | |||
127 | do { | |||
128 | res = s->chr_write(s, buf + offset, len - offset); | |||
129 | if (res == -1 && errno(*__errno_location ()) == EAGAIN11) { | |||
130 | g_usleep(100); | |||
131 | } | |||
132 | } while (res == -1 && errno(*__errno_location ()) == EAGAIN11); | |||
133 | ||||
134 | if (res == 0) { | |||
135 | break; | |||
136 | } | |||
137 | ||||
138 | if (res < 0) { | |||
139 | return res; | |||
140 | } | |||
141 | ||||
142 | offset += res; | |||
143 | } | |||
144 | ||||
145 | return offset; | |||
146 | } | |||
147 | ||||
148 | int qemu_chr_fe_ioctl(CharDriverState *s, int cmd, void *arg) | |||
149 | { | |||
150 | if (!s->chr_ioctl) | |||
151 | return -ENOTSUP95; | |||
152 | return s->chr_ioctl(s, cmd, arg); | |||
153 | } | |||
154 | ||||
155 | int qemu_chr_be_can_write(CharDriverState *s) | |||
156 | { | |||
157 | if (!s->chr_can_read) | |||
158 | return 0; | |||
159 | return s->chr_can_read(s->handler_opaque); | |||
160 | } | |||
161 | ||||
162 | void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len) | |||
163 | { | |||
164 | if (s->chr_read) { | |||
165 | s->chr_read(s->handler_opaque, buf, len); | |||
166 | } | |||
167 | } | |||
168 | ||||
169 | int qemu_chr_fe_get_msgfd(CharDriverState *s) | |||
170 | { | |||
171 | return s->get_msgfd ? s->get_msgfd(s) : -1; | |||
172 | } | |||
173 | ||||
174 | int qemu_chr_add_client(CharDriverState *s, int fd) | |||
175 | { | |||
176 | return s->chr_add_client ? s->chr_add_client(s, fd) : -1; | |||
177 | } | |||
178 | ||||
179 | void qemu_chr_accept_input(CharDriverState *s) | |||
180 | { | |||
181 | if (s->chr_accept_input) | |||
182 | s->chr_accept_input(s); | |||
183 | qemu_notify_event(); | |||
184 | } | |||
185 | ||||
186 | void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...) | |||
187 | { | |||
188 | char buf[READ_BUF_LEN4096]; | |||
189 | va_list ap; | |||
190 | va_start(ap, fmt)__builtin_va_start(ap, fmt); | |||
191 | vsnprintf(buf, sizeof(buf), fmt, ap); | |||
192 | qemu_chr_fe_write(s, (uint8_t *)buf, strlen(buf)); | |||
193 | va_end(ap)__builtin_va_end(ap); | |||
194 | } | |||
195 | ||||
196 | static void remove_fd_in_watch(CharDriverState *chr); | |||
197 | ||||
198 | void qemu_chr_add_handlers(CharDriverState *s, | |||
199 | IOCanReadHandler *fd_can_read, | |||
200 | IOReadHandler *fd_read, | |||
201 | IOEventHandler *fd_event, | |||
202 | void *opaque) | |||
203 | { | |||
204 | int fe_open; | |||
205 | ||||
206 | if (!opaque && !fd_can_read && !fd_read && !fd_event) { | |||
207 | fe_open = 0; | |||
208 | remove_fd_in_watch(s); | |||
209 | } else { | |||
210 | fe_open = 1; | |||
211 | } | |||
212 | s->chr_can_read = fd_can_read; | |||
213 | s->chr_read = fd_read; | |||
214 | s->chr_event = fd_event; | |||
215 | s->handler_opaque = opaque; | |||
216 | if (s->chr_update_read_handler) | |||
217 | s->chr_update_read_handler(s); | |||
218 | ||||
219 | if (!s->explicit_fe_open) { | |||
220 | qemu_chr_fe_set_open(s, fe_open); | |||
221 | } | |||
222 | ||||
223 | /* We're connecting to an already opened device, so let's make sure we | |||
224 | also get the open event */ | |||
225 | if (fe_open && s->be_open) { | |||
226 | qemu_chr_be_generic_open(s); | |||
227 | } | |||
228 | } | |||
229 | ||||
230 | static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len) | |||
231 | { | |||
232 | return len; | |||
233 | } | |||
234 | ||||
235 | static CharDriverState *qemu_chr_open_null(void) | |||
236 | { | |||
237 | CharDriverState *chr; | |||
238 | ||||
239 | chr = g_malloc0(sizeof(CharDriverState)); | |||
240 | chr->chr_write = null_chr_write; | |||
241 | chr->explicit_be_open = true1; | |||
242 | return chr; | |||
243 | } | |||
244 | ||||
245 | /* MUX driver for serial I/O splitting */ | |||
246 | #define MAX_MUX4 4 | |||
247 | #define MUX_BUFFER_SIZE32 32 /* Must be a power of 2. */ | |||
248 | #define MUX_BUFFER_MASK(32 - 1) (MUX_BUFFER_SIZE32 - 1) | |||
249 | typedef struct { | |||
250 | IOCanReadHandler *chr_can_read[MAX_MUX4]; | |||
251 | IOReadHandler *chr_read[MAX_MUX4]; | |||
252 | IOEventHandler *chr_event[MAX_MUX4]; | |||
253 | void *ext_opaque[MAX_MUX4]; | |||
254 | CharDriverState *drv; | |||
255 | int focus; | |||
256 | int mux_cnt; | |||
257 | int term_got_escape; | |||
258 | int max_size; | |||
259 | /* Intermediate input buffer allows to catch escape sequences even if the | |||
260 | currently active device is not accepting any input - but only until it | |||
261 | is full as well. */ | |||
262 | unsigned char buffer[MAX_MUX4][MUX_BUFFER_SIZE32]; | |||
263 | int prod[MAX_MUX4]; | |||
264 | int cons[MAX_MUX4]; | |||
265 | int timestamps; | |||
266 | int linestart; | |||
267 | int64_t timestamps_start; | |||
268 | } MuxDriver; | |||
269 | ||||
270 | ||||
271 | static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len) | |||
272 | { | |||
273 | MuxDriver *d = chr->opaque; | |||
274 | int ret; | |||
275 | if (!d->timestamps) { | |||
276 | ret = d->drv->chr_write(d->drv, buf, len); | |||
277 | } else { | |||
278 | int i; | |||
279 | ||||
280 | ret = 0; | |||
281 | for (i = 0; i < len; i++) { | |||
282 | if (d->linestart) { | |||
283 | char buf1[64]; | |||
284 | int64_t ti; | |||
285 | int secs; | |||
286 | ||||
287 | ti = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); | |||
288 | if (d->timestamps_start == -1) | |||
289 | d->timestamps_start = ti; | |||
290 | ti -= d->timestamps_start; | |||
291 | secs = ti / 1000; | |||
292 | snprintf(buf1, sizeof(buf1), | |||
293 | "[%02d:%02d:%02d.%03d] ", | |||
294 | secs / 3600, | |||
295 | (secs / 60) % 60, | |||
296 | secs % 60, | |||
297 | (int)(ti % 1000)); | |||
298 | d->drv->chr_write(d->drv, (uint8_t *)buf1, strlen(buf1)); | |||
299 | d->linestart = 0; | |||
300 | } | |||
301 | ret += d->drv->chr_write(d->drv, buf+i, 1); | |||
302 | if (buf[i] == '\n') { | |||
303 | d->linestart = 1; | |||
304 | } | |||
305 | } | |||
306 | } | |||
307 | return ret; | |||
308 | } | |||
309 | ||||
310 | static const char * const mux_help[] = { | |||
311 | "% h print this help\n\r", | |||
312 | "% x exit emulator\n\r", | |||
313 | "% s save disk data back to file (if -snapshot)\n\r", | |||
314 | "% t toggle console timestamps\n\r" | |||
315 | "% b send break (magic sysrq)\n\r", | |||
316 | "% c switch between console and monitor\n\r", | |||
317 | "% % sends %\n\r", | |||
318 | NULL((void*)0) | |||
319 | }; | |||
320 | ||||
321 | int term_escape_char = 0x01; /* ctrl-a is used for escape */ | |||
322 | static void mux_print_help(CharDriverState *chr) | |||
323 | { | |||
324 | int i, j; | |||
325 | char ebuf[15] = "Escape-Char"; | |||
326 | char cbuf[50] = "\n\r"; | |||
327 | ||||
328 | if (term_escape_char > 0 && term_escape_char < 26) { | |||
329 | snprintf(cbuf, sizeof(cbuf), "\n\r"); | |||
330 | snprintf(ebuf, sizeof(ebuf), "C-%c", term_escape_char - 1 + 'a'); | |||
331 | } else { | |||
332 | snprintf(cbuf, sizeof(cbuf), | |||
333 | "\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r", | |||
334 | term_escape_char); | |||
335 | } | |||
336 | chr->chr_write(chr, (uint8_t *)cbuf, strlen(cbuf)); | |||
337 | for (i = 0; mux_help[i] != NULL((void*)0); i++) { | |||
338 | for (j=0; mux_help[i][j] != '\0'; j++) { | |||
339 | if (mux_help[i][j] == '%') | |||
340 | chr->chr_write(chr, (uint8_t *)ebuf, strlen(ebuf)); | |||
341 | else | |||
342 | chr->chr_write(chr, (uint8_t *)&mux_help[i][j], 1); | |||
343 | } | |||
344 | } | |||
345 | } | |||
346 | ||||
347 | static void mux_chr_send_event(MuxDriver *d, int mux_nr, int event) | |||
348 | { | |||
349 | if (d->chr_event[mux_nr]) | |||
350 | d->chr_event[mux_nr](d->ext_opaque[mux_nr], event); | |||
351 | } | |||
352 | ||||
353 | static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch) | |||
354 | { | |||
355 | if (d->term_got_escape) { | |||
356 | d->term_got_escape = 0; | |||
357 | if (ch == term_escape_char) | |||
358 | goto send_char; | |||
359 | switch(ch) { | |||
360 | case '?': | |||
361 | case 'h': | |||
362 | mux_print_help(chr); | |||
363 | break; | |||
364 | case 'x': | |||
365 | { | |||
366 | const char *term = "QEMU: Terminated\n\r"; | |||
367 | chr->chr_write(chr,(uint8_t *)term,strlen(term)); | |||
368 | exit(0); | |||
369 | break; | |||
370 | } | |||
371 | case 's': | |||
372 | bdrv_commit_all(); | |||
373 | break; | |||
374 | case 'b': | |||
375 | qemu_chr_be_event(chr, CHR_EVENT_BREAK0); | |||
376 | break; | |||
377 | case 'c': | |||
378 | /* Switch to the next registered device */ | |||
379 | mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT4); | |||
380 | d->focus++; | |||
381 | if (d->focus >= d->mux_cnt) | |||
382 | d->focus = 0; | |||
383 | mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN3); | |||
384 | break; | |||
385 | case 't': | |||
386 | d->timestamps = !d->timestamps; | |||
387 | d->timestamps_start = -1; | |||
388 | d->linestart = 0; | |||
389 | break; | |||
390 | } | |||
391 | } else if (ch == term_escape_char) { | |||
392 | d->term_got_escape = 1; | |||
393 | } else { | |||
394 | send_char: | |||
395 | return 1; | |||
396 | } | |||
397 | return 0; | |||
398 | } | |||
399 | ||||
400 | static void mux_chr_accept_input(CharDriverState *chr) | |||
401 | { | |||
402 | MuxDriver *d = chr->opaque; | |||
403 | int m = d->focus; | |||
404 | ||||
405 | while (d->prod[m] != d->cons[m] && | |||
406 | d->chr_can_read[m] && | |||
407 | d->chr_can_read[m](d->ext_opaque[m])) { | |||
408 | d->chr_read[m](d->ext_opaque[m], | |||
409 | &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK(32 - 1)], 1); | |||
410 | } | |||
411 | } | |||
412 | ||||
413 | static int mux_chr_can_read(void *opaque) | |||
414 | { | |||
415 | CharDriverState *chr = opaque; | |||
416 | MuxDriver *d = chr->opaque; | |||
417 | int m = d->focus; | |||
418 | ||||
419 | if ((d->prod[m] - d->cons[m]) < MUX_BUFFER_SIZE32) | |||
420 | return 1; | |||
421 | if (d->chr_can_read[m]) | |||
422 | return d->chr_can_read[m](d->ext_opaque[m]); | |||
423 | return 0; | |||
424 | } | |||
425 | ||||
426 | static void mux_chr_read(void *opaque, const uint8_t *buf, int size) | |||
427 | { | |||
428 | CharDriverState *chr = opaque; | |||
429 | MuxDriver *d = chr->opaque; | |||
430 | int m = d->focus; | |||
431 | int i; | |||
432 | ||||
433 | mux_chr_accept_input (opaque); | |||
434 | ||||
435 | for(i = 0; i < size; i++) | |||
436 | if (mux_proc_byte(chr, d, buf[i])) { | |||
437 | if (d->prod[m] == d->cons[m] && | |||
438 | d->chr_can_read[m] && | |||
439 | d->chr_can_read[m](d->ext_opaque[m])) | |||
440 | d->chr_read[m](d->ext_opaque[m], &buf[i], 1); | |||
441 | else | |||
442 | d->buffer[m][d->prod[m]++ & MUX_BUFFER_MASK(32 - 1)] = buf[i]; | |||
443 | } | |||
444 | } | |||
445 | ||||
446 | static void mux_chr_event(void *opaque, int event) | |||
447 | { | |||
448 | CharDriverState *chr = opaque; | |||
449 | MuxDriver *d = chr->opaque; | |||
450 | int i; | |||
451 | ||||
452 | /* Send the event to all registered listeners */ | |||
453 | for (i = 0; i < d->mux_cnt; i++) | |||
454 | mux_chr_send_event(d, i, event); | |||
455 | } | |||
456 | ||||
457 | static void mux_chr_update_read_handler(CharDriverState *chr) | |||
458 | { | |||
459 | MuxDriver *d = chr->opaque; | |||
460 | ||||
461 | if (d->mux_cnt >= MAX_MUX4) { | |||
462 | fprintf(stderrstderr, "Cannot add I/O handlers, MUX array is full\n"); | |||
463 | return; | |||
464 | } | |||
465 | d->ext_opaque[d->mux_cnt] = chr->handler_opaque; | |||
466 | d->chr_can_read[d->mux_cnt] = chr->chr_can_read; | |||
467 | d->chr_read[d->mux_cnt] = chr->chr_read; | |||
468 | d->chr_event[d->mux_cnt] = chr->chr_event; | |||
469 | /* Fix up the real driver with mux routines */ | |||
470 | if (d->mux_cnt == 0) { | |||
471 | qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read, | |||
472 | mux_chr_event, chr); | |||
473 | } | |||
474 | if (d->focus != -1) { | |||
475 | mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT4); | |||
476 | } | |||
477 | d->focus = d->mux_cnt; | |||
478 | d->mux_cnt++; | |||
479 | mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN3); | |||
480 | } | |||
481 | ||||
482 | static bool_Bool muxes_realized; | |||
483 | ||||
484 | /** | |||
485 | * Called after processing of default and command-line-specified | |||
486 | * chardevs to deliver CHR_EVENT_OPENED events to any FEs attached | |||
487 | * to a mux chardev. This is done here to ensure that | |||
488 | * output/prompts/banners are only displayed for the FE that has | |||
489 | * focus when initial command-line processing/machine init is | |||
490 | * completed. | |||
491 | * | |||
492 | * After this point, any new FE attached to any new or existing | |||
493 | * mux will receive CHR_EVENT_OPENED notifications for the BE | |||
494 | * immediately. | |||
495 | */ | |||
496 | static void muxes_realize_done(Notifier *notifier, void *unused) | |||
497 | { | |||
498 | CharDriverState *chr; | |||
499 | ||||
500 | QTAILQ_FOREACH(chr, &chardevs, next)for ((chr) = ((&chardevs)->tqh_first); (chr); (chr) = ( (chr)->next.tqe_next)) { | |||
501 | if (chr->is_mux) { | |||
502 | MuxDriver *d = chr->opaque; | |||
503 | int i; | |||
504 | ||||
505 | /* send OPENED to all already-attached FEs */ | |||
506 | for (i = 0; i < d->mux_cnt; i++) { | |||
507 | mux_chr_send_event(d, i, CHR_EVENT_OPENED2); | |||
508 | } | |||
509 | /* mark mux as OPENED so any new FEs will immediately receive | |||
510 | * OPENED event | |||
511 | */ | |||
512 | qemu_chr_be_generic_open(chr); | |||
513 | } | |||
514 | } | |||
515 | muxes_realized = true1; | |||
516 | } | |||
517 | ||||
518 | static Notifier muxes_realize_notify = { | |||
519 | .notify = muxes_realize_done, | |||
520 | }; | |||
521 | ||||
522 | static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) | |||
523 | { | |||
524 | CharDriverState *chr; | |||
525 | MuxDriver *d; | |||
526 | ||||
527 | chr = g_malloc0(sizeof(CharDriverState)); | |||
528 | d = g_malloc0(sizeof(MuxDriver)); | |||
529 | ||||
530 | chr->opaque = d; | |||
531 | d->drv = drv; | |||
532 | d->focus = -1; | |||
533 | chr->chr_write = mux_chr_write; | |||
534 | chr->chr_update_read_handler = mux_chr_update_read_handler; | |||
535 | chr->chr_accept_input = mux_chr_accept_input; | |||
536 | /* Frontend guest-open / -close notification is not support with muxes */ | |||
537 | chr->chr_set_fe_open = NULL((void*)0); | |||
538 | /* only default to opened state if we've realized the initial | |||
539 | * set of muxes | |||
540 | */ | |||
541 | chr->explicit_be_open = muxes_realized ? 0 : 1; | |||
542 | chr->is_mux = 1; | |||
543 | ||||
544 | return chr; | |||
545 | } | |||
546 | ||||
547 | ||||
548 | #ifdef _WIN32 | |||
549 | int send_all(int fd, const void *buf, int len1) | |||
550 | { | |||
551 | int ret, len; | |||
552 | ||||
553 | len = len1; | |||
554 | while (len > 0) { | |||
555 | ret = send(fd, buf, len, 0); | |||
556 | if (ret < 0) { | |||
557 | errno(*__errno_location ()) = WSAGetLastError(); | |||
558 | if (errno(*__errno_location ()) != WSAEWOULDBLOCK) { | |||
559 | return -1; | |||
560 | } | |||
561 | } else if (ret == 0) { | |||
562 | break; | |||
563 | } else { | |||
564 | buf += ret; | |||
565 | len -= ret; | |||
566 | } | |||
567 | } | |||
568 | return len1 - len; | |||
569 | } | |||
570 | ||||
571 | #else | |||
572 | ||||
573 | int send_all(int fd, const void *_buf, int len1) | |||
574 | { | |||
575 | int ret, len; | |||
576 | const uint8_t *buf = _buf; | |||
577 | ||||
578 | len = len1; | |||
579 | while (len > 0) { | |||
580 | ret = write(fd, buf, len); | |||
581 | if (ret < 0) { | |||
582 | if (errno(*__errno_location ()) != EINTR4 && errno(*__errno_location ()) != EAGAIN11) | |||
583 | return -1; | |||
584 | } else if (ret == 0) { | |||
585 | break; | |||
586 | } else { | |||
587 | buf += ret; | |||
588 | len -= ret; | |||
589 | } | |||
590 | } | |||
591 | return len1 - len; | |||
592 | } | |||
593 | ||||
594 | int recv_all(int fd, void *_buf, int len1, bool_Bool single_read) | |||
595 | { | |||
596 | int ret, len; | |||
597 | uint8_t *buf = _buf; | |||
598 | ||||
599 | len = len1; | |||
600 | while ((len > 0) && (ret = read(fd, buf, len)) != 0) { | |||
601 | if (ret < 0) { | |||
602 | if (errno(*__errno_location ()) != EINTR4 && errno(*__errno_location ()) != EAGAIN11) { | |||
603 | return -1; | |||
604 | } | |||
605 | continue; | |||
606 | } else { | |||
607 | if (single_read) { | |||
608 | return ret; | |||
609 | } | |||
610 | buf += ret; | |||
611 | len -= ret; | |||
612 | } | |||
613 | } | |||
614 | return len1 - len; | |||
615 | } | |||
616 | ||||
617 | #endif /* !_WIN32 */ | |||
618 | ||||
619 | typedef struct IOWatchPoll | |||
620 | { | |||
621 | GSource parent; | |||
622 | ||||
623 | GIOChannel *channel; | |||
624 | GSource *src; | |||
625 | ||||
626 | IOCanReadHandler *fd_can_read; | |||
627 | GSourceFunc fd_read; | |||
628 | void *opaque; | |||
629 | } IOWatchPoll; | |||
630 | ||||
631 | static IOWatchPoll *io_watch_poll_from_source(GSource *source) | |||
632 | { | |||
633 | return container_of(source, IOWatchPoll, parent)({ const typeof(((IOWatchPoll *) 0)->parent) *__mptr = (source ); (IOWatchPoll *) ((char *) __mptr - __builtin_offsetof(IOWatchPoll , parent));}); | |||
634 | } | |||
635 | ||||
636 | static gboolean io_watch_poll_prepare(GSource *source, gint *timeout_) | |||
637 | { | |||
638 | IOWatchPoll *iwp = io_watch_poll_from_source(source); | |||
639 | bool_Bool now_active = iwp->fd_can_read(iwp->opaque) > 0; | |||
640 | bool_Bool was_active = iwp->src != NULL((void*)0); | |||
641 | if (was_active == now_active) { | |||
642 | return FALSE0; | |||
643 | } | |||
644 | ||||
645 | if (now_active) { | |||
646 | iwp->src = g_io_create_watch(iwp->channel, G_IO_IN | G_IO_ERR | G_IO_HUP); | |||
647 | g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL((void*)0)); | |||
648 | g_source_attach(iwp->src, NULL((void*)0)); | |||
649 | } else { | |||
650 | g_source_destroy(iwp->src); | |||
651 | g_source_unref(iwp->src); | |||
652 | iwp->src = NULL((void*)0); | |||
653 | } | |||
654 | return FALSE0; | |||
655 | } | |||
656 | ||||
657 | static gboolean io_watch_poll_check(GSource *source) | |||
658 | { | |||
659 | return FALSE0; | |||
660 | } | |||
661 | ||||
662 | static gboolean io_watch_poll_dispatch(GSource *source, GSourceFunc callback, | |||
663 | gpointer user_data) | |||
664 | { | |||
665 | abort(); | |||
666 | } | |||
667 | ||||
668 | static void io_watch_poll_finalize(GSource *source) | |||
669 | { | |||
670 | /* Due to a glib bug, removing the last reference to a source | |||
671 | * inside a finalize callback causes recursive locking (and a | |||
672 | * deadlock). This is not a problem inside other callbacks, | |||
673 | * including dispatch callbacks, so we call io_remove_watch_poll | |||
674 | * to remove this source. At this point, iwp->src must | |||
675 | * be NULL, or we would leak it. | |||
676 | * | |||
677 | * This would be solved much more elegantly by child sources, | |||
678 | * but we support older glib versions that do not have them. | |||
679 | */ | |||
680 | IOWatchPoll *iwp = io_watch_poll_from_source(source); | |||
681 | assert(iwp->src == NULL)((iwp->src == ((void*)0)) ? (void) (0) : __assert_fail ("iwp->src == ((void*)0)" , "/home/stefan/src/qemu/qemu.org/qemu/qemu-char.c", 681, __PRETTY_FUNCTION__ )); | |||
682 | } | |||
683 | ||||
684 | static GSourceFuncs io_watch_poll_funcs = { | |||
685 | .prepare = io_watch_poll_prepare, | |||
686 | .check = io_watch_poll_check, | |||
687 | .dispatch = io_watch_poll_dispatch, | |||
688 | .finalize = io_watch_poll_finalize, | |||
689 | }; | |||
690 | ||||
691 | /* Can only be used for read */ | |||
692 | static guint io_add_watch_poll(GIOChannel *channel, | |||
693 | IOCanReadHandler *fd_can_read, | |||
694 | GIOFunc fd_read, | |||
695 | gpointer user_data) | |||
696 | { | |||
697 | IOWatchPoll *iwp; | |||
698 | int tag; | |||
699 | ||||
700 | iwp = (IOWatchPoll *) g_source_new(&io_watch_poll_funcs, sizeof(IOWatchPoll)); | |||
701 | iwp->fd_can_read = fd_can_read; | |||
702 | iwp->opaque = user_data; | |||
703 | iwp->channel = channel; | |||
704 | iwp->fd_read = (GSourceFunc) fd_read; | |||
705 | iwp->src = NULL((void*)0); | |||
706 | ||||
707 | tag = g_source_attach(&iwp->parent, NULL((void*)0)); | |||
708 | g_source_unref(&iwp->parent); | |||
709 | return tag; | |||
710 | } | |||
711 | ||||
712 | static void io_remove_watch_poll(guint tag) | |||
713 | { | |||
714 | GSource *source; | |||
715 | IOWatchPoll *iwp; | |||
716 | ||||
717 | g_return_if_fail (tag > 0)do{ if (tag > 0) { } else { g_return_if_fail_warning (((gchar *) 0), __PRETTY_FUNCTION__, "tag > 0"); return; }; }while ( 0); | |||
718 | ||||
719 | source = g_main_context_find_source_by_id(NULL((void*)0), tag); | |||
720 | g_return_if_fail (source != NULL)do{ if (source != ((void*)0)) { } else { g_return_if_fail_warning (((gchar*) 0), __PRETTY_FUNCTION__, "source != NULL"); return ; }; }while (0); | |||
721 | ||||
722 | iwp = io_watch_poll_from_source(source); | |||
723 | if (iwp->src) { | |||
724 | g_source_destroy(iwp->src); | |||
725 | g_source_unref(iwp->src); | |||
726 | iwp->src = NULL((void*)0); | |||
727 | } | |||
728 | g_source_destroy(&iwp->parent); | |||
729 | } | |||
730 | ||||
731 | static void remove_fd_in_watch(CharDriverState *chr) | |||
732 | { | |||
733 | if (chr->fd_in_tag) { | |||
734 | io_remove_watch_poll(chr->fd_in_tag); | |||
735 | chr->fd_in_tag = 0; | |||
736 | } | |||
737 | } | |||
738 | ||||
739 | #ifndef _WIN32 | |||
740 | static GIOChannel *io_channel_from_fd(int fd) | |||
741 | { | |||
742 | GIOChannel *chan; | |||
743 | ||||
744 | if (fd == -1) { | |||
745 | return NULL((void*)0); | |||
746 | } | |||
747 | ||||
748 | chan = g_io_channel_unix_new(fd); | |||
749 | ||||
750 | g_io_channel_set_encoding(chan, NULL((void*)0), NULL((void*)0)); | |||
751 | g_io_channel_set_buffered(chan, FALSE0); | |||
752 | ||||
753 | return chan; | |||
754 | } | |||
755 | #endif | |||
756 | ||||
757 | static GIOChannel *io_channel_from_socket(int fd) | |||
758 | { | |||
759 | GIOChannel *chan; | |||
760 | ||||
761 | if (fd == -1) { | |||
762 | return NULL((void*)0); | |||
763 | } | |||
764 | ||||
765 | #ifdef _WIN32 | |||
766 | chan = g_io_channel_win32_new_socket(fd); | |||
767 | #else | |||
768 | chan = g_io_channel_unix_new(fd); | |||
769 | #endif | |||
770 | ||||
771 | g_io_channel_set_encoding(chan, NULL((void*)0), NULL((void*)0)); | |||
772 | g_io_channel_set_buffered(chan, FALSE0); | |||
773 | ||||
774 | return chan; | |||
775 | } | |||
776 | ||||
777 | static int io_channel_send(GIOChannel *fd, const void *buf, size_t len) | |||
778 | { | |||
779 | size_t offset = 0; | |||
780 | GIOStatus status = G_IO_STATUS_NORMAL; | |||
781 | ||||
782 | while (offset < len && status == G_IO_STATUS_NORMAL) { | |||
783 | gsize bytes_written = 0; | |||
784 | ||||
785 | status = g_io_channel_write_chars(fd, buf + offset, len - offset, | |||
786 | &bytes_written, NULL((void*)0)); | |||
787 | offset += bytes_written; | |||
788 | } | |||
789 | ||||
790 | if (offset > 0) { | |||
791 | return offset; | |||
792 | } | |||
793 | switch (status) { | |||
794 | case G_IO_STATUS_NORMAL: | |||
795 | g_assert(len == 0)do { if (len == 0) ; else g_assertion_message_expr (((gchar*) 0), "/home/stefan/src/qemu/qemu.org/qemu/qemu-char.c", 795, ( (const char*) (__PRETTY_FUNCTION__)), "len == 0"); } while (0 ); | |||
796 | return 0; | |||
797 | case G_IO_STATUS_AGAIN: | |||
798 | errno(*__errno_location ()) = EAGAIN11; | |||
799 | return -1; | |||
800 | default: | |||
801 | break; | |||
802 | } | |||
803 | errno(*__errno_location ()) = EINVAL22; | |||
804 | return -1; | |||
805 | } | |||
806 | ||||
807 | #ifndef _WIN32 | |||
808 | ||||
809 | typedef struct FDCharDriver { | |||
810 | CharDriverState *chr; | |||
811 | GIOChannel *fd_in, *fd_out; | |||
812 | int max_size; | |||
813 | QTAILQ_ENTRY(FDCharDriver)struct { struct FDCharDriver *tqe_next; struct FDCharDriver * *tqe_prev; } node; | |||
814 | } FDCharDriver; | |||
815 | ||||
816 | static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) | |||
817 | { | |||
818 | FDCharDriver *s = chr->opaque; | |||
819 | ||||
820 | return io_channel_send(s->fd_out, buf, len); | |||
821 | } | |||
822 | ||||
823 | static gboolean fd_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) | |||
824 | { | |||
825 | CharDriverState *chr = opaque; | |||
826 | FDCharDriver *s = chr->opaque; | |||
827 | int len; | |||
828 | uint8_t buf[READ_BUF_LEN4096]; | |||
829 | GIOStatus status; | |||
830 | gsize bytes_read; | |||
831 | ||||
832 | len = sizeof(buf); | |||
833 | if (len > s->max_size) { | |||
834 | len = s->max_size; | |||
835 | } | |||
836 | if (len == 0) { | |||
837 | return TRUE1; | |||
838 | } | |||
839 | ||||
840 | status = g_io_channel_read_chars(chan, (gchar *)buf, | |||
841 | len, &bytes_read, NULL((void*)0)); | |||
842 | if (status == G_IO_STATUS_EOF) { | |||
843 | remove_fd_in_watch(chr); | |||
844 | qemu_chr_be_event(chr, CHR_EVENT_CLOSED5); | |||
845 | return FALSE0; | |||
846 | } | |||
847 | if (status == G_IO_STATUS_NORMAL) { | |||
848 | qemu_chr_be_write(chr, buf, bytes_read); | |||
849 | } | |||
850 | ||||
851 | return TRUE1; | |||
852 | } | |||
853 | ||||
854 | static int fd_chr_read_poll(void *opaque) | |||
855 | { | |||
856 | CharDriverState *chr = opaque; | |||
857 | FDCharDriver *s = chr->opaque; | |||
858 | ||||
859 | s->max_size = qemu_chr_be_can_write(chr); | |||
860 | return s->max_size; | |||
861 | } | |||
862 | ||||
863 | static GSource *fd_chr_add_watch(CharDriverState *chr, GIOCondition cond) | |||
864 | { | |||
865 | FDCharDriver *s = chr->opaque; | |||
866 | return g_io_create_watch(s->fd_out, cond); | |||
867 | } | |||
868 | ||||
869 | static void fd_chr_update_read_handler(CharDriverState *chr) | |||
870 | { | |||
871 | FDCharDriver *s = chr->opaque; | |||
872 | ||||
873 | remove_fd_in_watch(chr); | |||
874 | if (s->fd_in) { | |||
875 | chr->fd_in_tag = io_add_watch_poll(s->fd_in, fd_chr_read_poll, | |||
876 | fd_chr_read, chr); | |||
877 | } | |||
878 | } | |||
879 | ||||
880 | static void fd_chr_close(struct CharDriverState *chr) | |||
881 | { | |||
882 | FDCharDriver *s = chr->opaque; | |||
883 | ||||
884 | remove_fd_in_watch(chr); | |||
885 | if (s->fd_in) { | |||
| ||||
886 | g_io_channel_unref(s->fd_in); | |||
887 | } | |||
888 | if (s->fd_out) { | |||
889 | g_io_channel_unref(s->fd_out); | |||
890 | } | |||
891 | ||||
892 | g_free(s); | |||
893 | qemu_chr_be_event(chr, CHR_EVENT_CLOSED5); | |||
894 | } | |||
895 | ||||
896 | /* open a character device to a unix fd */ | |||
897 | static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out) | |||
898 | { | |||
899 | CharDriverState *chr; | |||
900 | FDCharDriver *s; | |||
901 | ||||
902 | chr = g_malloc0(sizeof(CharDriverState)); | |||
903 | s = g_malloc0(sizeof(FDCharDriver)); | |||
904 | s->fd_in = io_channel_from_fd(fd_in); | |||
905 | s->fd_out = io_channel_from_fd(fd_out); | |||
906 | fcntl(fd_out, F_SETFL4, O_NONBLOCK04000); | |||
907 | s->chr = chr; | |||
908 | chr->opaque = s; | |||
909 | chr->chr_add_watch = fd_chr_add_watch; | |||
910 | chr->chr_write = fd_chr_write; | |||
911 | chr->chr_update_read_handler = fd_chr_update_read_handler; | |||
912 | chr->chr_close = fd_chr_close; | |||
913 | ||||
914 | return chr; | |||
915 | } | |||
916 | ||||
917 | static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts) | |||
918 | { | |||
919 | int fd_in, fd_out; | |||
920 | char filename_in[256], filename_out[256]; | |||
921 | const char *filename = opts->device; | |||
922 | ||||
923 | if (filename == NULL((void*)0)) { | |||
924 | fprintf(stderrstderr, "chardev: pipe: no filename given\n"); | |||
925 | return NULL((void*)0); | |||
926 | } | |||
927 | ||||
928 | snprintf(filename_in, 256, "%s.in", filename); | |||
929 | snprintf(filename_out, 256, "%s.out", filename); | |||
930 | TFR(fd_in = qemu_open(filename_in, O_RDWR | O_BINARY))do { if ((fd_in = qemu_open(filename_in, 02 | 0)) != -1) break ; } while ((*__errno_location ()) == 4); | |||
931 | TFR(fd_out = qemu_open(filename_out, O_RDWR | O_BINARY))do { if ((fd_out = qemu_open(filename_out, 02 | 0)) != -1) break ; } while ((*__errno_location ()) == 4); | |||
932 | if (fd_in < 0 || fd_out < 0) { | |||
933 | if (fd_in >= 0) | |||
934 | close(fd_in); | |||
935 | if (fd_out >= 0) | |||
936 | close(fd_out); | |||
937 | TFR(fd_in = fd_out = qemu_open(filename, O_RDWR | O_BINARY))do { if ((fd_in = fd_out = qemu_open(filename, 02 | 0)) != -1 ) break; } while ((*__errno_location ()) == 4); | |||
938 | if (fd_in < 0) { | |||
939 | return NULL((void*)0); | |||
940 | } | |||
941 | } | |||
942 | return qemu_chr_open_fd(fd_in, fd_out); | |||
943 | } | |||
944 | ||||
945 | /* init terminal so that we can grab keys */ | |||
946 | static struct termios oldtty; | |||
947 | static int old_fd0_flags; | |||
948 | static bool_Bool stdio_allow_signal; | |||
949 | ||||
950 | static void term_exit(void) | |||
951 | { | |||
952 | tcsetattr (0, TCSANOW0, &oldtty); | |||
953 | fcntl(0, F_SETFL4, old_fd0_flags); | |||
954 | } | |||
955 | ||||
956 | static void qemu_chr_set_echo_stdio(CharDriverState *chr, bool_Bool echo) | |||
957 | { | |||
958 | struct termios tty; | |||
959 | ||||
960 | tty = oldtty; | |||
961 | if (!echo) { | |||
962 | tty.c_iflag &= ~(IGNBRK0000001|BRKINT0000002|PARMRK0000010|ISTRIP0000040 | |||
963 | |INLCR0000100|IGNCR0000200|ICRNL0000400|IXON0002000); | |||
964 | tty.c_oflag |= OPOST0000001; | |||
965 | tty.c_lflag &= ~(ECHO0000010|ECHONL0000100|ICANON0000002|IEXTEN0100000); | |||
966 | tty.c_cflag &= ~(CSIZE0000060|PARENB0000400); | |||
967 | tty.c_cflag |= CS80000060; | |||
968 | tty.c_cc[VMIN6] = 1; | |||
969 | tty.c_cc[VTIME5] = 0; | |||
970 | } | |||
971 | if (!stdio_allow_signal) | |||
972 | tty.c_lflag &= ~ISIG0000001; | |||
973 | ||||
974 | tcsetattr (0, TCSANOW0, &tty); | |||
975 | } | |||
976 | ||||
977 | static void qemu_chr_close_stdio(struct CharDriverState *chr) | |||
978 | { | |||
979 | term_exit(); | |||
980 | fd_chr_close(chr); | |||
981 | } | |||
982 | ||||
983 | static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts) | |||
984 | { | |||
985 | CharDriverState *chr; | |||
986 | ||||
987 | if (is_daemonized()) { | |||
988 | error_report("cannot use stdio with -daemonize"); | |||
989 | return NULL((void*)0); | |||
990 | } | |||
991 | old_fd0_flags = fcntl(0, F_GETFL3); | |||
992 | tcgetattr (0, &oldtty); | |||
993 | fcntl(0, F_SETFL4, O_NONBLOCK04000); | |||
994 | atexit(term_exit); | |||
995 | ||||
996 | chr = qemu_chr_open_fd(0, 1); | |||
997 | chr->chr_close = qemu_chr_close_stdio; | |||
998 | chr->chr_set_echo = qemu_chr_set_echo_stdio; | |||
999 | if (opts->has_signal) { | |||
1000 | stdio_allow_signal = opts->signal; | |||
1001 | } | |||
1002 | qemu_chr_fe_set_echo(chr, false0); | |||
1003 | ||||
1004 | return chr; | |||
1005 | } | |||
1006 | ||||
1007 | #if defined(__linux__1) || defined(__sun__) || defined(__FreeBSD__) \ | |||
1008 | || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \ | |||
1009 | || defined(__GLIBC__2) | |||
1010 | ||||
1011 | #define HAVE_CHARDEV_TTY1 1 | |||
1012 | ||||
1013 | typedef struct { | |||
1014 | GIOChannel *fd; | |||
1015 | int connected; | |||
1016 | int read_bytes; | |||
1017 | guint timer_tag; | |||
1018 | } PtyCharDriver; | |||
1019 | ||||
1020 | static void pty_chr_update_read_handler(CharDriverState *chr); | |||
1021 | static void pty_chr_state(CharDriverState *chr, int connected); | |||
1022 | ||||
1023 | static gboolean pty_chr_timer(gpointer opaque) | |||
1024 | { | |||
1025 | struct CharDriverState *chr = opaque; | |||
1026 | PtyCharDriver *s = chr->opaque; | |||
1027 | ||||
1028 | s->timer_tag = 0; | |||
1029 | if (!s->connected) { | |||
1030 | /* Next poll ... */ | |||
1031 | pty_chr_update_read_handler(chr); | |||
1032 | } | |||
1033 | return FALSE0; | |||
1034 | } | |||
1035 | ||||
1036 | static void pty_chr_rearm_timer(CharDriverState *chr, int ms) | |||
1037 | { | |||
1038 | PtyCharDriver *s = chr->opaque; | |||
1039 | ||||
1040 | if (s->timer_tag) { | |||
1041 | g_source_remove(s->timer_tag); | |||
1042 | s->timer_tag = 0; | |||
1043 | } | |||
1044 | ||||
1045 | if (ms == 1000) { | |||
1046 | s->timer_tag = g_timeout_add_seconds(1, pty_chr_timer, chr); | |||
1047 | } else { | |||
1048 | s->timer_tag = g_timeout_add(ms, pty_chr_timer, chr); | |||
1049 | } | |||
1050 | } | |||
1051 | ||||
1052 | static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len) | |||
1053 | { | |||
1054 | PtyCharDriver *s = chr->opaque; | |||
1055 | ||||
1056 | if (!s->connected) { | |||
1057 | /* guest sends data, check for (re-)connect */ | |||
1058 | pty_chr_update_read_handler(chr); | |||
1059 | return 0; | |||
1060 | } | |||
1061 | return io_channel_send(s->fd, buf, len); | |||
1062 | } | |||
1063 | ||||
1064 | static GSource *pty_chr_add_watch(CharDriverState *chr, GIOCondition cond) | |||
1065 | { | |||
1066 | PtyCharDriver *s = chr->opaque; | |||
1067 | return g_io_create_watch(s->fd, cond); | |||
1068 | } | |||
1069 | ||||
1070 | static int pty_chr_read_poll(void *opaque) | |||
1071 | { | |||
1072 | CharDriverState *chr = opaque; | |||
1073 | PtyCharDriver *s = chr->opaque; | |||
1074 | ||||
1075 | s->read_bytes = qemu_chr_be_can_write(chr); | |||
1076 | return s->read_bytes; | |||
1077 | } | |||
1078 | ||||
1079 | static gboolean pty_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) | |||
1080 | { | |||
1081 | CharDriverState *chr = opaque; | |||
1082 | PtyCharDriver *s = chr->opaque; | |||
1083 | gsize size, len; | |||
1084 | uint8_t buf[READ_BUF_LEN4096]; | |||
1085 | GIOStatus status; | |||
1086 | ||||
1087 | len = sizeof(buf); | |||
1088 | if (len > s->read_bytes) | |||
1089 | len = s->read_bytes; | |||
1090 | if (len == 0) { | |||
1091 | return TRUE1; | |||
1092 | } | |||
1093 | status = g_io_channel_read_chars(s->fd, (gchar *)buf, len, &size, NULL((void*)0)); | |||
1094 | if (status != G_IO_STATUS_NORMAL) { | |||
1095 | pty_chr_state(chr, 0); | |||
1096 | return FALSE0; | |||
1097 | } else { | |||
1098 | pty_chr_state(chr, 1); | |||
1099 | qemu_chr_be_write(chr, buf, size); | |||
1100 | } | |||
1101 | return TRUE1; | |||
1102 | } | |||
1103 | ||||
1104 | static void pty_chr_update_read_handler(CharDriverState *chr) | |||
1105 | { | |||
1106 | PtyCharDriver *s = chr->opaque; | |||
1107 | GPollFD pfd; | |||
1108 | ||||
1109 | pfd.fd = g_io_channel_unix_get_fd(s->fd); | |||
1110 | pfd.events = G_IO_OUT; | |||
1111 | pfd.revents = 0; | |||
1112 | g_poll(&pfd, 1, 0); | |||
1113 | if (pfd.revents & G_IO_HUP) { | |||
1114 | pty_chr_state(chr, 0); | |||
1115 | } else { | |||
1116 | pty_chr_state(chr, 1); | |||
1117 | } | |||
1118 | } | |||
1119 | ||||
1120 | static void pty_chr_state(CharDriverState *chr, int connected) | |||
1121 | { | |||
1122 | PtyCharDriver *s = chr->opaque; | |||
1123 | ||||
1124 | if (!connected) { | |||
1125 | remove_fd_in_watch(chr); | |||
1126 | s->connected = 0; | |||
1127 | /* (re-)connect poll interval for idle guests: once per second. | |||
1128 | * We check more frequently in case the guests sends data to | |||
1129 | * the virtual device linked to our pty. */ | |||
1130 | pty_chr_rearm_timer(chr, 1000); | |||
1131 | } else { | |||
1132 | if (s->timer_tag) { | |||
1133 | g_source_remove(s->timer_tag); | |||
1134 | s->timer_tag = 0; | |||
1135 | } | |||
1136 | if (!s->connected) { | |||
1137 | s->connected = 1; | |||
1138 | qemu_chr_be_generic_open(chr); | |||
1139 | chr->fd_in_tag = io_add_watch_poll(s->fd, pty_chr_read_poll, | |||
1140 | pty_chr_read, chr); | |||
1141 | } | |||
1142 | } | |||
1143 | } | |||
1144 | ||||
1145 | ||||
1146 | static void pty_chr_close(struct CharDriverState *chr) | |||
1147 | { | |||
1148 | PtyCharDriver *s = chr->opaque; | |||
1149 | int fd; | |||
1150 | ||||
1151 | remove_fd_in_watch(chr); | |||
1152 | fd = g_io_channel_unix_get_fd(s->fd); | |||
1153 | g_io_channel_unref(s->fd); | |||
1154 | close(fd); | |||
1155 | if (s->timer_tag) { | |||
1156 | g_source_remove(s->timer_tag); | |||
1157 | s->timer_tag = 0; | |||
1158 | } | |||
1159 | g_free(s); | |||
1160 | qemu_chr_be_event(chr, CHR_EVENT_CLOSED5); | |||
1161 | } | |||
1162 | ||||
1163 | static CharDriverState *qemu_chr_open_pty(const char *id, | |||
1164 | ChardevReturn *ret) | |||
1165 | { | |||
1166 | CharDriverState *chr; | |||
1167 | PtyCharDriver *s; | |||
1168 | int master_fd, slave_fd; | |||
1169 | char pty_name[PATH_MAX4096]; | |||
1170 | ||||
1171 | master_fd = qemu_openpty_raw(&slave_fd, pty_name); | |||
1172 | if (master_fd < 0) { | |||
1173 | return NULL((void*)0); | |||
1174 | } | |||
1175 | ||||
1176 | close(slave_fd); | |||
1177 | ||||
1178 | chr = g_malloc0(sizeof(CharDriverState)); | |||
1179 | ||||
1180 | chr->filename = g_strdup_printf("pty:%s", pty_name); | |||
1181 | ret->pty = g_strdup(pty_name); | |||
1182 | ret->has_pty = true1; | |||
1183 | ||||
1184 | fprintf(stderrstderr, "char device redirected to %s (label %s)\n", | |||
1185 | pty_name, id); | |||
1186 | ||||
1187 | s = g_malloc0(sizeof(PtyCharDriver)); | |||
1188 | chr->opaque = s; | |||
1189 | chr->chr_write = pty_chr_write; | |||
1190 | chr->chr_update_read_handler = pty_chr_update_read_handler; | |||
1191 | chr->chr_close = pty_chr_close; | |||
1192 | chr->chr_add_watch = pty_chr_add_watch; | |||
1193 | chr->explicit_be_open = true1; | |||
1194 | ||||
1195 | s->fd = io_channel_from_fd(master_fd); | |||
1196 | s->timer_tag = 0; | |||
1197 | ||||
1198 | return chr; | |||
1199 | } | |||
1200 | ||||
1201 | static void tty_serial_init(int fd, int speed, | |||
1202 | int parity, int data_bits, int stop_bits) | |||
1203 | { | |||
1204 | struct termios tty; | |||
1205 | speed_t spd; | |||
1206 | ||||
1207 | #if 0 | |||
1208 | printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n", | |||
1209 | speed, parity, data_bits, stop_bits); | |||
1210 | #endif | |||
1211 | tcgetattr (fd, &tty); | |||
1212 | ||||
1213 | #define check_speed(val)if (speed <= val) { spd = Bval; break; } if (speed <= val) { spd = B##val; break; } | |||
1214 | speed = speed * 10 / 11; | |||
1215 | do { | |||
1216 | check_speed(50)if (speed <= 50) { spd = 0000001; break; }; | |||
1217 | check_speed(75)if (speed <= 75) { spd = 0000002; break; }; | |||
1218 | check_speed(110)if (speed <= 110) { spd = 0000003; break; }; | |||
1219 | check_speed(134)if (speed <= 134) { spd = 0000004; break; }; | |||
1220 | check_speed(150)if (speed <= 150) { spd = 0000005; break; }; | |||
1221 | check_speed(200)if (speed <= 200) { spd = 0000006; break; }; | |||
1222 | check_speed(300)if (speed <= 300) { spd = 0000007; break; }; | |||
1223 | check_speed(600)if (speed <= 600) { spd = 0000010; break; }; | |||
1224 | check_speed(1200)if (speed <= 1200) { spd = 0000011; break; }; | |||
1225 | check_speed(1800)if (speed <= 1800) { spd = 0000012; break; }; | |||
1226 | check_speed(2400)if (speed <= 2400) { spd = 0000013; break; }; | |||
1227 | check_speed(4800)if (speed <= 4800) { spd = 0000014; break; }; | |||
1228 | check_speed(9600)if (speed <= 9600) { spd = 0000015; break; }; | |||
1229 | check_speed(19200)if (speed <= 19200) { spd = 0000016; break; }; | |||
1230 | check_speed(38400)if (speed <= 38400) { spd = 0000017; break; }; | |||
1231 | /* Non-Posix values follow. They may be unsupported on some systems. */ | |||
1232 | check_speed(57600)if (speed <= 57600) { spd = 0010001; break; }; | |||
1233 | check_speed(115200)if (speed <= 115200) { spd = 0010002; break; }; | |||
1234 | #ifdef B2304000010003 | |||
1235 | check_speed(230400)if (speed <= 230400) { spd = 0010003; break; }; | |||
1236 | #endif | |||
1237 | #ifdef B4608000010004 | |||
1238 | check_speed(460800)if (speed <= 460800) { spd = 0010004; break; }; | |||
1239 | #endif | |||
1240 | #ifdef B5000000010005 | |||
1241 | check_speed(500000)if (speed <= 500000) { spd = 0010005; break; }; | |||
1242 | #endif | |||
1243 | #ifdef B5760000010006 | |||
1244 | check_speed(576000)if (speed <= 576000) { spd = 0010006; break; }; | |||
1245 | #endif | |||
1246 | #ifdef B9216000010007 | |||
1247 | check_speed(921600)if (speed <= 921600) { spd = 0010007; break; }; | |||
1248 | #endif | |||
1249 | #ifdef B10000000010010 | |||
1250 | check_speed(1000000)if (speed <= 1000000) { spd = 0010010; break; }; | |||
1251 | #endif | |||
1252 | #ifdef B11520000010011 | |||
1253 | check_speed(1152000)if (speed <= 1152000) { spd = 0010011; break; }; | |||
1254 | #endif | |||
1255 | #ifdef B15000000010012 | |||
1256 | check_speed(1500000)if (speed <= 1500000) { spd = 0010012; break; }; | |||
1257 | #endif | |||
1258 | #ifdef B20000000010013 | |||
1259 | check_speed(2000000)if (speed <= 2000000) { spd = 0010013; break; }; | |||
1260 | #endif | |||
1261 | #ifdef B25000000010014 | |||
1262 | check_speed(2500000)if (speed <= 2500000) { spd = 0010014; break; }; | |||
1263 | #endif | |||
1264 | #ifdef B30000000010015 | |||
1265 | check_speed(3000000)if (speed <= 3000000) { spd = 0010015; break; }; | |||
1266 | #endif | |||
1267 | #ifdef B35000000010016 | |||
1268 | check_speed(3500000)if (speed <= 3500000) { spd = 0010016; break; }; | |||
1269 | #endif | |||
1270 | #ifdef B40000000010017 | |||
1271 | check_speed(4000000)if (speed <= 4000000) { spd = 0010017; break; }; | |||
1272 | #endif | |||
1273 | spd = B1152000010002; | |||
1274 | } while (0); | |||
1275 | ||||
1276 | cfsetispeed(&tty, spd); | |||
1277 | cfsetospeed(&tty, spd); | |||
1278 | ||||
1279 | tty.c_iflag &= ~(IGNBRK0000001|BRKINT0000002|PARMRK0000010|ISTRIP0000040 | |||
1280 | |INLCR0000100|IGNCR0000200|ICRNL0000400|IXON0002000); | |||
1281 | tty.c_oflag |= OPOST0000001; | |||
1282 | tty.c_lflag &= ~(ECHO0000010|ECHONL0000100|ICANON0000002|IEXTEN0100000|ISIG0000001); | |||
1283 | tty.c_cflag &= ~(CSIZE0000060|PARENB0000400|PARODD0001000|CRTSCTS020000000000|CSTOPB0000100); | |||
1284 | switch(data_bits) { | |||
1285 | default: | |||
1286 | case 8: | |||
1287 | tty.c_cflag |= CS80000060; | |||
1288 | break; | |||
1289 | case 7: | |||
1290 | tty.c_cflag |= CS70000040; | |||
1291 | break; | |||
1292 | case 6: | |||
1293 | tty.c_cflag |= CS60000020; | |||
1294 | break; | |||
1295 | case 5: | |||
1296 | tty.c_cflag |= CS50000000; | |||
1297 | break; | |||
1298 | } | |||
1299 | switch(parity) { | |||
1300 | default: | |||
1301 | case 'N': | |||
1302 | break; | |||
1303 | case 'E': | |||
1304 | tty.c_cflag |= PARENB0000400; | |||
1305 | break; | |||
1306 | case 'O': | |||
1307 | tty.c_cflag |= PARENB0000400 | PARODD0001000; | |||
1308 | break; | |||
1309 | } | |||
1310 | if (stop_bits == 2) | |||
1311 | tty.c_cflag |= CSTOPB0000100; | |||
1312 | ||||
1313 | tcsetattr (fd, TCSANOW0, &tty); | |||
1314 | } | |||
1315 | ||||
1316 | static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg) | |||
1317 | { | |||
1318 | FDCharDriver *s = chr->opaque; | |||
1319 | ||||
1320 | switch(cmd) { | |||
1321 | case CHR_IOCTL_SERIAL_SET_PARAMS1: | |||
1322 | { | |||
1323 | QEMUSerialSetParams *ssp = arg; | |||
1324 | tty_serial_init(g_io_channel_unix_get_fd(s->fd_in), | |||
1325 | ssp->speed, ssp->parity, | |||
1326 | ssp->data_bits, ssp->stop_bits); | |||
1327 | } | |||
1328 | break; | |||
1329 | case CHR_IOCTL_SERIAL_SET_BREAK2: | |||
1330 | { | |||
1331 | int enable = *(int *)arg; | |||
1332 | if (enable) { | |||
1333 | tcsendbreak(g_io_channel_unix_get_fd(s->fd_in), 1); | |||
1334 | } | |||
1335 | } | |||
1336 | break; | |||
1337 | case CHR_IOCTL_SERIAL_GET_TIOCM14: | |||
1338 | { | |||
1339 | int sarg = 0; | |||
1340 | int *targ = (int *)arg; | |||
1341 | ioctl(g_io_channel_unix_get_fd(s->fd_in), TIOCMGET0x5415, &sarg); | |||
1342 | *targ = 0; | |||
1343 | if (sarg & TIOCM_CTS0x020) | |||
1344 | *targ |= CHR_TIOCM_CTS0x020; | |||
1345 | if (sarg & TIOCM_CAR0x040) | |||
1346 | *targ |= CHR_TIOCM_CAR0x040; | |||
1347 | if (sarg & TIOCM_DSR0x100) | |||
1348 | *targ |= CHR_TIOCM_DSR0x100; | |||
1349 | if (sarg & TIOCM_RI0x080) | |||
1350 | *targ |= CHR_TIOCM_RI0x080; | |||
1351 | if (sarg & TIOCM_DTR0x002) | |||
1352 | *targ |= CHR_TIOCM_DTR0x002; | |||
1353 | if (sarg & TIOCM_RTS0x004) | |||
1354 | *targ |= CHR_TIOCM_RTS0x004; | |||
1355 | } | |||
1356 | break; | |||
1357 | case CHR_IOCTL_SERIAL_SET_TIOCM13: | |||
1358 | { | |||
1359 | int sarg = *(int *)arg; | |||
1360 | int targ = 0; | |||
1361 | ioctl(g_io_channel_unix_get_fd(s->fd_in), TIOCMGET0x5415, &targ); | |||
1362 | targ &= ~(CHR_TIOCM_CTS0x020 | CHR_TIOCM_CAR0x040 | CHR_TIOCM_DSR0x100 | |||
1363 | | CHR_TIOCM_RI0x080 | CHR_TIOCM_DTR0x002 | CHR_TIOCM_RTS0x004); | |||
1364 | if (sarg & CHR_TIOCM_CTS0x020) | |||
1365 | targ |= TIOCM_CTS0x020; | |||
1366 | if (sarg & CHR_TIOCM_CAR0x040) | |||
1367 | targ |= TIOCM_CAR0x040; | |||
1368 | if (sarg & CHR_TIOCM_DSR0x100) | |||
1369 | targ |= TIOCM_DSR0x100; | |||
1370 | if (sarg & CHR_TIOCM_RI0x080) | |||
1371 | targ |= TIOCM_RI0x080; | |||
1372 | if (sarg & CHR_TIOCM_DTR0x002) | |||
1373 | targ |= TIOCM_DTR0x002; | |||
1374 | if (sarg & CHR_TIOCM_RTS0x004) | |||
1375 | targ |= TIOCM_RTS0x004; | |||
1376 | ioctl(g_io_channel_unix_get_fd(s->fd_in), TIOCMSET0x5418, &targ); | |||
1377 | } | |||
1378 | break; | |||
1379 | default: | |||
1380 | return -ENOTSUP95; | |||
1381 | } | |||
1382 | return 0; | |||
1383 | } | |||
1384 | ||||
1385 | static void qemu_chr_close_tty(CharDriverState *chr) | |||
1386 | { | |||
1387 | FDCharDriver *s = chr->opaque; | |||
1388 | int fd = -1; | |||
1389 | ||||
1390 | if (s) { | |||
| ||||
1391 | fd = g_io_channel_unix_get_fd(s->fd_in); | |||
1392 | } | |||
1393 | ||||
1394 | fd_chr_close(chr); | |||
1395 | ||||
1396 | if (fd >= 0) { | |||
1397 | close(fd); | |||
1398 | } | |||
1399 | } | |||
1400 | ||||
1401 | static CharDriverState *qemu_chr_open_tty_fd(int fd) | |||
1402 | { | |||
1403 | CharDriverState *chr; | |||
1404 | ||||
1405 | tty_serial_init(fd, 115200, 'N', 8, 1); | |||
1406 | chr = qemu_chr_open_fd(fd, fd); | |||
1407 | chr->chr_ioctl = tty_serial_ioctl; | |||
1408 | chr->chr_close = qemu_chr_close_tty; | |||
1409 | return chr; | |||
1410 | } | |||
1411 | #endif /* __linux__ || __sun__ */ | |||
1412 | ||||
1413 | #if defined(__linux__1) | |||
1414 | ||||
1415 | #define HAVE_CHARDEV_PARPORT1 1 | |||
1416 | ||||
1417 | typedef struct { | |||
1418 | int fd; | |||
1419 | int mode; | |||
1420 | } ParallelCharDriver; | |||
1421 | ||||
1422 | static int pp_hw_mode(ParallelCharDriver *s, uint16_t mode) | |||
1423 | { | |||
1424 | if (s->mode != mode) { | |||
1425 | int m = mode; | |||
1426 | if (ioctl(s->fd, PPSETMODE(((1U) << (((0 +8)+8)+14)) | ((('p')) << (0 +8)) | (((0x80)) << 0) | ((((sizeof(int)))) << ((0 +8)+ 8))), &m) < 0) | |||
1427 | return 0; | |||
1428 | s->mode = mode; | |||
1429 | } | |||
1430 | return 1; | |||
1431 | } | |||
1432 | ||||
1433 | static int pp_ioctl(CharDriverState *chr, int cmd, void *arg) | |||
1434 | { | |||
1435 | ParallelCharDriver *drv = chr->opaque; | |||
1436 | int fd = drv->fd; | |||
1437 | uint8_t b; | |||
1438 | ||||
1439 | switch(cmd) { | |||
1440 | case CHR_IOCTL_PP_READ_DATA3: | |||
1441 | if (ioctl(fd, PPRDATA(((2U) << (((0 +8)+8)+14)) | ((('p')) << (0 +8)) | (((0x85)) << 0) | ((((sizeof(unsigned char)))) << ((0 +8)+8))), &b) < 0) | |||
1442 | return -ENOTSUP95; | |||
1443 | *(uint8_t *)arg = b; | |||
1444 | break; | |||
1445 | case CHR_IOCTL_PP_WRITE_DATA4: | |||
1446 | b = *(uint8_t *)arg; | |||
1447 | if (ioctl(fd, PPWDATA(((1U) << (((0 +8)+8)+14)) | ((('p')) << (0 +8)) | (((0x86)) << 0) | ((((sizeof(unsigned char)))) << ((0 +8)+8))), &b) < 0) | |||
1448 | return -ENOTSUP95; | |||
1449 | break; | |||
1450 | case CHR_IOCTL_PP_READ_CONTROL5: | |||
1451 | if (ioctl(fd, PPRCONTROL(((2U) << (((0 +8)+8)+14)) | ((('p')) << (0 +8)) | (((0x83)) << 0) | ((((sizeof(unsigned char)))) << ((0 +8)+8))), &b) < 0) | |||
1452 | return -ENOTSUP95; | |||
1453 | /* Linux gives only the lowest bits, and no way to know data | |||
1454 | direction! For better compatibility set the fixed upper | |||
1455 | bits. */ | |||
1456 | *(uint8_t *)arg = b | 0xc0; | |||
1457 | break; | |||
1458 | case CHR_IOCTL_PP_WRITE_CONTROL6: | |||
1459 | b = *(uint8_t *)arg; | |||
1460 | if (ioctl(fd, PPWCONTROL(((1U) << (((0 +8)+8)+14)) | ((('p')) << (0 +8)) | (((0x84)) << 0) | ((((sizeof(unsigned char)))) << ((0 +8)+8))), &b) < 0) | |||
1461 | return -ENOTSUP95; | |||
1462 | break; | |||
1463 | case CHR_IOCTL_PP_READ_STATUS7: | |||
1464 | if (ioctl(fd, PPRSTATUS(((2U) << (((0 +8)+8)+14)) | ((('p')) << (0 +8)) | (((0x81)) << 0) | ((((sizeof(unsigned char)))) << ((0 +8)+8))), &b) < 0) | |||
1465 | return -ENOTSUP95; | |||
1466 | *(uint8_t *)arg = b; | |||
1467 | break; | |||
1468 | case CHR_IOCTL_PP_DATA_DIR12: | |||
1469 | if (ioctl(fd, PPDATADIR(((1U) << (((0 +8)+8)+14)) | ((('p')) << (0 +8)) | (((0x90)) << 0) | ((((sizeof(int)))) << ((0 +8)+ 8))), (int *)arg) < 0) | |||
1470 | return -ENOTSUP95; | |||
1471 | break; | |||
1472 | case CHR_IOCTL_PP_EPP_READ_ADDR8: | |||
1473 | if (pp_hw_mode(drv, IEEE1284_MODE_EPP(1<<6)|IEEE1284_ADDR(1<<13))) { | |||
1474 | struct ParallelIOArg *parg = arg; | |||
1475 | int n = read(fd, parg->buffer, parg->count); | |||
1476 | if (n != parg->count) { | |||
1477 | return -EIO5; | |||
1478 | } | |||
1479 | } | |||
1480 | break; | |||
1481 | case CHR_IOCTL_PP_EPP_READ9: | |||
1482 | if (pp_hw_mode(drv, IEEE1284_MODE_EPP(1<<6))) { | |||
1483 | struct ParallelIOArg *parg = arg; | |||
1484 | int n = read(fd, parg->buffer, parg->count); | |||
1485 | if (n != parg->count) { | |||
1486 | return -EIO5; | |||
1487 | } | |||
1488 | } | |||
1489 | break; | |||
1490 | case CHR_IOCTL_PP_EPP_WRITE_ADDR10: | |||
1491 | if (pp_hw_mode(drv, IEEE1284_MODE_EPP(1<<6)|IEEE1284_ADDR(1<<13))) { | |||
1492 | struct ParallelIOArg *parg = arg; | |||
1493 | int n = write(fd, parg->buffer, parg->count); | |||
1494 | if (n != parg->count) { | |||
1495 | return -EIO5; | |||
1496 | } | |||
1497 | } | |||
1498 | break; | |||
1499 | case CHR_IOCTL_PP_EPP_WRITE11: | |||
1500 | if (pp_hw_mode(drv, IEEE1284_MODE_EPP(1<<6))) { | |||
1501 | struct ParallelIOArg *parg = arg; | |||
1502 | int n = write(fd, parg->buffer, parg->count); | |||
1503 | if (n != parg->count) { | |||
1504 | return -EIO5; | |||
1505 | } | |||
1506 | } | |||
1507 | break; | |||
1508 | default: | |||
1509 | return -ENOTSUP95; | |||
1510 | } | |||
1511 | return 0; | |||
1512 | } | |||
1513 | ||||
1514 | static void pp_close(CharDriverState *chr) | |||
1515 | { | |||
1516 | ParallelCharDriver *drv = chr->opaque; | |||
1517 | int fd = drv->fd; | |||
1518 | ||||
1519 | pp_hw_mode(drv, IEEE1284_MODE_COMPAT(1<<8)); | |||
1520 | ioctl(fd, PPRELEASE(((0U) << (((0 +8)+8)+14)) | ((('p')) << (0 +8)) | (((0x8c)) << 0) | ((0) << ((0 +8)+8)))); | |||
1521 | close(fd); | |||
1522 | g_free(drv); | |||
1523 | qemu_chr_be_event(chr, CHR_EVENT_CLOSED5); | |||
1524 | } | |||
1525 | ||||
1526 | static CharDriverState *qemu_chr_open_pp_fd(int fd) | |||
1527 | { | |||
1528 | CharDriverState *chr; | |||
1529 | ParallelCharDriver *drv; | |||
1530 | ||||
1531 | if (ioctl(fd, PPCLAIM(((0U) << (((0 +8)+8)+14)) | ((('p')) << (0 +8)) | (((0x8b)) << 0) | ((0) << ((0 +8)+8)))) < 0) { | |||
1532 | close(fd); | |||
1533 | return NULL((void*)0); | |||
1534 | } | |||
1535 | ||||
1536 | drv = g_malloc0(sizeof(ParallelCharDriver)); | |||
1537 | drv->fd = fd; | |||
1538 | drv->mode = IEEE1284_MODE_COMPAT(1<<8); | |||
1539 | ||||
1540 | chr = g_malloc0(sizeof(CharDriverState)); | |||
1541 | chr->chr_write = null_chr_write; | |||
1542 | chr->chr_ioctl = pp_ioctl; | |||
1543 | chr->chr_close = pp_close; | |||
1544 | chr->opaque = drv; | |||
1545 | ||||
1546 | return chr; | |||
1547 | } | |||
1548 | #endif /* __linux__ */ | |||
1549 | ||||
1550 | #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) | |||
1551 | ||||
1552 | #define HAVE_CHARDEV_PARPORT1 1 | |||
1553 | ||||
1554 | static int pp_ioctl(CharDriverState *chr, int cmd, void *arg) | |||
1555 | { | |||
1556 | int fd = (int)(intptr_t)chr->opaque; | |||
1557 | uint8_t b; | |||
1558 | ||||
1559 | switch(cmd) { | |||
1560 | case CHR_IOCTL_PP_READ_DATA3: | |||
1561 | if (ioctl(fd, PPIGDATA, &b) < 0) | |||
1562 | return -ENOTSUP95; | |||
1563 | *(uint8_t *)arg = b; | |||
1564 | break; | |||
1565 | case CHR_IOCTL_PP_WRITE_DATA4: | |||
1566 | b = *(uint8_t *)arg; | |||
1567 | if (ioctl(fd, PPISDATA, &b) < 0) | |||
1568 | return -ENOTSUP95; | |||
1569 | break; | |||
1570 | case CHR_IOCTL_PP_READ_CONTROL5: | |||
1571 | if (ioctl(fd, PPIGCTRL, &b) < 0) | |||
1572 | return -ENOTSUP95; | |||
1573 | *(uint8_t *)arg = b; | |||
1574 | break; | |||
1575 | case CHR_IOCTL_PP_WRITE_CONTROL6: | |||
1576 | b = *(uint8_t *)arg; | |||
1577 | if (ioctl(fd, PPISCTRL, &b) < 0) | |||
1578 | return -ENOTSUP95; | |||
1579 | break; | |||
1580 | case CHR_IOCTL_PP_READ_STATUS7: | |||
1581 | if (ioctl(fd, PPIGSTATUS, &b) < 0) | |||
1582 | return -ENOTSUP95; | |||
1583 | *(uint8_t *)arg = b; | |||
1584 | break; | |||
1585 | default: | |||
1586 | return -ENOTSUP95; | |||
1587 | } | |||
1588 | return 0; | |||
1589 | } | |||
1590 | ||||
1591 | static CharDriverState *qemu_chr_open_pp_fd(int fd) | |||
1592 | { | |||
1593 | CharDriverState *chr; | |||
1594 | ||||
1595 | chr = g_malloc0(sizeof(CharDriverState)); | |||
1596 | chr->opaque = (void *)(intptr_t)fd; | |||
1597 | chr->chr_write = null_chr_write; | |||
1598 | chr->chr_ioctl = pp_ioctl; | |||
1599 | chr->explicit_be_open = true1; | |||
1600 | return chr; | |||
1601 | } | |||
1602 | #endif | |||
1603 | ||||
1604 | #else /* _WIN32 */ | |||
1605 | ||||
1606 | typedef struct { | |||
1607 | int max_size; | |||
1608 | HANDLE hcom, hrecv, hsend; | |||
1609 | OVERLAPPED orecv, osend; | |||
1610 | BOOL fpipe; | |||
1611 | DWORD len; | |||
1612 | } WinCharState; | |||
1613 | ||||
1614 | typedef struct { | |||
1615 | HANDLE hStdIn; | |||
1616 | HANDLE hInputReadyEvent; | |||
1617 | HANDLE hInputDoneEvent; | |||
1618 | HANDLE hInputThread; | |||
1619 | uint8_t win_stdio_buf; | |||
1620 | } WinStdioCharState; | |||
1621 | ||||
1622 | #define NSENDBUF 2048 | |||
1623 | #define NRECVBUF 2048 | |||
1624 | #define MAXCONNECT 1 | |||
1625 | #define NTIMEOUT 5000 | |||
1626 | ||||
1627 | static int win_chr_poll(void *opaque); | |||
1628 | static int win_chr_pipe_poll(void *opaque); | |||
1629 | ||||
1630 | static void win_chr_close(CharDriverState *chr) | |||
1631 | { | |||
1632 | WinCharState *s = chr->opaque; | |||
1633 | ||||
1634 | if (s->hsend) { | |||
1635 | CloseHandle(s->hsend); | |||
1636 | s->hsend = NULL((void*)0); | |||
1637 | } | |||
1638 | if (s->hrecv) { | |||
1639 | CloseHandle(s->hrecv); | |||
1640 | s->hrecv = NULL((void*)0); | |||
1641 | } | |||
1642 | if (s->hcom) { | |||
1643 | CloseHandle(s->hcom); | |||
1644 | s->hcom = NULL((void*)0); | |||
1645 | } | |||
1646 | if (s->fpipe) | |||
1647 | qemu_del_polling_cb(win_chr_pipe_poll, chr); | |||
1648 | else | |||
1649 | qemu_del_polling_cb(win_chr_poll, chr); | |||
1650 | ||||
1651 | qemu_chr_be_event(chr, CHR_EVENT_CLOSED5); | |||
1652 | } | |||
1653 | ||||
1654 | static int win_chr_init(CharDriverState *chr, const char *filename) | |||
1655 | { | |||
1656 | WinCharState *s = chr->opaque; | |||
1657 | COMMCONFIG comcfg; | |||
1658 | COMMTIMEOUTS cto = { 0, 0, 0, 0, 0}; | |||
1659 | COMSTAT comstat; | |||
1660 | DWORD size; | |||
1661 | DWORD err; | |||
1662 | ||||
1663 | s->hsend = CreateEvent(NULL((void*)0), TRUE1, FALSE0, NULL((void*)0)); | |||
1664 | if (!s->hsend) { | |||
1665 | fprintf(stderrstderr, "Failed CreateEvent\n"); | |||
1666 | goto fail; | |||
1667 | } | |||
1668 | s->hrecv = CreateEvent(NULL((void*)0), TRUE1, FALSE0, NULL((void*)0)); | |||
1669 | if (!s->hrecv) { | |||
1670 | fprintf(stderrstderr, "Failed CreateEvent\n"); | |||
1671 | goto fail; | |||
1672 | } | |||
1673 | ||||
1674 | s->hcom = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL((void*)0), | |||
1675 | OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); | |||
1676 | if (s->hcom == INVALID_HANDLE_VALUE) { | |||
1677 | fprintf(stderrstderr, "Failed CreateFile (%lu)\n", GetLastError()); | |||
1678 | s->hcom = NULL((void*)0); | |||
1679 | goto fail; | |||
1680 | } | |||
1681 | ||||
1682 | if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) { | |||
1683 | fprintf(stderrstderr, "Failed SetupComm\n"); | |||
1684 | goto fail; | |||
1685 | } | |||
1686 | ||||
1687 | ZeroMemory(&comcfg, sizeof(COMMCONFIG)); | |||
1688 | size = sizeof(COMMCONFIG); | |||
1689 | GetDefaultCommConfig(filename, &comcfg, &size); | |||
1690 | comcfg.dcb.DCBlength = sizeof(DCB); | |||
1691 | CommConfigDialog(filename, NULL((void*)0), &comcfg); | |||
1692 | ||||
1693 | if (!SetCommState(s->hcom, &comcfg.dcb)) { | |||
1694 | fprintf(stderrstderr, "Failed SetCommState\n"); | |||
1695 | goto fail; | |||
1696 | } | |||
1697 | ||||
1698 | if (!SetCommMask(s->hcom, EV_ERR)) { | |||
1699 | fprintf(stderrstderr, "Failed SetCommMask\n"); | |||
1700 | goto fail; | |||
1701 | } | |||
1702 | ||||
1703 | cto.ReadIntervalTimeout = MAXDWORD; | |||
1704 | if (!SetCommTimeouts(s->hcom, &cto)) { | |||
1705 | fprintf(stderrstderr, "Failed SetCommTimeouts\n"); | |||
1706 | goto fail; | |||
1707 | } | |||
1708 | ||||
1709 | if (!ClearCommError(s->hcom, &err, &comstat)) { | |||
1710 | fprintf(stderrstderr, "Failed ClearCommError\n"); | |||
1711 | goto fail; | |||
1712 | } | |||
1713 | qemu_add_polling_cb(win_chr_poll, chr); | |||
1714 | return 0; | |||
1715 | ||||
1716 | fail: | |||
1717 | win_chr_close(chr); | |||
1718 | return -1; | |||
1719 | } | |||
1720 | ||||
1721 | static int win_chr_write(CharDriverState *chr, const uint8_t *buf, int len1) | |||
1722 | { | |||
1723 | WinCharState *s = chr->opaque; | |||
1724 | DWORD len, ret, size, err; | |||
1725 | ||||
1726 | len = len1; | |||
1727 | ZeroMemory(&s->osend, sizeof(s->osend)); | |||
1728 | s->osend.hEvent = s->hsend; | |||
1729 | while (len > 0) { | |||
1730 | if (s->hsend) | |||
1731 | ret = WriteFile(s->hcom, buf, len, &size, &s->osend); | |||
1732 | else | |||
1733 | ret = WriteFile(s->hcom, buf, len, &size, NULL((void*)0)); | |||
1734 | if (!ret) { | |||
1735 | err = GetLastError(); | |||
1736 | if (err == ERROR_IO_PENDING) { | |||
1737 | ret = GetOverlappedResult(s->hcom, &s->osend, &size, TRUE1); | |||
1738 | if (ret) { | |||
1739 | buf += size; | |||
1740 | len -= size; | |||
1741 | } else { | |||
1742 | break; | |||
1743 | } | |||
1744 | } else { | |||
1745 | break; | |||
1746 | } | |||
1747 | } else { | |||
1748 | buf += size; | |||
1749 | len -= size; | |||
1750 | } | |||
1751 | } | |||
1752 | return len1 - len; | |||
1753 | } | |||
1754 | ||||
1755 | static int win_chr_read_poll(CharDriverState *chr) | |||
1756 | { | |||
1757 | WinCharState *s = chr->opaque; | |||
1758 | ||||
1759 | s->max_size = qemu_chr_be_can_write(chr); | |||
1760 | return s->max_size; | |||
1761 | } | |||
1762 | ||||
1763 | static void win_chr_readfile(CharDriverState *chr) | |||
1764 | { | |||
1765 | WinCharState *s = chr->opaque; | |||
1766 | int ret, err; | |||
1767 | uint8_t buf[READ_BUF_LEN4096]; | |||
1768 | DWORD size; | |||
1769 | ||||
1770 | ZeroMemory(&s->orecv, sizeof(s->orecv)); | |||
1771 | s->orecv.hEvent = s->hrecv; | |||
1772 | ret = ReadFile(s->hcom, buf, s->len, &size, &s->orecv); | |||
1773 | if (!ret) { | |||
1774 | err = GetLastError(); | |||
1775 | if (err == ERROR_IO_PENDING) { | |||
1776 | ret = GetOverlappedResult(s->hcom, &s->orecv, &size, TRUE1); | |||
1777 | } | |||
1778 | } | |||
1779 | ||||
1780 | if (size > 0) { | |||
1781 | qemu_chr_be_write(chr, buf, size); | |||
1782 | } | |||
1783 | } | |||
1784 | ||||
1785 | static void win_chr_read(CharDriverState *chr) | |||
1786 | { | |||
1787 | WinCharState *s = chr->opaque; | |||
1788 | ||||
1789 | if (s->len > s->max_size) | |||
1790 | s->len = s->max_size; | |||
1791 | if (s->len == 0) | |||
1792 | return; | |||
1793 | ||||
1794 | win_chr_readfile(chr); | |||
1795 | } | |||
1796 | ||||
1797 | static int win_chr_poll(void *opaque) | |||
1798 | { | |||
1799 | CharDriverState *chr = opaque; | |||
1800 | WinCharState *s = chr->opaque; | |||
1801 | COMSTAT status; | |||
1802 | DWORD comerr; | |||
1803 | ||||
1804 | ClearCommError(s->hcom, &comerr, &status); | |||
1805 | if (status.cbInQue > 0) { | |||
1806 | s->len = status.cbInQue; | |||
1807 | win_chr_read_poll(chr); | |||
1808 | win_chr_read(chr); | |||
1809 | return 1; | |||
1810 | } | |||
1811 | return 0; | |||
1812 | } | |||
1813 | ||||
1814 | static CharDriverState *qemu_chr_open_win_path(const char *filename) | |||
1815 | { | |||
1816 | CharDriverState *chr; | |||
1817 | WinCharState *s; | |||
1818 | ||||
1819 | chr = g_malloc0(sizeof(CharDriverState)); | |||
1820 | s = g_malloc0(sizeof(WinCharState)); | |||
1821 | chr->opaque = s; | |||
1822 | chr->chr_write = win_chr_write; | |||
1823 | chr->chr_close = win_chr_close; | |||
1824 | ||||
1825 | if (win_chr_init(chr, filename) < 0) { | |||
1826 | g_free(s); | |||
1827 | g_free(chr); | |||
1828 | return NULL((void*)0); | |||
1829 | } | |||
1830 | return chr; | |||
1831 | } | |||
1832 | ||||
1833 | static int win_chr_pipe_poll(void *opaque) | |||
1834 | { | |||
1835 | CharDriverState *chr = opaque; | |||
1836 | WinCharState *s = chr->opaque; | |||
1837 | DWORD size; | |||
1838 | ||||
1839 | PeekNamedPipe(s->hcom, NULL((void*)0), 0, NULL((void*)0), &size, NULL((void*)0)); | |||
1840 | if (size > 0) { | |||
1841 | s->len = size; | |||
1842 | win_chr_read_poll(chr); | |||
1843 | win_chr_read(chr); | |||
1844 | return 1; | |||
1845 | } | |||
1846 | return 0; | |||
1847 | } | |||
1848 | ||||
1849 | static int win_chr_pipe_init(CharDriverState *chr, const char *filename) | |||
1850 | { | |||
1851 | WinCharState *s = chr->opaque; | |||
1852 | OVERLAPPED ov; | |||
1853 | int ret; | |||
1854 | DWORD size; | |||
1855 | char openname[256]; | |||
1856 | ||||
1857 | s->fpipe = TRUE1; | |||
1858 | ||||
1859 | s->hsend = CreateEvent(NULL((void*)0), TRUE1, FALSE0, NULL((void*)0)); | |||
1860 | if (!s->hsend) { | |||
1861 | fprintf(stderrstderr, "Failed CreateEvent\n"); | |||
1862 | goto fail; | |||
1863 | } | |||
1864 | s->hrecv = CreateEvent(NULL((void*)0), TRUE1, FALSE0, NULL((void*)0)); | |||
1865 | if (!s->hrecv) { | |||
1866 | fprintf(stderrstderr, "Failed CreateEvent\n"); | |||
1867 | goto fail; | |||
1868 | } | |||
1869 | ||||
1870 | snprintf(openname, sizeof(openname), "\\\\.\\pipe\\%s", filename); | |||
1871 | s->hcom = CreateNamedPipe(openname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, | |||
1872 | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | | |||
1873 | PIPE_WAIT, | |||
1874 | MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL((void*)0)); | |||
1875 | if (s->hcom == INVALID_HANDLE_VALUE) { | |||
1876 | fprintf(stderrstderr, "Failed CreateNamedPipe (%lu)\n", GetLastError()); | |||
1877 | s->hcom = NULL((void*)0); | |||
1878 | goto fail; | |||
1879 | } | |||
1880 | ||||
1881 | ZeroMemory(&ov, sizeof(ov)); | |||
1882 | ov.hEvent = CreateEvent(NULL((void*)0), TRUE1, FALSE0, NULL((void*)0)); | |||
1883 | ret = ConnectNamedPipe(s->hcom, &ov); | |||
1884 | if (ret) { | |||
1885 | fprintf(stderrstderr, "Failed ConnectNamedPipe\n"); | |||
1886 | goto fail; | |||
1887 | } | |||
1888 | ||||
1889 | ret = GetOverlappedResult(s->hcom, &ov, &size, TRUE1); | |||
1890 | if (!ret) { | |||
1891 | fprintf(stderrstderr, "Failed GetOverlappedResult\n"); | |||
1892 | if (ov.hEvent) { | |||
1893 | CloseHandle(ov.hEvent); | |||
1894 | ov.hEvent = NULL((void*)0); | |||
1895 | } | |||
1896 | goto fail; | |||
1897 | } | |||
1898 | ||||
1899 | if (ov.hEvent) { | |||
1900 | CloseHandle(ov.hEvent); | |||
1901 | ov.hEvent = NULL((void*)0); | |||
1902 | } | |||
1903 | qemu_add_polling_cb(win_chr_pipe_poll, chr); | |||
1904 | return 0; | |||
1905 | ||||
1906 | fail: | |||
1907 | win_chr_close(chr); | |||
1908 | return -1; | |||
1909 | } | |||
1910 | ||||
1911 | ||||
1912 | static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts) | |||
1913 | { | |||
1914 | const char *filename = opts->device; | |||
1915 | CharDriverState *chr; | |||
1916 | WinCharState *s; | |||
1917 | ||||
1918 | chr = g_malloc0(sizeof(CharDriverState)); | |||
1919 | s = g_malloc0(sizeof(WinCharState)); | |||
1920 | chr->opaque = s; | |||
1921 | chr->chr_write = win_chr_write; | |||
1922 | chr->chr_close = win_chr_close; | |||
1923 | ||||
1924 | if (win_chr_pipe_init(chr, filename) < 0) { | |||
1925 | g_free(s); | |||
1926 | g_free(chr); | |||
1927 | return NULL((void*)0); | |||
1928 | } | |||
1929 | return chr; | |||
1930 | } | |||
1931 | ||||
1932 | static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out) | |||
1933 | { | |||
1934 | CharDriverState *chr; | |||
1935 | WinCharState *s; | |||
1936 | ||||
1937 | chr = g_malloc0(sizeof(CharDriverState)); | |||
1938 | s = g_malloc0(sizeof(WinCharState)); | |||
1939 | s->hcom = fd_out; | |||
1940 | chr->opaque = s; | |||
1941 | chr->chr_write = win_chr_write; | |||
1942 | return chr; | |||
1943 | } | |||
1944 | ||||
1945 | static CharDriverState *qemu_chr_open_win_con(void) | |||
1946 | { | |||
1947 | return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE)); | |||
1948 | } | |||
1949 | ||||
1950 | static int win_stdio_write(CharDriverState *chr, const uint8_t *buf, int len) | |||
1951 | { | |||
1952 | HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); | |||
1953 | DWORD dwSize; | |||
1954 | int len1; | |||
1955 | ||||
1956 | len1 = len; | |||
1957 | ||||
1958 | while (len1 > 0) { | |||
1959 | if (!WriteFile(hStdOut, buf, len1, &dwSize, NULL((void*)0))) { | |||
1960 | break; | |||
1961 | } | |||
1962 | buf += dwSize; | |||
1963 | len1 -= dwSize; | |||
1964 | } | |||
1965 | ||||
1966 | return len - len1; | |||
1967 | } | |||
1968 | ||||
1969 | static void win_stdio_wait_func(void *opaque) | |||
1970 | { | |||
1971 | CharDriverState *chr = opaque; | |||
1972 | WinStdioCharState *stdio = chr->opaque; | |||
1973 | INPUT_RECORD buf[4]; | |||
1974 | int ret; | |||
1975 | DWORD dwSize; | |||
1976 | int i; | |||
1977 | ||||
1978 | ret = ReadConsoleInput(stdio->hStdIn, buf, ARRAY_SIZE(buf)(sizeof(buf) / sizeof((buf)[0])), &dwSize); | |||
1979 | ||||
1980 | if (!ret) { | |||
1981 | /* Avoid error storm */ | |||
1982 | qemu_del_wait_object(stdio->hStdIn, NULL((void*)0), NULL((void*)0)); | |||
1983 | return; | |||
1984 | } | |||
1985 | ||||
1986 | for (i = 0; i < dwSize; i++) { | |||
1987 | KEY_EVENT_RECORD *kev = &buf[i].Event.KeyEvent; | |||
1988 | ||||
1989 | if (buf[i].EventType == KEY_EVENT0633 && kev->bKeyDown) { | |||
1990 | int j; | |||
1991 | if (kev->uChar.AsciiChar != 0) { | |||
1992 | for (j = 0; j < kev->wRepeatCount; j++) { | |||
1993 | if (qemu_chr_be_can_write(chr)) { | |||
1994 | uint8_t c = kev->uChar.AsciiChar; | |||
1995 | qemu_chr_be_write(chr, &c, 1); | |||
1996 | } | |||
1997 | } | |||
1998 | } | |||
1999 | } | |||
2000 | } | |||
2001 | } | |||
2002 | ||||
2003 | static DWORD WINAPI win_stdio_thread(LPVOID param) | |||
2004 | { | |||
2005 | CharDriverState *chr = param; | |||
2006 | WinStdioCharState *stdio = chr->opaque; | |||
2007 | int ret; | |||
2008 | DWORD dwSize; | |||
2009 | ||||
2010 | while (1) { | |||
2011 | ||||
2012 | /* Wait for one byte */ | |||
2013 | ret = ReadFile(stdio->hStdIn, &stdio->win_stdio_buf, 1, &dwSize, NULL((void*)0)); | |||
2014 | ||||
2015 | /* Exit in case of error, continue if nothing read */ | |||
2016 | if (!ret) { | |||
2017 | break; | |||
2018 | } | |||
2019 | if (!dwSize) { | |||
2020 | continue; | |||
2021 | } | |||
2022 | ||||
2023 | /* Some terminal emulator returns \r\n for Enter, just pass \n */ | |||
2024 | if (stdio->win_stdio_buf == '\r') { | |||
2025 | continue; | |||
2026 | } | |||
2027 | ||||
2028 | /* Signal the main thread and wait until the byte was eaten */ | |||
2029 | if (!SetEvent(stdio->hInputReadyEvent)) { | |||
2030 | break; | |||
2031 | } | |||
2032 | if (WaitForSingleObject(stdio->hInputDoneEvent, INFINITE) | |||
2033 | != WAIT_OBJECT_0) { | |||
2034 | break; | |||
2035 | } | |||
2036 | } | |||
2037 | ||||
2038 | qemu_del_wait_object(stdio->hInputReadyEvent, NULL((void*)0), NULL((void*)0)); | |||
2039 | return 0; | |||
2040 | } | |||
2041 | ||||
2042 | static void win_stdio_thread_wait_func(void *opaque) | |||
2043 | { | |||
2044 | CharDriverState *chr = opaque; | |||
2045 | WinStdioCharState *stdio = chr->opaque; | |||
2046 | ||||
2047 | if (qemu_chr_be_can_write(chr)) { | |||
2048 | qemu_chr_be_write(chr, &stdio->win_stdio_buf, 1); | |||
2049 | } | |||
2050 | ||||
2051 | SetEvent(stdio->hInputDoneEvent); | |||
2052 | } | |||
2053 | ||||
2054 | static void qemu_chr_set_echo_win_stdio(CharDriverState *chr, bool_Bool echo) | |||
2055 | { | |||
2056 | WinStdioCharState *stdio = chr->opaque; | |||
2057 | DWORD dwMode = 0; | |||
2058 | ||||
2059 | GetConsoleMode(stdio->hStdIn, &dwMode); | |||
2060 | ||||
2061 | if (echo) { | |||
2062 | SetConsoleMode(stdio->hStdIn, dwMode | ENABLE_ECHO_INPUT); | |||
2063 | } else { | |||
2064 | SetConsoleMode(stdio->hStdIn, dwMode & ~ENABLE_ECHO_INPUT); | |||
2065 | } | |||
2066 | } | |||
2067 | ||||
2068 | static void win_stdio_close(CharDriverState *chr) | |||
2069 | { | |||
2070 | WinStdioCharState *stdio = chr->opaque; | |||
2071 | ||||
2072 | if (stdio->hInputReadyEvent != INVALID_HANDLE_VALUE) { | |||
2073 | CloseHandle(stdio->hInputReadyEvent); | |||
2074 | } | |||
2075 | if (stdio->hInputDoneEvent != INVALID_HANDLE_VALUE) { | |||
2076 | CloseHandle(stdio->hInputDoneEvent); | |||
2077 | } | |||
2078 | if (stdio->hInputThread != INVALID_HANDLE_VALUE) { | |||
2079 | TerminateThread(stdio->hInputThread, 0); | |||
2080 | } | |||
2081 | ||||
2082 | g_free(chr->opaque); | |||
2083 | g_free(chr); | |||
2084 | } | |||
2085 | ||||
2086 | static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts) | |||
2087 | { | |||
2088 | CharDriverState *chr; | |||
2089 | WinStdioCharState *stdio; | |||
2090 | DWORD dwMode; | |||
2091 | int is_console = 0; | |||
2092 | ||||
2093 | chr = g_malloc0(sizeof(CharDriverState)); | |||
2094 | stdio = g_malloc0(sizeof(WinStdioCharState)); | |||
2095 | ||||
2096 | stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE); | |||
2097 | if (stdio->hStdIn == INVALID_HANDLE_VALUE) { | |||
2098 | fprintf(stderrstderr, "cannot open stdio: invalid handle\n"); | |||
2099 | exit(1); | |||
2100 | } | |||
2101 | ||||
2102 | is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0; | |||
2103 | ||||
2104 | chr->opaque = stdio; | |||
2105 | chr->chr_write = win_stdio_write; | |||
2106 | chr->chr_close = win_stdio_close; | |||
2107 | ||||
2108 | if (is_console) { | |||
2109 | if (qemu_add_wait_object(stdio->hStdIn, | |||
2110 | win_stdio_wait_func, chr)) { | |||
2111 | fprintf(stderrstderr, "qemu_add_wait_object: failed\n"); | |||
2112 | } | |||
2113 | } else { | |||
2114 | DWORD dwId; | |||
2115 | ||||
2116 | stdio->hInputReadyEvent = CreateEvent(NULL((void*)0), FALSE0, FALSE0, NULL((void*)0)); | |||
2117 | stdio->hInputDoneEvent = CreateEvent(NULL((void*)0), FALSE0, FALSE0, NULL((void*)0)); | |||
2118 | stdio->hInputThread = CreateThread(NULL((void*)0), 0, win_stdio_thread, | |||
2119 | chr, 0, &dwId); | |||
2120 | ||||
2121 | if (stdio->hInputThread == INVALID_HANDLE_VALUE | |||
2122 | || stdio->hInputReadyEvent == INVALID_HANDLE_VALUE | |||
2123 | || stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) { | |||
2124 | fprintf(stderrstderr, "cannot create stdio thread or event\n"); | |||
2125 | exit(1); | |||
2126 | } | |||
2127 | if (qemu_add_wait_object(stdio->hInputReadyEvent, | |||
2128 | win_stdio_thread_wait_func, chr)) { | |||
2129 | fprintf(stderrstderr, "qemu_add_wait_object: failed\n"); | |||
2130 | } | |||
2131 | } | |||
2132 | ||||
2133 | dwMode |= ENABLE_LINE_INPUT; | |||
2134 | ||||
2135 | if (is_console) { | |||
2136 | /* set the terminal in raw mode */ | |||
2137 | /* ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS */ | |||
2138 | dwMode |= ENABLE_PROCESSED_INPUT; | |||
2139 | } | |||
2140 | ||||
2141 | SetConsoleMode(stdio->hStdIn, dwMode); | |||
2142 | ||||
2143 | chr->chr_set_echo = qemu_chr_set_echo_win_stdio; | |||
2144 | qemu_chr_fe_set_echo(chr, false0); | |||
2145 | ||||
2146 | return chr; | |||
2147 | } | |||
2148 | #endif /* !_WIN32 */ | |||
2149 | ||||
2150 | ||||
2151 | /***********************************************************/ | |||
2152 | /* UDP Net console */ | |||
2153 | ||||
2154 | typedef struct { | |||
2155 | int fd; | |||
2156 | GIOChannel *chan; | |||
2157 | uint8_t buf[READ_BUF_LEN4096]; | |||
2158 | int bufcnt; | |||
2159 | int bufptr; | |||
2160 | int max_size; | |||
2161 | } NetCharDriver; | |||
2162 | ||||
2163 | static int udp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) | |||
2164 | { | |||
2165 | NetCharDriver *s = chr->opaque; | |||
2166 | gsize bytes_written; | |||
2167 | GIOStatus status; | |||
2168 | ||||
2169 | status = g_io_channel_write_chars(s->chan, (const gchar *)buf, len, &bytes_written, NULL((void*)0)); | |||
2170 | if (status == G_IO_STATUS_EOF) { | |||
2171 | return 0; | |||
2172 | } else if (status != G_IO_STATUS_NORMAL) { | |||
2173 | return -1; | |||
2174 | } | |||
2175 | ||||
2176 | return bytes_written; | |||
2177 | } | |||
2178 | ||||
2179 | static int udp_chr_read_poll(void *opaque) | |||
2180 | { | |||
2181 | CharDriverState *chr = opaque; | |||
2182 | NetCharDriver *s = chr->opaque; | |||
2183 | ||||
2184 | s->max_size = qemu_chr_be_can_write(chr); | |||
2185 | ||||
2186 | /* If there were any stray characters in the queue process them | |||
2187 | * first | |||
2188 | */ | |||
2189 | while (s->max_size > 0 && s->bufptr < s->bufcnt) { | |||
2190 | qemu_chr_be_write(chr, &s->buf[s->bufptr], 1); | |||
2191 | s->bufptr++; | |||
2192 | s->max_size = qemu_chr_be_can_write(chr); | |||
2193 | } | |||
2194 | return s->max_size; | |||
2195 | } | |||
2196 | ||||
2197 | static gboolean udp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) | |||
2198 | { | |||
2199 | CharDriverState *chr = opaque; | |||
2200 | NetCharDriver *s = chr->opaque; | |||
2201 | gsize bytes_read = 0; | |||
2202 | GIOStatus status; | |||
2203 | ||||
2204 | if (s->max_size == 0) { | |||
2205 | return TRUE1; | |||
2206 | } | |||
2207 | status = g_io_channel_read_chars(s->chan, (gchar *)s->buf, sizeof(s->buf), | |||
2208 | &bytes_read, NULL((void*)0)); | |||
2209 | s->bufcnt = bytes_read; | |||
2210 | s->bufptr = s->bufcnt; | |||
2211 | if (status != G_IO_STATUS_NORMAL) { | |||
2212 | remove_fd_in_watch(chr); | |||
2213 | return FALSE0; | |||
2214 | } | |||
2215 | ||||
2216 | s->bufptr = 0; | |||
2217 | while (s->max_size > 0 && s->bufptr < s->bufcnt) { | |||
2218 | qemu_chr_be_write(chr, &s->buf[s->bufptr], 1); | |||
2219 | s->bufptr++; | |||
2220 | s->max_size = qemu_chr_be_can_write(chr); | |||
2221 | } | |||
2222 | ||||
2223 | return TRUE1; | |||
2224 | } | |||
2225 | ||||
2226 | static void udp_chr_update_read_handler(CharDriverState *chr) | |||
2227 | { | |||
2228 | NetCharDriver *s = chr->opaque; | |||
2229 | ||||
2230 | remove_fd_in_watch(chr); | |||
2231 | if (s->chan) { | |||
2232 | chr->fd_in_tag = io_add_watch_poll(s->chan, udp_chr_read_poll, | |||
2233 | udp_chr_read, chr); | |||
2234 | } | |||
2235 | } | |||
2236 | ||||
2237 | static void udp_chr_close(CharDriverState *chr) | |||
2238 | { | |||
2239 | NetCharDriver *s = chr->opaque; | |||
2240 | ||||
2241 | remove_fd_in_watch(chr); | |||
2242 | if (s->chan) { | |||
2243 | g_io_channel_unref(s->chan); | |||
2244 | closesocket(s->fd)close(s->fd); | |||
2245 | } | |||
2246 | g_free(s); | |||
2247 | qemu_chr_be_event(chr, CHR_EVENT_CLOSED5); | |||
2248 | } | |||
2249 | ||||
2250 | static CharDriverState *qemu_chr_open_udp_fd(int fd) | |||
2251 | { | |||
2252 | CharDriverState *chr = NULL((void*)0); | |||
2253 | NetCharDriver *s = NULL((void*)0); | |||
2254 | ||||
2255 | chr = g_malloc0(sizeof(CharDriverState)); | |||
2256 | s = g_malloc0(sizeof(NetCharDriver)); | |||
2257 | ||||
2258 | s->fd = fd; | |||
2259 | s->chan = io_channel_from_socket(s->fd); | |||
2260 | s->bufcnt = 0; | |||
2261 | s->bufptr = 0; | |||
2262 | chr->opaque = s; | |||
2263 | chr->chr_write = udp_chr_write; | |||
2264 | chr->chr_update_read_handler = udp_chr_update_read_handler; | |||
2265 | chr->chr_close = udp_chr_close; | |||
2266 | /* be isn't opened until we get a connection */ | |||
2267 | chr->explicit_be_open = true1; | |||
2268 | return chr; | |||
2269 | } | |||
2270 | ||||
2271 | static CharDriverState *qemu_chr_open_udp(QemuOpts *opts) | |||
2272 | { | |||
2273 | Error *local_err = NULL((void*)0); | |||
2274 | int fd = -1; | |||
2275 | ||||
2276 | fd = inet_dgram_opts(opts, &local_err); | |||
2277 | if (fd < 0) { | |||
2278 | qerror_report_err(local_err); | |||
2279 | error_free(local_err); | |||
2280 | return NULL((void*)0); | |||
2281 | } | |||
2282 | return qemu_chr_open_udp_fd(fd); | |||
2283 | } | |||
2284 | ||||
2285 | /***********************************************************/ | |||
2286 | /* TCP Net console */ | |||
2287 | ||||
2288 | typedef struct { | |||
2289 | ||||
2290 | GIOChannel *chan, *listen_chan; | |||
2291 | guint listen_tag; | |||
2292 | int fd, listen_fd; | |||
2293 | int connected; | |||
2294 | int max_size; | |||
2295 | int do_telnetopt; | |||
2296 | int do_nodelay; | |||
2297 | int is_unix; | |||
2298 | int msgfd; | |||
2299 | } TCPCharDriver; | |||
2300 | ||||
2301 | static gboolean tcp_chr_accept(GIOChannel *chan, GIOCondition cond, void *opaque); | |||
2302 | ||||
2303 | static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) | |||
2304 | { | |||
2305 | TCPCharDriver *s = chr->opaque; | |||
2306 | if (s->connected) { | |||
2307 | return io_channel_send(s->chan, buf, len); | |||
2308 | } else { | |||
2309 | /* XXX: indicate an error ? */ | |||
2310 | return len; | |||
2311 | } | |||
2312 | } | |||
2313 | ||||
2314 | static int tcp_chr_read_poll(void *opaque) | |||
2315 | { | |||
2316 | CharDriverState *chr = opaque; | |||
2317 | TCPCharDriver *s = chr->opaque; | |||
2318 | if (!s->connected) | |||
2319 | return 0; | |||
2320 | s->max_size = qemu_chr_be_can_write(chr); | |||
2321 | return s->max_size; | |||
2322 | } | |||
2323 | ||||
2324 | #define IAC255 255 | |||
2325 | #define IAC_BREAK243 243 | |||
2326 | static void tcp_chr_process_IAC_bytes(CharDriverState *chr, | |||
2327 | TCPCharDriver *s, | |||
2328 | uint8_t *buf, int *size) | |||
2329 | { | |||
2330 | /* Handle any telnet client's basic IAC options to satisfy char by | |||
2331 | * char mode with no echo. All IAC options will be removed from | |||
2332 | * the buf and the do_telnetopt variable will be used to track the | |||
2333 | * state of the width of the IAC information. | |||
2334 | * | |||
2335 | * IAC commands come in sets of 3 bytes with the exception of the | |||
2336 | * "IAC BREAK" command and the double IAC. | |||
2337 | */ | |||
2338 | ||||
2339 | int i; | |||
2340 | int j = 0; | |||
2341 | ||||
2342 | for (i = 0; i < *size; i++) { | |||
2343 | if (s->do_telnetopt > 1) { | |||
2344 | if ((unsigned char)buf[i] == IAC255 && s->do_telnetopt == 2) { | |||
2345 | /* Double IAC means send an IAC */ | |||
2346 | if (j != i) | |||
2347 | buf[j] = buf[i]; | |||
2348 | j++; | |||
2349 | s->do_telnetopt = 1; | |||
2350 | } else { | |||
2351 | if ((unsigned char)buf[i] == IAC_BREAK243 && s->do_telnetopt == 2) { | |||
2352 | /* Handle IAC break commands by sending a serial break */ | |||
2353 | qemu_chr_be_event(chr, CHR_EVENT_BREAK0); | |||
2354 | s->do_telnetopt++; | |||
2355 | } | |||
2356 | s->do_telnetopt++; | |||
2357 | } | |||
2358 | if (s->do_telnetopt >= 4) { | |||
2359 | s->do_telnetopt = 1; | |||
2360 | } | |||
2361 | } else { | |||
2362 | if ((unsigned char)buf[i] == IAC255) { | |||
2363 | s->do_telnetopt = 2; | |||
2364 | } else { | |||
2365 | if (j != i) | |||
2366 | buf[j] = buf[i]; | |||
2367 | j++; | |||
2368 | } | |||
2369 | } | |||
2370 | } | |||
2371 | *size = j; | |||
2372 | } | |||
2373 | ||||
2374 | static int tcp_get_msgfd(CharDriverState *chr) | |||
2375 | { | |||
2376 | TCPCharDriver *s = chr->opaque; | |||
2377 | int fd = s->msgfd; | |||
2378 | s->msgfd = -1; | |||
2379 | return fd; | |||
2380 | } | |||
2381 | ||||
2382 | #ifndef _WIN32 | |||
2383 | static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg) | |||
2384 | { | |||
2385 | TCPCharDriver *s = chr->opaque; | |||
2386 | struct cmsghdr *cmsg; | |||
2387 | ||||
2388 | for (cmsg = CMSG_FIRSTHDR(msg)((size_t) (msg)->msg_controllen >= sizeof (struct cmsghdr ) ? (struct cmsghdr *) (msg)->msg_control : (struct cmsghdr *) 0); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)__cmsg_nxthdr (msg, cmsg)) { | |||
2389 | int fd; | |||
2390 | ||||
2391 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t ) ~(sizeof (size_t) - 1)) + (sizeof(int))) || | |||
2392 | cmsg->cmsg_level != SOL_SOCKET1 || | |||
2393 | cmsg->cmsg_type != SCM_RIGHTSSCM_RIGHTS) | |||
2394 | continue; | |||
2395 | ||||
2396 | fd = *((int *)CMSG_DATA(cmsg)((cmsg)->__cmsg_data)); | |||
2397 | if (fd < 0) | |||
2398 | continue; | |||
2399 | ||||
2400 | /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */ | |||
2401 | qemu_set_block(fd); | |||
2402 | ||||
2403 | #ifndef MSG_CMSG_CLOEXECMSG_CMSG_CLOEXEC | |||
2404 | qemu_set_cloexec(fd); | |||
2405 | #endif | |||
2406 | if (s->msgfd != -1) | |||
2407 | close(s->msgfd); | |||
2408 | s->msgfd = fd; | |||
2409 | } | |||
2410 | } | |||
2411 | ||||
2412 | static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) | |||
2413 | { | |||
2414 | TCPCharDriver *s = chr->opaque; | |||
2415 | struct msghdr msg = { NULL((void*)0), }; | |||
2416 | struct iovec iov[1]; | |||
2417 | union { | |||
2418 | struct cmsghdr cmsg; | |||
2419 | char control[CMSG_SPACE(sizeof(int))((((sizeof(int)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr)) + sizeof (size_t ) - 1) & (size_t) ~(sizeof (size_t) - 1)))]; | |||
2420 | } msg_control; | |||
2421 | int flags = 0; | |||
2422 | ssize_t ret; | |||
2423 | ||||
2424 | iov[0].iov_base = buf; | |||
2425 | iov[0].iov_len = len; | |||
2426 | ||||
2427 | msg.msg_iov = iov; | |||
2428 | msg.msg_iovlen = 1; | |||
2429 | msg.msg_control = &msg_control; | |||
2430 | msg.msg_controllen = sizeof(msg_control); | |||
2431 | ||||
2432 | #ifdef MSG_CMSG_CLOEXECMSG_CMSG_CLOEXEC | |||
2433 | flags |= MSG_CMSG_CLOEXECMSG_CMSG_CLOEXEC; | |||
2434 | #endif | |||
2435 | ret = recvmsg(s->fd, &msg, flags); | |||
2436 | if (ret > 0 && s->is_unix) { | |||
2437 | unix_process_msgfd(chr, &msg); | |||
2438 | } | |||
2439 | ||||
2440 | return ret; | |||
2441 | } | |||
2442 | #else | |||
2443 | static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) | |||
2444 | { | |||
2445 | TCPCharDriver *s = chr->opaque; | |||
2446 | return qemu_recv(s->fd, buf, len, 0)recv(s->fd, buf, len, 0); | |||
2447 | } | |||
2448 | #endif | |||
2449 | ||||
2450 | static GSource *tcp_chr_add_watch(CharDriverState *chr, GIOCondition cond) | |||
2451 | { | |||
2452 | TCPCharDriver *s = chr->opaque; | |||
2453 | return g_io_create_watch(s->chan, cond); | |||
2454 | } | |||
2455 | ||||
2456 | static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) | |||
2457 | { | |||
2458 | CharDriverState *chr = opaque; | |||
2459 | TCPCharDriver *s = chr->opaque; | |||
2460 | uint8_t buf[READ_BUF_LEN4096]; | |||
2461 | int len, size; | |||
2462 | ||||
2463 | if (!s->connected || s->max_size <= 0) { | |||
2464 | return TRUE1; | |||
2465 | } | |||
2466 | len = sizeof(buf); | |||
2467 | if (len > s->max_size) | |||
2468 | len = s->max_size; | |||
2469 | size = tcp_chr_recv(chr, (void *)buf, len); | |||
2470 | if (size == 0) { | |||
2471 | /* connection closed */ | |||
2472 | s->connected = 0; | |||
2473 | if (s->listen_chan) { | |||
2474 | s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN, tcp_chr_accept, chr); | |||
2475 | } | |||
2476 | remove_fd_in_watch(chr); | |||
2477 | g_io_channel_unref(s->chan); | |||
2478 | s->chan = NULL((void*)0); | |||
2479 | closesocket(s->fd)close(s->fd); | |||
2480 | s->fd = -1; | |||
2481 | qemu_chr_be_event(chr, CHR_EVENT_CLOSED5); | |||
2482 | } else if (size > 0) { | |||
2483 | if (s->do_telnetopt) | |||
2484 | tcp_chr_process_IAC_bytes(chr, s, buf, &size); | |||
2485 | if (size > 0) | |||
2486 | qemu_chr_be_write(chr, buf, size); | |||
2487 | } | |||
2488 | ||||
2489 | return TRUE1; | |||
2490 | } | |||
2491 | ||||
2492 | #ifndef _WIN32 | |||
2493 | CharDriverState *qemu_chr_open_eventfd(int eventfd) | |||
2494 | { | |||
2495 | return qemu_chr_open_fd(eventfd, eventfd); | |||
2496 | } | |||
2497 | #endif | |||
2498 | ||||
2499 | static void tcp_chr_connect(void *opaque) | |||
2500 | { | |||
2501 | CharDriverState *chr = opaque; | |||
2502 | TCPCharDriver *s = chr->opaque; | |||
2503 | ||||
2504 | s->connected = 1; | |||
2505 | if (s->chan) { | |||
2506 | chr->fd_in_tag = io_add_watch_poll(s->chan, tcp_chr_read_poll, | |||
2507 | tcp_chr_read, chr); | |||
2508 | } | |||
2509 | qemu_chr_be_generic_open(chr); | |||
2510 | } | |||
2511 | ||||
2512 | #define IACSET(x,a,b,c)x[0] = a; x[1] = b; x[2] = c; x[0] = a; x[1] = b; x[2] = c; | |||
2513 | static void tcp_chr_telnet_init(int fd) | |||
2514 | { | |||
2515 | char buf[3]; | |||
2516 | /* Send the telnet negotion to put telnet in binary, no echo, single char mode */ | |||
2517 | IACSET(buf, 0xff, 0xfb, 0x01)buf[0] = 0xff; buf[1] = 0xfb; buf[2] = 0x01;; /* IAC WILL ECHO */ | |||
2518 | send(fd, (char *)buf, 3, 0); | |||
2519 | IACSET(buf, 0xff, 0xfb, 0x03)buf[0] = 0xff; buf[1] = 0xfb; buf[2] = 0x03;; /* IAC WILL Suppress go ahead */ | |||
2520 | send(fd, (char *)buf, 3, 0); | |||
2521 | IACSET(buf, 0xff, 0xfb, 0x00)buf[0] = 0xff; buf[1] = 0xfb; buf[2] = 0x00;; /* IAC WILL Binary */ | |||
2522 | send(fd, (char *)buf, 3, 0); | |||
2523 | IACSET(buf, 0xff, 0xfd, 0x00)buf[0] = 0xff; buf[1] = 0xfd; buf[2] = 0x00;; /* IAC DO Binary */ | |||
2524 | send(fd, (char *)buf, 3, 0); | |||
2525 | } | |||
2526 | ||||
2527 | static int tcp_chr_add_client(CharDriverState *chr, int fd) | |||
2528 | { | |||
2529 | TCPCharDriver *s = chr->opaque; | |||
2530 | if (s->fd != -1) | |||
2531 | return -1; | |||
2532 | ||||
2533 | qemu_set_nonblock(fd); | |||
2534 | if (s->do_nodelay) | |||
2535 | socket_set_nodelay(fd); | |||
2536 | s->fd = fd; | |||
2537 | s->chan = io_channel_from_socket(fd); | |||
2538 | if (s->listen_tag) { | |||
2539 | g_source_remove(s->listen_tag); | |||
2540 | s->listen_tag = 0; | |||
2541 | } | |||
2542 | tcp_chr_connect(chr); | |||
2543 | ||||
2544 | return 0; | |||
2545 | } | |||
2546 | ||||
2547 | static gboolean tcp_chr_accept(GIOChannel *channel, GIOCondition cond, void *opaque) | |||
2548 | { | |||
2549 | CharDriverState *chr = opaque; | |||
2550 | TCPCharDriver *s = chr->opaque; | |||
2551 | struct sockaddr_in saddr; | |||
2552 | #ifndef _WIN32 | |||
2553 | struct sockaddr_un uaddr; | |||
2554 | #endif | |||
2555 | struct sockaddr *addr; | |||
2556 | socklen_t len; | |||
2557 | int fd; | |||
2558 | ||||
2559 | for(;;) { | |||
2560 | #ifndef _WIN32 | |||
2561 | if (s->is_unix) { | |||
2562 | len = sizeof(uaddr); | |||
2563 | addr = (struct sockaddr *)&uaddr; | |||
2564 | } else | |||
2565 | #endif | |||
2566 | { | |||
2567 | len = sizeof(saddr); | |||
2568 | addr = (struct sockaddr *)&saddr; | |||
2569 | } | |||
2570 | fd = qemu_accept(s->listen_fd, addr, &len); | |||
2571 | if (fd < 0 && errno(*__errno_location ()) != EINTR4) { | |||
2572 | s->listen_tag = 0; | |||
2573 | return FALSE0; | |||
2574 | } else if (fd >= 0) { | |||
2575 | if (s->do_telnetopt) | |||
2576 | tcp_chr_telnet_init(fd); | |||
2577 | break; | |||
2578 | } | |||
2579 | } | |||
2580 | if (tcp_chr_add_client(chr, fd) < 0) | |||
2581 | close(fd); | |||
2582 | ||||
2583 | return TRUE1; | |||
2584 | } | |||
2585 | ||||
2586 | static void tcp_chr_close(CharDriverState *chr) | |||
2587 | { | |||
2588 | TCPCharDriver *s = chr->opaque; | |||
2589 | if (s->fd >= 0) { | |||
2590 | remove_fd_in_watch(chr); | |||
2591 | if (s->chan) { | |||
2592 | g_io_channel_unref(s->chan); | |||
2593 | } | |||
2594 | closesocket(s->fd)close(s->fd); | |||
2595 | } | |||
2596 | if (s->listen_fd >= 0) { | |||
2597 | if (s->listen_tag) { | |||
2598 | g_source_remove(s->listen_tag); | |||
2599 | s->listen_tag = 0; | |||
2600 | } | |||
2601 | if (s->listen_chan) { | |||
2602 | g_io_channel_unref(s->listen_chan); | |||
2603 | } | |||
2604 | closesocket(s->listen_fd)close(s->listen_fd); | |||
2605 | } | |||
2606 | g_free(s); | |||
2607 | qemu_chr_be_event(chr, CHR_EVENT_CLOSED5); | |||
2608 | } | |||
2609 | ||||
2610 | static CharDriverState *qemu_chr_open_socket_fd(int fd, bool_Bool do_nodelay, | |||
2611 | bool_Bool is_listen, bool_Bool is_telnet, | |||
2612 | bool_Bool is_waitconnect, | |||
2613 | Error **errp) | |||
2614 | { | |||
2615 | CharDriverState *chr = NULL((void*)0); | |||
2616 | TCPCharDriver *s = NULL((void*)0); | |||
2617 | char host[NI_MAXHOST1025], serv[NI_MAXSERV32]; | |||
2618 | const char *left = "", *right = ""; | |||
2619 | struct sockaddr_storage ss; | |||
2620 | socklen_t ss_len = sizeof(ss); | |||
2621 | ||||
2622 | memset(&ss, 0, ss_len); | |||
2623 | if (getsockname(fd, (struct sockaddr *) &ss, &ss_len) != 0) { | |||
2624 | error_setg_errno(errp, errno, "getsockname")error_set_errno(errp, (*__errno_location ()), ERROR_CLASS_GENERIC_ERROR , "getsockname"); | |||
2625 | return NULL((void*)0); | |||
2626 | } | |||
2627 | ||||
2628 | chr = g_malloc0(sizeof(CharDriverState)); | |||
2629 | s = g_malloc0(sizeof(TCPCharDriver)); | |||
2630 | ||||
2631 | s->connected = 0; | |||
2632 | s->fd = -1; | |||
2633 | s->listen_fd = -1; | |||
2634 | s->msgfd = -1; | |||
2635 | ||||
2636 | chr->filename = g_malloc(256); | |||
2637 | switch (ss.ss_family) { | |||
2638 | #ifndef _WIN32 | |||
2639 | case AF_UNIX1: | |||
2640 | s->is_unix = 1; | |||
2641 | snprintf(chr->filename, 256, "unix:%s%s", | |||
2642 | ((struct sockaddr_un *)(&ss))->sun_path, | |||
2643 | is_listen ? ",server" : ""); | |||
2644 | break; | |||
2645 | #endif | |||
2646 | case AF_INET610: | |||
2647 | left = "["; | |||
2648 | right = "]"; | |||
2649 | /* fall through */ | |||
2650 | case AF_INET2: | |||
2651 | s->do_nodelay = do_nodelay; | |||
2652 | getnameinfo((struct sockaddr *) &ss, ss_len, host, sizeof(host), | |||
2653 | serv, sizeof(serv), NI_NUMERICHOST1 | NI_NUMERICSERV2); | |||
2654 | snprintf(chr->filename, 256, "%s:%s%s%s:%s%s", | |||
2655 | is_telnet ? "telnet" : "tcp", | |||
2656 | left, host, right, serv, | |||
2657 | is_listen ? ",server" : ""); | |||
2658 | break; | |||
2659 | } | |||
2660 | ||||
2661 | chr->opaque = s; | |||
2662 | chr->chr_write = tcp_chr_write; | |||
2663 | chr->chr_close = tcp_chr_close; | |||
2664 | chr->get_msgfd = tcp_get_msgfd; | |||
2665 | chr->chr_add_client = tcp_chr_add_client; | |||
2666 | chr->chr_add_watch = tcp_chr_add_watch; | |||
2667 | /* be isn't opened until we get a connection */ | |||
2668 | chr->explicit_be_open = true1; | |||
2669 | ||||
2670 | if (is_listen) { | |||
2671 | s->listen_fd = fd; | |||
2672 | s->listen_chan = io_channel_from_socket(s->listen_fd); | |||
2673 | s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN, tcp_chr_accept, chr); | |||
2674 | if (is_telnet) { | |||
2675 | s->do_telnetopt = 1; | |||
2676 | } | |||
2677 | } else { | |||
2678 | s->connected = 1; | |||
2679 | s->fd = fd; | |||
2680 | socket_set_nodelay(fd); | |||
2681 | s->chan = io_channel_from_socket(s->fd); | |||
2682 | tcp_chr_connect(chr); | |||
2683 | } | |||
2684 | ||||
2685 | if (is_listen && is_waitconnect) { | |||
2686 | fprintf(stderrstderr, "QEMU waiting for connection on: %s\n", | |||
2687 | chr->filename); | |||
2688 | tcp_chr_accept(s->listen_chan, G_IO_IN, chr); | |||
2689 | qemu_set_nonblock(s->listen_fd); | |||
2690 | } | |||
2691 | return chr; | |||
2692 | } | |||
2693 | ||||
2694 | static CharDriverState *qemu_chr_open_socket(QemuOpts *opts) | |||
2695 | { | |||
2696 | CharDriverState *chr = NULL((void*)0); | |||
2697 | Error *local_err = NULL((void*)0); | |||
2698 | int fd = -1; | |||
2699 | ||||
2700 | bool_Bool is_listen = qemu_opt_get_bool(opts, "server", false0); | |||
2701 | bool_Bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait", true1); | |||
2702 | bool_Bool is_telnet = qemu_opt_get_bool(opts, "telnet", false0); | |||
2703 | bool_Bool do_nodelay = !qemu_opt_get_bool(opts, "delay", true1); | |||
2704 | bool_Bool is_unix = qemu_opt_get(opts, "path") != NULL((void*)0); | |||
2705 | ||||
2706 | if (is_unix) { | |||
2707 | if (is_listen) { | |||
2708 | fd = unix_listen_opts(opts, &local_err); | |||
2709 | } else { | |||
2710 | fd = unix_connect_opts(opts, &local_err, NULL((void*)0), NULL((void*)0)); | |||
2711 | } | |||
2712 | } else { | |||
2713 | if (is_listen) { | |||
2714 | fd = inet_listen_opts(opts, 0, &local_err); | |||
2715 | } else { | |||
2716 | fd = inet_connect_opts(opts, &local_err, NULL((void*)0), NULL((void*)0)); | |||
2717 | } | |||
2718 | } | |||
2719 | if (fd < 0) { | |||
2720 | goto fail; | |||
2721 | } | |||
2722 | ||||
2723 | if (!is_waitconnect) | |||
2724 | qemu_set_nonblock(fd); | |||
2725 | ||||
2726 | chr = qemu_chr_open_socket_fd(fd, do_nodelay, is_listen, is_telnet, | |||
2727 | is_waitconnect, &local_err); | |||
2728 | if (error_is_set(&local_err)) { | |||
2729 | goto fail; | |||
2730 | } | |||
2731 | return chr; | |||
2732 | ||||
2733 | ||||
2734 | fail: | |||
2735 | if (local_err) { | |||
2736 | qerror_report_err(local_err); | |||
2737 | error_free(local_err); | |||
2738 | } | |||
2739 | if (fd >= 0) { | |||
2740 | closesocket(fd)close(fd); | |||
2741 | } | |||
2742 | if (chr) { | |||
2743 | g_free(chr->opaque); | |||
2744 | g_free(chr); | |||
2745 | } | |||
2746 | return NULL((void*)0); | |||
2747 | } | |||
2748 | ||||
2749 | /*********************************************************/ | |||
2750 | /* Ring buffer chardev */ | |||
2751 | ||||
2752 | typedef struct { | |||
2753 | size_t size; | |||
2754 | size_t prod; | |||
2755 | size_t cons; | |||
2756 | uint8_t *cbuf; | |||
2757 | } RingBufCharDriver; | |||
2758 | ||||
2759 | static size_t ringbuf_count(const CharDriverState *chr) | |||
2760 | { | |||
2761 | const RingBufCharDriver *d = chr->opaque; | |||
2762 | ||||
2763 | return d->prod - d->cons; | |||
2764 | } | |||
2765 | ||||
2766 | static int ringbuf_chr_write(CharDriverState *chr, const uint8_t *buf, int len) | |||
2767 | { | |||
2768 | RingBufCharDriver *d = chr->opaque; | |||
2769 | int i; | |||
2770 | ||||
2771 | if (!buf || (len < 0)) { | |||
2772 | return -1; | |||
2773 | } | |||
2774 | ||||
2775 | for (i = 0; i < len; i++ ) { | |||
2776 | d->cbuf[d->prod++ & (d->size - 1)] = buf[i]; | |||
2777 | if (d->prod - d->cons > d->size) { | |||
2778 | d->cons = d->prod - d->size; | |||
2779 | } | |||
2780 | } | |||
2781 | ||||
2782 | return 0; | |||
2783 | } | |||
2784 | ||||
2785 | static int ringbuf_chr_read(CharDriverState *chr, uint8_t *buf, int len) | |||
2786 | { | |||
2787 | RingBufCharDriver *d = chr->opaque; | |||
2788 | int i; | |||
2789 | ||||
2790 | for (i = 0; i < len && d->cons != d->prod; i++) { | |||
2791 | buf[i] = d->cbuf[d->cons++ & (d->size - 1)]; | |||
2792 | } | |||
2793 | ||||
2794 | return i; | |||
2795 | } | |||
2796 | ||||
2797 | static void ringbuf_chr_close(struct CharDriverState *chr) | |||
2798 | { | |||
2799 | RingBufCharDriver *d = chr->opaque; | |||
2800 | ||||
2801 | g_free(d->cbuf); | |||
2802 | g_free(d); | |||
2803 | chr->opaque = NULL((void*)0); | |||
2804 | } | |||
2805 | ||||
2806 | static CharDriverState *qemu_chr_open_ringbuf(ChardevRingbuf *opts, | |||
2807 | Error **errp) | |||
2808 | { | |||
2809 | CharDriverState *chr; | |||
2810 | RingBufCharDriver *d; | |||
2811 | ||||
2812 | chr = g_malloc0(sizeof(CharDriverState)); | |||
2813 | d = g_malloc(sizeof(*d)); | |||
2814 | ||||
2815 | d->size = opts->has_size ? opts->size : 65536; | |||
2816 | ||||
2817 | /* The size must be power of 2 */ | |||
2818 | if (d->size & (d->size - 1)) { | |||
2819 | error_setg(errp, "size of ringbuf chardev must be power of two")error_set(errp, ERROR_CLASS_GENERIC_ERROR, "size of ringbuf chardev must be power of two" ); | |||
2820 | goto fail; | |||
2821 | } | |||
2822 | ||||
2823 | d->prod = 0; | |||
2824 | d->cons = 0; | |||
2825 | d->cbuf = g_malloc0(d->size); | |||
2826 | ||||
2827 | chr->opaque = d; | |||
2828 | chr->chr_write = ringbuf_chr_write; | |||
2829 | chr->chr_close = ringbuf_chr_close; | |||
2830 | ||||
2831 | return chr; | |||
2832 | ||||
2833 | fail: | |||
2834 | g_free(d); | |||
2835 | g_free(chr); | |||
2836 | return NULL((void*)0); | |||
2837 | } | |||
2838 | ||||
2839 | static bool_Bool chr_is_ringbuf(const CharDriverState *chr) | |||
2840 | { | |||
2841 | return chr->chr_write == ringbuf_chr_write; | |||
2842 | } | |||
2843 | ||||
2844 | void qmp_ringbuf_write(const char *device, const char *data, | |||
2845 | bool_Bool has_format, enum DataFormat format, | |||
2846 | Error **errp) | |||
2847 | { | |||
2848 | CharDriverState *chr; | |||
2849 | const uint8_t *write_data; | |||
2850 | int ret; | |||
2851 | gsize write_count; | |||
2852 | ||||
2853 | chr = qemu_chr_find(device); | |||
2854 | if (!chr) { | |||
2855 | error_setg(errp, "Device '%s' not found", device)error_set(errp, ERROR_CLASS_GENERIC_ERROR, "Device '%s' not found" , device); | |||
2856 | return; | |||
2857 | } | |||
2858 | ||||
2859 | if (!chr_is_ringbuf(chr)) { | |||
2860 | error_setg(errp,"%s is not a ringbuf device", device)error_set(errp, ERROR_CLASS_GENERIC_ERROR, "%s is not a ringbuf device" , device); | |||
2861 | return; | |||
2862 | } | |||
2863 | ||||
2864 | if (has_format && (format == DATA_FORMAT_BASE64)) { | |||
2865 | write_data = g_base64_decode(data, &write_count); | |||
2866 | } else { | |||
2867 | write_data = (uint8_t *)data; | |||
2868 | write_count = strlen(data); | |||
2869 | } | |||
2870 | ||||
2871 | ret = ringbuf_chr_write(chr, write_data, write_count); | |||
2872 | ||||
2873 | if (write_data != (uint8_t *)data) { | |||
2874 | g_free((void *)write_data); | |||
2875 | } | |||
2876 | ||||
2877 | if (ret < 0) { | |||
2878 | error_setg(errp, "Failed to write to device %s", device)error_set(errp, ERROR_CLASS_GENERIC_ERROR, "Failed to write to device %s" , device); | |||
2879 | return; | |||
2880 | } | |||
2881 | } | |||
2882 | ||||
2883 | char *qmp_ringbuf_read(const char *device, int64_t size, | |||
2884 | bool_Bool has_format, enum DataFormat format, | |||
2885 | Error **errp) | |||
2886 | { | |||
2887 | CharDriverState *chr; | |||
2888 | uint8_t *read_data; | |||
2889 | size_t count; | |||
2890 | char *data; | |||
2891 | ||||
2892 | chr = qemu_chr_find(device); | |||
2893 | if (!chr) { | |||
2894 | error_setg(errp, "Device '%s' not found", device)error_set(errp, ERROR_CLASS_GENERIC_ERROR, "Device '%s' not found" , device); | |||
2895 | return NULL((void*)0); | |||
2896 | } | |||
2897 | ||||
2898 | if (!chr_is_ringbuf(chr)) { | |||
2899 | error_setg(errp,"%s is not a ringbuf device", device)error_set(errp, ERROR_CLASS_GENERIC_ERROR, "%s is not a ringbuf device" , device); | |||
2900 | return NULL((void*)0); | |||
2901 | } | |||
2902 | ||||
2903 | if (size <= 0) { | |||
2904 | error_setg(errp, "size must be greater than zero")error_set(errp, ERROR_CLASS_GENERIC_ERROR, "size must be greater than zero" ); | |||
2905 | return NULL((void*)0); | |||
2906 | } | |||
2907 | ||||
2908 | count = ringbuf_count(chr); | |||
2909 | size = size > count ? count : size; | |||
2910 | read_data = g_malloc(size + 1); | |||
2911 | ||||
2912 | ringbuf_chr_read(chr, read_data, size); | |||
2913 | ||||
2914 | if (has_format && (format == DATA_FORMAT_BASE64)) { | |||
2915 | data = g_base64_encode(read_data, size); | |||
2916 | g_free(read_data); | |||
2917 | } else { | |||
2918 | /* | |||
2919 | * FIXME should read only complete, valid UTF-8 characters up | |||
2920 | * to @size bytes. Invalid sequences should be replaced by a | |||
2921 | * suitable replacement character. Except when (and only | |||
2922 | * when) ring buffer lost characters since last read, initial | |||
2923 | * continuation characters should be dropped. | |||
2924 | */ | |||
2925 | read_data[size] = 0; | |||
2926 | data = (char *)read_data; | |||
2927 | } | |||
2928 | ||||
2929 | return data; | |||
2930 | } | |||
2931 | ||||
2932 | QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) | |||
2933 | { | |||
2934 | char host[65], port[33], width[8], height[8]; | |||
2935 | int pos; | |||
2936 | const char *p; | |||
2937 | QemuOpts *opts; | |||
2938 | Error *local_err = NULL((void*)0); | |||
2939 | ||||
2940 | opts = qemu_opts_create(qemu_find_opts("chardev"), label, 1, &local_err); | |||
2941 | if (error_is_set(&local_err)) { | |||
2942 | qerror_report_err(local_err); | |||
2943 | error_free(local_err); | |||
2944 | return NULL((void*)0); | |||
2945 | } | |||
2946 | ||||
2947 | if (strstart(filename, "mon:", &p)) { | |||
2948 | filename = p; | |||
2949 | qemu_opt_set(opts, "mux", "on"); | |||
2950 | if (strcmp(filename, "stdio") == 0) { | |||
2951 | /* Monitor is muxed to stdio: do not exit on Ctrl+C by default | |||
2952 | * but pass it to the guest. Handle this only for compat syntax, | |||
2953 | * for -chardev syntax we have special option for this. | |||
2954 | * This is what -nographic did, redirecting+muxing serial+monitor | |||
2955 | * to stdio causing Ctrl+C to be passed to guest. */ | |||
2956 | qemu_opt_set(opts, "signal", "off"); | |||
2957 | } | |||
2958 | } | |||
2959 | ||||
2960 | if (strcmp(filename, "null") == 0 || | |||
2961 | strcmp(filename, "pty") == 0 || | |||
2962 | strcmp(filename, "msmouse") == 0 || | |||
2963 | strcmp(filename, "braille") == 0 || | |||
2964 | strcmp(filename, "stdio") == 0) { | |||
2965 | qemu_opt_set(opts, "backend", filename); | |||
2966 | return opts; | |||
2967 | } | |||
2968 | if (strstart(filename, "vc", &p)) { | |||
2969 | qemu_opt_set(opts, "backend", "vc"); | |||
2970 | if (*p == ':') { | |||
2971 | if (sscanf(p+1, "%7[0-9]x%7[0-9]", width, height) == 2) { | |||
2972 | /* pixels */ | |||
2973 | qemu_opt_set(opts, "width", width); | |||
2974 | qemu_opt_set(opts, "height", height); | |||
2975 | } else if (sscanf(p+1, "%7[0-9]Cx%7[0-9]C", width, height) == 2) { | |||
2976 | /* chars */ | |||
2977 | qemu_opt_set(opts, "cols", width); | |||
2978 | qemu_opt_set(opts, "rows", height); | |||
2979 | } else { | |||
2980 | goto fail; | |||
2981 | } | |||
2982 | } | |||
2983 | return opts; | |||
2984 | } | |||
2985 | if (strcmp(filename, "con:") == 0) { | |||
2986 | qemu_opt_set(opts, "backend", "console"); | |||
2987 | return opts; | |||
2988 | } | |||
2989 | if (strstart(filename, "COM", NULL((void*)0))) { | |||
2990 | qemu_opt_set(opts, "backend", "serial"); | |||
2991 | qemu_opt_set(opts, "path", filename); | |||
2992 | return opts; | |||
2993 | } | |||
2994 | if (strstart(filename, "file:", &p)) { | |||
2995 | qemu_opt_set(opts, "backend", "file"); | |||
2996 | qemu_opt_set(opts, "path", p); | |||
2997 | return opts; | |||
2998 | } | |||
2999 | if (strstart(filename, "pipe:", &p)) { | |||
3000 | qemu_opt_set(opts, "backend", "pipe"); | |||
3001 | qemu_opt_set(opts, "path", p); | |||
3002 | return opts; | |||
3003 | } | |||
3004 | if (strstart(filename, "tcp:", &p) || | |||
3005 | strstart(filename, "telnet:", &p)) { | |||
3006 | if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) { | |||
3007 | host[0] = 0; | |||
3008 | if (sscanf(p, ":%32[^,]%n", port, &pos) < 1) | |||
3009 | goto fail; | |||
3010 | } | |||
3011 | qemu_opt_set(opts, "backend", "socket"); | |||
3012 | qemu_opt_set(opts, "host", host); | |||
3013 | qemu_opt_set(opts, "port", port); | |||
3014 | if (p[pos] == ',') { | |||
3015 | if (qemu_opts_do_parse(opts, p+pos+1, NULL((void*)0)) != 0) | |||
3016 | goto fail; | |||
3017 | } | |||
3018 | if (strstart(filename, "telnet:", &p)) | |||
3019 | qemu_opt_set(opts, "telnet", "on"); | |||
3020 | return opts; | |||
3021 | } | |||
3022 | if (strstart(filename, "udp:", &p)) { | |||
3023 | qemu_opt_set(opts, "backend", "udp"); | |||
3024 | if (sscanf(p, "%64[^:]:%32[^@,]%n", host, port, &pos) < 2) { | |||
3025 | host[0] = 0; | |||
3026 | if (sscanf(p, ":%32[^@,]%n", port, &pos) < 1) { | |||
3027 | goto fail; | |||
3028 | } | |||
3029 | } | |||
3030 | qemu_opt_set(opts, "host", host); | |||
3031 | qemu_opt_set(opts, "port", port); | |||
3032 | if (p[pos] == '@') { | |||
3033 | p += pos + 1; | |||
3034 | if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) { | |||
3035 | host[0] = 0; | |||
3036 | if (sscanf(p, ":%32[^,]%n", port, &pos) < 1) { | |||
3037 | goto fail; | |||
3038 | } | |||
3039 | } | |||
3040 | qemu_opt_set(opts, "localaddr", host); | |||
3041 | qemu_opt_set(opts, "localport", port); | |||
3042 | } | |||
3043 | return opts; | |||
3044 | } | |||
3045 | if (strstart(filename, "unix:", &p)) { | |||
3046 | qemu_opt_set(opts, "backend", "socket"); | |||
3047 | if (qemu_opts_do_parse(opts, p, "path") != 0) | |||
3048 | goto fail; | |||
3049 | return opts; | |||
3050 | } | |||
3051 | if (strstart(filename, "/dev/parport", NULL((void*)0)) || | |||
3052 | strstart(filename, "/dev/ppi", NULL((void*)0))) { | |||
3053 | qemu_opt_set(opts, "backend", "parport"); | |||
3054 | qemu_opt_set(opts, "path", filename); | |||
3055 | return opts; | |||
3056 | } | |||
3057 | if (strstart(filename, "/dev/", NULL((void*)0))) { | |||
3058 | qemu_opt_set(opts, "backend", "tty"); | |||
3059 | qemu_opt_set(opts, "path", filename); | |||
3060 | return opts; | |||
3061 | } | |||
3062 | ||||
3063 | fail: | |||
3064 | qemu_opts_del(opts); | |||
3065 | return NULL((void*)0); | |||
3066 | } | |||
3067 | ||||
3068 | static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend, | |||
3069 | Error **errp) | |||
3070 | { | |||
3071 | const char *path = qemu_opt_get(opts, "path"); | |||
3072 | ||||
3073 | if (path == NULL((void*)0)) { | |||
3074 | error_setg(errp, "chardev: file: no filename given")error_set(errp, ERROR_CLASS_GENERIC_ERROR, "chardev: file: no filename given" ); | |||
3075 | return; | |||
3076 | } | |||
3077 | backend->file = g_new0(ChardevFile, 1)((ChardevFile *) g_malloc0_n ((1), sizeof (ChardevFile))); | |||
3078 | backend->file->out = g_strdup(path); | |||
3079 | } | |||
3080 | ||||
3081 | static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend, | |||
3082 | Error **errp) | |||
3083 | { | |||
3084 | backend->stdio = g_new0(ChardevStdio, 1)((ChardevStdio *) g_malloc0_n ((1), sizeof (ChardevStdio))); | |||
3085 | backend->stdio->has_signal = true1; | |||
3086 | backend->stdio->signal = qemu_opt_get_bool(opts, "signal", true1); | |||
3087 | } | |||
3088 | ||||
3089 | static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend, | |||
3090 | Error **errp) | |||
3091 | { | |||
3092 | const char *device = qemu_opt_get(opts, "path"); | |||
3093 | ||||
3094 | if (device == NULL((void*)0)) { | |||
3095 | error_setg(errp, "chardev: serial/tty: no device path given")error_set(errp, ERROR_CLASS_GENERIC_ERROR, "chardev: serial/tty: no device path given" ); | |||
3096 | return; | |||
3097 | } | |||
3098 | backend->serial = g_new0(ChardevHostdev, 1)((ChardevHostdev *) g_malloc0_n ((1), sizeof (ChardevHostdev) )); | |||
3099 | backend->serial->device = g_strdup(device); | |||
3100 | } | |||
3101 | ||||
3102 | static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend, | |||
3103 | Error **errp) | |||
3104 | { | |||
3105 | const char *device = qemu_opt_get(opts, "path"); | |||
3106 | ||||
3107 | if (device == NULL((void*)0)) { | |||
3108 | error_setg(errp, "chardev: parallel: no device path given")error_set(errp, ERROR_CLASS_GENERIC_ERROR, "chardev: parallel: no device path given" ); | |||
3109 | return; | |||
3110 | } | |||
3111 | backend->parallel = g_new0(ChardevHostdev, 1)((ChardevHostdev *) g_malloc0_n ((1), sizeof (ChardevHostdev) )); | |||
3112 | backend->parallel->device = g_strdup(device); | |||
3113 | } | |||
3114 | ||||
3115 | static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend, | |||
3116 | Error **errp) | |||
3117 | { | |||
3118 | const char *device = qemu_opt_get(opts, "path"); | |||
3119 | ||||
3120 | if (device == NULL((void*)0)) { | |||
3121 | error_setg(errp, "chardev: pipe: no device path given")error_set(errp, ERROR_CLASS_GENERIC_ERROR, "chardev: pipe: no device path given" ); | |||
3122 | return; | |||
3123 | } | |||
3124 | backend->pipe = g_new0(ChardevHostdev, 1)((ChardevHostdev *) g_malloc0_n ((1), sizeof (ChardevHostdev) )); | |||
3125 | backend->pipe->device = g_strdup(device); | |||
3126 | } | |||
3127 | ||||
3128 | static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend, | |||
3129 | Error **errp) | |||
3130 | { | |||
3131 | int val; | |||
3132 | ||||
3133 | backend->ringbuf = g_new0(ChardevRingbuf, 1)((ChardevRingbuf *) g_malloc0_n ((1), sizeof (ChardevRingbuf) )); | |||
3134 | ||||
3135 | val = qemu_opt_get_size(opts, "size", 0); | |||
3136 | if (val != 0) { | |||
3137 | backend->ringbuf->has_size = true1; | |||
3138 | backend->ringbuf->size = val; | |||
3139 | } | |||
3140 | } | |||
3141 | ||||
3142 | static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend, | |||
3143 | Error **errp) | |||
3144 | { | |||
3145 | const char *chardev = qemu_opt_get(opts, "chardev"); | |||
3146 | ||||
3147 | if (chardev == NULL((void*)0)) { | |||
3148 | error_setg(errp, "chardev: mux: no chardev given")error_set(errp, ERROR_CLASS_GENERIC_ERROR, "chardev: mux: no chardev given" ); | |||
3149 | return; | |||
3150 | } | |||
3151 | backend->mux = g_new0(ChardevMux, 1)((ChardevMux *) g_malloc0_n ((1), sizeof (ChardevMux))); | |||
3152 | backend->mux->chardev = g_strdup(chardev); | |||
3153 | } | |||
3154 | ||||
3155 | typedef struct CharDriver { | |||
3156 | const char *name; | |||
3157 | /* old, pre qapi */ | |||
3158 | CharDriverState *(*open)(QemuOpts *opts); | |||
3159 | /* new, qapi-based */ | |||
3160 | ChardevBackendKind kind; | |||
3161 | void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp); | |||
3162 | } CharDriver; | |||
3163 | ||||
3164 | static GSList *backends; | |||
3165 | ||||
3166 | void register_char_driver(const char *name, CharDriverState *(*open)(QemuOpts *)) | |||
3167 | { | |||
3168 | CharDriver *s; | |||
3169 | ||||
3170 | s = g_malloc0(sizeof(*s)); | |||
3171 | s->name = g_strdup(name); | |||
3172 | s->open = open; | |||
3173 | ||||
3174 | backends = g_slist_append(backends, s); | |||
3175 | } | |||
3176 | ||||
3177 | void register_char_driver_qapi(const char *name, ChardevBackendKind kind, | |||
3178 | void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp)) | |||
3179 | { | |||
3180 | CharDriver *s; | |||
3181 | ||||
3182 | s = g_malloc0(sizeof(*s)); | |||
3183 | s->name = g_strdup(name); | |||
3184 | s->kind = kind; | |||
3185 | s->parse = parse; | |||
3186 | ||||
3187 | backends = g_slist_append(backends, s); | |||
3188 | } | |||
3189 | ||||
3190 | CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts, | |||
3191 | void (*init)(struct CharDriverState *s), | |||
3192 | Error **errp) | |||
3193 | { | |||
3194 | CharDriver *cd; | |||
3195 | CharDriverState *chr; | |||
3196 | GSList *i; | |||
3197 | ||||
3198 | if (qemu_opts_id(opts) == NULL((void*)0)) { | |||
3199 | error_setg(errp, "chardev: no id specified")error_set(errp, ERROR_CLASS_GENERIC_ERROR, "chardev: no id specified" ); | |||
3200 | goto err; | |||
3201 | } | |||
3202 | ||||
3203 | if (qemu_opt_get(opts, "backend") == NULL((void*)0)) { | |||
3204 | error_setg(errp, "chardev: \"%s\" missing backend",error_set(errp, ERROR_CLASS_GENERIC_ERROR, "chardev: \"%s\" missing backend" , qemu_opts_id(opts)) | |||
3205 | qemu_opts_id(opts))error_set(errp, ERROR_CLASS_GENERIC_ERROR, "chardev: \"%s\" missing backend" , qemu_opts_id(opts)); | |||
3206 | goto err; | |||
3207 | } | |||
3208 | for (i = backends; i; i = i->next) { | |||
3209 | cd = i->data; | |||
3210 | ||||
3211 | if (strcmp(cd->name, qemu_opt_get(opts, "backend")) == 0) { | |||
3212 | break; | |||
3213 | } | |||
3214 | } | |||
3215 | if (i == NULL((void*)0)) { | |||
3216 | error_setg(errp, "chardev: backend \"%s\" not found",error_set(errp, ERROR_CLASS_GENERIC_ERROR, "chardev: backend \"%s\" not found" , qemu_opt_get(opts, "backend")) | |||
3217 | qemu_opt_get(opts, "backend"))error_set(errp, ERROR_CLASS_GENERIC_ERROR, "chardev: backend \"%s\" not found" , qemu_opt_get(opts, "backend")); | |||
3218 | goto err; | |||
3219 | } | |||
3220 | ||||
3221 | if (!cd->open) { | |||
3222 | /* using new, qapi init */ | |||
3223 | ChardevBackend *backend = g_new0(ChardevBackend, 1)((ChardevBackend *) g_malloc0_n ((1), sizeof (ChardevBackend) )); | |||
3224 | ChardevReturn *ret = NULL((void*)0); | |||
3225 | const char *id = qemu_opts_id(opts); | |||
3226 | char *bid = NULL((void*)0); | |||
3227 | ||||
3228 | if (qemu_opt_get_bool(opts, "mux", 0)) { | |||
3229 | bid = g_strdup_printf("%s-base", id); | |||
3230 | } | |||
3231 | ||||
3232 | chr = NULL((void*)0); | |||
3233 | backend->kind = cd->kind; | |||
3234 | if (cd->parse) { | |||
3235 | cd->parse(opts, backend, errp); | |||
3236 | if (error_is_set(errp)) { | |||
3237 | goto qapi_out; | |||
3238 | } | |||
3239 | } | |||
3240 | ret = qmp_chardev_add(bid ? bid : id, backend, errp); | |||
3241 | if (error_is_set(errp)) { | |||
3242 | goto qapi_out; | |||
3243 | } | |||
3244 | ||||
3245 | if (bid) { | |||
3246 | qapi_free_ChardevBackend(backend); | |||
3247 | qapi_free_ChardevReturn(ret); | |||
3248 | backend = g_new0(ChardevBackend, 1)((ChardevBackend *) g_malloc0_n ((1), sizeof (ChardevBackend) )); | |||
3249 | backend->mux = g_new0(ChardevMux, 1)((ChardevMux *) g_malloc0_n ((1), sizeof (ChardevMux))); | |||
3250 | backend->kind = CHARDEV_BACKEND_KIND_MUX; | |||
3251 | backend->mux->chardev = g_strdup(bid); | |||
3252 | ret = qmp_chardev_add(id, backend, errp); | |||
3253 | if (error_is_set(errp)) { | |||
3254 | chr = qemu_chr_find(bid); | |||
3255 | qemu_chr_delete(chr); | |||
3256 | chr = NULL((void*)0); | |||
3257 | goto qapi_out; | |||
3258 | } | |||
3259 | } | |||
3260 | ||||
3261 | chr = qemu_chr_find(id); | |||
3262 | chr->opts = opts; | |||
3263 | ||||
3264 | qapi_out: | |||
3265 | qapi_free_ChardevBackend(backend); | |||
3266 | qapi_free_ChardevReturn(ret); | |||
3267 | g_free(bid); | |||
3268 | return chr; | |||
3269 | } | |||
3270 | ||||
3271 | chr = cd->open(opts); | |||
3272 | if (!chr) { | |||
3273 | error_setg(errp, "chardev: opening backend \"%s\" failed",error_set(errp, ERROR_CLASS_GENERIC_ERROR, "chardev: opening backend \"%s\" failed" , qemu_opt_get(opts, "backend")) | |||
3274 | qemu_opt_get(opts, "backend"))error_set(errp, ERROR_CLASS_GENERIC_ERROR, "chardev: opening backend \"%s\" failed" , qemu_opt_get(opts, "backend")); | |||
3275 | goto err; | |||
3276 | } | |||
3277 | ||||
3278 | if (!chr->filename) | |||
3279 | chr->filename = g_strdup(qemu_opt_get(opts, "backend")); | |||
3280 | chr->init = init; | |||
3281 | /* if we didn't create the chardev via qmp_chardev_add, we | |||
3282 | * need to send the OPENED event here | |||
3283 | */ | |||
3284 | if (!chr->explicit_be_open) { | |||
3285 | qemu_chr_be_event(chr, CHR_EVENT_OPENED2); | |||
3286 | } | |||
3287 | QTAILQ_INSERT_TAIL(&chardevs, chr, next)do { (chr)->next.tqe_next = ((void*)0); (chr)->next.tqe_prev = (&chardevs)->tqh_last; *(&chardevs)->tqh_last = (chr); (&chardevs)->tqh_last = &(chr)->next. tqe_next; } while ( 0); | |||
3288 | ||||
3289 | if (qemu_opt_get_bool(opts, "mux", 0)) { | |||
3290 | CharDriverState *base = chr; | |||
3291 | int len = strlen(qemu_opts_id(opts)) + 6; | |||
3292 | base->label = g_malloc(len); | |||
3293 | snprintf(base->label, len, "%s-base", qemu_opts_id(opts)); | |||
3294 | chr = qemu_chr_open_mux(base); | |||
3295 | chr->filename = base->filename; | |||
3296 | chr->avail_connections = MAX_MUX4; | |||
3297 | QTAILQ_INSERT_TAIL(&chardevs, chr, next)do { (chr)->next.tqe_next = ((void*)0); (chr)->next.tqe_prev = (&chardevs)->tqh_last; *(&chardevs)->tqh_last = (chr); (&chardevs)->tqh_last = &(chr)->next. tqe_next; } while ( 0); | |||
3298 | } else { | |||
3299 | chr->avail_connections = 1; | |||
3300 | } | |||
3301 | chr->label = g_strdup(qemu_opts_id(opts)); | |||
3302 | chr->opts = opts; | |||
3303 | return chr; | |||
3304 | ||||
3305 | err: | |||
3306 | qemu_opts_del(opts); | |||
3307 | return NULL((void*)0); | |||
3308 | } | |||
3309 | ||||
3310 | CharDriverState *qemu_chr_new(const char *label, const char *filename, void (*init)(struct CharDriverState *s)) | |||
3311 | { | |||
3312 | const char *p; | |||
3313 | CharDriverState *chr; | |||
3314 | QemuOpts *opts; | |||
3315 | Error *err = NULL((void*)0); | |||
3316 | ||||
3317 | if (strstart(filename, "chardev:", &p)) { | |||
3318 | return qemu_chr_find(p); | |||
3319 | } | |||
3320 | ||||
3321 | opts = qemu_chr_parse_compat(label, filename); | |||
3322 | if (!opts) | |||
3323 | return NULL((void*)0); | |||
3324 | ||||
3325 | chr = qemu_chr_new_from_opts(opts, init, &err); | |||
3326 | if (error_is_set(&err)) { | |||
3327 | error_report("%s", error_get_pretty(err)); | |||
3328 | error_free(err); | |||
3329 | } | |||
3330 | if (chr && qemu_opt_get_bool(opts, "mux", 0)) { | |||
3331 | qemu_chr_fe_claim_no_fail(chr); | |||
3332 | monitor_init(chr, MONITOR_USE_READLINE0x02); | |||
3333 | } | |||
3334 | return chr; | |||
3335 | } | |||
3336 | ||||
3337 | void qemu_chr_fe_set_echo(struct CharDriverState *chr, bool_Bool echo) | |||
3338 | { | |||
3339 | if (chr->chr_set_echo) { | |||
3340 | chr->chr_set_echo(chr, echo); | |||
3341 | } | |||
3342 | } | |||
3343 | ||||
3344 | void qemu_chr_fe_set_open(struct CharDriverState *chr, int fe_open) | |||
3345 | { | |||
3346 | if (chr->fe_open == fe_open) { | |||
3347 | return; | |||
3348 | } | |||
3349 | chr->fe_open = fe_open; | |||
3350 | if (chr->chr_set_fe_open) { | |||
3351 | chr->chr_set_fe_open(chr, fe_open); | |||
3352 | } | |||
3353 | } | |||
3354 | ||||
3355 | void qemu_chr_fe_event(struct CharDriverState *chr, int event) | |||
3356 | { | |||
3357 | if (chr->chr_fe_event) { | |||
3358 | chr->chr_fe_event(chr, event); | |||
3359 | } | |||
3360 | } | |||
3361 | ||||
3362 | int qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond, | |||
3363 | GIOFunc func, void *user_data) | |||
3364 | { | |||
3365 | GSource *src; | |||
3366 | guint tag; | |||
3367 | ||||
3368 | if (s->chr_add_watch == NULL((void*)0)) { | |||
3369 | return -ENOSYS38; | |||
3370 | } | |||
3371 | ||||
3372 | src = s->chr_add_watch(s, cond); | |||
3373 | g_source_set_callback(src, (GSourceFunc)func, user_data, NULL((void*)0)); | |||
3374 | tag = g_source_attach(src, NULL((void*)0)); | |||
3375 | g_source_unref(src); | |||
3376 | ||||
3377 | return tag; | |||
3378 | } | |||
3379 | ||||
3380 | int qemu_chr_fe_claim(CharDriverState *s) | |||
3381 | { | |||
3382 | if (s->avail_connections < 1) { | |||
3383 | return -1; | |||
3384 | } | |||
3385 | s->avail_connections--; | |||
3386 | return 0; | |||
3387 | } | |||
3388 | ||||
3389 | void qemu_chr_fe_claim_no_fail(CharDriverState *s) | |||
3390 | { | |||
3391 | if (qemu_chr_fe_claim(s) != 0) { | |||
3392 | fprintf(stderrstderr, "%s: error chardev \"%s\" already used\n", | |||
3393 | __func__, s->label); | |||
3394 | exit(1); | |||
3395 | } | |||
3396 | } | |||
3397 | ||||
3398 | void qemu_chr_fe_release(CharDriverState *s) | |||
3399 | { | |||
3400 | s->avail_connections++; | |||
3401 | } | |||
3402 | ||||
3403 | void qemu_chr_delete(CharDriverState *chr) | |||
3404 | { | |||
3405 | QTAILQ_REMOVE(&chardevs, chr, next)do { if (((chr)->next.tqe_next) != ((void*)0)) (chr)->next .tqe_next->next.tqe_prev = (chr)->next.tqe_prev; else ( &chardevs)->tqh_last = (chr)->next.tqe_prev; *(chr) ->next.tqe_prev = (chr)->next.tqe_next; } while ( 0); | |||
3406 | if (chr->chr_close) { | |||
3407 | chr->chr_close(chr); | |||
3408 | } | |||
3409 | g_free(chr->filename); | |||
3410 | g_free(chr->label); | |||
3411 | if (chr->opts) { | |||
3412 | qemu_opts_del(chr->opts); | |||
3413 | } | |||
3414 | g_free(chr); | |||
3415 | } | |||
3416 | ||||
3417 | ChardevInfoList *qmp_query_chardev(Error **errp) | |||
3418 | { | |||
3419 | ChardevInfoList *chr_list = NULL((void*)0); | |||
3420 | CharDriverState *chr; | |||
3421 | ||||
3422 | QTAILQ_FOREACH(chr, &chardevs, next)for ((chr) = ((&chardevs)->tqh_first); (chr); (chr) = ( (chr)->next.tqe_next)) { | |||
3423 | ChardevInfoList *info = g_malloc0(sizeof(*info)); | |||
3424 | info->value = g_malloc0(sizeof(*info->value)); | |||
3425 | info->value->label = g_strdup(chr->label); | |||
3426 | info->value->filename = g_strdup(chr->filename); | |||
3427 | ||||
3428 | info->next = chr_list; | |||
3429 | chr_list = info; | |||
3430 | } | |||
3431 | ||||
3432 | return chr_list; | |||
3433 | } | |||
3434 | ||||
3435 | CharDriverState *qemu_chr_find(const char *name) | |||
3436 | { | |||
3437 | CharDriverState *chr; | |||
3438 | ||||
3439 | QTAILQ_FOREACH(chr, &chardevs, next)for ((chr) = ((&chardevs)->tqh_first); (chr); (chr) = ( (chr)->next.tqe_next)) { | |||
3440 | if (strcmp(chr->label, name) != 0) | |||
3441 | continue; | |||
3442 | return chr; | |||
3443 | } | |||
3444 | return NULL((void*)0); | |||
3445 | } | |||
3446 | ||||
3447 | /* Get a character (serial) device interface. */ | |||
3448 | CharDriverState *qemu_char_get_next_serial(void) | |||
3449 | { | |||
3450 | static int next_serial; | |||
3451 | CharDriverState *chr; | |||
3452 | ||||
3453 | /* FIXME: This function needs to go away: use chardev properties! */ | |||
3454 | ||||
3455 | while (next_serial < MAX_SERIAL_PORTS4 && serial_hds[next_serial]) { | |||
3456 | chr = serial_hds[next_serial++]; | |||
3457 | qemu_chr_fe_claim_no_fail(chr); | |||
3458 | return chr; | |||
3459 | } | |||
3460 | return NULL((void*)0); | |||
3461 | } | |||
3462 | ||||
3463 | QemuOptsList qemu_chardev_opts = { | |||
3464 | .name = "chardev", | |||
3465 | .implied_opt_name = "backend", | |||
3466 | .head = QTAILQ_HEAD_INITIALIZER(qemu_chardev_opts.head){ ((void*)0), &(qemu_chardev_opts.head).tqh_first }, | |||
3467 | .desc = { | |||
3468 | { | |||
3469 | .name = "backend", | |||
3470 | .type = QEMU_OPT_STRING, | |||
3471 | },{ | |||
3472 | .name = "path", | |||
3473 | .type = QEMU_OPT_STRING, | |||
3474 | },{ | |||
3475 | .name = "host", | |||
3476 | .type = QEMU_OPT_STRING, | |||
3477 | },{ | |||
3478 | .name = "port", | |||
3479 | .type = QEMU_OPT_STRING, | |||
3480 | },{ | |||
3481 | .name = "localaddr", | |||
3482 | .type = QEMU_OPT_STRING, | |||
3483 | },{ | |||
3484 | .name = "localport", | |||
3485 | .type = QEMU_OPT_STRING, | |||
3486 | },{ | |||
3487 | .name = "to", | |||
3488 | .type = QEMU_OPT_NUMBER, | |||
3489 | },{ | |||
3490 | .name = "ipv4", | |||
3491 | .type = QEMU_OPT_BOOL, | |||
3492 | },{ | |||
3493 | .name = "ipv6", | |||
3494 | .type = QEMU_OPT_BOOL, | |||
3495 | },{ | |||
3496 | .name = "wait", | |||
3497 | .type = QEMU_OPT_BOOL, | |||
3498 | },{ | |||
3499 | .name = "server", | |||
3500 | .type = QEMU_OPT_BOOL, | |||
3501 | },{ | |||
3502 | .name = "delay", | |||
3503 | .type = QEMU_OPT_BOOL, | |||
3504 | },{ | |||
3505 | .name = "telnet", | |||
3506 | .type = QEMU_OPT_BOOL, | |||
3507 | },{ | |||
3508 | .name = "width", | |||
3509 | .type = QEMU_OPT_NUMBER, | |||
3510 | },{ | |||
3511 | .name = "height", | |||
3512 | .type = QEMU_OPT_NUMBER, | |||
3513 | },{ | |||
3514 | .name = "cols", | |||
3515 | .type = QEMU_OPT_NUMBER, | |||
3516 | },{ | |||
3517 | .name = "rows", | |||
3518 | .type = QEMU_OPT_NUMBER, | |||
3519 | },{ | |||
3520 | .name = "mux", | |||
3521 | .type = QEMU_OPT_BOOL, | |||
3522 | },{ | |||
3523 | .name = "signal", | |||
3524 | .type = QEMU_OPT_BOOL, | |||
3525 | },{ | |||
3526 | .name = "name", | |||
3527 | .type = QEMU_OPT_STRING, | |||
3528 | },{ | |||
3529 | .name = "debug", | |||
3530 | .type = QEMU_OPT_NUMBER, | |||
3531 | },{ | |||
3532 | .name = "size", | |||
3533 | .type = QEMU_OPT_SIZE, | |||
3534 | },{ | |||
3535 | .name = "chardev", | |||
3536 | .type = QEMU_OPT_STRING, | |||
3537 | }, | |||
3538 | { /* end of list */ } | |||
3539 | }, | |||
3540 | }; | |||
3541 | ||||
3542 | #ifdef _WIN32 | |||
3543 | ||||
3544 | static CharDriverState *qmp_chardev_open_file(ChardevFile *file, Error **errp) | |||
3545 | { | |||
3546 | HANDLE out; | |||
3547 | ||||
3548 | if (file->has_in) { | |||
3549 | error_setg(errp, "input file not supported")error_set(errp, ERROR_CLASS_GENERIC_ERROR, "input file not supported" ); | |||
3550 | return NULL((void*)0); | |||
3551 | } | |||
3552 | ||||
3553 | out = CreateFile(file->out, GENERIC_WRITE, FILE_SHARE_READ, NULL((void*)0), | |||
3554 | OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL((void*)0)); | |||
3555 | if (out == INVALID_HANDLE_VALUE) { | |||
3556 | error_setg(errp, "open %s failed", file->out)error_set(errp, ERROR_CLASS_GENERIC_ERROR, "open %s failed", file ->out); | |||
3557 | return NULL((void*)0); | |||
3558 | } | |||
3559 | return qemu_chr_open_win_file(out); | |||
3560 | } | |||
3561 | ||||
3562 | static CharDriverState *qmp_chardev_open_serial(ChardevHostdev *serial, | |||
3563 | Error **errp) | |||
3564 | { | |||
3565 | return qemu_chr_open_win_path(serial->device); | |||
3566 | } | |||
3567 | ||||
3568 | static CharDriverState *qmp_chardev_open_parallel(ChardevHostdev *parallel, | |||
3569 | Error **errp) | |||
3570 | { | |||
3571 | error_setg(errp, "character device backend type 'parallel' not supported")error_set(errp, ERROR_CLASS_GENERIC_ERROR, "character device backend type 'parallel' not supported" ); | |||
3572 | return NULL((void*)0); | |||
3573 | } | |||
3574 | ||||
3575 | #else /* WIN32 */ | |||
3576 | ||||
3577 | static int qmp_chardev_open_file_source(char *src, int flags, | |||
3578 | Error **errp) | |||
3579 | { | |||
3580 | int fd = -1; | |||
3581 | ||||
3582 | TFR(fd = qemu_open(src, flags, 0666))do { if ((fd = qemu_open(src, flags, 0666)) != -1) break; } while ((*__errno_location ()) == 4); | |||
3583 | if (fd == -1) { | |||
3584 | error_setg_file_open(errp, errno(*__errno_location ()), src); | |||
3585 | } | |||
3586 | return fd; | |||
3587 | } | |||
3588 | ||||
3589 | static CharDriverState *qmp_chardev_open_file(ChardevFile *file, Error **errp) | |||
3590 | { | |||
3591 | int flags, in = -1, out = -1; | |||
3592 | ||||
3593 | flags = O_WRONLY01 | O_TRUNC01000 | O_CREAT0100 | O_BINARY0; | |||
3594 | out = qmp_chardev_open_file_source(file->out, flags, errp); | |||
3595 | if (error_is_set(errp)) { | |||
3596 | return NULL((void*)0); | |||
3597 | } | |||
3598 | ||||
3599 | if (file->has_in) { | |||
3600 | flags = O_RDONLY00; | |||
3601 | in = qmp_chardev_open_file_source(file->in, flags, errp); | |||
3602 | if (error_is_set(errp)) { | |||
3603 | qemu_close(out); | |||
3604 | return NULL((void*)0); | |||
3605 | } | |||
3606 | } | |||
3607 | ||||
3608 | return qemu_chr_open_fd(in, out); | |||
3609 | } | |||
3610 | ||||
3611 | static CharDriverState *qmp_chardev_open_serial(ChardevHostdev *serial, | |||
3612 | Error **errp) | |||
3613 | { | |||
3614 | #ifdef HAVE_CHARDEV_TTY1 | |||
3615 | int fd; | |||
3616 | ||||
3617 | fd = qmp_chardev_open_file_source(serial->device, O_RDWR02, errp); | |||
3618 | if (error_is_set(errp)) { | |||
3619 | return NULL((void*)0); | |||
3620 | } | |||
3621 | qemu_set_nonblock(fd); | |||
3622 | return qemu_chr_open_tty_fd(fd); | |||
3623 | #else | |||
3624 | error_setg(errp, "character device backend type 'serial' not supported")error_set(errp, ERROR_CLASS_GENERIC_ERROR, "character device backend type 'serial' not supported" ); | |||
3625 | return NULL((void*)0); | |||
3626 | #endif | |||
3627 | } | |||
3628 | ||||
3629 | static CharDriverState *qmp_chardev_open_parallel(ChardevHostdev *parallel, | |||
3630 | Error **errp) | |||
3631 | { | |||
3632 | #ifdef HAVE_CHARDEV_PARPORT1 | |||
3633 | int fd; | |||
3634 | ||||
3635 | fd = qmp_chardev_open_file_source(parallel->device, O_RDWR02, errp); | |||
3636 | if (error_is_set(errp)) { | |||
3637 | return NULL((void*)0); | |||
3638 | } | |||
3639 | return qemu_chr_open_pp_fd(fd); | |||
3640 | #else | |||
3641 | error_setg(errp, "character device backend type 'parallel' not supported")error_set(errp, ERROR_CLASS_GENERIC_ERROR, "character device backend type 'parallel' not supported" ); | |||
3642 | return NULL((void*)0); | |||
3643 | #endif | |||
3644 | } | |||
3645 | ||||
3646 | #endif /* WIN32 */ | |||
3647 | ||||
3648 | static CharDriverState *qmp_chardev_open_socket(ChardevSocket *sock, | |||
3649 | Error **errp) | |||
3650 | { | |||
3651 | SocketAddress *addr = sock->addr; | |||
3652 | bool_Bool do_nodelay = sock->has_nodelay ? sock->nodelay : false0; | |||
3653 | bool_Bool is_listen = sock->has_server ? sock->server : true1; | |||
3654 | bool_Bool is_telnet = sock->has_telnet ? sock->telnet : false0; | |||
3655 | bool_Bool is_waitconnect = sock->has_wait ? sock->wait : false0; | |||
3656 | int fd; | |||
3657 | ||||
3658 | if (is_listen) { | |||
3659 | fd = socket_listen(addr, errp); | |||
3660 | } else { | |||
3661 | fd = socket_connect(addr, errp, NULL((void*)0), NULL((void*)0)); | |||
3662 | } | |||
3663 | if (error_is_set(errp)) { | |||
3664 | return NULL((void*)0); | |||
3665 | } | |||
3666 | return qemu_chr_open_socket_fd(fd, do_nodelay, is_listen, | |||
3667 | is_telnet, is_waitconnect, errp); | |||
3668 | } | |||
3669 | ||||
3670 | static CharDriverState *qmp_chardev_open_udp(ChardevUdp *udp, | |||
3671 | Error **errp) | |||
3672 | { | |||
3673 | int fd; | |||
3674 | ||||
3675 | fd = socket_dgram(udp->remote, udp->local, errp); | |||
3676 | if (error_is_set(errp)) { | |||
3677 | return NULL((void*)0); | |||
3678 | } | |||
3679 | return qemu_chr_open_udp_fd(fd); | |||
3680 | } | |||
3681 | ||||
3682 | ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend, | |||
3683 | Error **errp) | |||
3684 | { | |||
3685 | ChardevReturn *ret = g_new0(ChardevReturn, 1)((ChardevReturn *) g_malloc0_n ((1), sizeof (ChardevReturn))); | |||
3686 | CharDriverState *base, *chr = NULL((void*)0); | |||
3687 | ||||
3688 | chr = qemu_chr_find(id); | |||
3689 | if (chr) { | |||
3690 | error_setg(errp, "Chardev '%s' already exists", id)error_set(errp, ERROR_CLASS_GENERIC_ERROR, "Chardev '%s' already exists" , id); | |||
3691 | g_free(ret); | |||
3692 | return NULL((void*)0); | |||
3693 | } | |||
3694 | ||||
3695 | switch (backend->kind) { | |||
3696 | case CHARDEV_BACKEND_KIND_FILE: | |||
3697 | chr = qmp_chardev_open_file(backend->file, errp); | |||
3698 | break; | |||
3699 | case CHARDEV_BACKEND_KIND_SERIAL: | |||
3700 | chr = qmp_chardev_open_serial(backend->serial, errp); | |||
3701 | break; | |||
3702 | case CHARDEV_BACKEND_KIND_PARALLEL: | |||
3703 | chr = qmp_chardev_open_parallel(backend->parallel, errp); | |||
3704 | break; | |||
3705 | case CHARDEV_BACKEND_KIND_PIPE: | |||
3706 | chr = qemu_chr_open_pipe(backend->pipe); | |||
3707 | break; | |||
3708 | case CHARDEV_BACKEND_KIND_SOCKET: | |||
3709 | chr = qmp_chardev_open_socket(backend->socket, errp); | |||
3710 | break; | |||
3711 | case CHARDEV_BACKEND_KIND_UDP: | |||
3712 | chr = qmp_chardev_open_udp(backend->udp, errp); | |||
3713 | break; | |||
3714 | #ifdef HAVE_CHARDEV_TTY1 | |||
3715 | case CHARDEV_BACKEND_KIND_PTY: | |||
3716 | chr = qemu_chr_open_pty(id, ret); | |||
3717 | break; | |||
3718 | #endif | |||
3719 | case CHARDEV_BACKEND_KIND_NULL: | |||
3720 | chr = qemu_chr_open_null(); | |||
3721 | break; | |||
3722 | case CHARDEV_BACKEND_KIND_MUX: | |||
3723 | base = qemu_chr_find(backend->mux->chardev); | |||
3724 | if (base == NULL((void*)0)) { | |||
3725 | error_setg(errp, "mux: base chardev %s not found",error_set(errp, ERROR_CLASS_GENERIC_ERROR, "mux: base chardev %s not found" , backend->mux->chardev) | |||
3726 | backend->mux->chardev)error_set(errp, ERROR_CLASS_GENERIC_ERROR, "mux: base chardev %s not found" , backend->mux->chardev); | |||
3727 | break; | |||
3728 | } | |||
3729 | chr = qemu_chr_open_mux(base); | |||
3730 | break; | |||
3731 | case CHARDEV_BACKEND_KIND_MSMOUSE: | |||
3732 | chr = qemu_chr_open_msmouse(); | |||
3733 | break; | |||
3734 | #ifdef CONFIG_BRLAPI1 | |||
3735 | case CHARDEV_BACKEND_KIND_BRAILLE: | |||
3736 | chr = chr_baum_init(); | |||
3737 | break; | |||
3738 | #endif | |||
3739 | case CHARDEV_BACKEND_KIND_STDIO: | |||
3740 | chr = qemu_chr_open_stdio(backend->stdio); | |||
3741 | break; | |||
3742 | #ifdef _WIN32 | |||
3743 | case CHARDEV_BACKEND_KIND_CONSOLE: | |||
3744 | chr = qemu_chr_open_win_con(); | |||
3745 | break; | |||
3746 | #endif | |||
3747 | #ifdef CONFIG_SPICE1 | |||
3748 | case CHARDEV_BACKEND_KIND_SPICEVMC: | |||
3749 | chr = qemu_chr_open_spice_vmc(backend->spicevmc->type); | |||
3750 | break; | |||
3751 | case CHARDEV_BACKEND_KIND_SPICEPORT: | |||
3752 | chr = qemu_chr_open_spice_port(backend->spiceport->fqdn); | |||
3753 | break; | |||
3754 | #endif | |||
3755 | case CHARDEV_BACKEND_KIND_VC: | |||
3756 | chr = vc_init(backend->vc); | |||
3757 | break; | |||
3758 | case CHARDEV_BACKEND_KIND_RINGBUF: | |||
3759 | case CHARDEV_BACKEND_KIND_MEMORY: | |||
3760 | chr = qemu_chr_open_ringbuf(backend->ringbuf, errp); | |||
3761 | break; | |||
3762 | default: | |||
3763 | error_setg(errp, "unknown chardev backend (%d)", backend->kind)error_set(errp, ERROR_CLASS_GENERIC_ERROR, "unknown chardev backend (%d)" , backend->kind); | |||
3764 | break; | |||
3765 | } | |||
3766 | ||||
3767 | if (chr == NULL((void*)0) && !error_is_set(errp)) { | |||
3768 | error_setg(errp, "Failed to create chardev")error_set(errp, ERROR_CLASS_GENERIC_ERROR, "Failed to create chardev" ); | |||
3769 | } | |||
3770 | if (chr) { | |||
3771 | chr->label = g_strdup(id); | |||
3772 | chr->avail_connections = | |||
3773 | (backend->kind == CHARDEV_BACKEND_KIND_MUX) ? MAX_MUX4 : 1; | |||
3774 | if (!chr->filename) { | |||
3775 | chr->filename = g_strdup(ChardevBackendKind_lookup[backend->kind]); | |||
3776 | } | |||
3777 | if (!chr->explicit_be_open) { | |||
3778 | qemu_chr_be_event(chr, CHR_EVENT_OPENED2); | |||
3779 | } | |||
3780 | QTAILQ_INSERT_TAIL(&chardevs, chr, next)do { (chr)->next.tqe_next = ((void*)0); (chr)->next.tqe_prev = (&chardevs)->tqh_last; *(&chardevs)->tqh_last = (chr); (&chardevs)->tqh_last = &(chr)->next. tqe_next; } while ( 0); | |||
3781 | return ret; | |||
3782 | } else { | |||
3783 | g_free(ret); | |||
3784 | return NULL((void*)0); | |||
3785 | } | |||
3786 | } | |||
3787 | ||||
3788 | void qmp_chardev_remove(const char *id, Error **errp) | |||
3789 | { | |||
3790 | CharDriverState *chr; | |||
3791 | ||||
3792 | chr = qemu_chr_find(id); | |||
3793 | if (NULL((void*)0) == chr) { | |||
3794 | error_setg(errp, "Chardev '%s' not found", id)error_set(errp, ERROR_CLASS_GENERIC_ERROR, "Chardev '%s' not found" , id); | |||
3795 | return; | |||
3796 | } | |||
3797 | if (chr->chr_can_read || chr->chr_read || | |||
3798 | chr->chr_event || chr->handler_opaque) { | |||
3799 | error_setg(errp, "Chardev '%s' is busy", id)error_set(errp, ERROR_CLASS_GENERIC_ERROR, "Chardev '%s' is busy" , id); | |||
3800 | return; | |||
3801 | } | |||
3802 | qemu_chr_delete(chr); | |||
3803 | } | |||
3804 | ||||
3805 | static void register_types(void) | |||
3806 | { | |||
3807 | register_char_driver_qapi("null", CHARDEV_BACKEND_KIND_NULL, NULL((void*)0)); | |||
3808 | register_char_driver("socket", qemu_chr_open_socket); | |||
3809 | register_char_driver("udp", qemu_chr_open_udp); | |||
3810 | register_char_driver_qapi("ringbuf", CHARDEV_BACKEND_KIND_RINGBUF, | |||
3811 | qemu_chr_parse_ringbuf); | |||
3812 | register_char_driver_qapi("file", CHARDEV_BACKEND_KIND_FILE, | |||
3813 | qemu_chr_parse_file_out); | |||
3814 | register_char_driver_qapi("stdio", CHARDEV_BACKEND_KIND_STDIO, | |||
3815 | qemu_chr_parse_stdio); | |||
3816 | register_char_driver_qapi("serial", CHARDEV_BACKEND_KIND_SERIAL, | |||
3817 | qemu_chr_parse_serial); | |||
3818 | register_char_driver_qapi("tty", CHARDEV_BACKEND_KIND_SERIAL, | |||
3819 | qemu_chr_parse_serial); | |||
3820 | register_char_driver_qapi("parallel", CHARDEV_BACKEND_KIND_PARALLEL, | |||
3821 | qemu_chr_parse_parallel); | |||
3822 | register_char_driver_qapi("parport", CHARDEV_BACKEND_KIND_PARALLEL, | |||
3823 | qemu_chr_parse_parallel); | |||
3824 | register_char_driver_qapi("pty", CHARDEV_BACKEND_KIND_PTY, NULL((void*)0)); | |||
3825 | register_char_driver_qapi("console", CHARDEV_BACKEND_KIND_CONSOLE, NULL((void*)0)); | |||
3826 | register_char_driver_qapi("pipe", CHARDEV_BACKEND_KIND_PIPE, | |||
3827 | qemu_chr_parse_pipe); | |||
3828 | register_char_driver_qapi("mux", CHARDEV_BACKEND_KIND_MUX, | |||
3829 | qemu_chr_parse_mux); | |||
3830 | /* Bug-compatibility: */ | |||
3831 | register_char_driver_qapi("memory", CHARDEV_BACKEND_KIND_MEMORY, | |||
3832 | qemu_chr_parse_ringbuf); | |||
3833 | /* this must be done after machine init, since we register FEs with muxes | |||
3834 | * as part of realize functions like serial_isa_realizefn when -nographic | |||
3835 | * is specified | |||
3836 | */ | |||
3837 | qemu_add_machine_init_done_notifier(&muxes_realize_notify); | |||
3838 | } | |||
3839 | ||||
3840 | type_init(register_types)static void __attribute__((constructor)) do_qemu_init_register_types (void) { register_module_init(register_types, MODULE_INIT_QOM ); }; |