1 /* sane - Scanner Access Now Easy.
2 Copyright (C) 1996, 1997 David Mosberger-Tang
3 This file is part of the SANE package.
4
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.
9
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.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
17
18 As a special exception, the authors of SANE give permission for
19 additional uses of the libraries contained in this release of SANE.
20
21 The exception is that, if you link a SANE library with other files
22 to produce an executable, this does not by itself cause the
23 resulting executable to be covered by the GNU General Public
24 License. Your use of that executable is in no way restricted on
25 account of linking the SANE library code into it.
26
27 This exception does not, however, invalidate any other reasons why
28 the executable file might be covered by the GNU General Public
29 License.
30
31 If you submit changes to SANE to the maintainers to be included in
32 a subsequent release, you agree by submitting the changes that
33 those changes may be distributed with this exception intact.
34
35 If you write modifications of your own for SANE, it is your choice
36 whether to permit this exception to apply to your modifications.
37 If you do not wish that, delete this exception notice.
38
39 This file implements a dynamic linking based SANE meta backend. It
40 allows managing an arbitrary number of SANE backends by using
41 dynamic linking to load backends on demand. */
42
43 /* Please increase version number with every change
44 (don't forget to update dll.desc) */
45 #define DLL_VERSION "1.0.13"
46
47 #ifdef _AIX
48 # include "lalloca.h" /* MUST come first for AIX! */
49 #endif
50
51 #ifdef __BEOS__
52 #include <kernel/OS.h>
53 #include <storage/FindDirectory.h>
54 #include <kernel/image.h>
55 #include <posix/dirent.h>
56 #endif
57
58 #include "../include/sane/config.h"
59 #include "lalloca.h"
60
61 #include <errno.h>
62 #include <limits.h>
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <string.h>
66
67 #if defined(HAVE_DLOPEN) && defined(HAVE_DLFCN_H)
68 # include <dlfcn.h>
69
70 /* This works around a pedantic GCC compiler warning. The ISO C
71 standard says that the behaviour of converting an object pointer
72 like the void * returned by dlsym() to a function pointer like
73 void *(*)() is implementation defined. POSIX though guarantees
74 that this works fine.
75
76 Workaround based on http://stackoverflow.com/a/36385690. Turns
77 off pedantic warnings for the duration of the definition only.
78 */
79 # pragma GCC diagnostic push
80 # pragma GCC diagnostic ignored "-Wpedantic"
81 typedef void *(*func_ptr)(void);
82
83 func_ptr
posix_dlsym(void * handle,const char * func)84 posix_dlsym (void *handle, const char *func)
85 {
86 return dlsym (handle, func);
87 }
88 # pragma GCC diagnostic pop
89
90 /* Similar to the above, GCC also warns about conversion between
91 pointers to functions. The ISO C standard says that invoking a
92 converted pointer to a function whose type is not compatible with
93 the pointed-to type, the behavior is undefined. Although GCC is
94 correct to warn about this, the dll backend has been using these
95 conversions without issues for a very long time already.
96
97 Rather than push/pop around every use, which would get very ugly
98 real fast, ignore this particular warning for the remainder of
99 the file.
100 */
101 # pragma GCC diagnostic ignored "-Wpragmas" /* backward compatibility */
102 # pragma GCC diagnostic ignored "-Wcast-function-type"
103
104 /* Older versions of dlopen() don't define RTLD_NOW and RTLD_LAZY.
105 They all seem to use a mode of 1 to indicate RTLD_NOW and some do
106 not support RTLD_LAZY at all. Hence, unless defined, we define
107 both macros as 1 to play it safe. */
108 # ifndef RTLD_NOW
109 # define RTLD_NOW 1
110 # endif
111 # ifndef RTLD_LAZY
112 # define RTLD_LAZY 1
113 # endif
114 # define HAVE_DLL
115 #endif
116
117 /* HP/UX DLL support */
118 #if defined (HAVE_SHL_LOAD) && defined(HAVE_DL_H)
119 # include <dl.h>
120 # define HAVE_DLL
121 #endif
122
123 /* Mac OS X/Darwin support */
124 #if defined (HAVE_NSLINKMODULE) && defined(HAVE_MACH_O_DYLD_H)
125 # include <mach-o/dyld.h>
126 # define HAVE_DLL
127 #endif
128
129 #include <sys/types.h>
130 #include <sys/stat.h>
131 #include <dirent.h>
132
133 #include "../include/sane/sane.h"
134 #include "../include/sane/sanei.h"
135
136 #define BACKEND_NAME dll
137 #include "../include/sane/sanei_backend.h"
138
139 #ifndef PATH_MAX
140 # define PATH_MAX 1024
141 #endif
142
143 #ifndef NAME_MAX
144 # define NAME_MAX FILENAME_MAX
145 #endif
146
147 #if defined(_WIN32) || defined(HAVE_OS2_H)
148 # define DIR_SEP ";"
149 #else
150 # define DIR_SEP ":"
151 #endif
152
153
154 #include "../include/sane/sanei_config.h"
155 #define DLL_CONFIG_FILE "dll.conf"
156 #define DLL_ALIASES_FILE "dll.aliases"
157
158 #include "../include/sane/sanei_usb.h"
159
160 enum SANE_Ops
161 {
162 OP_INIT = 0,
163 OP_EXIT,
164 OP_GET_DEVS,
165 OP_OPEN,
166 OP_CLOSE,
167 OP_GET_OPTION_DESC,
168 OP_CTL_OPTION,
169 OP_GET_PARAMS,
170 OP_START,
171 OP_READ,
172 OP_CANCEL,
173 OP_SET_IO_MODE,
174 OP_GET_SELECT_FD,
175 NUM_OPS
176 };
177
178 typedef SANE_Status (*op_init_t) (SANE_Int *, SANE_Auth_Callback);
179 typedef void (*op_exit_t) (void);
180 typedef SANE_Status (*op_get_devs_t) (const SANE_Device ***, SANE_Bool);
181 typedef SANE_Status (*op_open_t) (SANE_String_Const, SANE_Handle *);
182 typedef void (*op_close_t) (SANE_Handle);
183 typedef const SANE_Option_Descriptor * (*op_get_option_desc_t) (SANE_Handle,
184 SANE_Int);
185 typedef SANE_Status (*op_ctl_option_t) (SANE_Handle, SANE_Int, SANE_Action,
186 void *, SANE_Int *);
187 typedef SANE_Status (*op_get_params_t) (SANE_Handle, SANE_Parameters *);
188 typedef SANE_Status (*op_start_t) (SANE_Handle);
189 typedef SANE_Status (*op_read_t) (SANE_Handle, SANE_Byte *, SANE_Int,
190 SANE_Int *);
191 typedef void (*op_cancel_t) (SANE_Handle);
192 typedef SANE_Status (*op_set_io_mode_t) (SANE_Handle, SANE_Bool);
193 typedef SANE_Status (*op_get_select_fd_t) (SANE_Handle, SANE_Int *);
194
195 struct backend
196 {
197 struct backend *next;
198 char *name;
199 u_int permanent:1; /* is the backend preloaded? */
200 u_int loaded:1; /* are the functions available? */
201 u_int inited:1; /* has the backend been initialized? */
202 void *handle; /* handle returned by dlopen() */
203 void *(*op[NUM_OPS]) (void);
204 };
205
206 #define BE_ENTRY(be,func) sane_##be##_##func
207
208 #define PRELOAD_DECL(name) \
209 extern SANE_Status BE_ENTRY(name,init) (SANE_Int *, SANE_Auth_Callback); \
210 extern void BE_ENTRY(name,exit) (void); \
211 extern SANE_Status BE_ENTRY(name,get_devices) (const SANE_Device ***, SANE_Bool); \
212 extern SANE_Status BE_ENTRY(name,open) (SANE_String_Const, SANE_Handle *); \
213 extern void BE_ENTRY(name,close) (SANE_Handle); \
214 extern const SANE_Option_Descriptor *BE_ENTRY(name,get_option_descriptor) (SANE_Handle, SANE_Int); \
215 extern SANE_Status BE_ENTRY(name,control_option) (SANE_Handle, SANE_Int, SANE_Action, void *, SANE_Int *); \
216 extern SANE_Status BE_ENTRY(name,get_parameters) (SANE_Handle, SANE_Parameters *); \
217 extern SANE_Status BE_ENTRY(name,start) (SANE_Handle); \
218 extern SANE_Status BE_ENTRY(name,read) (SANE_Handle, SANE_Byte *, SANE_Int, SANE_Int *); \
219 extern void BE_ENTRY(name,cancel) (SANE_Handle); \
220 extern SANE_Status BE_ENTRY(name,set_io_mode) (SANE_Handle, SANE_Bool); \
221 extern SANE_Status BE_ENTRY(name,get_select_fd) (SANE_Handle, SANE_Int *);
222
223 #define PRELOAD_DEFN(name) \
224 { \
225 0 /* next */, #name, \
226 1 /* permanent */, \
227 1 /* loaded */, \
228 0 /* inited */, \
229 0 /* handle */, \
230 { \
231 BE_ENTRY(name,init), \
232 BE_ENTRY(name,exit), \
233 BE_ENTRY(name,get_devices), \
234 BE_ENTRY(name,open), \
235 BE_ENTRY(name,close), \
236 BE_ENTRY(name,get_option_descriptor), \
237 BE_ENTRY(name,control_option), \
238 BE_ENTRY(name,get_parameters), \
239 BE_ENTRY(name,start), \
240 BE_ENTRY(name,read), \
241 BE_ENTRY(name,cancel), \
242 BE_ENTRY(name,set_io_mode), \
243 BE_ENTRY(name,get_select_fd) \
244 } \
245 }
246
247 #ifndef __BEOS__
248 #ifdef ENABLE_PRELOAD
249 #include "dll-preload.h"
250 #else
251 static struct backend preloaded_backends[] = {
252 { 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}
253 };
254 #endif
255 #endif
256
257 struct meta_scanner
258 {
259 struct backend *be;
260 SANE_Handle handle;
261 };
262
263 struct alias
264 {
265 struct alias *next;
266 char *oldname;
267 char *newname;
268 };
269
270 /*
271 * List of available devices, allocated by sane_get_devices, released
272 * by sane_exit()
273 */
274 static SANE_Device **devlist = NULL;
275 static int devlist_size = 0, devlist_len = 0;
276
277 static struct alias *first_alias;
278 static SANE_Auth_Callback auth_callback;
279 static struct backend *first_backend;
280
281 #ifndef __BEOS__
282 static const char *op_name[] = {
283 "init", "exit", "get_devices", "open", "close", "get_option_descriptor",
284 "control_option", "get_parameters", "start", "read", "cancel",
285 "set_io_mode", "get_select_fd"
286 };
287 #else
288 static const char *op_name[] = {
289 "sane_init", "sane_exit", "sane_get_devices", "sane_open", "sane_close", "sane_get_option_descriptor",
290 "sane_control_option", "sane_get_parameters", "sane_start", "sane_read", "sane_cancel",
291 "sane_set_io_mode", "sane_get_select_fd"
292 };
293 #endif /* __BEOS__ */
294
295 static void *
op_unsupported(void)296 op_unsupported (void)
297 {
298 DBG (1, "op_unsupported: call to unsupported backend operation\n");
299 return (void *) (long) SANE_STATUS_UNSUPPORTED;
300 }
301
302
303 static SANE_Status
add_backend(const char * name,struct backend ** bep)304 add_backend (const char *name, struct backend **bep)
305 {
306 struct backend *be, *prev;
307
308 DBG (3, "add_backend: adding backend `%s'\n", name);
309
310 if (strcmp (name, "dll") == 0)
311 {
312 DBG (0, "add_backend: remove the dll-backend from your dll.conf!\n");
313 return SANE_STATUS_GOOD;
314 }
315
316 for (prev = 0, be = first_backend; be; prev = be, be = be->next)
317 if (strcmp (be->name, name) == 0)
318 {
319 DBG (1, "add_backend: `%s' is already there\n", name);
320 /* move to front so we preserve order that we'd get with
321 dynamic loading: */
322 if (prev)
323 {
324 prev->next = be->next;
325 be->next = first_backend;
326 first_backend = be;
327 }
328 if (bep)
329 *bep = be;
330 return SANE_STATUS_GOOD;
331 }
332
333 be = calloc (1, sizeof (*be));
334 if (!be)
335 return SANE_STATUS_NO_MEM;
336
337 be->name = strdup (name);
338 if (!be->name)
339 return SANE_STATUS_NO_MEM;
340 be->next = first_backend;
341 first_backend = be;
342 if (bep)
343 *bep = be;
344 return SANE_STATUS_GOOD;
345 }
346
347 #if defined(HAVE_NSLINKMODULE)
348 static const char *dyld_get_error_str ();
349
350 static const char *
dyld_get_error_str()351 dyld_get_error_str ()
352 {
353 NSLinkEditErrors c;
354 int errorNumber;
355 const char *fileName;
356 const char *errorString;
357
358 NSLinkEditError (&c, &errorNumber, &fileName, &errorString);
359 return errorString;
360 }
361 #endif
362
363 #ifdef __BEOS__
364 #include <FindDirectory.h>
365
366 static SANE_Status
load(struct backend * be)367 load (struct backend *be)
368 {
369 /* use BeOS kernel function to load scanner addons from ~/config/add-ons/SANE */
370 char path[PATH_MAX];
371 image_id id = -1;
372 int i, w;
373 directory_which which[3] = { B_USER_ADDONS_DIRECTORY, B_COMMON_ADDONS_DIRECTORY, B_BEOS_ADDONS_DIRECTORY };
374
375 /* look for config files in SANE/conf */
376 for (w = 0; (w < 3) && (id < 0) && (find_directory(which[w],0,true,path,PATH_MAX) == 0); w++)
377 {
378 strcat(path,"/SANE/");
379 strcat(path,be->name);
380 DBG(1, "loading backend %s\n", be->name);
381
382 /* initialize all ops to "unsupported" so we can "use" the backend
383 even if the stuff later in this function fails */
384 be->loaded = 1;
385 be->handle = 0;
386 for (i = 0; i < NUM_OPS; ++i) be->op[i] = op_unsupported;
387 DBG(2, "dlopen()ing `%s'\n", path);
388 id=load_add_on(path);
389 if (id < 0)
390 {
391 continue; /* try next path */
392 }
393 be->handle=(void *)id;
394
395 for (i = 0; i < NUM_OPS; ++i)
396 {
397 void *(*op) ();
398 op = NULL;
399 /* Look for the symbol */
400 if ((get_image_symbol(id, op_name[i],B_SYMBOL_TYPE_TEXT,(void **)&op) < 0) || !op)
401 DBG(2, "unable to find %s\n", op_name[i]);
402 else be->op[i]=op;
403 }
404 }
405 if (id < 0)
406 {
407 DBG(2, "load: couldn't find %s\n",path);
408 return SANE_STATUS_INVAL;
409 }
410 return SANE_STATUS_GOOD;
411 }
412
413 #else
414 static SANE_Status
load(struct backend * be)415 load (struct backend *be)
416 {
417 #ifdef HAVE_DLL
418 int mode = 0;
419 char *funcname, *src, *orig_src = 0, *dir, *path = 0;
420 char libname[PATH_MAX];
421 int i;
422 int src_len;
423 FILE *fp = 0;
424
425 #if defined(HAVE_DLOPEN)
426 # define PREFIX "libsane-"
427 # ifdef __hpux
428 # define POSTFIX ".sl.%u"
429 # define ALT_POSTFIX ".so.%u"
430 # elif defined (HAVE_WINDOWS_H)
431 # undef PREFIX
432 # define PREFIX "cygsane-"
433 # define POSTFIX "-%u.dll"
434 # elif defined (HAVE_OS2_H)
435 # undef PREFIX
436 # define PREFIX ""
437 # define POSTFIX ".dll"
438 # elif defined (__APPLE__) && defined (__MACH__)
439 # define POSTFIX ".%u.so"
440 # else
441 # define POSTFIX ".so.%u"
442 # endif
443 mode = getenv ("LD_BIND_NOW") ? RTLD_NOW : RTLD_LAZY;
444 #elif defined(HAVE_SHL_LOAD)
445 # define PREFIX "libsane-"
446 # define POSTFIX ".sl.%u"
447 mode = BIND_DEFERRED;
448 #elif defined(HAVE_NSLINKMODULE)
449 # define PREFIX "libsane-"
450 # define POSTFIX ".%u.so"
451 mode = NSLINKMODULE_OPTION_RETURN_ON_ERROR + NSLINKMODULE_OPTION_PRIVATE;
452 #else
453 # error "Tried to compile unsupported DLL."
454 #endif /* HAVE_DLOPEN */
455
456 /* initialize all ops to "unsupported" so we can "use" the backend
457 even if the stuff later in this function fails */
458 be->loaded = 1;
459 be->handle = 0;
460 for (i = 0; i < NUM_OPS; ++i)
461 be->op[i] = op_unsupported;
462
463 path = getenv ("LD_LIBRARY_PATH");
464 if (!path)
465 path = getenv ("SHLIB_PATH"); /* for HP-UX */
466 if (!path)
467 path = getenv ("LIBPATH"); /* for AIX */
468
469 if (path)
470 {
471 src_len = strlen (path) + strlen (DIR_SEP) + strlen(LIBDIR) + 1;
472 src = malloc (src_len);
473 if (!src)
474 {
475 DBG (1, "load: malloc failed: %s\n", strerror (errno));
476 return SANE_STATUS_NO_MEM;
477 }
478 snprintf (src, src_len, "%s%s%s", path, DIR_SEP, LIBDIR);
479 }
480 else
481 {
482 src = LIBDIR;
483 src = strdup (src);
484 if (!src)
485 {
486 DBG (1, "load: strdup failed: %s\n", strerror (errno));
487 return SANE_STATUS_NO_MEM;
488 }
489 }
490 DBG (3, "load: searching backend `%s' in `%s'\n", be->name, src);
491
492 orig_src = src;
493 dir = strsep (&src, DIR_SEP);
494
495 while (dir)
496 {
497 #ifdef HAVE_OS2_H /* only max 7.3 names work with dlopen() for DLLs on OS/2 */
498 snprintf (libname, sizeof (libname), "%s/" PREFIX "%.2s%.5s" POSTFIX,
499 dir, be->name, strlen(be->name)>7 ? (be->name)+strlen(be->name)-5 :
500 (be->name)+2, V_MAJOR);
501 #else
502 snprintf (libname, sizeof (libname), "%s/" PREFIX "%s" POSTFIX,
503 dir, be->name, V_MAJOR);
504 #endif
505 DBG (4, "load: trying to load `%s'\n", libname);
506 fp = fopen (libname, "r");
507 if (fp)
508 break;
509 DBG (4, "load: couldn't open `%s' (%s)\n", libname, strerror (errno));
510
511 #ifdef ALT_POSTFIX
512 /* Some platforms have two ways of storing their libraries, try both
513 postfixes */
514 snprintf (libname, sizeof (libname), "%s/" PREFIX "%s" ALT_POSTFIX,
515 dir, be->name, V_MAJOR);
516 DBG (4, "load: trying to load `%s'\n", libname);
517 fp = fopen (libname, "r");
518 if (fp)
519 break;
520 DBG (4, "load: couldn't open `%s' (%s)\n", libname, strerror (errno));
521 #endif
522
523 dir = strsep (&src, DIR_SEP);
524 }
525 if (orig_src)
526 free (orig_src);
527 if (!fp)
528 {
529 DBG (1, "load: couldn't find backend `%s' (%s)\n",
530 be->name, strerror (errno));
531 return SANE_STATUS_INVAL;
532 }
533 fclose (fp);
534 DBG (3, "load: dlopen()ing `%s'\n", libname);
535
536 #ifdef HAVE_DLOPEN
537 be->handle = dlopen (libname, mode);
538 #elif defined(HAVE_SHL_LOAD)
539 be->handle = (shl_t) shl_load (libname, mode, 0L);
540 #elif defined(HAVE_NSLINKMODULE)
541 {
542 NSObjectFileImage objectfile_img = NULL;
543 if (NSCreateObjectFileImageFromFile (libname, &objectfile_img)
544 == NSObjectFileImageSuccess)
545 {
546 be->handle = NSLinkModule (objectfile_img, libname, mode);
547 NSDestroyObjectFileImage (objectfile_img);
548 }
549 }
550 #else
551 # error "Tried to compile unsupported DLL."
552 #endif /* HAVE_DLOPEN */
553 if (!be->handle)
554 {
555 #ifdef HAVE_DLOPEN
556 DBG (1, "load: dlopen() failed (%s)\n", dlerror ());
557 #elif defined(HAVE_NSLINKMODULE)
558 DBG (1, "load: dyld error (%s)\n", dyld_get_error_str ());
559 #else
560 DBG (1, "load: dlopen() failed (%s)\n", strerror (errno));
561 #endif
562 return SANE_STATUS_INVAL;
563 }
564
565 /* all is dandy---lookup and fill in backend ops: */
566 funcname = alloca (strlen (be->name) + 64);
567 for (i = 0; i < NUM_OPS; ++i)
568 {
569 void *(*op) (void);
570
571 sprintf (funcname, "_sane_%s_%s", be->name, op_name[i]);
572
573 /* First try looking up the symbol without a leading underscore. */
574 #ifdef HAVE_DLOPEN
575 op = posix_dlsym (be->handle, funcname + 1);
576 #elif defined(HAVE_SHL_LOAD)
577 shl_findsym ((shl_t *) & (be->handle), funcname + 1, TYPE_UNDEFINED,
578 &op);
579 #elif defined(HAVE_NSLINKMODULE)
580 {
581 NSSymbol *nssym = NSLookupSymbolInModule (be->handle, funcname);
582 if (!nssym)
583 {
584 DBG (15, "dyld error: %s\n", dyld_get_error_str ());
585 }
586 else
587 {
588 op = (void *(*)(void)) NSAddressOfSymbol (nssym);
589 }
590 }
591 #else
592 # error "Tried to compile unsupported DLL."
593 #endif /* HAVE_DLOPEN */
594 if (op)
595 be->op[i] = op;
596 else
597 {
598 /* Try again, with an underscore prepended. */
599 #ifdef HAVE_DLOPEN
600 op = posix_dlsym (be->handle, funcname);
601 #elif defined(HAVE_SHL_LOAD)
602 shl_findsym (be->handle, funcname, TYPE_UNDEFINED, &op);
603 #elif defined(HAVE_NSLINKMODULE)
604 {
605 NSSymbol *nssym = NSLookupSymbolInModule (be->handle, funcname);
606 if (!nssym)
607 {
608 DBG (15, "dyld error: %s\n", dyld_get_error_str ());
609 }
610 else
611 {
612 op = (void *(*)(void)) NSAddressOfSymbol (nssym);
613 }
614 }
615 #else
616 # error "Tried to compile unsupported DLL."
617 #endif /* HAVE_DLOPEN */
618 if (op)
619 be->op[i] = op;
620 }
621 if (NULL == op)
622 DBG (1, "load: unable to find %s\n", funcname);
623 }
624
625 return SANE_STATUS_GOOD;
626
627 # undef PREFIX
628 # undef POSTFIX
629 #else /* HAVE_DLL */
630 DBG (1,
631 "load: ignoring attempt to load `%s'; compiled without dl support\n",
632 be->name);
633 return SANE_STATUS_UNSUPPORTED;
634 #endif /* HAVE_DLL */
635 }
636 #endif /* __BEOS__ */
637
638 static SANE_Status
init(struct backend * be)639 init (struct backend *be)
640 {
641 SANE_Status status;
642 SANE_Int version;
643
644 if (!be->loaded)
645 {
646 status = load (be);
647 if (status != SANE_STATUS_GOOD)
648 return status;
649 }
650
651 DBG (3, "init: initializing backend `%s'\n", be->name);
652
653 status = (*(op_init_t)be->op[OP_INIT]) (&version, auth_callback);
654 if (status != SANE_STATUS_GOOD)
655 return status;
656
657 if (SANE_VERSION_MAJOR (version) != SANE_CURRENT_MAJOR)
658 {
659 DBG (1,
660 "init: backend `%s' has a wrong major version (%d instead of %d)\n",
661 be->name, SANE_VERSION_MAJOR (version), SANE_CURRENT_MAJOR);
662 return SANE_STATUS_INVAL;
663 }
664 DBG (4, "init: backend `%s' is version %d.%d.%d\n", be->name,
665 SANE_VERSION_MAJOR (version), SANE_VERSION_MINOR (version),
666 SANE_VERSION_BUILD (version));
667
668 be->inited = 1;
669
670 return SANE_STATUS_GOOD;
671 }
672
673
674 static void
add_alias(const char * line_param)675 add_alias (const char *line_param)
676 {
677 #ifndef __BEOS__
678 const char *command;
679 enum
680 { CMD_ALIAS, CMD_HIDE }
681 cmd;
682 const char *oldname, *oldend, *newname;
683 size_t oldlen, newlen;
684 struct alias *alias;
685 char *line;
686
687 command = sanei_config_skip_whitespace (line_param);
688 if (!*command)
689 return;
690
691 line = strchr (command, '#');
692 if (line)
693 *line = '\0';
694
695 line = strpbrk (command, " \t");
696 if (!line)
697 return;
698 *line++ = '\0';
699
700 if (strcmp (command, "alias") == 0)
701 cmd = CMD_ALIAS;
702 else if (strcmp (command, "hide") == 0)
703 cmd = CMD_HIDE;
704 else
705 return;
706
707 newlen = 0;
708 newname = NULL;
709 if (cmd == CMD_ALIAS)
710 {
711 char *newend;
712
713 newname = sanei_config_skip_whitespace (line);
714 if (!*newname)
715 return;
716 if (*newname == '\"')
717 {
718 ++newname;
719 newend = strchr (newname, '\"');
720 }
721 else
722 newend = strpbrk (newname, " \t");
723 if (!newend)
724 return;
725
726 newlen = newend - newname;
727 line = (char *) (newend + 1);
728 }
729
730 oldname = sanei_config_skip_whitespace (line);
731 if (!*oldname)
732 return;
733 oldend = oldname + strcspn (oldname, " \t");
734
735 oldlen = oldend - oldname;
736
737 alias = malloc (sizeof (struct alias));
738 if (alias)
739 {
740 alias->oldname = malloc (oldlen + newlen + 2);
741 if (alias->oldname)
742 {
743 strncpy (alias->oldname, oldname, oldlen);
744 alias->oldname[oldlen] = '\0';
745 if (cmd == CMD_ALIAS)
746 {
747 alias->newname = alias->oldname + oldlen + 1;
748 strncpy (alias->newname, newname, newlen);
749 alias->newname[newlen] = '\0';
750 }
751 else
752 alias->newname = NULL;
753
754 alias->next = first_alias;
755 first_alias = alias;
756 return;
757 }
758 free (alias);
759 }
760 return;
761 #endif
762 }
763
764
765 static void
read_config(const char * conffile)766 read_config (const char *conffile)
767 {
768 FILE *fp;
769 char config_line[PATH_MAX];
770 char *backend_name;
771
772 fp = sanei_config_open (conffile);
773 if (!fp)
774 {
775 DBG (1, "sane_init/read_config: Couldn't open config file (%s): %s\n",
776 conffile, strerror (errno));
777 return; /* don't insist on config file */
778 }
779
780 DBG (5, "sane_init/read_config: reading %s\n", conffile);
781 while (sanei_config_read (config_line, sizeof (config_line), fp))
782 {
783 char *comment;
784 SANE_String_Const cp;
785
786 cp = sanei_config_get_string (config_line, &backend_name);
787 /* ignore empty lines */
788 if (!backend_name || cp == config_line)
789 {
790 if (backend_name)
791 free (backend_name);
792 continue;
793 }
794 /* ignore line comments */
795 if (backend_name[0] == '#')
796 {
797 free (backend_name);
798 continue;
799 }
800 /* ignore comments after backend names */
801 comment = strchr (backend_name, '#');
802 if (comment)
803 *comment = '\0';
804 add_backend (backend_name, 0);
805 free (backend_name);
806 }
807 fclose (fp);
808 }
809
810 static void
read_dlld(void)811 read_dlld (void)
812 {
813 DIR *dlld;
814 struct dirent *dllconf;
815 struct stat st;
816 char dlldir[PATH_MAX];
817 char conffile[PATH_MAX + strlen("/") + NAME_MAX];
818 size_t len, plen;
819 const char *dir_list;
820 char *copy, *next, *dir;
821
822 dir_list = sanei_config_get_paths ();
823 if (!dir_list)
824 {
825 DBG(2, "sane_init/read_dlld: Unable to detect configuration directories\n");
826 return;
827 }
828
829 copy = strdup (dir_list);
830
831 for (next = copy; (dir = strsep (&next, DIR_SEP)) != NULL;)
832 {
833 snprintf (dlldir, sizeof (dlldir), "%s%s", dir, "/dll.d");
834
835 DBG(4, "sane_init/read_dlld: attempting to open directory `%s'\n", dlldir);
836
837 dlld = opendir (dlldir);
838 if (dlld)
839 {
840 /* length of path to parent dir of dll.d/ */
841 plen = strlen (dir) + 1;
842
843 DBG(3, "sane_init/read_dlld: using config directory `%s'\n", dlldir);
844 break;
845 }
846 }
847 free (copy);
848
849 if (dlld == NULL)
850 {
851 DBG (1, "sane_init/read_dlld: opendir failed: %s\n",
852 strerror (errno));
853 return;
854 }
855
856 while ((dllconf = readdir (dlld)) != NULL)
857 {
858 /* dotfile (or directory) */
859 if (dllconf->d_name[0] == '.')
860 continue;
861
862 len = strlen (dllconf->d_name);
863
864 /* backup files */
865 if ((dllconf->d_name[len-1] == '~')
866 || (dllconf->d_name[len-1] == '#'))
867 continue;
868
869 snprintf (conffile, sizeof(conffile), "%s/%s", dlldir, dllconf->d_name);
870
871 DBG (5, "sane_init/read_dlld: considering %s\n", conffile);
872
873 if (stat (conffile, &st) != 0)
874 continue;
875
876 if (!S_ISREG (st.st_mode))
877 continue;
878
879 /* expects a path relative to PATH_SANE_CONFIG_DIR */
880 read_config (conffile+plen);
881 }
882
883 closedir (dlld);
884
885 DBG (5, "sane_init/read_dlld: done.\n");
886 }
887
888 SANE_Status
sane_init(SANE_Int * version_code,SANE_Auth_Callback authorize)889 sane_init (SANE_Int * version_code, SANE_Auth_Callback authorize)
890 {
891 #ifndef __BEOS__
892 char config_line[PATH_MAX];
893 size_t len;
894 FILE *fp;
895 int i;
896 #else
897 DIR *dir;
898 struct dirent *dirent;
899 char path[1024];
900 directory_which which[3] = { B_USER_ADDONS_DIRECTORY, B_COMMON_ADDONS_DIRECTORY, B_BEOS_ADDONS_DIRECTORY };
901 int i;
902 #endif
903
904 DBG_INIT ();
905
906 auth_callback = authorize;
907
908 DBG (1, "sane_init: SANE dll backend version %s from %s\n", DLL_VERSION,
909 PACKAGE_STRING);
910
911 #ifndef __BEOS__
912 /* chain preloaded backends together: */
913 for (i = 0; i < NELEMS (preloaded_backends); ++i)
914 {
915 if (!preloaded_backends[i].name)
916 continue;
917 DBG (3, "sane_init: adding backend `%s' (preloaded)\n", preloaded_backends[i].name);
918 preloaded_backends[i].next = first_backend;
919 first_backend = &preloaded_backends[i];
920 }
921
922 /* Return the version number of the sane-backends package to allow
923 the frontend to print them. This is done only for net and dll,
924 because these backends are usually called by the frontend. */
925 if (version_code)
926 *version_code = SANE_VERSION_CODE (SANE_DLL_V_MAJOR, SANE_DLL_V_MINOR,
927 SANE_DLL_V_BUILD);
928
929 /*
930 * Read dll.conf & dll.d
931 * Read dll.d first, so that the extras backends will be tried last
932 */
933 read_dlld ();
934 read_config (DLL_CONFIG_FILE);
935
936 fp = sanei_config_open (DLL_ALIASES_FILE);
937 if (!fp)
938 return SANE_STATUS_GOOD; /* don't insist on aliases file */
939
940 DBG (5, "sane_init: reading %s\n", DLL_ALIASES_FILE);
941 while (sanei_config_read (config_line, sizeof (config_line), fp))
942 {
943 if (config_line[0] == '#') /* ignore line comments */
944 continue;
945
946 len = strlen (config_line);
947 if (!len)
948 continue; /* ignore empty lines */
949
950 add_alias (config_line);
951 }
952 fclose (fp);
953
954 #else
955 /* no ugly config files, just get scanners from their ~/config/add-ons/SANE */
956 /* look for drivers */
957 for (i = 0; i < 3; i++)
958 {
959 if (find_directory(which[i],0,true,path,1024) < B_OK)
960 continue;
961 strcat(path,"/SANE/");
962 dir=opendir(path);
963 if(!dir) continue;
964
965 while((dirent=readdir(dir)))
966 {
967 if((strcmp(dirent->d_name,".")==0) || (strcmp(dirent->d_name,"..")==0)) continue;
968 if((strcmp(dirent->d_name,"dll")==0)) continue;
969 add_backend(dirent->d_name,0);
970 }
971 closedir(dir);
972 }
973 #endif /* __BEOS__ */
974
975 return SANE_STATUS_GOOD;
976 }
977
978 void
sane_exit(void)979 sane_exit (void)
980 {
981 struct backend *be, *next;
982 struct alias *alias;
983
984 DBG (2, "sane_exit: exiting\n");
985
986 for (be = first_backend; be; be = next)
987 {
988 next = be->next;
989 if (be->loaded)
990 {
991 if (be->inited)
992 {
993 DBG (3, "sane_exit: calling backend `%s's exit function\n",
994 be->name);
995 (*(op_exit_t)be->op[OP_EXIT]) ();
996 }
997 #ifdef __BEOS__
998 /* use BeOS kernel functions to unload add-ons */
999 if(be->handle) unload_add_on((image_id)be->handle);
1000 #else
1001 #ifdef HAVE_DLL
1002
1003 #ifdef HAVE_DLOPEN
1004 if (be->handle)
1005 dlclose (be->handle);
1006 #elif defined(HAVE_SHL_LOAD)
1007 if (be->handle)
1008 shl_unload (be->handle);
1009 #elif defined(HAVE_NSLINKMODULE)
1010 if (be->handle)
1011 NSUnLinkModule (be->handle, NSUNLINKMODULE_OPTION_NONE
1012 # ifdef __ppc__
1013 | NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES
1014 # endif
1015 );
1016 #else
1017 # error "Tried to compile unsupported DLL."
1018 #endif /* HAVE_DLOPEN */
1019
1020 #endif /* HAVE_DLL */
1021 #endif /* __BEOS__ */
1022 }
1023 if (!be->permanent)
1024 {
1025 if (be->name)
1026 free ((void *) be->name);
1027 free (be);
1028 }
1029 else
1030 {
1031 be->inited = 0;
1032 }
1033 }
1034 first_backend = 0;
1035
1036 while ((alias = first_alias) != NULL)
1037 {
1038 first_alias = first_alias->next;
1039 free (alias->oldname);
1040 free (alias);
1041 }
1042
1043 if (NULL != devlist)
1044 { /* Release memory allocated by sane_get_devices(). */
1045 int i = 0;
1046 while (devlist[i])
1047 free (devlist[i++]);
1048 free (devlist);
1049
1050 devlist = NULL;
1051 devlist_size = 0;
1052 devlist_len = 0;
1053 }
1054 DBG (3, "sane_exit: finished\n");
1055 }
1056
1057 /* Note that a call to get_devices() implies that we'll have to load
1058 all backends. To avoid this, you can call sane_open() directly
1059 (assuming you know the name of the backend/device). This is
1060 appropriate for the command-line interface of SANE, for example.
1061 */
1062 SANE_Status
sane_get_devices(const SANE_Device *** device_list,SANE_Bool local_only)1063 sane_get_devices (const SANE_Device *** device_list, SANE_Bool local_only)
1064 {
1065 const SANE_Device **be_list;
1066 struct backend *be;
1067 SANE_Status status;
1068 char *full_name;
1069 int i, num_devs;
1070 size_t len;
1071 #define ASSERT_SPACE(n) do \
1072 { \
1073 if (devlist_len + (n) > devlist_size) \
1074 { \
1075 devlist_size += (n) + 15; \
1076 if (devlist) \
1077 devlist = realloc (devlist, devlist_size * sizeof (devlist[0])); \
1078 else \
1079 devlist = malloc (devlist_size * sizeof (devlist[0])); \
1080 if (!devlist) \
1081 return SANE_STATUS_NO_MEM; \
1082 } \
1083 } while (0)
1084
1085 DBG (3, "sane_get_devices\n");
1086
1087 if (devlist)
1088 for (i = 0; i < devlist_len; ++i)
1089 free ((void *) devlist[i]);
1090 devlist_len = 0;
1091
1092 for (be = first_backend; be; be = be->next)
1093 {
1094 if (!be->inited)
1095 if (init (be) != SANE_STATUS_GOOD)
1096 continue;
1097
1098 status = (*(op_get_devs_t)be->op[OP_GET_DEVS]) (&be_list, local_only);
1099 if (status != SANE_STATUS_GOOD || !be_list)
1100 continue;
1101
1102 /* count the number of devices for this backend: */
1103 for (num_devs = 0; be_list[num_devs]; ++num_devs);
1104
1105 ASSERT_SPACE (num_devs);
1106
1107 for (i = 0; i < num_devs; ++i)
1108 {
1109 SANE_Device *dev;
1110 char *mem;
1111 struct alias *alias;
1112
1113 for (alias = first_alias; alias != NULL; alias = alias->next)
1114 {
1115 len = strlen (be->name);
1116 if (strlen (alias->oldname) <= len)
1117 continue;
1118 if (strncmp (alias->oldname, be->name, len) == 0
1119 && alias->oldname[len] == ':'
1120 && strcmp (&alias->oldname[len + 1], be_list[i]->name) == 0)
1121 break;
1122 }
1123
1124 if (alias)
1125 {
1126 if (!alias->newname) /* hidden device */
1127 continue;
1128
1129 len = strlen (alias->newname);
1130 mem = malloc (sizeof (*dev) + len + 1);
1131 if (!mem)
1132 return SANE_STATUS_NO_MEM;
1133
1134 full_name = mem + sizeof (*dev);
1135 strcpy (full_name, alias->newname);
1136 }
1137 else
1138 {
1139 /* create a new device entry with a device name that is the
1140 sum of the backend name a colon and the backend's device
1141 name: */
1142 len = strlen (be->name) + 1 + strlen (be_list[i]->name);
1143 mem = malloc (sizeof (*dev) + len + 1);
1144 if (!mem)
1145 return SANE_STATUS_NO_MEM;
1146
1147 full_name = mem + sizeof (*dev);
1148 strcpy (full_name, be->name);
1149 strcat (full_name, ":");
1150 strcat (full_name, be_list[i]->name);
1151 }
1152
1153 dev = (SANE_Device *) mem;
1154 dev->name = full_name;
1155 dev->vendor = be_list[i]->vendor;
1156 dev->model = be_list[i]->model;
1157 dev->type = be_list[i]->type;
1158
1159 devlist[devlist_len++] = dev;
1160 }
1161 }
1162
1163 /* terminate device list with NULL entry: */
1164 ASSERT_SPACE (1);
1165 devlist[devlist_len++] = 0;
1166
1167 *device_list = (const SANE_Device **) devlist;
1168 DBG (3, "sane_get_devices: found %d devices\n", devlist_len - 1);
1169 return SANE_STATUS_GOOD;
1170 }
1171
1172 SANE_Status
sane_open(SANE_String_Const full_name,SANE_Handle * meta_handle)1173 sane_open (SANE_String_Const full_name, SANE_Handle * meta_handle)
1174 {
1175 char *be_name;
1176 const char *dev_name;
1177 struct meta_scanner *s;
1178 SANE_Handle handle;
1179 struct backend *be;
1180 SANE_Status status;
1181 struct alias *alias;
1182
1183 DBG (3, "sane_open: trying to open `%s'\n", full_name);
1184
1185 for (alias = first_alias; alias != NULL; alias = alias->next)
1186 {
1187 if (!alias->newname)
1188 continue;
1189 if (strcmp (alias->newname, full_name) == 0)
1190 {
1191 full_name = alias->oldname;
1192 break;
1193 }
1194 }
1195
1196 dev_name = strchr (full_name, ':');
1197
1198 int is_fakeusb = 0, is_fakeusbdev = 0, is_fakeusbout = 0;
1199
1200 if (dev_name)
1201 {
1202 is_fakeusb = strncmp(full_name, "fakeusb", dev_name - full_name) == 0 &&
1203 dev_name - full_name == 7;
1204 is_fakeusbdev = strncmp(full_name, "fakeusbdev", dev_name - full_name) == 0 &&
1205 dev_name - full_name == 10;
1206 is_fakeusbout = strncmp(full_name, "fakeusbout", dev_name - full_name) == 0 &&
1207 dev_name - full_name == 10;
1208 }
1209
1210 if (is_fakeusb || is_fakeusbdev)
1211 {
1212 ++dev_name; // skip colon
1213 status = sanei_usb_testing_enable_replay(dev_name, is_fakeusbdev);
1214 if (status != SANE_STATUS_GOOD)
1215 return status;
1216
1217 be_name = sanei_usb_testing_get_backend();
1218 if (be_name == NULL)
1219 {
1220 DBG (0, "%s: unknown backend for testing\n", __func__);
1221 return SANE_STATUS_ACCESS_DENIED;
1222 }
1223 }
1224 else
1225 {
1226 char* fakeusbout_path = NULL;
1227 if (is_fakeusbout)
1228 {
1229 ++dev_name; // skip colon
1230
1231 const char* path_end = strchr(dev_name, ':');
1232 if (path_end == NULL)
1233 {
1234 DBG (0, "%s: the device name does not contain path\n", __func__);
1235 return SANE_STATUS_INVAL;
1236 }
1237 fakeusbout_path = strndup(dev_name, path_end - dev_name);
1238
1239 full_name = path_end + 1; // skip colon
1240 dev_name = strchr(full_name, ':');
1241 }
1242
1243 if (dev_name)
1244 {
1245 be_name = strndup(full_name, dev_name - full_name);
1246 ++dev_name; /* skip colon */
1247 }
1248 else
1249 {
1250 /* if no colon interpret full_name as the backend name; an empty
1251 backend device name will cause us to open the first device of
1252 that backend. */
1253 be_name = strdup(full_name);
1254 dev_name = "";
1255 }
1256
1257 if (is_fakeusbout)
1258 {
1259 status = sanei_usb_testing_enable_record(fakeusbout_path, be_name);
1260 free(fakeusbout_path);
1261 if (status != SANE_STATUS_GOOD)
1262 return status;
1263 }
1264 }
1265
1266 if (!be_name)
1267 return SANE_STATUS_NO_MEM;
1268
1269 if (!be_name[0])
1270 be = first_backend;
1271 else
1272 for (be = first_backend; be; be = be->next)
1273 if (strcmp (be->name, be_name) == 0)
1274 break;
1275
1276 if (!be)
1277 {
1278 status = add_backend (be_name, &be);
1279 if (status != SANE_STATUS_GOOD)
1280 {
1281 free(be_name);
1282 return status;
1283 }
1284 }
1285 free(be_name);
1286
1287 if (!be->inited)
1288 {
1289 status = init (be);
1290 if (status != SANE_STATUS_GOOD)
1291 return status;
1292 }
1293
1294 status = (*(op_open_t)be->op[OP_OPEN]) (dev_name, &handle);
1295 if (status != SANE_STATUS_GOOD)
1296 return status;
1297
1298 s = calloc (1, sizeof (*s));
1299 if (!s)
1300 return SANE_STATUS_NO_MEM;
1301
1302 s->be = be;
1303 s->handle = handle;
1304 *meta_handle = s;
1305
1306 DBG (3, "sane_open: open successful\n");
1307 return SANE_STATUS_GOOD;
1308 }
1309
1310 void
sane_close(SANE_Handle handle)1311 sane_close (SANE_Handle handle)
1312 {
1313 struct meta_scanner *s = handle;
1314
1315 DBG (3, "sane_close(handle=%p)\n", handle);
1316 (*(op_close_t)s->be->op[OP_CLOSE]) (s->handle);
1317 free (s);
1318 }
1319
1320 const SANE_Option_Descriptor *
sane_get_option_descriptor(SANE_Handle handle,SANE_Int option)1321 sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
1322 {
1323 struct meta_scanner *s = handle;
1324
1325 DBG (3, "sane_get_option_descriptor(handle=%p,option=%d)\n", handle,
1326 option);
1327 return (*(op_get_option_desc_t)s->be->op[OP_GET_OPTION_DESC]) (s->handle, option);
1328 }
1329
1330 SANE_Status
sane_control_option(SANE_Handle handle,SANE_Int option,SANE_Action action,void * value,SANE_Word * info)1331 sane_control_option (SANE_Handle handle, SANE_Int option,
1332 SANE_Action action, void *value, SANE_Word * info)
1333 {
1334 struct meta_scanner *s = handle;
1335
1336 DBG (3,
1337 "sane_control_option(handle=%p,option=%d,action=%d,value=%p,info=%p)\n",
1338 handle, option, action, value, (void *) info);
1339 return (*(op_ctl_option_t)s->be->op[OP_CTL_OPTION]) (s->handle, option, action, value,
1340 info);
1341 }
1342
1343 SANE_Status
sane_get_parameters(SANE_Handle handle,SANE_Parameters * params)1344 sane_get_parameters (SANE_Handle handle, SANE_Parameters * params)
1345 {
1346 struct meta_scanner *s = handle;
1347
1348 DBG (3, "sane_get_parameters(handle=%p,params=%p)\n", handle, (void *) params);
1349 return (*(op_get_params_t)s->be->op[OP_GET_PARAMS]) (s->handle, params);
1350 }
1351
1352 SANE_Status
sane_start(SANE_Handle handle)1353 sane_start (SANE_Handle handle)
1354 {
1355 struct meta_scanner *s = handle;
1356
1357 DBG (3, "sane_start(handle=%p)\n", handle);
1358 return (*(op_start_t)s->be->op[OP_START]) (s->handle);
1359 }
1360
1361 SANE_Status
sane_read(SANE_Handle handle,SANE_Byte * data,SANE_Int max_length,SANE_Int * length)1362 sane_read (SANE_Handle handle, SANE_Byte * data, SANE_Int max_length,
1363 SANE_Int * length)
1364 {
1365 struct meta_scanner *s = handle;
1366
1367 DBG (3, "sane_read(handle=%p,data=%p,maxlen=%d,lenp=%p)\n",
1368 handle, (void *) data, max_length, (void *) length);
1369 return (*(op_read_t)s->be->op[OP_READ]) (s->handle, data, max_length, length);
1370 }
1371
1372 void
sane_cancel(SANE_Handle handle)1373 sane_cancel (SANE_Handle handle)
1374 {
1375 struct meta_scanner *s = handle;
1376
1377 DBG (3, "sane_cancel(handle=%p)\n", handle);
1378 (*(op_cancel_t)s->be->op[OP_CANCEL]) (s->handle);
1379 }
1380
1381 SANE_Status
sane_set_io_mode(SANE_Handle handle,SANE_Bool non_blocking)1382 sane_set_io_mode (SANE_Handle handle, SANE_Bool non_blocking)
1383 {
1384 struct meta_scanner *s = handle;
1385
1386 DBG (3, "sane_set_io_mode(handle=%p,nonblocking=%d)\n", handle,
1387 non_blocking);
1388 return (*(op_set_io_mode_t)s->be->op[OP_SET_IO_MODE]) (s->handle, non_blocking);
1389 }
1390
1391 SANE_Status
sane_get_select_fd(SANE_Handle handle,SANE_Int * fd)1392 sane_get_select_fd (SANE_Handle handle, SANE_Int * fd)
1393 {
1394 struct meta_scanner *s = handle;
1395
1396 DBG (3, "sane_get_select_fd(handle=%p,fdp=%p)\n", handle, (void *) fd);
1397 return (*(op_get_select_fd_t)s->be->op[OP_GET_SELECT_FD]) (s->handle, fd);
1398 }
1399