xref: /csrg-svn/old/vfilters/vpf/vpf.c (revision 20203)
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[] = "@(#)vpf.c	5.1 (Berkeley) 05/15/85";
9 #endif not lint
10 
11 /*
12  * Varian/Versatec printer filter
13  */
14 
15 #include <signal.h>
16 #include <stdio.h>
17 #include <sys/vcmd.h>
18 
19 #define LINELN 440
20 
21 int	pltmode[] = {VPLOT};
22 int	prtmode[] = {VPRINT};
23 char	linebuf[LINELN+1];
24 char	ovbuf[LINELN];
25 int	ov;
26 int	lineno;
27 int	varian = 1;	/* default is the varian */
28 int	width = 132;	/* default line length */
29 int	indent = 0;	/* default indent length */
30 int	length = 58;	/* 80 for 11" long paper */
31 int	npages = 1;
32 int	literal;
33 char	*name;		/* user's login name */
34 char	*host;		/* user's machine name */
35 char	*acctfile;	/* accounting information file */
36 
37 main(argc, argv)
38 	int argc;
39 	char *argv[];
40 {
41 	register int i;
42 
43 	if (argv[0][strlen(argv[0])-1] == 'W') { /* Wide: the versatec. */
44 		varian = 0;
45 		width = 440;
46 		length = 66;
47 	}
48 
49 	while (--argc) {
50 		if (*(*++argv) == '-') {
51 			switch (argv[0][1]) {
52 			case 'n':
53 				argc--;
54 				name = *++argv;
55 				break;
56 
57 			case 'h':
58 				argc--;
59 				host = *++argv;
60 				break;
61 
62 			case 'w':
63 				if ((i = atoi(&argv[0][2])) > 0 && i < LINELN)
64 					width = i;
65 				break;
66 
67 			case 'l':
68 				length = atoi(&argv[0][2]);
69 				break;
70 
71 			case 'i':
72 				if ((i = atoi(&argv[0][2])) >= 0 &&
73 				    i < LINELN - 1)
74 					indent = i;
75 				break;
76 
77 			case 'c':	/* Print input without throwing away
78 					   control chars and without putting
79 					   in page breaks. */
80 				literal++;
81 				break;
82 			}
83 		} else
84 			acctfile = *argv;
85 	}
86 	/*
87 	 * device should be open on file descriptor 1.
88 	 */
89 	ioctl(1, VSETSTATE, prtmode);
90 	send();
91 	if (name && acctfile && access(acctfile, 02) >= 0 &&
92 	    freopen(acctfile, "a", stdout) != NULL) {
93 		printf("%7.2f\t%s:%s\n", (float)npages, host, name);
94 	}
95 	exit(0);
96 }
97 
98 send()
99 {
100 	lineno = 0;
101 	while (getline()) {
102 		if (varian && !literal && lineno >= length) {
103 			putline(1);
104 			lineno = 0;
105 		} else
106 			putline(0);
107 	}
108 	if (varian && lineno) {
109 		putchar('\f');	/* be sure to end on a page boundary */
110 		npages++;
111 	}
112 	/*
113 	 * Put out an extra null to ensure varian will get an even
114 	 * number of good characters.
115 	 */
116 	putchar('\0');
117 }
118 
119 getline()
120 {
121 	register col, maxcol, c;
122 
123 	ov = 0;
124 	for (col = 0; col < width; col++) {
125 		linebuf[col] = ' ';
126 		ovbuf[col] = 0;
127 	}
128 	col = indent;
129 	maxcol = 0;
130 	for (;;) switch (c = getchar()) {
131 
132 	case EOF:
133 		return(0);
134 
135 	case '\031':
136 		/*
137 		 * lpd needs to use a different filter to print data so
138 		 * stop what we are doing and wait for lpd to restart us.
139 		 */
140 		if ((c = getchar()) == '\1') {
141 			putchar('\0');		/* make sure even # sent */
142 			fflush(stdout);
143 			kill(getpid(), SIGSTOP);
144 			ioctl(1, VSETSTATE, prtmode);
145 			continue;
146 		}
147 		ungetc(c, stdin);
148 		c = '\031';
149 		/* fall through if not stop sequence */
150 	default:
151 		if (c >= ' ' || literal) {
152 			if (col < width) {
153 				if (linebuf[col] == '_') {
154 					ovbuf[col] = 0377;
155 					ov++;
156 				}
157 				linebuf[col++] = c;
158 				if (col > maxcol)
159 					maxcol = col;
160 			} else
161 				col++;
162 		}
163 		continue;
164 
165 	case ' ':
166 		col++;
167 		continue;
168 
169 	case '\t':
170 		col = (col|07) + 1;
171 		continue;
172 
173 	case '\r':
174 		col = 0;
175 		continue;
176 
177 	case '_':
178 		if (col < width) {
179 			if (linebuf[col] != ' ') {
180 				ovbuf[col] = 0377;
181 				ov++;
182 			} else
183 				linebuf[col] = c;
184 			col++;
185 			if (col > maxcol)
186 				maxcol = col;
187 		} else
188 			col++;
189 		continue;
190 
191 	case '\f':
192 		/* Fall through, treating a ff as a line break, too... */
193 		lineno = length - 1;
194 	case '\n':
195 		if (maxcol > width)
196 			maxcol = width;
197 		linebuf[maxcol] = '\0';
198 		if (++lineno % length == 0)
199 			npages++;
200 		return(1);
201 
202 	case '\b':
203 		if (col > 0)
204 			col--;
205 		continue;
206 	}
207 }
208 
209 putline(ff)
210 int ff;
211 {
212 	register char *lp;
213 	register c, i;
214 
215 	lp = linebuf;
216 	while (c = *lp++)
217 		putchar(c);
218 	if (ov) {
219 		putchar('\n');
220 		putchar('\0');
221 		fflush(stdout);
222 		ioctl(1, VSETSTATE, pltmode);
223 		for (lp = ovbuf, i = ov; ov--; ) {
224 			putchar(*lp & 0377);
225 			putchar(*lp++ & 0377);
226 		}
227 		if (ov & 1)
228 			putchar('\0');
229 		fflush(stdout);
230 		ioctl(1, VSETSTATE, prtmode);
231 	}
232 	if (ff)
233 		putchar('\f');
234 	else if (ov == 0)
235 		putchar('\n');
236 	if (ferror(stdout))
237 		exit(1);
238 }
239