1
2 #include "ddconfig.h"
3
4 #include <stdio.h>
5 #if defined HAVE_SYS_SOCKET_H
6 # include <sys/socket.h>
7 # include <sys/select.h>
8 # include <netinet/in.h>
9 # include <arpa/inet.h>
10 #endif
11 #include <signal.h>
12 #include <unistd.h>
13 #include <stdlib.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <time.h>
17 #include <string.h>
18 #include <stdarg.h>
19 #include <fcntl.h>
20
21 #include "utils.h"
22
23 #include "fuiocl.h"
24
25
26 cl_f *dd= NULL;
27
deb(const char * format,...)28 void deb(const char *format, ...)
29 {
30 return;
31 if (dd==NULL)
32 {
33 dd= mk_io(/*cchars("/dev/pts/2"),cchars("w")*/"","");
34 dd->file_id= open("/dev/pts/4", O_WRONLY);
35 //dd->init();
36 }
37 va_list ap;
38 va_start(ap, format);
39 //dd->vprintf(format, ap);
40 //vdprintf(dd->file_id, format, ap);
41 {
42 char *buf= vformat_string(format, ap);
43 /*dd->*/write(dd->file_id, buf, strlen(buf));
44 free(buf);
45 }
46 va_end(ap);
47 }
48
49
cl_io()50 cl_io::cl_io(): cl_f()
51 {
52 }
53
cl_io(chars fn,chars mode)54 cl_io::cl_io(chars fn, chars mode): cl_f(fn, mode)
55 {
56 }
57
cl_io(int the_server_port)58 cl_io::cl_io(int the_server_port): cl_f(the_server_port)
59 {
60 }
61
62 int
close(void)63 cl_io::close(void)
64 {
65 int i= 0;
66
67 deb("fuio close fid=%d\n", file_id);
68 if ((type == F_SOCKET) ||
69 (type == F_LISTENER))
70 {
71 restore_attributes();
72 shutdown(file_id, 2/*SHUT_RDWR*/);
73 }
74 /*
75 if (file_f)
76 {
77 restore_attributes();
78 i= fclose(file_f);
79 }
80 else*/ if (file_id >= 0)
81 {
82 restore_attributes();
83 i= ::close(file_id);
84 }
85
86 //file_f= NULL;
87 file_id= -1;
88 own= false;
89 file_name= 0;
90 file_mode= 0;
91
92 changed();
93 return i;
94 }
95
~cl_io(void)96 cl_io::~cl_io(void)
97 {
98 deb("~cl_uio fid=%d\n", file_id);
99 restore_attributes();
100 if (echo_of != NULL)
101 echo_of->echo(NULL);
102 if (/*file_f*/file_id>=0)
103 {
104 if (own)
105 close();
106 else
107 stop_use();
108 }
109 }
110
111 void
changed(void)112 cl_io::changed(void)
113 {
114 //printf("fuio changed fid=%d\n", file_id);
115 if (file_id < 0)
116 {
117 type= F_UNKNOWN;
118 }
119 else
120 {
121 type= determine_type();
122 if (type == F_SOCKET) tty= true;
123 }
124 }
125
126 enum file_type
determine_type(void)127 cl_io::determine_type(void)
128 {
129 int i;
130 struct stat s;
131
132 if (file_id < 0)
133 return F_UNKNOWN;
134 i= fstat(file_id, &s);
135 if (i < 0)
136 return F_UNKNOWN;
137
138 if (S_ISDIR(s.st_mode) ||
139 S_ISLNK(s.st_mode))
140 return F_UNKNOWN;
141 if (S_ISCHR(s.st_mode))
142 return F_CHAR;
143 if (S_ISFIFO(s.st_mode))
144 return F_PIPE;
145 if (S_ISBLK(s.st_mode) ||
146 S_ISREG(s.st_mode))
147 return F_FILE;
148 if (S_ISSOCK(s.st_mode))
149 return F_SOCKET;
150 return F_UNKNOWN;
151 }
152
153 int
check_dev(void)154 cl_io::check_dev(void)
155 {
156 struct timeval tv= { 0, 0 };
157 fd_set s;
158 int i;
159
160 if (file_id<0)
161 {
162 return 0;
163 }
164 switch (type)
165 {
166 case F_UNKNOWN:
167 case F_CONSOLE:
168 case F_SERIAL:
169 return false;
170 break;
171 case F_FILE:
172 pick();
173 return last_used != first_free;
174 break;
175 case F_CHAR:
176 case F_SOCKET:
177 case F_LISTENER:
178 case F_PIPE:
179 FD_ZERO(&s);
180 FD_SET(file_id, &s);
181 i= select(file_id+1, &s, NULL, NULL, &tv);
182 if (i >= 0)
183 {
184 int ret= FD_ISSET(file_id, &s);
185 if (type == F_LISTENER)
186 return ret;
187 if (ret)
188 {
189 pick();
190 }
191 return last_used != first_free;
192 }
193 break;
194 }
195 return 0;
196 }
197
198 void
prepare_terminal()199 cl_io::prepare_terminal()
200 {
201 if (type == F_SOCKET)
202 {
203 // assume telnet client
204 char s[7];
205 //deb("preparing TELNET %d\n", file_id);
206 sprintf(s, "%c%c%c%c%c%c", 0xff, 0xfb, 1, 0xff, 0xfb, 3 );
207 write(s, 7);
208 }
209 else if (tty)
210 {
211 struct termios tattr;
212 //deb("preparing TTY %d\n", file_id);
213 tcgetattr(file_id, &tattr);
214 tattr.c_iflag&= ~IXON;
215 tattr.c_lflag&= ~ICANON;
216 tattr.c_lflag&= ~ECHO;
217 tattr.c_cc[VMIN] = 1;
218 tattr.c_cc[VTIME]= 0;
219 tcsetattr(file_id, TCSAFLUSH, &tattr);
220 }
221 }
222
223 void
save_attributes()224 cl_io::save_attributes()
225 {
226 if ((tty) &&
227 !attributes_saved)
228 {
229 tcgetattr(file_id, &saved_attributes);
230 attributes_saved= 1;
231 }
232 }
233
234 void
restore_attributes()235 cl_io::restore_attributes()
236 {
237 if (attributes_saved)
238 {
239 saved_attributes.c_lflag|= ICANON|ECHO;
240 tcsetattr(file_id, TCSAFLUSH, &saved_attributes);
241 attributes_saved= 0;
242 }
243 }
244
245 int
mk_srv_socket(int port)246 mk_srv_socket(int port)
247 {
248 int sock, i;
249 struct sockaddr_in name;
250
251 /* Create the socket. */
252 sock= socket(PF_INET, SOCK_STREAM, 0);
253 if (sock < 0)
254 {
255 perror("socket");
256 return(0);
257 }
258
259 /* Give the socket a name. */
260 i= 1;
261 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&i, sizeof(i)) < 0)
262 {
263 perror("setsockopt");
264 }
265 name.sin_family = AF_INET;
266 name.sin_port = htons(port);
267 name.sin_addr.s_addr= htonl(INADDR_ANY);
268 if (bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0)
269 {
270 perror("bind");
271 return(0);
272 }
273
274 return(sock);
275 }
276
277
278 class cl_f *
mk_io(chars fn,chars mode)279 mk_io(chars fn, chars mode)
280 {
281 class cl_io *io;
282
283 if (fn.empty())
284 {
285 io= new cl_io();
286 io->init();
287 return io;
288 }
289 else if (strcmp(fn, "-") == 0)
290 {
291 if (strcmp(mode, "r") == 0)
292 return cp_io(fileno(stdin), mode);
293 else if (strcmp(mode, "w") == 0)
294 return cp_io(fileno(stdout), mode);
295 }
296 io= new cl_io(fn, mode);
297 io->init();
298 return io;
299 }
300
301 class cl_f *
cp_io(int file_id,chars mode)302 cp_io(/*FILE *f*/int file_id, chars mode)
303 {
304 class cl_io *io;
305
306 io= new cl_io();
307 if (/*f*/file_id>=0)
308 io->use_opened(/*fileno(f)*/file_id, mode);
309 return io;
310 }
311
312 class cl_f *
mk_srv(int server_port)313 mk_srv(int server_port)
314 {
315 class cl_io *io;
316
317 io= new cl_io(server_port);
318 io->init();
319 io->type= F_LISTENER;
320 return io;
321 }
322
323
324 int
srv_accept(class cl_f * listen_io,class cl_f ** fin,class cl_f ** fout)325 srv_accept(class cl_f *listen_io,
326 class cl_f **fin, class cl_f **fout)
327 {
328 class cl_io *io;
329 //ACCEPT_SOCKLEN_T size;
330 //struct sockaddr_in sock_addr;
331 int new_sock;
332
333 //size= sizeof(struct sockaddr);
334 new_sock= accept(listen_io->file_id, /*(struct sockaddr *)sock_addr*/NULL, /*&size*/NULL);
335
336 if (fin)
337 {
338 io= new cl_io(listen_io->server_port);
339 if (new_sock > 0)
340 {
341 io->own_opened(new_sock, cchars("r"));
342 }
343 *fin= io;
344 }
345
346 if (fout)
347 {
348 io= new cl_io(listen_io->server_port);
349 if (new_sock > 0)
350 {
351 io->use_opened(new_sock, cchars("w"));
352 }
353 *fout= io;
354 }
355
356 return 0;
357 }
358
359 bool
check_inputs(class cl_list * active,class cl_list * avail)360 check_inputs(class cl_list *active, class cl_list *avail)
361 {
362 int i;
363 bool ret= false;
364
365 if (!active)
366 return false;
367
368 if (avail)
369 avail->disconn_all();
370
371 for (i= 0; i < active->count; i++)
372 {
373 class cl_f *fio= (class cl_f *)active->at(i);
374 //deb("checking fid=%d\n", fio->file_id);
375 if (fio->check_dev() ||
376 fio->eof())
377 {
378 deb("found dev input on fid=%d\n", fio->file_id);
379 if (avail)
380 avail->add(fio);
381 ret= true;
382 }
383 else
384 ;//deb("no dev input on fid=%d\n", fio->file_id);
385 }
386 return ret;
387 }
388
389 void
msleep(int msec)390 msleep(int msec)
391 {
392 struct timespec t;
393
394 t.tv_sec= msec/1000;
395 t.tv_nsec= (msec%1000)*1000000;
396 nanosleep(&t, NULL);
397 }
398
399 void
loop_delay()400 loop_delay()
401 {
402 msleep(100);
403 }
404
405
406 void
sigpipe_off()407 sigpipe_off()
408 {
409 struct sigaction sa;
410 sa.sa_handler= SIG_IGN;
411 sigaction(SIGPIPE, &sa, NULL);
412 }
413
414 /* End of fuio.cc */
415