lpf.c revision 1.2 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[] = "from: @(#)lpf.c 5.4 (Berkeley) 6/1/90";*/
42 static char rcsid[] = "$Id: lpf.c,v 1.2 1993/08/01 17:59:17 mycroft Exp $";
43 #endif /* not lint */
44
45 /*
46 * filter which reads the output of nroff and converts lines
47 * with ^H's to overwritten lines. Thus this works like 'ul'
48 * but is much better: it can handle more than 2 overwrites
49 * and it is written with some style.
50 * modified by kls to use register references instead of arrays
51 * to try to gain a little speed.
52 */
53
54 #include <stdio.h>
55 #include <signal.h>
56
57 #define MAXWIDTH 132
58 #define MAXREP 10
59
60 char buf[MAXREP][MAXWIDTH];
61 int maxcol[MAXREP] = {-1};
62 int lineno;
63 int width = 132; /* default line length */
64 int length = 66; /* page length */
65 int indent; /* indentation length */
66 int npages = 1;
67 int literal; /* print control characters */
68 char *name; /* user's login name */
69 char *host; /* user's machine name */
70 char *acctfile; /* accounting information file */
71
72 main(argc, argv)
73 int argc;
74 char *argv[];
75 {
76 register FILE *p = stdin, *o = stdout;
77 register int i, col;
78 register char *cp;
79 int done, linedone, maxrep;
80 char ch, *limit;
81
82 while (--argc) {
83 if (*(cp = *++argv) == '-') {
84 switch (cp[1]) {
85 case 'n':
86 argc--;
87 name = *++argv;
88 break;
89
90 case 'h':
91 argc--;
92 host = *++argv;
93 break;
94
95 case 'w':
96 if ((i = atoi(&cp[2])) > 0 && i <= MAXWIDTH)
97 width = i;
98 break;
99
100 case 'l':
101 length = atoi(&cp[2]);
102 break;
103
104 case 'i':
105 indent = atoi(&cp[2]);
106 break;
107
108 case 'c': /* Print control chars */
109 literal++;
110 break;
111 }
112 } else
113 acctfile = cp;
114 }
115
116 for (cp = buf[0], limit = buf[MAXREP]; cp < limit; *cp++ = ' ');
117 done = 0;
118
119 while (!done) {
120 col = indent;
121 maxrep = -1;
122 linedone = 0;
123 while (!linedone) {
124 switch (ch = getc(p)) {
125 case EOF:
126 linedone = done = 1;
127 ch = '\n';
128 break;
129
130 case '\f':
131 lineno = length;
132 case '\n':
133 if (maxrep < 0)
134 maxrep = 0;
135 linedone = 1;
136 break;
137
138 case '\b':
139 if (--col < indent)
140 col = indent;
141 break;
142
143 case '\r':
144 col = indent;
145 break;
146
147 case '\t':
148 col = ((col - indent) | 07) + indent + 1;
149 break;
150
151 case '\031':
152 /*
153 * lpd needs to use a different filter to
154 * print data so stop what we are doing and
155 * wait for lpd to restart us.
156 */
157 if ((ch = getchar()) == '\1') {
158 fflush(stdout);
159 kill(getpid(), SIGSTOP);
160 break;
161 } else {
162 ungetc(ch, stdin);
163 ch = '\031';
164 }
165
166 default:
167 if (col >= width || !literal && ch < ' ') {
168 col++;
169 break;
170 }
171 cp = &buf[0][col];
172 for (i = 0; i < MAXREP; i++) {
173 if (i > maxrep)
174 maxrep = i;
175 if (*cp == ' ') {
176 *cp = ch;
177 if (col > maxcol[i])
178 maxcol[i] = col;
179 break;
180 }
181 cp += MAXWIDTH;
182 }
183 col++;
184 break;
185 }
186 }
187
188 /* print out lines */
189 for (i = 0; i <= maxrep; i++) {
190 for (cp = buf[i], limit = cp+maxcol[i]; cp <= limit;) {
191 putc(*cp, o);
192 *cp++ = ' ';
193 }
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