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