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