1 #define CONSOLE "/dev/console" 2 #define dprcons if (debug) prcons 3 /* 4 * Varian or Versatec printer daemon 5 */ 6 #include <stdio.h> 7 #include <sys/types.h> 8 #include <dir.h> 9 #include <signal.h> 10 #include <stat.h> 11 #include <sgtty.h> 12 #include <errno.h> 13 #include <sys/vcmd.h> 14 #include <wait.h> 15 16 int debug; 17 extern int errno; 18 19 #define VRAST "/usr/local/lib/vrast" 20 21 #ifdef VARIAN 22 #define DEVICE "/dev/va0" 23 #define DFNAME "/usr/spool/vad/" 24 #define SPOOLDIR "/usr/spool/vad" 25 #define NAME "Varian" 26 #endif 27 28 #ifdef VERSATEC 29 #define DEVICE "/dev/vp0" 30 #define DFNAME "/usr/spool/vpd/" 31 #define SPOOLDIR "/usr/spool/vpd" 32 #define NAME "Versatec" 33 #endif 34 35 int prtmode[] = {VPRINT, 0, 0}; 36 37 char line[128]; 38 char linep[127]; 39 char banbuf[64]; 40 char printflag; 41 int linel; 42 FILE *dfb; 43 char dfname[33] = DFNAME; 44 int waittm = 6; 45 struct dir dbuf; 46 int onalrm (); 47 char tmplock[] = "lockXXXXXX"; 48 char fonts[4][50] = { 49 "/usr/lib/vfont/R", 50 "/usr/lib/vfont/I", 51 "/usr/lib/vfont/B", 52 "/usr/lib/vfont/S" 53 }; 54 55 main(argc, argv) 56 { 57 char dp, n; 58 register char *p1, *p2; 59 register int df; 60 struct stat stb; 61 int offline = 0; 62 int i, okreque = 1; 63 64 signal(SIGHUP, SIG_IGN); 65 signal(SIGINT, SIG_IGN); 66 signal(SIGQUIT, SIG_IGN); 67 signal(SIGTERM, SIG_IGN); 68 begin: 69 /* 70 * Close all files, open root as 0, 1, 2 71 * to assure standard environment 72 */ 73 for (df = 0; df <= 15; df++) 74 close(df); 75 open("/", 0); 76 dup(0); 77 dup(0); 78 if (chdir(SPOOLDIR) < 0 || (df = creat(mktemp(tmplock), 0)) < 0) { 79 close(1); 80 prcons("%s: error accessing %s\n", NAME, SPOOLDIR); 81 exit(1); 82 } 83 if (link(tmplock, "lock") < 0) { 84 unlink(tmplock); 85 exit(0); 86 } 87 unlink(tmplock); 88 close(df); 89 floop: 90 dprcons("floop\n"); 91 i = fork(); 92 if (i < 0) { 93 sleep(5); 94 goto floop; 95 } 96 if (i != 0) 97 exit(0); 98 reopen: 99 dprcons("reopen\n"); 100 for (;;) { 101 if (open(DEVICE, 1) == 3) 102 break; 103 if (errno != EIO) { 104 extern char *sys_errlist[]; 105 prcons("%s: %s: %s\n", NAME, DEVICE, sys_errlist[errno]); 106 unlink("lock"); 107 exit(1); 108 } 109 if (offline == 0) { 110 int f = open("/dev/tty", 1); 111 112 offline++; 113 if (f > 0) { 114 write(f, NAME, strlen(NAME)); 115 write(f, " is offline\n", 12); 116 close(f); 117 } 118 dprcons("offline\n"); 119 } 120 sleep(10); 121 } 122 dp = open(".", 0); 123 search: 124 dprcons("search\n"); 125 if (okreque == 1) { 126 lseek(dp, 0, 0); 127 do { 128 n = read(dp, &dbuf, sizeof dbuf); 129 if (n <= 0) { 130 if (printflag) 131 lastpage(); 132 unlink("lock"); 133 dprcons("nomore\n"); 134 if (printflag==0) { 135 dprcons("bye\n"); 136 exit(0); 137 } 138 dprcons("one last time\n"); 139 printflag = 0; 140 close(3); 141 sleep(30); 142 goto begin; 143 } 144 } while (!dbuf.d_ino 145 || dbuf.d_name[0] != 'd' || dbuf.d_name[1] != 'f'); 146 strcpy(&dfname[15], dbuf.d_name); 147 dprcons("found %s\n", dbuf.d_name); 148 } 149 dprcons("trying %s\n", dfname); 150 printflag = 1; 151 if (okreque == 0) 152 feedpage(); 153 if (trysend(dfname, okreque)) { 154 okreque = 0; 155 close(dp); 156 printf("reque %s\n", dfname); 157 close(3); 158 goto reopen; 159 } 160 dprcons("ok\n"); 161 okreque = 1; 162 goto search; 163 } 164 165 trysend(file, okreque) 166 char *file; 167 int okreque; 168 { 169 register int i; 170 char plot; 171 union wait status; 172 int bomb = 0; 173 174 resfonts(); 175 dfb = fopen(file, "r"); 176 if (dfb == NULL) { 177 unlink(file); 178 return (0); 179 } 180 for (*banbuf = plot = 0; getline (); ) switch (line[0]) { 181 182 case 'L': 183 strcpy(banbuf, line + 1); 184 continue; 185 186 case '1': 187 case '2': 188 case '3': 189 case '4': 190 strcpy(fonts[line[0]-'1'], line + 1); 191 continue; 192 193 case 'F': 194 case 'G': /* Like f, but invoke vpf with -l flag. */ 195 case 'T': 196 status.w_status = send(line[0]); 197 break; 198 199 case 'P': 200 if (plot) { 201 plot = 0; 202 status.w_status = send(line[0]); 203 break; 204 } 205 strcpy(linep, line + 1); 206 plot++; 207 continue; 208 209 case 'U': 210 continue; 211 212 case 'M': 213 continue; 214 } 215 /* 216 * If the process that did the work did an exit(1), 217 * we should requeue the file. 218 */ 219 if (!WIFEXITED(status) || status.w_retcode > 1) { 220 ioctl(3, VSETSTATE, prtmode); 221 write(3, "\nDAEMON MALFUNCTION\n", 20); 222 feedpage(); 223 bomb++; 224 } else if (status.w_retcode == 1 && okreque) 225 return (1); 226 /* 227 * All done, for better or for worse. 228 */ 229 fseek(dfb, 0, 0); 230 while (getline()) switch (*line) { 231 232 default: 233 continue; 234 235 case 'U': 236 unlink(line + 1); 237 continue; 238 239 case 'M': 240 sendmail(bomb); 241 continue; 242 } 243 remret: 244 fclose(dfb); 245 unlink(file); 246 return (0); 247 } 248 249 static char ifonts[4][50] = { 250 "/usr/lib/vfont/R", 251 "/usr/lib/vfont/I", 252 "/usr/lib/vfont/B", 253 "/usr/lib/vfont/S" 254 }; 255 256 resfonts() 257 { 258 int i; 259 for (i = 0; i < 4; i++) 260 strcpy(fonts[i], ifonts[i]); 261 } 262 263 sendmail(bomb) 264 int bomb; 265 { 266 static int p[2]; 267 register i; 268 int stat; 269 270 pipe(p); 271 if (fork() == 0) { 272 alarm(0); 273 close(0); 274 dup(p[0]); 275 for (i = 3; i <= 15; i++) 276 close(i); 277 execl("/bin/mail", "mail", &line[1], 0); 278 exit(0); 279 } 280 close(1); 281 dup(p[1]); 282 printf("Your %s job %s\n", NAME, bomb ? "screwed up" : "is done"); 283 close(1); 284 close(p[0]); 285 close(p[1]); 286 open("/", 0); 287 wait(&stat); 288 } 289 290 getline() 291 { 292 register char *lp; 293 register int c; 294 295 lp = line; 296 linel = 0; 297 while ((c = getc (dfb)) != '\n') { 298 if (c < 0) 299 return (0); 300 if (c == '\t') { 301 do { 302 *lp++ = ' '; 303 linel++; 304 } while ((linel & 07) != 0); 305 continue; 306 } 307 *lp++ = c; 308 linel++; 309 } 310 *lp++ = 0; 311 return (1); 312 } 313 314 int pid; 315 316 send (c) 317 char c; 318 { 319 int p, i, rm; 320 321 if (pid = fork ()) { 322 if (pid == -1) 323 return (1); 324 setexit(); 325 signal(SIGALRM, onalrm); 326 alarm(30); 327 wait(&p); 328 alarm(0); 329 return(p); 330 } 331 ioctl (3, VSETSTATE, prtmode); 332 switch (c) { 333 334 case 'F': 335 if (banbuf[0]) { 336 execl ("/usr/lib/vpf", "vpf", 337 #ifdef VERSATEC 338 "-W", 339 #endif 340 "-b", banbuf, line+1, 0); 341 break; 342 } 343 execl ("/usr/lib/vpf", "vpf", 344 #ifdef VERSATEC 345 "-W", 346 #endif 347 line, 0); 348 break; 349 350 case 'G': /* Like F (vpf), but passes through -l 351 flag to vpf (print control chars). */ 352 if (banbuf[0]) { 353 execl ("/usr/lib/vpf", "vpf", "-l", 354 #ifdef VERSATEC 355 "-W", 356 #endif 357 "-b", banbuf, line+1, 0); 358 break; 359 } 360 execl ("/usr/lib/vpf", "vpf", "-l", 361 #ifdef VERSATEC 362 "-W", 363 #endif 364 line, 0); 365 break; 366 367 case 'T': 368 unlink(".railmag"); 369 rm = creat(".railmag", 0666); 370 for (i = 0; i < 4; i++) { 371 if (fonts[i][0] != '/') 372 write(rm, "/usr/lib/vfont/", 15); 373 write(rm, fonts[i], strlen (fonts[i])); 374 write(rm, "\n", 1); 375 } 376 close(rm); 377 if (banbuf[0]) { 378 #ifdef VARIAN 379 execl("/usr/lib/rvcat", "rvcat", 380 #endif 381 #ifdef VERSATEC 382 execl("/usr/lib/vcat", "rvcat", 383 "-W", 384 #endif 385 "-3", "-b", banbuf, line+1, 0); 386 break; 387 } 388 #ifdef VARIAN 389 execl("/usr/lib/rvcat", "rvcat", 390 #endif 391 #ifdef VERSATEC 392 execl("/usr/lib/vcat", "rvcat", 393 "-W", 394 #endif 395 "-3", line+1, 0); 396 break; 397 398 case 'P': 399 close(1); 400 dup(3); 401 if (banbuf[0]) { 402 execl(VRAST, "vrast", 403 #ifdef VERSATEC 404 "-W", 405 #endif 406 "-v", "-b", banbuf, line+1, linep, 0); 407 break; 408 } 409 execl(VRAST, "vrast", 410 #ifdef VERSATEC 411 "-W", 412 #endif 413 "-v", line+1, linep, 0); 414 break; 415 } 416 exit(2); /* execl failed or not one of above cases. */ 417 } 418 419 onalrm() 420 { 421 struct stat stb; 422 423 signal(SIGALRM, onalrm); 424 if (stat(dfname, &stb) < 0) 425 kill(pid, SIGEMT); 426 reset(); 427 } 428 429 /* 430 * skip 16 inches or do two formfeeds. 431 */ 432 lastpage() 433 { 434 register int i; 435 436 ioctl(3, VSETSTATE, prtmode); 437 #ifdef VARIAN 438 write(3, "\014\014", 2); 439 #endif 440 #ifdef VERSATEC 441 for (i = 0; i < 18; i++) 442 write(3, "\n\n\n\n\n\n\n\n", 8); 443 #endif 444 } 445 446 feedpage() 447 { 448 449 ioctl(3, VSETSTATE, prtmode); 450 #ifdef VARIAN 451 write(3, "\014\0", 2); 452 #endif 453 #ifdef VERSATEC 454 write(3, "\n\n\n", 8); 455 #endif 456 } 457 458 prcons(cp, a1, a2, a3, a4, a5) 459 char *cp; 460 { 461 char buf[BUFSIZ]; 462 int f = open(CONSOLE, 1); 463 464 sprintf(buf, cp, a1, a2, a3, a4, a5); 465 write(f, buf, strlen(buf)); 466 close(f); 467 } 468