1 /*
2 * wconfig.c -- write variable configuration
3 *
4 * Copyright (C) 1997,1999 by Yoshifumi Mori
5 *
6 * tab:4
7 */
8
9 #include "cdefs.h"
10 #include "extern.h"
11
12 #define MAX1LINEBUF 1024
13
14 static FILE *ifp = NULL; /* input file */
15 static char ifname[_T_MAXPATHNAME];
16 static char ifpbuf[_T_FPBUFSIZE];
17 static char inbuf[MAX1LINEBUF];
18 static char combuf[MAX1LINEBUF];
19 static char rembuf[MAX1LINEBUF];
20
21 static FILE *ofp = NULL; /* output file */
22 static char ofname[_T_MAXPATHNAME];
23 static char ofpbuf[_T_FPBUFSIZE];
24 static int errflag = FALSE;
25
26 /*
27 * �������������ץ�������ʸ������������
28 *
29 * ���Ѹ�� free ���뤳��
30 */
31 static
makeEscString(const char * str)32 char *makeEscString(const char *str)
33 {
34 static const char *xchr = "#^\\\n\r\t";
35 static const char *tchr = "#^\\nrt";
36 int ch;
37 char *buf;
38 char *q;
39 const char *p;
40
41 if (str == NULL || *str == '\0') {
42 return (NULL);
43 }
44
45 buf = malloc(strlen(str) * 2 + 1);
46 if (buf == NULL) {
47 return (NULL);
48 }
49 q = buf;
50 while ((ch = *str++) != '\0') {
51 p = strchr(xchr, ch);
52 if (p != NULL) {
53 *q++ = '\\';
54 *q++ = tchr[p - xchr];
55 } else {
56 if (ch >= 0x00 && ch <= 0x1F) {
57 *q++ = '^';
58 *q++ = (char)(ch + '@');
59 } else {
60 *q++ = (char)ch;
61 if (iskanji(ch) != 0) {
62 ch = *str;
63 if (iskanji2(ch) != 0) {
64 *q++ = (char)ch;
65 str++;
66 }
67 }
68 }
69 }
70 }
71 *q = '\0';
72
73 return (buf);
74 }
75
76 static
close_writefile(void)77 void close_writefile(void)
78 {
79 if (ofp != NULL) {
80 fclose(ofp);
81 ofp = NULL;
82 }
83 }
84
85 /*
86 * return value:
87 * 0 ���ェλ
88 * -1 ���顼ȯ��
89 */
90 static
open_writefile(const char * filename)91 int open_writefile(const char *filename)
92 {
93 const char *filepath;
94
95 close_writefile();
96
97 filepath = search_filepath(filename);
98 if (filepath == NULL) {
99 return (-1);
100 }
101 strcpy(ofname, filepath);
102 strcat(ofname, ".new");
103
104 ofp = fopen(ofname, "w");
105 if (ofp == NULL) {
106 return (-1);
107 }
108 setvbuf(ofp, ofpbuf, _IOFBF, sizeof(ofpbuf));
109 return (0);
110 }
111
112 static
writefile(const char * fmt,...)113 void writefile(const char *fmt, ...)
114 {
115 va_list ap;
116
117 va_start(ap, fmt);
118 if (vfprintf(ofp, fmt, ap) == -1) {
119 errflag = TRUE;
120 }
121 va_end(ap);
122 }
123
124 static
close_readfile(void)125 void close_readfile(void)
126 {
127 if (ifp != NULL) {
128 fclose(ifp);
129 ifp = NULL;
130 }
131 }
132
133 /*
134 * return value:
135 * 0 ���ェλ
136 * -1 ���顼ȯ��
137 */
138 static
open_readfile(const char * filename)139 int open_readfile(const char *filename)
140 {
141 const char *filepath;
142
143 close_readfile();
144
145 filepath = search_filepath(filename);
146 if (filepath == NULL) {
147 return (-1);
148 }
149 strcpy(ifname, filepath);
150
151 ifp = fopen(ifname, "r");
152 if (ifp == NULL) {
153 return (-1);
154 }
155 setvbuf(ifp, ifpbuf, _IOFBF, sizeof(ifpbuf));
156
157 return (0);
158 }
159
160 /*
161 * �ե�������1���ɤ߹��ߡ��Хåե�����Ƭ���֤�
162 * ����Ƭ�ˤ��륹�ڡ��������֤��ɤߤȤФ�
163 * �ޤ�������Υ����Ȥ�������
164 *
165 * �ե����뤬��λ���뤤�ϥ��顼��ȯ���������ϡ�NULL ���֤�
166 */
167 static
readfile(void)168 char *readfile(void)
169 {
170 char *nl;
171 char *sp;
172
173 if (fgets(inbuf, sizeof(inbuf), ifp) == NULL) {
174 return (NULL);
175 }
176 nl = strchr(inbuf, '\n');
177 if (nl) {
178 *nl = '\0';
179 }
180 rembuf[0] = '\0';
181 strcpy(combuf, inbuf);
182 sp = combuf;
183 while (*sp == ' ' || *sp == '\t') {
184 sp++;
185 }
186 if (*sp == '#' || *sp == '\0') {
187 goto end_proc;
188 }
189 nl = sp;
190
191 again_search:
192 nl = strchr(nl, '#');
193 if (nl) {
194 #ifdef _T_SJIS
195 if (nl[-1] == '\\' && knjstat(combuf, (nl - 1) - combuf) == CODE_ANK) {
196 #endif
197 #ifdef _T_EUC
198 if (nl[-1] == '\\') {
199 #endif
200 const char *bkp = &nl[-1];
201 int c = 1;
202
203 while (--bkp >= combuf && *bkp == '\\') {
204 c++;
205 }
206 if ((c % 2) != 0) {
207 nl++;
208 goto again_search;
209 }
210 }
211 while (nl[-1] == ' ' || nl[-1] == '\t') {
212 nl--;
213 }
214 strcpy(rembuf, nl); /* copy comment */
215 *nl = '\0';
216 }
217
218 end_proc:;
219 return (sp);
220 }
221
222 /*
223 * �ѿ��ν���
224 *
225 * return value:
226 * TRUE �ѿ����Ϻ�
227 * FALSE ����
228 */
229 static
230 int check_op(struct CONFIG_VARIABLE_TABLE * const p, char *bp, int index)
231 {
232 char **chrp;
233 char *buf;
234 int *intp;
235 const struct OPERAND_TABLE *op;
236
237 switch (p->vl_type) {
238 case VAR_NONE:
239 return (FALSE);
240 case VAR_STR:
241 case VAR_DIMSTR:
242 chrp = p->vl_string;
243 buf = makeEscString(chrp[index]);
244 if (buf != NULL) {
245 writefile("%s = %s", bp, buf);
246 free(buf);
247 } else {
248 writefile("%s =", bp);
249 }
250 break;
251 case VAR_INT:
252 case VAR_DIMINT:
253 intp = p->vl_int;
254 switch (p->vl_fmt & 0x0F) {
255 case 0:
256 writefile("%s = %d", bp, intp[index]);
257 break;
258 case 1:
259 writefile("%s = 0x%0*X", bp, (p->vl_fmt >> 4) & 0x0F, intp[index]);
260 break;
261 }
262 break;
263 case VAR_OP:
264 intp = p->vl_int;
265 op = p->vl_optbl;
266 while (op->op_name != NULL) {
267 if (*intp == op->op_value) {
268 writefile("%s = %s", p->vl_name, op->op_name);
269 break;
270 }
271 op++;
272 }
273 break;
274 case VAR_OPNUM:
275 intp = p->vl_int;
276 op = p->vl_optbl;
277 writefile("%s = %s%d", p->vl_name, op->op_name, *intp);
278 break;
279 }
280
281 writefile("%s\n", rembuf);
282
283 return (TRUE);
284 }
285
286 /*
287 * �ѿ�̾�����
288 *
289 * return value:
290 * TRUE ̾������
291 * FALSE ����
292 */
293 static
294 int cmp_varname(const struct CONFIG_VARIABLE_TABLE * const p, const char *bp, int cmpsize)
295 {
296 if (p->vl_type == VAR_DIMSTR || p->vl_type == VAR_DIMINT) {
297 if (strncmp(p->vl_name, bp, cmpsize) == 0) {
298 return (TRUE);
299 }
300 } else {
301 if (strcmp(p->vl_name, bp) == 0) {
302 return (TRUE);
303 }
304 }
305 return (FALSE);
306 }
307
308 /*
309 * �ѿ�̾���������ֹ�(����ǥå���)�����
310 * �ѿ�̾����(����ǥå������������ʬ)��Ĺ�������
311 */
312 static
313 int get_cmpsize(const char *bp, int *index)
314 {
315 int cmpsize;
316
317 cmpsize = 0;
318 if (isdigit((unsigned char)*bp) != 0) { /* ��Ƭ�������ξ�� skip */
319 do {
320 bp++;
321 cmpsize++;
322 } while (*bp != '\0' && isdigit((unsigned char)*bp) != 0);
323 }
324 while (*bp != '\0' && (isdigit((unsigned char)*bp) == 0 && *bp != '-')) {
325 bp++;
326 cmpsize++;
327 }
328
329 if (*bp != '\0') {
330 *index = atoi(bp);
331 } else {
332 *index = 0;
333 }
334
335 return (cmpsize);
336 }
337
338 /*
339 * �ѿ�̾����ӡ��������
340 *
341 * return value:
342 * TRUE �Ѵ����Ϻ�
343 * FALSE ����
344 */
345 static
346 int search_varname_execop(struct CONFIG_VARIABLE_TABLE *cnf_tbl, char *bp)
347 {
348 char *np;
349 int cmpsize;
350 int index;
351 int hit_flag;
352 struct CONFIG_VARIABLE_TABLE *p;
353
354 np = strchr(bp, '=');
355 if (np == NULL) {
356 return (FALSE);
357 }
358 *np = '\0';
359
360 bp = strip(bp);
361 cmpsize = get_cmpsize(bp, &index);
362
363 hit_flag = FALSE;
364 p = cnf_tbl;
365 while (p->vl_name != NULL) {
366 if (cmp_varname(p, bp, cmpsize) == TRUE) {
367 hit_flag = check_op(p, bp, index);
368 break;
369 }
370 p++;
371 }
372
373 return (hit_flag);
374 }
375
376 /*
377 * ���ߥ֥�å�̾�����
378 * �ʹߤμ¹Ծ��֤����
379 *
380 * return value:
381 * TRUE ���ιԤ����о�
382 * FALSE ���Υ֥�å��ޤǥ����å�
383 */
384 static
385 int check_writeblock(const char *bp, const char **readblock)
386 {
387 bp++;
388 while (*readblock != NULL) {
389 if (strcmp(bp, *readblock) == 0) {
390 return (TRUE);
391 }
392 readblock++;
393 }
394 return (FALSE);
395 }
396
397 /*
398 * ����ե�����������������
399 *
400 * return value:
401 * TRUE ���ェλ
402 * FALSE ���顼ȯ��
403 */
404 int writeConfig(const char *config_filename, struct CONFIG_VARIABLE_TABLE *cnf_tbl, const char **readblock)
405 {
406 char *bp;
407 int skip_flag = FALSE;
408
409 if (open_readfile(config_filename)) {
410 return (FALSE);
411 }
412
413 if (open_writefile(config_filename)) {
414 close_readfile();
415 return (FALSE);
416 }
417
418 errflag = FALSE;
419 while ((bp = readfile()) != NULL) {
420 if (*bp == '#' || *bp == '\0') {
421 ;
422 } else if (*bp == '$') {
423 if (check_writeblock(strip(bp), readblock) == FALSE) {
424 skip_flag = TRUE; /* this block is skip */
425 } else {
426 skip_flag = FALSE; /* this block read */
427 }
428 } else if (skip_flag == TRUE) {
429 ;
430 } else if (search_varname_execop(cnf_tbl, bp) == TRUE) {
431 continue;
432 }
433 writefile("%s\n", inbuf);
434 }
435
436 close_readfile();
437 close_writefile();
438
439 if (errflag == TRUE || remove(ifname) != 0) {
440 remove(ofname);
441 return (FALSE);
442 }
443 rename(ofname, ifname);
444
445 return (TRUE);
446 }
447