1 /* scanimage -- command line scanning utility
2    Uses the SANE library.
3    Copyright (C) 2015 Rolf Bensch <rolf at bensch hyphen online dot de>
4    Copyright (C) 1996, 1997, 1998 Andreas Beck and David Mosberger
5 
6    Copyright (C) 1999 - 2009 by the SANE Project -- See AUTHORS and ChangeLog
7    for details.
8 
9    For questions and comments contact the sane-devel mailinglist (see
10    http://www.sane-project.org/mailing-lists.html).
11 
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License as
14    published by the Free Software Foundation; either version 2 of the
15    License, or (at your option) any later version.
16 
17    This program is distributed in the hope that it will be useful, but
18    WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20    General Public License for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <https://www.gnu.org/licenses/>.
24 */
25 
26 #ifdef _AIX
27 # include "../include/lalloca.h"                /* MUST come first for AIX! */
28 #endif
29 
30 #include "../include/sane/config.h"
31 #include "../include/lalloca.h"
32 
33 #include <assert.h>
34 #include "lgetopt.h"
35 #include <inttypes.h>
36 #include <signal.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <stdarg.h>
42 
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 
46 #ifdef HAVE_LIBPNG
47 #include <png.h>
48 #endif
49 
50 #ifdef HAVE_LIBJPEG
51 #include <jpeglib.h>
52 #endif
53 
54 #include "../include/_stdint.h"
55 
56 #include "../include/sane/sane.h"
57 #include "../include/sane/sanei.h"
58 #include "../include/sane/saneopts.h"
59 
60 #include "sicc.h"
61 #include "stiff.h"
62 
63 #include "../include/md5.h"
64 
65 #ifndef PATH_MAX
66 #define PATH_MAX 1024
67 #endif
68 
69 typedef struct
70 {
71   uint8_t *data;
72   int width;    /*WARNING: this is in bytes, get pixel width from param*/
73   int height;
74   int x;
75   int y;
76   int num_channels;
77 }
78 Image;
79 
80 #define OPTION_FORMAT   1001
81 #define OPTION_MD5	1002
82 #define OPTION_BATCH_COUNT	1003
83 #define OPTION_BATCH_START_AT	1004
84 #define OPTION_BATCH_DOUBLE	1005
85 #define OPTION_BATCH_INCREMENT	1006
86 #define OPTION_BATCH_PROMPT    1007
87 #define OPTION_BATCH_PRINT     1008
88 
89 #define BATCH_COUNT_UNLIMITED -1
90 
91 static struct option basic_options[] = {
92   {"device-name", required_argument, NULL, 'd'},
93   {"list-devices", no_argument, NULL, 'L'},
94   {"formatted-device-list", required_argument, NULL, 'f'},
95   {"help", no_argument, NULL, 'h'},
96   {"verbose", no_argument, NULL, 'v'},
97   {"progress", no_argument, NULL, 'p'},
98   {"output-file", required_argument, NULL, 'o'},
99   {"test", no_argument, NULL, 'T'},
100   {"all-options", no_argument, NULL, 'A'},
101   {"version", no_argument, NULL, 'V'},
102   {"buffer-size", optional_argument, NULL, 'B'},
103   {"batch", optional_argument, NULL, 'b'},
104   {"batch-count", required_argument, NULL, OPTION_BATCH_COUNT},
105   {"batch-start", required_argument, NULL, OPTION_BATCH_START_AT},
106   {"batch-double", no_argument, NULL, OPTION_BATCH_DOUBLE},
107   {"batch-increment", required_argument, NULL, OPTION_BATCH_INCREMENT},
108   {"batch-print", no_argument, NULL, OPTION_BATCH_PRINT},
109   {"batch-prompt", no_argument, NULL, OPTION_BATCH_PROMPT},
110   {"format", required_argument, NULL, OPTION_FORMAT},
111   {"accept-md5-only", no_argument, NULL, OPTION_MD5},
112   {"icc-profile", required_argument, NULL, 'i'},
113   {"dont-scan", no_argument, NULL, 'n'},
114   {0, 0, NULL, 0}
115 };
116 
117 #define OUTPUT_UNKNOWN  0
118 #define OUTPUT_PNM      1
119 #define OUTPUT_TIFF     2
120 #define OUTPUT_PNG      3
121 #define OUTPUT_JPEG     4
122 
123 #define BASE_OPTSTRING	"d:hi:Lf:o:B::nvVTAbp"
124 #define STRIP_HEIGHT	256	/* # lines we increment image height */
125 
126 static struct option *all_options;
127 static int option_number_len;
128 static int *option_number;
129 static SANE_Handle device;
130 static int verbose;
131 static int progress = 0;
132 static const char* output_file = NULL;
133 static int test;
134 static int all;
135 static int output_format = OUTPUT_UNKNOWN;
136 static int help;
137 static int dont_scan = 0;
138 static const char *prog_name;
139 static int resolution_optind = -1, resolution_value = 0;
140 
141 /* window (area) related options */
142 static SANE_Option_Descriptor window_option[4]; /*updated descs for x,y,l,t*/
143 static int window[4]; /*index into backend options for x,y,l,t*/
144 static SANE_Word window_val[2]; /*the value for x,y options*/
145 static int window_val_user[2];	/* is x,y user-specified? */
146 
147 static int accept_only_md5_auth = 0;
148 static const char *icc_profile = NULL;
149 
150 static void fetch_options (SANE_Device * device);
151 static void scanimage_exit (int);
152 
153 static SANE_Word tl_x = 0;
154 static SANE_Word tl_y = 0;
155 static SANE_Word br_x = 0;
156 static SANE_Word br_y = 0;
157 static SANE_Byte *buffer;
158 static size_t buffer_size;
159 
160 
161 static void
auth_callback(SANE_String_Const resource,SANE_Char * username,SANE_Char * password)162 auth_callback (SANE_String_Const resource,
163 	       SANE_Char * username, SANE_Char * password)
164 {
165   char tmp[3 + 128 + SANE_MAX_USERNAME_LEN + SANE_MAX_PASSWORD_LEN], *wipe;
166   unsigned char md5digest[16];
167   int md5mode = 0, len, query_user = 1;
168   FILE *pass_file;
169   struct stat stat_buf;
170   char * uname = NULL;
171 
172   *tmp = 0;
173 
174   if (getenv ("HOME") != NULL)
175     {
176       if (strlen (getenv ("HOME")) < 500)
177 	{
178 	  sprintf (tmp, "%s/.sane/pass", getenv ("HOME"));
179 	}
180     }
181 
182   if ((strlen (tmp) > 0) && (stat (tmp, &stat_buf) == 0))
183     {
184 
185       if ((stat_buf.st_mode & 63) != 0)
186 	{
187 	  fprintf (stderr, "%s has wrong permissions (use at least 0600)\n",
188 		   tmp);
189 	}
190       else
191 	{
192 
193 	  if ((pass_file = fopen (tmp, "r")) != NULL)
194 	    {
195 
196 	      if (strstr (resource, "$MD5$") != NULL)
197 		len = (strstr (resource, "$MD5$") - resource);
198 	      else
199 		len = strlen (resource);
200 
201 	      while (fgets (tmp, sizeof(tmp), pass_file))
202 		{
203 
204 		  if ((strlen (tmp) > 0) && (tmp[strlen (tmp) - 1] == '\n'))
205 		    tmp[strlen (tmp) - 1] = 0;
206 		  if ((strlen (tmp) > 0) && (tmp[strlen (tmp) - 1] == '\r'))
207 		    tmp[strlen (tmp) - 1] = 0;
208 
209 		  char *colon1 = strchr (tmp, ':');
210 		  if (colon1 != NULL)
211 		    {
212 		      char *tmp_username = tmp;
213 		      *colon1 = '\0';
214 
215 		      char *colon2 = strchr (colon1 + 1, ':');
216 		      if (colon2 != NULL)
217 			{
218 			  char *tmp_password = colon1 + 1;
219 			  *colon2 = '\0';
220 
221 			  if ((strncmp (colon2 + 1, resource, len) == 0)
222 			      && ((int) strlen (colon2 + 1) == len))
223 			    {
224 			      if ((strlen (tmp_username) < SANE_MAX_USERNAME_LEN) &&
225                                   (strlen (tmp_password) < SANE_MAX_PASSWORD_LEN))
226                                 {
227                                   strncpy (username, tmp_username, SANE_MAX_USERNAME_LEN);
228                                   strncpy (password, tmp_password, SANE_MAX_PASSWORD_LEN);
229 
230                                   query_user = 0;
231                                   break;
232                                 }
233 			    }
234 			}
235 		    }
236 		}
237 
238 	      fclose (pass_file);
239 	    }
240 	}
241     }
242 
243   if (strstr (resource, "$MD5$") != NULL)
244     {
245       md5mode = 1;
246       len = (strstr (resource, "$MD5$") - resource);
247       if (query_user == 1)
248 	fprintf (stderr, "Authentication required for resource %*.*s. "
249 		 "Enter username: ", len, len, resource);
250     }
251   else
252     {
253 
254       if (accept_only_md5_auth != 0)
255 	{
256 	  fprintf (stderr, "ERROR: backend requested plain-text password\n");
257 	  return;
258 	}
259       else
260 	{
261 	  fprintf (stderr,
262 		   "WARNING: backend requested plain-text password\n");
263 	  query_user = 1;
264 	}
265 
266       if (query_user == 1)
267 	fprintf (stderr,
268 		 "Authentication required for resource %s. Enter username: ",
269 		 resource);
270     }
271 
272   if (query_user == 1)
273     uname = fgets (username, SANE_MAX_USERNAME_LEN, stdin);
274 
275   if (uname != NULL && (strlen (username)) && (username[strlen (username) - 1] == '\n'))
276     username[strlen (username) - 1] = 0;
277 
278   if (query_user == 1)
279     {
280 #ifdef HAVE_GETPASS
281       strcpy (password, (wipe = getpass ("Enter password: ")));
282       memset (wipe, 0, strlen (password));
283 #else
284       printf("OS has no getpass().  User Queries will not work\n");
285 #endif
286     }
287 
288   if (md5mode)
289     {
290 
291       sprintf (tmp, "%.128s%.*s", (strstr (resource, "$MD5$")) + 5,
292 	       SANE_MAX_PASSWORD_LEN - 1, password);
293 
294       md5_buffer (tmp, strlen (tmp), md5digest);
295 
296       memset (password, 0, SANE_MAX_PASSWORD_LEN);
297 
298       sprintf (password, "$MD5$%02x%02x%02x%02x%02x%02x%02x%02x"
299 	       "%02x%02x%02x%02x%02x%02x%02x%02x",
300 	       md5digest[0], md5digest[1],
301 	       md5digest[2], md5digest[3],
302 	       md5digest[4], md5digest[5],
303 	       md5digest[6], md5digest[7],
304 	       md5digest[8], md5digest[9],
305 	       md5digest[10], md5digest[11],
306 	       md5digest[12], md5digest[13], md5digest[14], md5digest[15]);
307     }
308 }
309 
310 static void
sighandler(int signum)311 sighandler (int signum)
312 {
313   static SANE_Bool first_time = SANE_TRUE;
314 
315   if (device)
316     {
317       fprintf (stderr, "%s: received signal %d\n", prog_name, signum);
318       if (first_time)
319 	{
320 	  first_time = SANE_FALSE;
321 	  fprintf (stderr, "%s: trying to stop scanner\n", prog_name);
322 	  sane_cancel (device);
323 	}
324       else
325 	{
326 	  fprintf (stderr, "%s: aborting\n", prog_name);
327 	  _exit (0);
328 	}
329     }
330 }
331 
332 static void
print_unit(SANE_Unit unit)333 print_unit (SANE_Unit unit)
334 {
335   switch (unit)
336     {
337     case SANE_UNIT_NONE:
338       break;
339     case SANE_UNIT_PIXEL:
340       fputs ("pel", stdout);
341       break;
342     case SANE_UNIT_BIT:
343       fputs ("bit", stdout);
344       break;
345     case SANE_UNIT_MM:
346       fputs ("mm", stdout);
347       break;
348     case SANE_UNIT_DPI:
349       fputs ("dpi", stdout);
350       break;
351     case SANE_UNIT_PERCENT:
352       fputc ('%', stdout);
353       break;
354     case SANE_UNIT_MICROSECOND:
355       fputs ("us", stdout);
356       break;
357     }
358 }
359 
360 static void
print_option(SANE_Device * device,int opt_num,const SANE_Option_Descriptor * opt)361 print_option (SANE_Device * device, int opt_num, const SANE_Option_Descriptor *opt)
362 {
363   const char *str, *last_break, *start;
364   SANE_Bool not_first = SANE_FALSE;
365   int i, column;
366 
367   if (opt->type == SANE_TYPE_GROUP){
368     printf ("  %s:\n", opt->title);
369     return;
370   }
371 
372   /* if both of these are set, option is invalid */
373   if((opt->cap & SANE_CAP_SOFT_SELECT) && (opt->cap & SANE_CAP_HARD_SELECT)){
374     fprintf (stderr, "%s: invalid option caps, SS+HS\n", prog_name);
375     return;
376   }
377 
378   /* invalid to select but not detect */
379   if((opt->cap & SANE_CAP_SOFT_SELECT) && !(opt->cap & SANE_CAP_SOFT_DETECT)){
380     fprintf (stderr, "%s: invalid option caps, SS!SD\n", prog_name);
381     return;
382   }
383   /* standard allows this, though it makes little sense
384   if(opt->cap & SANE_CAP_HARD_SELECT && !(opt->cap & SANE_CAP_SOFT_DETECT)){
385     fprintf (stderr, "%s: invalid option caps, HS!SD\n", prog_name);
386     return;
387   }*/
388 
389   /* if one of these three is not set, option is useless, skip it */
390   if(!(opt->cap &
391    (SANE_CAP_SOFT_SELECT | SANE_CAP_HARD_SELECT | SANE_CAP_SOFT_DETECT)
392   )){
393     return;
394   }
395 
396   /* print the option */
397   if ( !strcmp (opt->name, "x")
398     || !strcmp (opt->name, "y")
399     || !strcmp (opt->name, "t")
400     || !strcmp (opt->name, "l"))
401       printf ("    -%s", opt->name);
402   else
403     printf ("    --%s", opt->name);
404 
405   /* print the option choices */
406   if (opt->type == SANE_TYPE_BOOL)
407     {
408       fputs ("[=(", stdout);
409       if (opt->cap & SANE_CAP_AUTOMATIC)
410 	fputs ("auto|", stdout);
411       fputs ("yes|no)]", stdout);
412     }
413   else if (opt->type != SANE_TYPE_BUTTON)
414     {
415       fputc (' ', stdout);
416       if (opt->cap & SANE_CAP_AUTOMATIC)
417 	{
418 	  fputs ("auto|", stdout);
419 	  not_first = SANE_TRUE;
420 	}
421       switch (opt->constraint_type)
422 	{
423 	case SANE_CONSTRAINT_NONE:
424 	  switch (opt->type)
425 	    {
426 	    case SANE_TYPE_INT:
427 	      fputs ("<int>", stdout);
428 	      break;
429 	    case SANE_TYPE_FIXED:
430 	      fputs ("<float>", stdout);
431 	      break;
432 	    case SANE_TYPE_STRING:
433 	      fputs ("<string>", stdout);
434 	      break;
435 	    default:
436 	      break;
437 	    }
438 	  if (opt->type != SANE_TYPE_STRING
439            && opt->size > (SANE_Int) sizeof (SANE_Word))
440 	    fputs (",...", stdout);
441 	  break;
442 
443 	case SANE_CONSTRAINT_RANGE:
444 	  // Check for no range - some buggy backends can miss this out.
445           if (!opt->constraint.range)
446             {
447               fputs ("{no_range}", stdout);
448             }
449           else
450             {
451               if (opt->type == SANE_TYPE_INT)
452                 {
453                   if (!strcmp (opt->name, "x"))
454                     {
455                       printf ("%d..%d", opt->constraint.range->min,
456                               opt->constraint.range->max - tl_x);
457                     }
458                   else if (!strcmp (opt->name, "y"))
459                     {
460                       printf ("%d..%d", opt->constraint.range->min,
461                               opt->constraint.range->max - tl_y);
462                     }
463                   else
464                     {
465                       printf ("%d..%d", opt->constraint.range->min,
466                               opt->constraint.range->max);
467                     }
468                   print_unit (opt->unit);
469                   if (opt->size > (SANE_Int) sizeof(SANE_Word))
470                     fputs (",...", stdout);
471                   if (opt->constraint.range->quant)
472                     printf (" (in steps of %d)", opt->constraint.range->quant);
473                 }
474               else
475                 {
476                   if (!strcmp (opt->name, "x"))
477                     {
478                       printf ("%g..%g", SANE_UNFIX(opt->constraint.range->min),
479                               SANE_UNFIX(opt->constraint.range->max - tl_x));
480                     }
481                   else if (!strcmp (opt->name, "y"))
482                     {
483                       printf ("%g..%g", SANE_UNFIX(opt->constraint.range->min),
484                               SANE_UNFIX(opt->constraint.range->max - tl_y));
485                     }
486                   else
487                     {
488                       printf ("%g..%g", SANE_UNFIX(opt->constraint.range->min),
489                               SANE_UNFIX(opt->constraint.range->max));
490                     }
491                   print_unit (opt->unit);
492                   if (opt->size > (SANE_Int) sizeof(SANE_Word))
493                     fputs (",...", stdout);
494                   if (opt->constraint.range->quant)
495                     printf (" (in steps of %g)",
496                             SANE_UNFIX(opt->constraint.range->quant));
497                 }
498             }
499           break;
500 
501 	case SANE_CONSTRAINT_WORD_LIST:
502 	  // Check no words in list or no list -  - some buggy backends can miss this out.
503 	  // Note the check on < 1 as SANE_Int is signed.
504           if (!opt->constraint.word_list || (opt->constraint.word_list[0] < 1))
505             {
506               fputs ("{no_wordlist}", stdout);
507             }
508           else
509             {
510               for (i = 0; i < opt->constraint.word_list[0]; ++i)
511                 {
512                   if (not_first)
513                     fputc ('|', stdout);
514 
515                   not_first = SANE_TRUE;
516 
517                   if (opt->type == SANE_TYPE_INT)
518                     printf ("%d", opt->constraint.word_list[i + 1]);
519                   else
520                     printf ("%g", SANE_UNFIX(opt->constraint.word_list[i + 1]));
521                 }
522             }
523 
524 	  print_unit (opt->unit);
525 	  if (opt->size > (SANE_Int) sizeof (SANE_Word))
526 	    fputs (",...", stdout);
527 	  break;
528 
529 	case SANE_CONSTRAINT_STRING_LIST:
530           // Check for missing strings - some buggy backends can miss this out.
531           if (!opt->constraint.string_list || !opt->constraint.string_list[0])
532             {
533               fputs ("{no_stringlist}", stdout);
534             }
535           else
536             {
537               for (i = 0; opt->constraint.string_list[i]; ++i)
538                 {
539                   if (i > 0)
540                     fputc ('|', stdout);
541 
542                   fputs (opt->constraint.string_list[i], stdout);
543                 }
544             }
545           break;
546 	}
547     }
548 
549   /* print current option value */
550   if (opt->type == SANE_TYPE_STRING || opt->size == sizeof (SANE_Word))
551     {
552       if (SANE_OPTION_IS_ACTIVE (opt->cap))
553 	{
554 	  void *val = alloca (opt->size);
555 	  sane_control_option (device, opt_num, SANE_ACTION_GET_VALUE, val,
556 			       0);
557 	  fputs (" [", stdout);
558 	  switch (opt->type)
559 	    {
560 	    case SANE_TYPE_BOOL:
561 	      fputs (*(SANE_Bool *) val ? "yes" : "no", stdout);
562 	      break;
563 
564 	    case SANE_TYPE_INT:
565 	      if (strcmp (opt->name, "l") == 0)
566 		{
567 		  tl_x = (*(SANE_Fixed *) val);
568 		  printf ("%d", tl_x);
569 		}
570 	      else if (strcmp (opt->name, "t") == 0)
571 		{
572 		  tl_y = (*(SANE_Fixed *) val);
573 		  printf ("%d", tl_y);
574 		}
575 	      else if (strcmp (opt->name, "x") == 0)
576 		{
577 		  br_x = (*(SANE_Fixed *) val);
578 		  printf ("%d", br_x - tl_x);
579 		}
580 	      else if (strcmp (opt->name, "y") == 0)
581 		{
582 		  br_y = (*(SANE_Fixed *) val);
583 		  printf ("%d", br_y - tl_y);
584 		}
585 	      else
586 		printf ("%d", *(SANE_Int *) val);
587 	      break;
588 
589 	    case SANE_TYPE_FIXED:
590 
591 	      if (strcmp (opt->name, "l") == 0)
592 		{
593 		  tl_x = (*(SANE_Fixed *) val);
594 		  printf ("%g", SANE_UNFIX (tl_x));
595 		}
596 	      else if (strcmp (opt->name, "t") == 0)
597 		{
598 		  tl_y = (*(SANE_Fixed *) val);
599 		  printf ("%g", SANE_UNFIX (tl_y));
600 		}
601 	      else if (strcmp (opt->name, "x") == 0)
602 		{
603 		  br_x = (*(SANE_Fixed *) val);
604 		  printf ("%g", SANE_UNFIX (br_x - tl_x));
605 		}
606 	      else if (strcmp (opt->name, "y") == 0)
607 		{
608 		  br_y = (*(SANE_Fixed *) val);
609 		  printf ("%g", SANE_UNFIX (br_y - tl_y));
610 		}
611 	      else
612 		printf ("%g", SANE_UNFIX (*(SANE_Fixed *) val));
613 
614 	      break;
615 
616 	    case SANE_TYPE_STRING:
617 	      fputs ((char *) val, stdout);
618 	      break;
619 
620 	    default:
621 	      break;
622 	    }
623 	  fputc (']', stdout);
624 	}
625     }
626 
627   if (!SANE_OPTION_IS_ACTIVE (opt->cap))
628     fputs (" [inactive]", stdout);
629 
630   else if(opt->cap & SANE_CAP_HARD_SELECT)
631     fputs (" [hardware]", stdout);
632 
633   else if(!(opt->cap & SANE_CAP_SOFT_SELECT) && (opt->cap & SANE_CAP_SOFT_DETECT))
634     fputs (" [read-only]", stdout);
635 
636   fputs ("\n        ", stdout);
637 
638   column = 8;
639   last_break = 0;
640   start = opt->desc;
641   for (str = opt->desc; *str; ++str)
642     {
643       ++column;
644       if (*str == ' ')
645         last_break = str;
646       else if (*str == '\n'){
647         column=80;
648         last_break = str;
649       }
650       if (column >= 79 && last_break)
651         {
652           while (start < last_break)
653             fputc (*start++, stdout);
654           start = last_break + 1;	/* skip blank */
655           fputs ("\n        ", stdout);
656           column = 8 + (str - start);
657         }
658     }
659   while (*start)
660     fputc (*start++, stdout);
661   fputc ('\n', stdout);
662 }
663 
664 /* A scalar has the following syntax:
665 
666      V [ U ]
667 
668    V is the value of the scalar.  It is either an integer or a
669    floating point number, depending on the option type.
670 
671    U is an optional unit.  If not specified, the default unit is used.
672    The following table lists which units are supported depending on
673    what the option's default unit is:
674 
675      Option's unit:	Allowed units:
676 
677      SANE_UNIT_NONE:
678      SANE_UNIT_PIXEL:	pel
679      SANE_UNIT_BIT:	b (bit), B (byte)
680      SANE_UNIT_MM:	mm (millimeter), cm (centimeter), in or " (inches),
681      SANE_UNIT_DPI:	dpi
682      SANE_UNIT_PERCENT:	%
683      SANE_UNIT_PERCENT:	us
684  */
685 static const char *
parse_scalar(const SANE_Option_Descriptor * opt,const char * str,SANE_Word * value)686 parse_scalar (const SANE_Option_Descriptor * opt, const char *str,
687 	      SANE_Word * value)
688 {
689   char *end;
690   double v;
691 
692   if (opt->type == SANE_TYPE_FIXED)
693     v = strtod (str, &end) * (1 << SANE_FIXED_SCALE_SHIFT);
694   else
695     v = strtol (str, &end, 10);
696 
697   if (str == end)
698     {
699       fprintf (stderr,
700 	       "%s: option --%s: bad option value (rest of option: %s)\n",
701 	       prog_name, opt->name, str);
702       scanimage_exit (1);
703     }
704   str = end;
705 
706   switch (opt->unit)
707     {
708     case SANE_UNIT_NONE:
709     case SANE_UNIT_PIXEL:
710       break;
711 
712     case SANE_UNIT_BIT:
713       if (*str == 'b' || *str == 'B')
714 	{
715 	  if (*str++ == 'B')
716 	    v *= 8;
717 	}
718       break;
719 
720     case SANE_UNIT_MM:
721       if (str[0] == '\0')
722 	v *= 1.0;		/* default to mm */
723       else if (strcmp (str, "mm") == 0)
724 	str += sizeof ("mm") - 1;
725       else if (strcmp (str, "cm") == 0)
726 	{
727 	  str += sizeof ("cm") - 1;
728 	  v *= 10.0;
729 	}
730       else if (strcmp (str, "in") == 0 || *str == '"')
731 	{
732 	  if (*str++ != '"')
733 	    ++str;
734 	  v *= 25.4;		/* 25.4 mm/inch */
735 	}
736       else
737 	{
738 	  fprintf (stderr,
739 		   "%s: option --%s: illegal unit (rest of option: %s)\n",
740 		   prog_name, opt->name, str);
741 	  return 0;
742 	}
743       break;
744 
745     case SANE_UNIT_DPI:
746       if (strcmp (str, "dpi") == 0)
747 	str += sizeof ("dpi") - 1;
748       break;
749 
750     case SANE_UNIT_PERCENT:
751       if (*str == '%')
752 	++str;
753       break;
754 
755     case SANE_UNIT_MICROSECOND:
756       if (strcmp (str, "us") == 0)
757 	str += sizeof ("us") - 1;
758       break;
759     }
760 
761   if(v < 0){
762     *value = v - 0.5;
763   }
764   else{
765     *value = v + 0.5;
766   }
767 
768   return str;
769 }
770 
771 /* A vector has the following syntax:
772 
773      [ '[' I ']' ] S { [','|'-'] [ '[' I ']' S }
774 
775    The number in brackets (I), if present, determines the index of the
776    vector element to be set next.  If I is not present, the value of
777    last index used plus 1 is used.  The first index value used is 0
778    unless I is present.
779 
780    S is a scalar value as defined by parse_scalar().
781 
782    If two consecutive value specs are separated by a comma (,) their
783    values are set independently.  If they are separated by a dash (-),
784    they define the endpoints of a line and all vector values between
785    the two endpoints are set according to the value of the
786    interpolated line.  For example, [0]15-[255]15 defines a vector of
787    256 elements whose value is 15.  Similarly, [0]0-[255]255 defines a
788    vector of 256 elements whose value starts at 0 and increases to
789    255.  */
790 static void
parse_vector(const SANE_Option_Descriptor * opt,const char * str,SANE_Word * vector,size_t vector_length)791 parse_vector (const SANE_Option_Descriptor * opt, const char *str,
792 	      SANE_Word * vector, size_t vector_length)
793 {
794   SANE_Word value, prev_value = 0;
795   int index = -1, prev_index = 0;
796   char *end, separator = '\0';
797 
798   /* initialize vector to all zeroes: */
799   memset (vector, 0, vector_length * sizeof (SANE_Word));
800 
801   do
802     {
803       if (*str == '[')
804 	{
805 	  /* read index */
806 	  index = strtol (++str, &end, 10);
807 	  if (str == end || *end != ']')
808 	    {
809 	      fprintf (stderr, "%s: option --%s: closing bracket missing "
810 		       "(rest of option: %s)\n", prog_name, opt->name, str);
811 	      scanimage_exit (1);
812 	    }
813 	  str = end + 1;
814 	}
815       else
816 	++index;
817 
818       if (index < 0 || index >= (int) vector_length)
819 	{
820 	  fprintf (stderr,
821 		   "%s: option --%s: index %d out of range [0..%ld]\n",
822 		   prog_name, opt->name, index, (long) vector_length - 1);
823 	  scanimage_exit (1);
824 	}
825 
826       /* read value */
827       str = parse_scalar (opt, str, &value);
828       if (!str)
829         scanimage_exit (1);
830 
831       if (*str && *str != '-' && *str != ',')
832 	{
833 	  fprintf (stderr,
834 		   "%s: option --%s: illegal separator (rest of option: %s)\n",
835 		   prog_name, opt->name, str);
836 	  scanimage_exit (1);
837 	}
838 
839       /* store value: */
840       vector[index] = value;
841       if (separator == '-')
842 	{
843 	  /* interpolate */
844 	  double v, slope;
845 	  int i;
846 
847 	  v = (double) prev_value;
848 	  slope = ((double) value - v) / (index - prev_index);
849 
850 	  for (i = prev_index + 1; i < index; ++i)
851 	    {
852 	      v += slope;
853 	      vector[i] = (SANE_Word) v;
854 	    }
855 	}
856 
857       prev_index = index;
858       prev_value = value;
859       separator = *str++;
860     }
861   while (separator == ',' || separator == '-');
862 
863   if (verbose > 2)
864     {
865       int i;
866 
867       fprintf (stderr, "%s: value for --%s is: ", prog_name, opt->name);
868       for (i = 0; i < (int) vector_length; ++i)
869 	if (opt->type == SANE_TYPE_FIXED)
870 	  fprintf (stderr, "%g ", SANE_UNFIX (vector[i]));
871 	else
872 	  fprintf (stderr, "%d ", vector[i]);
873       fputc ('\n', stderr);
874     }
875 }
876 
877 static void
fetch_options(SANE_Device * device)878 fetch_options (SANE_Device * device)
879 {
880   const SANE_Option_Descriptor *opt;
881   SANE_Int num_dev_options;
882   int i, option_count;
883   SANE_Status status;
884 
885   opt = sane_get_option_descriptor (device, 0);
886   if (opt == NULL)
887     {
888       fprintf (stderr, "Could not get option descriptor for option 0\n");
889       scanimage_exit (1);
890     }
891 
892   status = sane_control_option (device, 0, SANE_ACTION_GET_VALUE,
893                                 &num_dev_options, 0);
894   if (status != SANE_STATUS_GOOD)
895     {
896       fprintf (stderr, "Could not get value for option 0: %s\n",
897                sane_strstatus (status));
898       scanimage_exit (1);
899     }
900 
901   /* build the full table of long options */
902   option_count = 0;
903   for (i = 1; i < num_dev_options; ++i)
904     {
905       opt = sane_get_option_descriptor (device, i);
906       if (opt == NULL)
907 	{
908 	  fprintf (stderr, "Could not get option descriptor for option %d\n",i);
909 	  scanimage_exit (1);
910 	}
911 
912       /* create command line option only for settable options */
913       if (!SANE_OPTION_IS_SETTABLE (opt->cap) || opt->type == SANE_TYPE_GROUP)
914 	continue;
915 
916       option_number[option_count] = i;
917 
918       all_options[option_count].name = (const char *) opt->name;
919       all_options[option_count].flag = 0;
920       all_options[option_count].val = 0;
921 
922       if (opt->type == SANE_TYPE_BOOL)
923 	all_options[option_count].has_arg = optional_argument;
924       else if (opt->type == SANE_TYPE_BUTTON)
925 	all_options[option_count].has_arg = no_argument;
926       else
927 	all_options[option_count].has_arg = required_argument;
928 
929       /* Look for scan resolution */
930       if ((opt->type == SANE_TYPE_FIXED || opt->type == SANE_TYPE_INT)
931 	  && opt->size == sizeof (SANE_Int)
932 	  && (opt->unit == SANE_UNIT_DPI)
933 	  && (strcmp (opt->name, SANE_NAME_SCAN_RESOLUTION) == 0))
934 	resolution_optind = i;
935 
936       /* Keep track of top-left corner options (if they exist at
937          all) and replace the bottom-right corner options by a
938          width/height option (if they exist at all).  */
939       if ((opt->type == SANE_TYPE_FIXED || opt->type == SANE_TYPE_INT)
940 	  && opt->size == sizeof (SANE_Int)
941 	  && (opt->unit == SANE_UNIT_MM || opt->unit == SANE_UNIT_PIXEL))
942 	{
943 	  if (strcmp (opt->name, SANE_NAME_SCAN_BR_X) == 0)
944 	    {
945 	      window[0] = i;
946 	      all_options[option_count].name = "width";
947 	      all_options[option_count].val = 'x';
948 	      window_option[0] = *opt;
949 	      window_option[0].title = "Scan width";
950 	      window_option[0].desc = "Width of scan-area.";
951 	      window_option[0].name = "x";
952 	    }
953 	  else if (strcmp (opt->name, SANE_NAME_SCAN_BR_Y) == 0)
954 	    {
955 	      window[1] = i;
956 	      all_options[option_count].name = "height";
957 	      all_options[option_count].val = 'y';
958 	      window_option[1] = *opt;
959 	      window_option[1].title = "Scan height";
960 	      window_option[1].desc = "Height of scan-area.";
961 	      window_option[1].name = "y";
962 	    }
963 	  else if (strcmp (opt->name, SANE_NAME_SCAN_TL_X) == 0)
964 	    {
965 	      window[2] = i;
966 	      all_options[option_count].val = 'l';
967 	      window_option[2] = *opt;
968 	      window_option[2].name = "l";
969 	    }
970 	  else if (strcmp (opt->name, SANE_NAME_SCAN_TL_Y) == 0)
971 	    {
972 	      window[3] = i;
973 	      all_options[option_count].val = 't';
974 	      window_option[3] = *opt;
975 	      window_option[3].name = "t";
976 	    }
977 	}
978       ++option_count;
979     }
980   memcpy (all_options + option_count, basic_options, sizeof (basic_options));
981   option_count += NELEMS (basic_options);
982   memset (all_options + option_count, 0, sizeof (all_options[0]));
983 
984   /* Initialize width & height options based on backend default
985      values for top-left x/y and bottom-right x/y: */
986   for (i = 0; i < 2; ++i)
987     {
988       if (window[i] && !window_val_user[i])
989 	{
990 	  sane_control_option (device, window[i],
991                                 SANE_ACTION_GET_VALUE, &window_val[i], 0);
992           if (window[i + 2]){
993 	    SANE_Word pos;
994 	    sane_control_option (device, window[i + 2],
995 			       SANE_ACTION_GET_VALUE, &pos, 0);
996 	    window_val[i] -= pos;
997           }
998 	}
999     }
1000 }
1001 
1002 static void
set_option(SANE_Handle device,int optnum,void * valuep)1003 set_option (SANE_Handle device, int optnum, void *valuep)
1004 {
1005   const SANE_Option_Descriptor *opt;
1006   SANE_Status status;
1007   SANE_Word orig = 0;
1008   SANE_Int info = 0;
1009 
1010   opt = sane_get_option_descriptor (device, optnum);
1011   if (!opt)
1012     {
1013       if (verbose > 0)
1014         fprintf (stderr, "%s: ignored request to set invalid option %d\n",
1015                  prog_name, optnum);
1016       return;
1017     }
1018 
1019   if (!SANE_OPTION_IS_ACTIVE (opt->cap))
1020     {
1021       if (verbose > 0)
1022 	fprintf (stderr, "%s: ignored request to set inactive option %s\n",
1023 		 prog_name, opt->name);
1024       return;
1025     }
1026 
1027   if (opt->size == sizeof (SANE_Word) && opt->type != SANE_TYPE_STRING)
1028     orig = *(SANE_Word *) valuep;
1029 
1030   status = sane_control_option (device, optnum, SANE_ACTION_SET_VALUE,
1031 				valuep, &info);
1032   if (status != SANE_STATUS_GOOD)
1033     {
1034       fprintf (stderr, "%s: setting of option --%s failed (%s)\n",
1035 	       prog_name, opt->name, sane_strstatus (status));
1036       scanimage_exit (1);
1037     }
1038 
1039   if ((info & SANE_INFO_INEXACT) && opt->size == sizeof (SANE_Word))
1040     {
1041       if (opt->type == SANE_TYPE_INT)
1042 	fprintf (stderr, "%s: rounded value of %s from %d to %d\n",
1043 		 prog_name, opt->name, orig, *(SANE_Word *) valuep);
1044       else if (opt->type == SANE_TYPE_FIXED)
1045 	fprintf (stderr, "%s: rounded value of %s from %g to %g\n",
1046 		 prog_name, opt->name,
1047 		 SANE_UNFIX (orig), SANE_UNFIX (*(SANE_Word *) valuep));
1048     }
1049 
1050   if (info & SANE_INFO_RELOAD_OPTIONS)
1051     fetch_options (device);
1052 }
1053 
1054 static void
process_backend_option(SANE_Handle device,int optnum,const char * optarg)1055 process_backend_option (SANE_Handle device, int optnum, const char *optarg)
1056 {
1057   static SANE_Word *vector = 0;
1058   static size_t vector_size = 0;
1059   const SANE_Option_Descriptor *opt;
1060   size_t vector_length;
1061   SANE_Status status;
1062   SANE_Word value;
1063   void *valuep;
1064 
1065   opt = sane_get_option_descriptor (device, optnum);
1066 
1067   if (!SANE_OPTION_IS_ACTIVE (opt->cap))
1068     {
1069       fprintf (stderr, "%s: attempted to set inactive option %s\n",
1070 	       prog_name, opt->name);
1071       scanimage_exit (1);
1072     }
1073 
1074   if ((opt->cap & SANE_CAP_AUTOMATIC) && optarg &&
1075       strncasecmp (optarg, "auto", 4) == 0)
1076     {
1077       status = sane_control_option (device, optnum, SANE_ACTION_SET_AUTO,
1078 				    0, 0);
1079       if (status != SANE_STATUS_GOOD)
1080 	{
1081 	  fprintf (stderr,
1082 		   "%s: failed to set option --%s to automatic (%s)\n",
1083 		   prog_name, opt->name, sane_strstatus (status));
1084 	  scanimage_exit (1);
1085 	}
1086       return;
1087     }
1088 
1089   valuep = &value;
1090   switch (opt->type)
1091     {
1092     case SANE_TYPE_BOOL:
1093       value = 1;		/* no argument means option is set */
1094       if (optarg)
1095 	{
1096 	  if (strncasecmp (optarg, "yes", strlen (optarg)) == 0)
1097 	    value = 1;
1098 	  else if (strncasecmp (optarg, "no", strlen (optarg)) == 0)
1099 	    value = 0;
1100 	  else
1101 	    {
1102 	      fprintf (stderr, "%s: option --%s: bad option value `%s'\n",
1103 		       prog_name, opt->name, optarg);
1104 	      scanimage_exit (1);
1105 	    }
1106 	}
1107       break;
1108 
1109     case SANE_TYPE_INT:
1110     case SANE_TYPE_FIXED:
1111       /* ensure vector is long enough: */
1112       vector_length = opt->size / sizeof (SANE_Word);
1113       if (vector_size < vector_length)
1114 	{
1115 	  vector_size = vector_length;
1116 	  vector = realloc (vector, vector_length * sizeof (SANE_Word));
1117 	  if (!vector)
1118 	    {
1119 	      fprintf (stderr, "%s: out of memory\n", prog_name);
1120 	      scanimage_exit (1);
1121 	    }
1122 	}
1123       parse_vector (opt, optarg, vector, vector_length);
1124       valuep = vector;
1125       break;
1126 
1127     case SANE_TYPE_STRING:
1128       valuep = malloc (opt->size);
1129       if (!valuep)
1130 	{
1131 	  fprintf (stderr, "%s: out of memory\n", prog_name);
1132 	  scanimage_exit (1);
1133 	}
1134       strncpy (valuep, optarg, opt->size);
1135       ((char *) valuep)[opt->size - 1] = 0;
1136       break;
1137 
1138     case SANE_TYPE_BUTTON:
1139       value = 0;		/* value doesn't matter */
1140       break;
1141 
1142     default:
1143       fprintf (stderr, "%s: duh, got unknown option type %d\n",
1144 	       prog_name, opt->type);
1145       return;
1146     }
1147   set_option (device, optnum, valuep);
1148   if (opt->type == SANE_TYPE_STRING && valuep)
1149     free(valuep);
1150 }
1151 
1152 static void
write_pnm_header(SANE_Frame format,int width,int height,int depth,FILE * ofp)1153 write_pnm_header (SANE_Frame format, int width, int height, int depth, FILE *ofp)
1154 {
1155   /* The netpbm-package does not define raw image data with maxval > 255. */
1156   /* But writing maxval 65535 for 16bit data gives at least a chance */
1157   /* to read the image. */
1158   switch (format)
1159     {
1160     case SANE_FRAME_RED:
1161     case SANE_FRAME_GREEN:
1162     case SANE_FRAME_BLUE:
1163     case SANE_FRAME_RGB:
1164       fprintf (ofp, "P6\n# SANE data follows\n%d %d\n%d\n", width, height,
1165 	      (depth <= 8) ? 255 : 65535);
1166       break;
1167 
1168     default:
1169       if (depth == 1)
1170        fprintf (ofp, "P4\n# SANE data follows\n%d %d\n", width, height);
1171       else
1172        fprintf (ofp, "P5\n# SANE data follows\n%d %d\n%d\n", width, height,
1173 		(depth <= 8) ? 255 : 65535);
1174       break;
1175     }
1176 #ifdef __EMX__			/* OS2 - write in binary mode. */
1177   _fsetmode (ofp, "b");
1178 #endif
1179 }
1180 
1181 #ifdef HAVE_LIBPNG
1182 static void
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)1183 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)
1184 {
1185   int color_type;
1186   /* PNG does not have imperial reference units, so we must convert to metric. */
1187   /* There are nominally 39.3700787401575 inches in a meter. */
1188   const double pixels_per_meter = dpi * 39.3700787401575;
1189   size_t icc_size = 0;
1190   void *icc_buffer;
1191 
1192   *png_ptr = png_create_write_struct
1193        (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1194   if (!*png_ptr) {
1195     fprintf(stderr, "png_create_write_struct failed\n");
1196     exit(1);
1197   }
1198   *info_ptr = png_create_info_struct(*png_ptr);
1199   if (!*info_ptr) {
1200     fprintf(stderr, "png_create_info_struct failed\n");
1201     exit(1);
1202   }
1203   png_init_io(*png_ptr, ofp);
1204 
1205   switch (format)
1206     {
1207     case SANE_FRAME_RED:
1208     case SANE_FRAME_GREEN:
1209     case SANE_FRAME_BLUE:
1210     case SANE_FRAME_RGB:
1211       color_type = PNG_COLOR_TYPE_RGB;
1212       break;
1213 
1214     default:
1215       color_type = PNG_COLOR_TYPE_GRAY;
1216       break;
1217     }
1218 
1219   png_set_IHDR(*png_ptr, *info_ptr, width, height,
1220     depth, color_type, PNG_INTERLACE_NONE,
1221     PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
1222 
1223   png_set_pHYs(*png_ptr, *info_ptr,
1224     pixels_per_meter, pixels_per_meter,
1225     PNG_RESOLUTION_METER);
1226 
1227   if (icc_profile)
1228     {
1229       icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
1230       if (icc_size > 0)
1231         {
1232 	  /* libpng will abort if the profile and image colour spaces do not match*/
1233 	  /* The data colour space field is at bytes 16 to 20 in an ICC profile */
1234 	  /* see: ICC.1:2010 § 7.2.6 */
1235 	  int is_gray_profile = strncmp((char *) icc_buffer + 16, "GRAY", 4) == 0;
1236 	  int is_rgb_profile = strncmp((char *) icc_buffer + 16, "RGB ", 4) == 0;
1237 	  if ((is_gray_profile && color_type == PNG_COLOR_TYPE_GRAY) ||
1238 	      (is_rgb_profile && color_type == PNG_COLOR_TYPE_RGB))
1239 	    {
1240 	      png_set_iCCP(*png_ptr, *info_ptr, basename(icc_profile), PNG_COMPRESSION_TYPE_BASE, icc_buffer, icc_size);
1241 	    }
1242 	  else
1243 	    {
1244 	      if (is_gray_profile)
1245 	        {
1246 		  fprintf(stderr, "Ignoring 'GRAY' space ICC profile because the image is RGB.\n");
1247 	        }
1248 	      if (is_rgb_profile)
1249 	        {
1250 		  fprintf(stderr, "Ignoring 'RGB ' space ICC profile because the image is Grayscale.\n");
1251 		}
1252 	    }
1253 	  free(icc_buffer);
1254 	}
1255     }
1256 
1257   png_write_info(*png_ptr, *info_ptr);
1258 }
1259 #endif
1260 
1261 #ifdef HAVE_LIBJPEG
1262 static void
write_jpeg_header(SANE_Frame format,int width,int height,int dpi,FILE * ofp,struct jpeg_compress_struct * cinfo,struct jpeg_error_mgr * jerr)1263 write_jpeg_header (SANE_Frame format, int width, int height, int dpi, FILE *ofp,
1264                    struct jpeg_compress_struct *cinfo,
1265                    struct jpeg_error_mgr *jerr)
1266 {
1267   cinfo->err = jpeg_std_error(jerr);
1268   jpeg_create_compress(cinfo);
1269   jpeg_stdio_dest(cinfo, ofp);
1270 
1271   cinfo->image_width = width;
1272   cinfo->image_height = height;
1273   switch (format)
1274     {
1275     case SANE_FRAME_RED:
1276     case SANE_FRAME_GREEN:
1277     case SANE_FRAME_BLUE:
1278     case SANE_FRAME_RGB:
1279       cinfo->in_color_space = JCS_RGB;
1280       cinfo->input_components = 3;
1281       break;
1282 
1283     default:
1284       cinfo->in_color_space = JCS_GRAYSCALE;
1285       cinfo->input_components = 1;
1286       break;
1287     }
1288 
1289   jpeg_set_defaults(cinfo);
1290   /* jpeg_set_defaults overrides density, be careful. */
1291   cinfo->density_unit = 1;   /* Inches */
1292   cinfo->X_density = cinfo->Y_density = dpi;
1293   cinfo->write_JFIF_header = TRUE;
1294 
1295   jpeg_set_quality(cinfo, 75, TRUE);
1296   jpeg_start_compress(cinfo, TRUE);
1297 }
1298 #endif
1299 
1300 static void *
advance(Image * image)1301 advance (Image * image)
1302 {
1303   if (++image->x >= image->width)
1304     {
1305       image->x = 0;
1306       if (++image->y >= image->height || !image->data)
1307 	{
1308 	  size_t old_size = 0, new_size;
1309 
1310 	  if (image->data)
1311 	    old_size = image->height * image->width * image->num_channels;
1312 
1313 	  image->height += STRIP_HEIGHT;
1314 	  new_size = image->height * image->width * image->num_channels;
1315 
1316 	  if (image->data)
1317 	    image->data = realloc (image->data, new_size);
1318 	  else
1319 	    image->data = malloc (new_size);
1320 	  if (image->data)
1321 	    memset (image->data + old_size, 0, new_size - old_size);
1322 	}
1323     }
1324   if (!image->data)
1325     fprintf (stderr, "%s: can't allocate image buffer (%dx%d)\n",
1326 	     prog_name, image->width, image->height);
1327   return image->data;
1328 }
1329 
1330 static SANE_Status
scan_it(FILE * ofp)1331 scan_it (FILE *ofp)
1332 {
1333   int i, len, first_frame = 1, offset = 0, must_buffer = 0;
1334   uint64_t hundred_percent = 0;
1335   SANE_Byte min = 0xff, max = 0;
1336   SANE_Parameters parm;
1337   SANE_Status status;
1338   Image image = { 0, 0, 0, 0, 0, 0 };
1339   static const char *format_name[] = {
1340     "gray", "RGB", "red", "green", "blue"
1341   };
1342   uint64_t total_bytes = 0, expected_bytes;
1343   SANE_Int hang_over = -1;
1344 #ifdef HAVE_LIBPNG
1345   int pngrow = 0;
1346   png_bytep pngbuf = NULL;
1347   png_structp png_ptr;
1348   png_infop info_ptr;
1349 #endif
1350 #ifdef HAVE_LIBJPEG
1351   int jpegrow = 0;
1352   JSAMPLE *jpegbuf = NULL;
1353   struct jpeg_compress_struct cinfo;
1354   struct jpeg_error_mgr jerr;
1355 #endif
1356 
1357   do
1358     {
1359       if (!first_frame)
1360 	{
1361 #ifdef SANE_STATUS_WARMING_UP
1362           do
1363 	    {
1364 	      status = sane_start (device);
1365 	    }
1366 	  while(status == SANE_STATUS_WARMING_UP);
1367 #else
1368 	  status = sane_start (device);
1369 #endif
1370 	  if (status != SANE_STATUS_GOOD)
1371 	    {
1372 	      fprintf (stderr, "%s: sane_start: %s\n",
1373 		       prog_name, sane_strstatus (status));
1374 	      goto cleanup;
1375 	    }
1376 	}
1377 
1378       status = sane_get_parameters (device, &parm);
1379       if (status != SANE_STATUS_GOOD)
1380 	{
1381 	  fprintf (stderr, "%s: sane_get_parameters: %s\n",
1382 		   prog_name, sane_strstatus (status));
1383 	  goto cleanup;
1384 	}
1385 
1386       if (verbose)
1387 	{
1388 	  if (first_frame)
1389 	    {
1390 	      if (parm.lines >= 0)
1391 		fprintf (stderr, "%s: scanning image of size %dx%d pixels at "
1392 			 "%d bits/pixel\n",
1393 			 prog_name, parm.pixels_per_line, parm.lines,
1394 			 parm.depth * (SANE_FRAME_RGB == parm.format ? 3 : 1));
1395 	      else
1396 		fprintf (stderr, "%s: scanning image %d pixels wide and "
1397 			 "variable height at %d bits/pixel\n",
1398 			 prog_name, parm.pixels_per_line,
1399 			 parm.depth * (SANE_FRAME_RGB == parm.format ? 3 : 1));
1400 	    }
1401 
1402 	  fprintf (stderr, "%s: acquiring %s frame\n", prog_name,
1403 	   parm.format <= SANE_FRAME_BLUE ? format_name[parm.format]:"Unknown");
1404 	}
1405 
1406       if (first_frame)
1407 	{
1408           image.num_channels = 1;
1409 	  switch (parm.format)
1410 	    {
1411 	    case SANE_FRAME_RED:
1412 	    case SANE_FRAME_GREEN:
1413 	    case SANE_FRAME_BLUE:
1414 	      assert (parm.depth == 8);
1415 	      must_buffer = 1;
1416 	      offset = parm.format - SANE_FRAME_RED;
1417 	      image.num_channels = 3;
1418 	      break;
1419 
1420 	    case SANE_FRAME_RGB:
1421 	      assert ((parm.depth == 8) || (parm.depth == 16));
1422 	    case SANE_FRAME_GRAY:
1423 	      assert ((parm.depth == 1) || (parm.depth == 8)
1424 		      || (parm.depth == 16));
1425 	      if (parm.lines < 0)
1426 		{
1427 		  must_buffer = 1;
1428 		  offset = 0;
1429 		}
1430 	      else
1431 		  switch(output_format)
1432 		  {
1433 		  case OUTPUT_TIFF:
1434 		    sanei_write_tiff_header (parm.format,
1435 					     parm.pixels_per_line, parm.lines,
1436 					     parm.depth, resolution_value,
1437 					     icc_profile, ofp);
1438 		    break;
1439 		  case OUTPUT_PNM:
1440 		    write_pnm_header (parm.format, parm.pixels_per_line,
1441 				      parm.lines, parm.depth, ofp);
1442 		    break;
1443 #ifdef HAVE_LIBPNG
1444 		  case OUTPUT_PNG:
1445 		    write_png_header (parm.format, parm.pixels_per_line,
1446 				      parm.lines, parm.depth, resolution_value,
1447 				      icc_profile, ofp, &png_ptr, &info_ptr);
1448 		    break;
1449 #endif
1450 #ifdef HAVE_LIBJPEG
1451 		  case OUTPUT_JPEG:
1452 		    write_jpeg_header (parm.format, parm.pixels_per_line,
1453 				       parm.lines, resolution_value,
1454 				       ofp, &cinfo, &jerr);
1455 		    break;
1456 #endif
1457 		  }
1458 	      break;
1459 
1460             default:
1461 	      break;
1462 	    }
1463 #ifdef HAVE_LIBPNG
1464 	  if(output_format == OUTPUT_PNG)
1465 	    pngbuf = malloc(parm.bytes_per_line);
1466 #endif
1467 #ifdef HAVE_LIBJPEG
1468 	  if(output_format == OUTPUT_JPEG)
1469 	    jpegbuf = malloc(parm.bytes_per_line);
1470 #endif
1471 
1472 	  if (must_buffer)
1473 	    {
1474 	      /* We're either scanning a multi-frame image or the
1475 		 scanner doesn't know what the eventual image height
1476 		 will be (common for hand-held scanners).  In either
1477 		 case, we need to buffer all data before we can write
1478 		 the image.  */
1479 	      image.width = parm.bytes_per_line;
1480 
1481 	      if (parm.lines >= 0)
1482 		/* See advance(); we allocate one extra line so we
1483 		   don't end up realloc'ing in when the image has been
1484 		   filled in.  */
1485 		image.height = parm.lines - STRIP_HEIGHT + 1;
1486 	      else
1487 		image.height = 0;
1488 
1489 	      image.x = image.width - 1;
1490 	      image.y = -1;
1491 	      if (!advance (&image))
1492 		{
1493 		  status = SANE_STATUS_NO_MEM;
1494 		  goto cleanup;
1495 		}
1496 	    }
1497 	}
1498       else
1499 	{
1500 	  assert (parm.format >= SANE_FRAME_RED
1501 		  && parm.format <= SANE_FRAME_BLUE);
1502 	  offset = parm.format - SANE_FRAME_RED;
1503 	  image.x = image.y = 0;
1504 	}
1505       hundred_percent = ((uint64_t)parm.bytes_per_line) * parm.lines
1506 	* ((parm.format == SANE_FRAME_RGB || parm.format == SANE_FRAME_GRAY) ? 1:3);
1507 
1508       while (1)
1509 	{
1510 	  double progr;
1511 	  status = sane_read (device, buffer, buffer_size, &len);
1512 	  total_bytes += (SANE_Word) len;
1513           progr = ((total_bytes * 100.) / (double) hundred_percent);
1514           if (progr > 100.)
1515 	    progr = 100.;
1516           if (progress)
1517             {
1518               if (parm.lines >= 0)
1519                 fprintf(stderr, "Progress: %3.1f%%\r", progr);
1520               else
1521                 fprintf(stderr, "Progress: (unknown)\r");
1522             }
1523 
1524 	  if (status != SANE_STATUS_GOOD)
1525 	    {
1526 	      if (verbose && parm.depth == 8)
1527 		fprintf (stderr, "%s: min/max graylevel value = %d/%d\n",
1528 			 prog_name, min, max);
1529 	      if (status != SANE_STATUS_EOF)
1530 		{
1531 		  fprintf (stderr, "%s: sane_read: %s\n",
1532 			   prog_name, sane_strstatus (status));
1533 		  return status;
1534 		}
1535 	      break;
1536 	    }
1537 
1538 	  if (must_buffer)
1539 	    {
1540 	      switch (parm.format)
1541 		{
1542 		case SANE_FRAME_RED:
1543 		case SANE_FRAME_GREEN:
1544 		case SANE_FRAME_BLUE:
1545 		  image.num_channels = 3;
1546 		  for (i = 0; i < len; ++i)
1547 		    {
1548 		      image.data[offset + 3 * i] = buffer[i];
1549 		      if (!advance (&image))
1550 			{
1551 			  status = SANE_STATUS_NO_MEM;
1552 			  goto cleanup;
1553 			}
1554 		    }
1555 		  offset += 3 * len;
1556 		  break;
1557 
1558 		case SANE_FRAME_RGB:
1559 		  image.num_channels = 1;
1560 		  for (i = 0; i < len; ++i)
1561 		    {
1562 		      image.data[offset + i] = buffer[i];
1563 		      if (!advance (&image))
1564 			  {
1565 			    status = SANE_STATUS_NO_MEM;
1566 			    goto cleanup;
1567 			  }
1568 		    }
1569 		  offset += len;
1570 		  break;
1571 
1572 		case SANE_FRAME_GRAY:
1573 		  image.num_channels = 1;
1574 		  for (i = 0; i < len; ++i)
1575 		    {
1576 		      image.data[offset + i] = buffer[i];
1577 		      if (!advance (&image))
1578 			  {
1579 			    status = SANE_STATUS_NO_MEM;
1580 			    goto cleanup;
1581 			  }
1582 		    }
1583 		  offset += len;
1584 		  break;
1585 
1586                 default:
1587 		  break;
1588 		}
1589 	    }
1590 	  else			/* ! must_buffer */
1591 	    {
1592 #ifdef HAVE_LIBPNG
1593 	      if (output_format == OUTPUT_PNG)
1594 	        {
1595 		  int i = 0;
1596 		  int left = len;
1597 		  while(pngrow + left >= parm.bytes_per_line)
1598 		    {
1599 		      memcpy(pngbuf + pngrow, buffer + i, parm.bytes_per_line - pngrow);
1600 		      if(parm.depth == 1)
1601 			{
1602 			  int j;
1603 			  for(j = 0; j < parm.bytes_per_line; j++)
1604 			    pngbuf[j] = ~pngbuf[j];
1605 			}
1606 #ifndef WORDS_BIGENDIAN
1607                       /* SANE is endian-native, PNG is big-endian, */
1608                       /* see: https://www.w3.org/TR/2003/REC-PNG-20031110/#7Integers-and-byte-order */
1609                       if (parm.depth == 16)
1610                         {
1611                           int j;
1612                           for (j = 0; j < parm.bytes_per_line; j += 2)
1613                             {
1614                               SANE_Byte LSB;
1615                               LSB = pngbuf[j];
1616                               pngbuf[j] = pngbuf[j + 1];
1617                               pngbuf[j + 1] = LSB;
1618                             }
1619                         }
1620 #endif
1621 		      png_write_row(png_ptr, pngbuf);
1622 		      i += parm.bytes_per_line - pngrow;
1623 		      left -= parm.bytes_per_line - pngrow;
1624 		      pngrow = 0;
1625 		    }
1626 		  memcpy(pngbuf + pngrow, buffer + i, left);
1627 		  pngrow += left;
1628 		}
1629 	      else
1630 #endif
1631 #ifdef HAVE_LIBJPEG
1632 	      if (output_format == OUTPUT_JPEG)
1633 	        {
1634 		  int i = 0;
1635 		  int left = len;
1636 		  while(jpegrow + left >= parm.bytes_per_line)
1637 		    {
1638 		      memcpy(jpegbuf + jpegrow, buffer + i, parm.bytes_per_line - jpegrow);
1639 		      if(parm.depth == 1)
1640 			{
1641 			  int col1, col8;
1642 			  JSAMPLE *buf8 = malloc(parm.bytes_per_line * 8);
1643 			  for(col1 = 0; col1 < parm.bytes_per_line; col1++)
1644 			    for(col8 = 0; col8 < 8; col8++)
1645 			      buf8[col1 * 8 + col8] = jpegbuf[col1] & (1 << (8 - col8 - 1)) ? 0 : 0xff;
1646 		          jpeg_write_scanlines(&cinfo, &buf8, 1);
1647 			  free(buf8);
1648 			} else {
1649 		          jpeg_write_scanlines(&cinfo, &jpegbuf, 1);
1650 			}
1651 		      i += parm.bytes_per_line - jpegrow;
1652 		      left -= parm.bytes_per_line - jpegrow;
1653 		      jpegrow = 0;
1654 		    }
1655 		  memcpy(jpegbuf + jpegrow, buffer + i, left);
1656 		  jpegrow += left;
1657 		}
1658 	      else
1659 #endif
1660 	      if ((output_format == OUTPUT_TIFF) || (parm.depth != 16))
1661 		fwrite (buffer, 1, len, ofp);
1662 	      else
1663 		{
1664 #if !defined(WORDS_BIGENDIAN)
1665 		  int i, start = 0;
1666 
1667 		  /* check if we have saved one byte from the last sane_read */
1668 		  if (hang_over > -1)
1669 		    {
1670 		      if (len > 0)
1671 			{
1672 			  fwrite (buffer, 1, 1, ofp);
1673 			  buffer[0] = (SANE_Byte) hang_over;
1674 			  hang_over = -1;
1675 			  start = 1;
1676 			}
1677 		    }
1678 		  /* now do the byte-swapping */
1679 		  for (i = start; i < (len - 1); i += 2)
1680 		    {
1681 		      unsigned char LSB;
1682 		      LSB = buffer[i];
1683 		      buffer[i] = buffer[i + 1];
1684 		      buffer[i + 1] = LSB;
1685 		    }
1686 		  /* check if we have an odd number of bytes */
1687 		  if (((len - start) % 2) != 0)
1688 		    {
1689 		      hang_over = buffer[len - 1];
1690 		      len--;
1691 		    }
1692 #endif
1693 		  fwrite (buffer, 1, len, ofp);
1694 		}
1695 	    }
1696 
1697 	  if (verbose && parm.depth == 8)
1698 	    {
1699 	      for (i = 0; i < len; ++i)
1700 		if (buffer[i] >= max)
1701 		  max = buffer[i];
1702 		else if (buffer[i] < min)
1703 		  min = buffer[i];
1704 	    }
1705 	}
1706       first_frame = 0;
1707     }
1708   while (!parm.last_frame);
1709 
1710   if (must_buffer)
1711     {
1712       image.height = image.y;
1713 
1714       switch(output_format) {
1715       case OUTPUT_TIFF:
1716 	sanei_write_tiff_header (parm.format, parm.pixels_per_line,
1717 				 image.height, parm.depth, resolution_value,
1718 				 icc_profile, ofp);
1719       break;
1720       case OUTPUT_PNM:
1721 	write_pnm_header (parm.format, parm.pixels_per_line,
1722                           image.height, parm.depth, ofp);
1723       break;
1724 #ifdef HAVE_LIBPNG
1725       case OUTPUT_PNG:
1726 	write_png_header (parm.format, parm.pixels_per_line,
1727 			  image.height, parm.depth, resolution_value,
1728 			  icc_profile, ofp, &png_ptr, &info_ptr);
1729       break;
1730 #endif
1731 #ifdef HAVE_LIBJPEG
1732       case OUTPUT_JPEG:
1733 	write_jpeg_header (parm.format, parm.pixels_per_line,
1734 			   parm.lines, resolution_value,
1735 			   ofp, &cinfo, &jerr);
1736       break;
1737 #endif
1738       }
1739 
1740 #if !defined(WORDS_BIGENDIAN)
1741       /* multibyte pnm file may need byte swap to LE */
1742       /* FIXME: other bit depths? */
1743       if (output_format != OUTPUT_TIFF && parm.depth == 16)
1744 	{
1745 	  int i;
1746 	  for (i = 0; i < image.height * image.width; i += 2)
1747 	    {
1748 	      unsigned char LSB;
1749 	      LSB = image.data[i];
1750 	      image.data[i] = image.data[i + 1];
1751 	      image.data[i + 1] = LSB;
1752 	    }
1753 	}
1754 #endif
1755 
1756 	fwrite (image.data, 1, image.height * image.width * image.num_channels, ofp);
1757     }
1758 #ifdef HAVE_LIBPNG
1759     if(output_format == OUTPUT_PNG)
1760 	png_write_end(png_ptr, info_ptr);
1761 #endif
1762 #ifdef HAVE_LIBJPEG
1763     if(output_format == OUTPUT_JPEG)
1764 	jpeg_finish_compress(&cinfo);
1765 #endif
1766 
1767   /* flush the output buffer */
1768   fflush( ofp );
1769 
1770 cleanup:
1771 #ifdef HAVE_LIBPNG
1772   if(output_format == OUTPUT_PNG) {
1773     png_destroy_write_struct(&png_ptr, &info_ptr);
1774     free(pngbuf);
1775   }
1776 #endif
1777 #ifdef HAVE_LIBJPEG
1778   if(output_format == OUTPUT_JPEG) {
1779     jpeg_destroy_compress(&cinfo);
1780     free(jpegbuf);
1781   }
1782 #endif
1783   if (image.data)
1784     free (image.data);
1785 
1786 
1787   expected_bytes = ((uint64_t)parm.bytes_per_line) * parm.lines *
1788     ((parm.format == SANE_FRAME_RGB
1789       || parm.format == SANE_FRAME_GRAY) ? 1 : 3);
1790   if (parm.lines < 0)
1791     expected_bytes = 0;
1792   if (total_bytes > expected_bytes && expected_bytes != 0)
1793     {
1794       fprintf (stderr,
1795 	       "%s: WARNING: read more data than announced by backend "
1796                "(%" PRIu64 "/%" PRIu64 ")\n", prog_name, total_bytes, expected_bytes);
1797     }
1798   else if (verbose)
1799     fprintf (stderr, "%s: read %" PRIu64 " bytes in total\n", prog_name, total_bytes);
1800 
1801   return status;
1802 }
1803 
1804 #define clean_buffer(buf,size)	memset ((buf), 0x23, size)
1805 
1806 static void
pass_fail(int max,int len,SANE_Byte * buffer,SANE_Status status)1807 pass_fail (int max, int len, SANE_Byte * buffer, SANE_Status status)
1808 {
1809   if (status != SANE_STATUS_GOOD)
1810     fprintf (stderr, "FAIL Error: %s\n", sane_strstatus (status));
1811   else if (buffer[len] != 0x23)
1812     {
1813       while (len <= max && buffer[len] != 0x23)
1814 	++len;
1815       fprintf (stderr, "FAIL Cheat: %d bytes\n", len);
1816     }
1817   else if (len > max)
1818     fprintf (stderr, "FAIL Overflow: %d bytes\n", len);
1819   else if (len == 0)
1820     fprintf (stderr, "FAIL No data\n");
1821   else
1822     fprintf (stderr, "PASS\n");
1823 }
1824 
1825 static SANE_Status
test_it(void)1826 test_it (void)
1827 {
1828   int i, len;
1829   SANE_Parameters parm;
1830   SANE_Status status;
1831   Image image = { 0, 0, 0, 0, 0, 0 };
1832   static const char *format_name[] =
1833     { "gray", "RGB", "red", "green", "blue" };
1834 
1835 #ifdef SANE_STATUS_WARMING_UP
1836   do
1837     {
1838       status = sane_start (device);
1839     }
1840   while(status == SANE_STATUS_WARMING_UP);
1841 #else
1842   status = sane_start (device);
1843 #endif
1844 
1845   if (status != SANE_STATUS_GOOD)
1846     {
1847       fprintf (stderr, "%s: sane_start: %s\n",
1848 	       prog_name, sane_strstatus (status));
1849       goto cleanup;
1850     }
1851 
1852   status = sane_get_parameters (device, &parm);
1853   if (status != SANE_STATUS_GOOD)
1854     {
1855       fprintf (stderr, "%s: sane_get_parameters: %s\n",
1856 	       prog_name, sane_strstatus (status));
1857       goto cleanup;
1858     }
1859 
1860   if (parm.lines >= 0)
1861     fprintf (stderr, "%s: scanning image of size %dx%d pixels at "
1862 	     "%d bits/pixel\n", prog_name, parm.pixels_per_line, parm.lines,
1863 	     parm.depth * (SANE_FRAME_RGB == parm.format ? 3 : 1));
1864   else
1865     fprintf (stderr, "%s: scanning image %d pixels wide and "
1866 	     "variable height at %d bits/pixel\n",
1867 	     prog_name, parm.pixels_per_line,
1868 	     parm.depth * (SANE_FRAME_RGB == parm.format ? 3 : 1));
1869   fprintf (stderr, "%s: acquiring %s frame, %d bits/sample\n", prog_name,
1870 	   parm.format <= SANE_FRAME_BLUE ? format_name[parm.format]:"Unknown",
1871            parm.depth);
1872 
1873   image.data = malloc (parm.bytes_per_line * 2);
1874 
1875   clean_buffer (image.data, parm.bytes_per_line * 2);
1876   fprintf (stderr, "%s: reading one scanline, %d bytes...\t", prog_name,
1877 	   parm.bytes_per_line);
1878   status = sane_read (device, image.data, parm.bytes_per_line, &len);
1879   pass_fail (parm.bytes_per_line, len, image.data, status);
1880   if (status != SANE_STATUS_GOOD)
1881     goto cleanup;
1882 
1883   clean_buffer (image.data, parm.bytes_per_line * 2);
1884   fprintf (stderr, "%s: reading one byte...\t\t", prog_name);
1885   status = sane_read (device, image.data, 1, &len);
1886   pass_fail (1, len, image.data, status);
1887   if (status != SANE_STATUS_GOOD)
1888     goto cleanup;
1889 
1890   for (i = 2; i < parm.bytes_per_line * 2; i *= 2)
1891     {
1892       clean_buffer (image.data, parm.bytes_per_line * 2);
1893       fprintf (stderr, "%s: stepped read, %d bytes... \t", prog_name, i);
1894       status = sane_read (device, image.data, i, &len);
1895       pass_fail (i, len, image.data, status);
1896       if (status != SANE_STATUS_GOOD)
1897 	goto cleanup;
1898     }
1899 
1900   for (i /= 2; i > 2; i /= 2)
1901     {
1902       clean_buffer (image.data, parm.bytes_per_line * 2);
1903       fprintf (stderr, "%s: stepped read, %d bytes... \t", prog_name, i - 1);
1904       status = sane_read (device, image.data, i - 1, &len);
1905       pass_fail (i - 1, len, image.data, status);
1906       if (status != SANE_STATUS_GOOD)
1907 	goto cleanup;
1908     }
1909 
1910 cleanup:
1911   sane_cancel (device);
1912   if (image.data)
1913     free (image.data);
1914   return status;
1915 }
1916 
1917 
1918 static int
get_resolution(void)1919 get_resolution (void)
1920 {
1921   const SANE_Option_Descriptor *resopt;
1922   int resol = 0;
1923   void *val;
1924 
1925   if (resolution_optind < 0)
1926     return 0;
1927   resopt = sane_get_option_descriptor (device, resolution_optind);
1928   if (!resopt)
1929     return 0;
1930 
1931   val = alloca (resopt->size);
1932   if (!val)
1933     return 0;
1934 
1935   sane_control_option (device, resolution_optind, SANE_ACTION_GET_VALUE, val,
1936 		       0);
1937   if (resopt->type == SANE_TYPE_INT)
1938     resol = *(SANE_Int *) val;
1939   else
1940     resol = (int) (SANE_UNFIX (*(SANE_Fixed *) val) + 0.5);
1941 
1942   return resol;
1943 }
1944 
1945 static void
scanimage_exit(int status)1946 scanimage_exit (int status)
1947 {
1948   if (device)
1949     {
1950       if (verbose > 1)
1951 	fprintf (stderr, "Closing device\n");
1952       sane_close (device);
1953     }
1954   if (verbose > 1)
1955     fprintf (stderr, "Calling sane_exit\n");
1956   sane_exit ();
1957 
1958   if (all_options)
1959     free (all_options);
1960   if (option_number)
1961     free (option_number);
1962   if (verbose > 1)
1963     fprintf (stderr, "scanimage: finished\n");
1964   exit (status);
1965 }
1966 
1967 /** @brief print device options to stdout
1968  *
1969  * @param device struct of the opened device to describe
1970  * @param num_dev_options number of device options
1971  * @param ro SANE_TRUE to print read-only options
1972  */
print_options(SANE_Device * device,SANE_Int num_dev_options,SANE_Bool ro)1973 static void print_options(SANE_Device * device, SANE_Int num_dev_options, SANE_Bool ro)
1974 {
1975   int i, j;
1976   const SANE_Option_Descriptor *opt;
1977 
1978   for (i = 1; i < num_dev_options; ++i)
1979     {
1980       opt = 0;
1981 
1982       /* scan area uses modified option struct */
1983       for (j = 0; j < 4; ++j)
1984 	if (i == window[j])
1985 	  opt = window_option + j;
1986 
1987       if (!opt)
1988 	opt = sane_get_option_descriptor (device, i);
1989 
1990       if (ro || SANE_OPTION_IS_SETTABLE (opt->cap)
1991 	  || opt->type == SANE_TYPE_GROUP)
1992 	print_option (device, i, opt);
1993     }
1994   if (num_dev_options)
1995     fputc ('\n', stdout);
1996 }
1997 
guess_output_format(const char * output_file)1998 static int guess_output_format(const char* output_file)
1999 {
2000   if (output_file == NULL)
2001     {
2002       fprintf(stderr, "Output format is not set, using pnm as a default.\n");
2003       return OUTPUT_PNM;
2004     }
2005 
2006   // if the user passes us a path with a known extension then he won't be surprised if we figure
2007   // out correct --format option. No warning is necessary in that case.
2008   const char* extension = strrchr(output_file, '.');
2009   if (extension != NULL)
2010     {
2011       struct {
2012         const char* extension;
2013         int output_format;
2014       } formats[] = {
2015         { ".pnm", OUTPUT_PNM },
2016         { ".png", OUTPUT_PNG },
2017         { ".jpg", OUTPUT_JPEG },
2018         { ".jpeg", OUTPUT_JPEG },
2019         { ".tiff", OUTPUT_TIFF },
2020         { ".tif", OUTPUT_TIFF }
2021       };
2022       for (unsigned i = 0; i < sizeof(formats) / sizeof(formats[0]); ++i)
2023         {
2024           if (strcmp(extension, formats[i].extension) == 0)
2025             return formats[i].output_format;
2026         }
2027     }
2028 
2029   // it would be very confusing if user makes a typo in the filename and the output format changes.
2030   // This is most likely not what the user wanted.
2031   fprintf(stderr, "Could not guess output format from the given path and no --format given.\n");
2032   exit(1);
2033 }
2034 
2035 int
main(int argc,char ** argv)2036 main (int argc, char **argv)
2037 {
2038   int ch, i, index, all_options_len;
2039   const SANE_Device **device_list;
2040   SANE_Int num_dev_options = 0;
2041   const char *devname = 0;
2042   const char *defdevname = 0;
2043   const char *format = 0;
2044   char readbuf[2];
2045   char *readbuf2;
2046   int batch = 0;
2047   int batch_print = 0;
2048   int batch_prompt = 0;
2049   int batch_count = BATCH_COUNT_UNLIMITED;
2050   int batch_start_at = 1;
2051   int batch_increment = 1;
2052   SANE_Status status;
2053   char *full_optstring;
2054   SANE_Int version_code;
2055   FILE *ofp = NULL;
2056 
2057   buffer_size = (32 * 1024);	/* default size */
2058 
2059   prog_name = strrchr (argv[0], '/');
2060   if (prog_name)
2061     ++prog_name;
2062   else
2063     prog_name = argv[0];
2064 
2065   defdevname = getenv ("SANE_DEFAULT_DEVICE");
2066 
2067   sane_init (&version_code, auth_callback);
2068 
2069   /* make a first pass through the options with error printing and argument
2070      permutation disabled: */
2071   opterr = 0;
2072   while ((ch = getopt_long (argc, argv, "-" BASE_OPTSTRING, basic_options,
2073 			    &index)) != EOF)
2074     {
2075       switch (ch)
2076 	{
2077 	case ':':
2078 	case '?':
2079 	  break;		/* may be an option that we'll parse later on */
2080 	case 'd':
2081 	  devname = optarg;
2082 	  break;
2083 	case 'b':
2084 	  /* This may have already been set by the batch-count flag */
2085 	  batch = 1;
2086 	  format = optarg;
2087 	  break;
2088 	case 'h':
2089 	  help = 1;
2090 	  break;
2091 	case 'i':		/* icc profile */
2092 	  icc_profile = optarg;
2093 	  break;
2094 	case 'v':
2095 	  ++verbose;
2096 	  break;
2097 	case 'p':
2098           progress = 1;
2099 	  break;
2100         case 'o':
2101           output_file = optarg;
2102           break;
2103 	case 'B':
2104           if (optarg)
2105 	    buffer_size = 1024 * atoi(optarg);
2106           else
2107 	    buffer_size = (1024 * 1024);
2108 	  break;
2109 	case 'T':
2110 	  test = 1;
2111 	  break;
2112 	case 'A':
2113 	  all = 1;
2114 	  break;
2115 	case 'n':
2116 	  dont_scan = 1;
2117 	  break;
2118 	case OPTION_BATCH_PRINT:
2119 	  batch_print = 1;
2120 	  break;
2121 	case OPTION_BATCH_PROMPT:
2122 	  batch_prompt = 1;
2123 	  break;
2124 	case OPTION_BATCH_INCREMENT:
2125 	  batch_increment = atoi (optarg);
2126 	  break;
2127 	case OPTION_BATCH_START_AT:
2128 	  batch_start_at = atoi (optarg);
2129 	  break;
2130 	case OPTION_BATCH_DOUBLE:
2131 	  batch_increment = 2;
2132 	  break;
2133 	case OPTION_BATCH_COUNT:
2134 	  batch_count = atoi (optarg);
2135 	  batch = 1;
2136 	  break;
2137 	case OPTION_FORMAT:
2138 	  if (strcmp (optarg, "tiff") == 0)
2139 	    output_format = OUTPUT_TIFF;
2140 	  else if (strcmp (optarg, "png") == 0)
2141 	    {
2142 #ifdef HAVE_LIBPNG
2143 	      output_format = OUTPUT_PNG;
2144 #else
2145 	      fprintf(stderr, "PNG support not compiled in\n");
2146 	      exit(1);
2147 #endif
2148 	    }
2149 	  else if (strcmp (optarg, "jpeg") == 0)
2150 	    {
2151 #ifdef HAVE_LIBJPEG
2152 	      output_format = OUTPUT_JPEG;
2153 #else
2154 	      fprintf(stderr, "JPEG support not compiled in\n");
2155 	      exit(1);
2156 #endif
2157 	    }
2158           else if (strcmp (optarg, "pnm") == 0)
2159             {
2160               output_format = OUTPUT_PNM;
2161             }
2162           else
2163             {
2164               fprintf(stderr, "Unknown output image format '%s'.\n", optarg);
2165               fprintf(stderr, "Supported formats: pnm, tiff");
2166 #ifdef HAVE_LIBPNG
2167               fprintf(stderr, ", png");
2168 #endif
2169 #ifdef HAVE_LIBJPEG
2170               fprintf(stderr, ", jpeg");
2171 #endif
2172               fprintf(stderr, ".\n");
2173               exit(1);
2174             }
2175 	  break;
2176 	case OPTION_MD5:
2177 	  accept_only_md5_auth = 1;
2178 	  break;
2179 	case 'L':
2180 	case 'f':
2181 	  {
2182 	    int i = 0;
2183 
2184 	    status = sane_get_devices (&device_list, SANE_FALSE);
2185 	    if (status != SANE_STATUS_GOOD)
2186 	      {
2187 		fprintf (stderr, "%s: sane_get_devices() failed: %s\n",
2188 			 prog_name, sane_strstatus (status));
2189 		scanimage_exit (1);
2190 	      }
2191 
2192 	    if (ch == 'L')
2193 	      {
2194 		for (i = 0; device_list[i]; ++i)
2195 		  {
2196 		    printf ("device `%s' is a %s %s %s\n",
2197 			    device_list[i]->name, device_list[i]->vendor,
2198 			    device_list[i]->model, device_list[i]->type);
2199 		  }
2200 	      }
2201 	    else
2202 	      {
2203 		int i = 0, int_arg = 0;
2204 		const char *percent, *start;
2205 		const char *text_arg = 0;
2206 		char ftype;
2207 
2208 		for (i = 0; device_list[i]; ++i)
2209 		  {
2210 		    start = optarg;
2211 		    while (*start && (percent = strchr (start, '%')))
2212 		      {
2213 			int start_len = percent - start;
2214 			percent++;
2215 			if (*percent)
2216 			  {
2217 			    switch (*percent)
2218 			      {
2219 			      case 'd':
2220 				text_arg = device_list[i]->name;
2221 				ftype = 's';
2222 				break;
2223 			      case 'v':
2224 				text_arg = device_list[i]->vendor;
2225 				ftype = 's';
2226 				break;
2227 			      case 'm':
2228 				text_arg = device_list[i]->model;
2229 				ftype = 's';
2230 				break;
2231 			      case 't':
2232 				text_arg = device_list[i]->type;
2233 				ftype = 's';
2234 				break;
2235 			      case 'i':
2236 				int_arg = i;
2237 				ftype = 'i';
2238 				break;
2239 			      case 'n':
2240 				text_arg = "\n";
2241 				ftype = 's';
2242 				break;
2243 			      case '%':
2244 				text_arg = "%";
2245 				ftype = 's';
2246 				break;
2247 			      default:
2248 				fprintf (stderr,
2249 					 "%s: unknown format specifier %%%c\n",
2250 					 prog_name, *percent);
2251                                 text_arg = "%";
2252 				ftype = 's';
2253 			      }
2254 			    printf ("%.*s", start_len, start);
2255 			    switch (ftype)
2256 			      {
2257 			      case 's':
2258 				printf ("%s", text_arg);
2259 				break;
2260 			      case 'i':
2261 				printf ("%i", int_arg);
2262 				break;
2263 			      }
2264 			    start = percent + 1;
2265 			  }
2266 			else
2267 			  {
2268 			    /* last char of the string is a '%', ignore it */
2269 			    start++;
2270 			    break;
2271 			  }
2272 		      }
2273 		    if (*start)
2274 		      printf ("%s", start);
2275 		  }
2276 	      }
2277 	    if (i == 0 && ch != 'f')
2278 	      printf ("\nNo scanners were identified. If you were expecting "
2279                 "something different,\ncheck that the scanner is plugged "
2280 		"in, turned on and detected by the\nsane-find-scanner tool "
2281 		"(if appropriate). Please read the documentation\nwhich came "
2282 		"with this software (README, FAQ, manpages).\n");
2283 
2284 	    if (defdevname)
2285 	      printf ("default device is `%s'\n", defdevname);
2286 	    scanimage_exit (0);
2287 	    break;
2288 	  }
2289 	case 'V':
2290 	  printf ("scanimage (%s) %s; backend version %d.%d.%d\n", PACKAGE,
2291 		  VERSION, SANE_VERSION_MAJOR (version_code),
2292 		  SANE_VERSION_MINOR (version_code),
2293 		  SANE_VERSION_BUILD (version_code));
2294 	  scanimage_exit (0);
2295 	  break;
2296 	default:
2297 	  break;		/* ignore device specific options for now */
2298 	}
2299     }
2300 
2301   if (help)
2302     {
2303       printf ("Usage: %s [OPTION]...\n\
2304 \n\
2305 Start image acquisition on a scanner device and write image data to\n\
2306 standard output.\n\
2307 \n\
2308 Parameters are separated by a blank from single-character options (e.g.\n\
2309 -d epson) and by a \"=\" from multi-character options (e.g. --device-name=epson).\n\
2310 -d, --device-name=DEVICE   use a given scanner device (e.g. hp:/dev/scanner)\n\
2311     --format=pnm|tiff|png|jpeg  file format of output file\n\
2312 -i, --icc-profile=PROFILE  include this ICC profile into TIFF file\n", prog_name);
2313       printf ("\
2314 -L, --list-devices         show available scanner devices\n\
2315 -f, --formatted-device-list=FORMAT similar to -L, but the FORMAT of the output\n\
2316                            can be specified: %%d (device name), %%v (vendor),\n\
2317                            %%m (model), %%t (type), %%i (index number), and\n\
2318                            %%n (newline)\n\
2319 -b, --batch[=FORMAT]       working in batch mode, FORMAT is `out%%d.pnm' `out%%d.tif'\n\
2320                            `out%%d.png' or `out%%d.jpg' by default depending on --format\n\
2321                            This option is incompatible with --output-file.");
2322       printf ("\
2323     --batch-start=#        page number to start naming files with\n\
2324     --batch-count=#        how many pages to scan in batch mode\n\
2325     --batch-increment=#    increase page number in filename by #\n\
2326     --batch-double         increment page number by two, same as\n\
2327                            --batch-increment=2\n\
2328     --batch-print          print image filenames to stdout\n\
2329     --batch-prompt         ask for pressing a key before scanning a page\n");
2330       printf ("\
2331     --accept-md5-only      only accept authorization requests using md5\n\
2332 -p, --progress             print progress messages\n\
2333 -o, --output-file=PATH     save output to the given file instead of stdout.\n\
2334                            This option is incompatible with --batch.\n\
2335 -n, --dont-scan            only set options, don't actually scan\n\
2336 -T, --test                 test backend thoroughly\n\
2337 -A, --all-options          list all available backend options\n\
2338 -h, --help                 display this help message and exit\n\
2339 -v, --verbose              give even more status messages\n\
2340 -B, --buffer-size=#        change input buffer size (in kB, default 32)\n");
2341       printf ("\
2342 -V, --version              print version information\n");
2343     }
2344 
2345   if (batch && output_file != NULL)
2346     {
2347       fprintf(stderr, "--batch and --output-file can't be used together.\n");
2348       exit(1);
2349     }
2350 
2351   if (output_format == OUTPUT_UNKNOWN)
2352     output_format = guess_output_format(output_file);
2353 
2354   if (!devname)
2355     {
2356       /* If no device name was specified explicitly, we look at the
2357          environment variable SANE_DEFAULT_DEVICE.  If this variable
2358          is not set, we open the first device we find (if any): */
2359       devname = defdevname;
2360       if (!devname)
2361 	{
2362 	  status = sane_get_devices (&device_list, SANE_FALSE);
2363 	  if (status != SANE_STATUS_GOOD)
2364 	    {
2365 	      fprintf (stderr, "%s: sane_get_devices() failed: %s\n",
2366 		       prog_name, sane_strstatus (status));
2367 	      scanimage_exit (1);
2368 	    }
2369 	  if (!device_list[0])
2370 	    {
2371 	      fprintf (stderr, "%s: no SANE devices found\n", prog_name);
2372 	      scanimage_exit (1);
2373 	    }
2374 	  devname = device_list[0]->name;
2375 	}
2376     }
2377 
2378   status = sane_open (devname, &device);
2379   if (status != SANE_STATUS_GOOD)
2380     {
2381       fprintf (stderr, "%s: open of device %s failed: %s\n",
2382 	       prog_name, devname, sane_strstatus (status));
2383       if (devname[0] == '/')
2384 	fprintf (stderr, "\nYou seem to have specified a UNIX device name, "
2385 		 "or filename instead of selecting\nthe SANE scanner or "
2386 		 "image acquisition device you want to use. As an example,\n"
2387 		 "you might want \"epson:/dev/sg0\" or "
2388 		 "\"hp:/dev/usbscanner0\". If any supported\ndevices are "
2389 		 "installed in your system, you should be able to see a "
2390 		 "list with\n\"scanimage --list-devices\".\n");
2391       if (help)
2392 	device = 0;
2393       else
2394         scanimage_exit (1);
2395     }
2396 
2397   if (device)
2398     {
2399       const SANE_Option_Descriptor * desc_ptr;
2400 
2401       /* Good form to always get the descriptor once before value */
2402       desc_ptr = sane_get_option_descriptor(device, 0);
2403       if (!desc_ptr)
2404 	{
2405 	  fprintf (stderr, "%s: unable to get option count descriptor\n",
2406 		   prog_name);
2407 	  scanimage_exit (1);
2408 	}
2409 
2410       /* We got a device, find out how many options it has */
2411       status = sane_control_option (device, 0, SANE_ACTION_GET_VALUE,
2412 				    &num_dev_options, 0);
2413       if (status != SANE_STATUS_GOOD)
2414 	{
2415 	  fprintf (stderr, "%s: unable to determine option count\n",
2416 		   prog_name);
2417 	  scanimage_exit (1);
2418 	}
2419 
2420       /* malloc global option lists */
2421       all_options_len = num_dev_options + NELEMS (basic_options) + 1;
2422       all_options = malloc (all_options_len * sizeof (all_options[0]));
2423       option_number_len = num_dev_options;
2424       option_number = malloc (option_number_len * sizeof (option_number[0]));
2425       if (!all_options || !option_number)
2426 	{
2427 	  fprintf (stderr, "%s: out of memory in main()\n",
2428 		   prog_name);
2429 	  scanimage_exit (1);
2430 	}
2431 
2432       /* load global option lists */
2433       fetch_options (device);
2434 
2435       {
2436 	char *larg, *targ, *xarg, *yarg;
2437 	larg = targ = xarg = yarg = "";
2438 
2439 	/* Maybe accept t, l, x, and y options. */
2440 	if (window[0])
2441 	  xarg = "x:";
2442 
2443 	if (window[1])
2444 	  yarg = "y:";
2445 
2446 	if (window[2])
2447 	  larg = "l:";
2448 
2449 	if (window[3])
2450 	  targ = "t:";
2451 
2452 	/* Now allocate the full option list. */
2453 	full_optstring = malloc (strlen (BASE_OPTSTRING)
2454 				 + strlen (larg) + strlen (targ)
2455 				 + strlen (xarg) + strlen (yarg) + 1);
2456 
2457 	if (!full_optstring)
2458 	  {
2459 	    fprintf (stderr, "%s: out of memory\n", prog_name);
2460 	    scanimage_exit (1);
2461 	  }
2462 
2463 	strcpy (full_optstring, BASE_OPTSTRING);
2464 	strcat (full_optstring, larg);
2465 	strcat (full_optstring, targ);
2466 	strcat (full_optstring, xarg);
2467 	strcat (full_optstring, yarg);
2468       }
2469 
2470       /* re-run argument processing with backend-specific options included
2471        * this time, enable error printing and arg permutation */
2472       optind = 0;
2473       opterr = 1;
2474       while ((ch = getopt_long (argc, argv, full_optstring, all_options,
2475 				&index)) != EOF)
2476 	{
2477 	  switch (ch)
2478 	    {
2479 	    case ':':
2480 	    case '?':
2481 	      scanimage_exit (1);		/* error message is printed by getopt_long() */
2482 
2483 	    case 'd':
2484 	    case 'h':
2485 	    case 'p':
2486             case 'o':
2487 	    case 'v':
2488 	    case 'V':
2489 	    case 'T':
2490 	    case 'B':
2491 	      /* previously handled options */
2492 	      break;
2493 
2494 	    case 'x':
2495 	      window_val_user[0] = 1;
2496 	      parse_vector (&window_option[0], optarg, &window_val[0], 1);
2497 	      break;
2498 
2499 	    case 'y':
2500 	      window_val_user[1] = 1;
2501 	      parse_vector (&window_option[1], optarg, &window_val[1], 1);
2502 	      break;
2503 
2504 	    case 'l':		/* tl-x */
2505 	      process_backend_option (device, window[2], optarg);
2506 	      break;
2507 
2508 	    case 't':		/* tl-y */
2509 	      process_backend_option (device, window[3], optarg);
2510 	      break;
2511 
2512 	    case 0:
2513 	      process_backend_option (device, option_number[index], optarg);
2514 	      break;
2515 	    }
2516 	}
2517       if (optind < argc)
2518 	{
2519 	  fprintf (stderr, "%s: argument without option: `%s'; ", prog_name,
2520 		   argv[argc - 1]);
2521 	  fprintf (stderr, "try %s --help\n", prog_name);
2522 	  scanimage_exit (1);
2523 	}
2524 
2525       free (full_optstring);
2526 
2527       /* convert x/y to br_x/br_y */
2528       for (index = 0; index < 2; ++index)
2529 	if (window[index])
2530 	  {
2531             SANE_Word pos = 0;
2532 	    SANE_Word val = window_val[index];
2533 
2534 	    if (window[index + 2])
2535 	      {
2536 		sane_control_option (device, window[index + 2],
2537 				     SANE_ACTION_GET_VALUE, &pos, 0);
2538 		val += pos;
2539 	      }
2540 	    set_option (device, window[index], &val);
2541 	  }
2542 
2543       /* output device-specific help */
2544       if (help)
2545 	{
2546 	  printf ("\nOptions specific to device `%s':\n", devname);
2547 	  print_options(device, num_dev_options, SANE_FALSE);
2548 	}
2549 
2550       /*  list all device-specific options */
2551       if (all)
2552 	{
2553 	  printf ("\nAll options specific to device `%s':\n", devname);
2554 	  print_options(device, num_dev_options, SANE_TRUE);
2555 	  scanimage_exit (0);
2556 	}
2557     }
2558 
2559   /* output device list */
2560   if (help)
2561     {
2562       printf ("\
2563 Type ``%s --help -d DEVICE'' to get list of all options for DEVICE.\n\
2564 \n\
2565 List of available devices:", prog_name);
2566       status = sane_get_devices (&device_list, SANE_FALSE);
2567       if (status == SANE_STATUS_GOOD)
2568 	{
2569 	  int column = 80;
2570 
2571 	  for (i = 0; device_list[i]; ++i)
2572 	    {
2573 	      if (column + strlen (device_list[i]->name) + 1 >= 80)
2574 		{
2575 		  printf ("\n    ");
2576 		  column = 4;
2577 		}
2578 	      if (column > 4)
2579 		{
2580 		  fputc (' ', stdout);
2581 		  column += 1;
2582 		}
2583 	      fputs (device_list[i]->name, stdout);
2584 	      column += strlen (device_list[i]->name);
2585 	    }
2586 	}
2587       fputc ('\n', stdout);
2588       scanimage_exit (0);
2589     }
2590 
2591   if (dont_scan)
2592     scanimage_exit (0);
2593 
2594   if (output_format != OUTPUT_PNM)
2595     resolution_value = get_resolution ();
2596 
2597 #ifdef SIGHUP
2598   signal (SIGHUP, sighandler);
2599 #endif
2600 #ifdef SIGPIPE
2601   signal (SIGPIPE, sighandler);
2602 #endif
2603   signal (SIGINT, sighandler);
2604   signal (SIGTERM, sighandler);
2605 
2606   if (test == 0)
2607     {
2608       int n = batch_start_at;
2609 
2610       if (batch && NULL == format)
2611 	{
2612 	  switch(output_format) {
2613 	  case OUTPUT_TIFF:
2614 	    format = "out%d.tif";
2615 	    break;
2616 	  case OUTPUT_PNM:
2617 	    format = "out%d.pnm";
2618 	    break;
2619 #ifdef HAVE_LIBPNG
2620 	  case OUTPUT_PNG:
2621 	    format = "out%d.png";
2622 	    break;
2623 #endif
2624 #ifdef HAVE_LIBJPEG
2625 	  case OUTPUT_JPEG:
2626 	    format = "out%d.jpg";
2627 	    break;
2628 #endif
2629 	  }
2630 	}
2631 
2632       if (!batch)
2633         {
2634           ofp = stdout;
2635           if (output_file != NULL)
2636             {
2637               ofp = fopen(output_file, "w");
2638               if (ofp == NULL)
2639                 {
2640                   fprintf(stderr, "%s: could not open output file '%s', "
2641                           "exiting\n", prog_name, output_file);
2642                   scanimage_exit(1);
2643                 }
2644             }
2645         }
2646 
2647       if (batch)
2648 	{
2649 	  fputs("Scanning ", stderr);
2650 	  if (batch_count == BATCH_COUNT_UNLIMITED)
2651 	    fputs("infinity", stderr);
2652 	  else
2653 	    fprintf(stderr, "%d", batch_count);
2654 	  fprintf (stderr,
2655 		   " page%s, incrementing by %d, numbering from %d\n",
2656 		   batch_count == 1 ? "" : "s", batch_increment, batch_start_at);
2657 	}
2658 
2659       else if(isatty(fileno(ofp))){
2660 	fprintf (stderr,"%s: output is not a file, exiting\n", prog_name);
2661 	scanimage_exit (1);
2662       }
2663 
2664       buffer = malloc (buffer_size);
2665 
2666       do
2667 	{
2668 	  char path[PATH_MAX];
2669 	  char part_path[PATH_MAX];
2670 	  if (batch)		/* format is NULL unless batch mode */
2671 	    {
2672 	      sprintf (path, format, n);	/* love --(C++) */
2673 	      strcpy (part_path, path);
2674 	      strcat (part_path, ".part");
2675 	    }
2676 
2677 
2678 	  if (batch)
2679 	    {
2680 	      if (batch_prompt)
2681 		{
2682 		  fprintf (stderr, "Place document no. %d on the scanner.\n",
2683 			   n);
2684 		  fprintf (stderr, "Press <RETURN> to continue.\n");
2685 		  fprintf (stderr, "Press Ctrl + D to terminate.\n");
2686 		  readbuf2 = fgets (readbuf, 2, stdin);
2687 
2688 		  if (readbuf2 == NULL)
2689 		    {
2690 		      if (ofp)
2691 			{
2692 			  fclose (ofp);
2693 			  ofp = NULL;
2694 			}
2695 		      break;	/* get out of this loop */
2696 		    }
2697 		}
2698 	      fprintf (stderr, "Scanning page %d\n", n);
2699 	    }
2700 
2701 #ifdef SANE_STATUS_WARMING_UP
2702           do
2703 	    {
2704 	      status = sane_start (device);
2705 	    }
2706 	  while(status == SANE_STATUS_WARMING_UP);
2707 #else
2708 	  status = sane_start (device);
2709 #endif
2710 	  if (status != SANE_STATUS_GOOD)
2711 	    {
2712 	      fprintf (stderr, "%s: sane_start: %s\n",
2713 		       prog_name, sane_strstatus (status));
2714 	      if (ofp)
2715 		{
2716 		  fclose (ofp);
2717 		  ofp = NULL;
2718 		}
2719 	      break;
2720 	    }
2721 
2722 
2723 	  /* write to .part file while scanning is in progress */
2724 	  if (batch)
2725 	    {
2726 	      if (NULL == (ofp = fopen (part_path, "w")))
2727 		{
2728 		  fprintf (stderr, "cannot open %s\n", part_path);
2729 		  sane_cancel (device);
2730 		  return SANE_STATUS_ACCESS_DENIED;
2731 		}
2732 	    }
2733 
2734 	  status = scan_it (ofp);
2735 	  if (batch)
2736 	    {
2737 	      fprintf (stderr, "Scanned page %d.", n);
2738 	      fprintf (stderr, " (scanner status = %d)\n", status);
2739 	    }
2740 
2741 	  switch (status)
2742 	    {
2743 	    case SANE_STATUS_GOOD:
2744 	    case SANE_STATUS_EOF:
2745 	      status = SANE_STATUS_GOOD;
2746 	      if (batch)
2747 		{
2748 		  if (!ofp || 0 != fclose(ofp))
2749 		    {
2750 		      fprintf (stderr, "cannot close image file\n");
2751 		      sane_cancel (device);
2752 		      return SANE_STATUS_ACCESS_DENIED;
2753 		    }
2754 		  else
2755 		    {
2756 		      ofp = NULL;
2757 		      /* let the fully scanned file show up */
2758 		      if (rename (part_path, path))
2759 			{
2760 			  fprintf (stderr, "cannot rename %s to %s\n",
2761 				part_path, path);
2762 			  sane_cancel (device);
2763 			  return SANE_STATUS_ACCESS_DENIED;
2764 			}
2765 		      if (batch_print)
2766 			{
2767 			  fprintf (stdout, "%s\n", path);
2768 			  fflush (stdout);
2769 			}
2770 		    }
2771 		}
2772               else
2773                 {
2774                   if (output_file && ofp)
2775                     {
2776                       fclose(ofp);
2777                       ofp = NULL;
2778                     }
2779                 }
2780 	      break;
2781 	    default:
2782 	      if (batch)
2783 		{
2784 		  if (ofp)
2785 		    {
2786 		      fclose (ofp);
2787 		      ofp = NULL;
2788 		    }
2789 		  unlink (part_path);
2790 		}
2791               else
2792                 {
2793                   if (output_file && ofp)
2794                     {
2795                       fclose(ofp);
2796                       ofp = NULL;
2797                     }
2798                   unlink (output_file);
2799                 }
2800 	      break;
2801 	    }			/* switch */
2802 	  n += batch_increment;
2803 	}
2804       while ((batch
2805 	      && (batch_count == BATCH_COUNT_UNLIMITED || --batch_count))
2806 	     && SANE_STATUS_GOOD == status);
2807 
2808       if (batch)
2809 	{
2810 	  int num_pgs = (n - batch_start_at) / batch_increment;
2811 	  fprintf (stderr, "Batch terminated, %d page%s scanned\n",
2812 		   num_pgs, num_pgs == 1 ? "" : "s");
2813 	}
2814 
2815       if (batch
2816 	  && SANE_STATUS_NO_DOCS == status
2817 	  && (batch_count == BATCH_COUNT_UNLIMITED)
2818 	  && n > batch_start_at)
2819 	status = SANE_STATUS_GOOD;
2820 
2821       sane_cancel (device);
2822     }
2823   else
2824     status = test_it ();
2825 
2826   scanimage_exit (status);
2827   /* the line below avoids compiler warnings */
2828   return status;
2829 }
2830