aboutsummaryrefslogtreecommitdiff
path: root/chardev/char-pty.c
diff options
context:
space:
mode:
Diffstat (limited to 'chardev/char-pty.c')
-rw-r--r--chardev/char-pty.c41
1 files changed, 38 insertions, 3 deletions
diff --git a/chardev/char-pty.c b/chardev/char-pty.c
index cc2f761..674e9b3 100644
--- a/chardev/char-pty.c
+++ b/chardev/char-pty.c
@@ -29,6 +29,7 @@
#include "qemu/sockets.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
+#include "qemu/option.h"
#include "qemu/qemu-print.h"
#include "chardev/char-io.h"
@@ -41,6 +42,7 @@ struct PtyChardev {
int connected;
GSource *timer_src;
+ char *path;
};
typedef struct PtyChardev PtyChardev;
@@ -152,7 +154,7 @@ static gboolean pty_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
Chardev *chr = CHARDEV(opaque);
PtyChardev *s = PTY_CHARDEV(opaque);
gsize len;
- uint8_t buf[CHR_READ_BUF_LEN];
+ QEMU_UNINITIALIZED uint8_t buf[CHR_READ_BUF_LEN];
ssize_t ret;
len = sizeof(buf);
@@ -179,6 +181,9 @@ static void pty_chr_state(Chardev *chr, int connected)
if (!connected) {
remove_fd_in_watch(chr);
+ if (s->connected) {
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
+ }
s->connected = 0;
/* (re-)connect poll interval for idle guests: once per second.
* We check more frequently in case the guests sends data to
@@ -204,10 +209,15 @@ static void char_pty_finalize(Object *obj)
Chardev *chr = CHARDEV(obj);
PtyChardev *s = PTY_CHARDEV(obj);
+ /* unlink symlink */
+ if (s->path) {
+ unlink(s->path);
+ g_free(s->path);
+ }
+
pty_chr_state(chr, 0);
object_unref(OBJECT(s->ioc));
pty_chr_timer_cancel(s);
- qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
#if defined HAVE_PTY_H
@@ -330,6 +340,7 @@ static void char_pty_open(Chardev *chr,
int master_fd, slave_fd;
char pty_name[PATH_MAX];
char *name;
+ char *path = backend->u.pty.data->path;
master_fd = qemu_openpty_raw(&slave_fd, pty_name);
if (master_fd < 0) {
@@ -354,12 +365,36 @@ static void char_pty_open(Chardev *chr,
g_free(name);
s->timer_src = NULL;
*be_opened = false;
+
+ /* create symbolic link */
+ if (path) {
+ int res = symlink(pty_name, path);
+
+ if (res != 0) {
+ error_setg_errno(errp, errno, "Failed to create PTY symlink");
+ } else {
+ s->path = g_strdup(path);
+ }
+ }
+}
+
+static void char_pty_parse(QemuOpts *opts, ChardevBackend *backend,
+ Error **errp)
+{
+ const char *path = qemu_opt_get(opts, "path");
+ ChardevPty *pty;
+
+ backend->type = CHARDEV_BACKEND_KIND_PTY;
+ pty = backend->u.pty.data = g_new0(ChardevPty, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevPty_base(pty));
+ pty->path = g_strdup(path);
}
-static void char_pty_class_init(ObjectClass *oc, void *data)
+static void char_pty_class_init(ObjectClass *oc, const void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->parse = char_pty_parse;
cc->open = char_pty_open;
cc->chr_write = char_pty_chr_write;
cc->chr_update_read_handler = pty_chr_update_read_handler;