^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <termios.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "chan_user.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <os.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <um_malloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct pty_chan {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) void (*announce)(char *dev_name, int dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) int dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) int raw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct termios tt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) char dev_name[sizeof("/dev/pts/0123456\0")];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static void *pty_chan_init(char *str, int device, const struct chan_opts *opts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct pty_chan *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) if (data == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *data = ((struct pty_chan) { .announce = opts->announce,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) .dev = device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) .raw = opts->raw });
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int pts_open(int input, int output, int primary, void *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) char **dev_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct pty_chan *data = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) char *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int fd, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) fd = get_pty();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) err = -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) printk(UM_KERN_ERR "open_pts : Failed to open pts\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (data->raw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) CATCH_EINTR(err = tcgetattr(fd, &data->tt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) err = raw(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) goto out_close;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) dev = ptsname(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) sprintf(data->dev_name, "%s", dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) *dev_out = data->dev_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (data->announce)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) (*data->announce)(dev, data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) out_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int getmaster(char *line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct stat buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) char *pty, *bank, *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int master, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) pty = &line[strlen("/dev/ptyp")];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) for (bank = "pqrs"; *bank; bank++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) line[strlen("/dev/pty")] = *bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) *pty = '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* Did we hit the end ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if ((stat(line, &buf) < 0) && (errno == ENOENT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) for (cp = "0123456789abcdef"; *cp; cp++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) *pty = *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) master = open(line, O_RDWR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (master >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) char *tp = &line[strlen("/dev/")];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* verify slave side is usable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) *tp = 't';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) err = access(line, R_OK | W_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) *tp = 'p';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) close(master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) printk(UM_KERN_ERR "getmaster - no usable host pty devices\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static int pty_open(int input, int output, int primary, void *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) char **dev_out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct pty_chan *data = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int fd, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) fd = getmaster(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (data->raw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) err = raw(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (data->announce)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) (*data->announce)(dev, data->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) sprintf(data->dev_name, "%s", dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) *dev_out = data->dev_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) const struct chan_ops pty_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .type = "pty",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .init = pty_chan_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .open = pty_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .close = generic_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .read = generic_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .write = generic_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .console_write = generic_console_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .window_size = generic_window_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .free = generic_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .winch = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) const struct chan_ops pts_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .type = "pts",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .init = pty_chan_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .open = pts_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .close = generic_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .read = generic_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .write = generic_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .console_write = generic_console_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .window_size = generic_window_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .free = generic_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .winch = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) };