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