From: peter@martha.informatik.rwth-aachen.de (Peter Heimann)
Subject: Re: Help! pac does'nt work
Keywords: pac, printer accounting
Reply-To: peter@rwthi3.informatik.rwth-aachen.de
Organization: Informatik III, RWTH Aachen
Date: 27 Jul 92 11:49:28 GMT

In <1992Jul22.175929.12505@Logibec.COM> guy@Logibec.COM (Guy Thibault) writes:
>I try to use the command pac and the resuslt is always
>  Login               pages/feet   runs    price
>total                       0.00    0   $  0.00

In the BSD printer spooling system, the input filter has to write the page
accounting entries. In the standard SunOS distribution, no filter for this
purpose is provided.

A while ago, I simplified the vpf filter from the freely available
BSD sources and turned it into a simple input filter for line printers -
see code below.
Compile, install the filter in /usr/local/bin (or wherever you put local
enhancements and optional software) and add
	:af=/var/adm/lp.acct:\
	:if=/usr/local/bin/ipf:
to the /etc/printcap file.

--- Peter Heimann

Lehrstuhl fuer Informatik III	    peter@rwthi3.informatik.rwth-aachen.de
RWTH Aachen

------- cut here - c program follows -------------------------------------
/* ipf
 * A simple pass-through input filter for line printers
 * Does page accounting, expands tabs, indents, chops long lines.
 *
 * 11.11.1991
 *   Peter Heimann, Lehrstuhl fuer Informatik III, RWTH Aachen
 *   peter@rwthi3.informatik.rwth-aachen.de
 *
 * Tested on Sun3 (SunOS 4.0.3) and Sun4 (SunOS 4.1.1+4.1.2)
 * Use this code at your own risk.
 *
 * Based on ideas from the BSD vpf filter,
 *   Copyright (c) 1983 Regents of the University of California.
 *   All rights reserved.
 */

#include <stdio.h>

#define LINELN 140

int	lineno;
int	width = 132;	/* default line length */
int	indent = 0;	/* default indent length */
int	length = 72;	/* 72 for 12" long paper */
int	npages = 0;
int	literal;
char	*name;		/* user's login name */
char	*host;		/* user's machine name */
char	*acctfile;	/* accounting information file */

main(argc, argv)
	int argc;
	char *argv[];
{
	register int i;

	while (--argc) {
		if (*(*++argv) == '-') {
			switch (argv[0][1]) {
			case 'n':
				argc--;
				name = *++argv;
				break;

			case 'h':
				argc--;
				host = *++argv;
				break;

			case 'w':
				if ((i = atoi(&argv[0][2])) > 0 && i < LINELN)
					width = i;
				break;

			case 'l':
				length = atoi(&argv[0][2]);
				break;

			case 'i':
				if ((i = atoi(&argv[0][2])) >= 0 &&
				    i < LINELN - 1)
					indent = i;
				break;

			case 'c':	/* Print input without throwing away
					   control chars and without putting
					   in page breaks. */
				literal++;
				break;
			}
		} else
			acctfile = *argv;
	}
	filter();
	if (name && acctfile && access(acctfile, 02) >= 0 &&
	    freopen(acctfile, "a", stdout) != NULL) {
		printf("%7.2f\t%s:%s\n", (float)npages, host, name);
	}
	exit(0);
}

filter()
{
	register int c, col;

	lineno = 0;
	col = 0;
	while ((c = getchar()) != EOF)
	{
	    /* put out spaces for indentation */
	    while ((col < indent) && (col < width))
	    {   
		putchar(' '); col++;
	    }

	    switch(c)
	    {
	    case '\f':
		    lineno = length - 1;
		    /* fall through, ff is line break too */
	    case '\n':
		    col = 0;
		    if (++lineno % length == 0)
			npages++;
		    putchar(c);
		    continue;
	    case '\r':
		    col = 0;
		    putchar(c);
		    continue;
	    case '\b':
		    if (col > 0)
		    {
			col--;
			putchar(c);
		    }
		    continue;
	    case '\t':
		    if (! literal)
		    {
			do
			{
			    putchar(' '); col++;
			}
			while ((col % 8 != 0) && (col < width));
		    }
		    continue;
	    default:
		    /* discard control chars, cut off long lines */
		    if (((c >= ' ') && (col < width)) || literal)
		    {
			putchar(c); col++;
		    }
		    continue;
	    }
	}

	/* finish the job with a formfeed, if not already on page boundary */
	if ((lineno % length != 0) || (col > 0))
	{
	    npages++;
	    putchar('\f');
	}

	if (ferror(stdout))
	    exit(1);
} /* filter() */