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

Annotation of /lbbs/src/bbs_net.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.66 - (hide annotations)
Sat Oct 18 01:50:48 2025 UTC (4 months, 4 weeks ago) by sysadm
Branch: MAIN
Changes since 1.65: +4 -70 lines
Content type: text/x-csrc
Move io_buf_conv() to io.c(.h)

1 sysadm 1.1 /***************************************************************************
2 sysadm 1.14 bbs_net.c - description
3     -------------------
4 sysadm 1.25 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.25 * 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 "bbs.h"
18     #include "common.h"
19 sysadm 1.55 #include "io.h"
20 sysadm 1.15 #include "log.h"
21 sysadm 1.55 #include "login.h"
22     #include "menu.h"
23 sysadm 1.15 #include "screen.h"
24 sysadm 1.55 #include <errno.h>
25     #include <fcntl.h>
26     #include <netdb.h>
27     #include <stdarg.h>
28 sysadm 1.1 #include <stdio.h>
29 sysadm 1.55 #include <stdlib.h>
30 sysadm 1.29 #include <string.h>
31     #include <time.h>
32     #include <unistd.h>
33 sysadm 1.55 #include <arpa/inet.h>
34     #include <libssh/libssh.h>
35     #include <libssh/server.h>
36     #include <libssh/callbacks.h>
37     #include <netinet/in.h>
38     #include <netinet/ip.h>
39 sysadm 1.29 #include <sys/select.h>
40 sysadm 1.1 #include <sys/ioctl.h>
41     #include <sys/socket.h>
42 sysadm 1.38 #include <sys/epoll.h>
43 sysadm 1.1
44 sysadm 1.26 #define MENU_CONF_DELIM " \t\r\n"
45    
46 sysadm 1.14 #define MAX_PROCESS_BAR_LEN 30
47     #define MAXSTATION 26 * 2
48     #define STATION_PER_LINE 4
49 sysadm 1.1
50 sysadm 1.62 #define BBS_NET_DEFAULT_CHARSET "UTF-8"
51    
52 sysadm 1.1 struct _bbsnet_conf
53     {
54 sysadm 1.14 char host1[20];
55     char host2[40];
56     char ip[40];
57 sysadm 1.24 in_port_t port;
58 sysadm 1.60 char charset[20];
59 sysadm 1.1 } bbsnet_conf[MAXSTATION];
60    
61     MENU_SET bbsnet_menu;
62    
63 sysadm 1.14 int load_bbsnet_conf(const char *file_config)
64 sysadm 1.1 {
65 sysadm 1.14 FILE *fp;
66     MENU *p_menu;
67 sysadm 1.41 MENU_ITEM *p_menu_item;
68     MENU_ITEM_ID menu_item_id;
69 sysadm 1.60 char t[256], *t1, *t2, *t3, *t4, *t5, *saveptr;
70 sysadm 1.14
71     fp = fopen(file_config, "r");
72     if (fp == NULL)
73 sysadm 1.20 {
74 sysadm 1.14 return -1;
75 sysadm 1.20 }
76 sysadm 1.14
77 sysadm 1.41 bbsnet_menu.p_menu_pool = calloc(1, sizeof(MENU));
78     if (bbsnet_menu.p_menu_pool == NULL)
79     {
80     log_error("calloc(p_menu_pool) error\n");
81     return -3;
82     }
83     bbsnet_menu.menu_count = 1;
84    
85     bbsnet_menu.p_menu_item_pool = calloc(MAXSTATION, sizeof(MENU_ITEM));
86     if (bbsnet_menu.p_menu_item_pool == NULL)
87     {
88     log_error("calloc(p_menu_item_pool) error\n");
89     return -3;
90     }
91     bbsnet_menu.menu_item_count = MAXSTATION;
92    
93     p_menu = (MENU *)get_menu_by_id(&bbsnet_menu, 0);
94 sysadm 1.40
95 sysadm 1.21 strncpy(p_menu->name, "BBSNET", sizeof(p_menu->name) - 1);
96     p_menu->name[sizeof(p_menu->name) - 1] = '\0';
97 sysadm 1.14 p_menu->title.show = 0;
98 sysadm 1.41 p_menu->screen_show = 0;
99 sysadm 1.1
100 sysadm 1.41 menu_item_id = 0;
101     while (fgets(t, 255, fp) && menu_item_id < MAXSTATION)
102 sysadm 1.14 {
103 sysadm 1.26 t1 = strtok_r(t, MENU_CONF_DELIM, &saveptr);
104     t2 = strtok_r(NULL, MENU_CONF_DELIM, &saveptr);
105     t3 = strtok_r(NULL, MENU_CONF_DELIM, &saveptr);
106     t4 = strtok_r(NULL, MENU_CONF_DELIM, &saveptr);
107 sysadm 1.60 t5 = strtok_r(NULL, MENU_CONF_DELIM, &saveptr);
108 sysadm 1.14
109 sysadm 1.60 if (t1 == NULL || t2 == NULL || t3 == NULL || t4 == NULL || t5 == NULL || t[0] == '#' || t[0] == '*')
110 sysadm 1.18 {
111 sysadm 1.14 continue;
112 sysadm 1.18 }
113    
114 sysadm 1.41 strncpy(bbsnet_conf[menu_item_id].host1, t2, sizeof(bbsnet_conf[menu_item_id].host1) - 1);
115     bbsnet_conf[menu_item_id].host1[sizeof(bbsnet_conf[menu_item_id].host1) - 1] = '\0';
116     strncpy(bbsnet_conf[menu_item_id].host2, t1, sizeof(bbsnet_conf[menu_item_id].host2) - 1);
117     bbsnet_conf[menu_item_id].host2[sizeof(bbsnet_conf[menu_item_id].host2) - 1] = '\0';
118     strncpy(bbsnet_conf[menu_item_id].ip, t3, sizeof(bbsnet_conf[menu_item_id].ip) - 1);
119     bbsnet_conf[menu_item_id].ip[sizeof(bbsnet_conf[menu_item_id].ip) - 1] = '\0';
120     bbsnet_conf[menu_item_id].port = (in_port_t)(t4 ? atoi(t4) : 23);
121 sysadm 1.60 strncpy(bbsnet_conf[menu_item_id].charset, t5, sizeof(bbsnet_conf[menu_item_id].charset) - 1);
122     bbsnet_conf[menu_item_id].charset[sizeof(bbsnet_conf[menu_item_id].charset) - 1] = '\0';
123 sysadm 1.14
124 sysadm 1.41 p_menu_item = get_menu_item_by_id(&bbsnet_menu, menu_item_id);
125     if (p_menu_item == NULL)
126     {
127     log_error("get_menu_item_by_id(%d) return NULL pointer\n", menu_item_id);
128     return -1;
129     }
130 sysadm 1.14
131 sysadm 1.41 p_menu_item->row = (int16_t)(2 + menu_item_id / STATION_PER_LINE);
132     p_menu_item->col = (int16_t)(5 + menu_item_id % STATION_PER_LINE * 20);
133     snprintf(p_menu_item->action, sizeof(p_menu_item->action), "%d", (int16_t)menu_item_id);
134     p_menu_item->submenu = 0;
135     p_menu_item->priv = 0;
136     p_menu_item->level = 0;
137     p_menu_item->name[0] =
138     (char)(menu_item_id < MAXSTATION / 2 ? 'A' + menu_item_id : 'a' + menu_item_id);
139     p_menu_item->name[1] = '\0';
140     snprintf(p_menu_item->text, sizeof(p_menu_item->text), "%c. %s",
141     p_menu_item->name[0], bbsnet_conf[menu_item_id].host1);
142    
143     p_menu->items[p_menu->item_count] = menu_item_id;
144     p_menu->item_count++;
145     menu_item_id++;
146     }
147    
148     bbsnet_menu.menu_item_count = (int16_t)menu_item_id;
149     bbsnet_menu.menu_id_path[0] = 0;
150     bbsnet_menu.menu_item_pos[0] = 0;
151     bbsnet_menu.choose_step = 0;
152 sysadm 1.14
153 sysadm 1.41 fclose(fp);
154 sysadm 1.14
155     return 0;
156 sysadm 1.1 }
157    
158 sysadm 1.40 void unload_bbsnet_conf(void)
159     {
160 sysadm 1.41 bbsnet_menu.menu_count = 0;
161     bbsnet_menu.menu_item_count = 0;
162    
163     free(bbsnet_menu.p_menu_pool);
164     bbsnet_menu.p_menu_pool = NULL;
165     free(bbsnet_menu.p_menu_item_pool);
166     bbsnet_menu.p_menu_item_pool = NULL;
167 sysadm 1.40 }
168    
169     void process_bar(int n, int len)
170 sysadm 1.1 {
171 sysadm 1.27 char buf[LINE_BUFFER_LEN];
172     char buf2[LINE_BUFFER_LEN];
173    
174     if (len > LINE_BUFFER_LEN)
175     {
176     len = LINE_BUFFER_LEN - 1;
177     }
178     if (n < 0)
179     {
180     n = 0;
181     }
182     else if (n > len)
183     {
184     n = len;
185     }
186 sysadm 1.14
187     moveto(4, 0);
188 sysadm 1.23 prints(" ------------------------------ \r\n");
189 sysadm 1.27 snprintf(buf, sizeof(buf), " %3d%% ", n * 100 / len);
190 sysadm 1.30 strncpy(buf2, buf, (size_t)n);
191 sysadm 1.27 buf2[n] = '\0';
192     prints("|\033[46m%s\033[44m%s\033[m|\r\n", buf2, buf + n);
193 sysadm 1.23 prints(" ------------------------------ \r\n");
194 sysadm 1.14 iflush();
195 sysadm 1.1 }
196    
197 sysadm 1.14 int bbsnet_connect(int n)
198 sysadm 1.1 {
199 sysadm 1.36 int sock, ret, loop, error;
200 sysadm 1.38 int sock_connected = 0;
201 sysadm 1.36 int flags_sock;
202     int flags_stdin;
203     int flags_stdout;
204     int len;
205 sysadm 1.14 struct sockaddr_in sin;
206 sysadm 1.36 char input_buf[LINE_BUFFER_LEN];
207     char output_buf[LINE_BUFFER_LEN];
208     int input_buf_len = 0;
209     int output_buf_len = 0;
210     int input_buf_offset = 0;
211     int output_buf_offset = 0;
212 sysadm 1.60 iconv_t input_cd = NULL;
213     char input_conv[LINE_BUFFER_LEN * 2];
214     char output_conv[LINE_BUFFER_LEN * 2];
215     int input_conv_len = 0;
216     int output_conv_len = 0;
217     int input_conv_offset = 0;
218     int output_conv_offset = 0;
219     iconv_t output_cd = NULL;
220 sysadm 1.38 struct epoll_event ev, events[MAX_EVENTS];
221     int nfds, epollfd;
222     int stdin_read_wait = 0;
223     int stdout_write_wait = 0;
224     int sock_read_wait = 0;
225     int sock_write_wait = 0;
226 sysadm 1.26 struct hostent *p_host = NULL;
227 sysadm 1.31 int tos;
228 sysadm 1.26 char remote_addr[IP_ADDR_LEN];
229 sysadm 1.14 int remote_port;
230 sysadm 1.63 char local_addr[IP_ADDR_LEN];
231     int local_port;
232     socklen_t sock_len;
233 sysadm 1.56 time_t t_used = time(NULL);
234 sysadm 1.14 struct tm *tm_used;
235 sysadm 1.26 int ch;
236 sysadm 1.14
237 sysadm 1.53 if (user_online_update("BBS_NET") < 0)
238     {
239     log_error("user_online_update(BBS_NET) error\n");
240     }
241    
242 sysadm 1.14 clearscr();
243    
244     moveto(0, 0);
245 sysadm 1.57 prints("\033[1;32m正在测试往 %s (%s) 的连接,请稍候... \033[m\r\n",
246 sysadm 1.14 bbsnet_conf[n].host1, bbsnet_conf[n].ip);
247     iflush();
248    
249 sysadm 1.26 p_host = gethostbyname(bbsnet_conf[n].ip);
250 sysadm 1.14
251 sysadm 1.26 if (p_host == NULL)
252 sysadm 1.1 {
253 sysadm 1.57 prints("\033[1;31m查找主机名失败!\033[m\r\n");
254 sysadm 1.14 press_any_key();
255     return -1;
256 sysadm 1.1 }
257 sysadm 1.14
258     sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
259    
260     if (sock < 0)
261 sysadm 1.1 {
262 sysadm 1.57 prints("\033[1;31m无法创建socket!\033[m\r\n");
263 sysadm 1.14 press_any_key();
264     return -1;
265 sysadm 1.1 }
266    
267 sysadm 1.14 sin.sin_family = AF_INET;
268 sysadm 1.48 sin.sin_addr.s_addr = (BBS_address[0] != '\0' ? inet_addr(BBS_address) : INADDR_ANY);
269 sysadm 1.14 sin.sin_port = 0;
270    
271     if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
272     {
273 sysadm 1.31 log_error("Bind address %s:%u failed (%d)\n",
274     inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), errno);
275 sysadm 1.14 return -2;
276     }
277 sysadm 1.1
278 sysadm 1.49 memset(&sin, 0, sizeof(sin));
279 sysadm 1.14 sin.sin_family = AF_INET;
280 sysadm 1.26 sin.sin_addr = *(struct in_addr *)p_host->h_addr_list[0];
281 sysadm 1.14 sin.sin_port = htons(bbsnet_conf[n].port);
282    
283 sysadm 1.21 strncpy(remote_addr, inet_ntoa(sin.sin_addr), sizeof(remote_addr) - 1);
284     remote_addr[sizeof(remote_addr) - 1] = '\0';
285 sysadm 1.14 remote_port = ntohs(sin.sin_port);
286    
287 sysadm 1.57 prints("\033[1;32m穿梭进度条提示您当前已使用的时间,按\033[1;33mCtrl+C\033[1;32m中断。\033[m\r\n");
288 sysadm 1.14 process_bar(0, MAX_PROCESS_BAR_LEN);
289 sysadm 1.29
290 sysadm 1.39 // Set socket as non-blocking
291     flags_sock = fcntl(sock, F_GETFL, 0);
292     fcntl(sock, F_SETFL, flags_sock | O_NONBLOCK);
293    
294     // Set STDIN/STDOUT as non-blocking
295     flags_stdin = fcntl(STDIN_FILENO, F_GETFL, 0);
296     flags_stdout = fcntl(STDOUT_FILENO, F_GETFL, 0);
297     fcntl(STDIN_FILENO, F_SETFL, flags_stdin | O_NONBLOCK);
298     fcntl(STDOUT_FILENO, F_SETFL, flags_stdout | O_NONBLOCK);
299    
300 sysadm 1.38 epollfd = epoll_create1(0);
301     if (epollfd < 0)
302     {
303     log_error("epoll_create1() error (%d)\n", errno);
304     return -1;
305     }
306    
307 sysadm 1.59 ev.events = EPOLLOUT | EPOLLET;
308 sysadm 1.38 ev.data.fd = sock;
309     if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sock, &ev) == -1)
310     {
311     log_error("epoll_ctl(socket) error (%d)\n", errno);
312 sysadm 1.39 goto cleanup;
313 sysadm 1.38 }
314    
315 sysadm 1.59 ev.events = EPOLLIN | EPOLLET;
316 sysadm 1.38 ev.data.fd = STDIN_FILENO;
317     if (epoll_ctl(epollfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev) == -1)
318     {
319     log_error("epoll_ctl(STDIN_FILENO) error (%d)\n", errno);
320 sysadm 1.39 goto cleanup;
321 sysadm 1.38 }
322    
323     while (!SYS_server_exit)
324 sysadm 1.29 {
325 sysadm 1.38 if ((ret = connect(sock, (struct sockaddr *)&sin, sizeof(sin))) < 0)
326 sysadm 1.29 {
327 sysadm 1.38 if (errno == EAGAIN || errno == EALREADY || errno == EINPROGRESS)
328     {
329     // Use select / epoll to check writability of the socket,
330     // then use getsockopt to check the status of the socket.
331     // See man connect(2)
332     break;
333     }
334     else if (errno == EINTR)
335     {
336     continue;
337     }
338     else
339     {
340     log_error("connect(socket) error (%d)\n", errno);
341 sysadm 1.39
342 sysadm 1.57 prints("\033[1;31m连接失败!\033[m\r\n");
343 sysadm 1.38 press_any_key();
344 sysadm 1.39
345     goto cleanup;
346 sysadm 1.38 }
347 sysadm 1.29 }
348     }
349    
350 sysadm 1.38 for (int j = 0; j < MAX_PROCESS_BAR_LEN && !sock_connected && !SYS_server_exit; j++)
351 sysadm 1.1 {
352 sysadm 1.38 nfds = epoll_wait(epollfd, events, MAX_EVENTS, 500); // 0.5 second
353 sysadm 1.29
354 sysadm 1.38 if (nfds < 0)
355 sysadm 1.20 {
356 sysadm 1.29 if (errno != EINTR)
357     {
358 sysadm 1.38 log_error("epoll_wait() error (%d)\n", errno);
359 sysadm 1.39 break;
360 sysadm 1.29 }
361 sysadm 1.20 }
362 sysadm 1.38 else if (nfds == 0) // timeout
363     {
364     process_bar(j + 1, MAX_PROCESS_BAR_LEN);
365     }
366     else // ret > 0
367 sysadm 1.14 {
368 sysadm 1.38 for (int i = 0; i < nfds; i++)
369 sysadm 1.29 {
370 sysadm 1.38 if (events[i].data.fd == sock)
371     {
372     len = sizeof(error);
373     if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len) < 0)
374     {
375     log_error("getsockopt() error (%d) !\n", error);
376 sysadm 1.39 goto cleanup;
377 sysadm 1.38 }
378     if (error == 0)
379     {
380     sock_connected = 1;
381     }
382     }
383     else if (events[i].data.fd == STDIN_FILENO)
384     {
385     ch = igetch(0);
386 sysadm 1.45 if (ch == Ctrl('C') || ch == KEY_ESC)
387 sysadm 1.38 {
388 sysadm 1.39 goto cleanup;
389 sysadm 1.38 }
390     }
391 sysadm 1.29 }
392 sysadm 1.14 }
393 sysadm 1.12 }
394 sysadm 1.38 if (SYS_server_exit)
395     {
396 sysadm 1.39 goto cleanup;
397 sysadm 1.38 }
398     if (!sock_connected)
399 sysadm 1.12 {
400 sysadm 1.57 prints("\033[1;31m连接失败!\033[m\r\n");
401 sysadm 1.14 press_any_key();
402 sysadm 1.39
403     goto cleanup;
404 sysadm 1.12 }
405 sysadm 1.29
406 sysadm 1.31 tos = IPTOS_LOWDELAY;
407     if (setsockopt(sock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
408     {
409     log_error("setsockopt IP_TOS=%d error (%d)\n", tos, errno);
410     }
411 sysadm 1.14
412 sysadm 1.63 sock_len = sizeof(sin);
413     if (getsockname(sock, (struct sockaddr *)&sin, &sock_len) < 0)
414     {
415     log_error("getsockname() error: %d", errno);
416     goto cleanup;
417     }
418    
419     strncpy(local_addr, inet_ntoa(sin.sin_addr), sizeof(local_addr) - 1);
420     local_addr[sizeof(local_addr) - 1] = '\0';
421     local_port = ntohs(sin.sin_port);
422    
423 sysadm 1.57 prints("\033[1;31m连接成功!\033[m\r\n");
424 sysadm 1.33 iflush();
425 sysadm 1.63 log_common("BBSNET connect to %s:%d from %s:%d by [%s]\n",
426     remote_addr, remote_port, local_addr, local_port, BBS_username);
427 sysadm 1.14
428 sysadm 1.62 input_cd = iconv_open(bbsnet_conf[n].charset, BBS_NET_DEFAULT_CHARSET);
429 sysadm 1.60 if (input_cd == (iconv_t)(-1))
430     {
431 sysadm 1.62 log_error("iconv_open(%s->%s) error: %d\n", BBS_NET_DEFAULT_CHARSET, bbsnet_conf[n].charset, errno);
432 sysadm 1.60 goto cleanup;
433     }
434 sysadm 1.62 output_cd = iconv_open(BBS_NET_DEFAULT_CHARSET, bbsnet_conf[n].charset);
435 sysadm 1.60 if (input_cd == (iconv_t)(-1))
436     {
437 sysadm 1.62 log_error("iconv_open(%s->%s) error: %d\n", bbsnet_conf[n].charset, BBS_NET_DEFAULT_CHARSET, errno);
438 sysadm 1.60 iconv_close(input_cd);
439     goto cleanup;
440     }
441    
442 sysadm 1.38 ev.events = EPOLLIN | EPOLLOUT | EPOLLET;
443     ev.data.fd = sock;
444     if (epoll_ctl(epollfd, EPOLL_CTL_MOD, sock, &ev) == -1)
445     {
446     log_error("epoll_ctl(socket) error (%d)\n", errno);
447 sysadm 1.39 goto cleanup;
448 sysadm 1.38 }
449    
450 sysadm 1.59 ev.events = EPOLLOUT | EPOLLET;
451 sysadm 1.38 ev.data.fd = STDOUT_FILENO;
452     if (epoll_ctl(epollfd, EPOLL_CTL_ADD, STDOUT_FILENO, &ev) == -1)
453     {
454     log_error("epoll_ctl(STDOUT_FILENO) error (%d)\n", errno);
455 sysadm 1.39 goto cleanup;
456 sysadm 1.38 }
457    
458 sysadm 1.50 BBS_last_access_tm = t_used = time(NULL);
459 sysadm 1.14 loop = 1;
460    
461 sysadm 1.26 while (loop && !SYS_server_exit)
462 sysadm 1.12 {
463 sysadm 1.47 if (SSH_v2 && ssh_channel_is_closed(SSH_channel))
464     {
465     log_error("SSH channel is closed\n");
466     loop = 0;
467     break;
468     }
469    
470 sysadm 1.38 nfds = epoll_wait(epollfd, events, MAX_EVENTS, 100); // 0.1 second
471 sysadm 1.33
472 sysadm 1.38 if (nfds < 0)
473 sysadm 1.14 {
474 sysadm 1.38 if (errno != EINTR)
475 sysadm 1.14 {
476 sysadm 1.38 log_error("epoll_wait() error (%d)\n", errno);
477     break;
478 sysadm 1.14 }
479 sysadm 1.38 continue;
480 sysadm 1.14 }
481 sysadm 1.38 else if (nfds == 0) // timeout
482 sysadm 1.1 {
483 sysadm 1.50 if (time(NULL) - BBS_last_access_tm >= MAX_DELAY_TIME)
484 sysadm 1.28 {
485 sysadm 1.38 break;
486 sysadm 1.28 }
487 sysadm 1.1 }
488 sysadm 1.38
489     for (int i = 0; i < nfds; i++)
490 sysadm 1.1 {
491 sysadm 1.59 if (events[i].data.fd == STDIN_FILENO)
492 sysadm 1.14 {
493 sysadm 1.38 stdin_read_wait = 1;
494 sysadm 1.59 }
495    
496     if (events[i].data.fd == sock)
497     {
498     if (events[i].events & EPOLLIN)
499     {
500     sock_read_wait = 1;
501     }
502     if (events[i].events & EPOLLOUT)
503     {
504     sock_write_wait = 1;
505     }
506     }
507    
508     if (events[i].data.fd == STDOUT_FILENO)
509     {
510     stdout_write_wait = 1;
511     }
512     }
513    
514     if (stdin_read_wait)
515     {
516     while (input_buf_len < sizeof(input_buf) && !SYS_server_exit)
517     {
518     if (SSH_v2)
519 sysadm 1.33 {
520 sysadm 1.59 ret = ssh_channel_read_nonblocking(SSH_channel, input_buf + input_buf_len, sizeof(input_buf) - (uint32_t)input_buf_len, 0);
521     if (ret == SSH_ERROR)
522 sysadm 1.47 {
523 sysadm 1.59 log_error("ssh_channel_read_nonblocking() error: %s\n", ssh_get_error(SSH_session));
524     loop = 0;
525     break;
526 sysadm 1.47 }
527 sysadm 1.59 else if (ret == SSH_EOF)
528 sysadm 1.47 {
529 sysadm 1.59 stdin_read_wait = 0;
530     loop = 0;
531     break;
532 sysadm 1.47 }
533 sysadm 1.59 else if (ret == 0)
534 sysadm 1.33 {
535 sysadm 1.59 stdin_read_wait = 0;
536     break; // Check whether channel is still open
537 sysadm 1.38 }
538 sysadm 1.59 }
539     else
540     {
541     ret = (int)read(STDIN_FILENO, input_buf + input_buf_len, sizeof(input_buf) - (size_t)input_buf_len);
542     }
543     if (ret < 0)
544     {
545     if (errno == EAGAIN || errno == EWOULDBLOCK)
546 sysadm 1.38 {
547     stdin_read_wait = 0;
548     break;
549     }
550 sysadm 1.59 else if (errno == EINTR)
551     {
552     continue;
553     }
554 sysadm 1.38 else
555     {
556 sysadm 1.59 log_error("read(STDIN) error (%d)\n", errno);
557     loop = 0;
558     break;
559     }
560     }
561     else if (ret == 0) // broken pipe
562     {
563     #ifdef _DEBUG
564     log_error("read(STDIN) EOF\n");
565     #endif
566     stdin_read_wait = 0;
567     loop = 0;
568     break;
569     }
570     else
571     {
572     input_buf_len += ret;
573     BBS_last_access_tm = time(NULL);
574 sysadm 1.58
575 sysadm 1.59 // Refresh current action while user input
576     if (user_online_update("BBS_NET") < 0)
577     {
578     log_error("user_online_update(BBS_NET) error\n");
579     }
580 sysadm 1.58
581 sysadm 1.59 continue;
582 sysadm 1.33 }
583 sysadm 1.36 }
584 sysadm 1.59 }
585 sysadm 1.29
586 sysadm 1.59 if (sock_write_wait)
587     {
588 sysadm 1.60 if (input_buf_offset < input_buf_len)
589 sysadm 1.36 {
590 sysadm 1.66 ret = io_buf_conv(input_cd, input_buf, &input_buf_len, &input_buf_offset, input_conv, sizeof(input_conv), &input_conv_len);
591 sysadm 1.60 if (ret < 0)
592     {
593 sysadm 1.66 log_error("io_buf_conv(input, %d, %d, %d) error\n", input_buf_len, input_buf_offset, input_conv_len);
594 sysadm 1.60 }
595     }
596    
597     while (input_conv_offset < input_conv_len && !SYS_server_exit)
598     {
599     ret = (int)write(sock, input_conv + input_conv_offset, (size_t)(input_conv_len - input_conv_offset));
600 sysadm 1.59 if (ret < 0)
601 sysadm 1.36 {
602 sysadm 1.59 if (errno == EAGAIN || errno == EWOULDBLOCK)
603 sysadm 1.36 {
604 sysadm 1.59 sock_write_wait = 0;
605     break;
606 sysadm 1.38 }
607 sysadm 1.59 else if (errno == EINTR)
608 sysadm 1.38 {
609 sysadm 1.59 continue;
610     }
611     else
612     {
613     log_error("write(socket) error (%d)\n", errno);
614 sysadm 1.36 loop = 0;
615 sysadm 1.38 break;
616     }
617 sysadm 1.59 }
618     else if (ret == 0) // broken pipe
619     {
620     #ifdef _DEBUG
621     log_error("write(socket) EOF\n");
622     #endif
623     sock_write_wait = 0;
624     loop = 0;
625     break;
626     }
627     else
628     {
629 sysadm 1.60 input_conv_offset += ret;
630     if (input_conv_offset >= input_conv_len) // Output buffer complete
631 sysadm 1.38 {
632 sysadm 1.60 input_conv_offset = 0;
633     input_conv_len = 0;
634 sysadm 1.59 break;
635 sysadm 1.36 }
636 sysadm 1.59 continue;
637 sysadm 1.36 }
638 sysadm 1.14 }
639 sysadm 1.59 }
640 sysadm 1.36
641 sysadm 1.59 if (sock_read_wait)
642     {
643     while (output_buf_len < sizeof(output_buf) && !SYS_server_exit)
644 sysadm 1.14 {
645 sysadm 1.59 ret = (int)read(sock, output_buf + output_buf_len, sizeof(output_buf) - (size_t)output_buf_len);
646     if (ret < 0)
647 sysadm 1.14 {
648 sysadm 1.59 if (errno == EAGAIN || errno == EWOULDBLOCK)
649 sysadm 1.38 {
650 sysadm 1.59 sock_read_wait = 0;
651     break;
652 sysadm 1.38 }
653 sysadm 1.59 else if (errno == EINTR)
654 sysadm 1.33 {
655 sysadm 1.59 continue;
656 sysadm 1.38 }
657     else
658     {
659 sysadm 1.59 log_error("read(socket) error (%d)\n", errno);
660     loop = 0;
661     break;
662 sysadm 1.33 }
663     }
664 sysadm 1.59 else if (ret == 0) // broken pipe
665     {
666     #ifdef _DEBUG
667     log_error("read(socket) EOF\n");
668     #endif
669     sock_read_wait = 0;
670     loop = 0;
671     break;
672     }
673     else
674     {
675     output_buf_len += ret;
676     continue;
677     }
678 sysadm 1.36 }
679 sysadm 1.59 }
680 sysadm 1.36
681 sysadm 1.59 if (stdout_write_wait)
682     {
683 sysadm 1.60 if (output_buf_offset < output_buf_len)
684     {
685 sysadm 1.66 ret = io_buf_conv(output_cd, output_buf, &output_buf_len, &output_buf_offset, output_conv, sizeof(output_conv), &output_conv_len);
686 sysadm 1.60 if (ret < 0)
687     {
688 sysadm 1.66 log_error("io_buf_conv(output, %d, %d, %d) error\n", output_buf_len, output_buf_offset, output_conv_len);
689 sysadm 1.60 }
690     }
691    
692     while (output_conv_offset < output_conv_len && !SYS_server_exit)
693 sysadm 1.36 {
694 sysadm 1.59 if (SSH_v2)
695 sysadm 1.36 {
696 sysadm 1.60 ret = ssh_channel_write(SSH_channel, output_conv + output_conv_offset, (uint32_t)(output_conv_len - output_conv_offset));
697 sysadm 1.59 if (ret == SSH_ERROR)
698 sysadm 1.47 {
699 sysadm 1.59 log_error("ssh_channel_write() error: %s\n", ssh_get_error(SSH_session));
700     loop = 0;
701     break;
702 sysadm 1.47 }
703 sysadm 1.59 }
704     else
705     {
706 sysadm 1.60 ret = (int)write(STDOUT_FILENO, output_conv + output_conv_offset, (size_t)(output_conv_len - output_conv_offset));
707 sysadm 1.59 }
708     if (ret < 0)
709     {
710     if (errno == EAGAIN || errno == EWOULDBLOCK)
711 sysadm 1.47 {
712 sysadm 1.59 stdout_write_wait = 0;
713     break;
714 sysadm 1.47 }
715 sysadm 1.59 else if (errno == EINTR)
716 sysadm 1.38 {
717 sysadm 1.59 continue;
718 sysadm 1.38 }
719 sysadm 1.59 else
720 sysadm 1.33 {
721 sysadm 1.59 log_error("write(STDOUT) error (%d)\n", errno);
722 sysadm 1.36 loop = 0;
723 sysadm 1.38 break;
724     }
725 sysadm 1.59 }
726     else if (ret == 0) // broken pipe
727     {
728     #ifdef _DEBUG
729     log_error("write(STDOUT) EOF\n");
730     #endif
731     stdout_write_wait = 0;
732     loop = 0;
733     break;
734     }
735     else
736     {
737 sysadm 1.60 output_conv_offset += ret;
738     if (output_conv_offset >= output_conv_len) // Output buffer complete
739 sysadm 1.38 {
740 sysadm 1.60 output_conv_offset = 0;
741     output_conv_len = 0;
742 sysadm 1.59 break;
743 sysadm 1.36 }
744 sysadm 1.59 continue;
745 sysadm 1.36 }
746 sysadm 1.14 }
747 sysadm 1.1 }
748     }
749    
750 sysadm 1.60 iconv_close(input_cd);
751     iconv_close(output_cd);
752    
753 sysadm 1.39 cleanup:
754     if (close(epollfd) < 0)
755     {
756     log_error("close(epoll) error (%d)\n");
757     }
758    
759 sysadm 1.36 // Restore STDIN/STDOUT flags
760     fcntl(STDIN_FILENO, F_SETFL, flags_stdin);
761     fcntl(STDOUT_FILENO, F_SETFL, flags_stdout);
762    
763     // Restore socket flags
764     fcntl(sock, F_SETFL, flags_sock);
765    
766 sysadm 1.14 if (close(sock) == -1)
767     {
768     log_error("Close socket failed\n");
769     }
770 sysadm 1.1
771 sysadm 1.50 t_used = time(NULL) - t_used;
772 sysadm 1.14 tm_used = gmtime(&t_used);
773 sysadm 1.8
774 sysadm 1.46 log_common("BBSNET disconnect, %d days %d hours %d minutes %d seconds used\n",
775 sysadm 1.47 tm_used->tm_mday - 1, tm_used->tm_hour, tm_used->tm_min,
776     tm_used->tm_sec);
777 sysadm 1.8
778 sysadm 1.14 return 0;
779 sysadm 1.1 }
780    
781     static int
782 sysadm 1.14 bbsnet_refresh()
783 sysadm 1.1 {
784 sysadm 1.14 clearscr();
785     moveto(1, 0);
786 sysadm 1.23 prints(" ----------------------------------------------------------------------------- ");
787 sysadm 1.20 for (int i = 2; i < 19; i++)
788 sysadm 1.14 {
789     moveto(i, 0);
790 sysadm 1.23 prints("|");
791 sysadm 1.14 moveto(i, 79);
792 sysadm 1.23 prints("|");
793 sysadm 1.14 }
794     moveto(19, 0);
795 sysadm 1.23 prints("|-----------------------------------------------------------------------------|");
796 sysadm 1.14 moveto(22, 0);
797 sysadm 1.23 prints(" ----------------------------------------------------------------------------- ");
798 sysadm 1.14 moveto(23, 0);
799 sysadm 1.57 prints(" [\x1b[1;32mCtrl+C\x1b[m]退出");
800 sysadm 1.13
801 sysadm 1.14 iflush();
802 sysadm 1.1
803 sysadm 1.14 return 0;
804 sysadm 1.1 }
805    
806 sysadm 1.43 int bbsnet_selchange()
807 sysadm 1.1 {
808 sysadm 1.43 int i = bbsnet_menu.menu_item_pos[0];
809    
810 sysadm 1.14 moveto(20, 0);
811     clrtoeol();
812 sysadm 1.57 prints("|\x1b[1m单位:\x1b[1;33m%-18s\x1b[m 站名:\x1b[1;33m%s\x1b[m",
813 sysadm 1.43 bbsnet_conf[i].host2, bbsnet_conf[i].host1);
814 sysadm 1.14 moveto(20, 79);
815 sysadm 1.23 prints("|");
816 sysadm 1.14 moveto(21, 0);
817     clrtoeol();
818 sysadm 1.57 prints("|\x1b[1m连往:\x1b[1;33m%-20s", bbsnet_conf[i].ip);
819 sysadm 1.43 if (bbsnet_conf[i].port != 23)
820 sysadm 1.20 {
821 sysadm 1.43 prints(" %d", bbsnet_conf[i].port);
822 sysadm 1.20 }
823 sysadm 1.14 prints("\x1b[m");
824     moveto(21, 79);
825 sysadm 1.23 prints("|");
826 sysadm 1.14 iflush();
827 sysadm 1.1
828 sysadm 1.14 return 0;
829 sysadm 1.1 }
830    
831 sysadm 1.14 int bbs_net()
832 sysadm 1.1 {
833 sysadm 1.43 int ch, i;
834 sysadm 1.1
835 sysadm 1.17 load_bbsnet_conf(CONF_BBSNET);
836 sysadm 1.1
837 sysadm 1.14 clearscr();
838     bbsnet_refresh();
839 sysadm 1.41 display_menu(&bbsnet_menu);
840 sysadm 1.43 bbsnet_selchange();
841 sysadm 1.14
842 sysadm 1.26 while (!SYS_server_exit)
843 sysadm 1.1 {
844 sysadm 1.39 ch = igetch(100);
845 sysadm 1.52
846 sysadm 1.64 if (ch != KEY_NULL && ch != KEY_TIMEOUT)
847     {
848     BBS_last_access_tm = time(NULL);
849     }
850    
851 sysadm 1.14 switch (ch)
852     {
853 sysadm 1.47 case KEY_NULL: // broken pipe
854 sysadm 1.64 log_error("KEY_NULL\n");
855 sysadm 1.40 goto cleanup;
856 sysadm 1.14 case KEY_TIMEOUT:
857 sysadm 1.50 if (time(NULL) - BBS_last_access_tm >= MAX_DELAY_TIME)
858 sysadm 1.14 {
859 sysadm 1.64 log_error("User input timeout\n");
860 sysadm 1.40 goto cleanup;
861 sysadm 1.14 }
862 sysadm 1.29 continue;
863 sysadm 1.64 case KEY_ESC:
864     case Ctrl('C'): // user cancel
865     goto cleanup;
866 sysadm 1.14 case CR:
867 sysadm 1.43 bbsnet_connect(bbsnet_menu.menu_item_pos[0]);
868 sysadm 1.14 bbsnet_refresh();
869 sysadm 1.41 display_menu(&bbsnet_menu);
870 sysadm 1.43 bbsnet_selchange();
871 sysadm 1.14 break;
872     case KEY_UP:
873     for (i = 0; i < STATION_PER_LINE; i++)
874 sysadm 1.20 {
875 sysadm 1.14 menu_control(&bbsnet_menu, KEY_UP);
876 sysadm 1.20 }
877 sysadm 1.43 bbsnet_selchange();
878 sysadm 1.14 break;
879     case KEY_DOWN:
880     for (i = 0; i < STATION_PER_LINE; i++)
881 sysadm 1.20 {
882 sysadm 1.14 menu_control(&bbsnet_menu, KEY_DOWN);
883 sysadm 1.20 }
884 sysadm 1.43 bbsnet_selchange();
885 sysadm 1.14 break;
886     case KEY_LEFT:
887     menu_control(&bbsnet_menu, KEY_UP);
888 sysadm 1.43 bbsnet_selchange();
889 sysadm 1.14 break;
890     case KEY_RIGHT:
891     menu_control(&bbsnet_menu, KEY_DOWN);
892 sysadm 1.43 bbsnet_selchange();
893     break;
894 sysadm 1.44 case KEY_HOME:
895 sysadm 1.43 case KEY_PGUP:
896     menu_control(&bbsnet_menu, KEY_PGUP);
897     bbsnet_selchange();
898 sysadm 1.14 break;
899 sysadm 1.44 case KEY_END:
900     case KEY_PGDN:
901     menu_control(&bbsnet_menu, KEY_PGDN);
902     bbsnet_selchange();
903     break;
904 sysadm 1.14 default:
905     menu_control(&bbsnet_menu, ch);
906 sysadm 1.43 bbsnet_selchange();
907 sysadm 1.14 break;
908     }
909 sysadm 1.1 }
910    
911 sysadm 1.40 cleanup:
912     unload_bbsnet_conf();
913    
914 sysadm 1.14 return 0;
915 sysadm 1.1 }

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