static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)

{

    CharDriverState *chr = NULL;

    TCPCharDriver *s = NULL;

    int fd = -1;

    int is_listen;

    int is_waitconnect;

    int do_nodelay;

    int is_unix;

    int is_telnet;

    int ret;



    is_listen      = qemu_opt_get_bool(opts, "server", 0);

    is_waitconnect = qemu_opt_get_bool(opts, "wait", 1);

    is_telnet      = qemu_opt_get_bool(opts, "telnet", 0);

    do_nodelay     = !qemu_opt_get_bool(opts, "delay", 1);

    is_unix        = qemu_opt_get(opts, "path") != NULL;

    if (!is_listen)

        is_waitconnect = 0;



    chr = g_malloc0(sizeof(CharDriverState));

    s = g_malloc0(sizeof(TCPCharDriver));



    if (is_unix) {

        if (is_listen) {

            fd = unix_listen_opts(opts);

        } else {

            fd = unix_connect_opts(opts);

        }

    } else {

        if (is_listen) {

            fd = inet_listen_opts(opts, 0);

        } else {

            fd = inet_connect_opts(opts);

        }

    }

    if (fd < 0) {

        ret = -errno;

        goto fail;

    }



    if (!is_waitconnect)

        socket_set_nonblock(fd);



    s->connected = 0;

    s->fd = -1;

    s->listen_fd = -1;

    s->msgfd = -1;

    s->is_unix = is_unix;

    s->do_nodelay = do_nodelay && !is_unix;



    chr->opaque = s;

    chr->chr_write = tcp_chr_write;

    chr->chr_close = tcp_chr_close;

    chr->get_msgfd = tcp_get_msgfd;

    chr->chr_add_client = tcp_chr_add_client;



    if (is_listen) {

        s->listen_fd = fd;

        qemu_set_fd_handler2(s->listen_fd, NULL, tcp_chr_accept, NULL, chr);

        if (is_telnet)

            s->do_telnetopt = 1;



    } else {

        s->connected = 1;

        s->fd = fd;

        socket_set_nodelay(fd);

        tcp_chr_connect(chr);

    }



    /* for "info chardev" monitor command */

    chr->filename = g_malloc(256);

    if (is_unix) {

        snprintf(chr->filename, 256, "unix:%s%s",

                 qemu_opt_get(opts, "path"),

                 qemu_opt_get_bool(opts, "server", 0) ? ",server" : "");

    } else if (is_telnet) {

        snprintf(chr->filename, 256, "telnet:%s:%s%s",

                 qemu_opt_get(opts, "host"), qemu_opt_get(opts, "port"),

                 qemu_opt_get_bool(opts, "server", 0) ? ",server" : "");

    } else {

        snprintf(chr->filename, 256, "tcp:%s:%s%s",

                 qemu_opt_get(opts, "host"), qemu_opt_get(opts, "port"),

                 qemu_opt_get_bool(opts, "server", 0) ? ",server" : "");

    }



    if (is_listen && is_waitconnect) {

        printf("QEMU waiting for connection on: %s\n",

               chr->filename);

        tcp_chr_accept(chr);

        socket_set_nonblock(s->listen_fd);

    }



    *_chr = chr;

    return 0;



 fail:

    if (fd >= 0)

        closesocket(fd);

    g_free(s);

    g_free(chr);

    return ret;

}
