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