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