summaryrefslogtreecommitdiff
path: root/frontend/scanimage.c
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff.email>2024-06-30 15:46:39 +0200
committerJörg Frings-Fürst <debian@jff.email>2024-06-30 15:46:39 +0200
commit73365252941d4053dca0e7fa06f4c205194cf1b8 (patch)
tree3eff4566f12e48cfee6b35955d262e46ee5a5da1 /frontend/scanimage.c
parent52c7d661296d9efb9a51b52c38dda22516cf981a (diff)
parent3c9b873509b5c2278d4e345bf86a22c1ff26f3c0 (diff)
Merge branch 'release/debian/1.3.0-1'debian/1.3.0-1
Diffstat (limited to 'frontend/scanimage.c')
-rw-r--r--frontend/scanimage.c201
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