[comp.protocols.appletalk] banner pages with CAP?

cck@cunixc.columbia.EDU (Charlie C. Kim) (01/26/88)

The input filter is supposed to process a file called ".banner"
created by the output filter.  papif doesn't process the .banner file.
lnof doesn't create one.

To do things correctly, papif needs to be modified.  (The banner
should go down in the same job stream to prevent interleaving of pages
from other jobs).  Transcript's psbanner program can be used, but some
care needs to be taken (with all the transcript programs).

This is a very very low priority here since we have policy of no text
printing unless absolutely necessary on our LaserWriter.

Charlie C. Kim
User Services
Columbia University

ddl@husc6.harvard.edu (Dan Lanciani) (02/01/88)

In article <8801261521.AA02893@columbia.edu>, cck@cunixc.columbia.EDU (Charlie C. Kim) writes:
| The input filter is supposed to process a file called ".banner"
| created by the output filter.  papif doesn't process the .banner file.
| lnof doesn't create one.

	Strangely, the version of lnof we got does create one.

| To do things correctly, papif needs to be modified.  (The banner
| should go down in the same job stream to prevent interleaving of pages
| from other jobs).  Transcript's psbanner program can be used, but some
| care needs to be taken (with all the transcript programs).

	I modified papif to grind lpd's standard banner through pstext
because I didn't like the idea of parsing the "short-form" lpr banner
to recover the information to print a fancy burst page.  (Though I never
understood why Transcript does this rather than using the appropriate
arguments.)  I also added to papif the ability to return output from
a job to its originator, although this uses a feature of lpd that
seems to have changed in real 4.3.  Sigh.  Anyway, here are some
context diffs; use part or all at your own risk...
	By the way, has anyone noticed that leaving the STATUS feature
enabled reduces reliability?

				Dan Lanciani
				ddl@harvard.*

*** /usr/src/local/at/cap/samples/papif.c	Sat Jan 16 22:07:00 1988
--- /users/isr/isr-staff/staffs/ddl/src/cap/papif.c	Sat Jan 30 20:11:03 1988
***************
*** 1,6 ****
! static char rcsid[] = "$Author: cck $ $Date: 87/08/06 17:48:02 $";
! static char rcsident[] = "$Header: papif.c,v 1.24 87/08/06 17:48:02 cck Rel $";
! static char revision[] = "$Revision: 1.24 $";
  
  /*
   * papif - UNIX AppleTalk test program: simple line printer input filter 
--- 1,5 ----
! #define PSTEXT "/usr/vendor/lib/ps/pstext"
! #define NOSTATUS
  
  /*
   * papif - UNIX AppleTalk test program: simple line printer input filter 
***************
*** 45,51 ****
  int cno;
  int ppid;
  int pid;
! char host[30],printer[30],user[30];
  #define RFLOWQ 8
  #ifndef SFLOWQ
  # define SFLOWQ 8
--- 44,50 ----
  int cno;
  int ppid;
  int pid;
! char host[30],printer[30],user[30],group[30];
  #define RFLOWQ 8
  #ifndef SFLOWQ
  # define SFLOWQ 8
***************
*** 56,61 ****
--- 55,62 ----
  char rbuf[BUFMAX+10];
  int xdebug = TRUE;
  char *ptime();
+ FILE *pout;
+ int didout;
  
  /* quit gets called when we've been killed by lprm via SIGINT */
  quit()
***************
*** 91,96 ****
--- 92,100 ----
        case 'p':			/* printer name */
  	strcpy(printer,argv[++i]);
  	break;
+       case 'g':			/* group name */
+ 	strcpy(group,argv[++i]);
+ 	break;
        case 'n':			/* user name */
  	strcpy(user,argv[++i]);
  	break;
***************
*** 122,128 ****
--- 126,134 ----
      strcpy(printer, pgmname);
  }
  
+ char tname[] = "/tmp/papifXXXXXX";
  
+ 
  /*
   * our "input" filter - send input to laserwriter
   *
***************
*** 166,171 ****
--- 172,181 ----
    nbpInit();
    PAPInit();			/* init PAP printer routines */
  
+   mktemp(tname);
+   if(!(pout = fopen(tname, "w")))
+     pout = stderr;
+ 
    /* log message */
    fprintf(stderr,"PAPIF: Starting job for %s@%s at %s on printer %s\n",
  	  user,host,ptime(),lwname);
***************
*** 175,187 ****
  #endif
    signal(SIGINT,quit);		/* this is what lprm sends us */
  
- #ifdef notdef
-   if ((bannerfd = open(".banner", 0)) >= 0) {
-     sendbanner(ptr, bannerfd); /* don't care if we can't send it */
-     close(bannerfd);
-   }
- #endif
- 
    cno = openlw(lwname);
  
  #ifndef NOSTATUS
--- 185,190 ----
***************
*** 202,212 ****
--- 205,235 ----
  
    sendfile(cno);		/* send file to laserwriter */
  
+ #ifdef PSTEXT
+   close(0);
+   wait(0);
+   if (!index(host, '@') && !open(".banner", 0)) {
+     pstext();
+     sendfile(cno);
+   }
+ #endif
+ 
    epc = getpagecount(cno);	/* get the page count */
    PAPClose(cno);
  
    if (acctfile != NULL)
      doacct(spc, epc, acctfile, user, host);
+   if(pout != stderr) {
+     fclose(pout);
+     if(didout || index(host, '@')) {
+       if(!fork()) {
+ 	execl("/usr/local/bin/returnfile", "returnfile", host, user, tname, 0);
+ 	exit(1);
+       }
+     }
+     else
+       unlink(tname);
+   }
    exit(lpd_OK);			/* exit okay */
  }
  
***************
*** 320,327 ****
  	fprintf(stderr,"PAPRead error %d\n",rcomp);
  	break;
        } else if (rlen > 0) {
! 	rbuf[rlen] = '\0';
! 	fprintf(stderr,"%s",rbuf);
        }
        paperr = PAPRead(cno, rbuf, &rlen, &eof, &rcomp);
        if (paperr < 0) {
--- 343,350 ----
  	fprintf(stderr,"PAPRead error %d\n",rcomp);
  	break;
        } else if (rlen > 0) {
! 	write(fileno(pout), rbuf, rlen);
! 	didout = 1;
        }
        paperr = PAPRead(cno, rbuf, &rlen, &eof, &rcomp);
        if (paperr < 0) {
***************
*** 353,360 ****
  	fprintf(stderr,"PAPRead error %d\n",rcomp);
  	break;
        } else if (rlen > 0) {
! 	rbuf[rlen] = '\0';
! 	fprintf(stderr,"%s",rbuf);
        }
        if (eof) break;
        PAPRead(cno, rbuf, &rlen, &eof, &rcomp);
--- 376,383 ----
  	fprintf(stderr,"PAPRead error %d\n",rcomp);
  	break;
        } else if (rlen > 0) {
! 	write(fileno(pout), rbuf, rlen);
! 	didout = 1;
        }
        if (eof) break;
        PAPRead(cno, rbuf, &rlen, &eof, &rcomp);
***************
*** 423,429 ****
    if (epc >= spc && epc > 0 && spc > 0)  {
      if (user[0] != '\0' && acctfile && access(acctfile, 02) >= 0 &&
  	(afd = fopen(acctfile, "a")) != NULL)
!       fprintf(afd,"%7.2f\t%s:%s\n", (float)(epc-spc), host, user);
    } else
      fprintf(stderr, "Problems getting pagecount: start %d, end %d\n",spc,epc);
  }
--- 446,452 ----
    if (epc >= spc && epc > 0 && spc > 0)  {
      if (user[0] != '\0' && acctfile && access(acctfile, 02) >= 0 &&
  	(afd = fopen(acctfile, "a")) != NULL)
!       fprintf(afd,"%7.2f %-16s %-20s %-8s\n", (float)(epc-spc), host, group, user);
    } else
      fprintf(stderr, "Problems getting pagecount: start %d, end %d\n",spc,epc);
  }
***************
*** 553,559 ****
  	  for (i = 0 ; i < NSIG ; i++)
  	    signal(i, SIG_IGN);
  	  sprintf(retry,
! 		  "(sleep 2;/etc/lpc abort %s;sleep 2;/etc/lpc start %s)&", 
  		  printer, printer);
  	  system(retry);
  	  exit(lpd_REPRINT);
--- 576,582 ----
  	  for (i = 0 ; i < NSIG ; i++)
  	    signal(i, SIG_IGN);
  	  sprintf(retry,
! 		  "(sleep 3;/etc/lpc abort %s;sleep 3;/etc/lpc start %s)&", 
  		  printer, printer);
  	  system(retry);
  	  exit(lpd_REPRINT);
***************
*** 564,569 ****
      }
  #endif IDLESTUFF
      pstatus(status.StatusStr);
!     sleep(10);			/* update every 10 seconds */
    } while (1);
  }
--- 587,592 ----
      }
  #endif IDLESTUFF
      pstatus(status.StatusStr);
!     sleep(30);			/* update every 10 seconds */
    } while (1);
  }

mkupfer@acornrc.UUCP (Mike Kupfer) (02/03/88)

Brad Smith from UC Santa Cruz sent me a hacked version of papif that
produces banner pages in conjunction with psbanner.  I hacked on that
version some more, and the resulting diffs are appended to this
message.

This version, unlike Dan Lanciani's recent posting, uses psbanner to
produce the banner.  Another difference is that it lets you control
whether the banner is produced before or after the actual job
(depending on how your printer stacks its output).  There are also
some changes that I put in to better handle the "idle printer" problem
and to make lint happier.

Once again, thanks to all who replied to my original query.

Mike Kupfer
Olivetti Research Center			415-496-6238
orc!kupfer@unix.sri.com				...!oliveb!orc!kupfer
...!{decwrl, ames}!acornrc!mkupfer		...!ucbvax!kupfer

========== sample printcap entry ==========
lp|ps|PostScript|OliWriter (LaserWriter):\
        :lp=/dev/null:if=/usr/local/lib/lp:\
        :sd=/usr/spool/lpd:sb:\
        :of=/usr/local/lib/ps/psof:\
        :lf=/usr/adm/lp-errs:\
        :af=/usr/adm/lp.acct:

========== samples/INSTALLATION diffs ==========
*** INSTALLATION.orig	Tue Feb  2 14:02:18 1988
--- INSTALLATION	Tue Feb  2 14:01:36 1988
***************
*** 1,3 ****
--- 1,6 ----
+ 
+ @(#)INSTALLATION	2.1	(ORC) 1/28/88
+ 
  General notes:
  
  tlw, papif, lwpr, iwpr now have a settable "Send Flow Quantum
***************
*** 46,53 ****
  	/etc/printcap.
  	(b) make a copy or a hard or symbolic link to papif.  papif
  	will take the program name (if not papif) as the unix printer
! 	name.  point to the copy instead of papif in /etc/printcap
! (b) is the recommended method.
  
  LWSRV
  -----
--- 49,70 ----
  	/etc/printcap.
  	(b) make a copy or a hard or symbolic link to papif.  papif
  	will take the program name (if not papif) as the unix printer
! 	name.  point to the copy instead of papif in /etc/printcap.
! (b) is the recommended method, unless you want a banner page to be produced
! with each print job (see next paragraph).
! 
! If you are using Transcript and you want a banner page to be produced
! with each job, you must use method (a) (see previous paragraph).  This script
! should set either $BANNERFIRST or $BANNERLAST to 1, depending on which way
! your printer stacks the output.  For example, the script:
! 
! 	#! /bin/sh
! 	BANNERFIRST=1
! 	BANNERLAST=0
! 	export BANNERFIRST BANNERLAST 
! 	/usr/local/cap/papif ${*} -p lp
! 
! will generate a banner page before each job is printed.
  
  LWSRV
  -----

========== papif.c diffs ==========
*** papif.c.old	Tue Feb  2 14:47:36 1988
--- papif.c	Tue Feb  2 14:54:22 1988
***************
*** 1,6 ****
--- 1,9 ----
+ #ifndef lint
  static char rcsid[] = "$Author: cck $ $Date: 87/08/06 17:48:02 $";
  static char rcsident[] = "$Header: papif.c,v 1.24 87/08/06 17:48:02 cck Rel $";
  static char revision[] = "$Revision: 1.24 $";
+ static char orcid[] = "@(#)papif.c	2.2	(ORC) 2/2/88";
+ #endif
  
  /*
   * papif - UNIX AppleTalk test program: simple line printer input filter 
***************
*** 20,26 ****
--- 23,31 ----
   *
   */
  
+ #ifndef lint
  char copyright[] = "Copyright (c) 1986, 1987 by The Trustees of Columbia University in the City of New York";
+ #endif
  
  #include <stdio.h>
  #include <sys/types.h>
***************
*** 41,47 ****
  #define	lpd_REPRINT	1	/* forces a reprint */
  #define lpd_ERRORS	2	/* printed with errors */
  
- char *fname ;
  int cno;
  int ppid;
  int pid;
--- 46,51 ----
***************
*** 124,129 ****
--- 128,171 ----
  
  
  /*
+  * If "envname" is defined in the environment, then send a banner
+  * to the printer.
+  */
+ void
+ maybesendbanner(cno, envname)
+ int cno;			/* connection to printer */
+ char *envname;
+ {
+   int bannerfd;
+   void sendbanner();
+   extern char *getenv();
+   char *s;			/* value of envname, usually "0" or "1" */
+ 
+   s = getenv(envname);
+   if (s == (char *)NULL || atoi(s) == 0)
+     return;
+ 
+   if ((bannerfd = open(".banner", 0)) >= 0) {
+     sendbanner(cno, bannerfd); /* don't care if we can't send it */
+     close(bannerfd);
+   }
+ }
+ 
+ void
+ sendbanner(cno, bfd)
+ int bfd;			/* Banner file descriptor */
+ int cno;
+ {
+   int tfd;
+ 
+   tfd = dup(fileno(stdin));
+   dup2(bfd, fileno(stdin));
+   sendfile(cno);
+   dup2(tfd, fileno(stdin));
+ }
+ 
+ 
+ /*
   * our "input" filter - send input to laserwriter
   *
   * stdin - input
***************
*** 130,135 ****
--- 172,178 ----
   * stdout - points to devices, empty here
   * stderr - points to log file on BSD4.2, Ultrix 1.0 through Ultrix 1.2
   *        - points to "err" tmp file on BSD 4.3
+  * environment - BANNERFIRST, BANNERLAST
   *
   * Exit codes are listed above
   *
***************
*** 175,187 ****
  #endif
    signal(SIGINT,quit);		/* this is what lprm sends us */
  
- #ifdef notdef
-   if ((bannerfd = open(".banner", 0)) >= 0) {
-     sendbanner(ptr, bannerfd); /* don't care if we can't send it */
-     close(bannerfd);
-   }
- #endif
- 
    cno = openlw(lwname);
  
  #ifndef NOSTATUS
--- 218,223 ----
***************
*** 192,198 ****
    }
    if (pid)			/* status process */
      statuswatch(lwname, cno);
- 
  #endif
  
    spc = getpagecount(cno);	/* get the page count */
--- 228,233 ----
***************
*** 200,207 ****
    pstext();			/* convert text to postscript */
  #endif
  
    sendfile(cno);		/* send file to laserwriter */
! 
    epc = getpagecount(cno);	/* get the page count */
    PAPClose(cno);
  
--- 235,243 ----
    pstext();			/* convert text to postscript */
  #endif
  
+   maybesendbanner(cno, "BANNERFIRST");
    sendfile(cno);		/* send file to laserwriter */
!   maybesendbanner(cno, "BANNERLAST");
    epc = getpagecount(cno);	/* get the page count */
    PAPClose(cno);
  
***************
*** 299,305 ****
  #endif PSTEXT
  
  /*
!  * Send a file to the specified connection
   */
  sendfile(cno)
  int cno;
--- 335,341 ----
  #endif PSTEXT
  
  /*
!  * Send a file from stdin to the specified connection (cno).
   */
  sendfile(cno)
  int cno;
***************
*** 346,352 ****
  
    if (err < 0)			/* this is a little overloaded */
      perror("read");
!   paperr = PAPWrite(cno, NULL, 0, TRUE, &wcomp); /* send eof */
    while (!eof) {		/* wait for completion */
      if (rcomp <= 0) {
        if (rcomp != noErr)  {
--- 382,388 ----
  
    if (err < 0)			/* this is a little overloaded */
      perror("read");
!   paperr = PAPWrite(cno, (char *)NULL, 0, TRUE, &wcomp); /* send eof */
    while (!eof) {		/* wait for completion */
      if (rcomp <= 0) {
        if (rcomp != noErr)  {
***************
*** 376,382 ****
  int cno;
  {
    static char gpcstr[] = "statusdict begin pagecount (*) print == ";
!   char buf[100];		/* enough for page count! */
    char *p;
    int err, wcomp, rlen, eof, rcomp, started;
  
--- 412,418 ----
  int cno;
  {
    static char gpcstr[] = "statusdict begin pagecount (*) print == ";
!   char countbuf[100];		/* enough for page count! */
    char *p;
    int err, wcomp, rlen, eof, rcomp, started;
  
***************
*** 395,403 ****
  	  started = 1;
  	  p = index(rbuf, '*');	/* look for marker */
  	  if (p != NULL) 
! 	    strcpy(buf, p+1);
  	} else
! 	  strcat(buf, p);
        }
        if (eof)
  	break;
--- 431,439 ----
  	  started = 1;
  	  p = index(rbuf, '*');	/* look for marker */
  	  if (p != NULL) 
! 	    strcpy(countbuf, p+1);
  	} else
! 	  strcat(countbuf, p);
        }
        if (eof)
  	break;
***************
*** 407,413 ****
      }
      abSleep(4, TRUE);
    } while (!eof);
!   return(atoi(buf));
  }
  
  /*
--- 443,449 ----
      }
      abSleep(4, TRUE);
    } while (!eof);
!   return(atoi(countbuf));
  }
  
  /*
***************
*** 454,460 ****
  hangup()
  {
    union wait status;
!   while (wait3(&status, WNOHANG, 0) > 0) ;
    fprintf(stderr,"Finished job at %s\n",ptime());
    fflush(stderr);
    exit(lpd_OK);			/* exit */
--- 490,496 ----
  hangup()
  {
    union wait status;
!   while (wait3(&status, WNOHANG, (struct rusage *)0) > 0) ;
    fprintf(stderr,"Finished job at %s\n",ptime());
    fflush(stderr);
    exit(lpd_OK);			/* exit */
***************
*** 466,475 ****
  char *
  ptime()
  {
!   long clock;
    char *timestr;
  
!   clock = time(0);
    timestr = (char *)asctime(localtime(&clock));
    timestr[24] = '\0';			/* pretty hooky - but it works */
    return(timestr);
--- 502,512 ----
  char *
  ptime()
  {
!   time_t clock;
    char *timestr;
+   extern time_t time();
  
!   clock = time((time_t *)0);
    timestr = (char *)asctime(localtime(&clock));
    timestr[24] = '\0';			/* pretty hooky - but it works */
    return(timestr);
***************
*** 486,492 ****
  char *printer;
  {
    FILE *fd;
!   static char buf[256];
    char *ep;
  
    if (printer[0] == '\0')
--- 523,529 ----
  char *printer;
  {
    FILE *fd;
!   static char namebuf[256];
    char *ep;
  
    if (printer[0] == '\0')
***************
*** 497,511 ****
      return(NULL);
    }
    do {
!     if (fgets(buf, 256, fd) == NULL)
        break;
!     buf[strlen(buf)-1] = '\0';	/* get rid of the lf */
!     if (buf[0] == '#' || buf[0] == '\0')
        continue;
!     if ((ep=index(buf,'=')) == NULL) /* find first = */
        continue;			/* no = in string */
      *ep = '\0';			/* set = to null now */
!     if (strcmp(buf,printer) == 0) {
        if (strlen(ep+1) == 0)	/* no name */
  	continue;
        fclose(fd);
--- 534,548 ----
      return(NULL);
    }
    do {
!     if (fgets(namebuf, 256, fd) == NULL)
        break;
!     namebuf[strlen(namebuf)-1] = '\0';	/* get rid of the lf */
!     if (namebuf[0] == '#' || namebuf[0] == '\0')
        continue;
!     if ((ep=index(namebuf,'=')) == NULL) /* find first = */
        continue;			/* no = in string */
      *ep = '\0';			/* set = to null now */
!     if (strcmp(namebuf,printer) == 0) {
        if (strlen(ep+1) == 0)	/* no name */
  	continue;
        fclose(fd);
***************
*** 517,525 ****
  }
  
  /*
!  * Listens for status messages from lw
   *
  */
  statuswatch(lwname, cno)
  char *lwname;
  int cno;
--- 554,563 ----
  }
  
  /*
!  * Listens for status messages from lw every SLEEPTIME seconds. 
   *
  */
+ #define	SLEEPTIME	10
  statuswatch(lwname, cno)
  char *lwname;
  int cno;
***************
*** 527,532 ****
--- 565,573 ----
    AddrBlock addr;
    int hangup();
    PAPStatusRec status;
+ #ifdef IDLESTUFF
+   int idleSeconds = 0;		/* num of seconds printer is idle so far */
+ #endif
    
    PAPHalfClose(cno);
    signal(SIGCHLD, hangup);
***************
*** 534,539 ****
--- 575,585 ----
    do {
      PAPStatus(lwname, &status, &addr);
  #ifdef IDLESTUFF
+     /*
+      * If the printer has been idle for more than MAXIDLE seconds, then assume
+      * that something is hung.  Kill the current daemon and restart it.
+      */
+ #define	MAXIDLE		60
      {
        int i;
        char retry[128];
***************
*** 540,547 ****
        char tmpbuf[255];
  
        cpyp2cstr(tmpbuf, status.StatusStr);
!       if (strncmp("status: idle", tmpbuf, 12) == 0
! 	  || access("/tmp/papifidletest", F_OK) == 0) {
  	fprintf(stderr,"PAPIF:  status: idle bug; restarting\n");
  	fflush(stderr);
  	unlink("/tmp/papifidletest");
--- 586,596 ----
        char tmpbuf[255];
  
        cpyp2cstr(tmpbuf, status.StatusStr);
!       if (strncmp("status: idle", tmpbuf, 12) == 0)
!         idleSeconds += SLEEPTIME;
!       else
! 	idleSeconds = 0;
!       if (idleSeconds > MAXIDLE || access("/tmp/papifidletest", F_OK) == 0) {
  	fprintf(stderr,"PAPIF:  status: idle bug; restarting\n");
  	fflush(stderr);
  	unlink("/tmp/papifidletest");
***************
*** 556,561 ****
      }
  #endif IDLESTUFF
      pstatus(status.StatusStr);
!     sleep(10);			/* update every 10 seconds */
!   } while (1);
  }
--- 605,610 ----
      }
  #endif IDLESTUFF
      pstatus(status.StatusStr);
!     sleep(SLEEPTIME);
!   } while (1);			/* breaks out of loop via SIGCHLD */
  }