xref: /original-bsd/old/vpr/vpd.c (revision 8ac030d2)
1 #define	CONSOLE		"/dev/console"
2 #define	dprcons		if (debug) prcons
3 /*
4  * vpd.c						updated 11/18/82
5  * Varian or Versatec printer daemon
6  */
7 char vpdSCCSid[] = "@(#)vpd.c	1.4\t11/18/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 	int argc;
62 	char **argv;
63 {
64 	char n;
65 	register char *p1, *p2;
66 	register int df;
67 	register struct direct *dirp;
68 	DIR *dp;
69 	struct stat stb;
70 	int offline = 0;
71 	int i, okreque = 1;
72 
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());
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 	}
147 	dp = opendir(".");
148 search:
149 	dprcons("search\n");
150 	if (okreque == 1) {
151 		rewinddir(dp);
152 		do {
153 			dirp = readdir(dp);
154 			if (dirp == NULL) {
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);
166 				closedir(dp);
167 				sleep(30);
168 				goto begin;
169 			}
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);
173 	}
174 	dprcons("trying %s\n", dfname);
175 	printflag = 1;
176 	if (okreque == 0)
177 		feedpage();
178 	if (trysend(dfname, okreque)) {
179 		okreque = 0;
180 		closedir(dp);
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 	}
205 	banner[0] = '\0';
206 	for(*banbuf= plot= 0; getline();) switch(line[0]) {
207 
208 	case 'L':
209 		strcpy(banbuf, line + 1);
210 		continue;
211 
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 
221 	case '1':
222 	case '2':
223 	case '3':
224 	case '4':
225 		strcpy(fonts[line[0]-'1'], line + 1);
226 		continue;
227 
228 	case 'C':	/* called by cifplot */
229 	case 'V':	/* called by vplot */
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;
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;
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 }
519