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