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"
27 char dev
[sizeof("32768\0")];
30 static void *port_init(char *str
, int device
, struct chan_opts
*opts
)
32 struct port_chan
*data
;
38 printk("port_init : channel type 'port' must specify a "
43 port
= strtoul(str
, &end
, 0);
44 if((*end
!= '\0') || (end
== str
)){
45 printk("port_init : couldn't parse port '%s'\n", str
);
49 kern_data
= port_data(port
);
53 data
= um_kmalloc(sizeof(*data
));
57 *data
= ((struct port_chan
) { .raw
= opts
->raw
,
58 .kernel_data
= kern_data
});
59 sprintf(data
->dev
, "%d", port
);
63 port_kern_free(kern_data
);
67 static void port_free(void *d
)
69 struct port_chan
*data
= d
;
71 port_kern_free(data
->kernel_data
);
75 static int port_open(int input
, int output
, int primary
, void *d
,
78 struct port_chan
*data
= d
;
81 fd
= port_wait(data
->kernel_data
);
82 if((fd
>= 0) && data
->raw
){
83 CATCH_EINTR(err
= tcgetattr(fd
, &data
->tt
));
95 static void port_close(int fd
, void *d
)
97 struct port_chan
*data
= d
;
99 port_remove_dev(data
->kernel_data
);
103 struct chan_ops port_ops
= {
108 .read
= generic_read
,
109 .write
= generic_write
,
110 .console_write
= generic_console_write
,
111 .window_size
= generic_window_size
,
116 int port_listen_fd(int port
)
118 struct sockaddr_in addr
;
121 fd
= socket(PF_INET
, SOCK_STREAM
, 0);
126 if(setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &arg
, sizeof(arg
)) < 0){
131 addr
.sin_family
= AF_INET
;
132 addr
.sin_port
= htons(port
);
133 addr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
134 if(bind(fd
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0){
139 if(listen(fd
, 1) < 0){
144 err
= os_set_fd_block(fd
, 0);
154 struct port_pre_exec_data
{
159 void port_pre_exec(void *arg
)
161 struct port_pre_exec_data
*data
= arg
;
163 dup2(data
->sock_fd
, 0);
164 dup2(data
->sock_fd
, 1);
165 dup2(data
->sock_fd
, 2);
166 os_close_file(data
->sock_fd
);
167 dup2(data
->pipe_fd
, 3);
168 os_shutdown_socket(3, 1, 0);
169 os_close_file(data
->pipe_fd
);
172 int port_connection(int fd
, int *socket
, int *pid_out
)
175 char *argv
[] = { "/usr/sbin/in.telnetd", "-L",
176 "/usr/lib/uml/port-helper", NULL
};
177 struct port_pre_exec_data data
;
179 new = os_accept_connection(fd
);
183 err
= os_pipe(socket
, 0, 0);
187 data
= ((struct port_pre_exec_data
)
189 .pipe_fd
= socket
[1] });
191 err
= run_helper(port_pre_exec
, &data
, argv
, NULL
);
199 os_shutdown_socket(socket
[0], 1, 1);
200 os_close_file(socket
[0]);
201 os_shutdown_socket(socket
[1], 1, 1);
202 os_close_file(socket
[1]);
209 * Overrides for Emacs so that we follow Linus's tabbing style.
210 * Emacs will notice this stuff at the end of the file and automatically
211 * adjust the settings for this buffer only. This must remain at the end
213 * ---------------------------------------------------------------------------
215 * c-file-style: "linux"