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