1: /*
   2:  * $Header: xnsprint.c,v 2.0 85/11/21 07:23:11 jqj Exp $
   3:  *
   4:  * a program to print InterPress masters on an InterPress printer via
   5:  * Ethernet.   Uses xns Courier.
   6:  * This version runs on 4.3BSD only!
   7:  */
   8: 
   9: /*
  10:  * $Log:	xnsprint.c,v $
  11:  * Revision 2.0  85/11/21  07:23:11  jqj
  12:  * 4.3BSD standard release
  13:  *
  14:  * Revision 1.1  85/11/20  13:56:53  jqj
  15:  * Initial revision
  16:  *
  17:  * modified 8-6-85 by jqj.
  18:  *  Eliminated any hardwired addresses.  Instead, use CH_Enumerate to
  19:  *  find a printer if none is specified.  Also, you can now print multiple
  20:  *  files in a single call to xnsprint, and getopt() is used to parse
  21:  *  arguments.
  22:  */
  23: #include <stdio.h>
  24: #include <sys/types.h>
  25: #include <netns/ns.h>
  26: #include <netns/sp.h>
  27: #include "Printing3_defs.h"
  28: #include <xnscourier/Clearinghouse2.h>
  29: #include <xnscourier/except.h>
  30: #include <pwd.h>
  31: #include <sys/file.h>
  32: #include <strings.h>
  33: 
  34: static FILE *ipfile = NULL;
  35: static int ExitStatus = 0;      /* modified lpd conventions: */
  36:     /* 0 => Job printed.  (successfully sent to print-server) */
  37: #define X_GOOD 0
  38:     /* 1 => Couldn't send job.  Retry forever, should go eventually. */
  39: #define X_RETRY 1
  40:     /* 2 => Couldn't send job,  Strange error, Retry a limited number*/
  41:     /*		of times.  If it still hasn't worked, give up.	 */
  42: #define X_LIMRETRY 2
  43:     /* 3 => Couldn't send job:  Hard error, don't bother retrying,	 */
  44:     /*		get rid of the job.				 */
  45: #define X_NORETRY 3
  46: 
  47: SendSource(bdtconnection)
  48: CourierConnection *bdtconnection;
  49: {
  50:     int count;
  51:     char buffer[SPPMAXDATA];
  52: 
  53:     while ( (count = fread(buffer,1,SPPMAXDATA,ipfile)) > 0 &&
  54:         BDTwrite(bdtconnection,buffer,count) >= 0 )
  55:         ;
  56:     if (count <= 0)
  57:         BDTclosewrite(bdtconnection);   /* last packet with EOM set */
  58:     else
  59:         BDTabort(bdtconnection);
  60: }
  61: /*
  62:  * misc externals
  63:  */
  64: int remove = 0;
  65: int quiet = 0;
  66: int attn = 0;       /* Write lpr system STATUS file?	LCP 850415*/
  67: char *attnfile;     /* Status file name.		LCP 850415 */
  68: char *FileName = NULL;
  69: char *UserName = NULL;
  70: char *Banner = NULL;
  71: int copies = 1;
  72: Clearinghouse2_Name hostname;
  73: char *xnshost = NULL;
  74: 
  75: setxnshost(name)
  76:     Clearinghouse2_ObjectName name;
  77: {
  78:     extern char *malloc(), *strcpy();
  79: 
  80:     if (xnshost == NULL)
  81:       xnshost = strcpy(malloc(strlen(name.object)+1),name.object);
  82: }
  83: 
  84: main(argc, argv)
  85:     int argc;
  86:     char **argv;
  87: {
  88:     struct ns_addr *destaddr;
  89:     CourierConnection *conn;
  90:     extern struct ns_addr *getXNSaddr();
  91:     extern struct ns_addr *CH_LookupAddr();
  92:     Clearinghouse2_Name hostname, defaultname;
  93:     extern Clearinghouse2_Name CH_StringToName();
  94:     int opt;
  95:     extern int optind;
  96:     extern char *optarg;
  97:     int errflg = 0;
  98: 
  99:     while ((opt = getopt(argc,argv,"c:n:b:P:h:rqa:")) != EOF)
 100:         switch (opt) {
 101:         case 'c':   /* copies */
 102:         copies = atoi(optarg);
 103:         break;
 104:         case 'n':   /* user name */
 105:         UserName = optarg;
 106:         break;
 107:         case 'b':   /* file name */
 108:         Banner = optarg;
 109:         break;
 110:         case 'P':   /* printer */
 111:         case 'h':   /* host */
 112:         xnshost = optarg;
 113:         break;
 114:         case 'r':   /* remove input file when done */
 115:         remove++;
 116:         break;
 117:         case 'q':   /* don't print status messages */
 118:         quiet++;
 119:         break;
 120:         case 'a':   /* Write lpr STATUS file.  Name follows.  LCP 850415 */
 121:         quiet++;
 122:         attn++;
 123:         attnfile = optarg;
 124:         break;
 125:         default:
 126:         errflg = 1;
 127:         }
 128:     if (errflg) {
 129:         attnmsg("Usage: %s [-r] [-P host] [-c #] [-n name] [-b banner] file...\n",
 130:             argv[0]);
 131:         exit(X_NORETRY);
 132:     }
 133: 
 134:     /* set User Name for banner if necessary */
 135:     if (UserName == NULL) {
 136:         struct passwd *pwd, *getpwuid();
 137:         char *p;
 138:         extern char *getenv(), *index();
 139: 
 140:         UserName = getenv("USER");
 141:         if ((pwd = getpwuid(getuid())) != NULL) {
 142:         UserName = pwd->pw_gecos;
 143:         if (p = index(UserName,','))
 144:             *p = '\000';
 145:         }
 146:     }
 147: 
 148:     /* figure out what address we're sending to */
 149:     CH_NameDefault(&defaultname);/* default from clearinghouse.addresses */
 150:     if (xnshost == NULL) {
 151:         /* find the first object in the local domain of the CH
 152: 		 * with a printService property.  setxnshost sets xnshost
 153: 		 * to the name part of the object
 154: 		 */
 155:         hostname = defaultname;
 156:         hostname.object = "*";
 157:         CH_Enumerate(hostname,10001,setxnshost);
 158:         hostname.object = xnshost;
 159:     }
 160:     else hostname = CH_StringToName(xnshost,&defaultname);
 161:     if ((destaddr = CH_LookupAddr(hostname,4)) == NULL) {
 162:         attnmsg("Invalid address, %s:%s:%s\n",
 163:             hostname.object,hostname.domain,hostname.organization);
 164:         exit(X_NORETRY);
 165:     }
 166: 
 167:     /* make sure the printer is available */
 168:     checkIPstatus(destaddr);
 169: 
 170:     for ( ; optind < argc; optind++) {
 171:         FileName = argv[optind];
 172:         if (strcmp(FileName,"-") == 0) {
 173:         ipfile = stdin;
 174:         FileName = "standard input";
 175:         }
 176:         else if ((ipfile = fopen(FileName,"r")) == NULL) {
 177:         fprintf(stderr, "%s: Can't open %s\n", argv[0], FileName);
 178:         exit(X_NORETRY);
 179:         }
 180:         if(Banner == NULL)
 181:         Banner = FileName;
 182: 
 183:         if (!quiet)
 184:         printf("Sending to %s...", xnshost);
 185:         fflush(stdout);
 186: 
 187:         sendIPfile(ipfile,destaddr);
 188:         if (ipfile != stdin)
 189:         fclose(ipfile);
 190:     }
 191: 
 192:     if (!quiet)
 193:         printf("Done.\n");
 194:     exit(X_GOOD);
 195: }
 196: 
 197: /*
 198:  * Check printer status first so we won't dump big interpress
 199:  * files accross the net unless we're fairly confidant that they'll
 200:  * be accepted.
 201:  */
 202: checkIPstatus(destaddr)
 203:     struct ns_addr *destaddr;
 204: {
 205:     CourierConnection *conn;
 206:     GetPrinterStatusResults StatusResult;
 207: 
 208:     do {
 209:         if (!quiet)
 210:         printf("Opening connection to %s. ",xnshost);
 211:         if (attn)
 212:         attnmsg("Opening connection to %s.\n",xnshost);
 213:         if ((conn = CourierOpen(destaddr)) == NULL) {
 214:         attnmsg(stderr,"Can't open connection to %s\n",xnshost);
 215:         if(remove && !attn)
 216:             attnmsg(stderr,"Output left in %s\n", FileName);
 217:         exit(X_LIMRETRY);
 218:         }
 219:         if (!quiet)
 220:         printf("Connected.\n");
 221:         if (attn)
 222:         attnmsg("Requesting status.\n");
 223:         DURING
 224:         StatusResult = GetPrinterStatus(conn,NULL);
 225:         HANDLER {
 226:         ExitStatus = X_LIMRETRY;
 227:         switch (Exception.Code) {
 228:         case ServiceUnavailable:
 229:             attnmsg(stderr,"GetStat: Service unavailable\n");
 230:             ExitStatus = X_NORETRY;
 231:             break;
 232:         case SystemError:
 233:             attnmsg(stderr,"GetStat: System Error\n");
 234:             break;
 235:         case Undefined:
 236:             attnmsg(stderr,"GetStat: Undefined error, number %d\n",
 237:                 CourierErrArgs(UndefinedArgs,problem));
 238:             break;
 239:         case REJECT_ERROR:
 240:             attnmsg(stderr,"GetStat: REJECT:  type = %d\n",
 241:                 CourierErrArgs(rejectionDetails, designator));
 242:             break;
 243:         default:
 244:             attnmsg(stderr,"GetStat: Some random error, code %d\n",
 245:                 Exception.Code);
 246:             break;
 247:         }
 248:         if (remove && !attn)
 249:         attnmsg(stderr,"Output left in %s\n", FileName);
 250:         exit(ExitStatus);
 251:         } END_HANDLER;
 252: 
 253:         CourierClose(conn);
 254:     } while (printresults(StatusResult.status) != 0);
 255: }
 256: 
 257: /*
 258:  * display printer status, return 0 IFF spooler is available
 259:  */
 260: int
 261: printresults(status)
 262:     PrinterStatus status;
 263: {
 264:     int i, typ;
 265:     static char *spoollist[] = {"available","busy","disabled","full"};
 266:     static char *formatlist[] = {"available","busy","disabled"};
 267:     static char *printlist[] = {"available","busy","disabled",
 268:             "needs attention","needs key operator"};
 269:     int error = 1;
 270:     char bufr[256];
 271: 
 272:     bufr[0] = '\0';
 273:     for (i = 0; i < status.length; i++) {
 274:         switch (status.sequence[i].designator) {
 275:         case spooler:
 276:             typ = (int) status.sequence[i].spooler_case;
 277:             if (!quiet || typ > 1)
 278:                 sprintf(bufr+strlen(bufr),
 279:                 "Spooler: %s; ", spoollist[typ]);
 280:             error = typ;
 281:             break;
 282:         case formatter:
 283:             typ = (int) status.sequence[i].formatter_case;
 284:             if (!quiet || typ > 1)
 285:                 sprintf(bufr+strlen(bufr),
 286:                 "Formatter: %s; ", formatlist[typ]);
 287:             break;
 288:         case printer:
 289:             typ = (int) status.sequence[i].printer_case;
 290:             if (!quiet || typ > 1)
 291:                 sprintf(bufr+strlen(bufr),
 292:                 "Printer: %s. ", printlist[typ]);
 293:             break;
 294:         case media:
 295:             /* printmedia(status.sequence[i].media_case); */
 296:             break;
 297:         }
 298:     }
 299:     if (bufr[0] != '\0')
 300:     {
 301:         if (attn)
 302:         attnmsg("%s\n",bufr);
 303:         else
 304:             printf("%s\n",bufr);
 305:     }
 306: 
 307:     switch(error) {
 308:         case 0:
 309:             break;
 310:         case 1:
 311:             if (!quiet)
 312:                 printf("Retrying... ");
 313:             if (bufr[0] != '\0' && attn)
 314:                 attnmsg("Status: Busy.  Retrying...\n");
 315:             fflush(stdout);
 316:             sleep(15);
 317:             break;
 318:         default:
 319:             if(remove && !attn)
 320:                 attnmsg(stderr, "Output left in %s\n", FileName);
 321:             exit(1);
 322:     }
 323:     return(error);
 324: }
 325: 
 326: 
 327: attnmsg(fmt,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9)
 328:     char *fmt;
 329: {
 330:     char bufr[256];
 331:     int af;
 332: 
 333:     if (attn)
 334:     {
 335:         if ((af = open(attnfile,O_TRUNC|O_WRONLY|O_CREAT,0666)) < 0)
 336:             return; /* Oh Well. */
 337: 
 338:         sprintf(bufr,fmt,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9);
 339: 
 340:         (void) write(af,bufr,strlen(bufr)); /* In case of error??? */
 341:         close(af);
 342:     }
 343:     else
 344:         fprintf(stderr,fmt,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9);
 345: }
 346: 
 347: sendIPfile(ipfile,destaddr)
 348:     FILE *ipfile;
 349:     struct ns_addr *destaddr;
 350: {
 351:     PrintResults result;
 352:     CourierConnection *conn;
 353:     PrintAttributes attributes;
 354:     PrintOptions options;
 355:     char *malloc();
 356: 
 357:     /* only use sender name and file name, no date */
 358:     attributes.length = 2;
 359:     attributes.sequence = malloc( 2 * sizeof(*attributes.sequence));
 360:     attributes.sequence[0].designator = printObjectName;
 361:     attributes.sequence[0].printObjectName_case = Banner;
 362:     attributes.sequence[1].designator = senderName;
 363:     attributes.sequence[1].senderName_case = UserName;
 364: 
 365:     options.length = 1;
 366:     options.sequence = malloc( sizeof(*options.sequence));
 367:     options.sequence[0].designator = copyCount;
 368:     options.sequence[0].copyCount_case = copies;
 369: 
 370: again:
 371:     if (!quiet)
 372:         printf("Opening connection to %s. ",xnshost);
 373:     if (attn)
 374:         attnmsg("Opening connection to %s.\n",xnshost);
 375: 
 376:     if ((conn = CourierOpen(destaddr)) == NULL) {
 377:         attnmsg(stderr,"Can't open connection to %s\n",xnshost);
 378:         if(remove && !attn)
 379:             attnmsg(stderr,"Output left in %s\n", FileName);
 380:         exit(X_LIMRETRY);
 381:     }
 382: 
 383:     if (!quiet)
 384:         printf("Connected.\n");
 385:     if (attn)
 386:         attnmsg("Sending to %s\n",xnshost);
 387: 
 388:     DURING
 389:         result = Print(conn, SendSource, BulkData1_immediateSource,
 390:                     attributes, options);
 391:     HANDLER {
 392:         ExitStatus = X_RETRY;
 393:         switch (Exception.Code) {
 394:         case Busy:
 395:             if (!quiet)
 396:                 printf("Busy, retrying...\n");
 397:             if (attn)
 398:                 attnmsg("Busy, retrying...\n");
 399:             CourierClose(conn);
 400:             sleep(15);
 401:             if (rewind(ipfile) < 0) {
 402:                 ExitStatus = X_LIMRETRY;
 403:                 attnmsg(stderr,"Can't rewind file\n");
 404:             }
 405:             goto again;
 406:         case ConnectionError:
 407:             ExitStatus = X_LIMRETRY;
 408:             attnmsg(stderr,"Connection error, %d\n",
 409:                 CourierErrArgs(ConnectionErrorArgs,problem));
 410:             break;
 411:         case InsufficientSpoolSpace:
 412:             attnmsg(stderr,"Insufficient Spool Space error\n");
 413:             break;
 414:         case InvalidPrintParameters:
 415:             ExitStatus = X_LIMRETRY;
 416:             attnmsg(stderr,"InvalidPrintParameters error\n");
 417:             break;
 418:         case MasterTooLarge:
 419:             ExitStatus=X_NORETRY;
 420:             attnmsg(stderr,"MasterTooLarge error\n");
 421:             break;
 422:         case MediumUnavailable:
 423:             ExitStatus=X_NORETRY;
 424:             attnmsg(stderr,"MediumUnavailable error\n");
 425:             break;
 426:         case ServiceUnavailable:
 427:             ExitStatus=X_NORETRY;
 428:             attnmsg(stderr,"ServiceUnavailable error\n");
 429:             break;
 430:         case SpoolingDisabled:
 431:             attnmsg(stderr,"SpoolingDisabled\n");
 432:             break;
 433:         case SpoolingQueueFull:
 434:             attnmsg(stderr,"SpoolingQueueFull error\n");
 435:             break;
 436:         case SystemError:
 437:             ExitStatus = X_LIMRETRY;
 438:             attnmsg(stderr,"System Error\n");
 439:             break;
 440:         case TooManyClients:
 441:             attnmsg(stderr,"TooManyClients error\n");
 442:             break;
 443:         case TransferError:
 444:             ExitStatus = X_LIMRETRY;
 445:             attnmsg(stderr,"TransferError error\n");
 446:             break;
 447:         case Undefined:
 448:             attnmsg(stderr,"Undefined error, number %d\n",
 449:                 CourierErrArgs(UndefinedArgs,problem));
 450:             break;
 451:         case REJECT_ERROR:
 452:             ExitStatus = X_LIMRETRY;
 453:             attnmsg(stderr,"REJECT:  type = %d\n",
 454:                 CourierErrArgs(rejectionDetails, designator));
 455:             break;
 456:         default:
 457:             ExitStatus = X_LIMRETRY;
 458:             attnmsg(stderr,"Some random error, code %d\n",
 459:                 Exception.Code);
 460:             break;
 461:         }
 462:         if(remove && !attn)
 463:             attnmsg(stderr,"Output left in %s\n", FileName);
 464:         exit(ExitStatus);
 465:     } END_HANDLER;
 466: 
 467:     CourierClose(conn);
 468: 
 469:     /* RETURNS [printRequestID: RequestID] */
 470:     if(remove) unlink(FileName);
 471: }

Defined functions

SendSource defined in line 47; used 1 times
attnmsg defined in line 327; used 36 times
checkIPstatus defined in line 202; used 1 times
main defined in line 84; never used
printresults defined in line 260; used 1 times
sendIPfile defined in line 347; used 1 times
setxnshost defined in line 75; used 1 times

Defined variables

Banner defined in line 70; used 4 times
ExitStatus defined in line 35; used 15 times
FileName defined in line 68; used 12 times
UserName defined in line 69; used 6 times
attn defined in line 66; used 14 times
attnfile defined in line 67; used 2 times
copies defined in line 71; used 2 times
quiet defined in line 65; used 13 times
remove defined in line 64; used 7 times
xnshost defined in line 73; used 14 times

Defined macros

X_GOOD defined in line 37; used 1 times
X_LIMRETRY defined in line 42; used 10 times
X_NORETRY defined in line 45; used 7 times
X_RETRY defined in line 39; used 1 times
Last modified: 1986-03-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2265
Valid CSS Valid XHTML 1.0 Strict