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