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