The magicolor device apparently does not support WAIT_FOR_BUTTON
[sane-backend-magicolor.git] / sanei / sanei_config.c
blobca9b408a3fcb050a3a4ce16716989a5ef9050173
1 /* sane - Scanner Access Now Easy.
2 Copyright (C) 1997 Jeffrey S. Freedman
3 This file is part of the SANE package.
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
20 As a special exception, the authors of SANE give permission for
21 additional uses of the libraries contained in this release of SANE.
23 The exception is that, if you link a SANE library with other files
24 to produce an executable, this does not by itself cause the
25 resulting executable to be covered by the GNU General Public
26 License. Your use of that executable is in no way restricted on
27 account of linking the SANE library code into it.
29 This exception does not, however, invalidate any other reasons why
30 the executable file might be covered by the GNU General Public
31 License.
33 If you submit changes to SANE to the maintainers to be included in
34 a subsequent release, you agree by submitting the changes that
35 those changes may be distributed with this exception intact.
37 If you write modifications of your own for SANE, it is your choice
38 whether to permit this exception to apply to your modifications.
39 If you do not wish that, delete this exception notice.
41 This file provides generic configuration support. */
43 #include "sane/config.h"
45 #include <ctype.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
50 #include <sys/param.h>
52 #include "sane/sanei.h"
53 #include "sane/sanei_config.h"
55 #define BACKEND_NAME sanei_config
56 #include "sane/sanei_debug.h"
58 #ifndef PATH_MAX
59 # define PATH_MAX 1024
60 #endif
62 #if defined(HAVE_OS2_H)
63 # define DIR_SEP ";"
64 # define PATH_SEP '\\'
65 #elif defined(HAVE_WINDOWS_H)
66 # define DIR_SEP ";"
67 # define PATH_SEP '\\'
68 #else
69 # define DIR_SEP ":"
70 # define PATH_SEP '/'
71 #endif
73 #define DEFAULT_DIRS "." DIR_SEP STRINGIFY(PATH_SANE_CONFIG_DIR)
75 #ifdef __BEOS__
76 #include <FindDirectory.h>
77 #endif
79 static char *dir_list;
81 const char *
82 sanei_config_get_paths ()
84 #ifdef __BEOS__
85 char result[PATH_MAX];
86 #endif
87 void *mem;
88 char *dlist;
89 size_t len;
91 if (!dir_list)
93 DBG_INIT();
95 dlist = getenv ("SANE_CONFIG_DIR");
96 if (dlist)
97 dir_list = strdup (dlist);
98 #ifdef __BEOS__
99 /* ~/config/settings/SANE takes precedence over /etc/sane.d/ */
100 if (!dir_list)
102 if (find_directory(B_USER_SETTINGS_DIRECTORY, 0, true, result, PATH_MAX) == B_OK)
104 strcat(result,"/SANE");
105 strcat(result,DIR_SEP); /* do append the default ones */
106 dir_list = strdup (result);
109 #endif
110 if (dir_list)
112 len = strlen (dir_list);
113 if ((len > 0) && (dir_list[len - 1] == DIR_SEP[0]))
115 /* append default search directories: */
116 mem = malloc (len + sizeof (DEFAULT_DIRS));
117 memcpy (mem, dir_list, len);
118 memcpy ((char *) mem + len, DEFAULT_DIRS, sizeof (DEFAULT_DIRS));
119 free (dir_list);
120 dir_list = mem;
123 else
125 /* Create a copy, since we might call free on it */
126 dir_list = strdup (DEFAULT_DIRS);
129 DBG (5, "sanei_config_get_paths: using config directories %s\n", dir_list);
131 return dir_list;
134 FILE *
135 sanei_config_open (const char *filename)
137 char *next, *dir, result[PATH_MAX];
138 const char *cfg_dir_list;
139 FILE *fp;
140 char *copy;
142 cfg_dir_list = sanei_config_get_paths ();
143 if (!cfg_dir_list)
145 DBG(2, "sanei_config_open: could not find config file `%s'\n", filename);
146 return NULL;
149 copy = strdup (cfg_dir_list);
151 for (next = copy; (dir = strsep (&next, DIR_SEP)) != 0; )
153 snprintf (result, sizeof (result), "%s%c%s", dir, PATH_SEP, filename);
154 DBG(4, "sanei_config_open: attempting to open `%s'\n", result);
155 fp = fopen (result, "r");
156 if (fp)
158 DBG(3, "sanei_config_open: using file `%s'\n", result);
159 break;
162 free (copy);
164 if (!fp)
165 DBG(2, "sanei_config_open: could not find config file `%s'\n", filename);
167 return fp;
170 const char *
171 sanei_config_skip_whitespace (const char *str)
173 while (str && *str && isspace (*str))
174 ++str;
175 return str;
178 const char *
179 sanei_config_get_string (const char *str, char **string_const)
181 const char *start;
182 size_t len;
184 str = sanei_config_skip_whitespace (str);
186 if (*str == '"')
188 start = ++str;
189 while (*str && *str != '"')
190 ++str;
191 len = str - start;
192 if (*str == '"')
193 ++str;
194 else
195 start = 0; /* final double quote is missing */
197 else
199 start = str;
200 while (*str && !isspace (*str))
201 ++str;
202 len = str - start;
204 if (start)
205 *string_const = strndup (start, len);
206 else
207 *string_const = 0;
208 return str;
211 char *
212 sanei_config_read (char *str, int n, FILE *stream)
214 char* rc;
215 char* start;
216 int len;
218 /* read line from stream */
219 rc = fgets( str, n, stream);
220 if (rc == NULL)
221 return NULL;
223 /* remove ending whitespaces */
224 len = strlen( str);
225 while( (0 < len) && (isspace( str[--len])) )
226 str[len] = '\0';
228 /* remove starting whitespaces */
229 start = str;
230 while( isspace( *start))
231 start++;
233 if (start != str)
234 do {
235 *str++ = *start++;
236 } while( *str);
238 return rc;
242 SANE_Status
243 sanei_configure_attach (const char *config_file, SANEI_Config * config,
244 SANE_Status (*attach) (SANEI_Config * config,
245 const char *devname))
247 SANE_Char line[PATH_MAX];
248 SANE_Char *token, *string;
249 SANE_Int len;
250 const char *lp, *lp2;
251 FILE *fp;
252 SANE_Status status = SANE_STATUS_GOOD;
253 int i, j, count;
254 void *value = NULL;
255 int size=0;
256 SANE_Bool found;
257 SANE_Word *wa;
258 SANE_Bool *ba;
260 DBG (3, "sanei_configure_attach: start\n");
262 /* open configuration file */
263 fp = sanei_config_open (config_file);
264 if (!fp)
266 DBG (2, "sanei_configure_attach: couldn't access %s\n", config_file);
267 DBG (3, "sanei_configure_attach: exit\n");
268 return SANE_STATUS_ACCESS_DENIED;
271 /* loop reading the configuration file, all line beginning by "option " are
272 * parsed for value to store in configuration structure, other line are
273 * used are device to try to attach
275 while (sanei_config_read (line, PATH_MAX, fp) && status == SANE_STATUS_GOOD)
277 /* skip white spaces at beginning of line */
278 lp = sanei_config_skip_whitespace (line);
280 /* skip empty lines */
281 if (*lp == 0)
282 continue;
284 /* skip comment line */
285 if (line[0] == '#')
286 continue;
288 len = strlen (line);
290 /* delete newline characters at end */
291 if (line[len - 1] == '\n')
292 line[--len] = '\0';
294 lp2 = lp;
296 /* to ensure maximum compatibility, we accept line like:
297 * option "option_name" "option_value"
298 * "option_name" "option_value"
299 * So we parse the line 2 time to find an option */
300 /* check if it is an option */
301 lp = sanei_config_get_string (lp, &token);
302 if (strncmp (token, "option", 6) == 0)
304 /* skip the "option" token */
305 free (token);
306 lp = sanei_config_get_string (lp, &token);
309 /* search for a matching descriptor */
310 i = 0;
311 found = SANE_FALSE;
312 while (config!=NULL && i < config->count && !found)
314 if (strcmp (config->descriptors[i]->name, token) == 0)
316 found = SANE_TRUE;
317 switch (config->descriptors[i]->type)
319 case SANE_TYPE_INT:
320 size=config->descriptors[i]->size;
321 value = malloc (size);
322 wa = (SANE_Word *) value;
323 count = config->descriptors[i]->size / sizeof (SANE_Word);
324 for (j = 0; j < count; j++)
326 lp = sanei_config_get_string (lp, &string);
327 if (string == NULL)
329 DBG (2,
330 "sanei_configure_attach: couldn't find a string to parse");
331 return SANE_STATUS_INVAL;
333 wa[j] = strtol (string, NULL, 0);
334 free (string);
336 break;
337 case SANE_TYPE_BOOL:
338 size=config->descriptors[i]->size;
339 value = malloc (size);
340 ba = (SANE_Bool *) value;
341 count = config->descriptors[i]->size / sizeof (SANE_Bool);
342 for (j = 0; j < count; j++)
344 lp = sanei_config_get_string (lp, &string);
345 if (string == NULL)
347 DBG (2,
348 "sanei_configure_attach: couldn't find a string to parse");
349 return SANE_STATUS_INVAL;
351 if ((strcmp (string, "1") == 0)
352 || (strcmp (string, "true") == 0))
354 ba[j] = SANE_TRUE;
356 else
358 if ((strcmp (string, "0") == 0)
359 || (strcmp (string, "false") == 0))
360 ba[j] = SANE_FALSE;
361 else
363 DBG (2,
364 "sanei_configure_attach: couldn't find a valid boolean value");
365 return SANE_STATUS_INVAL;
368 free (string);
370 break;
371 case SANE_TYPE_FIXED:
372 size=config->descriptors[i]->size;
373 value = malloc (size);
374 wa = (SANE_Word *) value;
375 count = config->descriptors[i]->size / sizeof (SANE_Word);
376 for (j = 0; j < count; j++)
378 lp = sanei_config_get_string (lp, &string);
379 if (string == NULL)
381 DBG (2,
382 "sanei_configure_attach: couldn't find a string to parse");
383 return SANE_STATUS_INVAL;
385 wa[j] = SANE_FIX(strtod (string, NULL));
386 free (string);
388 break;
389 case SANE_TYPE_STRING:
390 sanei_config_get_string (lp, &string);
391 if (string == NULL)
393 DBG (2,
394 "sanei_configure_attach: couldn't find a string value to parse");
395 return SANE_STATUS_INVAL;
397 value = string;
398 size=strlen(string)+1;
399 if(size>config->descriptors[i]->size)
401 size=config->descriptors[i]->size-1;
402 string[size]=0;
404 break;
405 default:
406 DBG (1,
407 "sanei_configure_attach: incorrect type %d for option %s, skipping option ...\n",
408 config->descriptors[i]->type,
409 config->descriptors[i]->name);
412 /* check decoded value */
413 status = sanei_check_value (config->descriptors[i], value);
415 /* if value OK, copy it in configuration struct */
416 if (status == SANE_STATUS_GOOD)
418 memcpy (config->values[i], value, size);
420 if (value != NULL)
422 free (value);
423 value = NULL;
426 if (status != SANE_STATUS_GOOD)
428 DBG (1,
429 "sanei_configure_attach: failed to parse option '%s', line '%s'\n",
430 token, line);
432 i++;
434 free (token);
436 /* not detected as an option, so we call the attach function
437 * with it */
438 if (!found && status == SANE_STATUS_GOOD)
440 /* if not an option, try to attach */
441 /* to avoid every backend to depend on scsi and usb functions
442 * we call back the backend for attach. In turn it will call
443 * sanei_usb_attach_matching_devices, sanei_config_attach_matching_devices
444 * or other. This means 2 callback functions per backend using this
445 * function. */
446 DBG (3, "sanei_configure_attach: trying to attach with '%s'\n",
447 lp2);
448 if(attach!=NULL)
449 attach (config, lp2);
453 fclose (fp);
454 DBG (3, "sanei_configure_attach: exit\n");
455 return status;