2674 lines
84 KiB
C
2674 lines
84 KiB
C
static char sccsid[] = "@(#)35 1.20.1.23 src/bos/usr/lib/pios/pioout.c, cmdpios, bos41J, 9523B_all 6/7/95 16:35:30";
|
|
/*
|
|
* COMPONENT_NAME: (CMDPIOS) Printer Backend
|
|
*
|
|
* FUNCTIONS: main, outflush, outflush2, oct2char, piomsgout,
|
|
* sigterm_exit, sigusr1_exit, transp_init, rs_setup,
|
|
* rs_print, rs_cleanup, lion_setup, lion_print, lion_cleanup,
|
|
* cxma_setup, cxma_print, cxma_cleanup, lookup_TPF_cmds
|
|
*
|
|
* ORIGINS: 27
|
|
*
|
|
* IBM CONFIDENTIAL -- (IBM Confidential Restricted when
|
|
* combined with the aggregated modules for this product)
|
|
* SOURCE MATERIALS
|
|
* (C) COPYRIGHT International Business Machines Corp. 1989, 1995
|
|
* All Rights Reserved
|
|
*
|
|
* US Government Users Restricted Rights - Use, duplication or
|
|
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
|
|
*/
|
|
|
|
/*** pioout.c - device driver interface program for the printer backend ***/
|
|
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <sys/lpio.h>
|
|
#include <sys/signal.h>
|
|
#include <memory.h>
|
|
#include <locale.h>
|
|
#include <IN/backend.h>
|
|
#include <IN/standard.h>
|
|
#include <time.h>
|
|
#include <piobe_msg.h>
|
|
#include <sys/ldr.h>
|
|
#include "piostruct.h"
|
|
#include "pioout.h"
|
|
#include <sys/file.h>
|
|
#include <sys/stat.h>
|
|
#include <termios.h>
|
|
#include <signal.h>
|
|
#include <ttyent.h>
|
|
#include <curses.h>
|
|
#include <term.h>
|
|
#include <string.h>
|
|
#include <sys/li.h> /* 64-port adapter header file */
|
|
#include <sys/id.h>
|
|
#include <sys/cxma.h> /* 128-port adapter header file */
|
|
#include <sys/mode.h>
|
|
#include <stropts.h>
|
|
|
|
/* include for getmsg routine */
|
|
#include <nl_types.h>
|
|
char *piogetmsg();
|
|
|
|
#define PREFLAG 'P'
|
|
#define SUFFLAG 'S'
|
|
#define OUTFLAG 'O'
|
|
#define LOADFLAG 'R'
|
|
#define PREFLAGSTR "P"
|
|
#define SUFFLAGSTR "S"
|
|
#define OUTFLAGSTR "O"
|
|
#define LOADFLAGSTR "R"
|
|
#define DEFVARDIR "/var/spool/lpd/pio/@local" /* default base directory */
|
|
#define DEVNAME "\001" /* place holder for device name (replaced
|
|
by piomsgout() with appropriate string) */
|
|
|
|
/* Transparent print message set number */
|
|
#define TP_MSET 1
|
|
|
|
/* Default asynchronous adapter parameter values
|
|
*/
|
|
#define DFLT_RS_BUFSIZ 10
|
|
#define DFLT_RS_DELAY 200000L
|
|
#define DFLT_LION_PRIORITY 30
|
|
|
|
#define DFLT_CXMA_MAXCPS 100
|
|
#define DFLT_CXMA_MAXCHAR 50
|
|
#define DFLT_CXMA_BUFSIZ 100
|
|
|
|
/* 128-port transparent print device offset
|
|
*/
|
|
#define CXMA_DEV 0x8000
|
|
|
|
#define ATTR_TAB_SZ 20
|
|
|
|
#define OUTC(ch) { *nextp++ = (unsigned char) ch; \
|
|
if (nextp >= endbuf) { \
|
|
if (printer_dd) \
|
|
(void) outflush(0); \
|
|
else if (ttyprint) \
|
|
(*TPF->print)(); \
|
|
else \
|
|
(void) outflush2(); \
|
|
} \
|
|
}
|
|
|
|
#define FLUSH() { if (printer_dd) \
|
|
(void) outflush(1); \
|
|
else if (ttyprint) \
|
|
(*TPF->print)(); \
|
|
else \
|
|
(void) outflush2(); \
|
|
}
|
|
|
|
#define PIOEXIT(code) { if (printer_dd) { \
|
|
(void) ioctl(1, LPRMODS, &lpr_orig); \
|
|
} else if (ttyprint) { \
|
|
(void) (*TPF->cleanup)(); \
|
|
} \
|
|
exit(code); \
|
|
}
|
|
|
|
#define MALLOC(memptr, size) \
|
|
{if ((memptr = malloc(size)) == NULL) { \
|
|
(void) fprintf(stderr,(piogetmsg(MF_PIOBE,1,MSG_MALLOC))); \
|
|
PIOEXIT(PIOO_FAIL); \
|
|
}}
|
|
|
|
|
|
char can_str[500];
|
|
char ff_str[500];
|
|
|
|
|
|
extern int opterr;
|
|
extern char *optarg;
|
|
extern int optopt;
|
|
extern int errno;
|
|
|
|
void piomsgout();
|
|
int sigterm_exit();
|
|
int sigusr1_exit();
|
|
|
|
char *prefixfile;
|
|
char *suffixfile;
|
|
char *outputfile;
|
|
char *sub_node;
|
|
char *readroutine;
|
|
char *basedir;
|
|
|
|
char defbasedir[] = DEFVARDIR;
|
|
char nullstring[] = "";
|
|
char placeholder[] = DEVNAME; /* placeholder character for device name */
|
|
char msgbuf[1000];
|
|
char sub_user[200]; /* user who submitted print job */
|
|
char dev_sub[200]; /* device string destined for submitter */
|
|
char dev_irq[200]; /* device string destined for int. req'd user*/
|
|
char thishost[100]; /* name of this node */
|
|
char outbuf[BUFSIZ]; /* output buffer */
|
|
|
|
FILE *suffile;
|
|
|
|
int fildes = 1;
|
|
int statusfile = 0;
|
|
int sigterm, sigusr1;
|
|
int off_msgdone, pout_msgdone, tout_msgdone, noslct_msgdone;
|
|
int term_on_error;
|
|
long len_total;
|
|
long len_done;
|
|
long len_done_orig;
|
|
int numformfeeds;
|
|
int numcanstrs;
|
|
int len_canstr;
|
|
int len_ffstr;
|
|
int dothresh;
|
|
int lpquery_val;
|
|
int mask;
|
|
int wait_for_eof; /* wait for EOF from printer before exiting */
|
|
int eof_level; /* # EOFs sent to printer - # EOFs returned */
|
|
char *nextp = outbuf; /* where to put next char in output buffer */
|
|
char *endbuf = outbuf + BUFSIZ; /* character after end of buffer */
|
|
int special_power=FALSE; /* Added for A12747 */
|
|
|
|
uid_t invokers_uid;
|
|
uid_t programs_uid;
|
|
|
|
|
|
char *devname;
|
|
char *title;
|
|
char *qname;
|
|
char *qdname;
|
|
char *from;
|
|
char *ptrtype;
|
|
char *jobnum;
|
|
int mailonly;
|
|
|
|
int rc;
|
|
int printer_dd = TRUE; /* writing to the printer device driver? */
|
|
struct lprmod lpr_orig;
|
|
struct lprmod lpr_piobe;
|
|
struct termios spio;
|
|
struct stat statbuf; /* used with stat system call */
|
|
|
|
struct piormsg msginfo; /* interface to exit routine for read msgs */
|
|
|
|
/* info for chain of users to received "intervention required" messages */
|
|
struct irqelem { /* element in chain of users to receive */
|
|
struct irqelem *next; /* "intervention required" messages */
|
|
char *user;
|
|
char *node;
|
|
};
|
|
struct irqelem irquser_beg; /* dummy element at beginning of chain */
|
|
struct irqelem *irquser_end = &irquser_beg; /* ptr to last element in chain */
|
|
struct irqelem *irquserwp; /* work pointer */
|
|
|
|
/* info for chain of strings that identify messages to be discarded */
|
|
struct element discard_beg; /* dummy element at beginning of chain */
|
|
struct element *discard_end = &discard_beg; /* ptr to last element in chain */
|
|
struct element *discardwp; /* work pointer */
|
|
|
|
/* info for chain of strings that identify message */
|
|
/* types to send to "intervention required" users */
|
|
struct element irqtype_beg; /* dummy element at beginning of chain */
|
|
struct element *irqtype_end = &irqtype_beg; /* ptr to last element in chain */
|
|
struct element *irqtypewp; /* work pointer */
|
|
|
|
static union { /* used to convert back and forth between */
|
|
char *charptr; /* pointer types without upsetting lint */
|
|
struct irqelem *irqptr;
|
|
struct element *elemptr;
|
|
} mp;
|
|
|
|
int (*loadrc)(); /* return code from load() */
|
|
|
|
/* Declarations for Streams based serial line printers */
|
|
SP_WRITE_DECL
|
|
|
|
/* Declarations for message ipc (for Palladium) */
|
|
extern uchar_t piomsgipc; /* flag to indicate if msgs need be
|
|
sent via ipc */
|
|
extern int pmi_initmsgipc(void);
|
|
extern int pmi_bldhdrfrm(uchar_t,ushort_t,ushort_t,char const *);
|
|
extern int pmi_bldintfrm(int);
|
|
extern int pmi_bldstrfrm(const char *);
|
|
extern int pmi_dsptchmsg(const char *);
|
|
|
|
/* Declarations for ASCII terminal attached printers */
|
|
/*****************************************************/
|
|
struct termios back, fore; /* Terminal mode structures */
|
|
struct sigaction action; /* Action for SIGTTIN and SIGTTOU signals */
|
|
static char stpt[100], /* Start Passthru */
|
|
endpt[100]; /* End Passthru */
|
|
static int stptl, /* Start Passthru command length */
|
|
endptl; /* End Passthru command length */
|
|
char ttydevname[30]; /* TTY device name. e.g. tty0 */
|
|
char cxmadevname[80]; /* 128-port transparent print device name */
|
|
struct ttyent *outty; /* Pointer to tty definition */
|
|
static int backtty; /* Mode of tty (1: Background; 0: Foreground) */
|
|
static int burst_size; /* Number of characters to burst to tty on native, 8, or 16-port adapter */
|
|
static long delay; /* Delay between bursts to tty on native, 8, or 16-port adapter */
|
|
int ttyprint = 0; /* Flag indicating terminal attached printer */
|
|
|
|
void transp_init(void); /* Terminal attached printer initialization routine */
|
|
|
|
void rs_setup(void); /* Setup routine for native, 8, and 16-port adapter */
|
|
void rs_print(void); /* Print routine for native, 8, and 16-port adapter */
|
|
void rs_cleanup(void);
|
|
|
|
void lion_setup(void); /* Setup routine for 64-port adapter */
|
|
void lion_print(void); /* Print routine for 64-port adapter */
|
|
void lion_cleanup(void);
|
|
|
|
void cxma_setup(void); /* Setup routine for 128-port adapter */
|
|
void cxma_print(void); /* Print routine for 128-port adapter */
|
|
void cxma_cleanup(void);
|
|
|
|
char *dev_attrtab[ATTR_TAB_SZ]; /* Device driver attribute table.
|
|
dev_attrtab[0] is reserved for tty hardware
|
|
discipline defined by virtual printer attribute
|
|
"y0"
|
|
*/
|
|
|
|
/* Indices into device driver attribute table */
|
|
/* NOTE: Must start at 1 because dev_attrtab[0] is reserved. */
|
|
/* See comment for dev_attrtab[] */
|
|
/*************************************************************/
|
|
enum { RS_BUFSIZ = 1, RS_DELAY };
|
|
enum { LION_PRIORITY = 1 };
|
|
enum { CXMA_MAXCPS = 1, CXMA_MAXCHAR, CXMA_BUFSIZ };
|
|
|
|
struct TPF_cmds {
|
|
char *hard_disp; /* Hardware Discipline name */
|
|
void (*setup)(void); /* Entry point for setup routine */
|
|
void (*print)(void); /* Entry point for transparent print routine */
|
|
void (*cleanup)(void);/* Entry piont for cleanup routine */
|
|
} TPF_cmds_tab[] = { /* Table of transparent print routines based on hardware discipline */
|
|
/* Arrange in alphabetical order according to hardware discipline */
|
|
{ "cxia", rs_setup, rs_print, rs_cleanup }, /* Native, 8, and 16-port routines */
|
|
{ "cxma", cxma_setup, cxma_print, cxma_cleanup }, /* 128-port adapter routines */
|
|
{ "lion", lion_setup, lion_print, lion_cleanup }, /* 64-port adapter routines */
|
|
{ "rs", rs_setup, rs_print, rs_cleanup }, /* Native, 8, and 16-port routines */
|
|
{ "sty", rs_setup, rs_print, rs_cleanup } /* Native, 8, and 16-port routines */
|
|
};
|
|
#define TPF_CMDS (sizeof(TPF_cmds_tab) / sizeof(struct TPF_cmds))
|
|
struct TPF_cmds *TPF;
|
|
struct TPF_cmds *lookup_TPF_cmds(register char *name);
|
|
struct flock lockdat; /* lockdata for fcntl() D61224 */
|
|
|
|
#ifdef DEBUG
|
|
FILE *dbg_fp;
|
|
#endif /* DEBUG */
|
|
|
|
/*******************************************************************************
|
|
* *
|
|
* NAME: pioout *
|
|
* *
|
|
* DESCRIPTION: Interface with printer device driver. *
|
|
* *
|
|
* PARAMETERS: argc - argument count; *
|
|
* argv - argument vector; *
|
|
* *
|
|
* GLOBALS: *
|
|
* MODIFIED: *
|
|
* *
|
|
* *
|
|
* RETURN VALUES: *
|
|
* *
|
|
* *
|
|
* *
|
|
*******************************************************************************/
|
|
main(argc, argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
int cnt, cnt2, ch, val1, val2;
|
|
int bytes;
|
|
int threshcnt, done;
|
|
FILE *prefile;
|
|
char *cp1, *cp2, *p1, *p2;
|
|
|
|
/* initialize invokers_uid and programs_uid for privilege toggling */
|
|
invokers_uid = getuidx(ID_REAL);
|
|
programs_uid = getuidx(ID_SAVED);
|
|
|
|
/* toggle to the privilege domain of the invoker */
|
|
seteuid(invokers_uid);
|
|
|
|
|
|
setlocale(LC_ALL, "");
|
|
(void) signal(SIGTERM, sigterm_exit);
|
|
/* watch for signal from piobe to terminate */
|
|
(void) siginterrupt(SIGTERM, 0);
|
|
/* make sure write doesn't restart if signal arrives */
|
|
(void) signal(SIGUSR1, sigusr1_exit);
|
|
/* watch for signal from filter to terminate */
|
|
|
|
/* Set up the lockdat for fcntl() replaces lockf() D61224 */
|
|
lockdat.l_whence = 0; /* measure from the beginning of file */
|
|
lockdat.l_start = 0; /* start lock from the beginning */
|
|
lockdat.l_len = 0; /* Go till end of file */
|
|
|
|
/* Determine If We're Running Under the Spooler */
|
|
if (getenv("PIOSTATUSFILE") != NULL) {
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
(void) log_init();
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
statusfile = 1;
|
|
devname = getenv("PIODEVNAME");
|
|
title = getenv("PIOTITLE");
|
|
qname = getenv("PIOQNAME");
|
|
qdname = getenv("PIOQDNAME");
|
|
from = getenv("PIOFROM");
|
|
ptrtype = getenv("PIOPTRTYPE");
|
|
jobnum = getenv("PIOJOBNUM");
|
|
mailonly = atoi(getenv("PIOMAILONLY"));
|
|
}
|
|
|
|
/* Determine Base Directory */
|
|
if ((basedir = getenv("PIOVARDIR")) == NULL)
|
|
basedir = defbasedir; /* default base directory */
|
|
|
|
/* Set Up Defaults */
|
|
prefixfile = suffixfile = outputfile
|
|
= sub_node = readroutine = nullstring;
|
|
|
|
len_ffstr = DEFAULT_FF_LEN;
|
|
(void) memcpy(ff_str, DEFAULT_FF_STR, len_ffstr + 1);
|
|
numformfeeds = DEF_NUM_FF_STRS;
|
|
|
|
len_canstr = DEFAULT_CAN_LEN;
|
|
(void) memcpy(can_str, DEFAULT_CAN_STR, len_canstr + 1);
|
|
numcanstrs = DEF_NUM_CAN_STRS;
|
|
|
|
/* Get ID of Print Job Submitter */
|
|
if (statusfile)
|
|
(void) strncpy(sub_user, from, sizeof(sub_user) - 1);
|
|
|
|
/* Process Flags */
|
|
opterr = 0; /* suppress error messages to stderr */
|
|
while ((ch = getopt(argc, argv, "A:B:C:D:E:F:I:K:L:N:O:P:R:S:W:X")) != EOF) {
|
|
switch (ch) {
|
|
case '?': /* unrecognized flag */
|
|
(void) fprintf
|
|
(stderr, piogetmsg(MF_PIOBE, 1, MSG_BADFLAG2));
|
|
PIOEXIT(PIOO_FAIL);
|
|
break;
|
|
case PREFLAG: /* Prefix File */
|
|
prefixfile = optarg;
|
|
break;
|
|
case SUFFLAG: /* Suffix File */
|
|
suffixfile = optarg;
|
|
break;
|
|
case OUTFLAG: /* Output File */
|
|
outputfile = optarg;
|
|
break;
|
|
case 'E': /* ioctl LPQUERY Mask to Ignore */
|
|
for (p1 = optarg; *p1 != '\0'; p1 = p2 + 1) {
|
|
if ((p2 = strchr(p1, ',')) == NULL)
|
|
p2 = strchr(p1, '\0') - 1;
|
|
else
|
|
*p2 = '\0';
|
|
if (!strcmp(p1, "LPST_ERROR"))
|
|
lpquery_val |= LPST_ERROR;
|
|
else if (!strcmp(p1, "LPST_SOFT"))
|
|
lpquery_val |= LPST_SOFT;
|
|
}
|
|
break;
|
|
case 'F': /* Form Feed String */
|
|
len_ffstr = oct2char(ff_str, optarg);
|
|
break;
|
|
case 'N': /* Number of Form Feeds to Output When EOF is Reached */
|
|
numformfeeds = atoi(optarg);
|
|
break;
|
|
case 'B': /* Total Number of Bytes For Print Job */
|
|
len_total = atoi(optarg);
|
|
break;
|
|
case 'A': /* Number of Bytes Already Printed */
|
|
len_done = len_done_orig = atoi(optarg);
|
|
break;
|
|
case LOADFLAG: /* Full Path Name of optional "read printer" Routine */
|
|
readroutine = optarg;
|
|
break;
|
|
case 'D': /* String to Send to Printer If Print Job Is Cancelled */
|
|
len_canstr = oct2char(can_str, optarg);
|
|
break;
|
|
case 'C': /* Number of Times to Send String to Printer If Cancelled */
|
|
numcanstrs = atoi(optarg);
|
|
break;
|
|
case 'I': /* User[@host] For "Intervention Required" Messages */
|
|
/* User IDs separated by ','; null string represents submitter*/
|
|
done = FALSE;
|
|
p1 = p2 = optarg;
|
|
do {
|
|
if (*p2 == ',' || *p2 == '\0') {
|
|
if (p2 == p1)
|
|
cp1 = sub_user;
|
|
else
|
|
cp1 = p1;
|
|
if (*p2 == '\0')
|
|
done = TRUE;
|
|
else
|
|
*p2 = '\0';
|
|
p1 = p2 + 1;
|
|
MALLOC(mp.charptr, sizeof(struct irqelem));
|
|
irquserwp = mp.irqptr; /* convert char * to struct irqelem * */
|
|
irquserwp->next = NULL;
|
|
irquserwp->user = cp1;
|
|
irquserwp->node = nullstring;
|
|
for (cp2 = cp1; *cp2; cp2++)
|
|
if (*cp2 == '@') {
|
|
*cp2 = '\0';
|
|
irquserwp->node = ++cp2;
|
|
break;
|
|
}
|
|
irquser_end->next = irquserwp; /* add element to end of chain*/
|
|
irquser_end = irquserwp;
|
|
}
|
|
p2++;
|
|
} while (!done);
|
|
break;
|
|
case 'K': /* Text string that identifies messages from */
|
|
/* PostScript printer to be discarded */
|
|
MALLOC(mp.charptr, sizeof(struct element));
|
|
discardwp = mp.elemptr; /* convert char * to struct elem * */
|
|
discardwp->next = NULL; /* initialize the element */
|
|
discardwp->text = optarg;
|
|
discard_end->next = discardwp; /* add element to end of chain */
|
|
discard_end = discardwp;
|
|
break;
|
|
case 'L': /* Text string that specifies a PostScript message type */
|
|
/* to be sent to "intervenion required" users */
|
|
MALLOC(mp.charptr, sizeof(struct element));
|
|
irqtypewp = mp.elemptr; /* convert char * to struct elem * */
|
|
irqtypewp->next = NULL; /* initialize the element */
|
|
irqtypewp->text = optarg;
|
|
irqtype_end->next = irqtypewp; /* add element to end of chain */
|
|
irqtype_end = irqtypewp;
|
|
break;
|
|
case 'W': /* Wait For EOF (hex 04) From Printer Before Exiting */
|
|
/* (allows PostScript error messages to be accepted) */
|
|
if (*optarg == '+')
|
|
wait_for_eof = TRUE;
|
|
break;
|
|
case 'X': /* Added for A12747. Special handling for power off. */
|
|
special_power = TRUE;
|
|
break;
|
|
} /*switch*/
|
|
} /*for*/
|
|
|
|
/* Message ipc initialization */
|
|
pmi_initmsgipc();
|
|
|
|
/* Ignore -W+ Flag If Not A Serial Device */
|
|
if (wait_for_eof && tcgetattr(1, &spio) < 0)
|
|
wait_for_eof = FALSE;
|
|
|
|
/* Isolate User Name & Node Name of Print Job Submitter */
|
|
for (cp1 = sub_user; *cp1 != '\0'; cp1++)
|
|
if (*cp1 == '@') {
|
|
*cp1 = '\0';
|
|
sub_node = ++cp1;
|
|
break;
|
|
}
|
|
|
|
/* If -I Flag Not Specified, Intervention Req'd User Same As Submitter */
|
|
if (irquser_beg.next == NULL) {
|
|
MALLOC(mp.charptr, sizeof(struct irqelem));
|
|
irquserwp = mp.irqptr; /* convert (char *) to (struct irqelem *) */
|
|
irquserwp->next = NULL;
|
|
irquserwp->user = sub_user;
|
|
irquserwp->node = sub_node;
|
|
irquser_beg.next = irquserwp; /* create a one-element chain */
|
|
}
|
|
|
|
/* Build Device Names For Messages */
|
|
(void) strcpy(dev_sub, devname); /* device name for msgs to submitter */
|
|
if (ptrtype && *ptrtype != '\0') {
|
|
(void) strcat(dev_sub, " (");
|
|
(void) strcat(dev_sub, ptrtype);
|
|
(void) strcat(dev_sub, ")");
|
|
}
|
|
(void) strcpy(dev_irq, dev_sub); /* device name for "intervention req'd" msgs*/
|
|
if (gethostname(thishost, sizeof(thishost)) == 0 && *thishost != '\0') {
|
|
if (*sub_node && strcmp(sub_node, thishost)) {
|
|
(void) strcat(dev_sub, " @ ");
|
|
(void) strcat(dev_sub, thishost);
|
|
}
|
|
(void) strcat(dev_irq, " @ ");
|
|
(void) strcat(dev_irq, thishost);
|
|
}
|
|
|
|
|
|
/* Load the Optional "read printer" Routine */
|
|
if (*readroutine != '\0') {
|
|
if ((loadrc = (int (*)())load(readroutine, 0, 0)) == NULL) {
|
|
cnt = sprintf(msgbuf, piogetmsg(MF_PIOBE, 1, MSG_LOAD2),
|
|
LOADFLAG, readroutine, errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_LOAD2,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(LOADFLAGSTR);
|
|
(void)pmi_bldstrfrm(readroutine);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
if ((rc = loadbind(0, loadrc, main)) < 0) {
|
|
cnt = sprintf(msgbuf, piogetmsg(MF_PIOBE, 1, MSG_BIND2),
|
|
LOADFLAG, readroutine, errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_BIND2,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(LOADFLAGSTR);
|
|
(void)pmi_bldstrfrm(readroutine);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
}
|
|
|
|
/* If Output is to File Instead of Printer, Open the File */
|
|
if (*outputfile != '\0') {
|
|
(void) unlink(outputfile);
|
|
(void) umask (0777 ^ (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP));
|
|
fildes = open(outputfile, O_CREAT + O_WRONLY + O_TRUNC, 0660);
|
|
if (fildes < 0) {
|
|
cnt = sprintf(msgbuf, piogetmsg(MF_PIOBE, 1, MSG_FOPEN2),
|
|
OUTFLAG, outputfile, errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_FOPEN2,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(OUTFLAGSTR);
|
|
(void)pmi_bldstrfrm(outputfile);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
printer_dd = FALSE;
|
|
} else
|
|
fildes = 1; /* output is to printer device driver or pipe */
|
|
|
|
/* Determine If Using the Printer Device Driver; If So, Save Existing Modes */
|
|
if (printer_dd) {
|
|
if (ioctl(1, LPRMODG, &lpr_orig) < 0) {
|
|
if (errno == EINTR)
|
|
(void) sigterm_exit();
|
|
if (errno == EBADF || errno == EFAULT) {
|
|
cnt = sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_IOCTL),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_IOCTL,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
printer_dd = FALSE; /* not the printer device driver */
|
|
}
|
|
}
|
|
|
|
/* If Using Printer Device Driver, Set Up Our Printer Modes */
|
|
if (printer_dd) {
|
|
lpr_piobe.modes = PLOT + RPTERR;
|
|
if (ioctl(1, LPRMODS, &lpr_piobe) < 0) {
|
|
if (errno == EINTR)
|
|
(void) sigterm_exit();
|
|
cnt = sprintf
|
|
(msgbuf, piogetmsg(MF_PIOBE, 1, MSG_IOCTL), DEVNAME, errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_IOCTL,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
}
|
|
|
|
/* If not printer device and not to a file
|
|
check for tty attached printer */
|
|
if (isatty(fildes) && getenv("PIOASCII_ATTR")) {
|
|
(void) transp_init(); /* Run initialization routine */
|
|
ttyprint++; /* set flag for terminal attached printer */
|
|
}
|
|
|
|
/* Streams initialization */
|
|
if (printer_dd) {
|
|
SP_WRITE_INIT
|
|
}
|
|
|
|
/* Decide Whether or Not to Update Percentage Status Here */
|
|
dothresh = (statusfile && !printer_dd && !(*outputfile) && len_total != 0);
|
|
|
|
/* Process Input Data Stream and Prefix File (if any) */
|
|
bytes = threshcnt = 0;
|
|
while ((val1 = getc(stdin)) != EOF) {
|
|
if (bytes++ == 0 && *prefixfile != '\0') {
|
|
/* Process Prefix File */
|
|
if ((prefile = fopen(prefixfile, "r")) == NULL) {
|
|
cnt = sprintf(msgbuf, piogetmsg(MF_PIOBE, 1, MSG_FOPEN2),
|
|
PREFLAG, prefixfile, errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_FOPEN2,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(PREFLAGSTR);
|
|
(void)pmi_bldstrfrm(prefixfile);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
if (fstat(fileno(prefile), &statbuf) < 0) {
|
|
cnt = sprintf(msgbuf, piogetmsg(MF_PIOBE, 1, MSG_STAT2),
|
|
PREFLAG, prefixfile, errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_STAT2,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(PREFLAGSTR);
|
|
(void)pmi_bldstrfrm(prefixfile);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
len_done -= (int) statbuf.st_size; /* prefix file size not included
|
|
in "percent done" calculation */
|
|
while ((val2 = getc(prefile)) != EOF)
|
|
OUTC(val2);
|
|
}
|
|
OUTC(val1);
|
|
if (dothresh && ++threshcnt >= BUFSIZ) {
|
|
len_done += threshcnt;
|
|
cnt = (len_done * 100) / len_total;
|
|
if (cnt > 100)
|
|
cnt = 100;
|
|
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
if (log_init() >= 0)
|
|
(void) log_percent(cnt);
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
|
|
threshcnt = 0;
|
|
}
|
|
}
|
|
|
|
/* Output Form Feed (if wanted) */
|
|
for (cnt = 0; cnt < numformfeeds; cnt++)
|
|
for (cnt2 = 0; cnt2 < len_ffstr; cnt2++)
|
|
OUTC(*(ff_str + cnt2));
|
|
|
|
/* Process Suffix File (if any) */
|
|
if (bytes > 0 && *suffixfile != '\0') {
|
|
if ((suffile = fopen(suffixfile, "r")) == NULL) {
|
|
cnt = sprintf(msgbuf, piogetmsg(MF_PIOBE, 1, MSG_FOPEN2),
|
|
SUFFLAG, suffixfile, errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_FOPEN2,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(SUFFLAGSTR);
|
|
(void)pmi_bldstrfrm(suffixfile);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
(void) setvbuf(suffile, NULL, _IOFBF, BUFSIZ);
|
|
while ((val2 = getc(suffile)) != EOF)
|
|
OUTC(val2);
|
|
}
|
|
|
|
/* Cleanup */
|
|
FLUSH();
|
|
|
|
PIOEXIT(PIOO_GOOD);
|
|
return(0); /* won't get here, but it keeps lint happy */
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* *
|
|
* NAME: outflush *
|
|
* *
|
|
* DESCRIPTION: Flush the output buffer to the printer *
|
|
* *
|
|
* PARAMETERS: cleanup: 0 = called by OUTC(); normal processing *
|
|
* 1 = called by FLUSH(); cleanup time *
|
|
* *
|
|
* GLOBALS: *
|
|
* MODIFIED: *
|
|
* *
|
|
* RETURN VALUES: 0 *
|
|
* *
|
|
* ERROR EXIT: exit PIOOBAD *
|
|
* *
|
|
* *
|
|
*******************************************************************************/
|
|
|
|
outflush(cleanup)
|
|
int cleanup; /* 0 = called by OUTC(); 1 = called by FLUSH() */
|
|
{
|
|
int bytes_read, bytes_sent, bytes_to_send, cnt, rtnrc;
|
|
struct lpquery query_info;
|
|
char *readbuf, *cp1, *cp2;
|
|
char *sendp; /* ptr to where data is to be written from */
|
|
struct piormsg *msgp; /* ptr to info. passed to loadable ddifexit()*/
|
|
char wkbuf[200]; /* work buffer */
|
|
int saverrno;
|
|
|
|
#ifdef DEBUG
|
|
FILE *dbg_fp = fopen("/dev/console","w");
|
|
(void)setvbuf(dbg_fp,NULL,_IONBF,0);
|
|
#endif
|
|
|
|
|
|
sendp = outbuf;
|
|
off_msgdone = pout_msgdone = tout_msgdone = noslct_msgdone = FALSE;
|
|
|
|
/* Loop Till Data Is Output, or We Give Up */
|
|
while ((bytes_to_send = nextp - sendp) > 0
|
|
|| (cleanup && wait_for_eof && eof_level > 0)) {
|
|
|
|
if (bytes_to_send) {
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"pioout: bytes_to_send = %ld; sendp = %5.5s;\n",
|
|
bytes_to_send,sendp);
|
|
errno = 0;
|
|
# endif
|
|
/* Send the Bytes In the Buffer to the Printer */
|
|
bytes_sent = SP_WRITE(1, sendp, bytes_to_send);
|
|
saverrno = errno;
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"pioout: bytes_sent = %ld; errno = %ld\n",
|
|
bytes_sent,saverrno);
|
|
# endif
|
|
if (bytes_sent < 0) {
|
|
if (term_on_error)
|
|
if (sigterm)
|
|
PIOEXIT(PIOO_TERMQUIT) /* no semicolon */
|
|
else if (sigusr1)
|
|
PIOEXIT(PIOO_USR1QUIT);
|
|
|
|
if (saverrno == EINTR)
|
|
(void) sigterm_exit(SIGTERM);
|
|
|
|
/* Now that write() for the drivers (esp. parallel) returns -1
|
|
with errno ENOTREADY for printer intervention conditions, skip
|
|
the exit().
|
|
Check for ETIME and EBUSY for serial tty (sptr) drivers. */
|
|
if (isastream(1) && saverrno == EBUSY)
|
|
bytes_sent = bytes_to_send;
|
|
else if (saverrno == ENOTREADY || saverrno == EBUSY ||
|
|
saverrno == ETIME)
|
|
bytes_sent = 0;
|
|
else {
|
|
cnt = sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_WRITE), DEVNAME, saverrno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_WRITE,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(saverrno);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
if (special_power)
|
|
{
|
|
PIOEXIT(EXITIO);
|
|
}
|
|
else
|
|
{
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
}
|
|
}
|
|
if (wait_for_eof)
|
|
for (cnt = 0; cnt < bytes_sent; cnt++)
|
|
if (*(sendp + cnt) == '\004')
|
|
eof_level++;
|
|
sendp += bytes_sent;
|
|
/* Update Percentage Status */
|
|
len_done += bytes_sent;
|
|
if (statusfile && len_total != 0 && len_done > len_done_orig) {
|
|
cnt = (len_done * 100) / len_total;
|
|
if (cnt > 100)
|
|
cnt = 100;
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
if (log_init() >= 0)
|
|
(void) log_percent(cnt);
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
}
|
|
} else
|
|
(void) sleep(1); /* waiting for EOF (hex 04) from PostScript printer */
|
|
|
|
/* Query to See What's Happening */
|
|
if (ioctl(1, LPQUERY, &query_info) < 0) {
|
|
cnt = sprintf
|
|
(msgbuf, piogetmsg(MF_PIOBE, 1, MSG_IOCTL), DEVNAME, errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_IOCTL,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
|
|
/* If Print Job Being Cancelled, Don't Wait Around */
|
|
if (sigterm)
|
|
if (query_info.status &
|
|
(LPST_POUT + LPST_TOUT + LPST_ERROR + LPST_NOSLCT + LPST_SOFT)) {
|
|
(void)ioctl(1,TCFLSH,0);
|
|
PIOEXIT(PIOO_TERMQUIT);
|
|
}
|
|
|
|
/* Check For "Read" Condition */
|
|
if (query_info.reccnt > 0) {
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"pioout: query_info.reccnt = %ld\n",
|
|
query_info.reccnt);
|
|
# endif
|
|
MALLOC(readbuf, query_info.reccnt + 200);
|
|
bytes_read = read(1, readbuf, query_info.reccnt);
|
|
if (bytes_read < 0) {
|
|
if (errno == EINTR)
|
|
(void) sigterm_exit(SIGTERM);
|
|
cnt = sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_READ), DEVNAME, errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_READ,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
*(readbuf + bytes_read) = '\0';
|
|
|
|
/* Look For end-of-file Character Returned by Printer */
|
|
for (cp1 = readbuf; *cp1; cp1++)
|
|
if (*cp1 == '\004') {
|
|
for (cp2 = cp1; *cp2; cp2++)
|
|
*cp2 = *(cp2 + 1);
|
|
if (eof_level > 0)
|
|
eof_level--;
|
|
}
|
|
|
|
/* Set Up Default Values */
|
|
msgp = &msginfo;
|
|
msgp->textptr = readbuf; /* msg read from printer */
|
|
msgp->sub_predef = 1; /* assume "Message from printer xxx." */
|
|
MALLOC(msgp->sub_text, bytes_read + 101);
|
|
*(msgp->sub_text) = '\0'; /* buffer for messages to submitter */
|
|
msgp->irq_predef = 1; /* assume "Message from printer xxx." */
|
|
MALLOC(msgp->irq_text, bytes_read + 101);
|
|
*(msgp->irq_text) = '\0'; /* buffer for msgs to "int. req'd" user */
|
|
msgp->irq_typep = irqtype_beg.next; /* chain of message types for
|
|
"intervention req'd" user */
|
|
msgp->discardp = discard_beg.next; /* chain of strings identifying
|
|
messages to be discarded */
|
|
|
|
if (*readroutine != NULL) { /* if routine supplied to parse msg */
|
|
/* Let dynamically loaded parsemsg() parse the message text */
|
|
rtnrc = parsemsg(msgp); /* call the loaded subroutine */
|
|
} else { /* no read routine, so just send the msg */
|
|
/* No msg parse subroutine specified, so we'll do it */
|
|
{ /* open block */
|
|
char *sub_ptr, *irq_ptr, *p1, *p2, *p3, charsave;
|
|
struct element *ep;
|
|
|
|
sub_ptr = msgp->sub_text;
|
|
irq_ptr = msgp->irq_text;
|
|
p1 = msgp->textptr;
|
|
while (p1 = strstr(p1, BEGSTR)) {
|
|
if (!(p2 = strstr(p1 + BEGLEN, ENDSTR)))
|
|
break;
|
|
charsave = *(p2 + ENDLEN);
|
|
*(p2 + ENDLEN) = '\0';
|
|
for (ep = msgp->discardp; ep; ep = ep->next)
|
|
if (strstr(p1, ep->text))
|
|
goto NEXTMSG;
|
|
for (ep = msgp->irq_typep; ep; ep = ep->next)
|
|
if (p3 = strstr(p1 + BEGLEN, ep->text)) {
|
|
p3 += strlen(ep->text) + 2;
|
|
(void) strncpy(irq_ptr, p3, (p2-p3));
|
|
irq_ptr += (p2-p3);
|
|
*irq_ptr++ = '\n';
|
|
goto NEXTMSG;
|
|
}
|
|
(void) strncpy(sub_ptr, p1, p2 + ENDLEN - p1);
|
|
sub_ptr += p2 + ENDLEN - p1;
|
|
*sub_ptr++ = '\n';
|
|
NEXTMSG:
|
|
p1 = p2 + ENDLEN;
|
|
*p1 = charsave;
|
|
}
|
|
*sub_ptr = *irq_ptr = '\0';
|
|
} /* close block */
|
|
rtnrc = 0;
|
|
}
|
|
|
|
/* check for place-holder character */
|
|
if (msgp->sub_text)
|
|
for (cp1 = msgp->sub_text; *cp1; cp1++)
|
|
if (*cp1 == *placeholder)
|
|
*cp1 = ' ';
|
|
if (msgp->irq_text)
|
|
for (cp1 = msgp->irq_text; *cp1; cp1++)
|
|
if (*cp1 == *placeholder)
|
|
*cp1 = ' ';
|
|
|
|
/* Send Message (if any) for Print Job Submitter */
|
|
if (msgp->sub_text && *(msgp->sub_text)) {
|
|
if (msgp->sub_predef) /* if "Message from printer xxx:" wanted */
|
|
{
|
|
(void) sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_READHDR),DEVNAME);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_WARNING_RESOURCE_NEEDS_ATTENTION,
|
|
MSG_READHDR,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*msgbuf = '\0';
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_WARNING_RESOURCE_NEEDS_ATTENTION,0,0,"");
|
|
}
|
|
}
|
|
piomsgout(msgp->sub_text, strlen(msgp->sub_text), msgbuf, 1);
|
|
}
|
|
|
|
/* Send Message (if any) for "Intervention Required" User */
|
|
if (msgp->irq_text && *(msgp->irq_text)) {
|
|
if (msgp->irq_predef) /* if "Message from printer xxx:" wanted */
|
|
{
|
|
(void) sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_READHDR),DEVNAME);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_WARNING_RESOURCE_NEEDS_ATTENTION,
|
|
MSG_READHDR,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*msgbuf = '\0';
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_WARNING_RESOURCE_NEEDS_ATTENTION,0,0,"");
|
|
}
|
|
}
|
|
piomsgout(msgp->irq_text, strlen(msgp->irq_text), msgbuf, 2);
|
|
}
|
|
|
|
/* See If Need to Exit */
|
|
if (rtnrc == PIOR_END)
|
|
PIOEXIT(PIOO_GOOD) /* no ; */
|
|
else if (rtnrc == PIOR_BAD)
|
|
PIOEXIT(PIOO_BAD) /* no ; */
|
|
else if (rtnrc == PIOR_FAIL)
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
|
|
/* Check For "Power Off" Condition */
|
|
if (query_info.status & LPST_OFF) {
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"pioout: LPST_OFF!!!\n");
|
|
# endif
|
|
if (!off_msgdone) {
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
if (log_init() >= 0)
|
|
(void) log_status(WAITING);
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
cnt = sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_INTREQ), DEVNAME);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_WARNING_RESOURCE_NEEDS_ATTENTION,
|
|
MSG_PAPER,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 2);
|
|
off_msgdone = TRUE;
|
|
}
|
|
continue;
|
|
} else
|
|
if (off_msgdone) {
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
if (log_init() >= 0)
|
|
(void) log_status(RUNNING);
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
off_msgdone = FALSE;
|
|
}
|
|
|
|
/* Check For "Paper Out" Condition */
|
|
if (query_info.status & LPST_POUT) {
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"pioout: LPST_POUT!!!\n");
|
|
# endif
|
|
if (!pout_msgdone) {
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
if (log_init() >= 0)
|
|
(void) log_status(WAITING);
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
cnt = sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_PAPER), DEVNAME);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_WARNING_RESOURCE_NEEDS_ATTENTION,
|
|
MSG_PAPER,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 2);
|
|
pout_msgdone = TRUE;
|
|
}
|
|
continue;
|
|
} else
|
|
if (pout_msgdone) {
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
if (log_init() >= 0)
|
|
(void) log_status(RUNNING);
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
pout_msgdone = FALSE;
|
|
}
|
|
|
|
/* Check For "Off line" ("Intervention Required") Condition */
|
|
if (query_info.status & LPST_NOSLCT) {
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"pioout: LPST_NOSLCT!!!\n");
|
|
# endif
|
|
if (!noslct_msgdone) {
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
if (log_init() >= 0)
|
|
(void) log_status(WAITING);
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
cnt = sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_INTREQ), DEVNAME);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_WARNING_RESOURCE_NEEDS_ATTENTION,
|
|
MSG_INTREQ,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 2);
|
|
noslct_msgdone = TRUE;
|
|
}
|
|
continue;
|
|
} else
|
|
if (noslct_msgdone) {
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
if (log_init() >= 0)
|
|
(void) log_status(RUNNING);
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
noslct_msgdone = FALSE;
|
|
}
|
|
|
|
/* Check For "Intervention Required" Condition */
|
|
if (query_info.status & LPST_TOUT) {
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"pioout: LPST_TOUT!!!\n");
|
|
# endif
|
|
if (!tout_msgdone) {
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
if (log_init() >= 0)
|
|
(void) log_status(WAITING);
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
cnt = sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_INTREQ), DEVNAME);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_WARNING_RESOURCE_NEEDS_ATTENTION,
|
|
MSG_INTREQ,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 2);
|
|
tout_msgdone = TRUE;
|
|
}
|
|
continue;
|
|
} else
|
|
if (tout_msgdone) {
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
if (log_init() >= 0)
|
|
(void) log_status(RUNNING);
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
tout_msgdone = FALSE;
|
|
}
|
|
|
|
/* Check For "Error" Condition */
|
|
if ((mask = query_info.status & (LPST_ERROR + LPST_SOFT))
|
|
&& mask != lpquery_val) {
|
|
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"pioout: LPST_ERROR or LPST_SOFT!!!\n");
|
|
# endif
|
|
/* Build Error Message */
|
|
*wkbuf = '\0';
|
|
if (query_info.status & LPST_POUT)
|
|
strcat(wkbuf, "LPST_POUT");
|
|
if (query_info.status & LPST_TOUT) {
|
|
if (*wkbuf != '\0')
|
|
strcat(wkbuf, " + ");
|
|
strcat(wkbuf, "LPST_TOUT");
|
|
}
|
|
if (query_info.status & LPST_ERROR) {
|
|
if (*wkbuf != '\0')
|
|
strcat(wkbuf, " + ");
|
|
strcat(wkbuf, "LPST_ERROR");
|
|
}
|
|
if (query_info.status & LPST_BUSY) {
|
|
if (*wkbuf != '\0')
|
|
strcat(wkbuf, " + ");
|
|
strcat(wkbuf, "LPST_BUSY");
|
|
}
|
|
if (query_info.status & LPST_NOSLCT) {
|
|
if (*wkbuf != '\0')
|
|
strcat(wkbuf, " + ");
|
|
strcat(wkbuf, "LPST_NOSLCT");
|
|
}
|
|
if (query_info.status & LPST_SOFT) {
|
|
if (*wkbuf != '\0')
|
|
strcat(wkbuf, " + ");
|
|
strcat(wkbuf, "LPST_SOFT");
|
|
}
|
|
if (query_info.reccnt != 0)
|
|
sprintf(wkbuf + strlen(wkbuf)," (reccnt = %d)", query_info.reccnt);
|
|
|
|
cnt = sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_ERROR), DEVNAME, wkbuf);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_ERROR,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldstrfrm(wkbuf);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
}
|
|
|
|
nextp = outbuf; /* now have empty buffer */
|
|
#ifdef DEBUG
|
|
(void)fclose(dbg_fp);
|
|
#endif
|
|
return(0);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* *
|
|
* NAME: outflush2 *
|
|
* *
|
|
* DESCRIPTION: Flush the output buffer to the output file *
|
|
* *
|
|
* PARAMETERS: (none) *
|
|
* *
|
|
* GLOBALS: *
|
|
* MODIFIED: *
|
|
* *
|
|
* RETURN VALUES: 0 *
|
|
* *
|
|
* ERROR EXIT: exit PIOOBAD *
|
|
* *
|
|
* *
|
|
*******************************************************************************/
|
|
|
|
outflush2()
|
|
{
|
|
int bytes_read, bytes_sent, bytes_to_send, cnt;
|
|
int fullpipecnt = 0;
|
|
char *sendp; /* ptr to where data is to be written from */
|
|
|
|
sendp = outbuf;
|
|
|
|
/* Loop Till Data Is Output, or We Give Up */
|
|
while ((bytes_to_send = nextp - sendp) > 0) {
|
|
|
|
/* Send the Bytes In the Buffer to the Printer */
|
|
bytes_sent = write(fildes, sendp, bytes_to_send);
|
|
if (bytes_sent < 0) {
|
|
if (term_on_error)
|
|
if (sigterm)
|
|
PIOEXIT(PIOO_TERMQUIT) /* no semicolon */
|
|
else if (sigusr1)
|
|
PIOEXIT(PIOO_USR1QUIT);
|
|
|
|
if (errno == EINTR)
|
|
(void) sigterm_exit(SIGTERM);
|
|
cnt = sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_WRITE), DEVNAME, errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_WRITE,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
} else if (bytes_sent == 0 && sigterm) {
|
|
/* if pipe is full and SIGTERM has been received */
|
|
if (++fullpipecnt > 5) /* if threshold exceeded */
|
|
PIOEXIT(PIOO_TERMQUIT); /* give up */
|
|
sleep(1);
|
|
continue;
|
|
}
|
|
fullpipecnt = 0;
|
|
sendp += bytes_sent;
|
|
/* Update Percentage Status */
|
|
len_done += bytes_sent;
|
|
if (statusfile && len_total != 0 && len_done > len_done_orig) {
|
|
cnt = (len_done * 100) / len_total;
|
|
if (cnt > 100)
|
|
cnt = 100;
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
if (log_init() >= 0)
|
|
(void) log_percent(cnt);
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
}
|
|
}
|
|
|
|
nextp = outbuf; /* now have empty buffer */
|
|
return(0);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* *
|
|
* NAME: oct2char *
|
|
* *
|
|
* DESCRIPTION: Converts octal substrings embedded in odm attribute values *
|
|
* into 1 byte characters. For example a substring "\77" or *
|
|
* "\077" will be converted to a character '?'.
|
|
* *
|
|
* PARAMETERS: instr - input string
|
|
* outstr - output string
|
|
* *
|
|
* RETURN VALUES: length of output string
|
|
* *
|
|
*******************************************************************************/
|
|
|
|
oct2char(outstr, instr)
|
|
char *outstr; /* output string */
|
|
char *instr; /* input string */
|
|
{
|
|
char *newstring_p; /* pointer to transformed string */
|
|
char *string_p; /* pointer to original string string memory */
|
|
|
|
int backslash = 0; /* '\' flag, 1 if one is found */
|
|
int octcnt = 0; /* number of digits following a '\' */
|
|
int octindex = 0; /* index into octarray */
|
|
int octvalue = 0; /* value of octal string */
|
|
|
|
unsigned int octarray[3]; /* array which holds "octal" chars */
|
|
unsigned int newstrsiz = 0; /* size of the transformed string */
|
|
|
|
newstring_p = outstr;
|
|
|
|
for (string_p = instr; *string_p != '\0'; string_p++)
|
|
{
|
|
if (*string_p == '\\')
|
|
{
|
|
/* check for an escaped '\', i.e. "\\" */
|
|
if (backslash = (backslash) ? 0 : 1)
|
|
continue;
|
|
}
|
|
else if (backslash) /* should be some octal digits coming our way */
|
|
{
|
|
/* copy a max of 3 octal digits to octarray */
|
|
for (octcnt =0; octcnt <3 && (*string_p >= '0' && *string_p <='7');)
|
|
{
|
|
octarray[octcnt] = *string_p -'0'; /* convert char to int */
|
|
octcnt++, string_p++;
|
|
}
|
|
if (octcnt)
|
|
{
|
|
/* total up the octal digits */
|
|
for (octindex = --octcnt; octindex >= 0; octindex--)
|
|
octvalue +=(1<<(3 *(octcnt -octindex)))* octarray[octindex];
|
|
|
|
if (octvalue > 255)
|
|
{
|
|
(void) fprintf(stderr, piogetmsg(MF_PIOBE, 1,
|
|
MSG_BADSTRING), optopt);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
string_p--;
|
|
*newstring_p = (char) octvalue; /* copy new octval to new str */
|
|
newstring_p++; newstrsiz++;
|
|
backslash = octvalue = 0;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
(void) fprintf(stderr, piogetmsg(MF_PIOBE, 1,
|
|
MSG_BADSTRING), optopt);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
}
|
|
*newstring_p = *string_p;
|
|
newstring_p++;
|
|
newstrsiz++;
|
|
}
|
|
|
|
return(newstrsiz);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* *
|
|
* NAME: piomsgout *
|
|
* *
|
|
* DESCRIPTION: If called by Qdaemon piomsgout locks the statusfile and *
|
|
* calls sysnot() and then release the lock otherwise *
|
|
* the message goes to standard error. *
|
|
* *
|
|
* PARAMETERS: msgstr - message text *
|
|
* msglen - length of msgstr *
|
|
* subhead = string placed after msg header & before message *
|
|
* target - 1 submitter *
|
|
* 2 "intervention required" user(s) from si attribute.*
|
|
* *
|
|
* GLOBALS: *
|
|
* REFERENCED: statusfile - indicates whether a statusfile exists. *
|
|
* *
|
|
* *
|
|
* RETURN VALUES: void *
|
|
* *
|
|
*******************************************************************************/
|
|
|
|
void
|
|
piomsgout(msgstr, msglen, subhead, target)
|
|
char *msgstr; /* error message test */
|
|
int msglen; /* length of message */
|
|
char *subhead; /* string placed after msg header & before message */
|
|
int target; /* 1 (submitter), 2 (int req'd user - "si"), 3 (both) */
|
|
{
|
|
char *msgptr, *catmsg, *cp1, *cp2, *cp3, *msgtxt;
|
|
char fname[200];
|
|
char *dev_str;
|
|
int hdrlen, subhdrlen, cnt;
|
|
struct irqelem *irqp;
|
|
FILE *fd;
|
|
char wkbuf[1000];
|
|
char titlebuf[1000];
|
|
|
|
if (statusfile)
|
|
{
|
|
subhdrlen = strlen(subhead);
|
|
catmsg = piogetmsg(MF_PIOBE, 1, MSG_SPOOLHDR);
|
|
(void) sprintf(titlebuf, "%s (%s)", jobnum, title);
|
|
hdrlen = sprintf(wkbuf, catmsg, titlebuf);
|
|
MALLOC(msgptr, msglen + hdrlen +subhdrlen + 200);
|
|
(void) memcpy(msgptr, wkbuf, hdrlen);
|
|
msgtxt = msgptr + hdrlen;
|
|
|
|
if (target == 2)
|
|
dev_str = dev_irq;
|
|
else
|
|
dev_str = dev_sub;
|
|
cp1 = msgtxt;
|
|
/* copy subhead text, replacing place holder with device name */
|
|
for (cp2 = subhead; *cp2 != '\0'; cp2++)
|
|
if (*cp2 == *placeholder)
|
|
for (cp3 = dev_str; *cp3 != '\0'; cp3++)
|
|
*cp1++ = *cp3;
|
|
else
|
|
*cp1++ = *cp2;
|
|
/* copy message text, replacing place holder with device name */
|
|
for (cp2 = msgstr; (cp2 - msgstr) < msglen; cp2++)
|
|
if (*cp2 == *placeholder)
|
|
for (cp3 = dev_str; *cp3 != '\0'; cp3++)
|
|
*cp1++ = *cp3;
|
|
else
|
|
*cp1++ = *cp2;
|
|
*cp1 = '\0';
|
|
|
|
(void) freopen("/dev/null", "a", stderr);
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_dsptchmsg(msgptr);
|
|
}
|
|
else {
|
|
if (target == 2) {
|
|
irqp = irquser_beg.next;
|
|
/* if submitter is the only user in list */
|
|
if ((irqp->next == NULL) && (!strcmp(irqp->user,sub_user)))
|
|
(void) sysnot(irqp->user, irqp->node, msgptr,
|
|
mailonly?DOMAIL:DOWRITE);
|
|
else
|
|
for (; irqp; irqp = irqp->next)
|
|
(void) sysnot(irqp->user, irqp->node, msgptr,DOWRITE);
|
|
}
|
|
else
|
|
(void) sysnot(sub_user, sub_node, msgptr, mailonly?DOMAIL:DOWRITE);
|
|
}
|
|
|
|
{ /* keep a copy of the message in var dir for autopsies */
|
|
long clock;
|
|
struct tm *tdate;
|
|
char pdate[50];
|
|
clock = time ((long *) 0); /* get the time */
|
|
tdate = localtime(&clock);
|
|
(void) strftime(pdate,350,"%a %h %d %T %Y",tdate);
|
|
|
|
(void) sprintf(fname, "%s/msg2.%s:%s", basedir, qname, qdname);
|
|
|
|
(void) unlink(fname);
|
|
(void) umask (0777 ^ (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH));
|
|
cnt = open(fname, O_CREAT + O_WRONLY + O_TRUNC, 0664);
|
|
if (cnt > 0) {
|
|
fd = fdopen(cnt, "w");
|
|
fprintf(fd,
|
|
"-----------------------------------------------------------\n");
|
|
fprintf(fd,"%s", pdate);
|
|
if (target == 2) {
|
|
for (irqp = irquser_beg.next; irqp; irqp = irqp->next) {
|
|
fprintf(fd, " (%s", irqp->user);
|
|
if (*(irqp->node))
|
|
fprintf(fd, " @ %s", irqp->node);
|
|
fprintf(fd, ")");
|
|
}
|
|
} else {
|
|
fprintf(fd, " (%s", sub_user);
|
|
if (*sub_node)
|
|
fprintf(fd, " @ %s", sub_node);
|
|
fprintf(fd, ")");
|
|
}
|
|
|
|
fprintf(fd, "\n");
|
|
|
|
fprintf(fd,
|
|
"-----------------------------------------------------------\n\n");
|
|
cnt=fprintf(fd,"%s",msgptr);
|
|
fflush(fd);
|
|
}
|
|
} /* end block */
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
}
|
|
else {
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_dsptchmsg(msgstr);
|
|
}
|
|
else {
|
|
(void) fprintf(stderr, "%s\n", msgstr);
|
|
(void) fflush(stderr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* *
|
|
* NAME: sigterm_exit *
|
|
* *
|
|
* DESCRIPTION: Exit routine for SIGTERM signal *
|
|
* *
|
|
* PARAMETERS: signal value *
|
|
* *
|
|
* RETURN VALUES: (none) *
|
|
* *
|
|
*******************************************************************************/
|
|
|
|
sigterm_exit()
|
|
{
|
|
int cnt, cnt1, cnt2, val2, rc;
|
|
int i;
|
|
#ifdef DEBUG
|
|
FILE *dbg_fp;
|
|
#endif
|
|
|
|
(void) signal(SIGTERM, SIG_IGN);
|
|
sigterm = TRUE;
|
|
# ifdef DEBUG
|
|
dbg_fp = fopen("/dev/console","w");
|
|
(void)setvbuf(dbg_fp,NULL,_IONBF,0);
|
|
(void)fprintf(dbg_fp,"pioout: sigterm_exit entered\n");
|
|
#endif
|
|
|
|
if (printer_dd) {
|
|
/* For serial printers, flush the data and quit. */
|
|
if (isastream(fildes)) {
|
|
(void)ioctl(1,TCFLSH,TCIOFLUSH);
|
|
PIOEXIT(PIOO_TERMOK);
|
|
}
|
|
|
|
/* If Can't Print, Terminate */
|
|
if (off_msgdone || pout_msgdone || tout_msgdone || noslct_msgdone)
|
|
PIOEXIT(PIOO_TERMQUIT);
|
|
} else
|
|
rc = fcntl(fildes, F_SETFL, O_NDELAY); /* if pipe, will get return
|
|
code of 0 from write() when
|
|
pipe is full */
|
|
/* If Encounter Print Problem, Terminate */
|
|
term_on_error = TRUE;
|
|
|
|
/* Send Nulls (or whatever) In Case We're In the Middle of a Command */
|
|
nextp = outbuf;
|
|
/* Control the number of Nulls on transparent printers */
|
|
if (ttyprint)
|
|
i = 1;
|
|
else
|
|
i = numcanstrs - len_ffstr;
|
|
for (cnt1 = 0; cnt1 < i ; cnt1++)
|
|
for (cnt2 = 0; cnt2 < len_canstr; cnt2++)
|
|
OUTC(*(can_str + cnt2));
|
|
|
|
for (cnt2 = 0; cnt2 < len_ffstr; cnt2++)
|
|
OUTC(*(ff_str + cnt2));
|
|
|
|
/* Process Suffix File (if any) */
|
|
if (*suffixfile != '\0') {
|
|
if ((suffile = fopen(suffixfile, "r")) == NULL) {
|
|
cnt = sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_FOPEN2),
|
|
SUFFLAG, suffixfile, errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_FOPEN2,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(SUFFLAGSTR);
|
|
(void)pmi_bldstrfrm(suffixfile);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
while ((val2 = getc(suffile)) != EOF)
|
|
OUTC(val2);
|
|
}
|
|
|
|
FLUSH();
|
|
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"pioout: sigterm_exit exiting\n");
|
|
(void)fclose(dbg_fp);
|
|
# endif
|
|
PIOEXIT(PIOO_TERMOK);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* *
|
|
* NAME: sigusr1_exit *
|
|
* *
|
|
* DESCRIPTION: Exit routine for SIGUSR1 signal *
|
|
* *
|
|
* PARAMETERS: signal value *
|
|
* *
|
|
* RETURN VALUES: (none) *
|
|
* *
|
|
*******************************************************************************/
|
|
|
|
sigusr1_exit()
|
|
{
|
|
int val2, cnt;
|
|
|
|
(void) signal(SIGUSR1, SIG_IGN);
|
|
sigusr1 = TRUE;
|
|
|
|
if (printer_dd) {
|
|
/* For serial printers, flush the data and quit. */
|
|
if (isastream(fildes)) {
|
|
(void)ioctl(1,TCFLSH,TCIOFLUSH);
|
|
PIOEXIT(PIOO_USR1OK);
|
|
}
|
|
|
|
/* If Can't Print, Terminate */
|
|
if (off_msgdone || pout_msgdone || tout_msgdone || noslct_msgdone)
|
|
PIOEXIT(PIOO_USR1QUIT);
|
|
/* If Encounter Print Problem, Terminate */
|
|
term_on_error = TRUE;
|
|
}
|
|
|
|
if (*suffixfile != '\0') {
|
|
if ((suffile = fopen(suffixfile, "r")) == NULL) {
|
|
cnt = sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_FOPEN2),
|
|
SUFFLAG, suffixfile, errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_FOPEN2,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(SUFFLAGSTR);
|
|
(void)pmi_bldstrfrm(suffixfile);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf, cnt, "", 1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
while ((val2 = getc(suffile)) != EOF)
|
|
OUTC(val2);
|
|
}
|
|
|
|
FLUSH();
|
|
|
|
PIOEXIT(PIOO_USR1OK);
|
|
}
|
|
|
|
/*
|
|
*******************************************************************************
|
|
*******************************************************************************
|
|
** NAME: piogetmsg()
|
|
**
|
|
** DESCRIPTION: Replaces the NLgetamsg routine used in 3.1 code If the catalog
|
|
** is not found in the NLSPATH, it will look for a default in
|
|
** /usr/lib/lpd/pio/etc.
|
|
**
|
|
** ROUTINES
|
|
** CALLED: catopen() - gets catalog descriptor
|
|
**
|
|
** catgets() - gets message
|
|
** catclose - closes catalog
|
|
**
|
|
** PARAMETERS: catalog name, set number, message number
|
|
**
|
|
**
|
|
*******************************************************************************
|
|
*******************************************************************************
|
|
*/
|
|
static char *msgbuffer = NULL;
|
|
static nl_catd catd;
|
|
static nl_catd def_catd;
|
|
static char save_name[100];
|
|
|
|
char *piogetmsg(CatName, set, num)
|
|
char *CatName;
|
|
int set;
|
|
int num;
|
|
{
|
|
char *ptr;
|
|
char *nlspath;
|
|
char *defpath = malloc(200);
|
|
char default_msg[100];
|
|
|
|
if (strcmp(CatName,save_name) != 0) /* is it a different catalog */
|
|
{
|
|
catclose(catd); /* close /usr/lpp message catalog */
|
|
catclose(def_catd); /* close default message catalog */
|
|
catd = def_catd = (nl_catd)NULL; /* set catalog descriptors to NULL */
|
|
strcpy(save_name,CatName);
|
|
}
|
|
|
|
if (catd != -1)
|
|
if (catd == 0) /* if it hasn't been open before */
|
|
catd = catopen(CatName,NL_CAT_LOCALE);
|
|
|
|
if (catd != -1)
|
|
{
|
|
ptr = catgets(catd,set,num,"dummy");
|
|
if (!msgbuffer)
|
|
msgbuffer = malloc(4001);
|
|
if (msgbuffer)
|
|
strncpy(msgbuffer, ptr, 4000);
|
|
if (strcmp(ptr,"dummy") != 0) /* did catgets fail? */
|
|
return(msgbuffer);
|
|
}
|
|
|
|
if (def_catd == 0)
|
|
{
|
|
sprintf(defpath,"/usr/lib/lpd/pio/etc/%s",CatName);
|
|
def_catd = catopen(defpath,NL_CAT_LOCALE);
|
|
}
|
|
|
|
sprintf(default_msg,"Cannot access message catalog %s.\n",CatName);
|
|
ptr = catgets(def_catd,set,num, default_msg);
|
|
if (!msgbuffer)
|
|
msgbuffer = malloc(4001);
|
|
if (msgbuffer)
|
|
strncpy(msgbuffer, ptr, 4000);
|
|
|
|
free(defpath);
|
|
return(msgbuffer);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* FUNCTIONS TO SUPPORT ASCII TERMINAL ATTACHED PRINTERS
|
|
********************************************************************************
|
|
*/
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* NAME: transp_init
|
|
*
|
|
* DESCRIPTION: Initialization routine for terminal connected printers.
|
|
* 1. Get tty device name.
|
|
* 2. Get device driver attributes from environment, if any
|
|
* 3. Get terminal printer access cmds from terminfo DB
|
|
* 4. Get hardware discipline based on asynchronous adapter type.
|
|
* 5. Populate TPF_cmds struct
|
|
* 6. Setup signal handlers
|
|
*
|
|
* PARAMETERS: NONE
|
|
*
|
|
* GLOBALS:
|
|
* MODIFIED: ttydevname, dev_attrtab, stpt, stptl, endpt, endptl
|
|
*
|
|
* RETURN VALUES:
|
|
*
|
|
********************************************************************************
|
|
*/
|
|
void
|
|
transp_init(void)
|
|
{
|
|
struct str_list strlst;
|
|
char *termtype; /* stores termname found in PIOTERM or TTY ODM */
|
|
char *tmp;
|
|
char *p;
|
|
char *sp, *ep;
|
|
int stat;
|
|
int i;
|
|
int cnt;
|
|
|
|
# ifdef DEBUG
|
|
dbg_fp = fopen("/dev/console","w");
|
|
(void)setvbuf(dbg_fp,NULL,_IONBF,0);
|
|
# endif /* DEBUG */
|
|
|
|
/* Get TTY device name */
|
|
if (ioctl(1,TXTTYNAME, ttydevname) == -1) {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,1,MSG_IOCTL),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_IOCTL,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
|
|
/* if multiplexed, remove channel indicator */
|
|
if ((tmp = strrchr(ttydevname,'/')) != NULL)
|
|
strcpy(tmp,"\0");
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"TXTTYNAME: ttydevname = %s\n",ttydevname);
|
|
# endif /* DEBUG */
|
|
|
|
/* Get device driver attributes from environment, if any
|
|
then load device driver attribute table.
|
|
*/
|
|
bzero(dev_attrtab,sizeof(dev_attrtab));
|
|
if ((tmp = getenv("PIOASCII_ATTR")) != NULL) {
|
|
i=0;
|
|
while ((i < ATTR_TAB_SZ) && ((p = strtok(tmp,":")) != NULL)) {
|
|
if (strcmp(p,"<na>") == 0) { /* null attribute accepted */
|
|
tmp = NULL;
|
|
i++;
|
|
continue;
|
|
}
|
|
if ((tmp = malloc(strlen(p)+1)) != NULL) {
|
|
strcpy(tmp,p);
|
|
dev_attrtab[i] = tmp; /* load table */
|
|
}
|
|
tmp = NULL;
|
|
i++;
|
|
}
|
|
}
|
|
# ifdef DEBUG
|
|
for (i = 0; i < ATTR_TAB_SZ; i++)
|
|
(void)fprintf(dbg_fp,"PIOASCII_ATTR: dev_attrtab[%d] = %s\n",
|
|
i,dev_attrtab[i]);
|
|
# endif /* DEBUG */
|
|
|
|
/* Get terminal type.
|
|
1. Check PIOTERM environment variable.
|
|
2. Check tty description file.
|
|
*/
|
|
termtype = NULL;
|
|
if ((termtype = getenv("PIOTERM")) == (char *)NULL) {
|
|
/* raise to program's privilege */
|
|
seteuid(programs_uid);
|
|
if ((outty = getttynam(ttydevname)) != NULL)
|
|
termtype = outty->ty_type;
|
|
/* lower to invoker's privilege */
|
|
seteuid(invokers_uid);
|
|
}
|
|
if (termtype == (char *) NULL) {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,TP_MSET,TP_UNKNOWN_TERM));
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
TP_UNKNOWN_TERM,TP_MSET,MF_PIOBE);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"getttynam: termtype = %s\n",termtype);
|
|
# endif /* DEBUG */
|
|
|
|
/* Read in terminfo entry for terminal */
|
|
setupterm(termtype,1,&stat);
|
|
if (stat != 1) {
|
|
cnt=sprintf(msgbuf,piogetmsg(MF_PIOBE,TP_MSET,TP_TERMINFO1),termtype);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
TP_TERMINFO1,TP_MSET,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(termtype);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
|
|
/* Get start passthru command from terminfo database */
|
|
if ((sp = tparm(prtr_on)) != NULL) {
|
|
strcpy(stpt,sp);
|
|
stptl = strlen(stpt);
|
|
} else {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,TP_MSET,TP_TERMINFO2),"mc5",termtype);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
TP_TERMINFO2,TP_MSET,MF_PIOBE);
|
|
(void)pmi_bldstrfrm("mc5");
|
|
(void)pmi_bldstrfrm(termtype);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"tparm: prtr_on = %s\n",stpt);
|
|
# endif /* DEBUG */
|
|
|
|
/* Get stop passthru command from terminfo database */
|
|
if ((ep = tparm(prtr_off)) != NULL) {
|
|
strcpy(endpt,ep);
|
|
endptl = strlen(endpt);
|
|
} else {
|
|
cnt=sprintf(msgbuf,piogetmsg(MF_PIOBE,TP_MSET,TP_TERMINFO2),"mc4",termtype);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
TP_TERMINFO2,TP_MSET,MF_PIOBE);
|
|
(void)pmi_bldstrfrm("mc4");
|
|
(void)pmi_bldstrfrm(termtype);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"tparm: prtr_off = %s\n",endpt);
|
|
# endif /* DEBUG */
|
|
|
|
/* Determine Hardware Discipline */
|
|
if ((strlst.sl_nmods = ioctl(1,I_LIST,NULL)) == -1 || !strlst.sl_nmods)
|
|
{
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,1,MSG_IOCTL),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_IOCTL,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
MALLOC(strlst.sl_modlist,strlst.sl_nmods*sizeof(*strlst.sl_modlist));
|
|
if ((i = ioctl(1,I_LIST,&strlst)) == -1 || !i) {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,1,MSG_IOCTL),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_IOCTL,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
# ifdef DEBUG
|
|
for (i = 0; i < strlst.sl_nmods; i++)
|
|
(void)fprintf(dbg_fp,"I_LIST: strlst.sl_modlist[%d].l_name = %s\n",
|
|
i,strlst.sl_modlist[i].l_name);
|
|
# endif /* DEBUG */
|
|
|
|
/* Check tty harware discipline against queue setup */
|
|
if ((dev_attrtab[0] == NULL) ||
|
|
(strcmp(dev_attrtab[0],
|
|
(strlst.sl_modlist+strlst.sl_nmods-1)->l_name) != 0))
|
|
{ /* TTY hardware discipline error */
|
|
cnt = sprintf(msgbuf, piogetmsg(MF_PIOBE, TP_MSET, TP_BADHD), ttydevname, dev_attrtab[0]);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
TP_BADHD,TP_MSET,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(ttydevname);
|
|
(void)pmi_bldstrfrm(dev_attrtab[0]);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
|
|
/* Get adapter specific routines */
|
|
if ((TPF = lookup_TPF_cmds(
|
|
(strlst.sl_modlist+strlst.sl_nmods-1)->l_name)) != NULL) {
|
|
(*TPF->setup)(); /* Execute setup routine */
|
|
} else {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,TP_MSET,TP_UNKNOWN_ASYNC));
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
TP_UNKNOWN_ASYNC,TP_MSET,MF_PIOBE);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
|
|
/* Setup signal handlers */
|
|
action.sa_handler = SIG_IGN;
|
|
sigaction(SIGTTIN, &action, NULL);
|
|
sigaction(SIGTTOU, &action, NULL);
|
|
signal(SIGHUP, sigterm_exit);
|
|
|
|
}
|
|
/*******************************************************************************
|
|
*
|
|
* NAME: rs_setup
|
|
*
|
|
* DESCRIPTION: Transparent Printing setup routine for native, 8, and 16-port
|
|
* adapters.
|
|
*
|
|
* PARAMETERS: NONE
|
|
*
|
|
* GLOBALS:
|
|
* MODIFIED: burst_size, delay
|
|
*
|
|
* RETURN VALUES:
|
|
*
|
|
********************************************************************************
|
|
*/
|
|
void
|
|
rs_setup(void)
|
|
{
|
|
int i;
|
|
|
|
/* Check for user defined buffer size */
|
|
if ((i = atoi(dev_attrtab[RS_BUFSIZ])) > 0)
|
|
burst_size = i;
|
|
else
|
|
burst_size = DFLT_RS_BUFSIZ; /* if not in environment, use default */
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"rs_setup: burst_size = %d\n",burst_size);
|
|
# endif /* DEBUG */
|
|
|
|
/* Check for user defined delay value */
|
|
if ((i = atoi(dev_attrtab[RS_DELAY])) > 0)
|
|
delay = i;
|
|
else
|
|
delay = DFLT_RS_DELAY; /* if not in environment, use default */
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"rs_setup: delay = %d\n",delay);
|
|
# endif /* DEBUG */
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* NAME: rs_print
|
|
*
|
|
* DESCRIPTION: Transparent Printing routine for native, 8, and 16-port
|
|
* adapters.
|
|
*
|
|
* PARAMETERS: NONE
|
|
*
|
|
* GLOBALS:
|
|
* MODIFIED: len_done, nextp, backtty
|
|
*
|
|
* RETURN VALUES:
|
|
*
|
|
********************************************************************************
|
|
*/
|
|
void
|
|
rs_print(void)
|
|
{
|
|
int bytes_read, bytes_sent, bytes_to_send, cnt;
|
|
int fullpipecnt = 0;
|
|
char *sendp;
|
|
char *buf;
|
|
char *bufinp;
|
|
int saverrno;
|
|
|
|
sendp = outbuf;
|
|
backtty=FALSE;
|
|
MALLOC(buf, burst_size+stptl+endptl); /* Allocate space for temp out buffer */
|
|
memcpy(buf, stpt, stptl); /* Copy start passthru command in buf */
|
|
bufinp=buf+stptl; /* Point just beyond the start passthru command */
|
|
while ((bytes_to_send = nextp - sendp) > 0) {
|
|
|
|
/* Copy print data to temp buffer */
|
|
memcpy(bufinp, sendp, bytes_read = ((bytes_to_send > burst_size) ? burst_size : bytes_to_send));
|
|
|
|
/* Tag data with end passthru command */
|
|
memcpy(bufinp+bytes_read, endpt, endptl);
|
|
|
|
/* Get ttymode of output (Foreground) */
|
|
if (tcgetattr(fildes, &fore) == -1) {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,1,MSG_IOCTL),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_IOCTL,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"tcgetattr: fore.c_oflag = %d\n",
|
|
fore.c_oflag);
|
|
# endif /* DEBUG */
|
|
|
|
back = fore;
|
|
back.c_oflag = 0x0; /* Turn off output processing */
|
|
|
|
/* Set ttymode of output (Background) */
|
|
if (tcsetattr(fildes, TCSANOW, &back) == -1) {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,1,MSG_IOCTL),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_IOCTL,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
backtty=TRUE;
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"tcsetattr: back.c_oflag = %d\n",
|
|
back.c_oflag);
|
|
# endif /* DEBUG */
|
|
|
|
/* Send data to printer */
|
|
bytes_sent = write(fildes, buf, bytes_read+stptl+endptl);
|
|
saverrno = errno;
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"write: bytes_sent = %d; saverrno = %d\n",
|
|
bytes_sent,saverrno);
|
|
# endif /* DEBUG */
|
|
|
|
/* Set ttymode of output (Foreground) */
|
|
if (tcsetattr(fildes, TCSANOW, &fore) == -1) {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,1,MSG_IOCTL),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_IOCTL,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
backtty=FALSE;
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"tcsetattr: fore.c_oflag = %d\n",
|
|
fore.c_oflag);
|
|
# endif /* DEBUG */
|
|
|
|
|
|
if (bytes_sent < 0) {
|
|
if (term_on_error)
|
|
if (sigterm)
|
|
PIOEXIT(PIOO_TERMQUIT) /* no semicolon */
|
|
else if (sigusr1)
|
|
PIOEXIT(PIOO_USR1QUIT);
|
|
|
|
if (saverrno == EINTR)
|
|
(void) sigterm_exit(SIGTERM);
|
|
cnt = sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_WRITE), DEVNAME, saverrno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_WRITE,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(saverrno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
} else if (bytes_sent == 0 && sigterm) {
|
|
/* if pipe is full and SIGTERM has been received */
|
|
if (++fullpipecnt > 5) /* if threshold exceeded */
|
|
PIOEXIT(PIOO_TERMQUIT); /* give up */
|
|
sleep(1);
|
|
continue;
|
|
}
|
|
fullpipecnt = 0;
|
|
sendp += bytes_read;
|
|
/* Update Percentage Status */
|
|
len_done += bytes_sent;
|
|
if (statusfile && len_total != 0 && len_done > len_done_orig) {
|
|
cnt = (len_done * 100) / len_total;
|
|
if (cnt > 100)
|
|
cnt = 100;
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
if (log_init() >= 0)
|
|
(void) log_percent(cnt);
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
}
|
|
|
|
/* Pause between data packets */
|
|
usleep((unsigned int) delay);
|
|
}
|
|
|
|
nextp = outbuf; /* now have empty buffer */
|
|
free(buf);
|
|
|
|
}
|
|
/******************************************************************
|
|
*
|
|
* NAME: rs_cleanup
|
|
*
|
|
* DESCRIPTION: Function to restore previous state of native, 8, 16-port
|
|
* driver.
|
|
*
|
|
* PARAMETERS: NONE
|
|
*
|
|
* GLOBALS:
|
|
* MODIFIED:
|
|
*
|
|
* RETURN VALUES:
|
|
*
|
|
*******************************************************************
|
|
*/
|
|
void
|
|
rs_cleanup()
|
|
{
|
|
/* Restore Terminal (If necessary) */
|
|
if (backtty) {
|
|
(void) tcsetattr(fildes, TCSANOW, &fore);
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"rs_cleanup-tcsetattr:fore.c_oflag = %d\n",
|
|
fore.c_oflag);
|
|
# endif /* DEBUG */
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* NAME: lion_setup
|
|
*
|
|
* DESCRIPTION: Transparent Printing setup routine for 64-port adapter.
|
|
*
|
|
* PARAMETERS: NONE
|
|
*
|
|
* GLOBALS:
|
|
* MODIFIED:
|
|
*
|
|
* RETURN VALUES:
|
|
*
|
|
********************************************************************************
|
|
*/
|
|
void
|
|
lion_setup(void)
|
|
{
|
|
char lionfname[80];
|
|
struct xpar_parms xpar;
|
|
int i;
|
|
int cnt;
|
|
|
|
|
|
/* Get current device driver settings */
|
|
if (ioctl(1, LI_GETXP, &xpar)) {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,1,MSG_IOCTL),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_IOCTL,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
|
|
/* Set Start Passthru */
|
|
memset(xpar.in_xpar, 0xff, sizeof(xpar.in_xpar));
|
|
memcpy(xpar.in_xpar, stpt, stptl);
|
|
|
|
/* Set End Passthru */
|
|
memset(xpar.lv_xpar, 0xff, sizeof(xpar.lv_xpar));
|
|
memcpy(xpar.lv_xpar, endpt, endptl);
|
|
|
|
/* Set Priority */
|
|
if (((i = atoi(dev_attrtab[LION_PRIORITY])) > 0) && (i <= 60))
|
|
xpar.priority = i;
|
|
else
|
|
xpar.priority = DFLT_LION_PRIORITY;
|
|
|
|
/* Make settings known to 64-port adapter */
|
|
if (ioctl(1, LI_SETXP, &xpar)) {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,1,MSG_IOCTL),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_IOCTL,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
|
|
/* Construct transparent printer device name */
|
|
sprintf(lionfname,"/dev/x%s", ttydevname);
|
|
|
|
/* Open file on transparent printer channel */
|
|
if ((fildes = open(lionfname, O_WRONLY)) == -1) {
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"open: %s FAILED! errno = %d\n",lionfname,errno);
|
|
# endif /* DEBUG */
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,TP_MSET,TP_FOPEN1),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
TP_FOPEN1,TP_MSET,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"open: lionfname = %s\n",lionfname);
|
|
# endif /* DEBUG */
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* NAME: lion_print
|
|
*
|
|
* DESCRIPTION: Transparent Printing routine for 64-port adapter.
|
|
*
|
|
* PARAMETERS: NONE
|
|
*
|
|
* GLOBALS:
|
|
* MODIFIED: len_done, nextp
|
|
*
|
|
*
|
|
* RETURN VALUES:
|
|
*
|
|
*
|
|
*
|
|
********************************************************************************
|
|
*/
|
|
void
|
|
lion_print(void)
|
|
{
|
|
int bytes_read, bytes_sent, bytes_to_send, cnt;
|
|
int fullpipecnt = 0;
|
|
char *sendp;
|
|
|
|
sendp = outbuf;
|
|
while ((bytes_to_send = nextp - sendp) > 0) {
|
|
|
|
/* Write buffer to output */
|
|
errno = 0;
|
|
bytes_sent = write(fildes, sendp, bytes_to_send);
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"write: bytes_sent = %d; errno = %d\n",
|
|
bytes_sent,errno);
|
|
# endif /* DEBUG */
|
|
|
|
if (bytes_sent < 0) {
|
|
if (term_on_error)
|
|
if (sigterm)
|
|
PIOEXIT(PIOO_TERMQUIT) /* no semicolon */
|
|
else if (sigusr1)
|
|
PIOEXIT(PIOO_USR1QUIT);
|
|
|
|
if (errno == EINTR)
|
|
(void) sigterm_exit(SIGTERM);
|
|
cnt = sprintf(msgbuf,
|
|
piogetmsg(MF_PIOBE, 1, MSG_WRITE), DEVNAME, errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_WRITE,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
} else if (bytes_sent == 0 && sigterm) {
|
|
/* if pipe is full and SIGTERM has been received */
|
|
if (++fullpipecnt > 5) /* if threshold exceeded */
|
|
PIOEXIT(PIOO_TERMQUIT); /* give up */
|
|
sleep(1);
|
|
continue;
|
|
}
|
|
fullpipecnt = 0;
|
|
sendp += bytes_sent;
|
|
/* Update Percentage Status */
|
|
len_done += bytes_sent;
|
|
if (statusfile && len_total != 0 && len_done > len_done_orig) {
|
|
cnt = (len_done * 100) / len_total;
|
|
if (cnt > 100)
|
|
cnt = 100;
|
|
lockdat.l_type = F_WRLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
if (log_init() >= 0)
|
|
(void) log_percent(cnt);
|
|
lockdat.l_type = F_UNLCK;
|
|
(void) fcntl(3, F_SETLKW, &lockdat);
|
|
}
|
|
}
|
|
|
|
nextp = outbuf; /* now have empty buffer */
|
|
}
|
|
|
|
/******************************************************************
|
|
*
|
|
* NAME: lion_cleanup
|
|
*
|
|
* DESCRIPTION: Function to restore previous state of 64-Port device
|
|
* driver.
|
|
*
|
|
* PARAMETERS: NONE
|
|
*
|
|
* GLOBALS:
|
|
* MODIFIED:
|
|
*
|
|
* RETURN VALUES:
|
|
*
|
|
*******************************************************************
|
|
*/
|
|
void
|
|
lion_cleanup(void)
|
|
{
|
|
close(fildes); /* Turn off transparent print dev. */
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"lion_cleanup: fildes closed\n");
|
|
# endif /* DEBUG */
|
|
}
|
|
/******************************************************************
|
|
*
|
|
* NAME: cxma_setup
|
|
*
|
|
* DESCRIPTION: Function to setup 128-Port device driver paramters
|
|
* for transparent printing.
|
|
*
|
|
* PARAMETERS: NONE
|
|
*
|
|
* GLOBALS:
|
|
* MODIFIED:
|
|
*
|
|
* RETURN VALUES:
|
|
*
|
|
*******************************************************************
|
|
*/
|
|
void
|
|
cxma_setup(void)
|
|
{
|
|
char ttyname[30];
|
|
struct stat fstat;
|
|
cxma_t xpar; /* ioctl structure */
|
|
int i;
|
|
int cnt;
|
|
|
|
/* Get current settings */
|
|
if (ioctl(1, CXMA_GETA, &xpar)) {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,1,MSG_IOCTL),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_IOCTL,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
|
|
/* Set start passthrough command and length */
|
|
memcpy(xpar.cxma_onstr, stpt, stptl);
|
|
xpar.cxma_onlen = (unsigned char) stptl;
|
|
|
|
/* Set end passthrough command and length */
|
|
memcpy(xpar.cxma_offstr, endpt, endptl);
|
|
xpar.cxma_offlen = (unsigned char) endptl;
|
|
|
|
/* Set MAXCPS */
|
|
if ((i = atoi(dev_attrtab[CXMA_MAXCPS])) > 0)
|
|
xpar.cxma_maxcps = (unsigned short) i;
|
|
else
|
|
xpar.cxma_maxcps = DFLT_CXMA_MAXCPS;
|
|
|
|
/* Set MAXCHAR */
|
|
if ((i = atoi(dev_attrtab[CXMA_MAXCHAR])) > 0)
|
|
xpar.cxma_maxchar = (unsigned short) i;
|
|
else
|
|
xpar.cxma_maxchar = DFLT_CXMA_MAXCHAR;
|
|
|
|
/* Set BUFSIZE */
|
|
if ((i = atoi(dev_attrtab[CXMA_BUFSIZ])) > 0)
|
|
xpar.cxma_bufsize = (unsigned short) i;
|
|
else
|
|
xpar.cxma_bufsize = DFLT_CXMA_BUFSIZ;
|
|
|
|
/* Make settings known to 128-port adapter */
|
|
if (ioctl(1, CXMA_SETA, &xpar)) {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,1,MSG_IOCTL),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_IOCTL,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
|
|
/* Get terminal device status */
|
|
sprintf(ttyname, "/dev/%s", ttydevname);
|
|
if (statx(ttyname, &fstat, STATXSIZE, STX_NORMAL) != 0) {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,1,MSG_STAT2),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
MSG_STAT2,1,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"statx: ttyname = %s\n",ttyname);
|
|
# endif /* DEBUG */
|
|
|
|
/* Construct transparent printer device name */
|
|
sprintf(cxmadevname, "%s/dev/%s", defbasedir, ttydevname);
|
|
|
|
/* Create transparent print device */
|
|
seteuid(programs_uid);
|
|
unlink(cxmadevname);
|
|
i = mknod(cxmadevname, S_IFCHR|S_IRWXU, fstat.st_rdev + CXMA_DEV) ||
|
|
chown(cxmadevname, invokers_uid, -1);
|
|
seteuid(invokers_uid);
|
|
if (i) {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,TP_MSET,TP_FOPEN1),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
TP_FOPEN1,TP_MSET,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"mknod: cxmadevname = %s\n",cxmadevname);
|
|
# endif /* DEBUG */
|
|
|
|
/* Open transparent printer device */
|
|
if ((fildes = open(cxmadevname, O_WRONLY)) == -1) {
|
|
cnt = sprintf(msgbuf,piogetmsg(MF_PIOBE,TP_MSET,TP_FOPEN1),DEVNAME,errno);
|
|
if (piomsgipc) { /* if message is to be sent via ipc */
|
|
(void)pmi_bldhdrfrm(
|
|
ID_VAL_EVENT_ABORTED_BY_SERVER,
|
|
TP_FOPEN1,TP_MSET,MF_PIOBE);
|
|
(void)pmi_bldstrfrm(DEVNAME);
|
|
(void)pmi_bldintfrm(errno);
|
|
}
|
|
piomsgout(msgbuf,cnt,"",1);
|
|
PIOEXIT(PIOO_FAIL);
|
|
}
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"open: cxmadevname = %s\n",cxmadevname);
|
|
# endif /* DEBUG */
|
|
|
|
}
|
|
|
|
/******************************************************************
|
|
*
|
|
* NAME: cxma_print
|
|
*
|
|
* DESCRIPTION: Function to send output to 128-Port device driver
|
|
* for transparent printing.
|
|
*
|
|
* PARAMETERS: NONE
|
|
*
|
|
* GLOBALS:
|
|
* MODIFIED:
|
|
*
|
|
* RETURN VALUES:
|
|
*
|
|
*******************************************************************
|
|
*/
|
|
void
|
|
cxma_print(void)
|
|
{
|
|
lion_print(); /* same operation as 64-port */
|
|
}
|
|
|
|
/******************************************************************
|
|
*
|
|
* NAME: cxma_cleanup
|
|
*
|
|
* DESCRIPTION: Function to restore previous state of 128-Port device
|
|
* driver.
|
|
*
|
|
* PARAMETERS: NONE
|
|
*
|
|
* GLOBALS:
|
|
* MODIFIED:
|
|
*
|
|
* RETURN VALUES:
|
|
*
|
|
*******************************************************************
|
|
*/
|
|
void
|
|
cxma_cleanup(void)
|
|
{
|
|
|
|
close(fildes);
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"cxma_cleanup: %s closed\n",cxmadevname);
|
|
# endif /* DEBUG */
|
|
unlink(cxmadevname);
|
|
# ifdef DEBUG
|
|
(void)fprintf(dbg_fp,"cxma_cleanup: %s unlinked\n",cxmadevname);
|
|
# endif /* DEBUG */
|
|
}
|
|
/*******************************************************************************
|
|
*
|
|
* NAME: lookup_TPF_cmds
|
|
*
|
|
* DESCRIPTION: Function to search Transparent Printing Function Table
|
|
* for entry based on the hardware discipline.
|
|
*
|
|
* PARAMETERS: name - hardware discipline name;
|
|
*
|
|
* GLOBALS:
|
|
* MODIFIED:
|
|
*
|
|
*
|
|
* RETURN VALUES: Pointer to TPF_cmds structure
|
|
*
|
|
*
|
|
*
|
|
********************************************************************************
|
|
*/
|
|
struct TPF_cmds *lookup_TPF_cmds(register char *name)
|
|
{
|
|
register int lo = 0, hi = TPF_CMDS - 2;
|
|
register int mid;
|
|
register struct TPF_cmds *p;
|
|
|
|
if (name == (char *) NULL)
|
|
return ((struct TPF_cmds *)NULL);
|
|
while (lo <= hi) {
|
|
if (strcmp(name, (p = TPF_cmds_tab + (mid = (lo + hi) >> 1))->hard_disp) <= 0)
|
|
hi = mid - 1;
|
|
else
|
|
lo = mid + 1;
|
|
}
|
|
p = TPF_cmds_tab + lo;
|
|
if (strcmp(name,p->hard_disp) == 0)
|
|
return(p);
|
|
else
|
|
return(NULL);
|
|
}
|