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