/[LeafOK_CVS]/lbbs/src/io.c
ViewVC logotype

Annotation of /lbbs/src/io.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.58 - (hide annotations)
Sun Oct 19 09:09:18 2025 UTC (4 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.57: +11 -6 lines
Content type: text/x-csrc
Refine tocode passed into iconv_open()

1 sysadm 1.1 /***************************************************************************
2 sysadm 1.14 io.c - description
3     -------------------
4 sysadm 1.20 Copyright : (C) 2004-2025 by Leaflet
5     Email : leaflet@leafok.com
6 sysadm 1.1 ***************************************************************************/
7    
8     /***************************************************************************
9     * *
10     * This program is free software; you can redistribute it and/or modify *
11     * it under the terms of the GNU General Public License as published by *
12 sysadm 1.20 * the Free Software Foundation; either version 3 of the License, or *
13 sysadm 1.1 * (at your option) any later version. *
14     * *
15     ***************************************************************************/
16    
17 sysadm 1.47 #include "common.h"
18 sysadm 1.1 #include "io.h"
19 sysadm 1.16 #include "log.h"
20 sysadm 1.22 #include <errno.h>
21 sysadm 1.47 #include <fcntl.h>
22     #include <stdarg.h>
23 sysadm 1.1 #include <stdio.h>
24 sysadm 1.28 #include <string.h>
25 sysadm 1.9 #include <time.h>
26     #include <unistd.h>
27 sysadm 1.47 #include <sys/epoll.h>
28     #include <sys/ioctl.h>
29 sysadm 1.22 #include <sys/select.h>
30 sysadm 1.47 #include <libssh/callbacks.h>
31 sysadm 1.39 #include <libssh/libssh.h>
32     #include <libssh/server.h>
33 sysadm 1.1
34 sysadm 1.58 char stdio_charset[20] = BBS_DEFAULT_CHARSET;
35 sysadm 1.55
36     // static input / output buffer
37     static char stdin_buf[LINE_BUFFER_LEN];
38 sysadm 1.57 static char stdout_buf[BUFSIZ];
39 sysadm 1.55 static int stdin_buf_len = 0;
40 sysadm 1.57 static int stdout_buf_len = 0;
41 sysadm 1.55 static int stdin_buf_offset = 0;
42 sysadm 1.57 static int stdout_buf_offset = 0;
43 sysadm 1.55
44 sysadm 1.57 static char stdin_conv[LINE_BUFFER_LEN * 2];
45     static char stdout_conv[BUFSIZ * 2];
46     static int stdin_conv_len = 0;
47 sysadm 1.55 static int stdout_conv_len = 0;
48 sysadm 1.57 static int stdin_conv_offset = 0;
49 sysadm 1.55 static int stdout_conv_offset = 0;
50    
51     static iconv_t stdin_cd = NULL;
52     static iconv_t stdout_cd = NULL;
53 sysadm 1.1
54 sysadm 1.14 int prints(const char *format, ...)
55 sysadm 1.1 {
56 sysadm 1.28 char buf[BUFSIZ];
57 sysadm 1.14 va_list args;
58 sysadm 1.28 int ret;
59 sysadm 1.1
60 sysadm 1.14 va_start(args, format);
61 sysadm 1.28 ret = vsnprintf(buf, sizeof(buf), format, args);
62 sysadm 1.14 va_end(args);
63 sysadm 1.1
64 sysadm 1.30 if (ret > 0)
65 sysadm 1.28 {
66 sysadm 1.30 if (stdout_buf_len + ret > BUFSIZ)
67     {
68     iflush();
69     }
70 sysadm 1.31
71 sysadm 1.30 if (stdout_buf_len + ret <= BUFSIZ)
72     {
73     memcpy(stdout_buf + stdout_buf_len, buf, (size_t)ret);
74     stdout_buf_len += ret;
75     }
76     else
77     {
78     errno = EAGAIN;
79     ret = (BUFSIZ - stdout_buf_len - ret);
80 sysadm 1.35 log_error("Output buffer is full, additional %d is required\n", ret);
81 sysadm 1.30 }
82 sysadm 1.28 }
83 sysadm 1.30
84     return ret;
85     }
86    
87     int outc(char c)
88     {
89     int ret;
90    
91     if (stdout_buf_len + 1 > BUFSIZ)
92 sysadm 1.28 {
93 sysadm 1.30 iflush();
94     }
95    
96     if (stdout_buf_len + 1 <= BUFSIZ)
97     {
98     stdout_buf[stdout_buf_len] = c;
99     stdout_buf_len++;
100     }
101     else
102     {
103     errno = EAGAIN;
104     ret = -1;
105 sysadm 1.28 }
106    
107     return ret;
108 sysadm 1.1 }
109    
110 sysadm 1.43 int iflush(void)
111 sysadm 1.1 {
112 sysadm 1.28 int flags;
113 sysadm 1.29 struct epoll_event ev, events[MAX_EVENTS];
114     int nfds, epollfd;
115 sysadm 1.30 int retry;
116 sysadm 1.28 int ret = 0;
117    
118 sysadm 1.29 epollfd = epoll_create1(0);
119     if (epollfd < 0)
120     {
121     log_error("epoll_create1() error (%d)\n", errno);
122     return -1;
123     }
124    
125     ev.events = EPOLLOUT;
126     ev.data.fd = STDOUT_FILENO;
127     if (epoll_ctl(epollfd, EPOLL_CTL_ADD, STDOUT_FILENO, &ev) == -1)
128     {
129     log_error("epoll_ctl(STDOUT_FILENO) error (%d)\n", errno);
130 sysadm 1.31 if (close(epollfd) < 0)
131     {
132     log_error("close(epoll) error (%d)\n");
133     }
134 sysadm 1.29 return -1;
135     }
136    
137 sysadm 1.28 // Set STDOUT as non-blocking
138     flags = fcntl(STDOUT_FILENO, F_GETFL, 0);
139     fcntl(STDOUT_FILENO, F_SETFL, flags | O_NONBLOCK);
140    
141 sysadm 1.30 // Retry wait / flush for at most 3 times
142     retry = 3;
143     while (retry > 0 && !SYS_server_exit)
144 sysadm 1.28 {
145 sysadm 1.30 retry--;
146    
147 sysadm 1.29 nfds = epoll_wait(epollfd, events, MAX_EVENTS, 100); // 0.1 second
148 sysadm 1.28
149 sysadm 1.29 if (nfds < 0)
150 sysadm 1.28 {
151 sysadm 1.29 if (errno != EINTR)
152     {
153     log_error("epoll_wait() error (%d)\n", errno);
154     break;
155     }
156 sysadm 1.28 continue;
157     }
158 sysadm 1.29 else if (nfds == 0) // timeout
159 sysadm 1.28 {
160 sysadm 1.29 continue;
161 sysadm 1.28 }
162 sysadm 1.29
163     for (int i = 0; i < nfds; i++)
164 sysadm 1.28 {
165 sysadm 1.29 if (events[i].data.fd == STDOUT_FILENO)
166 sysadm 1.28 {
167 sysadm 1.55 if (stdout_buf_offset < stdout_buf_len)
168     {
169     ret = io_buf_conv(stdout_cd, stdout_buf, &stdout_buf_len, &stdout_buf_offset, stdout_conv, sizeof(stdout_conv), &stdout_conv_len);
170     if (ret < 0)
171     {
172     log_error("io_buf_conv(stdout, %d, %d, %d) error\n", stdout_buf_len, stdout_buf_offset, stdout_conv_len);
173     }
174     }
175    
176     while (stdout_conv_offset < stdout_conv_len && !SYS_server_exit) // write until complete or error
177 sysadm 1.28 {
178 sysadm 1.39 if (SSH_v2)
179     {
180 sysadm 1.55 ret = ssh_channel_write(SSH_channel, stdout_conv + stdout_conv_offset, (uint32_t)(stdout_conv_len - stdout_conv_offset));
181 sysadm 1.39 if (ret == SSH_ERROR)
182     {
183     log_error("ssh_channel_write() error: %s\n", ssh_get_error(SSH_session));
184     retry = 0;
185     break;
186     }
187     }
188     else
189     {
190 sysadm 1.55 ret = (int)write(STDOUT_FILENO, stdout_conv + stdout_conv_offset, (size_t)(stdout_conv_len - stdout_conv_offset));
191 sysadm 1.39 }
192 sysadm 1.29 if (ret < 0)
193     {
194     if (errno == EAGAIN || errno == EWOULDBLOCK)
195     {
196     break;
197     }
198     else if (errno == EINTR)
199     {
200     continue;
201     }
202     else
203     {
204 sysadm 1.46 #ifdef _DEBUG
205 sysadm 1.29 log_error("write(STDOUT) error (%d)\n", errno);
206 sysadm 1.46 #endif
207 sysadm 1.30 retry = 0;
208 sysadm 1.29 break;
209     }
210     }
211     else if (ret == 0) // broken pipe
212     {
213 sysadm 1.30 retry = 0;
214 sysadm 1.29 break;
215     }
216     else
217     {
218 sysadm 1.55 stdout_conv_offset += ret;
219     if (stdout_conv_offset >= stdout_conv_len) // flush buffer completely
220 sysadm 1.29 {
221     ret = 0;
222 sysadm 1.55 stdout_conv_offset = 0;
223     stdout_conv_len = 0;
224 sysadm 1.30 retry = 0;
225 sysadm 1.29 break;
226     }
227     continue;
228     }
229 sysadm 1.28 }
230     }
231     }
232     }
233 sysadm 1.6
234 sysadm 1.28 // Restore STDOUT flags
235     fcntl(STDOUT_FILENO, F_SETFL, flags);
236 sysadm 1.6
237 sysadm 1.31 if (close(epollfd) < 0)
238     {
239     log_error("close(epoll) error (%d)\n");
240     }
241    
242 sysadm 1.28 return ret;
243 sysadm 1.1 }
244    
245 sysadm 1.31 int igetch(int timeout)
246 sysadm 1.1 {
247 sysadm 1.29 struct epoll_event ev, events[MAX_EVENTS];
248     int nfds, epollfd;
249 sysadm 1.31 int ret;
250     int loop;
251 sysadm 1.21
252 sysadm 1.22 unsigned char tmp[LINE_BUFFER_LEN];
253 sysadm 1.31 int out = KEY_NULL;
254 sysadm 1.18 int in_esc = 0;
255     int in_ascii = 0;
256     int in_control = 0;
257     int i = 0;
258 sysadm 1.26 int flags;
259 sysadm 1.1
260 sysadm 1.55 if (stdin_conv_offset >= stdin_conv_len)
261 sysadm 1.29 {
262 sysadm 1.55 stdin_conv_len = 0;
263     stdin_conv_offset = 0;
264 sysadm 1.31
265 sysadm 1.48 epollfd = epoll_create1(0);
266     if (epollfd < 0)
267 sysadm 1.31 {
268 sysadm 1.48 log_error("epoll_create1() error (%d)\n", errno);
269     return -1;
270 sysadm 1.31 }
271 sysadm 1.9
272 sysadm 1.48 ev.events = EPOLLIN;
273     ev.data.fd = STDIN_FILENO;
274     if (epoll_ctl(epollfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev) == -1)
275     {
276     log_error("epoll_ctl(STDIN_FILENO) error (%d)\n", errno);
277 sysadm 1.9
278 sysadm 1.48 if (close(epollfd) < 0)
279     {
280     log_error("close(epoll) error (%d)\n");
281     }
282     return -1;
283     }
284 sysadm 1.31
285 sysadm 1.48 flags = fcntl(STDIN_FILENO, F_GETFL, 0);
286     fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
287 sysadm 1.31
288 sysadm 1.57 for (loop = 1; loop && stdin_buf_len < sizeof(stdin_buf) && stdin_conv_offset >= stdin_conv_len && !SYS_server_exit;)
289 sysadm 1.39 {
290 sysadm 1.48 if (SSH_v2 && ssh_channel_is_closed(SSH_channel))
291     {
292     log_error("SSH channel is closed\n");
293     loop = 0;
294     break;
295     }
296 sysadm 1.39
297 sysadm 1.48 nfds = epoll_wait(epollfd, events, MAX_EVENTS, timeout);
298 sysadm 1.9
299 sysadm 1.48 if (nfds < 0)
300     {
301     if (errno != EINTR)
302     {
303     log_error("epoll_wait() error (%d)\n", errno);
304     break;
305     }
306     continue;
307     }
308     else if (nfds == 0) // timeout
309 sysadm 1.21 {
310 sysadm 1.48 out = KEY_TIMEOUT;
311 sysadm 1.31 break;
312 sysadm 1.21 }
313    
314 sysadm 1.48 for (int i = 0; i < nfds; i++)
315 sysadm 1.26 {
316 sysadm 1.48 if (events[i].data.fd == STDIN_FILENO)
317 sysadm 1.26 {
318 sysadm 1.55 while (stdin_buf_len < sizeof(stdin_buf) && !SYS_server_exit) // read until complete or error
319 sysadm 1.39 {
320 sysadm 1.48 if (SSH_v2)
321 sysadm 1.39 {
322 sysadm 1.55 ret = ssh_channel_read_nonblocking(SSH_channel, stdin_buf + stdin_buf_len, sizeof(stdin_buf) - (uint32_t)stdin_buf_len, 0);
323 sysadm 1.48 if (ret == SSH_ERROR)
324     {
325     log_error("ssh_channel_read_nonblocking() error: %s\n", ssh_get_error(SSH_session));
326     loop = 0;
327     break;
328     }
329     else if (ret == SSH_EOF)
330     {
331     loop = 0;
332     break;
333     }
334     else if (ret == 0)
335     {
336     out = 0;
337 sysadm 1.52 loop = 0;
338     break;
339 sysadm 1.48 }
340 sysadm 1.39 }
341 sysadm 1.48 else
342 sysadm 1.39 {
343 sysadm 1.55 ret = (int)read(STDIN_FILENO, stdin_buf + stdin_buf_len, sizeof(stdin_buf) - (size_t)stdin_buf_len);
344 sysadm 1.39 }
345 sysadm 1.48 if (ret < 0)
346 sysadm 1.39 {
347 sysadm 1.48 if (errno == EAGAIN || errno == EWOULDBLOCK)
348     {
349     out = 0;
350     loop = 0;
351     break;
352     }
353     else if (errno == EINTR)
354     {
355     continue;
356     }
357     else
358     {
359     #ifdef _DEBUG
360     log_error("read(STDIN) error (%d)\n", errno);
361     #endif
362     loop = 0;
363     break;
364     }
365 sysadm 1.39 }
366 sysadm 1.48 else if (ret == 0) // broken pipe
367 sysadm 1.29 {
368 sysadm 1.31 loop = 0;
369     break;
370 sysadm 1.29 }
371 sysadm 1.48 else
372 sysadm 1.29 {
373 sysadm 1.55 stdin_buf_len += ret;
374 sysadm 1.29 continue;
375     }
376     }
377 sysadm 1.26 }
378     }
379 sysadm 1.48
380     // For debug
381     #ifdef _DEBUG
382 sysadm 1.55 for (int j = stdin_buf_offset; j < stdin_buf_len; j++)
383 sysadm 1.48 {
384 sysadm 1.56 log_error("Debug input: <--[%u]\n", (stdin_buf[j] + 256) % 256);
385 sysadm 1.48 }
386     #endif
387 sysadm 1.14 }
388    
389 sysadm 1.48 fcntl(STDIN_FILENO, F_SETFL, flags);
390    
391     if (close(epollfd) < 0)
392 sysadm 1.45 {
393 sysadm 1.48 log_error("close(epoll) error (%d)\n");
394 sysadm 1.45 }
395 sysadm 1.55
396     if (stdin_buf_offset < stdin_buf_len)
397     {
398     ret = io_buf_conv(stdin_cd, stdin_buf, &stdin_buf_len, &stdin_buf_offset, stdin_conv, sizeof(stdin_conv), &stdin_conv_len);
399     if (ret < 0)
400     {
401     log_error("io_buf_conv(stdin, %d, %d, %d) error\n", stdin_buf_len, stdin_buf_offset, stdin_conv_len);
402     }
403 sysadm 1.56
404     // For debug
405     #ifdef _DEBUG
406     for (int j = stdin_conv_offset; j < stdin_conv_len; j++)
407     {
408     log_error("Debug input_conv: <--[%u]\n", (stdin_conv[j] + 256) % 256);
409     }
410     #endif
411 sysadm 1.55 }
412 sysadm 1.11 }
413 sysadm 1.14
414 sysadm 1.55 while (stdin_conv_offset < stdin_conv_len)
415 sysadm 1.11 {
416 sysadm 1.55 unsigned char c = (unsigned char)stdin_conv[stdin_conv_offset++];
417 sysadm 1.5
418 sysadm 1.51 // Convert \r\n to \r
419 sysadm 1.55 if (c == CR && stdin_conv_offset < stdin_conv_len && stdin_conv[stdin_conv_offset] == LF)
420 sysadm 1.51 {
421 sysadm 1.55 stdin_conv_offset++;
422 sysadm 1.51 }
423    
424     // Convert single \n to \r
425     if (c == LF)
426     {
427     c = CR;
428     }
429    
430 sysadm 1.14 if (c == KEY_CONTROL)
431     {
432     if (in_control == 0)
433     {
434     in_control = 1;
435     i = 0;
436     continue;
437     }
438     }
439 sysadm 1.1
440 sysadm 1.14 if (in_control)
441     {
442     tmp[i++] = c;
443     if (i >= 2)
444     {
445     out = (int)tmp[0] * 256 + tmp[1];
446     in_control = 0;
447     break;
448     }
449     continue;
450     }
451 sysadm 1.6
452 sysadm 1.37 if (c == KEY_ESC)
453 sysadm 1.14 {
454     if (in_esc == 0)
455     {
456     in_esc = 1;
457     in_ascii = 1;
458     i = 0;
459     continue;
460     }
461     else
462     {
463 sysadm 1.37 out = KEY_CSI;
464 sysadm 1.14 in_esc = 0;
465     break;
466     }
467     }
468 sysadm 1.3
469 sysadm 1.14 in_esc = 0;
470 sysadm 1.1
471 sysadm 1.14 if (in_ascii)
472     {
473     tmp[i++] = c;
474 sysadm 1.33 if (i == 2 && (tmp[0] == 79 || tmp[0] == 91))
475 sysadm 1.14 {
476     in_ascii = 0;
477 sysadm 1.33 switch (tmp[1])
478 sysadm 1.14 {
479 sysadm 1.33 case 65:
480 sysadm 1.14 out = KEY_UP;
481     break;
482 sysadm 1.33 case 66:
483 sysadm 1.14 out = KEY_DOWN;
484     break;
485 sysadm 1.33 case 67:
486 sysadm 1.14 out = KEY_RIGHT;
487     break;
488 sysadm 1.33 case 68:
489 sysadm 1.14 out = KEY_LEFT;
490     break;
491 sysadm 1.33 default:
492     in_ascii = 1;
493     }
494     if (!in_ascii)
495     {
496     break;
497     }
498     }
499     if (i == 2 && tmp[0] == 91) // Fterm
500     {
501     in_ascii = 0;
502     switch (tmp[1])
503     {
504     case 86:
505     out = KEY_SHIFT_F1;
506     break;
507     case 90:
508     out = KEY_SHIFT_F2;
509     break;
510     case 97:
511     out = KEY_SHIFT_F3;
512     break;
513     case 98:
514     out = KEY_SHIFT_F4;
515     break;
516     case 99:
517     out = KEY_SHIFT_F5;
518     break;
519     case 100:
520     out = KEY_SHIFT_F6;
521     break;
522     case 101:
523     out = KEY_SHIFT_F7;
524     break;
525     case 102:
526     out = KEY_SHIFT_F8;
527     break;
528     case 103:
529     out = KEY_SHIFT_F9;
530     break;
531     case 104:
532     out = KEY_SHIFT_F10;
533     break;
534     case 107:
535     out = KEY_CTRL_F1;
536     break;
537     case 108:
538     out = KEY_CTRL_F2;
539     break;
540     case 109:
541     out = KEY_CTRL_F3;
542     break;
543     case 112:
544     out = KEY_CTRL_F6;
545     break;
546     case 113:
547     out = KEY_CTRL_F7;
548     break;
549     case 114:
550     out = KEY_CTRL_F8;
551     break;
552     case 115:
553     out = KEY_CTRL_F9;
554     break;
555     case 116:
556     out = KEY_CTRL_F10;
557     break;
558     default:
559     in_ascii = 1;
560     }
561     if (!in_ascii)
562     {
563     break;
564     }
565     }
566     if (i == 2 && tmp[0] == 79) // Xterm
567     {
568     in_ascii = 0;
569     switch (tmp[1])
570     {
571     case 80:
572     out = KEY_F1;
573     break;
574     case 81:
575     out = KEY_F2;
576     break;
577     case 82:
578     out = KEY_F3;
579     break;
580     case 83:
581     out = KEY_F4;
582     break;
583     default:
584     in_ascii = 1;
585     }
586     if (!in_ascii)
587     {
588     break;
589 sysadm 1.14 }
590     }
591     if (i == 3 && tmp[0] == 91 && tmp[2] == 126)
592     {
593     in_ascii = 0;
594     switch (tmp[1])
595     {
596     case 49:
597     out = KEY_HOME;
598     break;
599 sysadm 1.42 case 50:
600     out = KEY_INS;
601     break;
602 sysadm 1.14 case 51:
603     out = KEY_DEL;
604     break;
605     case 52:
606     out = KEY_END;
607     break;
608     case 53:
609     out = KEY_PGUP;
610     break;
611     case 54:
612     out = KEY_PGDN;
613     break;
614 sysadm 1.33 default:
615     in_ascii = 1;
616     }
617     if (!in_ascii)
618     {
619     break;
620     }
621     }
622 sysadm 1.39 if (i == 4 && tmp[0] == 91 && tmp[1] == 49 && tmp[3] == 126) // Fterm
623 sysadm 1.33 {
624     in_ascii = 0;
625     switch (tmp[2])
626     {
627     case 49:
628     out = KEY_F1;
629     break;
630     case 50:
631     out = KEY_F2;
632     break;
633     case 51:
634     out = KEY_F3;
635     break;
636     case 52:
637     out = KEY_F4;
638     break;
639     case 53:
640     out = KEY_F5;
641     break;
642     case 55:
643     out = KEY_F6;
644     break;
645     case 56:
646     out = KEY_F7;
647     break;
648     case 57:
649     out = KEY_F8;
650     break;
651     default:
652     in_ascii = 1;
653     }
654     if (!in_ascii)
655     {
656     break;
657     }
658     }
659     if (i == 4 && tmp[0] == 91 && tmp[1] == 50 && tmp[3] == 126) // Fterm
660     {
661     in_ascii = 0;
662     switch (tmp[2])
663     {
664     case 48:
665     out = KEY_F9;
666     break;
667     case 49:
668     out = KEY_F10;
669     break;
670     case 50:
671     out = KEY_F11; // Fterm
672     break;
673     case 51:
674     out = KEY_F11; // Xterm
675     break;
676     case 52:
677     out = KEY_F12; // Xterm
678     break;
679     default:
680     in_ascii = 1;
681     }
682     if (!in_ascii)
683     {
684     break;
685     }
686     }
687     if (i == 5 && tmp[0] == 91 && tmp[1] == 49 && tmp[2] == 59 && tmp[3] == 53) // Xterm
688     {
689     in_ascii = 0;
690     switch (tmp[4])
691     {
692 sysadm 1.41 case 65:
693     out = KEY_CTRL_UP;
694     break;
695     case 66:
696     out = KEY_CTRL_DOWN;
697     break;
698     case 67:
699     out = KEY_CTRL_RIGHT;
700     break;
701     case 68:
702     out = KEY_CTRL_LEFT;
703     break;
704     case 70:
705     out = KEY_CTRL_END;
706     break;
707     case 72:
708     out = KEY_CTRL_HOME;
709     break;
710 sysadm 1.33 case 80:
711     out = KEY_CTRL_F1;
712     break;
713     case 81:
714     out = KEY_CTRL_F2;
715     break;
716     case 82:
717     out = KEY_CTRL_F3;
718     break;
719     default:
720     in_ascii = 1;
721     }
722     if (!in_ascii)
723     {
724     break;
725     }
726     }
727     if (i == 6 && tmp[0] == 91 && tmp[1] == 49 && tmp[3] == 59 && tmp[4] == 53 && tmp[5] == 126) // Xterm
728     {
729     in_ascii = 0;
730     switch (tmp[2])
731     {
732     case 53:
733     out = KEY_CTRL_F5;
734     break;
735     case 55:
736     out = KEY_CTRL_F6;
737     break;
738     case 56:
739     out = KEY_CTRL_F7;
740     break;
741     case 57:
742     out = KEY_CTRL_F8;
743     break;
744     default:
745     in_ascii = 1;
746     }
747     if (!in_ascii)
748     {
749     break;
750     }
751     }
752     if (i == 6 && tmp[0] == 91 && tmp[1] == 50 && tmp[3] == 59 && tmp[4] == 53 && tmp[5] == 126) // Xterm
753     {
754     in_ascii = 0;
755     switch (tmp[2])
756     {
757     case 48:
758     out = KEY_CTRL_F9;
759     break;
760     case 49:
761     out = KEY_CTRL_F10;
762     break;
763     case 51:
764     out = KEY_CTRL_F11;
765     break;
766     case 52:
767     out = KEY_CTRL_F12;
768     break;
769     default:
770     in_ascii = 1;
771     }
772     if (!in_ascii)
773     {
774     break;
775     }
776     }
777     if (i == 5 && tmp[0] == 91 && tmp[1] == 49 && tmp[2] == 59 && tmp[3] == 50) // Xterm
778     {
779     in_ascii = 0;
780     switch (tmp[4])
781     {
782     case 80:
783     out = KEY_SHIFT_F1;
784     break;
785     case 81:
786     out = KEY_SHIFT_F2;
787     break;
788     case 82:
789     out = KEY_SHIFT_F3;
790     break;
791     case 83:
792     out = KEY_SHIFT_F4;
793     break;
794     default:
795     in_ascii = 1;
796     }
797     if (!in_ascii)
798     {
799     break;
800 sysadm 1.14 }
801 sysadm 1.33 }
802     if (i == 6 && tmp[0] == 91 && tmp[1] == 49 && tmp[3] == 59 && tmp[4] == 50 && tmp[5] == 126) // Xterm
803     {
804     in_ascii = 0;
805     switch (tmp[2])
806     {
807     case 53:
808     out = KEY_SHIFT_F5;
809     break;
810     case 55:
811     out = KEY_SHIFT_F6;
812     break;
813     case 56:
814     out = KEY_SHIFT_F7;
815     break;
816     case 57:
817     out = KEY_SHIFT_F8;
818     break;
819     default:
820     in_ascii = 1;
821     }
822     if (!in_ascii)
823     {
824     break;
825     }
826     }
827     if (i == 6 && tmp[0] == 91 && tmp[1] == 50 && tmp[3] == 59 && tmp[4] == 50 && tmp[5] == 126) // Xterm
828     {
829     in_ascii = 0;
830     switch (tmp[2])
831     {
832     case 48:
833     out = KEY_SHIFT_F9;
834     break;
835     case 49:
836     out = KEY_SHIFT_F10;
837     break;
838     case 51:
839     out = KEY_SHIFT_F11;
840     break;
841     case 52:
842     out = KEY_SHIFT_F12;
843     break;
844     default:
845     in_ascii = 1;
846     }
847     if (!in_ascii)
848     {
849     break;
850     }
851     }
852    
853     if (c == 'm')
854     {
855     in_ascii = 0;
856 sysadm 1.14 }
857     continue;
858     }
859 sysadm 1.1
860 sysadm 1.14 out = ((int)c + 256) % 256;
861     break;
862 sysadm 1.1 }
863    
864 sysadm 1.36 // For ESC key
865     if (out == 0 && in_esc)
866     {
867     out = KEY_ESC;
868     }
869    
870 sysadm 1.33 // for debug
871 sysadm 1.45 #ifdef _DEBUG
872     if (out != KEY_TIMEOUT && out != KEY_NULL)
873     {
874 sysadm 1.56 log_error("Debug: -->[0x %x]\n", out);
875 sysadm 1.45 }
876     #endif
877 sysadm 1.33
878 sysadm 1.14 return out;
879 sysadm 1.1 }
880 sysadm 1.5
881 sysadm 1.31 int igetch_t(int sec)
882 sysadm 1.9 {
883 sysadm 1.14 int ch;
884 sysadm 1.44 time_t t_begin = time(NULL);
885 sysadm 1.10
886 sysadm 1.14 do
887     {
888 sysadm 1.31 ch = igetch(100);
889 sysadm 1.44 } while (!SYS_server_exit && ch == KEY_TIMEOUT && (time(NULL) - t_begin < sec));
890 sysadm 1.9
891 sysadm 1.14 return ch;
892 sysadm 1.9 }
893 sysadm 1.31
894     void igetch_reset()
895     {
896     int ch;
897     do
898     {
899 sysadm 1.53 ch = igetch(100);
900 sysadm 1.31 } while (ch != KEY_NULL && ch != KEY_TIMEOUT);
901     }
902 sysadm 1.54
903     int io_buf_conv(iconv_t cd, char *p_buf, int *p_buf_len, int *p_buf_offset, char *p_conv, size_t conv_size, int *p_conv_len)
904     {
905     char *in_buf;
906     char *out_buf;
907     size_t in_bytes;
908     size_t out_bytes;
909     int ret;
910 sysadm 1.56 int in_control = 0;
911     size_t i = 0;
912 sysadm 1.54
913 sysadm 1.55 if (cd == NULL || p_buf == NULL || p_buf_len == NULL || p_buf_offset == NULL || p_conv == NULL || p_conv_len == NULL)
914     {
915     log_error("NULL pointer error\n");
916     return -1;
917     }
918    
919 sysadm 1.54 in_buf = p_buf + *p_buf_offset;
920     in_bytes = (size_t)(*p_buf_len - *p_buf_offset);
921     out_buf = p_conv + *p_conv_len;
922     out_bytes = conv_size - (size_t)(*p_conv_len);
923    
924     while (in_bytes > 0)
925     {
926 sysadm 1.56 if ((unsigned char)(*in_buf) == KEY_CONTROL)
927     {
928     if (in_control == 0)
929     {
930     in_control = 1;
931     i = 0;
932     }
933     }
934    
935     if (in_control)
936     {
937     if (out_bytes <= 0)
938     {
939     log_error("iconv(inbytes=%d, outbytes=%d) error: EILSEQ and E2BIG\n", in_bytes, out_bytes);
940     return -2;
941     }
942    
943     *out_buf = *in_buf;
944     in_buf++;
945     out_buf++;
946     in_bytes--;
947     out_bytes--;
948    
949     (*p_buf_offset)++;
950     *p_conv_len = (int)(conv_size - out_bytes);
951    
952     i++;
953     if (i >= 2)
954     {
955     in_control = 0;
956     }
957     continue;
958     }
959    
960 sysadm 1.54 ret = (int)iconv(cd, &in_buf, &in_bytes, &out_buf, &out_bytes);
961     if (ret == -1)
962     {
963     if (errno == EINVAL) // Incomplete
964     {
965     #ifdef _DEBUG
966 sysadm 1.56 log_error("iconv(inbytes=%d, outbytes=%d) error: EINVAL, in_buf[0]=%d\n", in_bytes, out_bytes, in_buf[0]);
967 sysadm 1.54 #endif
968 sysadm 1.56 if (p_buf != in_buf)
969     {
970     *p_buf_len = (int)(p_buf + *p_buf_len - in_buf);
971     *p_buf_offset = 0;
972     *p_conv_len = (int)(conv_size - out_bytes);
973     memmove(p_buf, in_buf, (size_t)(*p_buf_len));
974     }
975 sysadm 1.54
976     break;
977     }
978     else if (errno == E2BIG)
979     {
980     log_error("iconv(inbytes=%d, outbytes=%d) error: E2BIG\n", in_bytes, out_bytes);
981     return -1;
982     }
983     else if (errno == EILSEQ)
984     {
985     if (in_bytes > out_bytes || out_bytes <= 0)
986     {
987     log_error("iconv(inbytes=%d, outbytes=%d) error: EILSEQ and E2BIG\n", in_bytes, out_bytes);
988     return -2;
989     }
990    
991     *out_buf = *in_buf;
992     in_buf++;
993     out_buf++;
994     in_bytes--;
995     out_bytes--;
996    
997     continue;
998     }
999     }
1000     else
1001     {
1002     *p_buf_len = 0;
1003     *p_buf_offset = 0;
1004     *p_conv_len = (int)(conv_size - out_bytes);
1005    
1006     break;
1007     }
1008     }
1009    
1010     return 0;
1011     }
1012 sysadm 1.55
1013     int io_conv_init(const char *charset)
1014     {
1015 sysadm 1.58 char tocode[32];
1016    
1017 sysadm 1.55 if (charset == NULL)
1018     {
1019     log_error("NULL pointer error\n");
1020     return -1;
1021     }
1022    
1023     io_conv_cleanup();
1024    
1025 sysadm 1.58 strncpy(stdio_charset, charset, sizeof(stdio_charset) - 1);
1026     stdio_charset[sizeof(stdio_charset) - 1] = '\0';
1027 sysadm 1.55
1028 sysadm 1.58 stdin_cd = iconv_open(BBS_DEFAULT_CHARSET "//TRANSLIT", stdio_charset);
1029 sysadm 1.55 if (stdin_cd == (iconv_t)(-1))
1030     {
1031 sysadm 1.58 log_error("iconv_open(%s->%s) error: %d\n", stdio_charset, BBS_DEFAULT_CHARSET "//TRANSLIT", errno);
1032 sysadm 1.55 return -2;
1033     }
1034 sysadm 1.58
1035     snprintf(tocode, sizeof(tocode), "%s//TRANSLIT", stdio_charset);
1036     stdout_cd = iconv_open(tocode, BBS_DEFAULT_CHARSET);
1037 sysadm 1.55 if (stdout_cd == (iconv_t)(-1))
1038     {
1039 sysadm 1.58 log_error("iconv_open(%s->%s) error: %d\n", BBS_DEFAULT_CHARSET, tocode, errno);
1040 sysadm 1.55 iconv_close(stdin_cd);
1041     return -2;
1042     }
1043    
1044     return 0;
1045     }
1046    
1047     int io_conv_cleanup(void)
1048     {
1049     if (stdin_cd != NULL)
1050     {
1051     iconv_close(stdin_cd);
1052     stdin_cd = NULL;
1053     }
1054     if (stdout_cd != NULL)
1055     {
1056     iconv_close(stdout_cd);
1057     stdout_cd = NULL;
1058     }
1059    
1060     return 0;
1061     }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1