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

Annotation of /lbbs/src/io.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.55 - (hide annotations)
Sat Oct 18 05:02:15 2025 UTC (4 months, 4 weeks ago) by sysadm
Branch: MAIN
Changes since 1.54: +107 -26 lines
Content type: text/x-csrc
Add user preferred charset selection and conversion

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.55 char stdio_charset[20] = BBS_DEFAULT_CHARSET;
35    
36     // static input / output buffer
37     static char stdin_buf[LINE_BUFFER_LEN];
38     static char stdin_conv[LINE_BUFFER_LEN];
39     static int stdin_buf_len = 0;
40     static int stdin_conv_len = 0;
41     static int stdin_buf_offset = 0;
42     static int stdin_conv_offset = 0;
43    
44 sysadm 1.28 static char stdout_buf[BUFSIZ];
45 sysadm 1.55 static char stdout_conv[BUFSIZ];
46 sysadm 1.28 static int stdout_buf_len = 0;
47 sysadm 1.55 static int stdout_conv_len = 0;
48 sysadm 1.30 static int stdout_buf_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.55 for (loop = 1; loop && 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.55 log_common("Debug: <--[%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     }
404 sysadm 1.11 }
405 sysadm 1.14
406 sysadm 1.55 while (stdin_conv_offset < stdin_conv_len)
407 sysadm 1.11 {
408 sysadm 1.55 unsigned char c = (unsigned char)stdin_conv[stdin_conv_offset++];
409 sysadm 1.5
410 sysadm 1.51 // Convert \r\n to \r
411 sysadm 1.55 if (c == CR && stdin_conv_offset < stdin_conv_len && stdin_conv[stdin_conv_offset] == LF)
412 sysadm 1.51 {
413 sysadm 1.55 stdin_conv_offset++;
414 sysadm 1.51 }
415    
416     // Convert single \n to \r
417     if (c == LF)
418     {
419     c = CR;
420     }
421    
422 sysadm 1.14 if (c == KEY_CONTROL)
423     {
424     if (in_control == 0)
425     {
426     in_control = 1;
427     i = 0;
428     continue;
429     }
430     }
431 sysadm 1.1
432 sysadm 1.14 if (in_control)
433     {
434     tmp[i++] = c;
435     if (i >= 2)
436     {
437     out = (int)tmp[0] * 256 + tmp[1];
438     in_control = 0;
439     break;
440     }
441     continue;
442     }
443 sysadm 1.6
444 sysadm 1.37 if (c == KEY_ESC)
445 sysadm 1.14 {
446     if (in_esc == 0)
447     {
448     in_esc = 1;
449     in_ascii = 1;
450     i = 0;
451     continue;
452     }
453     else
454     {
455 sysadm 1.37 out = KEY_CSI;
456 sysadm 1.14 in_esc = 0;
457     break;
458     }
459     }
460 sysadm 1.3
461 sysadm 1.14 in_esc = 0;
462 sysadm 1.1
463 sysadm 1.14 if (in_ascii)
464     {
465     tmp[i++] = c;
466 sysadm 1.33 if (i == 2 && (tmp[0] == 79 || tmp[0] == 91))
467 sysadm 1.14 {
468     in_ascii = 0;
469 sysadm 1.33 switch (tmp[1])
470 sysadm 1.14 {
471 sysadm 1.33 case 65:
472 sysadm 1.14 out = KEY_UP;
473     break;
474 sysadm 1.33 case 66:
475 sysadm 1.14 out = KEY_DOWN;
476     break;
477 sysadm 1.33 case 67:
478 sysadm 1.14 out = KEY_RIGHT;
479     break;
480 sysadm 1.33 case 68:
481 sysadm 1.14 out = KEY_LEFT;
482     break;
483 sysadm 1.33 default:
484     in_ascii = 1;
485     }
486     if (!in_ascii)
487     {
488     break;
489     }
490     }
491     if (i == 2 && tmp[0] == 91) // Fterm
492     {
493     in_ascii = 0;
494     switch (tmp[1])
495     {
496     case 86:
497     out = KEY_SHIFT_F1;
498     break;
499     case 90:
500     out = KEY_SHIFT_F2;
501     break;
502     case 97:
503     out = KEY_SHIFT_F3;
504     break;
505     case 98:
506     out = KEY_SHIFT_F4;
507     break;
508     case 99:
509     out = KEY_SHIFT_F5;
510     break;
511     case 100:
512     out = KEY_SHIFT_F6;
513     break;
514     case 101:
515     out = KEY_SHIFT_F7;
516     break;
517     case 102:
518     out = KEY_SHIFT_F8;
519     break;
520     case 103:
521     out = KEY_SHIFT_F9;
522     break;
523     case 104:
524     out = KEY_SHIFT_F10;
525     break;
526     case 107:
527     out = KEY_CTRL_F1;
528     break;
529     case 108:
530     out = KEY_CTRL_F2;
531     break;
532     case 109:
533     out = KEY_CTRL_F3;
534     break;
535     case 112:
536     out = KEY_CTRL_F6;
537     break;
538     case 113:
539     out = KEY_CTRL_F7;
540     break;
541     case 114:
542     out = KEY_CTRL_F8;
543     break;
544     case 115:
545     out = KEY_CTRL_F9;
546     break;
547     case 116:
548     out = KEY_CTRL_F10;
549     break;
550     default:
551     in_ascii = 1;
552     }
553     if (!in_ascii)
554     {
555     break;
556     }
557     }
558     if (i == 2 && tmp[0] == 79) // Xterm
559     {
560     in_ascii = 0;
561     switch (tmp[1])
562     {
563     case 80:
564     out = KEY_F1;
565     break;
566     case 81:
567     out = KEY_F2;
568     break;
569     case 82:
570     out = KEY_F3;
571     break;
572     case 83:
573     out = KEY_F4;
574     break;
575     default:
576     in_ascii = 1;
577     }
578     if (!in_ascii)
579     {
580     break;
581 sysadm 1.14 }
582     }
583     if (i == 3 && tmp[0] == 91 && tmp[2] == 126)
584     {
585     in_ascii = 0;
586     switch (tmp[1])
587     {
588     case 49:
589     out = KEY_HOME;
590     break;
591 sysadm 1.42 case 50:
592     out = KEY_INS;
593     break;
594 sysadm 1.14 case 51:
595     out = KEY_DEL;
596     break;
597     case 52:
598     out = KEY_END;
599     break;
600     case 53:
601     out = KEY_PGUP;
602     break;
603     case 54:
604     out = KEY_PGDN;
605     break;
606 sysadm 1.33 default:
607     in_ascii = 1;
608     }
609     if (!in_ascii)
610     {
611     break;
612     }
613     }
614 sysadm 1.39 if (i == 4 && tmp[0] == 91 && tmp[1] == 49 && tmp[3] == 126) // Fterm
615 sysadm 1.33 {
616     in_ascii = 0;
617     switch (tmp[2])
618     {
619     case 49:
620     out = KEY_F1;
621     break;
622     case 50:
623     out = KEY_F2;
624     break;
625     case 51:
626     out = KEY_F3;
627     break;
628     case 52:
629     out = KEY_F4;
630     break;
631     case 53:
632     out = KEY_F5;
633     break;
634     case 55:
635     out = KEY_F6;
636     break;
637     case 56:
638     out = KEY_F7;
639     break;
640     case 57:
641     out = KEY_F8;
642     break;
643     default:
644     in_ascii = 1;
645     }
646     if (!in_ascii)
647     {
648     break;
649     }
650     }
651     if (i == 4 && tmp[0] == 91 && tmp[1] == 50 && tmp[3] == 126) // Fterm
652     {
653     in_ascii = 0;
654     switch (tmp[2])
655     {
656     case 48:
657     out = KEY_F9;
658     break;
659     case 49:
660     out = KEY_F10;
661     break;
662     case 50:
663     out = KEY_F11; // Fterm
664     break;
665     case 51:
666     out = KEY_F11; // Xterm
667     break;
668     case 52:
669     out = KEY_F12; // Xterm
670     break;
671     default:
672     in_ascii = 1;
673     }
674     if (!in_ascii)
675     {
676     break;
677     }
678     }
679     if (i == 5 && tmp[0] == 91 && tmp[1] == 49 && tmp[2] == 59 && tmp[3] == 53) // Xterm
680     {
681     in_ascii = 0;
682     switch (tmp[4])
683     {
684 sysadm 1.41 case 65:
685     out = KEY_CTRL_UP;
686     break;
687     case 66:
688     out = KEY_CTRL_DOWN;
689     break;
690     case 67:
691     out = KEY_CTRL_RIGHT;
692     break;
693     case 68:
694     out = KEY_CTRL_LEFT;
695     break;
696     case 70:
697     out = KEY_CTRL_END;
698     break;
699     case 72:
700     out = KEY_CTRL_HOME;
701     break;
702 sysadm 1.33 case 80:
703     out = KEY_CTRL_F1;
704     break;
705     case 81:
706     out = KEY_CTRL_F2;
707     break;
708     case 82:
709     out = KEY_CTRL_F3;
710     break;
711     default:
712     in_ascii = 1;
713     }
714     if (!in_ascii)
715     {
716     break;
717     }
718     }
719     if (i == 6 && tmp[0] == 91 && tmp[1] == 49 && tmp[3] == 59 && tmp[4] == 53 && tmp[5] == 126) // Xterm
720     {
721     in_ascii = 0;
722     switch (tmp[2])
723     {
724     case 53:
725     out = KEY_CTRL_F5;
726     break;
727     case 55:
728     out = KEY_CTRL_F6;
729     break;
730     case 56:
731     out = KEY_CTRL_F7;
732     break;
733     case 57:
734     out = KEY_CTRL_F8;
735     break;
736     default:
737     in_ascii = 1;
738     }
739     if (!in_ascii)
740     {
741     break;
742     }
743     }
744     if (i == 6 && tmp[0] == 91 && tmp[1] == 50 && tmp[3] == 59 && tmp[4] == 53 && tmp[5] == 126) // Xterm
745     {
746     in_ascii = 0;
747     switch (tmp[2])
748     {
749     case 48:
750     out = KEY_CTRL_F9;
751     break;
752     case 49:
753     out = KEY_CTRL_F10;
754     break;
755     case 51:
756     out = KEY_CTRL_F11;
757     break;
758     case 52:
759     out = KEY_CTRL_F12;
760     break;
761     default:
762     in_ascii = 1;
763     }
764     if (!in_ascii)
765     {
766     break;
767     }
768     }
769     if (i == 5 && tmp[0] == 91 && tmp[1] == 49 && tmp[2] == 59 && tmp[3] == 50) // Xterm
770     {
771     in_ascii = 0;
772     switch (tmp[4])
773     {
774     case 80:
775     out = KEY_SHIFT_F1;
776     break;
777     case 81:
778     out = KEY_SHIFT_F2;
779     break;
780     case 82:
781     out = KEY_SHIFT_F3;
782     break;
783     case 83:
784     out = KEY_SHIFT_F4;
785     break;
786     default:
787     in_ascii = 1;
788     }
789     if (!in_ascii)
790     {
791     break;
792 sysadm 1.14 }
793 sysadm 1.33 }
794     if (i == 6 && tmp[0] == 91 && tmp[1] == 49 && tmp[3] == 59 && tmp[4] == 50 && tmp[5] == 126) // Xterm
795     {
796     in_ascii = 0;
797     switch (tmp[2])
798     {
799     case 53:
800     out = KEY_SHIFT_F5;
801     break;
802     case 55:
803     out = KEY_SHIFT_F6;
804     break;
805     case 56:
806     out = KEY_SHIFT_F7;
807     break;
808     case 57:
809     out = KEY_SHIFT_F8;
810     break;
811     default:
812     in_ascii = 1;
813     }
814     if (!in_ascii)
815     {
816     break;
817     }
818     }
819     if (i == 6 && tmp[0] == 91 && tmp[1] == 50 && tmp[3] == 59 && tmp[4] == 50 && tmp[5] == 126) // Xterm
820     {
821     in_ascii = 0;
822     switch (tmp[2])
823     {
824     case 48:
825     out = KEY_SHIFT_F9;
826     break;
827     case 49:
828     out = KEY_SHIFT_F10;
829     break;
830     case 51:
831     out = KEY_SHIFT_F11;
832     break;
833     case 52:
834     out = KEY_SHIFT_F12;
835     break;
836     default:
837     in_ascii = 1;
838     }
839     if (!in_ascii)
840     {
841     break;
842     }
843     }
844    
845     if (c == 'm')
846     {
847     in_ascii = 0;
848 sysadm 1.14 }
849     continue;
850     }
851 sysadm 1.1
852 sysadm 1.14 out = ((int)c + 256) % 256;
853     break;
854 sysadm 1.1 }
855    
856 sysadm 1.36 // For ESC key
857     if (out == 0 && in_esc)
858     {
859     out = KEY_ESC;
860     }
861    
862 sysadm 1.33 // for debug
863 sysadm 1.45 #ifdef _DEBUG
864     if (out != KEY_TIMEOUT && out != KEY_NULL)
865     {
866     log_common("Debug: -->[0x %x]\n", out);
867     }
868     #endif
869 sysadm 1.33
870 sysadm 1.14 return out;
871 sysadm 1.1 }
872 sysadm 1.5
873 sysadm 1.31 int igetch_t(int sec)
874 sysadm 1.9 {
875 sysadm 1.14 int ch;
876 sysadm 1.44 time_t t_begin = time(NULL);
877 sysadm 1.10
878 sysadm 1.14 do
879     {
880 sysadm 1.31 ch = igetch(100);
881 sysadm 1.44 } while (!SYS_server_exit && ch == KEY_TIMEOUT && (time(NULL) - t_begin < sec));
882 sysadm 1.9
883 sysadm 1.14 return ch;
884 sysadm 1.9 }
885 sysadm 1.31
886     void igetch_reset()
887     {
888     int ch;
889     do
890     {
891 sysadm 1.53 ch = igetch(100);
892 sysadm 1.31 } while (ch != KEY_NULL && ch != KEY_TIMEOUT);
893     }
894 sysadm 1.54
895     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)
896     {
897     char *in_buf;
898     char *out_buf;
899     size_t in_bytes;
900     size_t out_bytes;
901     int ret;
902    
903 sysadm 1.55 if (cd == NULL || p_buf == NULL || p_buf_len == NULL || p_buf_offset == NULL || p_conv == NULL || p_conv_len == NULL)
904     {
905     log_error("NULL pointer error\n");
906     return -1;
907     }
908    
909 sysadm 1.54 in_buf = p_buf + *p_buf_offset;
910     in_bytes = (size_t)(*p_buf_len - *p_buf_offset);
911     out_buf = p_conv + *p_conv_len;
912     out_bytes = conv_size - (size_t)(*p_conv_len);
913    
914     while (in_bytes > 0)
915     {
916     ret = (int)iconv(cd, &in_buf, &in_bytes, &out_buf, &out_bytes);
917     if (ret == -1)
918     {
919     if (errno == EINVAL) // Incomplete
920     {
921     #ifdef _DEBUG
922     log_error("iconv(inbytes=%d, outbytes=%d) error: EINVAL\n", in_bytes, out_bytes);
923     #endif
924     *p_buf_len = (int)(p_buf + *p_buf_len - in_buf);
925     *p_buf_offset = 0;
926     *p_conv_len = (int)(conv_size - out_bytes);
927     memmove(p_buf, in_buf, (size_t)(*p_buf_len));
928    
929     break;
930     }
931     else if (errno == E2BIG)
932     {
933     log_error("iconv(inbytes=%d, outbytes=%d) error: E2BIG\n", in_bytes, out_bytes);
934     return -1;
935     }
936     else if (errno == EILSEQ)
937     {
938     if (in_bytes > out_bytes || out_bytes <= 0)
939     {
940     log_error("iconv(inbytes=%d, outbytes=%d) error: EILSEQ and E2BIG\n", in_bytes, out_bytes);
941     return -2;
942     }
943    
944     *out_buf = *in_buf;
945     in_buf++;
946     out_buf++;
947     in_bytes--;
948     out_bytes--;
949    
950     continue;
951     }
952     }
953     else
954     {
955     *p_buf_len = 0;
956     *p_buf_offset = 0;
957     *p_conv_len = (int)(conv_size - out_bytes);
958    
959     break;
960     }
961     }
962    
963     return 0;
964     }
965 sysadm 1.55
966     int io_conv_init(const char *charset)
967     {
968     if (charset == NULL)
969     {
970     log_error("NULL pointer error\n");
971     return -1;
972     }
973    
974     io_conv_cleanup();
975    
976     strncpy(stdio_charset, charset, sizeof(stdio_charset) - 1);
977     stdio_charset[sizeof(stdio_charset) - 1] = '\0';
978    
979     stdin_cd = iconv_open(BBS_DEFAULT_CHARSET, stdio_charset);
980     if (stdin_cd == (iconv_t)(-1))
981     {
982     log_error("iconv_open(%s->%s) error: %d\n", stdio_charset, BBS_DEFAULT_CHARSET, errno);
983     return -2;
984     }
985     stdout_cd = iconv_open(stdio_charset, BBS_DEFAULT_CHARSET);
986     if (stdout_cd == (iconv_t)(-1))
987     {
988     log_error("iconv_open(%s->%s) error: %d\n", BBS_DEFAULT_CHARSET, stdio_charset, errno);
989     iconv_close(stdin_cd);
990     return -2;
991     }
992    
993     return 0;
994     }
995    
996     int io_conv_cleanup(void)
997     {
998     if (stdin_cd != NULL)
999     {
1000     iconv_close(stdin_cd);
1001     stdin_cd = NULL;
1002     }
1003     if (stdout_cd != NULL)
1004     {
1005     iconv_close(stdout_cd);
1006     stdout_cd = NULL;
1007     }
1008    
1009     return 0;
1010     }

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