xref: /csrg-svn/old/vpr/vpd.c (revision 7661)
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