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