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