1*fbffadb9Smrg /* $NetBSD: lpf.c,v 1.15 2019/02/03 03:19:30 mrg Exp $ */
261f28255Scgd /*
3f881d1d4Scgd * Copyright (c) 1983, 1993
4f881d1d4Scgd * The Regents of the University of California. All rights reserved.
561f28255Scgd *
661f28255Scgd * Redistribution and use in source and binary forms, with or without
761f28255Scgd * modification, are permitted provided that the following conditions
861f28255Scgd * are met:
961f28255Scgd * 1. Redistributions of source code must retain the above copyright
1061f28255Scgd * notice, this list of conditions and the following disclaimer.
1161f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1261f28255Scgd * notice, this list of conditions and the following disclaimer in the
1361f28255Scgd * documentation and/or other materials provided with the distribution.
14326b2259Sagc * 3. Neither the name of the University nor the names of its contributors
1561f28255Scgd * may be used to endorse or promote products derived from this software
1661f28255Scgd * without specific prior written permission.
1761f28255Scgd *
1861f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1961f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2061f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2161f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2261f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2361f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2461f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2561f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2661f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2761f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2861f28255Scgd * SUCH DAMAGE.
2961f28255Scgd */
3061f28255Scgd
31fe7ed7ceSmrg #include <sys/cdefs.h>
3261f28255Scgd #ifndef lint
339c194566Slukem __COPYRIGHT("@(#) Copyright (c) 1983, 1993\
349c194566Slukem The Regents of the University of California. All rights reserved.");
354a711f6dSmikel #if 0
36f881d1d4Scgd static char sccsid[] = "@(#)lpf.c 8.1 (Berkeley) 6/6/93";
374a711f6dSmikel #else
38*fbffadb9Smrg __RCSID("$NetBSD: lpf.c,v 1.15 2019/02/03 03:19:30 mrg Exp $");
394a711f6dSmikel #endif
4061f28255Scgd #endif /* not lint */
4161f28255Scgd
4261f28255Scgd /*
4361f28255Scgd * filter which reads the output of nroff and converts lines
4461f28255Scgd * with ^H's to overwritten lines. Thus this works like 'ul'
4561f28255Scgd * but is much better: it can handle more than 2 overwrites
4661f28255Scgd * and it is written with some style.
4761f28255Scgd * modified by kls to use register references instead of arrays
4861f28255Scgd * to try to gain a little speed.
4961f28255Scgd */
5061f28255Scgd
5161f28255Scgd #include <signal.h>
529581f118Sthorpej #include <string.h>
53f881d1d4Scgd #include <unistd.h>
54f881d1d4Scgd #include <stdlib.h>
55f881d1d4Scgd #include <stdio.h>
5661f28255Scgd
5761f28255Scgd #define MAXWIDTH 132
5861f28255Scgd #define MAXREP 10
5961f28255Scgd
60257a846aSjoerg static char buf[MAXREP][MAXWIDTH];
61257a846aSjoerg static int maxcol[MAXREP] = {-1};
62257a846aSjoerg static int lineno;
63257a846aSjoerg static int width = 132; /* default line length */
64257a846aSjoerg static int length = 66; /* page length */
65257a846aSjoerg static int indent; /* indentation length */
66257a846aSjoerg static int npages = 1;
67257a846aSjoerg static int literal; /* print control characters */
68257a846aSjoerg static char *name; /* user's login name */
69257a846aSjoerg static char *host; /* user's machine name */
70257a846aSjoerg static char *acctfile; /* accounting information file */
71257a846aSjoerg static int crnl; /* \n -> \r\n */
72257a846aSjoerg static int need_cr;
7361f28255Scgd
74257a846aSjoerg __dead static void usage(void);
75fe7ed7ceSmrg
76f881d1d4Scgd int
main(int argc,char * argv[])77895dc72aSwiz main(int argc, char *argv[])
7861f28255Scgd {
79fe7ed7ceSmrg FILE *p = stdin, *o = stdout;
80fe7ed7ceSmrg int i, col;
81fe7ed7ceSmrg char *cp;
825b6d0e7eSmrg int done, linedone, maxrep, ch, prch;
83fe7ed7ceSmrg char *limit;
8461f28255Scgd
858eef858aSchristos while ((ch = getopt(argc, argv, "cfh:i:j:l:n:w:")) != -1)
866a7a9484Sabs switch (ch) {
8761f28255Scgd case 'n':
886a7a9484Sabs name = optarg;
8961f28255Scgd break;
9061f28255Scgd case 'h':
916a7a9484Sabs host = optarg;
9261f28255Scgd break;
9361f28255Scgd case 'w':
946a7a9484Sabs if ((i = atoi(optarg)) > 0 && i <= MAXWIDTH)
9561f28255Scgd width = i;
9661f28255Scgd break;
9761f28255Scgd case 'l':
986a7a9484Sabs length = atoi(optarg);
9961f28255Scgd break;
10061f28255Scgd case 'i':
1016a7a9484Sabs indent = atoi(optarg);
10261f28255Scgd break;
10361f28255Scgd case 'c': /* Print control chars */
10461f28255Scgd literal++;
10561f28255Scgd break;
1065b6d0e7eSmrg case 'f': /* Fix missing carriage returns */
1075b6d0e7eSmrg crnl++;
1085b6d0e7eSmrg break;
1098eef858aSchristos case 'j': /* ignore job name */
1108eef858aSchristos break;
1116a7a9484Sabs default:
1126a7a9484Sabs usage();
11361f28255Scgd }
1146a7a9484Sabs argc -= optind;
1156a7a9484Sabs argv += optind;
1166a7a9484Sabs if (argc)
1176a7a9484Sabs acctfile = *argv;
11861f28255Scgd
1196a7a9484Sabs memset(buf, ' ', sizeof(buf));
12061f28255Scgd done = 0;
12161f28255Scgd
12261f28255Scgd while (!done) {
12361f28255Scgd col = indent;
12461f28255Scgd maxrep = -1;
12561f28255Scgd linedone = 0;
1265b6d0e7eSmrg prch = ch = 0;
1275b6d0e7eSmrg need_cr = 0;
12861f28255Scgd while (!linedone) {
1295b6d0e7eSmrg prch = ch;
13061f28255Scgd switch (ch = getc(p)) {
13161f28255Scgd case EOF:
13261f28255Scgd linedone = done = 1;
13361f28255Scgd ch = '\n';
13461f28255Scgd break;
13561f28255Scgd
13661f28255Scgd case '\f':
13761f28255Scgd lineno = length;
138*fbffadb9Smrg /* FALLTHROUGH */
13961f28255Scgd case '\n':
1405b6d0e7eSmrg if (crnl && prch != '\r')
1415b6d0e7eSmrg need_cr = 1;
14261f28255Scgd if (maxrep < 0)
14361f28255Scgd maxrep = 0;
14461f28255Scgd linedone = 1;
14561f28255Scgd break;
14661f28255Scgd
14761f28255Scgd case '\b':
14861f28255Scgd if (--col < indent)
14961f28255Scgd col = indent;
15061f28255Scgd break;
15161f28255Scgd
15261f28255Scgd case '\r':
15361f28255Scgd col = indent;
15461f28255Scgd break;
15561f28255Scgd
15661f28255Scgd case '\t':
15761f28255Scgd col = ((col - indent) | 07) + indent + 1;
15861f28255Scgd break;
15961f28255Scgd
16061f28255Scgd case '\031':
16161f28255Scgd /*
16261f28255Scgd * lpd needs to use a different filter to
16361f28255Scgd * print data so stop what we are doing and
16461f28255Scgd * wait for lpd to restart us.
16561f28255Scgd */
16661f28255Scgd if ((ch = getchar()) == '\1') {
16761f28255Scgd fflush(stdout);
16861f28255Scgd kill(getpid(), SIGSTOP);
16961f28255Scgd break;
17061f28255Scgd } else {
17161f28255Scgd ungetc(ch, stdin);
17261f28255Scgd ch = '\031';
17361f28255Scgd }
17461f28255Scgd
175*fbffadb9Smrg /* FALLTHROUGH */
17661f28255Scgd default:
1774a711f6dSmikel if (col >= width || (!literal && ch < ' ')) {
17861f28255Scgd col++;
17961f28255Scgd break;
18061f28255Scgd }
18161f28255Scgd cp = &buf[0][col];
18261f28255Scgd for (i = 0; i < MAXREP; i++) {
18361f28255Scgd if (i > maxrep)
18461f28255Scgd maxrep = i;
18561f28255Scgd if (*cp == ' ') {
18661f28255Scgd *cp = ch;
18761f28255Scgd if (col > maxcol[i])
18861f28255Scgd maxcol[i] = col;
18961f28255Scgd break;
19061f28255Scgd }
19161f28255Scgd cp += MAXWIDTH;
19261f28255Scgd }
19361f28255Scgd col++;
19461f28255Scgd break;
19561f28255Scgd }
19661f28255Scgd }
19761f28255Scgd
19861f28255Scgd /* print out lines */
19961f28255Scgd for (i = 0; i <= maxrep; i++) {
20061f28255Scgd for (cp = buf[i], limit = cp+maxcol[i]; cp <= limit;) {
20161f28255Scgd putc(*cp, o);
20261f28255Scgd *cp++ = ' ';
20361f28255Scgd }
20461f28255Scgd if (i < maxrep)
20561f28255Scgd putc('\r', o);
2065b6d0e7eSmrg else {
2075b6d0e7eSmrg if (need_cr)
2085b6d0e7eSmrg putc('\r', o);
20961f28255Scgd putc(ch, o);
2105b6d0e7eSmrg }
21161f28255Scgd if (++lineno >= length) {
21261f28255Scgd fflush(o);
21361f28255Scgd npages++;
21461f28255Scgd lineno = 0;
21561f28255Scgd }
21661f28255Scgd maxcol[i] = -1;
21761f28255Scgd }
21861f28255Scgd }
21961f28255Scgd if (lineno) { /* be sure to end on a page boundary */
22061f28255Scgd putchar('\f');
22161f28255Scgd npages++;
22261f28255Scgd }
22361f28255Scgd if (name && acctfile && access(acctfile, 02) >= 0 &&
22461f28255Scgd freopen(acctfile, "a", stdout) != NULL) {
22561f28255Scgd printf("%7.2f\t%s:%s\n", (float)npages, host, name);
22661f28255Scgd }
22761f28255Scgd exit(0);
22861f28255Scgd }
2296a7a9484Sabs
230257a846aSjoerg static void
usage(void)231895dc72aSwiz usage(void)
2326a7a9484Sabs {
2336a7a9484Sabs fprintf(stderr,
2346a7a9484Sabs "usage: lpf [-c] [-f] [-h host] [-i indent] [-l length] [-n name] [-w width] [acctfile]\n");
2356a7a9484Sabs exit(1);
2366a7a9484Sabs
2376a7a9484Sabs }
2386a7a9484Sabs
239