Commit | Line | Data |
---|---|---|
0d2cd677 BJ |
1 | #define CONSOLE "/dev/console" |
2 | #define dprcons if (debug) prcons | |
3 | /* | |
4916dcc2 | 4 | * vpd.c updated %G% |
0d2cd677 BJ |
5 | * Varian or Versatec printer daemon |
6 | */ | |
4742deda | 7 | char vpdSCCSid[] = "@(#)vpd.c 1.4\t%G%"; |
4916dcc2 | 8 | |
0d2cd677 | 9 | #include <stdio.h> |
fef7eb28 | 10 | #include <sys/param.h> |
0d2cd677 BJ |
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" | |
4916dcc2 DH |
23 | #define VDMP "/usr/lib/vdmp" |
24 | #define VPLTDMP "/usr/lib/vpltdmp" | |
0d2cd677 BJ |
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]; | |
4916dcc2 | 45 | char banner[512]; |
0d2cd677 BJ |
46 | char printflag; |
47 | int linel; | |
48 | FILE *dfb; | |
49 | char dfname[33] = DFNAME; | |
50 | int waittm = 6; | |
0d2cd677 BJ |
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) | |
4742deda KM |
61 | int argc; |
62 | char **argv; | |
0d2cd677 | 63 | { |
fef7eb28 | 64 | char n; |
0d2cd677 BJ |
65 | register char *p1, *p2; |
66 | register int df; | |
fef7eb28 KM |
67 | register struct direct *dirp; |
68 | DIR *dp; | |
0d2cd677 BJ |
69 | struct stat stb; |
70 | int offline = 0; | |
71 | int i, okreque = 1; | |
72 | ||
4742deda KM |
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()); | |
0d2cd677 BJ |
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 | } | |
fef7eb28 | 147 | dp = opendir("."); |
0d2cd677 BJ |
148 | search: |
149 | dprcons("search\n"); | |
150 | if (okreque == 1) { | |
fef7eb28 | 151 | rewinddir(dp); |
0d2cd677 | 152 | do { |
fef7eb28 KM |
153 | dirp = readdir(dp); |
154 | if (dirp == NULL) { | |
0d2cd677 BJ |
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); | |
fef7eb28 | 166 | closedir(dp); |
0d2cd677 BJ |
167 | sleep(30); |
168 | goto begin; | |
169 | } | |
fef7eb28 KM |
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); | |
0d2cd677 BJ |
173 | } |
174 | dprcons("trying %s\n", dfname); | |
175 | printflag = 1; | |
176 | if (okreque == 0) | |
177 | feedpage(); | |
178 | if (trysend(dfname, okreque)) { | |
179 | okreque = 0; | |
fef7eb28 | 180 | closedir(dp); |
0d2cd677 BJ |
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 | } | |
4916dcc2 DH |
205 | banner[0] = '\0'; |
206 | for(*banbuf= plot= 0; getline();) switch(line[0]) { | |
0d2cd677 BJ |
207 | |
208 | case 'L': | |
209 | strcpy(banbuf, line + 1); | |
210 | continue; | |
211 | ||
4916dcc2 DH |
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 | ||
0d2cd677 BJ |
221 | case '1': |
222 | case '2': | |
223 | case '3': | |
224 | case '4': | |
225 | strcpy(fonts[line[0]-'1'], line + 1); | |
226 | continue; | |
227 | ||
4916dcc2 DH |
228 | case 'C': /* called by cifplot */ |
229 | case 'V': /* called by vplot */ | |
0d2cd677 BJ |
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; | |
4916dcc2 DH |
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; | |
0d2cd677 BJ |
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 | } |