/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <setjmp.h>
#include <string.h>
#include <stdlib.h>
#include <libintl.h>
#include "lp.h"
#include "msgs.h"
#include "printers.h"
#include "requests.h"
#include "form.h"
#include "oam.h"
#include "lpadmin.h"
extern void mount_unmount();
extern short printer_status;
extern char *cur_pwheel,
static int again();
static void disable(),
enable(),
accept(),
reject(),
cancel(),
sigpipe(),
sigother();
/**
** do_align() - SET UP PRINTER TO PRINT ALIGNMENT PATTERNS
**/
char *printer,
*form,
*pwheel;
{
short status;
char *req_id = 0,
*rfile,
*fifo,
long printer_chk;
int try;
*fifo_fp;
void (*old_sighup)(),
(*old_sigint)(),
(*old_sigquit)(),
(*old_sigterm)();
/*
* Having reached this point means we've already fetched
* the form definition. Now get the alignment pattern.
*/
done (1);
}
if (!align_fp) {
return (0);
}
/*
* Having reached this far also means we've already obtained
* the printer status from the Spooler. We'll be changing the
* status of the printer and queue and will have to restore
* NOTE: We can't restore the dates!
*/
/*
* Construct a request to print a ``file'' for copy. The
* equivalent "lp" command (with a filename) would be:
*
* lp -p printer -H immediate -f form -T type -S charset -c -P 1-N
*
* "type", "charset", and "N" are derived from the form def'n.
* This command would make us next to print ONCE THE FORM IS
* MOUNTED.
*
* NOTE: Don't bother with the -S charset if it isn't mandatory,
* so we won't get a rejection. Also, we use either the print
* wheel given in the -S option or, lacking that, the currently
* mounted print wheel. (The former WILL be mounted.) This also
* avoids a rejection by the Spooler.
*/
/* req.file_list = 0; This is done later. */
/*
* The following code is sensitive to interrupts: We must
* catch interrupts so to restore the printer to its original
* state, but if we get interrupted while receiving a message
* from the Spooler, we can't issue additional messages because
* the old responses still in the response queue will confuse us.
*/
if (setjmp(cleanup_env) != 0)
done (1);
trap_signals (); /* make sure we've done this once */
/*
* We'll try the following twice, first with the page list
* set as above. If the request gets refused because there's
* no filter to convert the content, we'll try again without
* the page list. I don't think the number-of-pages-in-a-form
* feature is likely to be used much, so why hassle the
* administrator?
#if defined(WARN_OF_TOO_MANY_LINES)
* However, do warn him or her.
#endif
*/
try = 0;
/*
* Have the Spooler allocate a request file and another file
* for our use. We'll delete the other file and recreate it
* as a FIFO. We can do this because "lpadmin" can only be run
* (successfully) by an administrator. This is the key to what
* we're doing! We are submitting a named pipe (FIFO) for
* printing, which gives us a connection to the printer
* through any filters needed!
*/
done (1);
}
switch (status) {
case MOK:
break;
case MNOMEM:
done (1);
}
done (1);
}
done (1);
}
if (
) {
done (1);
}
/*
* In quick succession,
*
* - mount the form,
* - disable the printer,
* - make the Spooler accept requests (if need be),
* - submit the request,
* - make the Spooler reject requests (if need be).
*
* We want to minimize the window when another request can
* be submitted ahead of ours. Though this window is small,
* it is a flaw in our design. Disabling the printer will
* help, because it will stop any request that is printing
* (if the form is already mounted) and will prevent any other
* request from printing. (We disable the printer AFTER trying
* to mount the form, because we don't disable a printer for a
* regular mount, and we'd like to make this mount APPEAR to
* be as similar as possible.)
*/
if (try == 1) {
/* This will die if the mount fails, leaving */
/* the Spooler to clean up our files. */
if (!(printer_status & PS_DISABLED))
if (printer_status & PS_REJECTED)
if (setjmp(cleanup_env) != 0) {
if (printer_status & PS_DISABLED)
if (printer_status & PS_REJECTED)
done (1);
}
}
goto Done;
}
done (1);
}
switch (status) {
case MNOFILTER:
if (try == 1) {
goto Again;
}
goto Done;
case MOK:
#if defined(WARN_OF_TOO_MANY_LINES)
#endif
break;
case MERRDEST:
goto Again;
case MNOMEM:
goto Done;
case MNODEST:
goto Done;
case MNOOPEN: /* not quite, but close */
goto Done;
case MDENYDEST:
if (printer_chk) {
if (printer_chk & PCK_TYPE)
if (printer_chk & PCK_CHARSET)
if (printer_chk & PCK_CPI)
if (printer_chk & PCK_LPI)
if (printer_chk & PCK_WIDTH)
if (printer_chk & PCK_LENGTH)
if (printer_chk & PCK_BANNER)
cp[-2] = 0;
goto Done;
}
/*fall through*/
case MUNKNOWN:
case MNOMEDIA:
case MDENYMEDIA:
case MNOMOUNT:
case MNOSPACE:
case MNOPERM:
if (printer_status & PS_REJECTED)
done (1);
/*NOTREACHED*/
}
if (printer_status & PS_REJECTED)
/*
* Enable printing, to start the interface program going.
* Because of our precautions above, our request SHOULD be
* the one that prints!
*/
/*
* Open the FIFO. One problem: This will hang until the
* interface program opens the other end!!
*/
done (1);
}
/*
* Loop, dumping the ENTIRE alignment pattern to the FIFO
* each time. SIGPIPE probably means the printer faulted.
*/
/*
* Don't send a form feed after the last copy, since
* the interface program does that. To implement this,
* we send the form feed BEFORE the alignment pattern;
* this way we can simply not send it the first time.
*/
char * ff = 0;
char * ff_before = 0;
/*
* If we'll be inserting page breaks between alignment
* patterns, look up the control sequence for this.
*
* MORE: We currently don't have the smarts to figure out
* WHICH printer type the Spooler will pick; we would need
* to steal some of its code for that (see pickfilter.c)
* The best we do so far is use the alignment pattern's
* content type, if known.
*/
if (filebreak) {
if (
T /* having "filebreak" => OK */
)
)
else
}
do {
register int n;
} while (again());
} else {
#define P(X) printf (X)
P("We were interrupted while printing the alignment pattern;\n");
P("check the printer. The form is mounted, so you will have to\n");
P("unmount it if you need to print more alignment patterns later.\n");
}
/*
* Disable the printer, if needed, and close the FIFO.
* Use the wait version of the disable, so our request isn't
* stopped, and do it before closing the FIFO, so another request
* can't start printing if it isn't supposed to.
*/
if (printer_status & PS_DISABLED)
return (1);
}
/**
** accept() - MAKE PRINTER ACCEPT REQUESTS
**/
char *printer;
{
int rc;
switch (rc) {
case MOK:
case MERRDEST: /* someone may have snuck in an accept */
break;
case MNODEST: /* make up your mind, Spooler! */
case MNOPERM: /* taken care of up front */
default:
done (1);
}
return;
}
/**
** reject() - MAKE PRINTER REJECT REQUESTS
**/
char *printer,
*reason;
{
int rc;
switch (rc) {
case MOK:
case MERRDEST: /* someone may have snuck in a reject */
break;
case MNODEST: /* make up your mind, Spooler! */
case MNOPERM: /* taken care of up front */
default:
done (1);
}
return;
}
/**
** enable() - ENABLE THE PRINTER
**/
char *printer;
{
int rc;
switch (rc) {
case MOK:
case MERRDEST: /* someone may have snuck in an enable */
break;
case MNODEST: /* make up your mind, Spooler! */
case MNOPERM: /* taken care of up front */
default:
done (1);
}
return;
}
/**
** disable() - DISABLE THE PRINTER
**/
char *printer,
*reason;
int when;
{
int rc;
switch (rc) {
case MOK:
case MERRDEST: /* someone may have snuck in a disable */
break;
case MNODEST: /* make up your mind, Spooler! */
case MNOPERM: /* taken care of up front */
default:
done (1);
}
return;
}
/**
** cancel() - MAKE PRINTER ACCEPT REQUESTS
**/
char *req_id;
{
int rc;
switch (rc) {
case MOK:
case MUNKNOWN:
case M2LATE:
break;
case MNOPERM:
default:
done (1);
}
return;
}
/**
** again()
**/
static int again ()
{
for (;;) {
printf (
gettext("Press return to print an alignment pattern [q to quit]: ")
);
return (0);
if (
)
return (0);
else if (
!*answer
)
return (1);
}
}
/**
** sigpipe()
** sigother()
**/
static void sigpipe ()
{
/*NOTREACHED*/
}
int sig;
{
/*NOTREACHED*/
}