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"
28 char dev
[sizeof("32768\0")];
31 static void *port_init(char *str
, int device
, 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 static int port_console_write(int fd
, const char *buf
, int n
, void *d
)
106 struct port_chan
*data
= d
;
108 return(generic_console_write(fd
, buf
, n
, &data
->tt
));
111 struct chan_ops port_ops
= {
116 .read
= generic_read
,
117 .write
= generic_write
,
118 .console_write
= port_console_write
,
119 .window_size
= generic_window_size
,
124 int port_listen_fd(int port
)
126 struct sockaddr_in addr
;
129 fd
= socket(PF_INET
, SOCK_STREAM
, 0);
134 if(setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &arg
, sizeof(arg
)) < 0){
139 addr
.sin_family
= AF_INET
;
140 addr
.sin_port
= htons(port
);
141 addr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
142 if(bind(fd
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0){
147 if(listen(fd
, 1) < 0){
152 err
= os_set_fd_block(fd
, 0);
162 struct port_pre_exec_data
{
167 void port_pre_exec(void *arg
)
169 struct port_pre_exec_data
*data
= arg
;
171 dup2(data
->sock_fd
, 0);
172 dup2(data
->sock_fd
, 1);
173 dup2(data
->sock_fd
, 2);
174 os_close_file(data
->sock_fd
);
175 dup2(data
->pipe_fd
, 3);
176 os_shutdown_socket(3, 1, 0);
177 os_close_file(data
->pipe_fd
);
180 int port_connection(int fd
, int *socket
, int *pid_out
)
183 char *argv
[] = { "/usr/sbin/in.telnetd", "-L",
184 "/usr/lib/uml/port-helper", NULL
};
185 struct port_pre_exec_data data
;
187 new = os_accept_connection(fd
);
191 err
= os_pipe(socket
, 0, 0);
195 data
= ((struct port_pre_exec_data
)
197 .pipe_fd
= socket
[1] });
199 err
= run_helper(port_pre_exec
, &data
, argv
, NULL
);
207 os_shutdown_socket(socket
[0], 1, 1);
208 os_close_file(socket
[0]);
209 os_shutdown_socket(socket
[1], 1, 1);
210 os_close_file(socket
[1]);
217 * Overrides for Emacs so that we follow Linus's tabbing style.
218 * Emacs will notice this stuff at the end of the file and automatically
219 * adjust the settings for this buffer only. This must remain at the end
221 * ---------------------------------------------------------------------------
223 * c-file-style: "linux"