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