/[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.2 - (show annotations)
Fri Nov 7 14:44:47 2025 UTC (4 months, 1 week ago) by sysadm
Branch: MAIN
Changes since 1.1: +18 -5 lines
Content type: text/x-csrc
Refine

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

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