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

Annotation of /lbbs/src/data_file_mgr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (hide annotations)
Tue Nov 11 00:28:05 2025 UTC (4 months ago) by sysadm
Branch: MAIN
Changes since 1.3: +4 -0 lines
Content type: text/x-csrc
Use config.h

1 sysadm 1.1 /* SPDX-License-Identifier: GPL-3.0-or-later */
2     /*
3     * data_file_mgr
4     * - Edit / Preview data files
5     *
6     * Copyright (C) 2004-2025 Leaflet <leaflet@leafok.com>
7     */
8    
9 sysadm 1.4 #ifdef HAVE_CONFIG_H
10     #include "config.h"
11     #endif
12    
13 sysadm 1.1 #include "bbs.h"
14     #include "bbs_cmd.h"
15     #include "common.h"
16     #include "data_file_mgr.h"
17     #include "editor.h"
18     #include "log.h"
19     #include "screen.h"
20     #include "str_process.h"
21     #include <ctype.h>
22     #include <errno.h>
23     #include <fcntl.h>
24     #include <stdio.h>
25     #include <stdlib.h>
26     #include <unistd.h>
27     #include <sys/mman.h>
28     #include <sys/stat.h>
29    
30     enum _data_file_mgr_constant_t
31     {
32     DATA_FILE_MAX_LEN = 1024 * 1024 * 4, // 4MB
33     };
34    
35     struct data_file_item_t
36     {
37     const char *const name;
38     const char *const path;
39     };
40     typedef struct data_file_item_t DATA_FILE_ITEM;
41    
42     static const DATA_FILE_ITEM data_file_list[] = {
43     {"进站欢迎", DATA_WELCOME},
44     {"离站告别", DATA_GOODBYE},
45     {"登陆错误", DATA_LOGIN_ERROR},
46     {"活动看板", DATA_ACTIVE_BOARD},
47     {"浏览帮助", DATA_READ_HELP},
48     {"编辑帮助", DATA_EDITOR_HELP},
49 sysadm 1.3 {"敏感词表", CONF_BWF},
50     {"穿梭配置", CONF_BBSNET},
51 sysadm 1.1 };
52    
53     static const int data_file_cnt = sizeof(data_file_list) / sizeof(DATA_FILE_ITEM);
54    
55     int data_file_mgr(void *param)
56     {
57     char path[FILE_PATH_LEN];
58     int fd = -1;
59     struct stat sb;
60     void *p_data = NULL;
61     size_t len_data = 0;
62     EDITOR_DATA *p_editor_data = NULL;
63     long len_data_new = 0;
64     char *p_data_new = NULL;
65     long line_total;
66     long line_offsets[MAX_SPLIT_FILE_LINES];
67     char buf[3] = "";
68     int ch = 0;
69     int previewed = 0;
70     int i;
71    
72     clearscr();
73     moveto(1, 1);
74     prints("数据文件列表: ");
75    
76     for (i = 0; i < data_file_cnt; i++)
77     {
78     moveto(3 + i, 4);
79     prints("%2d. %s", i + 1, data_file_list[i].name);
80     }
81    
82     get_data(SCREEN_ROWS, 1, "请输入需要编辑的文件编号: ", buf, sizeof(buf), 2);
83     i = atoi(buf) - 1;
84     if (i < 0 || i >= data_file_cnt)
85     {
86     return REDRAW;
87     }
88    
89     snprintf(path, sizeof(path), "%s.user", data_file_list[i].path);
90     if ((fd = open(path, O_RDONLY)) < 0 &&
91     (fd = open(data_file_list[i].path, O_RDONLY)) < 0)
92     {
93     log_error("open(%s) error (%d)\n", data_file_list[i].path, errno);
94     return REDRAW;
95     }
96    
97     if (fstat(fd, &sb) < 0)
98     {
99     log_error("fstat(fd) error (%d)\n", errno);
100     goto cleanup;
101     }
102    
103     len_data = (size_t)sb.st_size;
104     p_data = mmap(NULL, len_data, PROT_READ, MAP_SHARED, fd, 0L);
105     if (p_data == MAP_FAILED)
106     {
107     log_error("mmap() error (%d)\n", errno);
108     goto cleanup;
109     }
110    
111     if (close(fd) < 0)
112     {
113     log_error("close(fd) error (%d)\n", errno);
114     fd = -1;
115     goto cleanup;
116     }
117     fd = -1;
118    
119     p_editor_data = editor_data_load(p_data);
120     if (p_editor_data == NULL)
121     {
122     log_error("editor_data_load(data) error\n");
123     goto cleanup;
124     }
125    
126     if (munmap(p_data, len_data) < 0)
127     {
128     log_error("munmap() error (%d)\n", errno);
129     p_data = NULL;
130     goto cleanup;
131     }
132     p_data = NULL;
133    
134     p_data_new = malloc(DATA_FILE_MAX_LEN);
135     if (p_data_new == NULL)
136     {
137     log_error("malloc(content) error: OOM\n");
138     goto cleanup;
139     }
140    
141     for (ch = 'E'; !SYS_server_exit;)
142     {
143     if (ch == 'E')
144     {
145     editor_display(p_editor_data);
146     previewed = 0;
147     }
148    
149     clearscr();
150     moveto(1, 1);
151     if (previewed)
152     {
153     prints("(S)保存, (P)预览, (C)取消 or (E)再编辑? [P]: ");
154     }
155     else
156     {
157     prints("(P)预览, (C)取消 or (E)再编辑? [P]: ");
158     }
159     iflush();
160    
161     ch = igetch_t(BBS_max_user_idle_time);
162     switch (toupper(ch))
163     {
164     case KEY_NULL:
165     case KEY_TIMEOUT:
166     goto cleanup;
167     case CR:
168     case 'P':
169     len_data_new = editor_data_save(p_editor_data, p_data_new, DATA_FILE_MAX_LEN);
170     if (len_data_new < 0)
171     {
172     log_error("editor_data_save() error\n");
173     goto cleanup;
174     }
175     line_total = split_data_lines(p_data_new, SCREEN_COLS, line_offsets, MAX_SPLIT_FILE_LINES, 1, NULL);
176     display_data(p_data_new, line_total, line_offsets, 1, display_file_key_handler, DATA_READ_HELP);
177     previewed = 1;
178     continue;
179     case 'S':
180     if (!previewed)
181     {
182     continue;
183     }
184     break;
185     case 'C':
186     clearscr();
187     moveto(1, 1);
188     prints("取消更改...");
189     press_any_key();
190     goto cleanup;
191     case 'E':
192     ch = 'E';
193     continue;
194     default: // Invalid selection
195     continue;
196     }
197    
198     break;
199     }
200    
201 sysadm 1.2 if (SYS_server_exit) // Do not save data on shutdown
202     {
203     goto cleanup;
204     }
205    
206 sysadm 1.1 if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640)) < 0)
207     {
208     log_error("open(%s) error (%d)\n", path, errno);
209     goto cleanup;
210     }
211    
212     if (write(fd, p_data_new, (size_t)len_data_new) < 0)
213     {
214     log_error("write(len=%ld) error (%d)\n", len_data_new, errno);
215     goto cleanup;
216     }
217    
218     if (close(fd) < 0)
219     {
220     log_error("close(fd) error (%d)\n", errno);
221     fd = -1;
222     goto cleanup;
223     }
224    
225 sysadm 1.2 // Make another copy of the data file so that the user editored copy will be kept after upgrade / reinstall
226     if ((fd = open(data_file_list[i].path, O_WRONLY | O_CREAT | O_TRUNC, 0640)) < 0)
227     {
228     log_error("open(%s) error (%d)\n", data_file_list[i].path, errno);
229     goto cleanup;
230     }
231    
232     if (write(fd, p_data_new, (size_t)len_data_new) < 0)
233 sysadm 1.1 {
234 sysadm 1.2 log_error("write(len=%ld) error (%d)\n", len_data_new, errno);
235 sysadm 1.1 goto cleanup;
236     }
237    
238 sysadm 1.2 if (close(fd) < 0)
239 sysadm 1.1 {
240 sysadm 1.2 log_error("close(fd) error (%d)\n", errno);
241     fd = -1;
242 sysadm 1.1 goto cleanup;
243     }
244 sysadm 1.2 fd = -1;
245 sysadm 1.1
246     clearscr();
247     moveto(1, 1);
248     prints("修改已完成,需要重新加载配置后才会生效...");
249     press_any_key();
250    
251     cleanup:
252     if (p_editor_data != NULL)
253     {
254     editor_data_cleanup(p_editor_data);
255     }
256    
257     if (p_data_new != NULL)
258     {
259     free(p_data_new);
260     }
261    
262     if (p_data != NULL && munmap(p_data, len_data) < 0)
263     {
264     log_error("munmap() error (%d)\n", errno);
265     }
266    
267     if (fd >= 0 && close(fd) < 0)
268     {
269     log_error("close(fd) error (%d)\n", errno);
270     }
271    
272     return REDRAW;
273     }

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