lp.tell.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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
* or http://www.opensolaris.org/os/licensing.
* 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 1997 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.6 */
#include "signal.h"
#include "stdio.h"
#include "errno.h"
#include "lp.h"
#include "msgs.h"
#include "string.h"
void startup(),
cleanup(),
done();
extern char *getenv(),
*malloc(),
*realloc();
extern long atol();
extern int atoi();
static void wakeup();
extern char *optarg;
extern int optind, opterr, optopt;
int optsw;
#define PREFIX_STRING "%%["
#define SUFFIX_STRING "]%%"
#define PRINTER_ERROR_STRING "PrinterError:"
#define STATUS_STRING "status:"
#define JOB_STRING "job:"
#define STATUS_OK_STRING "ready and printing"
#define PAPER_CHANGED_STRING "paper changed:"
/*
* Some common postscript printer fault messages.
* These strings are here so that they get l10ned and then lpstat will
* be able to display them in the users language.
* This seemed like a good place for them, since lp.tell knows about
* postscript msgs.
*/
char *ps_m1 = "unable to print: out of media (paper)";
char *ps_m2 = "out of media (paper)";
char *ps_m3 = "unable to print: tray not (properly) installed";
char *ps_m4 = "tray not (properly) installed";
char *ps_m5 = "unable to print: paper out for the selected tray";
char *ps_m6 = "paper out for the selected tray";
char *ps_m7 = "unable to print: cartridge life expiring";
char *ps_m8 = "cartridge life expiring";
char *ps_m9 = "unable to print: printer cover not locked";
char *ps_m10 = "printer cover not locked";
char *ps_m11 = "unable to print: media (paper) jam in exit path";
char *ps_m12 = "media (paper) jam in exit path";
char *ps_m13 = "unable to print: media (paper) jam in feed path";
char *ps_m14 = "media (paper) jam in feed path";
char *ps_m15 = "unable to print: drum assembly almost expended";
char *ps_m16 = "drum assembly almost expended";
char *ps_m17 = "unable to print: toner cartridge almost expended";
char *ps_m18 = "toner cartridge almost expended";
char *ps_m19 = "unable to print: drum assembly not (properly) installed";
char *ps_m20 = "drum assembly not (properly) installed";
char *ps_m21 = "unable to print: toner cartridge not (properly) installed";
char *ps_m22 = "toner cartridge not (properly) installed";
char *ps_m23 = "unable to print: drum assembly requires replacement";
char *ps_m24 = "drum assembly requires replacement";
char *ps_m25 = "unable to print: toner cartridge requires replacement";
char *ps_m26 = "toner cartridge requires replacement";
char *ps_m27 = "unable to print: fuser warming up";
char *ps_m28 = "fuser warming up";
char *ps_m29 = "unable to print: printer not responding";
char *ps_m30 = "printer not responding";
char *ps_m31 = "unable to print: fuser pausing";
char *ps_m32 = "fuser pausing";
char *ps_m33 = "unable to print: printer turned off";
char *ps_m34 = "printer turned off";
char *ps_m35 = "unable to print: printer warming up";
char *ps_m36 = "printer warming up";
char *ps_m37 = "unable to print: interlock open";
char *ps_m38 = "interlock open";
char *ps_m39 = "unable to print: selected tray out";
char *ps_m40 = "selected tray out";
char *ps_m41 = "unable to print: paper out for the manual tray";
char *ps_m42 = "paper out for the manual tray";
char *ps_m43 = "unable to print: paper exit jam";
char *ps_m44 = "paper exit jam";
char *ps_m45 = "unable to print: paper misfeed jam";
char *ps_m46 = "paper misfeed jam";
char *ps_m47 = "unable to print: paper jam between registration & heat rollers";
char *ps_m48 = "paper jam between registration & heat rollers";
char *ps_m49 = "unable to print: paper jam at registration roller";
char *ps_m50 = "paper jam at registration roller";
char *ps_m51 = "unable to print: no cartridge";
char *ps_m52 = "no cartridge";
char *ps_m53 = "unable to print: cartridge out";
char *ps_m54 = "cartridge out";
/**
** main()
**/
int main (argc, argv)
int argc;
char *argv[];
{
char *alert_text,
buf[BUFSIZ],
msgbuf[MSGMAX],
*bufPtr,
*printer,
*s_key;
char *printerErrorString = NULL;
char *statusString = NULL;
char *paperChangedString = NULL;
char *suffixString = NULL;
char *jobString = NULL;
char *prefixString = NULL;
char *statusOkString = NULL;
int mtype,
doStdOut,
doDebug,
first,
oldalarm;
short status;
long key,clearKey;
char *ptr1,*ptr2,*ptr3,*ptr4,*ptr5;
int trayNum = 0;
int mode = 0;
int pagesPrinted = 0;
char *paperType = NULL;
short mesgRetType;
int useLaserWriterMessages;
int pLen,sLen,peLen,jLen,pcLen ;
void (*oldsignal)();
/*
* Run immune from typical interruptions, so that
* we stand a chance to get the fault message.
* EOF (or startup error) is the only way out.
*/
signal (SIGHUP, SIG_IGN);
signal (SIGINT, SIG_IGN);
signal (SIGQUIT, SIG_IGN);
signal (SIGTERM, SIG_IGN);
/*
* Do we have a key?
*/
if (
argc < 2
|| !(s_key = getenv("SPOOLER_KEY"))
|| !*s_key
|| (key = atol(s_key)) <= 0
) {
printf( "Usage: lptell [-lodk] [-X String] printer\n");
printf("Options (where X is P,S,e,s, O or c )\n");
printf(" environment variable SPOOLER_KEY: must be defined and > 0\n");
printf(" printer: name of printer to give status for.\n");
printf(" -l: expect laser writer type messages (NeWSprint does)\n");
printf(" -o: send input to stdout\n");
printf(" -d: send additional debugging output to stdout\n");
printf(" -P String: string for prefix, default: '%%%%['\n");
printf(" -S String: string for suffix, default: ']%%%%'\n");
printf(" -e String: string to detect printer error,\n");
printf(" default: 'PrinterError:', send S_SEND_FAULT to lpsched\n");
printf(
" -c String: string to detect paper change in context of printer error,\n");
printf(" default: 'paper changed:', send S_PAPER_CHANGED to lpsched\n");
printf(" -s String: string to detect printer ok status, \n");
printf(" default: 'status:', send S_CLEAR_FAULT to lpsched\n");
printf(" -k: do not use the key for making status ok\n");
printf(" -O String: string sent as status message to lpsched,\n");
printf(" default: 'ready and printing:'\n");
exit (90);
}
doStdOut = 0;
doDebug = 0;
useLaserWriterMessages = 0;
clearKey = key;
prefixString = PREFIX_STRING; pLen = strlen(prefixString);
suffixString = SUFFIX_STRING;
printerErrorString = PRINTER_ERROR_STRING;
peLen = strlen(printerErrorString);
statusString = STATUS_STRING; sLen = strlen(statusString);
jobString = JOB_STRING; jLen = strlen(jobString);
paperChangedString = PAPER_CHANGED_STRING;
pcLen = strlen(paperChangedString);
statusOkString = STATUS_OK_STRING;
while ((optsw = getopt(argc, argv, "le:s:c:okdO:S:P:")) != EOF) {
switch ( optsw ) {
case 'l':
useLaserWriterMessages = 1;
break;
case 'P':
prefixString = (optarg ? strdup(optarg) : NULL);
pLen = strlen(prefixString );
break;
case 'S':
suffixString = (optarg ? strdup(optarg) : NULL);
break;
case 'e':
printerErrorString = (optarg ? strdup(optarg) : NULL);
peLen = strlen(printerErrorString);
break;
case 's':
statusString = (optarg ? strdup(optarg) : NULL);
sLen = strlen(statusString);
break;
case 'O':
statusOkString = (optarg ? strdup(optarg) : NULL);
break;
case 'c':
paperChangedString = (optarg ? strdup(optarg) : NULL);
pcLen = strlen(paperChangedString );
break;
case 'k':
clearKey = -1;
break;
case 'o':
doStdOut = 1;
break;
case 'd':
doDebug = 1;
break;
}
}
/*
* Which printer is this? Do we have a key?
*/
if (
!(printer = argv[optind])
|| !*printer
) {
exit (90);
}
if (doDebug) {
printf( "start lp.tell for %s key %d mode %s %s\n",
printer,key,(useLaserWriterMessages ? "LW" : "standard"),
(doStdOut ? "doStdOut" : "no output"));
printf( "prefix (%s) suffix (%s) printerError (%s)\n",
prefixString,suffixString,printerErrorString);
printf( "paper_changed (%s) status (%s) key %d \n",
paperChangedString,statusString , clearKey);
fflush(stdout);
}
/*
* Wait for a message on the standard input. When a single line
* comes in, take a couple of more seconds to get any other lines
* that may be ready, then send them to the Spooler.
*/
while (fgets(buf, BUFSIZ, stdin)) {
if (useLaserWriterMessages) {
/* NeWSprint style processing (which simulates the LaserWriter
*There are four types of messages:
* 1) fault messages: printer error message from handler
* 2) clear fault messages: printer ok messages from handler
* 3) paper changed messages: printer handler detected paper change
* 4) server messages: xnews problems
*/
bufPtr = buf;
if (strncmp(prefixString, bufPtr, pLen) == 0) {
bufPtr += pLen;
while (*bufPtr == ' ')
bufPtr++;
if (strncmp(printerErrorString, bufPtr,
peLen) == 0) {
bufPtr += peLen;
while (*bufPtr == ' ')
bufPtr++;
if ((strncmp(bufPtr,paperChangedString,pcLen) == 0) &&
(ptr1 = bufPtr +pcLen) &&
(ptr2 = strchr(ptr1+1,':')) &&
(ptr3 = strchr(ptr2+1,':')) &&
(ptr4 = strchr(ptr3+1,':')) &&
(ptr5 = strchr(ptr4+1,'\n'))) {
if (doStdOut) printf("%s",buf);
*ptr2 =0;
*ptr3= 0;
*ptr4= 0;
*ptr5= 0;
trayNum = atoi(ptr1+1);
paperType = ptr2+1;
mode = atoi(ptr3+1);
pagesPrinted = atoi(ptr4+1);
if (doDebug) {
printf("Paper changed: %s tray %d paper %s md %d pages %d\n",
printer,trayNum,paperType,mode,pagesPrinted);
}
startup ();
mesgRetType = R_PAPER_CHANGED;
(void)putmessage ( msgbuf, S_PAPER_CHANGED, printer, trayNum,
paperType, mode, pagesPrinted);
} else {
if (doStdOut) printf("%s",buf);
if (ptr1 = strstr(bufPtr,suffixString)) *ptr1 = 0;
if ( doDebug ) {
printf("Send fault: %s key %d (%s)\n",printer,key,bufPtr);
}
mesgRetType = R_SEND_FAULT;
startup ();
(void)putmessage (msgbuf,S_SEND_FAULT,printer,key,bufPtr);
}
} else if ((first = (strncmp(statusString,bufPtr,sLen) == 0)) ||
(strncmp(jobString,bufPtr,jLen) == 0)) {
bufPtr += (first ? sLen : jLen);
if (doStdOut) printf("%s",buf);
if (ptr1 = strstr(bufPtr,suffixString)) *ptr1 = 0;
if ( doDebug ) {
printf("Clear fault: %s key %d (%s)\n",printer, clearKey,
bufPtr);
}
mesgRetType = R_CLEAR_FAULT;
startup ();
(void)putmessage( msgbuf,S_CLEAR_FAULT,printer,clearKey,
statusOkString);
} else {
if (doStdOut) printf("%s",buf);
if (ptr1 = strstr(bufPtr,suffixString)) *ptr1 = 0;
if ( doDebug ) {
printf("Server error: %s key %d (%s)\n",printer,key,
buf);
}
mesgRetType = 0;
}
} else {
if (doStdOut) printf("%s",buf);
if (ptr1 = strstr(bufPtr,suffixString))
*ptr1 = 0;
if (doDebug) {
printf("Server error: %s key %d (%s)\n",
printer, key, buf);
}
mesgRetType = 0;
}
} else { /* not generic PostScript style messages */
oldsignal = signal(SIGALRM, wakeup);
oldalarm = alarm(2);
alert_text = 0;
do {
if (alert_text)
alert_text = realloc(alert_text,
strlen(alert_text)+strlen(buf)+1
);
else {
alert_text = malloc(strlen(buf) + 1);
alert_text[0] = 0;
}
strcat (alert_text, buf);
} while (fgets(buf, BUFSIZ, stdin));
alarm (oldalarm);
signal (SIGALRM, oldsignal);
if (doStdOut) {
if ( doDebug ) {
printf("Send generic fault: %s key %d (%s)\n",printer,key,
alert_text);
}
else {
printf("%s\n",alert_text);
}
}
if (strcmp(alert_text, "printer ok\n") == 0) {
mesgRetType = R_CLEAR_FAULT;
startup ();
(void)putmessage(msgbuf, S_CLEAR_FAULT, printer,
clearKey, statusOkString);
} else {
mesgRetType = R_SEND_FAULT;
startup ();
(void)putmessage(msgbuf, S_SEND_FAULT, printer,
key, alert_text);
}
}
if (mesgRetType) {
if (msend(msgbuf) == -1)
done (91);
if (mrecv(msgbuf, sizeof(msgbuf)) == -1)
done (92);
mtype = getmessage(msgbuf, mesgRetType, &status);
/*
* check for R_CLEAR_FAULT here and 3 lines below
* because older lpsched doesn't pass S_CLEAR_FAULT
*/
if ((mtype != mesgRetType) &&
(mesgRetType != R_CLEAR_FAULT))
done (93);
if ((status != MOK) && (mesgRetType != R_CLEAR_FAULT))
done (94);
}
}
done (0);
}
/**
** startup() - OPEN MESSAGE QUEUE TO SPOOLER
** cleanup() - CLOSE THE MESSAGE QUEUE TO THE SPOOLER
**/
static int have_contacted_spooler = 0;
void startup ()
{
void catch();
/*
* Open a message queue to the Spooler.
* An error is deadly.
*/
if (!have_contacted_spooler) {
if (mopen() == -1) {
switch (errno) {
case ENOMEM:
case ENOSPC:
break;
default:
break;
}
exit (1);
}
have_contacted_spooler = 1;
}
return;
}
void cleanup ()
{
if (have_contacted_spooler)
mclose ();
return;
}
/**
** wakeup() - TRAP ALARM
**/
static void wakeup ()
{
return;
}
/**
** done() - CLEANUP AND EXIT
**/
void done (ec)
int ec;
{
cleanup ();
exit (ec);
}