lpf.c revision 1.6.8.1 1 /* $NetBSD: lpf.c,v 1.6.8.1 1999/12/27 18:37:51 wrstuden Exp $ */
2 /*
3 * Copyright (c) 1983, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 #ifndef lint
37 __COPYRIGHT("@(#) Copyright (c) 1983, 1993\n\
38 The Regents of the University of California. All rights reserved.\n");
39 #if 0
40 static char sccsid[] = "@(#)lpf.c 8.1 (Berkeley) 6/6/93";
41 #else
42 __RCSID("$NetBSD: lpf.c,v 1.6.8.1 1999/12/27 18:37:51 wrstuden Exp $");
43 #endif
44 #endif /* not lint */
45
46 /*
47 * filter which reads the output of nroff and converts lines
48 * with ^H's to overwritten lines. Thus this works like 'ul'
49 * but is much better: it can handle more than 2 overwrites
50 * and it is written with some style.
51 * modified by kls to use register references instead of arrays
52 * to try to gain a little speed.
53 */
54
55 #include <signal.h>
56 #include <unistd.h>
57 #include <stdlib.h>
58 #include <stdio.h>
59
60 #define MAXWIDTH 132
61 #define MAXREP 10
62
63 char buf[MAXREP][MAXWIDTH];
64 int maxcol[MAXREP] = {-1};
65 int lineno;
66 int width = 132; /* default line length */
67 int length = 66; /* page length */
68 int indent; /* indentation length */
69 int npages = 1;
70 int literal; /* print control characters */
71 char *name; /* user's login name */
72 char *host; /* user's machine name */
73 char *acctfile; /* accounting information file */
74 int crnl; /* \n -> \r\n */
75 int need_cr;
76
77 int main __P((int, char *[]));
78
79 int
80 main(argc, argv)
81 int argc;
82 char *argv[];
83 {
84 FILE *p = stdin, *o = stdout;
85 int i, col;
86 char *cp;
87 int done, linedone, maxrep, ch, prch;
88 char *limit;
89
90 while (--argc) {
91 if (*(cp = *++argv) == '-') {
92 switch (cp[1]) {
93 case 'n':
94 argc--;
95 name = *++argv;
96 break;
97
98 case 'h':
99 argc--;
100 host = *++argv;
101 break;
102
103 case 'w':
104 if ((i = atoi(&cp[2])) > 0 && i <= MAXWIDTH)
105 width = i;
106 break;
107
108 case 'l':
109 length = atoi(&cp[2]);
110 break;
111
112 case 'i':
113 indent = atoi(&cp[2]);
114 break;
115
116 case 'c': /* Print control chars */
117 literal++;
118 break;
119
120 case 'f': /* Fix missing carriage returns */
121 crnl++;
122 break;
123 }
124 } else
125 acctfile = cp;
126 }
127
128 for (cp = buf[0], limit = buf[MAXREP]; cp < limit; *cp++ = ' ');
129 done = 0;
130
131 while (!done) {
132 col = indent;
133 maxrep = -1;
134 linedone = 0;
135 prch = ch = 0;
136 need_cr = 0;
137 while (!linedone) {
138 prch = ch;
139 switch (ch = getc(p)) {
140 case EOF:
141 linedone = done = 1;
142 ch = '\n';
143 break;
144
145 case '\f':
146 lineno = length;
147 case '\n':
148 if (crnl && prch != '\r')
149 need_cr = 1;
150 if (maxrep < 0)
151 maxrep = 0;
152 linedone = 1;
153 break;
154
155 case '\b':
156 if (--col < indent)
157 col = indent;
158 break;
159
160 case '\r':
161 col = indent;
162 break;
163
164 case '\t':
165 col = ((col - indent) | 07) + indent + 1;
166 break;
167
168 case '\031':
169 /*
170 * lpd needs to use a different filter to
171 * print data so stop what we are doing and
172 * wait for lpd to restart us.
173 */
174 if ((ch = getchar()) == '\1') {
175 fflush(stdout);
176 kill(getpid(), SIGSTOP);
177 break;
178 } else {
179 ungetc(ch, stdin);
180 ch = '\031';
181 }
182
183 default:
184 if (col >= width || (!literal && ch < ' ')) {
185 col++;
186 break;
187 }
188 cp = &buf[0][col];
189 for (i = 0; i < MAXREP; i++) {
190 if (i > maxrep)
191 maxrep = i;
192 if (*cp == ' ') {
193 *cp = ch;
194 if (col > maxcol[i])
195 maxcol[i] = col;
196 break;
197 }
198 cp += MAXWIDTH;
199 }
200 col++;
201 break;
202 }
203 }
204
205 /* print out lines */
206 for (i = 0; i <= maxrep; i++) {
207 for (cp = buf[i], limit = cp+maxcol[i]; cp <= limit;) {
208 putc(*cp, o);
209 *cp++ = ' ';
210 }
211 if (i < maxrep)
212 putc('\r', o);
213 else {
214 if (need_cr)
215 putc('\r', o);
216 putc(ch, o);
217 }
218 if (++lineno >= length) {
219 fflush(o);
220 npages++;
221 lineno = 0;
222 }
223 maxcol[i] = -1;
224 }
225 }
226 if (lineno) { /* be sure to end on a page boundary */
227 putchar('\f');
228 npages++;
229 }
230 if (name && acctfile && access(acctfile, 02) >= 0 &&
231 freopen(acctfile, "a", stdout) != NULL) {
232 printf("%7.2f\t%s:%s\n", (float)npages, host, name);
233 }
234 exit(0);
235 }
236