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

Annotation of /lbbs/src/io.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.28 - (hide annotations)
Sun May 11 14:52:26 2025 UTC (10 months ago) by sysadm
Branch: MAIN
Changes since 1.27: +85 -19 lines
Content type: text/x-csrc
Refact format output with non-blocking socket write

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

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