|
|
Initial revision
/*
* $Header: /var/lib/cvsd/repos/CSRG/43BSDTahoe/new/xns/examples/print/xnsprint.c,v 1.1 2018/04/24 16:12:58 root Exp $
*
* a program to print InterPress masters on an InterPress printer via
* Ethernet. Uses xns Courier.
* This version runs on 4.3BSD only!
*/
/*
* $Log: xnsprint.c,v $
* Revision 1.1 2018/04/24 16:12:58 root
* Initial revision
*
* Revision 2.4 87/01/09 16:34:23 ed
* Webster version
*
* Revision 2.4 87/01/09 16:34:23 ed
* Added -W flag to wait until printing is completed (from Lee Moore)
*
* Revision 2.3 86/12/11 04:43:34 jqj
* Added support for -s and -m flags.
*
* Revision 2.2 86/09/07 06:57:41 jqj
* Fixed inconsistent calls to attnmsg() by eliminating stderr first arg.
* Changed banner not to use "Cornell Computer Science".
*
* Revision 2.1 86/05/16 11:04:18 jqj
* fix to correspond to new enumeration semantics (tags are now global)
*
* Revision 2.0 85/11/21 07:23:11 jqj
* 4.3BSD standard release
*
* Revision 1.1 85/11/20 13:56:53 jqj
* Initial revision
*
* modified 8-6-85 by jqj.
* Eliminated any hardwired addresses. Instead, use CH_Enumerate to
* find a printer if none is specified. Also, you can now print multiple
* files in a single call to xnsprint, and getopt() is used to parse
* arguments.
*/
#include <stdio.h>
#include <sys/types.h>
#include <netns/ns.h>
#include <netns/sp.h>
#include "Printing3_defs.h"
#include <xnscourier/Clearinghouse2.h>
#include <xnscourier/except.h>
#include <pwd.h>
#include <sys/file.h>
#include <strings.h>
static FILE *ipfile = NULL;
static int ExitStatus = 0; /* modified lpd conventions: */
/* 0 => Job printed. (successfully sent to print-server) */
#define X_GOOD 0
/* 1 => Couldn't send job. Retry forever, should go eventually. */
#define X_RETRY 1
/* 2 => Couldn't send job, Strange error, Retry a limited number*/
/* of times. If it still hasn't worked, give up. */
#define X_LIMRETRY 2
/* 3 => Couldn't send job: Hard error, don't bother retrying, */
/* get rid of the job. */
#define X_NORETRY 3
static struct {
char * sizename;
int sizevalue;
} papersizetable[] = {
"usLetter", (int) usLetter, /* 1 */
"usLegal", (int) usLegal, /* 2 */
"a0", (int) a0, /* 3 */
"a1", (int) a1, /* 4 */
"a2", (int) a2, /* 5 */
"a3", (int) a3, /* 6 */
"a4", (int) a4, /* 7 */
"a5", (int) a5, /* 8 */
"a6", (int) a6, /* 9 */
"a7", (int) a7, /* 10 */
"a8", (int) a8, /* 11 */
"a9", (int) a9, /* 12 */
"a10", (int) a10, /* 35 */
"isoB0", (int) isoB0, /* 13 */
"isoB1", (int) isoB1, /* 14 */
"isoB2", (int) isoB2, /* 15 */
"isoB3", (int) isoB3, /* 16 */
"isoB4", (int) isoB4, /* 17 */
"isoB5", (int) isoB5, /* 18 */
"isoB6", (int) isoB6, /* 19 */
"isoB7", (int) isoB7, /* 20 */
"isoB8", (int) isoB8, /* 21 */
"isoB9", (int) isoB9, /* 22 */
"isoB10", (int) isoB10, /* 23 */
"jisB0", (int) jisB0, /* 24 */
"jisB1", (int) jisB1, /* 25 */
"jisB2", (int) jisB2, /* 26 */
"jisB3", (int) jisB3, /* 27 */
"jisB4", (int) jisB4, /* 28 */
"jisB5", (int) jisB5, /* 29 */
"jisB6", (int) jisB6, /* 30 */
"jisB7", (int) jisB7, /* 31 */
"jisB8", (int) jisB8, /* 32 */
"jisB9", (int) jisB9, /* 33 */
"jisB10", (int) jisB10, /* 34 */
(char *) 0, 0
};
SendSource(bdtconnection)
CourierConnection *bdtconnection;
{
int count;
char buffer[SPPMAXDATA];
while ( (count = fread(buffer,1,SPPMAXDATA,ipfile)) > 0 &&
BDTwrite(bdtconnection,buffer,count) >= 0 )
;
if (count <= 0)
BDTclosewrite(bdtconnection); /* last packet with EOM set */
else
BDTabort(bdtconnection);
}
/*
* misc externals
*/
int remove = 0;
int quiet = 0;
int attn = 0; /* Write lpr system STATUS file? LCP 850415*/
char *attnfile; /* Status file name. LCP 850415 */
char *FileName = NULL;
char *UserName = NULL;
char *Banner = NULL;
int copies = 1;
Medium paperchoice;
char *UserMessage = NULL;
Clearinghouse2_Name hostname;
char *xnshost = NULL;
int WaitFlag = 0; /* wait until job is printed ? LCM */
setxnshost(name)
Clearinghouse2_ObjectName name;
{
extern char *malloc(), *strcpy();
if (xnshost == NULL)
xnshost = strcpy(malloc(strlen(name.object)+1),name.object);
}
main(argc, argv)
int argc;
char **argv;
{
struct ns_addr *destaddr;
CourierConnection *conn;
extern struct ns_addr *getXNSaddr();
extern struct ns_addr *CH_LookupAddr();
Clearinghouse2_Name defaultname;
extern Clearinghouse2_Name CH_StringToName();
int opt;
extern int optind;
extern char *optarg;
int errflg = 0;
int i;
paperchoice.designator = paper;
paperchoice.paper_case.designator = knownSize;
paperchoice.paper_case.knownSize_case = usLetter;
while ((opt = getopt(argc,argv,"c:n:b:P:h:rqa:lm:s:W")) != EOF)
switch (opt) {
case 'c': /* copies */
copies = atoi(optarg);
break;
case 'n': /* user name */
UserName = optarg;
break;
case 'b': /* file name */
Banner = optarg;
break;
case 'P': /* printer */
case 'h': /* host */
xnshost = optarg;
break;
case 'r': /* remove input file when done */
remove++;
break;
case 'q': /* don't print status messages */
quiet++;
break;
case 'a': /* Write lpr STATUS file. Name follows. LCP 850415 */
quiet++;
attn++;
attnfile = optarg;
break;
case 'l': /* use legal-sized (long) paper */
paperchoice.paper_case.knownSize_case = usLegal;
break;
case 'm': /* message field follows (default to XNS name) */
UserMessage = optarg;
break;
case 's': /* papersize name follows */
for (i = 0; papersizetable[i].sizename != NULL; i++)
if (strcmp(optarg,papersizetable[i].sizename) == 0) {
*(int*)& paperchoice.paper_case.knownSize_case =
papersizetable[i].sizevalue;
goto gotsize;
}
*(int*)& paperchoice.paper_case.knownSize_case = atoi(optarg);
gotsize:
break;
case 'W': /* wait for the job to be printed LCM */
WaitFlag++;
break;
default:
errflg = 1;
}
if (errflg) {
attnmsg("Usage: %s [-r] [-P host] [-c #] [-n name] [-b banner] [-l] [-s size] [-m message] [-W] file...\n",
argv[0]);
exit(X_NORETRY);
}
/* set User Name for banner if necessary */
if (UserName == NULL) {
struct passwd *pwd, *getpwuid();
char *p;
extern char *getenv(), *index();
UserName = getenv("USER");
if ((pwd = getpwuid(getuid())) != NULL) {
UserName = pwd->pw_gecos;
if (p = index(UserName,','))
*p = '\000';
}
}
/* figure out what address we're sending to */
CH_NameDefault(&defaultname);/* default from clearinghouse.addresses */
if (xnshost == NULL) {
xnshost= getenv("PRINTER");
if ( (xnshost == NULL) || (*xnshost == '\0') ) {
/* find the first object in the local domain of the CH
* with a printService property. setxnshost sets xnshost
* to the name part of the object
*/
hostname = defaultname;
hostname.object = "*";
CH_Enumerate(hostname,10001,setxnshost);
hostname.object = xnshost;
} else
hostname = CH_StringToName(xnshost,&defaultname);
}
else hostname = CH_StringToName(xnshost,&defaultname);
if ((destaddr = CH_LookupAddr(hostname,4)) == NULL) {
attnmsg("Invalid address, %s:%s:%s\n",
hostname.object,hostname.domain,hostname.organization);
exit(X_NORETRY);
}
/* make sure the printer is available */
checkIPstatus(destaddr);
for ( ; optind < argc; optind++) {
FileName = argv[optind];
if (strcmp(FileName,"-") == 0) {
ipfile = stdin;
FileName = "standard input";
}
else if ((ipfile = fopen(FileName,"r")) == NULL) {
fprintf(stderr, "%s: Can't open %s\n", argv[0], FileName);
exit(X_NORETRY);
}
if(Banner == NULL)
Banner = FileName;
if (!quiet)
printf("Sending to %s...", xnshost);
fflush(stdout);
sendIPfile(ipfile,destaddr);
if (ipfile != stdin)
fclose(ipfile);
}
if (!quiet)
printf("Done.\n");
exit(X_GOOD);
}
/*
* Check printer status first so we won't dump big interpress
* files accross the net unless we're fairly confidant that they'll
* be accepted.
*/
checkIPstatus(destaddr)
struct ns_addr *destaddr;
{
CourierConnection *conn;
GetPrinterStatusResults StatusResult;
do {
if (!quiet)
printf("Opening connection to %s. ",xnshost);
if (attn)
attnmsg("Opening connection to %s.\n",xnshost);
if ((conn = CourierOpen(destaddr)) == NULL) {
attnmsg("Can't open connection to %s\n",xnshost);
if(remove && !attn)
attnmsg("Output left in %s\n", FileName);
exit(X_LIMRETRY);
}
if (!quiet)
printf("Connected.\n");
if (attn)
attnmsg("Requesting status.\n");
DURING
StatusResult = GetPrinterStatus(conn,NULL);
HANDLER {
ExitStatus = X_LIMRETRY;
switch (Exception.Code) {
case ServiceUnavailable:
attnmsg("GetStat: Service unavailable\n");
ExitStatus = X_NORETRY;
break;
case SystemError:
attnmsg("GetStat: System Error\n");
break;
case Undefined:
attnmsg("GetStat: Undefined error, number %d\n",
CourierErrArgs(UndefinedArgs,problem));
break;
case REJECT_ERROR:
attnmsg("GetStat: REJECT: type = %d\n",
CourierErrArgs(rejectionDetails, designator));
break;
default:
attnmsg("GetStat: Some random error, code %d\n",
Exception.Code);
break;
}
if (remove && !attn)
attnmsg("Output left in %s\n", FileName);
exit(ExitStatus);
} END_HANDLER;
CourierClose(conn);
} while (printresults(StatusResult.status) != 0);
}
/*
* display printer status, return 0 IFF spooler is available
*/
int
printresults(status)
PrinterStatus status;
{
int i, typ;
static char *spoollist[] = {"available","busy","disabled","full"};
static char *formatlist[] = {"available","busy","disabled"};
static char *printlist[] = {"available","busy","disabled",
"needs attention","needs key operator"};
int error = 1;
char bufr[256];
bufr[0] = '\0';
for (i = 0; i < status.length; i++) {
switch (status.sequence[i].designator) {
case spooler:
typ = (int) status.sequence[i].spooler_case;
if (!quiet || typ > 1)
sprintf(bufr+strlen(bufr),
"Spooler: %s; ", spoollist[typ]);
error = typ;
break;
case formatter:
typ = (int) status.sequence[i].formatter_case;
if (!quiet || typ > 1)
sprintf(bufr+strlen(bufr),
"Formatter: %s; ", formatlist[typ]);
break;
case printer:
typ = (int) status.sequence[i].printer_case;
if (!quiet || typ > 1)
sprintf(bufr+strlen(bufr),
"Printer: %s. ", printlist[typ]);
break;
case media:
/* printmedia(status.sequence[i].media_case); */
break;
}
}
if (bufr[0] != '\0')
{
if (attn)
attnmsg("%s\n",bufr);
else
printf("%s\n",bufr);
}
switch(error) {
case 0:
break;
case 1:
if (!quiet)
printf("Retrying... ");
if (bufr[0] != '\0' && attn)
attnmsg("Status: Busy. Retrying...\n");
fflush(stdout);
sleep(15);
break;
default:
if(remove && !attn)
attnmsg( "Output left in %s\n", FileName);
exit(1);
}
return(error);
}
attnmsg(fmt,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9)
char *fmt;
{
char bufr[256];
int af;
if (attn)
{
if ((af = open(attnfile,O_TRUNC|O_WRONLY|O_CREAT,0666)) < 0)
return; /* Oh Well. */
sprintf(bufr,fmt,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9);
(void) write(af,bufr,strlen(bufr)); /* In case of error??? */
close(af);
}
else
fprintf(stderr,fmt,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9);
}
sendIPfile(ipfile,destaddr)
FILE *ipfile;
struct ns_addr *destaddr;
{
PrintResults result;
CourierConnection *conn;
PrintAttributes attributes;
PrintOptions options;
char *malloc();
/* only use sender name and file name, no date */
attributes.length = 2;
attributes.sequence = malloc(attributes.length *
sizeof(*attributes.sequence));
attributes.sequence[0].designator = printObjectName;
attributes.sequence[0].printObjectName_case = Banner;
attributes.sequence[1].designator = senderName;
attributes.sequence[1].senderName_case = UserName;
options.length = 3;
options.sequence = malloc(options.length *
sizeof(*options.sequence));
options.sequence[0].designator = copyCount;
options.sequence[0].copyCount_case = copies;
options.sequence[1].designator = mediumHint;
options.sequence[1].mediumHint_case = paperchoice;
options.sequence[2].designator = message;
options.sequence[2].message_case =
UserMessage ? UserMessage :
sprintf(malloc(44),"%s:%s:%s",
hostname.object,hostname.domain,
hostname.organization)
;
again:
if (!quiet)
printf("Opening connection to %s. ",xnshost);
if (attn)
attnmsg("Opening connection to %s.\n",xnshost);
if ((conn = CourierOpen(destaddr)) == NULL) {
attnmsg("Can't open connection to %s\n",xnshost);
if(remove && !attn)
attnmsg("Output left in %s\n", FileName);
exit(X_LIMRETRY);
}
if (!quiet)
printf("Connected.\n");
if (attn)
attnmsg("Sending to %s\n",xnshost);
DURING
result = Print(conn, SendSource, BulkData1_immediateSource,
attributes, options);
HANDLER {
ExitStatus = X_RETRY;
switch (Exception.Code) {
case Busy:
if (!quiet)
printf("Busy, retrying...\n");
if (attn)
attnmsg("Busy, retrying...\n");
CourierClose(conn);
sleep(15);
if (rewind(ipfile) < 0) {
ExitStatus = X_LIMRETRY;
attnmsg("Can't rewind file\n");
}
goto again;
case ConnectionError:
ExitStatus = X_LIMRETRY;
attnmsg("Connection error, %d\n",
CourierErrArgs(ConnectionErrorArgs,problem));
break;
case InsufficientSpoolSpace:
attnmsg("Insufficient Spool Space error\n");
break;
case InvalidPrintParameters:
ExitStatus = X_LIMRETRY;
attnmsg("InvalidPrintParameters error\n");
break;
case MasterTooLarge:
ExitStatus=X_NORETRY;
attnmsg("MasterTooLarge error\n");
break;
case MediumUnavailable:
ExitStatus=X_NORETRY;
attnmsg("MediumUnavailable error\n");
break;
case ServiceUnavailable:
ExitStatus=X_NORETRY;
attnmsg("ServiceUnavailable error\n");
break;
case SpoolingDisabled:
attnmsg("SpoolingDisabled\n");
break;
case SpoolingQueueFull:
attnmsg("SpoolingQueueFull error\n");
break;
case SystemError:
ExitStatus = X_LIMRETRY;
attnmsg("System Error\n");
break;
case TooManyClients:
attnmsg("TooManyClients error\n");
break;
case TransferError:
ExitStatus = X_LIMRETRY;
attnmsg("TransferError error\n");
break;
case Undefined:
attnmsg("Undefined error, number %d\n",
CourierErrArgs(UndefinedArgs,problem));
break;
case REJECT_ERROR:
ExitStatus = X_LIMRETRY;
attnmsg("REJECT: type = %d\n",
CourierErrArgs(rejectionDetails, designator));
break;
default:
ExitStatus = X_LIMRETRY;
attnmsg("Some random error, code %d\n",
Exception.Code);
break;
}
if(remove && !attn)
attnmsg("Output left in %s\n", FileName);
exit(ExitStatus);
} END_HANDLER;
if (WaitFlag) /* wait for completion LCM */
WaitForCompletion(conn, result.printRequestID);
CourierClose(conn);
/* RETURNS [printRequestID: RequestID] */
if(remove) unlink(FileName);
}
/*
* Wait for the job to complete
*/
WaitForCompletion(conn, printRequestID)
CourierConnection *conn;
Printing3_RequestID printRequestID;
{
static char *statusStrings[] = {"pending", "inProgress", "completed",
"completedWithWarning", "unknown", "rejected", "aborted",
"canceled", "held"};
#define DONE 0
#define WAIT 1
static char statusActions[] = {WAIT, WAIT, DONE,
DONE, DONE, DONE, DONE,
DONE, WAIT};
int i, typ,
cycle,
action;
GetPrintRequestStatusResults result;
for(cycle = 0;; cycle++) {
if (!quiet)
printf("try #%d\n", cycle);
DURING
result = GetPrintRequestStatus(conn, NULL, printRequestID);
HANDLER {
ExitStatus = X_NORETRY; /* if it got this far... */
switch (Exception.Code) {
case ServiceUnavailable:
attnmsg("GetReqStat: Service unavailable\n");
break;
case SystemError:
attnmsg("GetReqStat: System error\n");
break;
case Undefined:
attnmsg("GetReqStat: Undefined error, number %d\n",
CourierErrArgs(UndefinedArgs, problem));
case REJECT_ERROR:
attnmsg("GetReqStat: REJECT: type = %d\n",
CourierErrArgs(rejectionDetails, designator));
break;
default:
attnmsg("GetStat: Some random error, code %d\n",
Exception.Code);
break;
}
exit(ExitStatus);
} END_HANDLER;
action = WAIT;
/* check out the returned status */
for( i = 0; i < result.status.length; i++ ) {
switch (result.status.sequence[i].designator) {
case status:
typ = (int) result.status.sequence[i].status_case;
action = statusActions[typ];
if (!quiet)
printf("\tstatus: %s\n", statusStrings[typ]);
break;
case statusMessage:
if(!quiet)
printf("\tstatus message (%d bytes): %s\n",
strlen(result.status.sequence[i].statusMessage_case),
result.status.sequence[i].statusMessage_case);
break;
default:
printf("GetReqStatu: help!\n");
}
}
if( action == DONE )
return;
sleep(3); /* wait three seconds before trying again */
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.