summaryrefslogtreecommitdiff
path: root/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'frontend')
-rw-r--r--frontend/Makefile.am12
-rw-r--r--frontend/Makefile.in86
-rw-r--r--frontend/saned.c169
-rw-r--r--frontend/scanimage.c100
-rw-r--r--frontend/sicc.c67
-rw-r--r--frontend/sicc.h19
-rw-r--r--frontend/stiff.c99
7 files changed, 381 insertions, 171 deletions
diff --git a/frontend/Makefile.am b/frontend/Makefile.am
index 23061b3..525953f 100644
--- a/frontend/Makefile.am
+++ b/frontend/Makefile.am
@@ -14,21 +14,21 @@ else
EXTRA_PROGRAMS += saned
endif
-AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include
+AM_CPPFLAGS += -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include
-scanimage_SOURCES = scanimage.c stiff.c stiff.h
+scanimage_SOURCES = scanimage.c sicc.c sicc.h stiff.c stiff.h
scanimage_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \
- ../lib/libfelib.la @PNG_LIBS@ @JPEG_LIBS@
+ $(PNG_LIBS) $(JPEG_LIBS)
saned_SOURCES = saned.c
saned_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \
- ../lib/libfelib.la @SYSLOG_LIBS@ @SYSTEMD_LIBS@
+ $(SYSLOG_LIBS) $(SYSTEMD_LIBS) $(AVAHI_LIBS)
test_SOURCES = test.c
-test_LDADD = ../lib/liblib.la ../lib/libfelib.la ../backend/libsane.la
+test_LDADD = ../lib/liblib.la ../backend/libsane.la
tstbackend_SOURCES = tstbackend.c
-tstbackend_LDADD = ../lib/liblib.la ../lib/libfelib.la ../backend/libsane.la
+tstbackend_LDADD = ../lib/liblib.la ../backend/libsane.la
clean-local:
rm -f test tstbackend
diff --git a/frontend/Makefile.in b/frontend/Makefile.in
index 2e36e0e..9ea467f 100644
--- a/frontend/Makefile.in
+++ b/frontend/Makefile.in
@@ -86,11 +86,16 @@ subdir = frontend
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/ltoptions.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
- $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
- $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/byteorder.m4 \
- $(top_srcdir)/m4/stdint.m4 $(top_srcdir)/configure.in
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/byteorder.m4 $(top_srcdir)/m4/stdint.m4 \
+ $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
@@ -102,24 +107,25 @@ am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"
PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS)
am_saned_OBJECTS = saned.$(OBJEXT)
saned_OBJECTS = $(am_saned_OBJECTS)
+am__DEPENDENCIES_1 =
saned_DEPENDENCIES = ../backend/libsane.la ../sanei/libsanei.la \
- ../lib/liblib.la ../lib/libfelib.la
+ ../lib/liblib.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
-am_scanimage_OBJECTS = scanimage.$(OBJEXT) stiff.$(OBJEXT)
+am_scanimage_OBJECTS = scanimage.$(OBJEXT) sicc.$(OBJEXT) \
+ stiff.$(OBJEXT)
scanimage_OBJECTS = $(am_scanimage_OBJECTS)
scanimage_DEPENDENCIES = ../backend/libsane.la ../sanei/libsanei.la \
- ../lib/liblib.la ../lib/libfelib.la
+ ../lib/liblib.la $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
am_test_OBJECTS = test.$(OBJEXT)
test_OBJECTS = $(am_test_OBJECTS)
-test_DEPENDENCIES = ../lib/liblib.la ../lib/libfelib.la \
- ../backend/libsane.la
+test_DEPENDENCIES = ../lib/liblib.la ../backend/libsane.la
am_tstbackend_OBJECTS = tstbackend.$(OBJEXT)
tstbackend_OBJECTS = $(am_tstbackend_OBJECTS)
-tstbackend_DEPENDENCIES = ../lib/liblib.la ../lib/libfelib.la \
- ../backend/libsane.la
+tstbackend_DEPENDENCIES = ../lib/liblib.la ../backend/libsane.la
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
@@ -186,7 +192,11 @@ DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@ -I. -I$(srcdir) -I$(top_builddir)/include \
+ -I$(top_srcdir)/include
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AM_LDFLAGS = @AM_LDFLAGS@
AR = @AR@
AS = @AS@
AUTOCONF = @AUTOCONF@
@@ -207,7 +217,7 @@ CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
-DISTCLEAN_FILES = @DISTCLEAN_FILES@
+DLH = @DLH@
DLLTOOL = @DLLTOOL@
DL_LIBS = @DL_LIBS@
DSYMUTIL = @DSYMUTIL@
@@ -220,34 +230,42 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+FIG2DEV = @FIG2DEV@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@
GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@
GPHOTO2_LIBS = @GPHOTO2_LIBS@
GREP = @GREP@
+GS = @GS@
HAVE_GPHOTO2 = @HAVE_GPHOTO2@
IEEE1284_LIBS = @IEEE1284_LIBS@
-INCLUDES = @INCLUDES@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_LOCKPATH = @INSTALL_LOCKPATH@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
JPEG_LIBS = @JPEG_LIBS@
LATEX = @LATEX@
LD = @LD@
LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
-LIBUSB_1_0_CFLAGS = @LIBUSB_1_0_CFLAGS@
-LIBUSB_1_0_LIBS = @LIBUSB_1_0_LIBS@
LIBV4L_CFLAGS = @LIBV4L_CFLAGS@
LIBV4L_LIBS = @LIBV4L_LIBS@
-LINKER_RPATH = @LINKER_RPATH@
LIPO = @LIPO@
LN_S = @LN_S@
LOCKPATH_GROUP = @LOCKPATH_GROUP@
+LTALLOCA = @LTALLOCA@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINDEX = @MAKEINDEX@
@@ -256,10 +274,10 @@ MANIFEST_TOOL = @MANIFEST_TOOL@
MATH_LIB = @MATH_LIB@
MKDIR_P = @MKDIR_P@
MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
MSGMERGE = @MSGMERGE@
NM = @NM@
NMEDIT = @NMEDIT@
-NUMBER_VERSION = @NUMBER_VERSION@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
@@ -272,10 +290,13 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
+PDFLATEX = @PDFLATEX@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PNG_LIBS = @PNG_LIBS@
+POSUB = @POSUB@
+PPMTOGIF = @PPMTOGIF@
PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@
PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@
PTHREAD_LIBS = @PTHREAD_LIBS@
@@ -297,12 +318,16 @@ SYSLOG_LIBS = @SYSLOG_LIBS@
SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@
SYSTEMD_LIBS = @SYSTEMD_LIBS@
TIFF_LIBS = @TIFF_LIBS@
+USB_CFLAGS = @USB_CFLAGS@
USB_LIBS = @USB_LIBS@
+USE_NLS = @USE_NLS@
VERSION = @VERSION@
V_MAJOR = @V_MAJOR@
V_MINOR = @V_MINOR@
V_REV = @V_REV@
XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
@@ -358,19 +383,18 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include
-scanimage_SOURCES = scanimage.c stiff.c stiff.h
+scanimage_SOURCES = scanimage.c sicc.c sicc.h stiff.c stiff.h
scanimage_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \
- ../lib/libfelib.la @PNG_LIBS@ @JPEG_LIBS@
+ $(PNG_LIBS) $(JPEG_LIBS)
saned_SOURCES = saned.c
saned_LDADD = ../backend/libsane.la ../sanei/libsanei.la ../lib/liblib.la \
- ../lib/libfelib.la @SYSLOG_LIBS@ @SYSTEMD_LIBS@
+ $(SYSLOG_LIBS) $(SYSTEMD_LIBS) $(AVAHI_LIBS)
test_SOURCES = test.c
-test_LDADD = ../lib/liblib.la ../lib/libfelib.la ../backend/libsane.la
+test_LDADD = ../lib/liblib.la ../backend/libsane.la
tstbackend_SOURCES = tstbackend.c
-tstbackend_LDADD = ../lib/liblib.la ../lib/libfelib.la ../backend/libsane.la
+tstbackend_LDADD = ../lib/liblib.la ../backend/libsane.la
all: all-am
.SUFFIXES:
@@ -528,27 +552,31 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/saned.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scanimage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sicc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stiff.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tstbackend.Po@am__quote@
.c.o:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
diff --git a/frontend/saned.c b/frontend/saned.c
index 108512d..3bb99bb 100644
--- a/frontend/saned.c
+++ b/frontend/saned.c
@@ -82,6 +82,8 @@
#include <pwd.h>
#include <grp.h>
+#include "lgetopt.h"
+
#if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL)
# include <sys/poll.h>
#else
@@ -196,16 +198,19 @@ static AvahiEntryGroup *avahi_group = NULL;
#endif
#ifdef ENABLE_IPV6
-# define SANE_IN6_IS_ADDR_LOOPBACK(a) \
+# ifndef IN6_IS_ADDR_LOOPBACK
+# define IN6_IS_ADDR_LOOPBACK(a) \
(((const uint32_t *) (a))[0] == 0 \
&& ((const uint32_t *) (a))[1] == 0 \
&& ((const uint32_t *) (a))[2] == 0 \
&& ((const uint32_t *) (a))[3] == htonl (1))
-
-#define SANE_IN6_IS_ADDR_V4MAPPED(a) \
+# endif
+# ifndef IN6_IS_ADDR_V4MAPPED
+# define IN6_IS_ADDR_V4MAPPED(a) \
((((const uint32_t *) (a))[0] == 0) \
&& (((const uint32_t *) (a))[1] == 0) \
&& (((const uint32_t *) (a))[2] == htonl (0xffff)))
+# endif
#endif /* ENABLE_IPV6 */
#ifndef MAXHOSTNAMELEN
@@ -247,6 +252,7 @@ static int num_handles;
static int debug;
static int run_mode;
static Handle *handle;
+static char *bind_addr;
static union
{
int w;
@@ -786,7 +792,7 @@ check_host (int fd)
#ifdef ENABLE_IPV6
sin6 = &remote_address.sin6;
- if (SANE_IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr))
+ if (IN6_IS_ADDR_V4MAPPED ((struct in6_addr *)sin6->sin6_addr.s6_addr))
{
DBG (DBG_DBG, "check_host: detected an IPv4-mapped address\n");
remote_ipv4 = remote_ip + 7;
@@ -843,7 +849,7 @@ check_host (int fd)
break;
#ifdef ENABLE_IPV6
case AF_INET6:
- if (SANE_IN6_IS_ADDR_LOOPBACK (sin6->sin6_addr.s6_addr))
+ if (IN6_IS_ADDR_LOOPBACK ((struct in6_addr *)sin6->sin6_addr.s6_addr))
{
DBG (DBG_MSG,
"check_host: remote host is IN6_LOOPBACK: access granted\n");
@@ -1428,7 +1434,7 @@ start_scan (Wire * w, int h, SANE_Start_Reply * reply)
SANE_Handle be_handle;
int fd, len;
in_port_t data_port;
- int ret;
+ int ret = -1;
be_handle = handle[h].handle;
@@ -1986,6 +1992,38 @@ process_request (Wire * w)
return 1;
}
+ /* Addresses CVE-2017-6318 (#315576, Debian BTS #853804) */
+ /* This is done here (rather than in sanei/sanei_wire.c where
+ * it should be done) to minimize scope of impact and amount
+ * of code change.
+ */
+ if (w->direction == WIRE_DECODE
+ && req.value_type == SANE_TYPE_STRING
+ && req.action == SANE_ACTION_GET_VALUE)
+ {
+ if (req.value)
+ {
+ /* FIXME: If req.value contains embedded NUL
+ * characters, this is wrong but we do not have
+ * access to the amount of memory allocated in
+ * sanei/sanei_wire.c at this point.
+ */
+ w->allocated_memory -= (1 + strlen (req.value));
+ free (req.value);
+ }
+ req.value = malloc (req.value_size);
+ if (!req.value)
+ {
+ w->status = ENOMEM;
+ DBG (DBG_ERR,
+ "process_request: (control_option) "
+ "h=%d (%s)\n", req.handle, strerror (w->status));
+ return 1;
+ }
+ memset (req.value, 0, req.value_size);
+ w->allocated_memory += req.value_size;
+ }
+
can_authorize = 1;
memset (&reply, 0, sizeof (reply)); /* avoid leaking bits */
@@ -2807,13 +2845,13 @@ do_bindings (int *nfds, struct pollfd **fds)
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
- err = getaddrinfo (NULL, SANED_SERVICE_NAME, &hints, &res);
+ err = getaddrinfo (bind_addr, SANED_SERVICE_NAME, &hints, &res);
if (err)
{
DBG (DBG_WARN, "do_bindings: \" %s \" service unknown on your host; you should add\n", SANED_SERVICE_NAME);
DBG (DBG_WARN, "do_bindings: %s %d/tcp saned # SANE network scanner daemon\n", SANED_SERVICE_NAME, SANED_SERVICE_PORT);
DBG (DBG_WARN, "do_bindings: to your /etc/services file (or equivalent). Proceeding anyway.\n");
- err = getaddrinfo (NULL, SANED_SERVICE_PORT_S, &hints, &res);
+ err = getaddrinfo (bind_addr, SANED_SERVICE_PORT_S, &hints, &res);
if (err)
{
DBG (DBG_ERR, "do_bindings: getaddrinfo() failed even with numeric port: %s\n", gai_strerror (err));
@@ -2891,7 +2929,10 @@ do_bindings (int *nfds, struct pollfd **fds)
memset (&sin, 0, sizeof (sin));
sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
+ if(bind_addr)
+ sin.sin_addr.s_addr = inet_addr(bind_addr);
+ else
+ sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = port;
DBG (DBG_DBG, "do_bindings: socket ()\n");
@@ -2923,7 +2964,7 @@ do_bindings (int *nfds, struct pollfd **fds)
static void
-run_standalone (int argc, char **argv)
+run_standalone (char *user)
{
struct pollfd *fds = NULL;
struct pollfd *fdp = NULL;
@@ -2944,13 +2985,13 @@ run_standalone (int argc, char **argv)
if (run_mode != SANED_RUN_DEBUG)
{
- if (argc > 2)
+ if (user)
{
- pwent = getpwnam(argv[2]);
+ pwent = getpwnam(user);
if (pwent == NULL)
{
- DBG (DBG_ERR, "FATAL ERROR: user %s not found on system\n", argv[2]);
+ DBG (DBG_ERR, "FATAL ERROR: user %s not found on system\n", user);
bail_out (1);
}
@@ -2981,7 +3022,7 @@ run_standalone (int argc, char **argv)
while (grp->gr_mem[i])
{
- if (strcmp(grp->gr_mem[i], argv[2]) == 0)
+ if (strcmp(grp->gr_mem[i], user) == 0)
{
int need_to_add = 1, j;
@@ -3172,7 +3213,7 @@ run_standalone (int argc, char **argv)
static void
-run_inetd (int argc, char **argv)
+run_inetd (char __sane_unused__ *sock)
{
int fd = -1;
@@ -3238,18 +3279,13 @@ run_inetd (int argc, char **argv)
close (dave_null);
}
-#ifndef HAVE_OS2_H
- /* Unused in this function */
- argc = argc;
- argv = argv;
-
-#else
+#ifdef HAVE_OS2_H
/* under OS/2, the socket handle is passed as argument on the command
line; the socket handle is relative to IBM TCP/IP, so a call
to impsockethandle() is required to add it to the EMX runtime */
- if (argc == 2)
+ if (sock)
{
- fd = _impsockhandle (atoi (argv[1]), 0);
+ fd = _impsockhandle (atoi (sock), 0);
if (fd == -1)
perror ("impsockhandle");
}
@@ -3258,11 +3294,44 @@ run_inetd (int argc, char **argv)
handle_connection(fd);
}
+static void usage(char *me, int err)
+{
+ fprintf (stderr,
+ "Usage: %s [OPTIONS]\n\n"
+ " Options:\n\n"
+ " -a, --alone[=user] run standalone and fork in background as `user'\n"
+ " -d, --debug[=level] run foreground with output to stdout\n"
+ " and debug level `level' (default is 2)\n"
+ " -s, --syslog[=level] run foreground with output to syslog\n"
+ " and debug level `level' (default is 2)\n"
+ " -b, --bind=addr bind address `addr'\n"
+ " -h, --help show this help message and exit\n", me);
+
+ exit(err);
+}
+
+static int debug;
+
+static struct option long_options[] =
+{
+/* These options set a flag. */
+ {"help", no_argument, 0, 'h'},
+ {"alone", optional_argument, 0, 'a'},
+ {"debug", optional_argument, 0, 'd'},
+ {"syslog", optional_argument, 0, 's'},
+ {"bind", required_argument, 0, 'b'},
+ {0, 0, 0, 0 }
+};
int
main (int argc, char *argv[])
{
char options[64] = "";
+ char *user = NULL;
+ char *sock = NULL;
+ int c;
+ int long_index = 0;
+
debug = DBG_WARN;
prog_name = strrchr (argv[0], '/');
@@ -3274,34 +3343,30 @@ main (int argc, char *argv[])
numchildren = 0;
run_mode = SANED_RUN_INETD;
- if (argc >= 2)
+ while((c = getopt_long(argc, argv,"ha::d::s::b:", long_options, &long_index )) != -1)
{
- if (strncmp (argv[1], "-a", 2) == 0)
+ switch(c) {
+ case 'a':
run_mode = SANED_RUN_ALONE;
- else if (strncmp (argv[1], "-d", 2) == 0)
- {
- run_mode = SANED_RUN_DEBUG;
- log_to_syslog = SANE_FALSE;
- }
- else if (strncmp (argv[1], "-s", 2) == 0)
+ user = optarg;
+ break;
+ case 'd':
+ log_to_syslog = SANE_FALSE;
+ case 's':
run_mode = SANED_RUN_DEBUG;
- else
- {
- printf ("Usage: saned [ -a [ username ] | -d [ n ] | -s [ n ] ] | -h\n");
- if ((strncmp (argv[1], "-h", 2) == 0) ||
- (strncmp (argv[1], "--help", 6) == 0))
- exit (EXIT_SUCCESS);
- else
- exit (EXIT_FAILURE);
- }
- }
-
- if (run_mode == SANED_RUN_DEBUG)
- {
- if (argv[1][2])
- debug = atoi (argv[1] + 2);
-
- DBG (DBG_WARN, "main: starting debug mode (level %d)\n", debug);
+ if(optarg)
+ debug = atoi(optarg);
+ break;
+ case 'b':
+ bind_addr = optarg;
+ break;
+ case 'h':
+ usage(argv[0], EXIT_SUCCESS);
+ break;
+ default:
+ usage(argv[0], EXIT_FAILURE);
+ break;
+ }
}
if (log_to_syslog)
@@ -3342,11 +3407,15 @@ main (int argc, char *argv[])
if ((run_mode == SANED_RUN_ALONE) || (run_mode == SANED_RUN_DEBUG))
{
- run_standalone(argc, argv);
+ run_standalone(user);
}
else
{
- run_inetd(argc, argv);
+#ifdef HAVE_OS2_H
+ if (argc == 2)
+ sock = argv[1];
+#endif
+ run_inetd(sock);
}
DBG (DBG_WARN, "saned exiting\n");
diff --git a/frontend/scanimage.c b/frontend/scanimage.c
index 7f7c1f0..fe02750 100644
--- a/frontend/scanimage.c
+++ b/frontend/scanimage.c
@@ -56,6 +56,7 @@
#include "../include/sane/sanei.h"
#include "../include/sane/saneopts.h"
+#include "sicc.h"
#include "stiff.h"
#include "../include/md5.h"
@@ -322,7 +323,7 @@ auth_callback (SANE_String_Const resource,
}
}
-static RETSIGTYPE
+static void
sighandler (int signum)
{
static SANE_Bool first_time = SANE_TRUE;
@@ -1165,9 +1166,14 @@ write_pnm_header (SANE_Frame format, int width, int height, int depth, FILE *ofp
#ifdef HAVE_LIBPNG
static void
-write_png_header (SANE_Frame format, int width, int height, int depth, FILE *ofp, png_structp* png_ptr, png_infop* info_ptr)
+write_png_header (SANE_Frame format, int width, int height, int depth, int dpi, const char * icc_profile, FILE *ofp, png_structp* png_ptr, png_infop* info_ptr)
{
int color_type;
+ /* PNG does not have imperial reference units, so we must convert to metric. */
+ /* There are nominally 39.3700787401575 inches in a meter. */
+ const double pixels_per_meter = dpi * 39.3700787401575;
+ size_t icc_size = 0;
+ void *icc_buffer;
*png_ptr = png_create_write_struct
(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
@@ -1200,13 +1206,47 @@ write_png_header (SANE_Frame format, int width, int height, int depth, FILE *ofp
depth, color_type, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+ png_set_pHYs(*png_ptr, *info_ptr,
+ pixels_per_meter, pixels_per_meter,
+ PNG_RESOLUTION_METER);
+
+ if (icc_profile)
+ {
+ icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
+ if (icc_size > 0)
+ {
+ /* libpng will abort if the profile and image colour spaces do not match*/
+ /* The data colour space field is at bytes 16 to 20 in an ICC profile */
+ /* see: ICC.1:2010 ยง 7.2.6 */
+ int is_gray_profile = strncmp((char *) icc_buffer + 16, "GRAY", 4) == 0;
+ int is_rgb_profile = strncmp((char *) icc_buffer + 16, "RGB ", 4) == 0;
+ if ((is_gray_profile && color_type == PNG_COLOR_TYPE_GRAY) ||
+ (is_rgb_profile && color_type == PNG_COLOR_TYPE_RGB))
+ {
+ png_set_iCCP(*png_ptr, *info_ptr, basename(icc_profile), PNG_COMPRESSION_TYPE_BASE, icc_buffer, icc_size);
+ }
+ else
+ {
+ if (is_gray_profile)
+ {
+ fprintf(stderr, "Ignoring 'GRAY' space ICC profile because the image is RGB.\n");
+ }
+ if (is_rgb_profile)
+ {
+ fprintf(stderr, "Ignoring 'RGB ' space ICC profile because the image is Grayscale.\n");
+ }
+ }
+ free(icc_buffer);
+ }
+ }
+
png_write_info(*png_ptr, *info_ptr);
}
#endif
#ifdef HAVE_LIBJPEG
static void
-write_jpeg_header (SANE_Frame format, int width, int height, FILE *ofp, struct jpeg_compress_struct *cinfo, struct jpeg_error_mgr *jerr)
+write_jpeg_header (SANE_Frame format, int width, int height, int dpi, FILE *ofp, struct jpeg_compress_struct *cinfo, struct jpeg_error_mgr *jerr)
{
cinfo->err = jpeg_std_error(jerr);
jpeg_create_compress(cinfo);
@@ -1231,6 +1271,11 @@ write_jpeg_header (SANE_Frame format, int width, int height, FILE *ofp, struct j
}
jpeg_set_defaults(cinfo);
+ /* jpeg_set_defaults overrides density, be careful. */
+ cinfo->density_unit = 1; /* Inches */
+ cinfo->X_density = cinfo->Y_density = dpi;
+ cinfo->write_JFIF_header = TRUE;
+
jpeg_set_quality(cinfo, 75, TRUE);
jpeg_start_compress(cinfo, TRUE);
}
@@ -1379,13 +1424,15 @@ scan_it (FILE *ofp)
#ifdef HAVE_LIBPNG
case OUTPUT_PNG:
write_png_header (parm.format, parm.pixels_per_line,
- parm.lines, parm.depth, ofp, &png_ptr, &info_ptr);
+ parm.lines, parm.depth, resolution_value,
+ icc_profile, ofp, &png_ptr, &info_ptr);
break;
#endif
#ifdef HAVE_LIBJPEG
case OUTPUT_JPEG:
write_jpeg_header (parm.format, parm.pixels_per_line,
- parm.lines, ofp, &cinfo, &jerr);
+ parm.lines, resolution_value,
+ ofp, &cinfo, &jerr);
break;
#endif
}
@@ -1529,6 +1576,21 @@ scan_it (FILE *ofp)
for(j = 0; j < parm.bytes_per_line; j++)
pngbuf[j] = ~pngbuf[j];
}
+#ifndef WORDS_BIGENDIAN
+ /* SANE is endian-native, PNG is big-endian, */
+ /* see: https://www.w3.org/TR/2003/REC-PNG-20031110/#7Integers-and-byte-order */
+ if (parm.depth == 16)
+ {
+ int j;
+ for (j = 0; j < parm.bytes_per_line; j += 2)
+ {
+ SANE_Byte LSB;
+ LSB = pngbuf[j];
+ pngbuf[j] = pngbuf[j + 1];
+ pngbuf[j + 1] = LSB;
+ }
+ }
+#endif
png_write_row(png_ptr, pngbuf);
i += parm.bytes_per_line - pngrow;
left -= parm.bytes_per_line - pngrow;
@@ -1635,13 +1697,15 @@ scan_it (FILE *ofp)
#ifdef HAVE_LIBPNG
case OUTPUT_PNG:
write_png_header (parm.format, parm.pixels_per_line,
- image.height, parm.depth, ofp, &png_ptr, &info_ptr);
+ image.height, parm.depth, resolution_value,
+ icc_profile, ofp, &png_ptr, &info_ptr);
break;
#endif
#ifdef HAVE_LIBJPEG
case OUTPUT_JPEG:
write_jpeg_header (parm.format, parm.pixels_per_line,
- parm.lines, ofp, &cinfo, &jerr);
+ parm.lines, resolution_value,
+ ofp, &cinfo, &jerr);
break;
#endif
}
@@ -2474,9 +2538,16 @@ List of available devices:", prog_name);
ofp = stdout;
if (batch)
- fprintf (stderr,
- "Scanning %d pages, incrementing by %d, numbering from %d\n",
- batch_count, batch_increment, batch_start_at);
+ {
+ fputs("Scanning ", stderr);
+ if (batch_count == BATCH_COUNT_UNLIMITED)
+ fputs("infinity", stderr);
+ else
+ fprintf(stderr, "%d", batch_count);
+ fprintf (stderr,
+ " page%s, incrementing by %d, numbering from %d\n",
+ batch_count == 1 ? "" : "s", batch_increment, batch_start_at);
+ }
else if(isatty(fileno(ofp))){
fprintf (stderr,"%s: output is not a file, exiting\n", prog_name);
@@ -2509,8 +2580,6 @@ List of available devices:", prog_name);
if (readbuf2 == NULL)
{
- fprintf (stderr, "Batch terminated, %d pages scanned\n",
- (n - batch_increment));
if (ofp)
{
fclose (ofp);
@@ -2612,6 +2681,13 @@ List of available devices:", prog_name);
&& (batch_count == BATCH_COUNT_UNLIMITED || --batch_count))
&& SANE_STATUS_GOOD == status);
+ if (batch)
+ {
+ int num_pgs = (n - batch_start_at) / batch_increment;
+ fprintf (stderr, "Batch terminated, %d page%s scanned\n",
+ num_pgs, num_pgs == 1 ? "" : "s");
+ }
+
if (batch
&& SANE_STATUS_NO_DOCS == status
&& (batch_count == BATCH_COUNT_UNLIMITED)
diff --git a/frontend/sicc.c b/frontend/sicc.c
new file mode 100644
index 0000000..c93e5c3
--- /dev/null
+++ b/frontend/sicc.c
@@ -0,0 +1,67 @@
+/* Load an ICC profile for embedding in an output file
+ Copyright (C) 2017 Aaron Muir Hamilton <aaron@correspondwith.me>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "../include/sane/config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+
+void *
+sanei_load_icc_profile (const char *path, size_t *size)
+{
+ FILE *fd = NULL;
+ size_t stated_size = 0;
+ void *profile = NULL;
+ struct stat s;
+
+ fd = fopen(path, "r");
+
+ if (!fd)
+ {
+ fprintf(stderr, "Could not open ICC profile %s\n", path);
+ }
+ else
+ {
+ fstat(fileno(fd), &s);
+ stated_size = 16777216 * fgetc(fd) + 65536 * fgetc(fd) + 256 * fgetc(fd) + fgetc(fd);
+ rewind(fd);
+
+ if (stated_size > (size_t) s.st_size)
+ {
+ fprintf(stderr, "Ignoring ICC profile because file %s is shorter than the profile\n", path);
+ }
+ else
+ {
+ profile = malloc(stated_size);
+
+ if (fread(profile, stated_size, 1, fd) != 1)
+ {
+ fprintf(stderr, "Error reading ICC profile %s\n", path);
+ free(profile);
+ }
+ else
+ {
+ fclose(fd);
+ *size = stated_size;
+ return profile;
+ }
+ }
+ fclose(fd);
+ }
+ return NULL;
+}
diff --git a/frontend/sicc.h b/frontend/sicc.h
new file mode 100644
index 0000000..5c225da
--- /dev/null
+++ b/frontend/sicc.h
@@ -0,0 +1,19 @@
+/* Load an ICC profile for embedding in an output file
+ Copyright (C) 2017 Aaron Muir Hamilton <aaron@correspondwith.me>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+void *
+sanei_load_icc_profile (const char *path, size_t *size);
diff --git a/frontend/stiff.c b/frontend/stiff.c
index 01d845b..c9153e5 100644
--- a/frontend/stiff.c
+++ b/frontend/stiff.c
@@ -1,6 +1,7 @@
/* Create SANE/tiff headers TIFF interfacing routines for SANE
Copyright (C) 2000 Peter Kirchgessner
Copyright (C) 2002 Oliver Rauch: added tiff ICC profile
+ Copyright (C) 2017 Aaron Muir Hamilton <aaron@correspondwith.me>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -20,6 +21,7 @@
2000-11-19, PK: Color TIFF-header: write 3 values for bits per sample
2001-12-16, PK: Write fill order tag for b/w-images
2002-08-27, OR: Added tiff tag for ICC profile
+ 2017-04-16, AMH: Separate ICC profile loading into a separate file
*/
#ifdef _AIX
# include "../include/lalloca.h" /* MUST come first for AIX! */
@@ -31,6 +33,7 @@
#include "../include/sane/config.h"
#include "../include/sane/sane.h"
+#include "sicc.h"
#include "stiff.h"
typedef struct {
@@ -269,22 +272,12 @@ write_tiff_grey_header (FILE *fptr, int width, int height, int depth,
int strip_bytecount;
int ntags;
int motorola, bps, maxsamplevalue;
- FILE *icc_file = 0;
- int icc_len = -1;
+ void *icc_buffer = NULL;
+ size_t icc_size = 0;
if (icc_profile)
{
- icc_file = fopen(icc_profile, "r");
-
- if (!icc_file)
- {
- fprintf(stderr, "Could not open ICC profile %s\n", icc_profile);
- }
- else
- {
- icc_len = 16777216 * fgetc(icc_file) + 65536 * fgetc(icc_file) + 256 * fgetc(icc_file) + fgetc(icc_file);
- rewind(icc_file);
- }
+ icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
}
ifd = create_ifd ();
@@ -302,10 +295,10 @@ write_tiff_grey_header (FILE *fptr, int width, int height, int depth,
data_size += 2*4 + 2*4;
}
- if (icc_len > 0) /* if icc profile exists add memory for tag */
+ if (icc_size > 0) /* if icc profile exists add memory for tag */
{
ntags += 1;
- data_size += icc_len;
+ data_size += icc_size;
}
ifd_size = 2 + ntags*12 + 4;
@@ -355,10 +348,10 @@ write_tiff_grey_header (FILE *fptr, int width, int height, int depth,
add_ifd_entry (ifd, 296, IFDE_TYP_SHORT, 1, 2);
}
- if (icc_len > 0) /* add ICC-profile TAG */
+ if (icc_size > 0) /* add ICC-profile TAG */
{
- add_ifd_entry(ifd, 34675, 7, icc_len, data_offset);
- data_offset += icc_len;
+ add_ifd_entry(ifd, 34675, 7, (int) icc_size, data_offset);
+ data_offset += icc_size;
}
/* I prefer motorola format. Its human readable. But for 16 bit, */
@@ -383,33 +376,16 @@ write_tiff_grey_header (FILE *fptr, int width, int height, int depth,
write_i4 (fptr, 1, motorola);
}
- /* Write ICC profile */
- if (icc_len > 0)
+ if (icc_size > 0)
{
- int i;
- for (i=0; i<icc_len; i++)
- {
- if (!feof(icc_file))
- {
- fputc(fgetc(icc_file), fptr);
- }
- else
- {
- fprintf(stderr, "ICC profile %s is too short\n", icc_profile);
- break;
- }
- }
+ fwrite(icc_buffer, icc_size, 1, fptr);
}
- if (icc_file)
- {
- fclose(icc_file);
- }
+ free(icc_buffer);
free_ifd (ifd);
}
-
static void
write_tiff_color_header (FILE *fptr, int width, int height, int depth,
int resolution, const char *icc_profile)
@@ -419,22 +395,12 @@ write_tiff_color_header (FILE *fptr, int width, int height, int depth,
int strip_bytecount;
int ntags;
int motorola, bps, maxsamplevalue;
- FILE *icc_file = 0;
- int icc_len = -1;
+ void *icc_buffer = NULL;
+ size_t icc_size = 0;
if (icc_profile)
{
- icc_file = fopen(icc_profile, "r");
-
- if (!icc_file)
- {
- fprintf(stderr, "Could not open ICC profile %s\n", icc_profile);
- }
- else
- {
- icc_len = 16777216 * fgetc(icc_file) + 65536 * fgetc(icc_file) + 256 * fgetc(icc_file) + fgetc(icc_file);
- rewind(icc_file);
- }
+ icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
}
@@ -454,10 +420,10 @@ write_tiff_color_header (FILE *fptr, int width, int height, int depth,
data_size += 2*4 + 2*4;
}
- if (icc_len > 0) /* if icc profile exists add memory for tag */
+ if (icc_size > 0) /* if icc profile exists add memory for tag */
{
ntags += 1;
- data_size += icc_len;
+ data_size += icc_size;
}
@@ -513,10 +479,10 @@ write_tiff_color_header (FILE *fptr, int width, int height, int depth,
add_ifd_entry (ifd, 296, IFDE_TYP_SHORT, 1, 2);
}
- if (icc_len > 0) /* add ICC-profile TAG */
+ if (icc_size > 0) /* add ICC-profile TAG */
{
- add_ifd_entry(ifd, 34675, 7, icc_len, data_offset);
- data_offset += icc_len;
+ add_ifd_entry(ifd, 34675, 7, (int) icc_size, data_offset);
+ data_offset += icc_size;
}
@@ -558,27 +524,12 @@ write_tiff_color_header (FILE *fptr, int width, int height, int depth,
}
/* Write ICC profile */
- if (icc_len > 0)
+ if (icc_size > 0)
{
- int i;
- for (i=0; i<icc_len; i++)
- {
- if (!feof(icc_file))
- {
- fputc(fgetc(icc_file), fptr);
- }
- else
- {
- fprintf(stderr, "ICC profile %s is too short\n", icc_profile);
- break;
- }
- }
+ fwrite(icc_buffer, icc_size, 1, fptr);
}
- if (icc_file)
- {
- fclose(icc_file);
- }
+ free(icc_buffer);
free_ifd (ifd);
}