xref: /original-bsd/usr.sbin/lpr/filters/lpf.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1983, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1983, 1993\n\
11 	The Regents of the University of California.  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)lpf.c	8.1 (Berkeley) 06/06/93";
16 #endif /* not lint */
17 
18 /*
19  * 	filter which reads the output of nroff and converts lines
20  *	with ^H's to overwritten lines.  Thus this works like 'ul'
21  *	but is much better: it can handle more than 2 overwrites
22  *	and it is written with some style.
23  *	modified by kls to use register references instead of arrays
24  *	to try to gain a little speed.
25  */
26 
27 #include <signal.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 
32 #define MAXWIDTH  132
33 #define MAXREP    10
34 
35 char	buf[MAXREP][MAXWIDTH];
36 int	maxcol[MAXREP] = {-1};
37 int	lineno;
38 int	width = 132;	/* default line length */
39 int	length = 66;	/* page length */
40 int	indent;		/* indentation length */
41 int	npages = 1;
42 int	literal;	/* print control characters */
43 char	*name;		/* user's login name */
44 char	*host;		/* user's machine name */
45 char	*acctfile;	/* accounting information file */
46 
47 int
48 main(argc, argv)
49 	int argc;
50 	char *argv[];
51 {
52 	register FILE *p = stdin, *o = stdout;
53 	register int i, col;
54 	register char *cp;
55 	int done, linedone, maxrep;
56 	char ch, *limit;
57 
58 	while (--argc) {
59 		if (*(cp = *++argv) == '-') {
60 			switch (cp[1]) {
61 			case 'n':
62 				argc--;
63 				name = *++argv;
64 				break;
65 
66 			case 'h':
67 				argc--;
68 				host = *++argv;
69 				break;
70 
71 			case 'w':
72 				if ((i = atoi(&cp[2])) > 0 && i <= MAXWIDTH)
73 					width = i;
74 				break;
75 
76 			case 'l':
77 				length = atoi(&cp[2]);
78 				break;
79 
80 			case 'i':
81 				indent = atoi(&cp[2]);
82 				break;
83 
84 			case 'c':	/* Print control chars */
85 				literal++;
86 				break;
87 			}
88 		} else
89 			acctfile = cp;
90 	}
91 
92 	for (cp = buf[0], limit = buf[MAXREP]; cp < limit; *cp++ = ' ');
93 	done = 0;
94 
95 	while (!done) {
96 		col = indent;
97 		maxrep = -1;
98 		linedone = 0;
99 		while (!linedone) {
100 			switch (ch = getc(p)) {
101 			case EOF:
102 				linedone = done = 1;
103 				ch = '\n';
104 				break;
105 
106 			case '\f':
107 				lineno = length;
108 			case '\n':
109 				if (maxrep < 0)
110 					maxrep = 0;
111 				linedone = 1;
112 				break;
113 
114 			case '\b':
115 				if (--col < indent)
116 					col = indent;
117 				break;
118 
119 			case '\r':
120 				col = indent;
121 				break;
122 
123 			case '\t':
124 				col = ((col - indent) | 07) + indent + 1;
125 				break;
126 
127 			case '\031':
128 				/*
129 				 * lpd needs to use a different filter to
130 				 * print data so stop what we are doing and
131 				 * wait for lpd to restart us.
132 				 */
133 				if ((ch = getchar()) == '\1') {
134 					fflush(stdout);
135 					kill(getpid(), SIGSTOP);
136 					break;
137 				} else {
138 					ungetc(ch, stdin);
139 					ch = '\031';
140 				}
141 
142 			default:
143 				if (col >= width || !literal && ch < ' ') {
144 					col++;
145 					break;
146 				}
147 				cp = &buf[0][col];
148 				for (i = 0; i < MAXREP; i++) {
149 					if (i > maxrep)
150 						maxrep = i;
151 					if (*cp == ' ') {
152 						*cp = ch;
153 						if (col > maxcol[i])
154 							maxcol[i] = col;
155 						break;
156 					}
157 					cp += MAXWIDTH;
158 				}
159 				col++;
160 				break;
161 			}
162 		}
163 
164 		/* print out lines */
165 		for (i = 0; i <= maxrep; i++) {
166 			for (cp = buf[i], limit = cp+maxcol[i]; cp <= limit;) {
167 				putc(*cp, o);
168 				*cp++ = ' ';
169 			}
170 			if (i < maxrep)
171 				putc('\r', o);
172 			else
173 				putc(ch, o);
174 			if (++lineno >= length) {
175 				fflush(o);
176 				npages++;
177 				lineno = 0;
178 			}
179 			maxcol[i] = -1;
180 		}
181 	}
182 	if (lineno) {		/* be sure to end on a page boundary */
183 		putchar('\f');
184 		npages++;
185 	}
186 	if (name && acctfile && access(acctfile, 02) >= 0 &&
187 	    freopen(acctfile, "a", stdout) != NULL) {
188 		printf("%7.2f\t%s:%s\n", (float)npages, host, name);
189 	}
190 	exit(0);
191 }
192