diff options
Diffstat (limited to 'frontend/scanimage.c')
| -rw-r--r-- | frontend/scanimage.c | 201 | 
1 files changed, 103 insertions, 98 deletions
| diff --git a/frontend/scanimage.c b/frontend/scanimage.c index d79d487..ff53157 100644 --- a/frontend/scanimage.c +++ b/frontend/scanimage.c @@ -39,15 +39,8 @@  #include <string.h>  #include <unistd.h>  #include <stdarg.h> - -#ifdef __FreeBSD__ -#include <libgen.h> -#endif - -#if defined (__APPLE__) && defined (__MACH__) +#include <errno.h>  #include <libgen.h>     // for basename() -#endif -  #include <sys/types.h>  #include <sys/stat.h> @@ -111,7 +104,7 @@ static struct option basic_options[] = {    {"test", no_argument, NULL, 'T'},    {"all-options", no_argument, NULL, 'A'},    {"version", no_argument, NULL, 'V'}, -  {"buffer-size", optional_argument, NULL, 'B'}, +  {"buffer-size", required_argument, NULL, 'B'},    {"batch", optional_argument, NULL, 'b'},    {"batch-count", required_argument, NULL, OPTION_BATCH_COUNT},    {"batch-start", required_argument, NULL, OPTION_BATCH_START_AT}, @@ -133,29 +126,30 @@ static struct option basic_options[] = {  #define OUTPUT_JPEG     4  #define OUTPUT_PDF      5 -#define BASE_OPTSTRING	"d:hi:Lf:o:B::nvVTAbp" +#define BASE_OPTSTRING	"d:hi:Lf:o:B:nvVTAbp"  #define STRIP_HEIGHT	256	/* # lines we increment image height */ -static struct option *all_options; -static int option_number_len; -static int *option_number; -static SANE_Handle device; -static int verbose; +static struct option *all_options = NULL; +static int option_number_len = 0; +static int *option_number = 0; +static SANE_Handle device = 0; +static int verbose = 0;  static int progress = 0;  static const char* output_file = NULL; -static int test; -static int all; +static int test = 0; +static int all = 0;  static int output_format = OUTPUT_UNKNOWN; -static int help; +static int help = 0;  static int dont_scan = 0; -static const char *prog_name; +static const char *prog_name = NULL;  static int resolution_optind = -1, resolution_value = 0;  /* window (area) related options */ -static SANE_Option_Descriptor window_option[4]; /*updated descs for x,y,l,t*/ -static int window[4]; /*index into backend options for x,y,l,t*/ -static SANE_Word window_val[2]; /*the value for x,y options*/ -static int window_val_user[2];	/* is x,y user-specified? */ +static SANE_Option_Descriptor window_option[4] = {0}; /*updated descs for x,y,l,t*/ +static int window[4] = {0}; /*index into backend options for x,y,l,t*/ +static SANE_Word window_val[2] = {0}; /*the value for x,y options*/ +static int window_val_user[2] = {0};	/* is x,y user-specified? */ +static char *full_optstring = NULL;  static int accept_only_md5_auth = 0;  static const char *icc_profile = NULL; @@ -167,18 +161,16 @@ static SANE_Word tl_x = 0;  static SANE_Word tl_y = 0;  static SANE_Word br_x = 0;  static SANE_Word br_y = 0; -static SANE_Byte *buffer; -static size_t buffer_size; +static SANE_Byte *buffer = NULL; +static size_t buffer_size = 0;  static void  auth_callback (SANE_String_Const resource,  	       SANE_Char * username, SANE_Char * password)  { -  char tmp[3 + 128 + SANE_MAX_USERNAME_LEN + SANE_MAX_PASSWORD_LEN], *wipe; -  unsigned char md5digest[16]; +  char tmp[3 + 128 + SANE_MAX_USERNAME_LEN + SANE_MAX_PASSWORD_LEN];    int md5mode = 0, len, query_user = 1; -  FILE *pass_file;    struct stat stat_buf;    char * uname = NULL; @@ -202,6 +194,7 @@ auth_callback (SANE_String_Const resource,  	}        else  	{ +          FILE *pass_file;  	  if ((pass_file = fopen (tmp, "r")) != NULL)  	    { @@ -291,6 +284,7 @@ auth_callback (SANE_String_Const resource,    if (query_user == 1)      {  #ifdef HAVE_GETPASS +      char *wipe;        strcpy (password, (wipe = getpass ("Enter password: ")));        memset (wipe, 0, strlen (password));  #else @@ -300,6 +294,7 @@ auth_callback (SANE_String_Const resource,    if (md5mode)      { +      unsigned char md5digest[16];        sprintf (tmp, "%.128s%.*s", (strstr (resource, "$MD5$")) + 5,  	       SANE_MAX_PASSWORD_LEN - 1, password); @@ -323,10 +318,10 @@ auth_callback (SANE_String_Const resource,  static void  sighandler (int signum)  { -  static SANE_Bool first_time = SANE_TRUE; -    if (device)      { +      static SANE_Bool first_time = SANE_TRUE; +        fprintf (stderr, "%s: received signal %d\n", prog_name, signum);        if (first_time)  	{ @@ -1210,18 +1205,17 @@ write_png_header (SANE_Frame format, int width, int height, int depth, int dpi,    /* 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);    if (!*png_ptr) {      fprintf(stderr, "png_create_write_struct failed\n"); -    exit(1); +    scanimage_exit (1);    }    *info_ptr = png_create_info_struct(*png_ptr);    if (!*info_ptr) {      fprintf(stderr, "png_create_info_struct failed\n"); -    exit(1); +    scanimage_exit (1);    }    png_init_io(*png_ptr, ofp); @@ -1249,7 +1243,7 @@ write_png_header (SANE_Frame format, int width, int height, int depth, int dpi,    if (icc_profile)      { -      icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size); +      void *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*/ @@ -1260,7 +1254,21 @@ write_png_header (SANE_Frame format, int width, int height, int depth, int dpi,  	  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); +	      char *icc_profile_cp = strdup(icc_profile); +	      if (icc_profile_cp == NULL) +	        { +                  fprintf(stderr, "Memory allocation failure prevented the setting of PNG ICC profile.\n"); +	        } +	      else +	        { +                  png_set_iCCP (*png_ptr, +                                *info_ptr, +                                basename (icc_profile_cp), +                                PNG_COMPRESSION_TYPE_BASE, +                                icc_buffer, +                                icc_size); +                  free(icc_profile_cp); +	        }  	    }  	  else  	    { @@ -1625,11 +1633,11 @@ scan_it (FILE *ofp, void* pw)  #ifdef HAVE_LIBPNG  	      if (output_format == OUTPUT_PNG)  	        { -		  int i = 0; +		  int idx = 0;  		  int left = len;  		  while(pngrow + left >= parm.bytes_per_line)  		    { -		      memcpy(pngbuf + pngrow, buffer + i, parm.bytes_per_line - pngrow); +		      memcpy(pngbuf + pngrow, buffer + idx, parm.bytes_per_line - pngrow);  		      if(parm.depth == 1)  			{  			  int j; @@ -1652,11 +1660,11 @@ scan_it (FILE *ofp, void* pw)                          }  #endif  		      png_write_row(png_ptr, pngbuf); -		      i += parm.bytes_per_line - pngrow; +		      idx += parm.bytes_per_line - pngrow;  		      left -= parm.bytes_per_line - pngrow;  		      pngrow = 0;  		    } -		  memcpy(pngbuf + pngrow, buffer + i, left); +		  memcpy(pngbuf + pngrow, buffer + idx, left);  		  pngrow += left;  		}  	      else @@ -1664,28 +1672,28 @@ scan_it (FILE *ofp, void* pw)  #ifdef HAVE_LIBJPEG  	      if (output_format == OUTPUT_JPEG || output_format == OUTPUT_PDF)  	        { -		  int i = 0; +		  int idx = 0;  		  int left = len;  		  while(jpegrow + left >= parm.bytes_per_line)  		    { -		      memcpy(jpegbuf + jpegrow, buffer + i, parm.bytes_per_line - jpegrow); +		      memcpy(jpegbuf + jpegrow, buffer + idx, parm.bytes_per_line - jpegrow);  		      if(parm.depth == 1)  			{  			  int col1, col8;  			  JSAMPLE *buf8 = malloc(parm.bytes_per_line * 8);  			  for(col1 = 0; col1 < parm.bytes_per_line; col1++)  			    for(col8 = 0; col8 < 8; col8++) -			      buf8[col1 * 8 + col8] = jpegbuf[col1] & (1 << (8 - col8 - 1)) ? 0 : 0xff; +			      buf8[col1 * 8 + col8] = (jpegbuf[col1] & (1 << (8 - col8 - 1))) ? 0 : 0xff;  		          jpeg_write_scanlines(&cinfo, &buf8, 1);  			  free(buf8);  			} else {  		          jpeg_write_scanlines(&cinfo, &jpegbuf, 1);  			} -		      i += parm.bytes_per_line - jpegrow; +		      idx += parm.bytes_per_line - jpegrow;  		      left -= parm.bytes_per_line - jpegrow;  		      jpegrow = 0;  		    } -		  memcpy(jpegbuf + jpegrow, buffer + i, left); +		  memcpy(jpegbuf + jpegrow, buffer + idx, left);  		  jpegrow += left;  		}  	      else @@ -1695,7 +1703,7 @@ scan_it (FILE *ofp, void* pw)  	      else  		{  #if !defined(WORDS_BIGENDIAN) -		  int i, start = 0; +		  int start = 0;  		  /* check if we have saved one byte from the last sane_read */  		  if (hang_over > -1) @@ -1709,12 +1717,12 @@ scan_it (FILE *ofp, void* pw)  			}  		    }  		  /* now do the byte-swapping */ -		  for (i = start; i < (len - 1); i += 2) +		  for (int idx = start; idx < (len - 1); idx += 2)  		    {  		      unsigned char LSB; -		      LSB = buffer[i]; -		      buffer[i] = buffer[i + 1]; -		      buffer[i + 1] = LSB; +		      LSB = buffer[idx]; +		      buffer[idx] = buffer[idx + 1]; +		      buffer[idx + 1] = LSB;  		    }  		  /* check if we have an odd number of bytes */  		  if (((len - start) % 2) != 0) @@ -1783,13 +1791,12 @@ scan_it (FILE *ofp, void* pw)        /* FIXME: other bit depths? */        if (output_format != OUTPUT_TIFF && parm.depth == 16)  	{ -	  int i; -	  for (i = 0; i < image.height * image.width; i += 2) +	  for (int idx = 0; idx < image.height * image.width; idx += 2)  	    {  	      unsigned char LSB; -	      LSB = image.data[i]; -	      image.data[i] = image.data[i + 1]; -	      image.data[i + 1] = LSB; +	      LSB = image.data[idx]; +	      image.data[idx] = image.data[idx + 1]; +	      image.data[idx + 1] = LSB;  	    }  	}  #endif @@ -1996,6 +2003,8 @@ scanimage_exit (int status)      fprintf (stderr, "Calling sane_exit\n");    sane_exit (); +  if (full_optstring) +    free(full_optstring);    if (all_options)      free (all_options);    if (option_number) @@ -2013,15 +2022,12 @@ scanimage_exit (int status)   */  static void print_options(SANE_Device * device, SANE_Int num_dev_options, SANE_Bool ro)  { -  int i, j; -  const SANE_Option_Descriptor *opt; - -  for (i = 1; i < num_dev_options; ++i) +  for (int i = 1; i < num_dev_options; ++i)      { -      opt = 0; +      const SANE_Option_Descriptor *opt = 0;        /* scan area uses modified option struct */ -      for (j = 0; j < 4; ++j) +      for (int j = 0; j < 4; ++j)  	if (i == window[j])  	  opt = window_option + j; @@ -2072,36 +2078,31 @@ static int guess_output_format(const char* output_file)          }      } -  // it would be very confusing if user makes a typo in the filename and the output format changes. -  // This is most likely not what the user wanted. -  fprintf(stderr, "Could not guess output format from the given path and no --format given.\n"); -  exit(1); +  return OUTPUT_UNKNOWN;  }  int  main (int argc, char **argv)  { -  int ch, i, index, all_options_len; +  int ch, index;    const SANE_Device **device_list;    SANE_Int num_dev_options = 0;    const char *devname = 0;    const char *defdevname = 0;    const char *format = 0; -  char readbuf[2]; -  char *readbuf2;    int batch = 0;    int batch_print = 0;    int batch_prompt = 0;    int batch_count = BATCH_COUNT_UNLIMITED;    int batch_start_at = 1;    int batch_increment = 1; +  int promptc;    SANE_Status status; -  char *full_optstring;    SANE_Int version_code;    void *pw = NULL;    FILE *ofp = NULL; -  buffer_size = (32 * 1024);	/* default size */ +  buffer_size = (1024 * 1024);	/* default size */    prog_name = strrchr (argv[0], '/');    if (prog_name) @@ -2148,10 +2149,7 @@ main (int argc, char **argv)            output_file = optarg;            break;  	case 'B': -          if (optarg) -	    buffer_size = 1024 * atoi(optarg); -          else -	    buffer_size = (1024 * 1024); +          buffer_size = 1024 * atoi(optarg);  	  break;  	case 'T':  	  test = 1; @@ -2190,7 +2188,7 @@ main (int argc, char **argv)  	      output_format = OUTPUT_PNG;  #else  	      fprintf(stderr, "PNG support not compiled in\n"); -	      exit(1); +	      scanimage_exit (1);  #endif  	    }  	  else if (strcmp (optarg, "jpeg") == 0) @@ -2199,7 +2197,7 @@ main (int argc, char **argv)  	      output_format = OUTPUT_JPEG;  #else  	      fprintf(stderr, "JPEG support not compiled in\n"); -	      exit(1); +	      scanimage_exit (1);  #endif  	    }  	  else if (strcmp (optarg, "pdf") == 0) @@ -2208,7 +2206,7 @@ main (int argc, char **argv)  	      output_format = OUTPUT_PDF;  #else  	      fprintf(stderr, "PDF support not compiled in\n"); -	      exit(1); +	      scanimage_exit (1);  #endif  	    }            else if (strcmp (optarg, "pnm") == 0) @@ -2226,7 +2224,7 @@ main (int argc, char **argv)                fprintf(stderr, ", jpeg");  #endif                fprintf(stderr, ".\n"); -              exit(1); +              scanimage_exit (1);              }  	  break;  	case OPTION_MD5: @@ -2256,14 +2254,14 @@ main (int argc, char **argv)  	      }  	    else  	      { -		int i = 0, int_arg = 0; -		const char *percent, *start; +		int int_arg = 0; +		const char *percent;  		const char *text_arg = 0;  		char ftype; -		for (i = 0; device_list[i]; ++i) +		for (int dev_num = 0; device_list[dev_num]; ++dev_num)  		  { -		    start = optarg; +		    const char *start = optarg;  		    while (*start && (percent = strchr (start, '%')))  		      {  			int start_len = percent - start; @@ -2273,23 +2271,23 @@ main (int argc, char **argv)  			    switch (*percent)  			      {  			      case 'd': -				text_arg = device_list[i]->name; +				text_arg = device_list[dev_num]->name;  				ftype = 's';  				break;  			      case 'v': -				text_arg = device_list[i]->vendor; +				text_arg = device_list[dev_num]->vendor;  				ftype = 's';  				break;  			      case 'm': -				text_arg = device_list[i]->model; +				text_arg = device_list[dev_num]->model;  				ftype = 's';  				break;  			      case 't': -				text_arg = device_list[i]->type; +				text_arg = device_list[dev_num]->type;  				ftype = 's';  				break;  			      case 'i': -				int_arg = i; +				int_arg = dev_num;  				ftype = 'i';  				break;  			      case 'n': @@ -2401,12 +2399,20 @@ Parameters are separated by a blank from single-character options (e.g.\n\    if (batch && output_file != NULL)      {        fprintf(stderr, "--batch and --output-file can't be used together.\n"); -      exit(1); +      scanimage_exit (1);      }    if (output_format == OUTPUT_UNKNOWN) -    output_format = guess_output_format(output_file); - +    { +      output_format = guess_output_format(output_file); +      if (output_format == OUTPUT_UNKNOWN) +        { +          // it would be very confusing if user makes a typo in the filename and the output format changes. +          // This is most likely not what the user wanted. +          fprintf(stderr, "Could not guess output format from the given path and no --format given.\n"); +          scanimage_exit (1); +        } +    }    if (!devname)      {        /* If no device name was specified explicitly, we look at the @@ -2474,7 +2480,7 @@ Parameters are separated by a blank from single-character options (e.g.\n\  	}        /* malloc global option lists */ -      all_options_len = num_dev_options + NELEMS (basic_options) + 1; +      int all_options_len = num_dev_options + NELEMS (basic_options) + 1;        all_options = malloc (all_options_len * sizeof (all_options[0]));        option_number_len = num_dev_options;        option_number = malloc (option_number_len * sizeof (option_number[0])); @@ -2579,6 +2585,7 @@ Parameters are separated by a blank from single-character options (e.g.\n\  	}        free (full_optstring); +      full_optstring = NULL;        /* convert x/y to br_x/br_y */        for (index = 0; index < 2; ++index) @@ -2624,7 +2631,7 @@ List of available devices:", prog_name);  	{  	  int column = 80; -	  for (i = 0; device_list[i]; ++i) +	  for (int i = 0; device_list[i]; ++i)  	    {  	      if (column + strlen (device_list[i]->name) + 1 >= 80)  		{ @@ -2741,21 +2748,19 @@ List of available devices:", prog_name);  	      if (output_format != OUTPUT_PDF)  #endif       	         strcat (part_path, ".part"); -	    } - -	  if (batch) -	    {  	      if (batch_prompt)  		{  		  fprintf (stderr, "Place document no. %d on the scanner.\n",  			   n);  		  fprintf (stderr, "Press <RETURN> to continue.\n"); -		  fprintf (stderr, "Press Ctrl + D to terminate.\n"); -		  readbuf2 = fgets (readbuf, 2, stdin); +		  fprintf (stderr, "Press Ctrl + D (EOF) to terminate.\n"); +		  while ((promptc = getchar()) != '\n' && promptc != EOF); -		  if (readbuf2 == NULL) +		  if (promptc == EOF)  		    { +		      if (ferror(stdin)) +			fprintf(stderr, "%s: stdin error: %s\n", prog_name, strerror(errno));  		      if (ofp)  			{  #ifdef HAVE_LIBJPEG | 
