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