Commit | Line | Data |
---|---|---|
ce8a9c05 BJ |
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 | } |