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