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