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

Annotation of /lbbs/src/io.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.29 - (hide annotations)
Mon May 12 09:41:50 2025 UTC (10 months ago) by sysadm
Branch: MAIN
Changes since 1.28: +123 -66 lines
Content type: text/x-csrc
Refact IO with epoll

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     #include "io.h"
18 sysadm 1.16 #include "log.h"
19 sysadm 1.1 #include "common.h"
20 sysadm 1.22 #include <errno.h>
21 sysadm 1.1 #include <stdio.h>
22     #include <stdarg.h>
23 sysadm 1.28 #include <string.h>
24 sysadm 1.9 #include <time.h>
25     #include <fcntl.h>
26     #include <unistd.h>
27 sysadm 1.22 #include <sys/select.h>
28 sysadm 1.5 #include <sys/ioctl.h>
29 sysadm 1.29 #include <sys/epoll.h>
30 sysadm 1.1
31 sysadm 1.28 static char stdout_buf[BUFSIZ];
32     static int stdout_buf_len = 0;
33 sysadm 1.1
34 sysadm 1.14 int prints(const char *format, ...)
35 sysadm 1.1 {
36 sysadm 1.28 char buf[BUFSIZ];
37 sysadm 1.14 va_list args;
38 sysadm 1.28 int ret;
39 sysadm 1.1
40 sysadm 1.14 va_start(args, format);
41 sysadm 1.28 ret = vsnprintf(buf, sizeof(buf), format, args);
42 sysadm 1.14 va_end(args);
43 sysadm 1.1
44 sysadm 1.28 if (ret > 0 && stdout_buf_len + ret < BUFSIZ)
45     {
46     memcpy(stdout_buf + stdout_buf_len, buf, (size_t)(ret + 1));
47     stdout_buf_len += ret;
48     }
49     else if (ret > 0) // No enough free buffer
50     {
51     ret = (BUFSIZ - stdout_buf_len - ret - 1);
52     }
53    
54     return ret;
55 sysadm 1.1 }
56    
57 sysadm 1.14 int iflush()
58 sysadm 1.1 {
59 sysadm 1.28 int flags;
60 sysadm 1.29 struct epoll_event ev, events[MAX_EVENTS];
61     int nfds, epollfd;
62 sysadm 1.28 int stdout_buf_offset = 0;
63     int loop = 1;
64     int ret = 0;
65    
66 sysadm 1.29 epollfd = epoll_create1(0);
67     if (epollfd < 0)
68     {
69     log_error("epoll_create1() error (%d)\n", errno);
70     return -1;
71     }
72    
73     ev.events = EPOLLOUT;
74     ev.data.fd = STDOUT_FILENO;
75     if (epoll_ctl(epollfd, EPOLL_CTL_ADD, STDOUT_FILENO, &ev) == -1)
76     {
77     log_error("epoll_ctl(STDOUT_FILENO) error (%d)\n", errno);
78     return -1;
79     }
80    
81 sysadm 1.28 // Set STDOUT as non-blocking
82     flags = fcntl(STDOUT_FILENO, F_GETFL, 0);
83     fcntl(STDOUT_FILENO, F_SETFL, flags | O_NONBLOCK);
84    
85     while (loop && !SYS_server_exit)
86     {
87 sysadm 1.29 nfds = epoll_wait(epollfd, events, MAX_EVENTS, 100); // 0.1 second
88 sysadm 1.28
89 sysadm 1.29 if (nfds < 0)
90 sysadm 1.28 {
91 sysadm 1.29 if (errno != EINTR)
92     {
93     log_error("epoll_wait() error (%d)\n", errno);
94     break;
95     }
96 sysadm 1.28 continue;
97     }
98 sysadm 1.29 else if (nfds == 0) // timeout
99 sysadm 1.28 {
100 sysadm 1.29 continue;
101 sysadm 1.28 }
102 sysadm 1.29
103     for (int i = 0; i < nfds; i++)
104 sysadm 1.28 {
105 sysadm 1.29 if (events[i].data.fd == STDOUT_FILENO)
106 sysadm 1.28 {
107 sysadm 1.29 while (1) // write until complete or error
108 sysadm 1.28 {
109 sysadm 1.29 ret = (int)write(STDOUT_FILENO, stdout_buf + stdout_buf_offset, (size_t)(stdout_buf_len - stdout_buf_offset));
110     if (ret < 0)
111     {
112     if (errno == EAGAIN || errno == EWOULDBLOCK)
113     {
114     break;
115     }
116     else if (errno == EINTR)
117     {
118     continue;
119     }
120     else
121     {
122     log_error("write(STDOUT) error (%d)\n", errno);
123     loop = 0;
124     break;
125     }
126     }
127     else if (ret == 0) // broken pipe
128     {
129     loop = 0;
130     break;
131     }
132     else
133     {
134     stdout_buf_offset += ret;
135     if (stdout_buf_offset >= stdout_buf_len) // Flush buffer complete
136     {
137     ret = 0;
138     stdout_buf_len = 0;
139     loop = 0;
140     break;
141     }
142     continue;
143     }
144 sysadm 1.28 }
145     }
146     }
147     }
148 sysadm 1.6
149 sysadm 1.28 // Restore STDOUT flags
150     fcntl(STDOUT_FILENO, F_SETFL, flags);
151 sysadm 1.6
152 sysadm 1.28 return ret;
153 sysadm 1.1 }
154    
155 sysadm 1.17 int igetch(int clear_buf)
156 sysadm 1.1 {
157 sysadm 1.18 // static input buffer
158 sysadm 1.22 static unsigned char buf[LINE_BUFFER_LEN];
159 sysadm 1.19 static ssize_t len = 0;
160 sysadm 1.18 static int pos = 0;
161    
162 sysadm 1.29 struct epoll_event ev, events[MAX_EVENTS];
163     int nfds, epollfd;
164 sysadm 1.21
165 sysadm 1.22 unsigned char tmp[LINE_BUFFER_LEN];
166 sysadm 1.27 int out = '\0';
167 sysadm 1.18 int in_esc = 0;
168     int in_ascii = 0;
169     int in_control = 0;
170     int i = 0;
171 sysadm 1.26 int flags;
172 sysadm 1.1
173 sysadm 1.17 if (clear_buf)
174     {
175     pos = 0;
176     len = 0;
177    
178 sysadm 1.27 return '\0';
179 sysadm 1.17 }
180    
181 sysadm 1.29 epollfd = epoll_create1(0);
182     if (epollfd < 0)
183     {
184     log_error("epoll_create1() error (%d)\n", errno);
185     return -1;
186     }
187    
188     ev.events = EPOLLIN;
189     ev.data.fd = STDIN_FILENO;
190     if (epoll_ctl(epollfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev) == -1)
191 sysadm 1.14 {
192 sysadm 1.29 log_error("epoll_ctl(STDIN_FILENO) error (%d)\n", errno);
193     return -1;
194     }
195 sysadm 1.9
196 sysadm 1.29 flags = fcntl(STDIN_FILENO, F_GETFL, 0);
197     fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
198 sysadm 1.9
199 sysadm 1.29 while (!SYS_server_exit && pos >= len)
200     {
201     nfds = epoll_wait(epollfd, events, MAX_EVENTS, 100); // 0.1 second
202 sysadm 1.9
203 sysadm 1.29 if (nfds < 0)
204 sysadm 1.14 {
205 sysadm 1.21 if (errno != EINTR)
206     {
207 sysadm 1.29 log_error("epoll_wait() error (%d)\n", errno);
208     fcntl(STDIN_FILENO, F_SETFL, flags);
209 sysadm 1.21 return KEY_NULL;
210     }
211     continue;
212 sysadm 1.14 }
213 sysadm 1.29 else if (nfds == 0)
214 sysadm 1.14 {
215 sysadm 1.29 fcntl(STDIN_FILENO, F_SETFL, flags);
216 sysadm 1.21 return KEY_TIMEOUT;
217 sysadm 1.14 }
218 sysadm 1.21
219 sysadm 1.29 for (int i = 0; i < nfds; i++)
220 sysadm 1.14 {
221 sysadm 1.29 if (events[i].data.fd == STDIN_FILENO)
222 sysadm 1.26 {
223 sysadm 1.29 while (1) // read until complete or error
224 sysadm 1.26 {
225 sysadm 1.29 len = read(STDIN_FILENO, buf, sizeof(buf));
226     if (len < 0)
227     {
228     if (errno == EAGAIN || errno == EWOULDBLOCK)
229     {
230     fcntl(STDIN_FILENO, F_SETFL, flags);
231     return KEY_TIMEOUT;
232     }
233     else if (errno == EINTR)
234     {
235     continue;
236     }
237     else
238     {
239     log_error("read(STDIN) error (%d)\n", errno);
240     fcntl(STDIN_FILENO, F_SETFL, flags);
241     return KEY_NULL;
242     }
243     }
244     else if (len == 0) // broken pipe
245     {
246     fcntl(STDIN_FILENO, F_SETFL, flags);
247     return KEY_NULL;
248     }
249    
250     pos = 0;
251     break;
252 sysadm 1.26 }
253     }
254 sysadm 1.14 }
255    
256     // For debug
257     // for (j = 0; j < len; j++)
258     // log_std ("<--[%u]\n", (buf[j] + 256) % 256);
259 sysadm 1.11 }
260 sysadm 1.14
261 sysadm 1.29 fcntl(STDIN_FILENO, F_SETFL, flags);
262    
263 sysadm 1.14 while (pos < len)
264 sysadm 1.11 {
265 sysadm 1.18 unsigned char c = buf[pos++];
266 sysadm 1.5
267 sysadm 1.14 if (c == KEY_CONTROL)
268     {
269     if (in_control == 0)
270     {
271     in_control = 1;
272     i = 0;
273     continue;
274     }
275     }
276 sysadm 1.1
277 sysadm 1.14 if (in_control)
278     {
279     tmp[i++] = c;
280     if (i >= 2)
281     {
282     out = (int)tmp[0] * 256 + tmp[1];
283     in_control = 0;
284     break;
285     }
286     continue;
287     }
288 sysadm 1.6
289 sysadm 1.14 if (c == ESC_KEY)
290     {
291     if (in_esc == 0)
292     {
293     in_esc = 1;
294     in_ascii = 1;
295     i = 0;
296     continue;
297     }
298     else
299     {
300     out = ESC_KEY;
301     in_esc = 0;
302     break;
303     }
304     }
305 sysadm 1.3
306 sysadm 1.14 in_esc = 0;
307 sysadm 1.1
308 sysadm 1.14 if (in_ascii)
309     {
310     tmp[i++] = c;
311     if (c == 'm')
312     {
313     in_ascii = 0;
314     continue;
315     }
316     if (i == 2 && c >= 'A' && c <= 'D')
317     {
318     in_ascii = 0;
319     switch (c)
320     {
321     case 'A':
322     out = KEY_UP;
323     break;
324     case 'B':
325     out = KEY_DOWN;
326     break;
327     case 'C':
328     out = KEY_RIGHT;
329     break;
330     case 'D':
331     out = KEY_LEFT;
332     break;
333     }
334     break;
335     }
336     if (i == 3 && tmp[0] == 91 && tmp[2] == 126)
337     {
338     in_ascii = 0;
339     switch (tmp[1])
340     {
341     case 49:
342     out = KEY_HOME;
343     break;
344     case 51:
345     out = KEY_DEL;
346     break;
347     case 52:
348     out = KEY_END;
349     break;
350     case 53:
351     out = KEY_PGUP;
352     break;
353     case 54:
354     out = KEY_PGDN;
355     break;
356     }
357     break;
358     }
359     continue;
360     }
361 sysadm 1.1
362 sysadm 1.14 out = ((int)c + 256) % 256;
363     break;
364 sysadm 1.1 }
365    
366 sysadm 1.14 // for debug
367     // log_std ("-->[%u]\n", out);
368 sysadm 1.1
369 sysadm 1.14 return out;
370 sysadm 1.1 }
371 sysadm 1.5
372 sysadm 1.14 int igetch_t(long int sec)
373 sysadm 1.9 {
374 sysadm 1.14 int ch;
375     time_t t_begin = time(0);
376 sysadm 1.10
377 sysadm 1.14 do
378     {
379 sysadm 1.17 ch = igetch(0);
380 sysadm 1.25 } while (!SYS_server_exit && ch == KEY_TIMEOUT && (time(0) - t_begin < sec));
381 sysadm 1.9
382 sysadm 1.14 return ch;
383 sysadm 1.9 }

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