[BACK]Return to set_scanner.c CVS log [TXT][DIR] Up to [local] / src / usr.sbin / ssio

File: [local] / src / usr.sbin / ssio / Attic / set_scanner.c (download)

Revision 1.3, Sun May 23 17:19:23 1999 UTC (25 years ago) by aaron
Branch: MAIN
CVS Tags: OPENBSD_3_1_BASE, OPENBSD_3_1, OPENBSD_3_0_BASE, OPENBSD_3_0, OPENBSD_2_9_BASE, OPENBSD_2_9, OPENBSD_2_8_BASE, OPENBSD_2_8, OPENBSD_2_7_BASE, OPENBSD_2_7, OPENBSD_2_6_BASE, OPENBSD_2_6
Changes since 1.2: +2 -2 lines

getopt(3) returns -1, not EOF

static char *rcs_id = "$Id: set_scanner.c,v 1.3 1999/05/23 17:19:23 aaron Exp $";
/*
 * Copyright (c) 1995 Kenneth Stailey
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed for the NetBSD Project
 *	by Kenneth Stailey
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * set-scanner.c:
 *
 *   Set the scan area in decimal fractions of inches.
 *   If the defaults are to be changed use system("chdev...")
 *   otherwise use ioctl()
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/ioctl.h>
#endif
#include <sys/scanio.h>

#define UNINITIALIZED -10

int inches_to_1200th(char *numeral);
void usage(char *prog_name);
int xlate_image_code(char *);
int ipow10(int);
int scanner_type(char *);

main(int argc, char *argv[])
{
  int width, height;
  int x_origin, y_origin;
  int brightness, contrast;
  int resolution, image_mode;

  int defaults = FALSE;

  char *logical_name = "scan0";
  char device_special[255];

  int    c;			/* for command line parsing */
  extern int   optind;		/* for getopt() */
  extern char *optarg;		/* for getopt() */

  char command[256];
  struct scan_io s_io;

  int s_fd;

  brightness = contrast = resolution =
    width = height = x_origin = y_origin =
      image_mode =
	UNINITIALIZED;

  while ((c = getopt(argc, argv, "w:h:x:y:l:b:c:r:i:d")) != -1) {
    switch (c) {
    case 'w':
      width = inches_to_1200th(optarg);
      break;
    case 'h':
      height = inches_to_1200th(optarg);
      break;
    case 'x':
      x_origin = inches_to_1200th(optarg);
      break;
    case 'y':
      y_origin = inches_to_1200th(optarg);
      break;
    case 'l':
      logical_name = optarg;
      break;
    case 'd':
      defaults = TRUE;		/* use chdev to set defaults */
      break;
    case 'b':
      brightness = atol(optarg);
      break;
    case 'c':
      contrast = atol(optarg);
      break;
    case 'r':
      resolution = atol(optarg);
      break;
    case 'i':
      image_mode = xlate_image_code(optarg);
      if (image_mode == -1) {
	usage(argv[0]);
      }
      break;
    case '?':
      usage(argv[0]);
    }
  }

#ifdef __IBMR2
  if (defaults) {
    sprintf(command, "chdev -l %s", logical_name);

    if (width != UNINITIALIZED)
      sprintf(command, "%s -a window_width=%d", command, width);

    if (height != UNINITIALIZED)
      sprintf(command, "%s -a window_length=%d", command, height);

    if (x_origin != UNINITIALIZED)
      sprintf(command, "%s -a x_origin=%d", command, x_origin);

    if (y_origin != UNINITIALIZED)
      sprintf(command, "%s -a y_origin=%d", command, y_origin);

    if (brightness != UNINITIALIZED)
      sprintf(command, "%s -a brightness=%d", command, brightness);

    /* note that the FUJITSU doesn't support contrast via the ODM */
    if (contrast != UNINITIALIZED && scanner_type(logical_name) != FUJITSU)
      sprintf(command, "%s -a contrast=%d", command, contrast);

    if (resolution != UNINITIALIZED) {
      sprintf(command, "%s -a x_resolution=%d", command, resolution);
      sprintf(command, "%s -a y_resolution=%d", command, resolution);
    }

    if (image_mode != UNINITIALIZED) {
      sprintf(command, "%s -a image_mode=", command);
      switch (image_mode) {
      case SIM_BINARY_MONOCHROME:
	sprintf(command, "%smonochrome ", command);
	break;
      case SIM_DITHERED_MONOCHROME:
	sprintf(command, "%sdithered ", command);
	break;
      case SIM_GRAYSCALE:
	sprintf(command, "%sgrayscale ", command);
	break;
      case SIM_COLOR:
	sprintf(command, "%scolor ", command);
	break;
      case SIM_RED:
	sprintf(command, "%sred ", command);
	break;
      case SIM_GREEN:
	sprintf(command, "%sgreen ", command);
	break;
      case SIM_BLUE:
	sprintf(command, "%sblue ", command);
	break;
      }
    }

    system(command);

  } else { 			/* use ioctl() instead of chdev */
#endif
    sprintf(device_special, "/dev/%s", logical_name);
    if ((s_fd = open(device_special, O_RDONLY)) < 0) {
      fprintf(stderr, "open of %s failed: ", device_special);
      perror("");
      exit(-1);
    }

    if (ioctl(s_fd, SCIOCGET, &s_io) < 0) {
      perror("ioctl SCIOCGET");
      exit(-1);
    }

    if (width != UNINITIALIZED)
      s_io.scan_width = width;

    if (height != UNINITIALIZED)
      s_io.scan_height = height;

    if (x_origin != UNINITIALIZED)
      s_io.scan_x_origin = x_origin;

    if (y_origin != UNINITIALIZED)
      s_io.scan_y_origin = y_origin;

    if (brightness != UNINITIALIZED)
      s_io.scan_brightness = brightness;

    if (contrast != UNINITIALIZED)
      s_io.scan_contrast = contrast;

    if (resolution != UNINITIALIZED) {
      s_io.scan_x_resolution = resolution;
      s_io.scan_y_resolution = resolution;
    }

    if (image_mode != UNINITIALIZED)
      s_io.scan_image_mode = image_mode;

    if (ioctl(s_fd, SCIOCSET, &s_io) < 0) {
      perror("ioctl SCIOCSET");
      exit(-1);
    }
#ifdef __IBMR2
  }
#endif

  exit(0);
}

/*
 * Convert a numeral representing inches into a number representing
 * 1/1200ths of an inch.  If multipling the input by 1200 still leaves
 * a fractional part then abort with an error message.
 *
 * Note that "numeral" here means string of digits with optional decimal point
 */
int
inches_to_1200th(char *numeral)
{
  FILE *bc;
  char result[50];
  char *p;

  /* test to see if "numeral" really is a numeral */
  p = numeral;
  while (*p) {
    if (!isdigit(*p) && *p != '.')
      usage("set_scanner");
    ++p;
  }

  /* test to see if it is a multiple of 1/1200 */

  if ((bc = fopen("/tmp/set_scanner.bc_work", "w")) == NULL) {
    perror("creating temp file '/tmp/set_scanner.bc_work'");
    exit(-1);
  }
  fprintf(bc, "%s * 1200\nquit\n", numeral);
  fclose(bc);

  if ((bc = popen("bc -l /tmp/set_scanner.bc_work", "r")) == NULL) {
    perror("running bc");
    exit(-1);
  }
  fgets(result, 50, bc);
  result[strlen(result) - 1] = '\0';  /* eat newline from fgets */
  pclose(bc);
  unlink("/tmp/set_scanner.bc_work");

  if ((p = strchr(result, '.')) != NULL) {
    ++p;
    while (*p)
      if (*p++ != '0') {
	fprintf(stderr, "set_scanner: please do not use fractions with a  ");
	fprintf(stderr, "granularity less than\nset_scanner: one ");
	fprintf(stderr, "twelve-thousandths of an inch\n");
	exit(-1);
      }
  }

  return (atoi(result));
}

void
usage(char *prog_name)
{
  fprintf(stderr,
	  "usage: %s [-w width] [-h height] [-x x_origin] [-y y_origin]\n[-r resolution] [-l logical name] [-i image mode] [-d (for setting defaults)]\n",
	  prog_name);
  exit(-1);
}

int xlate_image_code(char *image_code)
{
  switch (image_code[0]) {
  case 'm':
    return (SIM_BINARY_MONOCHROME);
  case 'd':
    return (SIM_DITHERED_MONOCHROME);
  case 'g':
    return (SIM_GRAYSCALE);
  case 'c':
    return (SIM_COLOR);
  case 'R':
    return (SIM_RED);
  case 'G':
    return (SIM_GREEN);
  case 'B':
    return (SIM_BLUE);
  default:
    return (-1);
  }
}

int scanner_type(char *lname)
{
  char special_file[256];
  int scan_fd;
  struct scan_io sp;

  sprintf(special_file, "/dev/%s", lname);

  if ((scan_fd = open(special_file, O_RDONLY)) < 0) {
    perror("set_scanner: can't open scanner--");
    exit(1);
  }

  if (ioctl(scan_fd, SCIOCGET, &sp) < 0) {
    perror("set_scanner: can't get parameters from scanner--");
    exit(1);
  }

  close(scan_fd);

  return ((int)sp.scan_scanner_type);
}