xref: /original-bsd/old/vpr/vpd.c (revision 6c57d260)
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