data.c revision 1.3 1 1.3 he /* $NetBSD: data.c,v 1.3 2005/06/07 14:01:49 he Exp $ */
2 1.1 takemura
3 1.1 takemura /*-
4 1.1 takemura * Copyright (c) 2002 TAKEMRUA Shin
5 1.1 takemura * All rights reserved.
6 1.1 takemura *
7 1.1 takemura * Redistribution and use in source and binary forms, with or without
8 1.1 takemura * modification, are permitted provided that the following conditions
9 1.1 takemura * are met:
10 1.1 takemura * 1. Redistributions of source code must retain the above copyright
11 1.1 takemura * notice, this list of conditions and the following disclaimer.
12 1.1 takemura * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 takemura * notice, this list of conditions and the following disclaimer in the
14 1.1 takemura * documentation and/or other materials provided with the distribution.
15 1.1 takemura * 3. Neither the name of The NetBSD Foundation nor the names of its
16 1.1 takemura * contributors may be used to endorse or promote products derived
17 1.1 takemura * from this software without specific prior written permission.
18 1.1 takemura *
19 1.1 takemura * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 takemura * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 takemura * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 takemura * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 takemura * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 takemura * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 takemura * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 takemura * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 takemura * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 takemura * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 takemura * POSSIBILITY OF SUCH DAMAGE.
30 1.1 takemura */
31 1.1 takemura
32 1.1 takemura #include <stdio.h>
33 1.1 takemura #include <strings.h>
34 1.1 takemura #include <stdlib.h>
35 1.1 takemura #include <time.h>
36 1.1 takemura #include <fcntl.h>
37 1.1 takemura #include <unistd.h>
38 1.1 takemura #include <sys/param.h>
39 1.1 takemura
40 1.1 takemura #include "tpctl.h"
41 1.1 takemura
42 1.1 takemura #ifndef lint
43 1.1 takemura #include <sys/cdefs.h>
44 1.3 he __RCSID("$NetBSD: data.c,v 1.3 2005/06/07 14:01:49 he Exp $");
45 1.1 takemura #endif /* not lint */
46 1.1 takemura
47 1.1 takemura static void *
48 1.1 takemura alloc(int size)
49 1.1 takemura {
50 1.1 takemura void *res;
51 1.1 takemura
52 1.1 takemura if ((res = malloc(size)) == NULL) {
53 1.1 takemura perror(getprogname());
54 1.1 takemura exit(EXIT_FAILURE);
55 1.1 takemura }
56 1.1 takemura
57 1.1 takemura return (res);
58 1.1 takemura }
59 1.1 takemura
60 1.1 takemura /*
61 1.1 takemura * duplicate string
62 1.1 takemura * trailing white space will be removed.
63 1.1 takemura */
64 1.1 takemura static char *
65 1.1 takemura strdup_prune(char *s)
66 1.1 takemura {
67 1.1 takemura char *res, *tail;
68 1.1 takemura
69 1.1 takemura tail = &s[strlen(s) - 1];
70 1.1 takemura while (s <= tail && strchr(" \t", *tail) != NULL)
71 1.1 takemura tail--;
72 1.1 takemura
73 1.1 takemura res = alloc(tail - s + 2);
74 1.1 takemura memcpy(res, s, tail - s + 1);
75 1.1 takemura res[tail - s + 1] = '\0';
76 1.1 takemura
77 1.1 takemura return (res);
78 1.1 takemura }
79 1.1 takemura
80 1.1 takemura int
81 1.1 takemura init_data(struct tpctl_data *data)
82 1.1 takemura {
83 1.1 takemura TAILQ_INIT(&data->list);
84 1.1 takemura
85 1.1 takemura return (0);
86 1.1 takemura }
87 1.1 takemura
88 1.1 takemura int
89 1.1 takemura read_data(char *filename, struct tpctl_data *data)
90 1.1 takemura {
91 1.1 takemura int res, len, n, i, t;
92 1.1 takemura char buf[MAXDATALEN + 2], *p, *p2;
93 1.1 takemura FILE *fp;
94 1.1 takemura struct tpctl_data_elem *elem;
95 1.1 takemura
96 1.1 takemura data->lineno = 0;
97 1.1 takemura
98 1.1 takemura if ((fp = fopen(filename, "r")) == NULL)
99 1.1 takemura return (ERR_NOFILE);
100 1.1 takemura
101 1.1 takemura while (fgets(buf, sizeof(buf), fp) != NULL) {
102 1.1 takemura data->lineno++;
103 1.1 takemura buf[MAXDATALEN + 1] = '\0';
104 1.1 takemura len = strlen(buf);
105 1.1 takemura if (MAXDATALEN < len) {
106 1.1 takemura res = ERR_SYNTAX;
107 1.1 takemura goto exit_func;
108 1.1 takemura }
109 1.1 takemura
110 1.1 takemura /* prune trailing space and newline */;
111 1.1 takemura p = &buf[len - 1];
112 1.1 takemura while (buf <= p && strchr(" \t\n\r", *p) != NULL)
113 1.1 takemura *p-- = '\0';
114 1.1 takemura
115 1.1 takemura /* skip space */;
116 1.1 takemura p = buf;
117 1.1 takemura while (*p != '\0' && strchr(" \t", *p) != NULL)
118 1.1 takemura p++;
119 1.1 takemura
120 1.1 takemura /* comment or empty line */
121 1.1 takemura if (*p == '#' || *p == '\0') {
122 1.1 takemura elem = alloc(sizeof(*elem));
123 1.1 takemura elem->type = TPCTL_COMMENT;
124 1.1 takemura elem->name = strdup_prune(buf);
125 1.1 takemura TAILQ_INSERT_TAIL(&data->list, elem, link);
126 1.1 takemura continue;
127 1.1 takemura }
128 1.1 takemura
129 1.1 takemura /* calibration parameter */
130 1.1 takemura elem = alloc(sizeof(*elem));
131 1.1 takemura elem->type = TPCTL_CALIBCOORDS;
132 1.1 takemura p2 = p;
133 1.1 takemura while (*p2 != ',' && *p2 != '\0')
134 1.1 takemura p2++;
135 1.1 takemura if (*p2 != ',') {
136 1.1 takemura /* missing ',' */
137 1.1 takemura res = ERR_SYNTAX;
138 1.1 takemura free(elem);
139 1.1 takemura goto exit_func;
140 1.1 takemura }
141 1.1 takemura *p2 = '\0';
142 1.1 takemura elem->name = strdup_prune(p);
143 1.1 takemura if (search_data(data, elem->name) != NULL) {
144 1.1 takemura free(elem);
145 1.1 takemura res = ERR_DUPNAME;
146 1.1 takemura goto exit_func;
147 1.1 takemura }
148 1.1 takemura TAILQ_INSERT_TAIL(&data->list, elem, link);
149 1.1 takemura p = p2 + 1;
150 1.1 takemura
151 1.2 takemura /*
152 1.2 takemura * minX, maxX, minY, maxY
153 1.2 takemura */
154 1.2 takemura for (i = 0; i < 4; i++) {
155 1.2 takemura t = strtol(p, &p2, 0);
156 1.2 takemura if (p == p2) {
157 1.2 takemura res = ERR_SYNTAX;
158 1.2 takemura goto exit_func;
159 1.2 takemura }
160 1.2 takemura p = p2;
161 1.2 takemura while (*p != '\0' && strchr(" \t", *p) != NULL)
162 1.2 takemura p++;
163 1.2 takemura if (*p != ',') {
164 1.2 takemura res = ERR_SYNTAX;
165 1.2 takemura goto exit_func;
166 1.2 takemura }
167 1.2 takemura p++;
168 1.2 takemura switch (i % 4) {
169 1.2 takemura case 0:
170 1.2 takemura elem->calibcoords.minx = t;
171 1.2 takemura break;
172 1.2 takemura case 1:
173 1.2 takemura elem->calibcoords.miny = t;
174 1.2 takemura break;
175 1.2 takemura case 2:
176 1.2 takemura elem->calibcoords.maxx = t;
177 1.2 takemura break;
178 1.2 takemura case 3:
179 1.2 takemura elem->calibcoords.maxy = t;
180 1.2 takemura break;
181 1.2 takemura }
182 1.2 takemura }
183 1.2 takemura
184 1.2 takemura /*
185 1.2 takemura * number of samples
186 1.2 takemura */
187 1.1 takemura n = strtol(p, &p2, 0);
188 1.1 takemura if (p == p2) {
189 1.1 takemura res = ERR_SYNTAX;
190 1.1 takemura goto exit_func;
191 1.1 takemura }
192 1.1 takemura p = p2;
193 1.1 takemura while (*p != '\0' && strchr(" \t", *p) != NULL)
194 1.1 takemura p++;
195 1.1 takemura
196 1.1 takemura if (WSMOUSE_CALIBCOORDS_MAX < n) {
197 1.1 takemura res = ERR_SYNTAX;
198 1.1 takemura goto exit_func;
199 1.1 takemura }
200 1.1 takemura elem->calibcoords.samplelen = n;
201 1.2 takemura
202 1.2 takemura /*
203 1.2 takemura * samples
204 1.2 takemura */
205 1.1 takemura for (i = 0; i < n * 4; i++) {
206 1.1 takemura if (*p != ',') {
207 1.1 takemura res = ERR_SYNTAX;
208 1.1 takemura goto exit_func;
209 1.1 takemura }
210 1.1 takemura p++;
211 1.1 takemura t = strtol(p, &p2, 0);
212 1.1 takemura if (p == p2) {
213 1.1 takemura res = ERR_SYNTAX;
214 1.1 takemura goto exit_func;
215 1.1 takemura }
216 1.1 takemura p = p2;
217 1.1 takemura while (*p != '\0' && strchr(" \t", *p) != NULL)
218 1.1 takemura p++;
219 1.1 takemura switch (i % 4) {
220 1.1 takemura case 0:
221 1.1 takemura elem->calibcoords.samples[i / 4].rawx = t;
222 1.1 takemura break;
223 1.1 takemura case 1:
224 1.1 takemura elem->calibcoords.samples[i / 4].rawy = t;
225 1.1 takemura break;
226 1.1 takemura case 2:
227 1.1 takemura elem->calibcoords.samples[i / 4].x = t;
228 1.1 takemura break;
229 1.1 takemura case 3:
230 1.1 takemura elem->calibcoords.samples[i / 4].y = t;
231 1.1 takemura break;
232 1.1 takemura }
233 1.1 takemura }
234 1.1 takemura if (*p != '\0') {
235 1.1 takemura res = ERR_SYNTAX;
236 1.1 takemura goto exit_func;
237 1.1 takemura }
238 1.1 takemura }
239 1.1 takemura
240 1.1 takemura if (ferror(fp))
241 1.1 takemura res = ERR_IO;
242 1.1 takemura else
243 1.1 takemura res = ERR_NONE;
244 1.1 takemura
245 1.1 takemura exit_func:
246 1.1 takemura fclose(fp);
247 1.1 takemura if (res != ERR_NONE) {
248 1.1 takemura free_data(data);
249 1.1 takemura }
250 1.1 takemura
251 1.1 takemura return (res);
252 1.1 takemura }
253 1.1 takemura
254 1.1 takemura int
255 1.1 takemura write_data(char *filename, struct tpctl_data *data)
256 1.1 takemura {
257 1.1 takemura int res, fd;
258 1.1 takemura FILE *fp;
259 1.1 takemura struct tpctl_data_elem *elem;
260 1.1 takemura char *p, tmpfile[MAXPATHLEN + 1];
261 1.1 takemura
262 1.3 he fd = 0; /* XXXGCC -Wuninitialized [hpcarm] */
263 1.3 he
264 1.1 takemura if (filename == NULL) {
265 1.1 takemura fp = stdout;
266 1.1 takemura } else {
267 1.1 takemura strncpy(tmpfile, filename, MAXPATHLEN);
268 1.1 takemura tmpfile[MAXPATHLEN] = '\0';
269 1.1 takemura if ((p = strrchr(tmpfile, '/')) == NULL) {
270 1.1 takemura strcpy(tmpfile, TPCTL_TMP_FILENAME);
271 1.1 takemura } else {
272 1.1 takemura p++;
273 1.1 takemura if (MAXPATHLEN <
274 1.1 takemura p - tmpfile + strlen(TPCTL_TMP_FILENAME))
275 1.1 takemura return (ERR_NOFILE);/* file name is too long */
276 1.1 takemura strcat(tmpfile, TPCTL_TMP_FILENAME);
277 1.1 takemura }
278 1.1 takemura if ((fd = open(tmpfile, O_RDWR|O_CREAT|O_EXCL, 0644)) < 0) {
279 1.1 takemura fprintf(stderr, "%s: can't create %s\n",
280 1.1 takemura getprogname(), tmpfile);
281 1.1 takemura return (ERR_NOFILE);
282 1.1 takemura }
283 1.1 takemura if ((fp = fdopen(fd, "w")) == NULL) {
284 1.1 takemura perror("fdopen");
285 1.1 takemura exit(EXIT_FAILURE);
286 1.1 takemura }
287 1.1 takemura }
288 1.1 takemura
289 1.1 takemura TAILQ_FOREACH(elem, &data->list, link) {
290 1.1 takemura switch (elem->type) {
291 1.1 takemura case TPCTL_CALIBCOORDS:
292 1.1 takemura write_coords(fp, elem->name, &elem->calibcoords);
293 1.1 takemura break;
294 1.1 takemura case TPCTL_COMMENT:
295 1.1 takemura fprintf(fp, "%s\n", elem->name);
296 1.1 takemura break;
297 1.1 takemura default:
298 1.1 takemura fprintf(stderr, "%s: internal error\n", getprogname());
299 1.1 takemura exit(EXIT_FAILURE);
300 1.1 takemura break;
301 1.1 takemura }
302 1.1 takemura }
303 1.1 takemura
304 1.1 takemura if (filename != NULL) {
305 1.1 takemura fclose(fp);
306 1.1 takemura close(fd);
307 1.1 takemura if (rename(tmpfile, filename) < 0) {
308 1.1 takemura unlink(tmpfile);
309 1.1 takemura return (ERR_NOFILE);
310 1.1 takemura }
311 1.1 takemura }
312 1.1 takemura res = ERR_NONE;
313 1.1 takemura
314 1.1 takemura return (res);
315 1.1 takemura }
316 1.1 takemura
317 1.1 takemura void
318 1.1 takemura write_coords(FILE *fp, char *name, struct wsmouse_calibcoords *coords)
319 1.1 takemura {
320 1.1 takemura int i;
321 1.1 takemura
322 1.2 takemura fprintf(fp, "%s,%d,%d,%d,%d,%d", name,
323 1.2 takemura coords->minx, coords->miny,
324 1.2 takemura coords->maxx, coords->maxy,
325 1.2 takemura coords->samplelen);
326 1.1 takemura for (i = 0; i < coords->samplelen; i++) {
327 1.1 takemura fprintf(fp, ",%d,%d,%d,%d",
328 1.1 takemura coords->samples[i].rawx,
329 1.1 takemura coords->samples[i].rawy,
330 1.1 takemura coords->samples[i].x,
331 1.1 takemura coords->samples[i].y);
332 1.1 takemura }
333 1.1 takemura fprintf(fp, "\n");
334 1.1 takemura }
335 1.1 takemura
336 1.1 takemura void
337 1.1 takemura free_data(struct tpctl_data *data)
338 1.1 takemura {
339 1.1 takemura struct tpctl_data_elem *elem;
340 1.1 takemura
341 1.1 takemura while (!TAILQ_EMPTY(&data->list)) {
342 1.1 takemura elem = TAILQ_FIRST(&data->list);
343 1.1 takemura TAILQ_REMOVE(&data->list, elem, link);
344 1.1 takemura
345 1.1 takemura switch (elem->type) {
346 1.1 takemura case TPCTL_CALIBCOORDS:
347 1.1 takemura case TPCTL_COMMENT:
348 1.1 takemura free(elem->name);
349 1.1 takemura break;
350 1.1 takemura default:
351 1.1 takemura fprintf(stderr, "%s: internal error\n", getprogname());
352 1.1 takemura exit(EXIT_FAILURE);
353 1.1 takemura break;
354 1.1 takemura }
355 1.1 takemura }
356 1.1 takemura }
357 1.1 takemura
358 1.1 takemura int
359 1.1 takemura replace_data(struct tpctl_data *data, char *name, struct wsmouse_calibcoords *calibcoords)
360 1.1 takemura {
361 1.1 takemura struct tpctl_data_elem *elem;
362 1.1 takemura
363 1.1 takemura TAILQ_FOREACH(elem, &data->list, link) {
364 1.1 takemura if (elem->type == TPCTL_CALIBCOORDS &&
365 1.1 takemura strcmp(name, elem->name) == 0) {
366 1.1 takemura elem->calibcoords = *calibcoords;
367 1.1 takemura return (0);
368 1.1 takemura }
369 1.1 takemura }
370 1.1 takemura
371 1.1 takemura elem = alloc(sizeof(*elem));
372 1.1 takemura elem->type = TPCTL_CALIBCOORDS;
373 1.1 takemura elem->name = strdup(name);
374 1.1 takemura elem->calibcoords = *calibcoords;
375 1.1 takemura if (elem->name == NULL) {
376 1.1 takemura perror(getprogname());
377 1.1 takemura exit(EXIT_FAILURE);
378 1.1 takemura }
379 1.1 takemura TAILQ_INSERT_TAIL(&data->list, elem, link);
380 1.1 takemura
381 1.1 takemura return (1);
382 1.1 takemura }
383 1.1 takemura
384 1.1 takemura struct wsmouse_calibcoords *
385 1.1 takemura search_data(struct tpctl_data *data, char *name)
386 1.1 takemura {
387 1.1 takemura struct tpctl_data_elem *elem;
388 1.1 takemura
389 1.1 takemura TAILQ_FOREACH(elem, &data->list, link) {
390 1.1 takemura if (elem->type == TPCTL_CALIBCOORDS &&
391 1.1 takemura strcmp(name, elem->name) == 0) {
392 1.1 takemura return (&elem->calibcoords);
393 1.1 takemura }
394 1.1 takemura }
395 1.1 takemura
396 1.1 takemura return (NULL);
397 1.1 takemura }
398