BSD 4_4_Lite1 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Fri, 8 May 1987 06:58:57 +0000 (22:58 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Fri, 8 May 1987 06:58:57 +0000 (22:58 -0800)
Work on file usr/src/contrib/xns/examples/print/xnsprint.c

Synthesized-from: CSRG/cd2/4.4BSD-Lite1

usr/src/contrib/xns/examples/print/xnsprint.c [new file with mode: 0644]

diff --git a/usr/src/contrib/xns/examples/print/xnsprint.c b/usr/src/contrib/xns/examples/print/xnsprint.c
new file mode 100644 (file)
index 0000000..510a520
--- /dev/null
@@ -0,0 +1,660 @@
+/*
+ * $Header: xnsprint.c,v 2.4 87/01/09 16:34:23 ed 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 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 */
+       }
+}