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 | */ | |
4916dcc2 DH |
7 | char vpdSCCSid[] = "@(#)vpd.c 1.2\t%G%"; |
8 | ||
0d2cd677 BJ |
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" | |
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; | |
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 | } | |
4916dcc2 DH |
186 | banner[0] = '\0'; |
187 | for(*banbuf= plot= 0; getline();) switch(line[0]) { | |
0d2cd677 BJ |
188 | |
189 | case 'L': | |
190 | strcpy(banbuf, line + 1); | |
191 | continue; | |
192 | ||
4916dcc2 DH |
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 | ||
0d2cd677 BJ |
202 | case '1': |
203 | case '2': | |
204 | case '3': | |
205 | case '4': | |
206 | strcpy(fonts[line[0]-'1'], line + 1); | |
207 | continue; | |
208 | ||
4916dcc2 DH |
209 | case 'C': /* called by cifplot */ |
210 | case 'V': /* called by vplot */ | |
0d2cd677 BJ |
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; | |
4916dcc2 DH |
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; | |
0d2cd677 BJ |
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 | } |