Blame view

arch/um/drivers/pty.c 3.11 KB
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
1
  /*
75886f21e   Jeff Dike   uml: pty channel ...
2
   * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
6
   * Licensed under the GPL
   */
  
  #include <stdio.h>
24fa6c083   Jeff Dike   uml: move remaini...
7
  #include <stdlib.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
  #include <unistd.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
  #include <errno.h>
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
10
11
  #include <fcntl.h>
  #include <string.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
  #include <termios.h>
75886f21e   Jeff Dike   uml: pty channel ...
13
  #include <sys/stat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
  #include "chan_user.h"
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
15
  #include "os.h"
c13e56907   Paolo 'Blaisorblade' Giarrusso   [PATCH] uml: spli...
16
  #include "um_malloc.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
18
19
20
21
22
23
24
  
  struct pty_chan {
  	void (*announce)(char *dev_name, int dev);
  	int dev;
  	int raw;
  	struct termios tt;
  	char dev_name[sizeof("/dev/pts/0123456\0")];
  };
5e7672ec3   Jeff Dike   [PATCH] uml: cons...
25
  static void *pty_chan_init(char *str, int device, const struct chan_opts *opts)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
  {
  	struct pty_chan *data;
43f5b3085   Jeff Dike   uml: fix build wh...
28
  	data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
75886f21e   Jeff Dike   uml: pty channel ...
29
30
  	if (data == NULL)
  		return NULL;
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
31
  	*data = ((struct pty_chan) { .announce  	= opts->announce,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
  				     .dev  		= device,
  				     .raw  		= opts->raw });
75886f21e   Jeff Dike   uml: pty channel ...
34
  	return data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
38
39
40
41
42
43
44
  }
  
  static int pts_open(int input, int output, int primary, void *d,
  		    char **dev_out)
  {
  	struct pty_chan *data = d;
  	char *dev;
  	int fd, err;
  
  	fd = get_pty();
75886f21e   Jeff Dike   uml: pty channel ...
45
  	if (fd < 0) {
b4fd310e1   Jeff Dike   [PATCH] uml: pres...
46
  		err = -errno;
75886f21e   Jeff Dike   uml: pty channel ...
47
48
  		printk(UM_KERN_ERR "open_pts : Failed to open pts
  ");
b4fd310e1   Jeff Dike   [PATCH] uml: pres...
49
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
  	}
75886f21e   Jeff Dike   uml: pty channel ...
51
52
  
  	if (data->raw) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  		CATCH_EINTR(err = tcgetattr(fd, &data->tt));
75886f21e   Jeff Dike   uml: pty channel ...
54
  		if (err)
e99525f97   Jeff Dike   uml: console subs...
55
  			goto out_close;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
  
  		err = raw(fd);
75886f21e   Jeff Dike   uml: pty channel ...
58
  		if (err)
e99525f97   Jeff Dike   uml: console subs...
59
  			goto out_close;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
64
  	}
  
  	dev = ptsname(fd);
  	sprintf(data->dev_name, "%s", dev);
  	*dev_out = data->dev_name;
75886f21e   Jeff Dike   uml: pty channel ...
65

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
  	if (data->announce)
  		(*data->announce)(dev, data->dev);
75886f21e   Jeff Dike   uml: pty channel ...
68
69
  
  	return fd;
e99525f97   Jeff Dike   uml: console subs...
70
71
72
73
  
  out_close:
  	close(fd);
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
76
77
  }
  
  static int getmaster(char *line)
  {
75886f21e   Jeff Dike   uml: pty channel ...
78
  	struct stat buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
82
83
84
85
  	char *pty, *bank, *cp;
  	int master, err;
  
  	pty = &line[strlen("/dev/ptyp")];
  	for (bank = "pqrs"; *bank; bank++) {
  		line[strlen("/dev/pty")] = *bank;
  		*pty = '0';
75886f21e   Jeff Dike   uml: pty channel ...
86
87
  		/* Did we hit the end ? */
  		if ((stat(line, &buf) < 0) && (errno == ENOENT))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
  			break;
75886f21e   Jeff Dike   uml: pty channel ...
89

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
  		for (cp = "0123456789abcdef"; *cp; cp++) {
  			*pty = *cp;
75886f21e   Jeff Dike   uml: pty channel ...
92
  			master = open(line, O_RDWR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
95
96
97
  			if (master >= 0) {
  				char *tp = &line[strlen("/dev/")];
  
  				/* verify slave side is usable */
  				*tp = 't';
75886f21e   Jeff Dike   uml: pty channel ...
98
  				err = access(line, R_OK | W_OK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  				*tp = 'p';
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
100
  				if (!err)
75886f21e   Jeff Dike   uml: pty channel ...
101
102
  					return master;
  				close(master);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
  			}
  		}
  	}
75886f21e   Jeff Dike   uml: pty channel ...
106
107
108
109
  
  	printk(UM_KERN_ERR "getmaster - no usable host pty devices
  ");
  	return -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
113
114
115
116
117
118
119
  }
  
  static int pty_open(int input, int output, int primary, void *d,
  		    char **dev_out)
  {
  	struct pty_chan *data = d;
  	int fd, err;
  	char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx";
  
  	fd = getmaster(dev);
75886f21e   Jeff Dike   uml: pty channel ...
120
121
  	if (fd < 0)
  		return fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122

e99525f97   Jeff Dike   uml: console subs...
123
  	if (data->raw) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
  		err = raw(fd);
e99525f97   Jeff Dike   uml: console subs...
125
126
  		if (err) {
  			close(fd);
75886f21e   Jeff Dike   uml: pty channel ...
127
  			return err;
e99525f97   Jeff Dike   uml: console subs...
128
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  	}
cb8fa61c2   Jeff Dike   uml: arch/um/driv...
130

75886f21e   Jeff Dike   uml: pty channel ...
131
132
  	if (data->announce)
  		(*data->announce)(dev, data->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
134
135
  
  	sprintf(data->dev_name, "%s", dev);
  	*dev_out = data->dev_name;
75886f21e   Jeff Dike   uml: pty channel ...
136
137
  
  	return fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
  }
5e7672ec3   Jeff Dike   [PATCH] uml: cons...
139
  const struct chan_ops pty_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
143
144
145
  	.type		= "pty",
  	.init		= pty_chan_init,
  	.open		= pty_open,
  	.close		= generic_close,
  	.read		= generic_read,
  	.write		= generic_write,
fd9bc53b9   Paolo 'Blaisorblade' Giarrusso   [PATCH] uml conso...
146
  	.console_write	= generic_console_write,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
149
150
  	.window_size	= generic_window_size,
  	.free		= generic_free,
  	.winch		= 0,
  };
5e7672ec3   Jeff Dike   [PATCH] uml: cons...
151
  const struct chan_ops pts_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
155
156
157
  	.type		= "pts",
  	.init		= pty_chan_init,
  	.open		= pts_open,
  	.close		= generic_close,
  	.read		= generic_read,
  	.write		= generic_write,
fd9bc53b9   Paolo 'Blaisorblade' Giarrusso   [PATCH] uml conso...
158
  	.console_write	= generic_console_write,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
161
162
  	.window_size	= generic_window_size,
  	.free		= generic_free,
  	.winch		= 0,
  };