lp.cat.c revision de81e71e031139a0a7f13b7bf64152c3faa76698
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#include <stdio.h>
#include <stdlib.h>
#include <termio.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <limits.h>
#include "lp.h"
#include <locale.h>
/*
* Begin Sun Additions for Parallel ports
*/
#include <string.h>
#include <stdarg.h>
#include <signal.h>
#include <unistd.h>
#include <stropts.h>
/*
* the parameter structure for the parallel port
*/
struct ppc_params_t {
int flags; /* same as above */
int state; /* status of the printer interface */
int strobe_w; /* strobe width, in uS */
int data_setup; /* data setup time, in uS */
int ack_timeout; /* ACK timeout, in secs */
int error_timeout; /* PAPER OUT, etc... timeout, in secs */
int busy_timeout; /* BUSY timeout, in seconds */
};
static void printer_info(char *fmt, ...);
/* These are the routines avaliable to others for use */
int is_a_parallel_bpp(int);
int bpp_state(int);
int parallel_comm(int, int());
int get_ecpp_status(int fd);
int is_a_prnio(int);
int prnio_state(int);
#define PRINTER_ERROR_PAPER_OUT 1
#define PRINTER_ERROR_OFFLINE 2
#define PRINTER_ERROR_BUSY 3
#define PRINTER_ERROR_ERROR 4
#define PRINTER_ERROR_CABLE_POWER 5
#define PRINTER_ERROR_UNKNOWN 6
#define PRINTER_ERROR_TIMEOUT 7
#define PRINTER_IO_ERROR 129
/*
* for BPP PARALLEL interfaces
*/
int
is_a_parallel_bpp(int fd)
{
return (1);
return (0);
}
char *
{
return (buf);
}
#endif
int
{
struct bpp_error_status bpp_stat;
int state;
#endif
/* paper is out */
return (PRINTER_ERROR_PAPER_OUT);
} else if (state & BPP_BUSY_ERR) {
/* printer is busy */
return (PRINTER_ERROR_BUSY);
} else if (state & BPP_SLCT_ERR) {
/* printer is offline */
return (PRINTER_ERROR_OFFLINE);
} else if (state & BPP_ERR_ERR) {
/* printer is errored */
return (PRINTER_ERROR_ERROR);
} else if (state == BPP_PE_ERR) {
return (PRINTER_ERROR_CABLE_POWER);
} else if (state) {
return (PRINTER_ERROR_UNKNOWN);
} else
return (0);
}
return (0);
}
/*
* For ecpp parallel port
*/
int
get_ecpp_status(int fd)
{
int state;
struct ecpp_transfer_parms transfer_parms;
return (-1);
}
/*
* We don't know what all printers will return in
* nibble mode, therefore if we support nibble mode we will
* force the printer to be in CENTRONICS mode.
*/
if (state != ECPP_CENTRONICS) {
return (-1);
} else {
}
}
return (state);
}
/*
* For prnio(7I) - generic printer interface
*/
int
is_a_prnio(int fd)
{
/* check if device supports prnio */
return (0);
}
/* we will use 1284 status if available */
if ((cap & PRN_1284_STATUS) == 0) {
/* some devices may only support 1284 status in unidir. mode */
}
}
return (1);
}
int
prnio_state(int fd)
{
return (0);
}
return (PRINTER_ERROR_UNKNOWN);
}
/* paper is out */
return (PRINTER_ERROR_PAPER_OUT);
return (PRINTER_ERROR_CABLE_POWER);
} else if ((pins & PRN_1284_SELECT) == 0) {
/* printer is offline */
return (PRINTER_ERROR_OFFLINE);
} else if ((pins & PRN_1284_NOFAULT) == 0) {
/* printer is errored */
return (PRINTER_ERROR_ERROR);
} else if (pins & PRN_1284_PE) {
/* paper is out */
return (PRINTER_ERROR_PAPER_OUT);
return (PRINTER_ERROR_UNKNOWN);
}
return (0);
}
/*
* Common routines
*/
/*ARGSUSED0*/
static void
ByeByeParallel(int sig)
{
/* try to shove out the EOT */
exit(0);
}
/*ARGSUSED0*/
static void
printer_info(char *fmt, ...)
{
/*
* fprintf(stderr,
* "%%%%[ PrinterError: %s; source: parallel ]%%%%\n",
* mesg);
*/
fsync(2);
}
static void
printer_error(int error)
{
switch (error) {
case -1:
break;
case PRINTER_ERROR_PAPER_OUT:
printer_info("out of paper");
break;
case PRINTER_ERROR_OFFLINE:
printer_info("offline");
break;
case PRINTER_ERROR_BUSY:
printer_info("busy");
break;
case PRINTER_ERROR_ERROR:
printer_info("printer error");
break;
printer_info("printer powered off or disconnected");
break;
case PRINTER_ERROR_UNKNOWN:
printer_info("unknown error");
break;
case PRINTER_ERROR_TIMEOUT:
printer_info("communications timeout");
break;
default:
printer_info("get_status() failed");
}
}
static void
{
int state;
int was_faulted = 0;
was_faulted = 1;
sleep(15);
}
if (was_faulted) {
fsync(2);
}
}
/*
* end of Sun Additions for parallel port
*/
#define E_SUCCESS 0
#define E_BAD_INPUT 1
#define E_BAD_OUTPUT 2
#define E_BAD_TERM 3
#define E_IDENTICAL 4
#define E_WRITE_FAILED 5
#define E_TIMEOUT 6
#define E_HANGUP 7
#define E_INTERRUPT 8
#define SAFETY_FACTOR 2.0
#define R(F) (int)((F) + .5)
#define DELAY(N, D) R(SAFETY_FACTOR * ((N) / (double)(D)))
void sighup(),
sigint(),
sigquit(),
sigpipe(),
sigalrm(),
sigterm();
#if defined(baudrate)
#endif
int baudrate();
int
{
return (0);
}
int bpp_state(int);
/*
* main()
*/
int
{
int report_rate;
short print_rate;
long epoch_start, epoch_end;
char *TERM;
/*
* The Spooler can hit us with SIGTERM for three reasons:
*
* - the user's job has been canceled
* - the printer has been disabled while we were printing
* - the Spooler heard that the printer has a fault,
* and the fault recovery is wait or beginning
*
* We should exit cleanly for the first two cases,
* but we have to be careful with the last. If it was THIS
* PROGRAM that told the Spooler about the fault, we must
* exit consistently.
*
* The method of avoiding any problem is to turn off the
* trapping of SIGTERM before telling the Spooler about
* the fault.
*
* Faults that we can detect:
* - hangup (drop of carrier)
* - interrupt (printer sent a break or quit character)
* - SIGPIPE (output port is a FIFO, and was closed early)
* - failed or incomplete write()
* - excess delay in write() (handled with SIGALRM later)
*
* Pseudo-faults (errors in use):
* - No TERM defined or trouble reading Terminfo database
*/
report_rate = 1;
argc--;
argv++;
} else
report_rate = 0;
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
/*
* Stat the standard output to be sure it is defined.
*/
}
/*
* Stat the standard input to be sure it is defined.
*/
}
/*
* If the standard output is not a character special file or a
* block special file, make sure it is not identical to the
* standard input.
*
* If we are an ecpp parallel port in centronics mode treat
* ourselves as a bpp compatible device.
*/
if (is_a_prnio(1)) {
func = prnio_state;
} else if (is_a_parallel_bpp(1) ||
} else if (isatty(1)) {
/* serial connection (probably) - continue as usual */
} else {
}
"incorrect use of lp.cat!\n"));
}
/*
* The effective data transfer rate is the lesser
* of the transmission rate and print rate. If an
* argument was passed to us, it should be a data
* rate and it may be lower still.
* Based on the effective data transfer rate,
* we can predict the maximum delay we should experience.
* But there are other factors that could introduce
* delay, so let's be generous; after all, we'd rather
* err in favor of waiting too long to detect a fault
* than err too often on false alarms.
*/
"Trouble with the Spooler!\n"));
}
"type \"%s\"; check the Terminfo database.\n"), TERM);
}
print_rate = -1;
effective_rate = n; /* 0 means infinite delay */
if (effective_rate)
/*
* We'll use the "alarm()" system call to keep us from
* waiting too long to write to a printer in trouble.
*/
if (max_delay)
/*
* While not end of standard input, copy blocks to
* standard output.
*/
/*
* We should be safe from incomplete writes to a full
* pipe, as long as the size of the buffer we write is
* a even divisor of the pipe buffer limit. As long as
* we read from files or pipes (not communication devices)
* this should be true for all but the last buffer. The
* last will be smaller, and won't straddle the pipe max
* limit (think about it).
*/
#endif
if (report_rate)
do {
if (max_delay)
alarm(0);
if (nout < 0) {
"(%s);\nperhaps the printer has gone "
"off-line.\n"), PERROR);
/* I/O error on device, get lpcshed to retry */
else /* wait for printer to come back online */
sleep(15);
} else {
}
} while (nin > 0);
if (max_delay)
alarm(0);
else if (report_rate) {
if (epoch_end - epoch_start > 0)
R((100 * BUFSIZ) /
(double)(epoch_end - epoch_start)));
}
}
return (E_SUCCESS);
}
/*
* sighup() - CATCH A HANGUP (LOSS OF CARRIER)
*/
void
sighup()
{
}
/*
* sigint() - CATCH AN INTERRUPT
*/
void
sigint()
{
}
/*
* sigpipe() - CATCH EARLY CLOSE OF PIPE
*/
void
sigpipe()
{
}
/*
* sigalrm() - CATCH AN ALARM
*/
void
sigalrm()
{
"perhaps the printer has gone off-line.\n"));
}
/*
* sigterm() - CATCH A TERMINATION SIGNAL
*/
void
sigterm()
{
/*
* try to flush the output queue in the case of ecpp port.
* ignore the return code as this may not be the ecpp.
*/
}
/*
* baudrate() - RETURN BAUD RATE OF OUTPUT LINE
*/
static int baud_convert[] =
{
0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
1800, 2400, 4800, 9600, 19200, 38400, 57600,
76800, 115200, 153600, 230400, 307200, 460800, 921600
};
int
baudrate()
{
int speed;
return (1200);
else
} else
}