lp.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
* 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 1996-2002 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/* lp -- print files on a line printer */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <assert.h>
#include <locale.h>
#include <string.h>
#include "requests.h"
#include "lp.h"
#include "msgs.h"
#include "printers.h"
#include "oam.h"
#define TRUE 1
#define FALSE 0
/* file to run when job is done if -p option is selected */
FALSE => don't do it */
#define HOLD 1
#define RESUME 2
#define IMMEDIATE 3
#define POSTSCRIPT "postscript"
static int specialh = 0; /* -H flag indicates special handling */
static char *curdir; /* working directory at time of request */
static char *stdinfile;
static char *rfilebase;
static short copies = 0; /* number of copies of output */
* via write, FALSE => don't write
*/
* true
*/
static int nfiles = 0; /* # of files on cmd line (excluding "-") */
static int stdinp = 0; /* indicates how many times to print std input
*-1 ==> standard input empty
*/
static int Tflag = 0; /* 0, -T not specified, 1, -T specified
* this flag used for autorecognizing
* postscript
* if == 1, autorec. ps. is off!
*/
static int exit_code = 0; /* exit with this value */
extern char *sprintlist();
extern int appendlist();
static int psfile(char *);
#define OPTSTRING "q:H:f:d:T:S:o:y:P:i:cmwpn:st:r"
static void
char *str;
{
exit(1);
}
}
char *
mkAlertCmd(char *reqfile)
{
int len;
return(str);
}
int argc;
char *argv[];
{
int letter;
char *file;
int fileargs = 0;
extern char *optarg;
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
opterr = 0; /* disable printing of errors by getopt */
switch(letter) {
case 'c': /* copy files */
break;
case 'd': /* destination */
exit (1);
}
break;
case 'f':
break;
case 'H':
else {
exit(1);
}
break;
case 'i':
break;
case 'm': /* mail */
break;
case 'n': /* # of copies */
if (
*optarg == 0
|| *p
) {
exit(1);
}
break;
case 'o': /* option for interface program */
if (!stemp)
break; /* MR bl88-14720 */
while (*templist)
break;
case 'y':
if (!stemp)
break; /* MR bl88-14720 */
while (*templist)
break;
case 'P':
break;
case 'q':
exit(1);
}
break;
case 'r':
break;
case 's': /* silent */
silent = 1;
break;
case 'S':
break;
case 't': /* title */
break;
case 'T':
Tflag++;
break;
case 'p':
break;
case 'w': /* write */
break;
default:
if (optopt == '?') {
(void)printf(
gettext("usage:\n\n(submit file(s) for printing)\n"));
"lp [options] { file-name ... | - }\n"));
" [-c] (make copies first)\n"
" [-f form [-d any]] (print on this form)\n"
" [-H hold] (don't print yet)\n"
" [-H immediate] (print first--reserved)\n"
" [-p] (notify when done via ToolTalk)\n"
" [-n copies] (print this many copies)\n"
" [-o nobanner] (no banner page)\n"));
" [-o nofilebreak] (no inter-file formfeed)\n"
" [-o length=scaled-number] (page length)\n"
" [-o width=scaled-number] (page width)\n"));
" [-o lpi=scaled-number] (line pitch)\n"
" [-o cpi=scaled-number] (character pitch)\n"));
" [-o stty='stty-options'] (port characteristics)\n"
" [-o other-local-options] (as defined locally)\n"));
" [-P page-list] (locally defined)\n"
" [-q priority] (priority level)\n"
" [-r] (use no filter)\n"));
" [-s] (no request-id message)\n"
" [-S char-set | print-wheel [-d any]] (font to start with)\n"
" [-t title] (title for banner page)\n"
" [-T file-type] (type of input files)\n"
" [-y local-modes] (locally defined)\n"
"\n"));
" (change previous request)\n"
" lp -i request-id {options}\n"
" [-H resume] (resume held request)\n"
" [other options listed above]\n"));
exit(0);
}
else
exit(1);
}
fileargs++;
stdinp++;
} else {
else
exit_code = 1;
exit_code = 1;
exit_code = 1;
} else {
nfiles++;
continue;
}
}
}
if(fileargs == 0) {
} else if (pre_rqid) {
exit(1);
exit(1);
}
/* args parsed, now let's do it */
startup(); /* open message queue
and catch interupts so it gets closed too */
err_exit();
}
/* allocate files for request, standard input and files if copy */
if (pre_rqid) {
switch(errno) {
default:
err_exit();
}
}
} else {
allocfiles();
if(stdinp > 0) {
savestd(); /* save standard input */
}
}
clean_up();
ack_job(); /* issue request id message */
return(0);
}
/* startup -- initialization routine */
static void
startup()
{
void catch();
int try = 0;
for (;;)
if (mopen() == 0) break;
else {
(void) sleep(3);
continue;
}
exit(1);
}
(void) umask(0000);
}
/* catch -- catch signals */
static void
catch()
{
err_exit();
}
/* clean_up -- called by catch() after interrupts
or by err_exit() after errors */
static void
clean_up()
{
(void)mclose ();
}
static void
err_exit()
{
clean_up();
exit(1);
}
/*
* copyfile(stream, name) -- copy stream to file "name"
*/
static void
char *name;
{
int i;
return;
}
errno = 0;
}
if (errno != 0) {
} else {
}
err_exit();
}
}
/* makereq -- sanity check args, establish defaults */
static REQUEST *
makereq()
{
char *preqfile;
/*
* begin changes for 1112940
* The test used to look like: if (!dest && !pre_rqid && !cont_type)
* Now, if either LPDEST or a default is set, use those instead of "any".
* This is probably more like what the user expects and the SVID isn't
* real clear about the interaction of LPDEST, the default and -T.
* If the printer can't handle this content, we'll get an error later.
*/
;
else {
if (!(dest = getdefault())) {
if (cont_type)
dest = "any";
else {
err_exit();
}
}
}
}
/* end changes for 1112940 */
Tflag++;/* for autorecognizing postscript, LPTYPE is */
/* equivalent to specifying "-T" */
}
}
err_exit();
}
err_exit();
}
/* now to build the request */
if (pre_rqid) {
if (raw) {
/*appendlist(&opts, "stty=raw");*/
}
return(&rq);
}
if (raw) {
/*appendlist(&opts, "stty=raw");*/
}
return(&rq);
}
/* files -- process command line file arguments */
static void
{
FILE *f;
{
copy = 1;
}
if (stdinp > 0) {
*p++ = '1';
*p = 0;
filenum++;
}
if(stdinp > 0)
} else {
if(copy) {
(void) fclose(f);
} else
} else {
else {
err_exit ();
}
}
}
}
}
/* start_ch -- start change request */
static char *
{
short status;
char message[100],
reply[100],
*rqfile;
err_exit();
}
err_exit();
}
if (type != R_START_CHANGE_REQUEST
err_exit();
}
switch (status) {
case MOK:
case MNOPERM:
break;
case MUNKNOWN:
break;
case MBUSY:
break;
case M2LATE:
break;
case MGONEREMOTE:
break;
default:
}
err_exit();
/*NOTREACHED*/
}
static void
{
long chkbits;
short status;
char message[255],
reply[100],
*chkp;
err_exit();
}
err_exit();
}
if (type != R_END_CHANGE_REQUEST
err_exit();
}
switch (status) {
case MOK:
return;
case MNOPERM:
break;
case MNOSTART:
break;
case MNODEST:
break;
case MDENYDEST:
if (chkbits) {
/* PCK_TYPE indicates a Terminfo error, and should */
/* be handled as a ``get help'' problem. */
if (chkbits & PCK_CHARSET)
gettext("does not print on specified type of paper, "));
else
chkp[-2] = 0;
}
break;
case MNOMEDIA:
break;
case MDENYMEDIA:
break;
case MNOMOUNT:
break;
case MNOFILTER:
break;
case MERRDEST:
break;
case MNOOPEN:
break;
default:
}
err_exit();
}
/* getfile -- allocate the requested number of temp files */
static char *
{
short status;
char message[100],
reply[100],
*pfix;
err_exit();
}
err_exit();
}
if (type != R_ALLOC_FILES
err_exit();
}
switch (status) {
case MOK:
case MOKREMOTE:
clean_up();
startup();
return(NULL);
case MNOMEM:
break;
case MERRDEST:
break;
default:
}
err_exit();
/*NOTREACHED*/
}
static char *
{
long chkbits;
short status;
char message[255],
reply[100],
*chkp,
*req_id;
err_exit();
}
err_exit();
}
if (type != R_PRINT_REQUEST
err_exit();
}
switch (status) {
case MOK:
case MNOPERM:
break;
case MNODEST:
break;
case MDENYDEST:
if (chkbits) {
/* PCK_TYPE indicates a Terminfo error, and should */
/* be handled as a ``get help'' problem. */
gettext("does not print on specified type of paper, "));
else
chkp[-2] = 0;
}
break;
case MNOMEDIA:
break;
case MDENYMEDIA:
break;
case MNOMOUNT:
break;
case MNOFILTER:
break;
case MERRDEST:
break;
case MNOOPEN:
break;
case MUNKNOWN:
break;
default:
}
err_exit();
/*NOTREACHED*/
}
/* ack_job -- issue request id message */
static void
ack_job()
{
if (nfiles > 0) {
if (stdinp > 0) {
"(%d file(s) and standard input)\n"), nfiles);
} else {
}
} else if (stdinp > 0) {
} else
printf("\n");
}
/* savestd -- save standard input */
static void
savestd()
{
if(nfiles == 0) {
err_exit();
} else {/* inhibit printing of std input */
stdinp = -1;
}
}
else { /* see if our non-zero size file is postscript */
}
}
}
/* psfile(): Determine whether a file is postscript or not
* input: char string of the filename
* ouput: 0 if the file isn't postscript,
* non-zero if it is.
* Description:
* This routine looks to see if the "%!" characters are the first
* parts of the document (See PostScript Language Reference Manual,
* Second Edition - Adobe Systems Inc.; Appendix G - D.S.C. 3.0, p. 621).
*
* This code has been blatently (and legally) ripped off from lpr,
* with only one apology: USL should've done this in the first place!!
*/
#define PSCOM "%!"
#define PC_PSCOM "\004%!"
static int
{
int fd;
register int ret = 0;
ret++;
return(ret);
}
/* arps(): autorecognize postscript files
* input: REQUEST pointer.
* ouput: none directly; the REQUEST pointer may be modified.
* description:
* this routine is called before the REQUEST structure
* is written to disk. the list of files to be printed is
* examined to see if all of the files are postscript. if
* they are, then the input_type field is changed to
* "postscript".
*
* NOTE WELL - autorecognition is not done under the following
* conditions:
* 1) The -T flag has been used.
* 2) *Any* file in the file_list is *not* postscript. Right now,
* this is actually an ugly design decision. The request
* file specifies only one input_type for all of the files
* in the request. If any type isn't postscript, then
* input_type is unmodified, and the request will be
* treated as "simple". The reason for this is due
* to the design of the lp subsystem. What's need is
* to change the request handling to allow for multiple
* file types per request. However, this current
* implementation will fit in 100% with the original
* design of the lp subsystem.
*/
static void
{
char **lfiles;
int start = 0;
int current;
if (Tflag != 0) {
return;
}
return;
}
}
if (start != 0) { /* all the files are postscript */
}
}