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