Check the IP address of the remote host before any communication occurs.

Check for a errors before trsuting values that came from remote.  Make sure
that strings are 0-terminated.
RELEASE_1_0_11_BRANCH
Henning Geinitz 2003-02-09 13:52:14 +00:00
rodzic af92ce6fd8
commit 2a635c33ed
12 zmienionych plików z 628 dodań i 185 usunięć

Wyświetl plik

@ -1,3 +1,10 @@
2003-02-09 Henning Meier-Geinitz <henning@meier-geinitz.de>
* frontend/saned.c sanei/sanei_codec_bin.c sanei/sanei_wire.c: Check
the IP address of the remote host before any communication occurs.
Check for a errors before trsuting values that came from remote.
Make sure that strings are 0-terminated.
****** Release of sane-backends 1.0.10. End of code freeze ******
2003-02-01 Henning Meier-Geinitz <henning@meier-geinitz.de>

Wyświetl plik

@ -1,59 +0,0 @@
; SANE Backend specification file
;
; It's basically emacs-lisp --- so ";" indicates comment to end of line.
; All syntactic elements are keyword tokens, followed by a string or
; keyword argument, as specified.
;
; ":backend" *must* be specified.
; All other information is optional (but what good is the file without it?).
:backend "avision" ; name of backend
:version "0.3.1" ; version of backend
:status :beta ; :alpha, :beta, :stable, :new
:url "http://drocklinux.dyndns.org/rene/avision/index.html" ; backend's web page
:manpage "sane-avision" ; name of manpage (if it exists)
:devicetype :scanner
:mfg "Avision" ; name a manufacturer
:url "http://www.avision.com/"
:model "AV 6240" ; name models for above-specified mfg.
:interface "SCSI"
:comment "1 pass, ??? DPI"
:model "AV 630 CS"
:interface "SCSI"
:comment "1 pass, 600 DPI"
:model "AV 620 CS"
:interface "SCSI"
:comment "1 pass, 600 DPI"
:mfg "HP"
:url "http://www.hp.com/"
:model "HP 5300"
:interface "USB"
:comment "1 pass, 600 DPI"
:model "HP 5370c"
:interface "USB"
:comment "1 pass, 600 DPI"
:model "HP 7400"
:interface "USB"
:comment "1 pass, 1200 DPI"
:mfg "MINOLTA"
:url "http://www.minolta.com/"
:model "FS-V1"
:interface "USB"
:comment "1 pass, 2820 DPI, film-scanner"
:mfg "Mitsubishi"
:model "MCA-S600C"
:interface "SCSI
:model "MCA-SS600"
:interface "SCSI"

Wyświetl plik

@ -183,6 +183,12 @@ auth_callback (SANE_String_Const res,
return;
}
if (wire.status)
{
DBG(DBG_ERR, "auth_callback: bad status %d\n", wire.status);
return;
}
switch (current_request)
{
case SANE_NET_OPEN:
@ -222,10 +228,24 @@ auth_callback (SANE_String_Const res,
current_request, res);
break;
}
if (wire.status)
{
DBG(DBG_ERR, "auth_callback: bad status %d\n", wire.status);
return;
}
reset_watchdog ();
sanei_w_set_dir (&wire, WIRE_DECODE);
sanei_w_word (&wire, &word);
if (wire.status)
{
DBG(DBG_ERR, "auth_callback: bad status %d\n", wire.status);
return;
}
procnum = word;
if (procnum != SANE_NET_AUTHORIZE)
{
@ -237,6 +257,12 @@ auth_callback (SANE_String_Const res,
}
sanei_w_authorization_req (&wire, &req);
if (wire.status)
{
DBG(DBG_ERR, "auth_callback: bad status %d\n", wire.status);
return;
}
if (req.username)
strcpy (username, req.username);
if (req.password)
@ -514,30 +540,51 @@ init (Wire * w)
reset_watchdog ();
sanei_w_set_dir (w, WIRE_DECODE);
sanei_w_word (w, &word); /* decode procedure number */
sanei_w_init_req (w, &req);
w->version = SANEI_NET_PROTOCOL_VERSION;
status = check_host (w->io.fd);
if (status != SANE_STATUS_GOOD)
{
DBG (DBG_WARN, "init: access by host %s denied\n", remote_hostname);
return -1;
}
sanei_w_set_dir (w, WIRE_DECODE);
if (w->status)
{
DBG (DBG_ERR, "init: bad status after sanei_w_set_dir: %d\n", w->status);
return -1;
}
sanei_w_word (w, &word); /* decode procedure number */
if (w->status || word != SANE_NET_INIT)
{
DBG (DBG_ERR, "init: bad status=%d or procnum=%d\n",
w->status, word);
return -1;
}
sanei_w_init_req (w, &req);
if (w->status)
{
DBG (DBG_ERR, "init: bad status after sanei_w_init_req: %d\n", w->status);
return -1;
}
w->version = SANEI_NET_PROTOCOL_VERSION;
if (req.username)
default_username = strdup (req.username);
sanei_w_free (w, (WireCodecFunc) sanei_w_init_req, &req);
if (w->status)
{
DBG (DBG_ERR, "init: bad status after sanei_w_free: %d\n", w->status);
return -1;
}
reply.version_code = SANE_VERSION_CODE (V_MAJOR, V_MINOR,
SANEI_NET_PROTOCOL_VERSION);
status = check_host (w->io.fd);
DBG (DBG_WARN, "init: access by %s@%s %s\n",
default_username, remote_hostname,
(status == SANE_STATUS_GOOD) ? "accepted" : "rejected");
DBG (DBG_WARN, "init: access by %s@%s accepted\n",
default_username, remote_hostname);
if (status == SANE_STATUS_GOOD)
{
@ -823,6 +870,14 @@ process_request (Wire * w)
DBG (DBG_DBG, "process_request: waiting for request\n");
sanei_w_set_dir (w, WIRE_DECODE);
sanei_w_word (w, &word); /* decode procedure number */
if (w->status)
{
DBG (DBG_ERR,
"process_request: bad status %d\n", w->status);
quit (0);
}
current_request = word;
DBG (DBG_MSG, "process_request: got request %d\n", current_request);

Wyświetl plik

@ -15,28 +15,113 @@
You should have received a copy of the GNU General Public License
along with sane; see the file COPYING. If not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
This file declares SANE internal routines that are provided to
simplify backend implementation. */
/** @file sanei.h
* Convenience macros and function declarations for backends
* @sa sanei_backend.h sanei_thread.h
*/
/* Doxygen documentation */
/** @mainpage SANEI (SANE internal routines) documentation
*
* @image html ../sane-logo2.jpg
* @section intro Introduction
*
* The header files in the include/sane/ directory named sanei_*.h provide
* function declarations and macros that can be used by every SANE backend.
* Their implementations can be found in the sanei/ directory. The code aims
* to be platform-independent to avoid lots of \#ifdef code in the backends.
* Please use the SANEI functions wherever possible.
*
* This documentation was created by the use of doxygen, the
* doc/doxygen-sanei.conf configuration file and dcoumentation in the sanei_*.h
* files.
*
* This documenation is far from complete. Any help is appreciated.
*
* @section additional Additional documentation
* - The SANE standard can be found at <a
* href="http://www.mostang.com/sane/html/">the SANE webserver</a>.
* - Information on how to write a backend: <a
* href="../backend-writing.txt">backend-writing.txt</a>.
* - General SANE documentation is on <a
* href="http://www.mostang.com/sane/docs.html>the SANE documentation
* page</a>.
*
* @section contact Contact
*
* The common way to contact the developers of SANE is the sane-devel
* mailing list. See the <a
* href="http://www.mostang.com/sane/mail.html">mailing list webpage</a>
* for details. That's the place to ask questions, report bugs, or announce
* a new backend.
*
*/
#ifndef sanei_h
#define sanei_h
#include <sane/sane.h>
/* A few convenience macros: */
/** @name Public macros and functions
* @{
*/
/** @def STRINGIFY(x)
* Turn parameter into string.
*/
/** @def PASTE(x,y)
* Concatenate parameters.
*
*/
/** @def NELEMS(a)
* Return number of elements of an array.
*
*/
/** @fn extern SANE_Status sanei_constrain_value (const SANE_Option_Descriptor * opt, void * value, SANE_Word * info);
* Check the constraints of a SANE option and adjust its value if necessary.
*
* Depending on the type of the option and constraint, value is modified
* to fit inside constraint.
*
* @param opt option to check
* @param value value of the option
* @param info info is set to SANE_INFO_INEXACT if value was changed
*
* @return
* - SANE_STATUS_GOOD - on success
* - SANE_STATUS_INVAL - if the function wasn't able to fit value into the
* constraint or any other error occured
*/
/* @} */
/** @name Private macros
* @{
*/
/** @def STRINGIFY1(x)
* Internal use only.
*/
/** @def PASTE1(x,y)
* Internal use only.
*/
/* @} */
/* A few convenience macros: */
/** @hideinitializer */
#define NELEMS(a) ((int)(sizeof (a) / sizeof (a[0])))
/** @hideinitializer */
#define STRINGIFY1(x) #x
/** @hideinitializer */
#define STRINGIFY(x) STRINGIFY1(x)
/** @hideinitializer */
#define PASTE1(x,y) x##y
/** @hideinitializer */
#define PASTE(x,y) PASTE1(x,y)
#define NELEMS(a) ((int)(sizeof (a) / sizeof (a[0])))
extern SANE_Status sanei_constrain_value (const SANE_Option_Descriptor * opt,
void * value, SANE_Word * info);
extern int sanei_save_values (int fd, SANE_Handle device);
extern int sanei_load_values (int fd, SANE_Handle device);
#endif /* sanei_h */

Wyświetl plik

@ -37,6 +37,25 @@
If you write modifications of your own for SANE, it is your choice
whether to permit this exception to apply to your modifications.
If you do not wish that, delete this exception notice. */
/** @file sanei_ab306.h
* Support for the Mustek-proprietary SCSI-over-parallel-port
* interface AB306.
*
* This chip is used by the Mustek Paragon 600 II N. It's similar to a parport
* but has it's own ISA card and cable.
*
* /dev/port access is used where available. If this doesn't work, inb/outb
* functions or inb/outb assembler code is used.
*
* Depending on the operating system it may be necessary to run this code as
* root.
*
* @sa sanei_pio.h sanei_scsi.h sanei_usb.h
*/
#ifndef sanei_ab306_h
#define sanei_ab306_h
@ -44,14 +63,95 @@
#include <sane/sane.h>
/**
* Open the connection to an AB306 device.
*
* The scanner is also turned on.
*
* @param dev Port address as text.
* @param fd Information about port address and I/O method. fd is not a file
* descriptor. The name and type are used for compatibility reasons.
*
* @return
* - SANE_STATUS_GOOD - on success
* - SANE_STATUS_INVAL - if the port address can't be interpreted
* - SANE_STATUS_IO_ERROR - if the device file for a port couldn't be accessed
*/
SANE_Status sanei_ab306_open (const char *dev, int *fd);
/**
* Close the connection to an AB306 device.
*
* @param fd Information about port address and I/O method.
*
*/
void sanei_ab306_close (int fd);
/**
* Exit ab306.
*
* Also powers down all devices.
*
*/
void sanei_ab306_exit (void);
/**
* Get the permission for direct access to the ports.
*
* The only occasion this function must be called, is when the I/O privilege
* was lost, e.g. after forking. Otherwise, it's called automatically by
* sanei_ab306_open().
*
* @param fd Information about port address and I/O method.
*
* @return
* - SANE_STATUS_GOOD - on success
* - SANE_STATUS_IO_ERROR - if the i/o privilege was denied by the operating
* system
*/
SANE_Status sanei_ab306_get_io_privilege (int fd);
/**
* Find out if the device is ready to accept new commands.
*
* @param fd Information about port address and I/O method.
*
* @return
* - SANE_STATUS_GOOD - if the device is ready
* - SANE_STATUS_DEVICE_BUSY if the device is still busy (try again later)
*/
SANE_Status sanei_ab306_test_ready (int fd);
/**
* Send a command to the AB306 device.
*
* @param fd Information about port address and I/O method.
* @param src Data to be sent to the device.
* @param src_size Size of data to be sent to the device.
* @param dst Data to be received from the device.
* @param dst_size Size of data to be received from the device
*
* @return
* - SANE_STATUS_GOOD - on success
* - SANE_STATUS_IO_ERROR - if an error occured during the dialog with the
* device
*/
SANE_Status sanei_ab306_cmd (int fd, const void *src, size_t src_size,
void *dst, size_t *dst_size);
/**
* Read scanned image data.
*
* @param fd Information about port address and I/O method.
* @param planes Bytes per pixel (3 for color, 1 for all other modes)
* @param buf Buffer for image data.
* @param lines Number of lines
* @param bpl Bytes per line
*
* @return
* - SANE_STATUS_GOOD - on success
* - SANE_STATUS_IO_ERROR - if an error occured during the dialog with the
* device
*/
SANE_Status sanei_ab306_rdata (int fd, int planes,
SANE_Byte *buf, int lines, int bpl);

Wyświetl plik

@ -1,35 +1,45 @@
/** @file sanei_backend.h
* Compatibility header file for backends
*
* This file provides some defines for macros missing on some platforms.
* It also has the SANE API entry points. sanei_backend.h muste be included
* by every backend.
*
* @sa sanei.h sanei_thread.h
*/
/** @name Compatibility macros
* @{
*/
#include <sane/sanei_debug.h>
#ifdef HAVE_SYS_HW_H
/* OS/2 i/o-port access compatibility macros: */
# define inb(p) _inp8 (p)
# define outb(v,p) _outp8 ((p),(v))
# define ioperm(b,l,o) _portaccess ((b),(b)+(l)-1)
# define HAVE_IOPERM 1
# define inb(p) _inp8 (p)
# define outb(v,p) _outp8 ((p),(v))
# define ioperm(b,l,o) _portaccess ((b),(b)+(l)-1)
# define HAVE_IOPERM 1
#endif
#ifndef HAVE_OS2_H
#include <fcntl.h>
#ifndef O_NONBLOCK
# ifdef O_NDELAY
# define O_NONBLOCK O_NDELAY
# else
# define O_NONBLOCK FNDELAY /* last resort */
# define O_NONBLOCK FNDELAY /* last resort */
# endif
#endif
#endif /* HAVE_OS2_H */
#ifndef __GLIBC__
# ifndef u_int8_t
# define u_int8_t unsigned char
# endif
# ifndef u_int16_t
# define u_int16_t unsigned short
# endif
# ifndef u_int32_t
# define u_int32_t unsigned int
# endif
#include <limits.h>
#ifndef PATH_MAX
# define PATH_MAX 1024
#endif
#ifdef HAVE_SIGPROCMASK
# define SIGACTION sigaction
# define SIGACTION sigaction
#else
/* Just enough backwards compatibility that we get by in the backends
@ -62,35 +72,38 @@
# undef SIG_SETMASK
# endif
# define sigset_t int
# define sigemptyset(set) do { *(set) = 0; } while (0)
# define sigfillset(set) do { *(set) = ~0; } while (0)
# define sigaddset(set,signal) do { *(set) |= sigmask (signal); } while (0)
# define sigdelset(set,signal) do { *(set) &= ~sigmask (signal); } while (0)
# define sigaction(sig,new,old) sigvec (sig,new,old)
# define sigset_t int
# define sigemptyset(set) do { *(set) = 0; } while (0)
# define sigfillset(set) do { *(set) = ~0; } while (0)
# define sigaddset(set,signal) do { *(set) |= sigmask (signal); } while (0)
# define sigdelset(set,signal) do { *(set) &= ~sigmask (signal); } while (0)
# define sigaction(sig,new,old) sigvec (sig,new,old)
/* Note: it's not safe to just declare our own "struct sigaction" since
some systems (e.g., some versions of OpenStep) declare that structure,
but do not implement sigprocmask(). Hard to believe, aint it? */
# define SIGACTION sigvec
# define SIG_BLOCK 1
# define SIG_UNBLOCK 2
# define SIG_SETMASK 3
# define SIGACTION sigvec
# define SIG_BLOCK 1
# define SIG_UNBLOCK 2
# define SIG_SETMASK 3
#endif /* !HAVE_SIGPROCMASK */
/* @} */
/* Declare the entry points: */
/** @name Declaration of entry points:
* @{
*/
extern SANE_Status ENTRY(init) (SANE_Int *, SANE_Auth_Callback);
extern SANE_Status ENTRY(get_devices) (const SANE_Device ***, SANE_Bool);
extern SANE_Status ENTRY(open) (SANE_String_Const, SANE_Handle *);
extern const SANE_Option_Descriptor *
ENTRY(get_option_descriptor) (SANE_Handle, SANE_Int);
extern SANE_Status ENTRY(control_option) (SANE_Handle, SANE_Int, SANE_Action,
void *, SANE_Word *);
void *, SANE_Word *);
extern SANE_Status ENTRY(get_parameters) (SANE_Handle, SANE_Parameters *);
extern SANE_Status ENTRY(start) (SANE_Handle);
extern SANE_Status ENTRY(read) (SANE_Handle, SANE_Byte *, SANE_Int,
SANE_Int *);
SANE_Int *);
extern SANE_Status ENTRY(set_io_mode) (SANE_Handle, SANE_Bool);
extern SANE_Status ENTRY(get_select_fd) (SANE_Handle, SANE_Int *);
extern void ENTRY(cancel) (SANE_Handle);
@ -100,17 +113,28 @@ extern void ENTRY(exit) (void);
#ifndef STUBS
/* Now redirect sane_* calls to backend's functions: */
#define sane_init(a,b) ENTRY(init) (a,b)
#define sane_get_devices(a,b) ENTRY(get_devices) (a,b)
#define sane_open(a,b) ENTRY(open) (a,b)
#define sane_get_option_descriptor(a,b) ENTRY(get_option_descriptor) (a,b)
#define sane_control_option(a,b,c,d,e) ENTRY(control_option) (a,b,c,d,e)
#define sane_get_parameters(a,b) ENTRY(get_parameters) (a,b)
#define sane_start(a) ENTRY(start) (a)
#define sane_read(a,b,c,d) ENTRY(read) (a,b,c,d)
#define sane_set_io_mode(a,b) ENTRY(set_io_mode) (a,b)
#define sane_get_select_fd(a,b) ENTRY(get_select_fd) (a,b)
#define sane_cancel(a) ENTRY(cancel) (a)
#define sane_close(a) ENTRY(close) (a)
#define sane_exit(a) ENTRY(exit) (a)
#define sane_init(a,b) ENTRY(init) (a,b)
#define sane_get_devices(a,b) ENTRY(get_devices) (a,b)
#define sane_open(a,b) ENTRY(open) (a,b)
#define sane_get_option_descriptor(a,b) ENTRY(get_option_descriptor) (a,b)
#define sane_control_option(a,b,c,d,e) ENTRY(control_option) (a,b,c,d,e)
#define sane_get_parameters(a,b) ENTRY(get_parameters) (a,b)
#define sane_start(a) ENTRY(start) (a)
#define sane_read(a,b,c,d) ENTRY(read) (a,b,c,d)
#define sane_set_io_mode(a,b) ENTRY(set_io_mode) (a,b)
#define sane_get_select_fd(a,b) ENTRY(get_select_fd) (a,b)
#define sane_cancel(a) ENTRY(cancel) (a)
#define sane_close(a) ENTRY(close) (a)
#define sane_exit(a) ENTRY(exit) (a)
#endif /* STUBS */
/* @} */
/** @name Internationalization for SANE backends
* Add SANE_I18N() to all texts that can be translated.
* E.g. out_txt = SANE_I18N("Hello");
* @{
*/
#ifndef SANE_I18N
#define SANE_I18N(text) text
#endif
/* @} */

Wyświetl plik

@ -15,12 +15,27 @@
You should have received a copy of the GNU General Public License
along with sane; see the file COPYING. If not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
This file declares SANE application interface. See the SANE
standard for a detailed explanation of the interface. */
/** @file sanei_codec_ascii.h
* ASCII codec for network and file transmissions
*
* Instead translating data to a byte stream this codec uses ASCII hex numbers.
* Therefore it can be used for streams that are not 8-bit clean or which can
* only use printable characters. It's currently used for saving/restoring
* data to/from disk.
*
* @sa sanei_codec_bin.h sanei_net.h sanei_wire.h
*/
#ifndef sanei_codec_ascii_h
#define sanei_codec_ascii_h
/** Initialize the ascii codec
*
* Set the i/o functions of the Wire to those of the ASCII codec.
*
* @param w Wire
*/
extern void sanei_codec_ascii_init (Wire *w);
#endif /* sanei_codec_ascii_h */

Wyświetl plik

@ -15,12 +15,25 @@
You should have received a copy of the GNU General Public License
along with sane; see the file COPYING. If not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/** @file sanei_codec_bin.h
* Binary codec for network transmissions
*
* Transtale data to a byte stream while taking byte order problems into
* account. This codec is currently used for saned and the network backend.
*
* @sa sanei_codec_ascii.h sanei_net.h sanei_wire.h
*/
This file declares SANE application interface. See the SANE
standard for a detailed explanation of the interface. */
#ifndef sanei_codec_bin_h
#define sanei_codec_bin_h
/** Initialize the binary codec
*
* Set the i/o functions of the Wire to those of the binary codec.
*
* @param w Wire
*/
extern void sanei_codec_bin_init (Wire *w);
#endif /* sanei_codec_bin_h */

Wyświetl plik

@ -37,40 +37,91 @@
If you write modifications of your own for SANE, it is your choice
whether to permit this exception to apply to your modifications.
If you do not wish that, delete this exception notice.
*/
This file provides generic configuration support. */
/** @file sanei_config.h
* Generic configuration support.
*
* Use the functions of this header file if you want to read and analyze
* configuration files.
*/
#ifndef sanei_config_h
#include <stdio.h>
/** Search configuration file \a name along directory list and return file
* pointer if such a file exists.
*
* The following directory list is used:
* 1st: SANE_CONFIG_DIR environment variable.
* 2nd: PATH_SANE_CONFIG_DIR set during configuration.
* 3rd: Current directory.
* @param name filename with extension but without path (such as "mustek.conf")
*
* @return file pointer, or NULL if not found
*
*/
extern FILE *sanei_config_open (const char *name);
/** Read a line from configuration file.
*
* Strips all unwanted chars. Use this instead of fgets() to remove
* line ending chars on all known platforms.
*
* @param str points to the buffer for the line
* @param n size of the buffer
* @param stream file pointer
*
* @return \a str on success and NULL on error
*/
extern char *sanei_config_read (char *str, int n, FILE *stream);
/** Remove all whitespace from the beginning of a string.
*
* @param str string
*
* @return string without leading whitespace
*
*/
extern const char *sanei_config_skip_whitespace (const char *str);
/* Scan a string constant from the string pointed to by STR and return
a malloced copy of it in *STRING_CONST (it's the responsibility of
the caller to free the returned string at an appropriate time).
Whitespace in front of the string constant is ignored. Whitespace
can be included in the string constant by enclosing it in
double-quotes. A return val of NULL indicates that no string
constant was found. */
/** Scan a string constant from a line of text and return a malloced copy
* of it.
*
* It's the responsibility of the caller to free the returned string constant
* at an appropriate time. Whitespace in front of the string constant is
* ignored. Whitespace can be included in the string constant by enclosing it
* in double-quotes.
*
* @param str line of text to scan for a string constant
* @param string_const copy of the string constant
*
* @return a pointer to the position in str where the scan stopped
*/
extern const char *sanei_config_get_string (const char *str,
char **string_const);
/* A convenience function to support expanding device name patterns
into a list of devices. Apart from a normal device name
(such as /dev/sdb), this function currently supports SCSI
device specifications of the form:
scsi VENDOR MODEL TYPE BUS CHANNEL ID LUN
Where VENDOR is the desired vendor name. MODEL is the desired
MODEL name. TYPE is the desired device type. All of these can be
set to * to match anything. To include whitespace in these
strings, enclose them in double-quotes ("). BUS, ID, and LUN are
the desired SCSI bus, id, and logical-unit numbers. These can be
set to * or simply omitted to match anything. */
/** Expand device name patterns into a list of devices.
*
* Apart from a normal device name (such as /dev/sdb), this function currently
* supports SCSI device specifications of the form:
*
* scsi VENDOR MODEL TYPE BUS CHANNEL ID LUN
*
* Where VENDOR is the desired vendor name. MODEL is the desired model name.
* TYPE is the desired device type. All of these can be set to * to match
* anything. To include whitespace in these strings, enclose them in
* double-quotes ("). BUS, ID, and LUN are the desired SCSI bus, id, and
* logical-unit numbers. These can be set to * or simply omitted to match
* anything.
*
* @param name device name pattern
* @param attach attach function
*/
extern void sanei_config_attach_matching_devices (const char *name,
SANE_Status (*attach)
(const char *dev));
(const char *dev));
#endif /* sanei_config_h */

Wyświetl plik

@ -1,51 +1,176 @@
/** @file sanei_debug.h
* Support for printing debug messages.
*
* Use the functions of this header file to print debug or warning messages.
*/
#ifndef _SANEI_DEBUG_H
#define _SANEI_DEBUG_H
#include <sane/sanei.h>
#define ENTRY(name) PASTE(PASTE(PASTE(sane_,BACKEND_NAME),_),name)
/** @name Public macros
* These macros can be used in backends and other SANE-related
* code.
*
* Before including sanei_debug.h, the following macros must be set:
*
* - BACKEND_NAME - The name of your backend without double-quotes (must be set in any case)
* - STUBS - If this is defined, no macros will be included. Used in
* backends consisting of more than one .c file.
* - DEBUG_DECLARE_ONLY - Generates prototypes instead of functions. Used in
* backends consisting of more than one .c file.
* - DEBUG_NOT_STATIC - Doesn't generate static functions. Used in header files if
* they are include in more than one .c file.
*
* @{
*/
/* The cpp that comes with GNU C 2.5 seems to have troubles understanding
vararg macros. */
#if __GNUC__ - 0 > 2 || (__GNUC__ - 0 == 2 && __GNUC_MINOR__ > 5)
# define HAVE_VARARG_MACROS
#endif
/** @def DBG_INIT()
* Initialize sanei_debug.
*
* Call this function before you use any DBG function.
*/
#ifndef HAVE_VARARG_MACROS
extern void sanei_debug (int level, const char *msg, ...);
#endif
/** @def DBG(level, fmt, ...)
* Print a message at debug level `level' or higher using a printf-like
* function. Example: DBG(1, "sane_open: opening fd \%d\\n", fd).
*
* @param level debug level
* @param fmt format (see man 3 printf for details)
* @param ... additional arguments
*/
/** @def IF_DBG(x)
* Compile code only if debugging is enabled.
*
* Expands to x if debug support is enabled at compile-time. If NDEBUG is
* defined at compile-time this macro expands to nothing.
*
* @param x code to expand when debugging is enabled
*/
/**
* @def DBG_LEVEL
* Current debug level.
*
* You can only read this "variable".
*/
/** @def ENTRY(name)
* Expands to sane_BACKEND_NAME_name.
*
* Example: ENTRY(init) in mustek.c will expand to sane_mustek_init.
*/
/* @} */
/** @name Internal macros and functions
* Do not use in your own code.
* @{
*/
/** @def DBG_LOCAL
* Do not use in backends directly.
*
* Internal wrapper for printing function.
*/
/** @fn extern void sanei_init_debug (const char * backend, int * debug_level_var);
* Do not use in backends directly.
*
* Actual init function.
*/
/** @fn extern void sanei_debug_msg (int level, int max_level, const char *be, const char *fmt, va_list ap);
* Do not use in backends directly.
*
* Actual printing function.
*/
/* @} */
/** @hideinitializer*/
#define ENTRY(name) PASTE(PASTE(PASTE(sane_,BACKEND_NAME),_),name)
#ifdef NDEBUG
# define DBG_INIT(backend, var)
# ifdef HAVE_VARARG_MACROS
# define DBG(level, msg, args...)
# else
# define DBG if (0) sanei_debug
# endif
# define IF_DBG(x)
#else
# include <stdio.h>
extern void sanei_debug_ndebug (int level, const char *msg, ...);
# define DBG_LEVEL (0)
# define DBG_INIT()
# define DBG sanei_debug_ndebug
# define IF_DBG(x)
#else /* !NDEBUG */
/** @hideinitializer*/
# define DBG_LEVEL PASTE(sanei_debug_,BACKEND_NAME)
#define DBG_LEVEL PASTE(sanei_debug_,BACKEND_NAME)
# if defined(BACKEND_NAME) && !defined(STUBS)
# ifdef DEBUG_DECLARE_ONLY
extern int DBG_LEVEL;
# else /* !DEBUG_DECLARE_ONLY */
int DBG_LEVEL = 0;
# endif /* DEBUG_DECLARE_ONLY */
# endif /* BACKEND_NAME && !STUBS */
#if defined(BACKEND_NAME) && !defined(STUBS)
int PASTE(sanei_debug_,BACKEND_NAME);
/** @hideinitializer*/
# define DBG_INIT() \
sanei_init_debug (STRINGIFY(BACKEND_NAME), &DBG_LEVEL)
/** @hideinitializer*/
# define DBG_LOCAL PASTE(DBG_LEVEL,_call)
# ifndef STUBS
# ifdef DEBUG_DECLARE_ONLY
extern void DBG_LOCAL (int level, const char *msg, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 2, 3)))
#endif
;
# define DBG_INIT() \
sanei_init_debug (STRINGIFY(BACKEND_NAME), \
&PASTE(sanei_debug_,BACKEND_NAME))
# else /* !DEBUG_DECLARE_ONLY */
/* The cpp that comes with GNU C 2.5 seems to have troubles understanding
vararg macros. */
#ifdef HAVE_VARARG_MACROS
# define DBG(level, msg, args...) \
do { \
if (DBG_LEVEL >= (level)) \
fprintf (stderr, "[" STRINGIFY(BACKEND_NAME) "] " msg, ##args); \
} while (0)
# include <stdarg.h>
extern void sanei_debug_msg
(int level, int max_level, const char *be, const char *fmt, va_list ap);
extern void sanei_init_debug (const char * backend, int * debug_level_var);
#else
# define DBG sanei_debug
#endif
#ifdef __GNUC__
# ifndef DEBUG_NOT_STATIC
static
# endif /* !DEBUG_NOT_STATIC */
void DBG_LOCAL (int level, const char *msg, ...) __attribute__ ((format (printf, 2, 3)));
#endif /* __GNUC__ */
# define IF_DBG(x) x
#endif
# ifndef DEBUG_NOT_STATIC
static
# endif /* !DEBUG_NOT_STATIC */
void
DBG_LOCAL (int level, const char *msg, ...)
{
va_list ap;
va_start (ap, msg);
sanei_debug_msg (level, DBG_LEVEL, STRINGIFY(BACKEND_NAME), msg, ap);
va_end (ap);
}
# endif /* DEBUG_DECLARE_ONLY */
# endif /* !STUBS */
/** @hideinitializer*/
# define DBG DBG_LOCAL
extern void sanei_init_debug (const char * backend, int * debug_level_var);
/** @hideinitializer*/
# define IF_DBG(x) x
#endif /* NDEBUG */
#endif /* _SANEI_DEBUG_H */

Wyświetl plik

@ -54,6 +54,9 @@ bin_w_byte (Wire *w, void *v)
SANE_Byte *b = v;
sanei_w_space (w, 1);
if (w->status)
return;
switch (w->direction)
{
case WIRE_ENCODE:
@ -82,8 +85,14 @@ bin_w_string (Wire *w, void *v)
len = strlen (*s) + 1;
}
sanei_w_array (w, &len, v, w->codec.w_byte, 1);
if (w->direction == WIRE_DECODE && !len)
*s = 0;
if (w->direction == WIRE_DECODE)
{
if (len == 0)
*s = 0;
else if (w->status == 0)
*(*s + len - 1) = '\0';
}
}
static void
@ -92,6 +101,8 @@ bin_w_word (Wire *w, void *v)
SANE_Word val, *word = v;
sanei_w_space (w, 4);
if (w->status)
return;
switch (w->direction)
{
case WIRE_ENCODE:

Wyświetl plik

@ -192,8 +192,14 @@ sanei_w_array (Wire * w, SANE_Word * len_ptr, void **v,
len = *len_ptr;
DBG (4, "sanei_w_array: send/receive array length\n");
sanei_w_word (w, &len);
DBG (4, "sanei_w_array: array has %d elements\n", len);
if (w->status)
{
DBG (1, "sanei_w_array: bad status: %d\n", w->status);
return;
}
DBG (4, "sanei_w_array: array has %d elements\n", len);
if (w->direction == WIRE_DECODE)
{
*len_ptr = len;
@ -219,6 +225,11 @@ sanei_w_array (Wire * w, SANE_Word * len_ptr, void **v,
{
(*w_element) (w, val);
val += element_size;
if (w->status)
{
DBG (1, "sanei_w_array: bad status: %d\n", w->status);
return;
}
}
DBG (4, "sanei_w_array: done\n");
}
@ -251,6 +262,11 @@ sanei_w_ptr (Wire * w, void **v, WireCodecFunc w_value, size_t value_size)
DBG (4, "sanei_w_ptr: send/receive is_null\n");
sanei_w_word (w, &is_null);
if (w->status)
{
DBG (1, "sanei_w_ptr: bad status: %d\n", w->status);
return;
}
if (!is_null)
{
@ -307,7 +323,7 @@ sanei_w_string (Wire * w, SANE_String * v)
{
DBG (3, "sanei_w_string: wire %d\n", w->io.fd);
(*w->codec.w_string) (w, v);
if (w->direction != WIRE_FREE)
if (w->direction != WIRE_FREE && w->status == 0)
DBG (4, "sanei_w_string: value = %s\n", *v);
}