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

Contents of /lbbs/src/data_file_mgr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (show annotations)
Sat Jan 3 10:27:14 2026 UTC (2 months, 1 week ago) by sysadm
Branch: MAIN
CVS Tags: HEAD
Changes since 1.5: +1 -1 lines
Content type: text/x-csrc
Update copyright info

1 /* SPDX-License-Identifier: GPL-3.0-or-later */
2 /*
3 * data_file_mgr
4 * - Edit / Preview data files
5 *
6 * Copyright (C) 2004-2026 Leaflet <leaflet@leafok.com>
7 */
8
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
12
13 #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 {"敏感词表", CONF_BWF},
50 {"穿梭配置", CONF_BBSNET},
51 };
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)", 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)", 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)", errno);
108 goto cleanup;
109 }
110
111 if (close(fd) < 0)
112 {
113 log_error("close(fd) error (%d)", 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");
123 goto cleanup;
124 }
125
126 if (munmap(p_data, len_data) < 0)
127 {
128 log_error("munmap() error (%d)", 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");
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");
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 if (SYS_server_exit) // Do not save data on shutdown
202 {
203 goto cleanup;
204 }
205
206 if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640)) < 0)
207 {
208 log_error("open(%s) error (%d)", 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)", len_data_new, errno);
215 goto cleanup;
216 }
217
218 if (close(fd) < 0)
219 {
220 log_error("close(fd) error (%d)", errno);
221 fd = -1;
222 goto cleanup;
223 }
224
225 // 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)", 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 {
234 log_error("write(len=%ld) error (%d)", len_data_new, errno);
235 goto cleanup;
236 }
237
238 if (close(fd) < 0)
239 {
240 log_error("close(fd) error (%d)", errno);
241 fd = -1;
242 goto cleanup;
243 }
244 fd = -1;
245
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)", errno);
265 }
266
267 if (fd >= 0 && close(fd) < 0)
268 {
269 log_error("close(fd) error (%d)", errno);
270 }
271
272 return REDRAW;
273 }

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