Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/um/drivers/pty.c
26439 views
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
};
166
167