root/arch/um/drivers/pty.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pty_chan_init
  2. pts_open
  3. getmaster
  4. pty_open

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   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 
  18 struct 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 
  26 static 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 
  40 static 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 
  73 out_close:
  74         close(fd);
  75         return err;
  76 }
  77 
  78 static 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 
 113 static 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 
 141 const 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 
 154 const 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 };

/* [<][>][^][v][top][bottom][index][help] */