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