2 * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
13 #include <sys/socket.h>
15 #include <netinet/in.h>
16 #include "user_util.h"
17 #include "kern_util.h"
19 #include "chan_user.h"
22 #include "um_malloc.h"
28 char dev
[sizeof("32768\0")];
31 static void *port_init(char *str
, int device
, const struct chan_opts
*opts
)
33 struct port_chan
*data
;
39 printk("port_init : channel type 'port' must specify a "
44 port
= strtoul(str
, &end
, 0);
45 if((*end
!= '\0') || (end
== str
)){
46 printk("port_init : couldn't parse port '%s'\n", str
);
50 kern_data
= port_data(port
);
54 data
= um_kmalloc(sizeof(*data
));
58 *data
= ((struct port_chan
) { .raw
= opts
->raw
,
59 .kernel_data
= kern_data
});
60 sprintf(data
->dev
, "%d", port
);
64 port_kern_free(kern_data
);
68 static void port_free(void *d
)
70 struct port_chan
*data
= d
;
72 port_kern_free(data
->kernel_data
);
76 static int port_open(int input
, int output
, int primary
, void *d
,
79 struct port_chan
*data
= d
;
82 fd
= port_wait(data
->kernel_data
);
83 if((fd
>= 0) && data
->raw
){
84 CATCH_EINTR(err
= tcgetattr(fd
, &data
->tt
));
96 static void port_close(int fd
, void *d
)
98 struct port_chan
*data
= d
;
100 port_remove_dev(data
->kernel_data
);
104 const struct chan_ops port_ops
= {
109 .read
= generic_read
,
110 .write
= generic_write
,
111 .console_write
= generic_console_write
,
112 .window_size
= generic_window_size
,
117 int port_listen_fd(int port
)
119 struct sockaddr_in addr
;
122 fd
= socket(PF_INET
, SOCK_STREAM
, 0);
127 if(setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &arg
, sizeof(arg
)) < 0){
132 addr
.sin_family
= AF_INET
;
133 addr
.sin_port
= htons(port
);
134 addr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
135 if(bind(fd
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0){
140 if(listen(fd
, 1) < 0){
145 err
= os_set_fd_block(fd
, 0);
155 struct port_pre_exec_data
{
160 void port_pre_exec(void *arg
)
162 struct port_pre_exec_data
*data
= arg
;
164 dup2(data
->sock_fd
, 0);
165 dup2(data
->sock_fd
, 1);
166 dup2(data
->sock_fd
, 2);
167 os_close_file(data
->sock_fd
);
168 dup2(data
->pipe_fd
, 3);
169 os_shutdown_socket(3, 1, 0);
170 os_close_file(data
->pipe_fd
);
173 int port_connection(int fd
, int *socket
, int *pid_out
)
176 char *argv
[] = { "/usr/sbin/in.telnetd", "-L",
177 "/usr/lib/uml/port-helper", NULL
};
178 struct port_pre_exec_data data
;
180 new = os_accept_connection(fd
);
184 err
= os_pipe(socket
, 0, 0);
188 data
= ((struct port_pre_exec_data
)
190 .pipe_fd
= socket
[1] });
192 err
= run_helper(port_pre_exec
, &data
, argv
, NULL
);
200 os_shutdown_socket(socket
[0], 1, 1);
201 os_close_file(socket
[0]);
202 os_shutdown_socket(socket
[1], 1, 1);
203 os_close_file(socket
[1]);
210 * Overrides for Emacs so that we follow Linus's tabbing style.
211 * Emacs will notice this stuff at the end of the file and automatically
212 * adjust the settings for this buffer only. This must remain at the end
214 * ---------------------------------------------------------------------------
216 * c-file-style: "linux"