xref: /csrg-svn/old/vfilters/vpf/vpf.c (revision 11582)
1 /*	vpf.c	4.2	83/03/17	*/
2 /*
3  * Varian/Versatec printer filter
4  */
5 
6 #include <signal.h>
7 #include <stdio.h>
8 #include <sys/vcmd.h>
9 
10 #define LINELN 440
11 
12 int	pltmode[] = {VPLOT, 0, 0};
13 int	prtmode[] = {VPRINT, 0, 0};
14 char	linebuf[LINELN+1];
15 char	ovbuf[LINELN];
16 int	ov;
17 int	lineno;
18 int	varian = 1;	/* default is the varian */
19 int	width = 132;	/* default line length */
20 int	length = 58;	/* 80 for 11" long paper */
21 int	npages = 1;
22 int	literal;
23 char	*name;		/* user's login name */
24 char	*host;		/* user's machine name */
25 char	*acctfile;	/* accounting information file */
26 
27 onintr()
28 {
29 	signal(SIGTERM, SIG_IGN);
30 	exit(1);
31 }
32 
33 main(argc, argv)
34 	int argc;
35 	char *argv[];
36 {
37 	register int i;
38 
39 	signal(SIGHUP, SIG_IGN);
40 	signal(SIGINT, SIG_IGN);
41 	signal(SIGQUIT, SIG_IGN);
42 	signal(SIGTERM, onintr);
43 
44 	if (argv[0][strlen(argv[0])-1] == 'W') { /* Wide: the versatec. */
45 		varian = 0;
46 		width = 440;
47 		length = 66;
48 	}
49 
50 	while (--argc) {
51 		if (*(*++argv) == '-') {
52 			switch (argv[0][1]) {
53 			case 'n':
54 				argc--;
55 				name = *++argv;
56 				break;
57 
58 			case 'h':
59 				argc--;
60 				host = *++argv;
61 				break;
62 
63 			case 'w':
64 				if ((i = atoi(&argv[0][2])) > 0 && i < LINELN)
65 					width = i;
66 				break;
67 
68 			case 'l':
69 				length = atoi(&argv[0][2]);
70 				break;
71 
72 			case 'c':	/* Print input without throwing away
73 					   control chars and without putting
74 					   in page breaks. */
75 				literal++;
76 				break;
77 			}
78 		} else
79 			acctfile = *argv;
80 	}
81 	/*
82 	 * device should be open on file descriptor 1.
83 	 */
84 	ioctl(1, VSETSTATE, prtmode);
85 	send();
86 	if (name && acctfile && access(acctfile, 02) >= 0 &&
87 	    freopen(acctfile, "a", stdout) != NULL) {
88 		printf("%7.2f\t%s:%s\n", (float)npages, host, name);
89 	}
90 	exit(0);
91 }
92 
93 send()
94 {
95 	register nskipped;
96 
97 	lineno = 0;
98 	nskipped = 0;
99 	while (getline()) {
100 		if (!literal && varian && lineno==0 && linebuf[0]==0 && nskipped<3) {
101 			nskipped++;
102 			continue;
103 		}
104 		if (varian && lineno >= length) {
105 			nskipped = 0;
106 			putline(1);
107 			lineno = 0;
108 		} else {
109 			putline(0);
110 			if (literal)	/* Don't make page breaks if -l. */
111 				lineno = 1;
112 			else
113 				lineno++;
114 		}
115 	}
116 	if (varian && lineno)
117 		putchar('\f');	/* be sure to end on a page boundary */
118 	/*
119 	 * Put out an extra null to ensure varian will get an even
120 	 * number of good characters.
121 	 */
122 	putchar('\0');
123 	npages += (lineno + length - 1) / length;
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 = 0;
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;
201 	case '\n':
202 		if (maxcol > width)
203 			maxcol = width;
204 		linebuf[maxcol] = '\0';
205 		return(1);
206 
207 	case '\b':
208 		if (col > 0)
209 			col--;
210 		continue;
211 	}
212 }
213 
214 putline(ff)
215 int ff;
216 {
217 	register char *lp;
218 	register c, i;
219 
220 	lp = linebuf;
221 	while (c = *lp++)
222 		putchar(c);
223 	if (ov) {
224 		putchar('\n');
225 		putchar('\0');
226 		fflush(stdout);
227 		ioctl(1, VSETSTATE, pltmode);
228 		for (lp = ovbuf, i = ov; ov--; ) {
229 			putchar(*lp & 0377);
230 			putchar(*lp++ & 0377);
231 		}
232 		if (ov & 1)
233 			putchar('\0');
234 		fflush(stdout);
235 		ioctl(1, VSETSTATE, prtmode);
236 	}
237 	if (ff) {
238 		putchar('\f');
239 		npages++;
240 	} else if (ov == 0)
241 		putchar('\n');
242 	if (ferror(stdout))
243 		exit(1);
244 }
245