1 | /* |
---|
2 | * $Id: printjob.c,v 1.31 1999-01-22 23:10:44 ghudson Exp $ |
---|
3 | */ |
---|
4 | |
---|
5 | /* |
---|
6 | * Copyright (c) 1983 Regents of the University of California. |
---|
7 | * All rights reserved. The Berkeley software License Agreement |
---|
8 | * specifies the terms and conditions for redistribution. |
---|
9 | */ |
---|
10 | |
---|
11 | #ifndef lint |
---|
12 | static char sccsid[] = "@(#)printjob.c 5.2 (Berkeley) 9/17/85"; |
---|
13 | static char *rcsid_printjob_c = "$Id: printjob.c,v 1.31 1999-01-22 23:10:44 ghudson Exp $"; |
---|
14 | #endif |
---|
15 | |
---|
16 | /* |
---|
17 | * printjob -- print jobs in the queue. |
---|
18 | * |
---|
19 | * NOTE: the lock file is used to pass information to lpq and lprm. |
---|
20 | * it does not need to be removed because file locks are dynamic. |
---|
21 | */ |
---|
22 | |
---|
23 | #include "lp.h" |
---|
24 | #ifdef _AUX_SOURCE |
---|
25 | #include <sys/termio.h> |
---|
26 | #endif |
---|
27 | |
---|
28 | #include <string.h> |
---|
29 | #if defined(POSIX) && !defined(ultrix) |
---|
30 | #include "posix.h" /* flock() */ |
---|
31 | #else |
---|
32 | #include "nonposix.h" /* EWOULDBLOCK setty() */ |
---|
33 | #endif |
---|
34 | #define DORETURN 0 /* absorb fork error */ |
---|
35 | #define DOABORT 1 /* abort if dofork fails */ |
---|
36 | /* |
---|
37 | * Error tokens |
---|
38 | */ |
---|
39 | #define DEFER -4 /* Defer printing file till later */ |
---|
40 | #define REPRINT -2 |
---|
41 | #define ERROR -1 |
---|
42 | #define OK 0 |
---|
43 | #define FATALERR 1 |
---|
44 | #define NOACCT 2 |
---|
45 | #define FILTERERR 3 |
---|
46 | #define ACCESS 4 |
---|
47 | |
---|
48 | static int network; /* true if network access to printer */ |
---|
49 | #ifdef ZEPHYR |
---|
50 | #undef STAT |
---|
51 | #include <zephyr/zephyr.h> |
---|
52 | |
---|
53 | #define ZCLASS "MESSAGE" |
---|
54 | #define ZINSTANCE "PERSONAL" |
---|
55 | #define ZSENDER "Printer Daemon" |
---|
56 | #define ZDEFAULTFORMAT "$message" |
---|
57 | |
---|
58 | ZNotice_t notice; |
---|
59 | char zrecipient[40+REALM_SZ]; |
---|
60 | char *zmessage[6]; |
---|
61 | char zmessagetext[BUFSIZ]; |
---|
62 | int zerrno; |
---|
63 | int zflag = 0; |
---|
64 | |
---|
65 | static char *zerrtext[]={"Document printing has been deferred", |
---|
66 | "This is impossible", |
---|
67 | "Attempting to reprint document", |
---|
68 | "Generic error", |
---|
69 | "Document has finished printing successfully", |
---|
70 | "Fatal error", |
---|
71 | "No local account, document not printed", |
---|
72 | "Error in document output filter", |
---|
73 | "Error accessing symlinked file"}; |
---|
74 | |
---|
75 | static char *zerrtoken[]={"DEFER","IMPOSSIBLE","REPRINT","ERROR","OK", |
---|
76 | "FATALERR","NOACCT","FILTERERR","ACCESS"}; |
---|
77 | |
---|
78 | #endif ZEPHYR |
---|
79 | |
---|
80 | |
---|
81 | char title[80]; /* ``pr'' title */ |
---|
82 | FILE *cfp = NULL; /* control file */ |
---|
83 | int pfd; /* printer file descriptor */ |
---|
84 | int ofd; /* output filter file descriptor */ |
---|
85 | int lfd = -1; /* lock file descriptor */ |
---|
86 | int pid; /* pid of lpd process */ |
---|
87 | int prchild; /* id of pr process */ |
---|
88 | int child; /* id of any filters */ |
---|
89 | int ofilter; /* id of output filter, if any */ |
---|
90 | int tof; /* true if at top of form */ |
---|
91 | int remote; /* true if sending files to remote */ |
---|
92 | dev_t fdev; /* device of file pointed to by symlink */ |
---|
93 | ino_t fino; /* inode of file pointed to by symlink */ |
---|
94 | |
---|
95 | char fromhost[MAXHOSTNAMELEN + 1]; /* user's host machine */ |
---|
96 | #ifdef KERBEROS |
---|
97 | char logname[ANAME_SZ + INST_SZ + REALM_SZ + 3]; |
---|
98 | #else |
---|
99 | char logname[32]; /* user's login name */ |
---|
100 | #endif KERBEROS |
---|
101 | char jobname[100]; /* job or file name */ |
---|
102 | char queuename[100]; /* print queue name */ |
---|
103 | |
---|
104 | char class[MAXHOSTNAMELEN + 1]; /* classification field */ |
---|
105 | char width[10] = "-w"; /* page width in characters */ |
---|
106 | char length[10] = "-l"; /* page length in lines */ |
---|
107 | char pxwidth[10] = "-x"; /* page width in pixels */ |
---|
108 | char pxlength[10] = "-y"; /* page length in pixels */ |
---|
109 | char indent[10] = "-i0"; /* indentation size in characters */ |
---|
110 | char cost[10] = "-m"; /* Cost/page option */ |
---|
111 | char qacct[128] = "-a"; |
---|
112 | char tpfile[] = "errsXXXXXX"; /* file name for filter output */ |
---|
113 | int lflag; /* Log info flag */ |
---|
114 | int account_flag = 0; |
---|
115 | |
---|
116 | printjob() |
---|
117 | { |
---|
118 | struct stat stb; |
---|
119 | register struct queue_ *q, **qp; |
---|
120 | struct queue_ **queue; |
---|
121 | register int i, nitems; |
---|
122 | long pidoff; |
---|
123 | int count = 0; |
---|
124 | extern void abortpr(); |
---|
125 | |
---|
126 | |
---|
127 | init(); /* set up capabilities */ |
---|
128 | (void) write(1, "", 1); /* ack that daemon is started */ |
---|
129 | setgid(getegid()); |
---|
130 | pid = getpid(); /* for use with lprm */ |
---|
131 | setsid(); |
---|
132 | signal(SIGHUP, abortpr); |
---|
133 | signal(SIGINT, abortpr); |
---|
134 | signal(SIGQUIT, abortpr); |
---|
135 | signal(SIGTERM, abortpr); |
---|
136 | |
---|
137 | (void) mktemp(tpfile); |
---|
138 | |
---|
139 | /* |
---|
140 | * uses short form file names |
---|
141 | */ |
---|
142 | if (chdir(SD) < 0) { |
---|
143 | syslog(LOG_ERR, "%s: %m", SD); |
---|
144 | exit(1); |
---|
145 | } |
---|
146 | if (stat(LO, &stb) == 0 && (stb.st_mode & 0100)) |
---|
147 | exit(0); /* printing disabled */ |
---|
148 | lfd = open(LO, O_WRONLY|O_CREAT, 0644); |
---|
149 | if (lfd < 0) { |
---|
150 | syslog(LOG_ERR, "%s: %s: %m", printer, LO); |
---|
151 | exit(1); |
---|
152 | } |
---|
153 | |
---|
154 | if (flock(lfd, LOCK_EX|LOCK_NB) < 0) { |
---|
155 | if (errno == EWOULDBLOCK) /* active daemon present */ |
---|
156 | exit(0); |
---|
157 | syslog(LOG_ERR, "%s: %s: %m", printer, LO); |
---|
158 | exit(1); |
---|
159 | } |
---|
160 | ftruncate(lfd, 0); |
---|
161 | |
---|
162 | /* |
---|
163 | * write process id for others to know |
---|
164 | */ |
---|
165 | sprintf(line, "%u\n", pid); |
---|
166 | pidoff = i = strlen(line); |
---|
167 | if (write(lfd, line, i) != i) { |
---|
168 | syslog(LOG_ERR, "%s: %s: %m", printer, LO); |
---|
169 | exit(1); |
---|
170 | } |
---|
171 | |
---|
172 | /* |
---|
173 | * search the spool directory for work and sort by queue order. |
---|
174 | */ |
---|
175 | if ((nitems = getq_(&queue)) < 0) { |
---|
176 | syslog(LOG_ERR, "%s: can't scan %s", printer, SD); |
---|
177 | exit(1); |
---|
178 | } |
---|
179 | |
---|
180 | if (nitems == 0) /* no work to do */ |
---|
181 | { |
---|
182 | if (lflag) syslog(LOG_INFO, "No work on %s.", printer); |
---|
183 | exit(0); |
---|
184 | } |
---|
185 | if (stb.st_mode & 01) { /* reset queue flag */ |
---|
186 | if (fchmod(lfd, stb.st_mode & 0776) < 0) |
---|
187 | syslog(LOG_ERR, "%s: %s: %m", printer, LO); |
---|
188 | } |
---|
189 | if(lflag) syslog(LOG_INFO, "Opening printer on %s", printer); |
---|
190 | openpr(); /* open printer or remote */ |
---|
191 | again: |
---|
192 | /* |
---|
193 | * we found something to do now do it -- |
---|
194 | * write the name of the current control file into the lock file |
---|
195 | * so the spool queue program can tell what we're working on |
---|
196 | */ |
---|
197 | if (lflag)syslog(LOG_INFO,"Got something to print.."); |
---|
198 | for (qp = queue; nitems--; free((char *) q)) { |
---|
199 | q = *qp++; |
---|
200 | if (stat(q->q_name, &stb) < 0) { |
---|
201 | continue; |
---|
202 | } |
---|
203 | restart: |
---|
204 | (void) lseek(lfd, pidoff, 0); |
---|
205 | (void) sprintf(line, "%s\n", q->q_name); |
---|
206 | i = strlen(line); |
---|
207 | if (write(lfd, line, i) != i) |
---|
208 | syslog(LOG_ERR, "%s: %s: %m", printer, LO); |
---|
209 | |
---|
210 | if (!remote) |
---|
211 | i = printit(q->q_name); |
---|
212 | else |
---|
213 | i = sendit(q->q_name); |
---|
214 | /* |
---|
215 | * Check to see if we are supposed to stop printing or |
---|
216 | * if we are to rebuild the queue. |
---|
217 | */ |
---|
218 | if (fstat(lfd, &stb) == 0) { |
---|
219 | /* stop printing before starting next job? */ |
---|
220 | if (stb.st_mode & 0100) |
---|
221 | goto done; |
---|
222 | /* rebuild queue (after lpc topq) */ |
---|
223 | if (stb.st_mode & 01) { |
---|
224 | for (free((char *) q); nitems--; free((char *) q)) |
---|
225 | q = *qp++; |
---|
226 | if (fchmod(lfd, stb.st_mode & 0776) < 0) |
---|
227 | syslog(LOG_WARNING, "%s: %s: %m", |
---|
228 | printer, LO); |
---|
229 | break; |
---|
230 | } |
---|
231 | if (i == DEFER) { |
---|
232 | if (fchmod(lfd, stb.st_mode | 001) < 0) |
---|
233 | syslog(LOG_WARNING, "%s: %s: %m", |
---|
234 | printer, LO); |
---|
235 | continue; |
---|
236 | } |
---|
237 | } |
---|
238 | if (i == OK) /* file ok and printed */ |
---|
239 | count++; |
---|
240 | else if (i == REPRINT) { /* try reprinting the job */ |
---|
241 | if (lflag)syslog(LOG_INFO, "restarting %s", printer); |
---|
242 | if (ofilter > 0) { |
---|
243 | kill(ofilter, SIGCONT); /* to be sure */ |
---|
244 | (void) close(ofd); |
---|
245 | while ((i = wait(NULL)) > 0 && i != ofilter) |
---|
246 | ; |
---|
247 | ofilter = 0; |
---|
248 | } |
---|
249 | (void) close(pfd); /* close printer */ |
---|
250 | if (ftruncate(lfd, pidoff) < 0) |
---|
251 | syslog(LOG_WARNING, "%s: %s: %m", printer, LO); |
---|
252 | openpr(); /* try to reopen printer */ |
---|
253 | goto restart; |
---|
254 | } |
---|
255 | } |
---|
256 | free((char *) queue); |
---|
257 | /* |
---|
258 | * search the spool directory for more work. |
---|
259 | */ |
---|
260 | if ((nitems = getq_(&queue)) < 0) { |
---|
261 | syslog(LOG_ERR, "%s: can't scan %s", printer, SD); |
---|
262 | exit(1); |
---|
263 | } |
---|
264 | if (nitems == 0) { /* no more work to do */ |
---|
265 | done: |
---|
266 | if (count > 0) { /* Files actually printed */ |
---|
267 | if (!SF && !tof) |
---|
268 | (void) write(ofd, FF, strlen(FF)); |
---|
269 | if (TR != NULL) /* output trailer */ |
---|
270 | (void) write(ofd, TR, strlen(TR)); |
---|
271 | } |
---|
272 | (void) UNLINK(tpfile); |
---|
273 | exit(0); |
---|
274 | } |
---|
275 | goto again; |
---|
276 | } |
---|
277 | |
---|
278 | char fonts[4][50]; /* fonts for troff */ |
---|
279 | |
---|
280 | char ifonts[4][18] = { |
---|
281 | "/usr/lib/vfont/R", |
---|
282 | "/usr/lib/vfont/I", |
---|
283 | "/usr/lib/vfont/B", |
---|
284 | "/usr/lib/vfont/S" |
---|
285 | }; |
---|
286 | |
---|
287 | /* |
---|
288 | * The remaining part is the reading of the control file (cf) |
---|
289 | * and performing the various actions. |
---|
290 | */ |
---|
291 | printit(file) |
---|
292 | char *file; |
---|
293 | { |
---|
294 | register int i; |
---|
295 | char *cp; |
---|
296 | int bombed = OK; |
---|
297 | |
---|
298 | /* |
---|
299 | * open control file; ignore if no longer there. |
---|
300 | */ |
---|
301 | |
---|
302 | if ((cfp = fopen(file, "r+")) == NULL) { |
---|
303 | syslog(LOG_INFO, "%s: %s: %m", printer, file); |
---|
304 | return(OK); |
---|
305 | } |
---|
306 | /* |
---|
307 | * Try to lock control file. If we fail, defer processing |
---|
308 | * this file till later |
---|
309 | */ |
---|
310 | if (!network && (flock(fileno(cfp), LOCK_EX|LOCK_NB) < 0)) { |
---|
311 | |
---|
312 | if (errno == EWOULDBLOCK) { |
---|
313 | /* |
---|
314 | * We couldn't get the lock. Probably lprm |
---|
315 | * has locked it, in preparation for blowing |
---|
316 | * it away. So we defer it till later; |
---|
317 | * usually it won't be there, but just in |
---|
318 | * case some other bozo locks the file.... |
---|
319 | */ |
---|
320 | fclose(cfp); |
---|
321 | cfp = NULL; |
---|
322 | return(DEFER); |
---|
323 | } |
---|
324 | syslog(LOG_ERR, "%s: %s: %m", printer, file); |
---|
325 | exit(1); |
---|
326 | } |
---|
327 | |
---|
328 | /* |
---|
329 | * Reset troff fonts. |
---|
330 | */ |
---|
331 | |
---|
332 | for (i = 0; i < 4; i++) |
---|
333 | strcpy(fonts[i], ifonts[i]); |
---|
334 | sprintf(&width[2], "%d", PW); |
---|
335 | strcpy(indent+2, "0"); |
---|
336 | qacct[2] = NULL; |
---|
337 | jobname[0] = '\0'; |
---|
338 | |
---|
339 | /* |
---|
340 | * read the control file for work to do |
---|
341 | * |
---|
342 | * file format -- first character in the line is a command |
---|
343 | * rest of the line is the argument. |
---|
344 | * valid commands are: |
---|
345 | * |
---|
346 | * S -- "stat info" for symbolic link protection |
---|
347 | * J -- "job name" on banner page |
---|
348 | * C -- "class name" on banner page |
---|
349 | * L -- "literal" user's name to print on banner |
---|
350 | * T -- "title" for pr |
---|
351 | * H -- "host name" of machine where lpr was done |
---|
352 | * P -- "person" user's login name |
---|
353 | * W -- "width" width of page |
---|
354 | * I -- "indent" amount to indent output |
---|
355 | * f -- "file name" name of text file to print |
---|
356 | * l -- "file name" text file with control chars |
---|
357 | * p -- "file name" text file to print with pr(1) |
---|
358 | * t -- "file name" troff(1) file to print |
---|
359 | * n -- "file name" ditroff(1) file to print |
---|
360 | * d -- "file name" dvi file to print |
---|
361 | * g -- "file name" plot(1G) file to print |
---|
362 | * v -- "file name" plain raster file to print |
---|
363 | * c -- "file name" cifplot file to print |
---|
364 | * 1 -- "R font file" for troff |
---|
365 | * 2 -- "I font file" for troff |
---|
366 | * 3 -- "B font file" for troff |
---|
367 | * 4 -- "S font file" for troff |
---|
368 | * N -- "name" of file (used by lpq) |
---|
369 | * U -- "unlink" name of file to remove |
---|
370 | * (after we print it. (Pass 2 only)). |
---|
371 | * M -- "mail" to user when done printing |
---|
372 | * |
---|
373 | * Additions: |
---|
374 | * Z -- send zephyr message to user |
---|
375 | * Q -- Account number for quota management |
---|
376 | * q -- printer queue name |
---|
377 | * getline reads a line and expands tabs to blanks |
---|
378 | */ |
---|
379 | |
---|
380 | /* pass 1 */ |
---|
381 | |
---|
382 | account_flag = 0; |
---|
383 | while (getline(cfp)) |
---|
384 | switch (line[0]) { |
---|
385 | case 'H': |
---|
386 | strcpy(fromhost, line+1); |
---|
387 | if (class[0] == '\0') |
---|
388 | strncpy(class, line+1, sizeof(class)-1); |
---|
389 | continue; |
---|
390 | |
---|
391 | case 'P': |
---|
392 | strncpy(logname, line+1, sizeof(logname)-1); |
---|
393 | if (RS) { /* restricted */ |
---|
394 | if (getpwnam(logname) == (struct passwd *)0) { |
---|
395 | bombed = NOACCT; |
---|
396 | #ifdef ZEPHYR |
---|
397 | sendzephyr(line+1, bombed); |
---|
398 | #else |
---|
399 | sendmail(line+1, bombed); |
---|
400 | #endif ZEPHYR |
---|
401 | goto pass2; |
---|
402 | } |
---|
403 | } |
---|
404 | continue; |
---|
405 | |
---|
406 | case 'A': /* For old client compatibility */ |
---|
407 | case 'Q': |
---|
408 | if (line[1] != '\0') { |
---|
409 | strcpy(&qacct[2], line+1); |
---|
410 | account_flag = 1; |
---|
411 | } |
---|
412 | continue; |
---|
413 | |
---|
414 | case 'S': |
---|
415 | cp = line+1; |
---|
416 | i = 0; |
---|
417 | while (*cp >= '0' && *cp <= '9') |
---|
418 | i = i * 10 + (*cp++ - '0'); |
---|
419 | fdev = i; |
---|
420 | cp++; |
---|
421 | i = 0; |
---|
422 | while (*cp >= '0' && *cp <= '9') |
---|
423 | i = i * 10 + (*cp++ - '0'); |
---|
424 | fino = i; |
---|
425 | continue; |
---|
426 | |
---|
427 | case 'J': |
---|
428 | if (line[1] != '\0') |
---|
429 | strncpy(jobname, line+1, sizeof(jobname)-1); |
---|
430 | else |
---|
431 | strcpy(jobname, " "); |
---|
432 | continue; |
---|
433 | |
---|
434 | case 'C': |
---|
435 | if (line[1] != '\0') |
---|
436 | strncpy(class, line+1, sizeof(class)-1); |
---|
437 | else if (class[0] == '\0') |
---|
438 | { |
---|
439 | struct hostent *hp; |
---|
440 | gethostname(class, sizeof(class)); |
---|
441 | hp = gethostbyname(class); |
---|
442 | if (hp) { |
---|
443 | strncpy(class, hp -> h_name, sizeof(class)); |
---|
444 | class[sizeof(class) - 1] = '\0'; |
---|
445 | } |
---|
446 | } |
---|
447 | continue; |
---|
448 | |
---|
449 | case 'T': /* header title for pr */ |
---|
450 | strncpy(title, line+1, sizeof(title)-1); |
---|
451 | continue; |
---|
452 | |
---|
453 | case 'L': /* identification line */ |
---|
454 | if (!SH && !HL) |
---|
455 | banner(line+1, jobname); |
---|
456 | continue; |
---|
457 | |
---|
458 | case '1': /* troff fonts */ |
---|
459 | case '2': |
---|
460 | case '3': |
---|
461 | case '4': |
---|
462 | if (line[1] != '\0') |
---|
463 | strcpy(fonts[line[0]-'1'], line+1); |
---|
464 | continue; |
---|
465 | |
---|
466 | case 'W': /* page width */ |
---|
467 | strncpy(width+2, line+1, sizeof(width)-3); |
---|
468 | continue; |
---|
469 | |
---|
470 | case 'I': /* indent amount */ |
---|
471 | strncpy(indent+2, line+1, sizeof(indent)-3); |
---|
472 | continue; |
---|
473 | |
---|
474 | default: /* some file to print */ |
---|
475 | switch (i = print(line[0], line+1)) { |
---|
476 | case ERROR: |
---|
477 | if (bombed == OK) |
---|
478 | bombed = FATALERR; |
---|
479 | break; |
---|
480 | case REPRINT: |
---|
481 | (void) fclose(cfp); |
---|
482 | cfp = NULL; |
---|
483 | |
---|
484 | return(REPRINT); |
---|
485 | case FILTERERR: |
---|
486 | case ACCESS: |
---|
487 | bombed = i; |
---|
488 | #ifdef ZEPHYR |
---|
489 | sendzephyr(logname, bombed); |
---|
490 | #else |
---|
491 | sendmail(logname, bombed); |
---|
492 | #endif ZEPHYR |
---|
493 | } |
---|
494 | title[0] = '\0'; |
---|
495 | continue; |
---|
496 | |
---|
497 | case 'N': |
---|
498 | case 'U': |
---|
499 | case 'M': |
---|
500 | case 'Z': |
---|
501 | case 'E': /* From multics days */ |
---|
502 | continue; |
---|
503 | |
---|
504 | case 'q': |
---|
505 | if (line[1]) { |
---|
506 | strncpy(queuename, line+1, sizeof(queuename)-1); |
---|
507 | printer = queuename; |
---|
508 | } |
---|
509 | continue; |
---|
510 | } |
---|
511 | |
---|
512 | /* pass 2 */ |
---|
513 | |
---|
514 | pass2: |
---|
515 | fseek(cfp, 0L, 0); |
---|
516 | while (getline(cfp)) |
---|
517 | switch (line[0]) { |
---|
518 | case 'L': /* identification line */ |
---|
519 | if (!SH && HL) |
---|
520 | banner(line+1, jobname); |
---|
521 | continue; |
---|
522 | |
---|
523 | case 'M': |
---|
524 | if (bombed < NOACCT) /* already sent if >= NOACCT */ |
---|
525 | sendmail(line+1, bombed); |
---|
526 | continue; |
---|
527 | |
---|
528 | case 'U': |
---|
529 | (void) spool_unlink(line+1, 'd', 1); |
---|
530 | continue; |
---|
531 | #ifdef ZEPHYR |
---|
532 | case 'Z': |
---|
533 | if (bombed < NOACCT) /* already sent if >= NOACCT */ |
---|
534 | sendzephyr(line+1, bombed); |
---|
535 | continue; |
---|
536 | #endif ZEPHYR |
---|
537 | |
---|
538 | } |
---|
539 | /* |
---|
540 | * clean-up in case another control file exists |
---|
541 | */ |
---|
542 | (void) fclose(cfp); |
---|
543 | cfp = NULL; |
---|
544 | (void) spool_unlink(file, 'c', 1); |
---|
545 | return(bombed == OK ? OK : ERROR); |
---|
546 | } |
---|
547 | |
---|
548 | /* |
---|
549 | * Print a file. |
---|
550 | * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}. |
---|
551 | * Return -1 if a non-recoverable error occured, |
---|
552 | * 2 if the filter detected some errors (but printed the job anyway), |
---|
553 | * 1 if we should try to reprint this job and |
---|
554 | * 0 if all is well. |
---|
555 | * Note: all filters take stdin as the file, stdout as the printer, |
---|
556 | * stderr as the log file, and must not ignore SIGINT. |
---|
557 | */ |
---|
558 | print(format, file) |
---|
559 | int format; |
---|
560 | char *file; |
---|
561 | { |
---|
562 | register int n; |
---|
563 | register char *prog; |
---|
564 | int fi, fo; |
---|
565 | char *av[15], buf[BUFSIZ]; |
---|
566 | int pid, p[2], stopped = 0; |
---|
567 | #if defined(POSIX) && !defined(ultrix) |
---|
568 | int status; |
---|
569 | #else |
---|
570 | union wait status; |
---|
571 | #endif |
---|
572 | struct stat stb; |
---|
573 | |
---|
574 | if (file[0] == '.' || strchr(file, '/')) { |
---|
575 | syslog(LOG_ERR, "lpd attempted to print %s", file); |
---|
576 | return(ERROR); |
---|
577 | } |
---|
578 | if (file[0] != 'd' || file[1] != 'f' || |
---|
579 | file[2] != 'A' || !isxdigit(file[3]) || |
---|
580 | !isxdigit(file[4]) || !isxdigit(file[5])) { |
---|
581 | syslog(LOG_NOTICE, |
---|
582 | "nonstandard job character for print in %d.%d.%d.%d.%d.%d", |
---|
583 | file[0], file[1], file[2], file[3], |
---|
584 | file[4], file[5]); |
---|
585 | } |
---|
586 | |
---|
587 | if (lstat(file, &stb) < 0 || (fi = open(file, O_RDONLY)) < 0) |
---|
588 | return(ERROR); |
---|
589 | /* |
---|
590 | * Check to see if data file is a symbolic link. If so, it should |
---|
591 | * still point to the same file or someone is trying to print |
---|
592 | * something he shouldn't. |
---|
593 | */ |
---|
594 | if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(fi, &stb) == 0 && |
---|
595 | (stb.st_dev != fdev || stb.st_ino != fino)) |
---|
596 | return(ACCESS); |
---|
597 | if (!SF && !tof) { /* start on a fresh page */ |
---|
598 | (void) write(ofd, FF, strlen(FF)); |
---|
599 | tof = 1; |
---|
600 | } |
---|
601 | if (IF == NULL && (format == 'f' || format == 'l')) { |
---|
602 | tof = 0; |
---|
603 | while ((n = read(fi, buf, BUFSIZ)) > 0) |
---|
604 | if (write(ofd, buf, n) != n) { |
---|
605 | (void) close(fi); |
---|
606 | return(REPRINT); |
---|
607 | } |
---|
608 | (void) close(fi); |
---|
609 | return(OK); |
---|
610 | } |
---|
611 | switch (format) { |
---|
612 | case 'p': /* print file using 'pr' */ |
---|
613 | if (IF == NULL) { /* use output filter */ |
---|
614 | prog = PR; |
---|
615 | av[0] = "pr"; |
---|
616 | av[1] = width; |
---|
617 | av[2] = length; |
---|
618 | av[3] = "-h"; |
---|
619 | av[4] = *title ? title : " "; |
---|
620 | av[5] = 0; |
---|
621 | fo = ofd; |
---|
622 | goto start; |
---|
623 | } |
---|
624 | pipe(p); |
---|
625 | if ((prchild = dofork(DORETURN)) == 0) { /* child */ |
---|
626 | dup2(fi, 0); /* file is stdin */ |
---|
627 | dup2(p[1], 1); /* pipe is stdout */ |
---|
628 | for (n = 3; n < NOFILE; n++) |
---|
629 | (void) close(n); |
---|
630 | execl(PR, "pr", width, length, "-h", *title ? title : " ", 0); |
---|
631 | syslog(LOG_ERR, "cannot execl %s", PR); |
---|
632 | exit(2); |
---|
633 | } |
---|
634 | (void) close(p[1]); /* close output side */ |
---|
635 | (void) close(fi); |
---|
636 | if (prchild < 0) { |
---|
637 | prchild = 0; |
---|
638 | (void) close(p[0]); |
---|
639 | return(ERROR); |
---|
640 | } |
---|
641 | fi = p[0]; /* use pipe for input */ |
---|
642 | case 'f': /* print plain text file */ |
---|
643 | prog = IF; |
---|
644 | av[1] = width; |
---|
645 | av[2] = length; |
---|
646 | av[3] = indent; |
---|
647 | n = 4; |
---|
648 | break; |
---|
649 | case 'l': /* like 'f' but pass control characters */ |
---|
650 | prog = IF; |
---|
651 | av[1] = "-c"; |
---|
652 | av[2] = width; |
---|
653 | av[3] = length; |
---|
654 | av[4] = indent; |
---|
655 | n = 5; |
---|
656 | break; |
---|
657 | case 'r': /* print a fortran text file */ |
---|
658 | prog = RF; |
---|
659 | av[1] = width; |
---|
660 | av[2] = length; |
---|
661 | n = 3; |
---|
662 | break; |
---|
663 | case 't': /* print troff output */ |
---|
664 | case 'n': /* print ditroff output */ |
---|
665 | case 'd': /* print tex output */ |
---|
666 | (void) UNLINK(".railmag"); |
---|
667 | if ((fo = creat(".railmag", FILMOD)) < 0) { |
---|
668 | syslog(LOG_ERR, "%s: cannot create .railmag", printer); |
---|
669 | (void) UNLINK(".railmag"); |
---|
670 | } else { |
---|
671 | for (n = 0; n < 4; n++) { |
---|
672 | if (fonts[n][0] != '/') |
---|
673 | (void) write(fo, "/usr/lib/vfont/", 15); |
---|
674 | (void) write(fo, fonts[n], strlen(fonts[n])); |
---|
675 | (void) write(fo, "\n", 1); |
---|
676 | } |
---|
677 | (void) close(fo); |
---|
678 | } |
---|
679 | prog = (format == 't') ? TF : (format == 'n') ? NF : DF; |
---|
680 | av[1] = pxwidth; |
---|
681 | av[2] = pxlength; |
---|
682 | n = 3; |
---|
683 | break; |
---|
684 | case 'c': /* print cifplot output */ |
---|
685 | prog = CF; |
---|
686 | av[1] = pxwidth; |
---|
687 | av[2] = pxlength; |
---|
688 | n = 3; |
---|
689 | break; |
---|
690 | case 'g': /* print plot(1G) output */ |
---|
691 | prog = GF; |
---|
692 | av[1] = pxwidth; |
---|
693 | av[2] = pxlength; |
---|
694 | n = 3; |
---|
695 | break; |
---|
696 | case 'v': /* print raster output */ |
---|
697 | prog = VF; |
---|
698 | av[1] = pxwidth; |
---|
699 | av[2] = pxlength; |
---|
700 | n = 3; |
---|
701 | break; |
---|
702 | default: |
---|
703 | (void) close(fi); |
---|
704 | syslog(LOG_ERR, "%s: illegal format character '%c'", |
---|
705 | printer, format); |
---|
706 | return(ERROR); |
---|
707 | } |
---|
708 | if ((av[0] = strrchr(prog, '/')) != NULL) |
---|
709 | av[0]++; |
---|
710 | else |
---|
711 | av[0] = prog; |
---|
712 | av[n++] = "-P"; |
---|
713 | av[n++] = printer; |
---|
714 | av[n++] = "-n"; |
---|
715 | av[n++] = logname; |
---|
716 | av[n++] = "-h"; |
---|
717 | av[n++] = fromhost; |
---|
718 | av[n++] = cost; |
---|
719 | if (account_flag) |
---|
720 | av[n++] = qacct; |
---|
721 | av[n++] = AF; |
---|
722 | av[n] = 0; |
---|
723 | fo = pfd; |
---|
724 | if (ofilter > 0) { /* stop output filter */ |
---|
725 | write(ofd, "\031\1", 2); |
---|
726 | #if defined(POSIX) && !defined(ultrix) |
---|
727 | while ((pid = waitpid(-1,(int *)&status, WUNTRACED)) > 0 && pid != ofilter) |
---|
728 | #else |
---|
729 | while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter) |
---|
730 | #endif |
---|
731 | ; |
---|
732 | if (pid == -1 || !WIFSTOPPED(status)) { |
---|
733 | (void) close(fi); |
---|
734 | syslog(LOG_WARNING, "%s: output filter died (%d)", |
---|
735 | printer, WEXITSTATUS(status)); |
---|
736 | return(REPRINT); |
---|
737 | } |
---|
738 | stopped++; |
---|
739 | } |
---|
740 | start: |
---|
741 | if ((child = dofork(DORETURN)) == 0) { /* child */ |
---|
742 | dup2(fi, 0); |
---|
743 | dup2(fo, 1); |
---|
744 | n = open(tpfile, O_WRONLY|O_CREAT|O_TRUNC, 0664); |
---|
745 | if (n >= 0) |
---|
746 | dup2(n, 2); |
---|
747 | for (n = 3; n < NOFILE; n++) |
---|
748 | (void) close(n); |
---|
749 | execv(prog, av); |
---|
750 | syslog(LOG_ERR, "cannot execv %s", prog); |
---|
751 | exit(2); |
---|
752 | } |
---|
753 | (void) close(fi); |
---|
754 | if (child < 0) |
---|
755 | #if defined(POSIX) && !defined(ultrix) |
---|
756 | status= 100; |
---|
757 | #else |
---|
758 | status.w_retcode = 100; |
---|
759 | #endif |
---|
760 | else |
---|
761 | while ((pid = waitpid(-1, &status, WUNTRACED)) > 0 && pid != child) ; |
---|
762 | child = 0; |
---|
763 | prchild = 0; |
---|
764 | |
---|
765 | if (stopped) { /* restart output filter */ |
---|
766 | if (kill(ofilter, SIGCONT) < 0) { |
---|
767 | syslog(LOG_ERR, "cannot restart output filter"); |
---|
768 | exit(1); |
---|
769 | } |
---|
770 | |
---|
771 | if (isatty(pfd)) { |
---|
772 | setty (); |
---|
773 | #if defined(POSIX) && !defined(ultrix) |
---|
774 | if (MS) |
---|
775 | setms(); |
---|
776 | #endif |
---|
777 | } |
---|
778 | } |
---|
779 | tof = 0; |
---|
780 | #ifdef _AUX_SOURCE |
---|
781 | /* WIFEXITED on the MAC with POSIX_SOURCE uses wrong macro */ |
---|
782 | if (!(((status).w_stopval != WSTOPPED && (status).w_termsig == 0))) { |
---|
783 | #else |
---|
784 | if (!WIFEXITED(status)) { |
---|
785 | #endif |
---|
786 | syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)", |
---|
787 | printer, format, WTERMSIG(status)); |
---|
788 | return(ERROR); |
---|
789 | } |
---|
790 | switch (WEXITSTATUS(status)) { |
---|
791 | case 0: |
---|
792 | tof = 1; |
---|
793 | return(OK); |
---|
794 | case 1: |
---|
795 | return(REPRINT); |
---|
796 | default: |
---|
797 | syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)", |
---|
798 | printer, format, WEXITSTATUS(status)); |
---|
799 | case 2: |
---|
800 | return(ERROR); |
---|
801 | } |
---|
802 | } |
---|
803 | |
---|
804 | /* |
---|
805 | * Send the daemon control file (cf) and any data files. |
---|
806 | * Return -1 if a non-recoverable error occured, 1 if a recoverable error and |
---|
807 | * 0 if all is well. |
---|
808 | */ |
---|
809 | sendit(file) |
---|
810 | char *file; |
---|
811 | { |
---|
812 | register int i, err = OK; |
---|
813 | char *cp, last[BUFSIZ]; |
---|
814 | |
---|
815 | /* |
---|
816 | * open control file |
---|
817 | */ |
---|
818 | if ((cfp = fopen(file, "r")) == NULL) |
---|
819 | return(OK); |
---|
820 | /* |
---|
821 | * read the control file for work to do |
---|
822 | * |
---|
823 | * file format -- first character in the line is a command |
---|
824 | * rest of the line is the argument. |
---|
825 | * commands of interest are: |
---|
826 | * |
---|
827 | * a-z -- "file name" name of file to print |
---|
828 | * U -- "unlink" name of file to remove |
---|
829 | * (after we print it. (Pass 2 only)). |
---|
830 | */ |
---|
831 | |
---|
832 | /* |
---|
833 | * pass 1 |
---|
834 | */ |
---|
835 | while (getline(cfp)) { |
---|
836 | again: |
---|
837 | if (line[0] == 'S') { |
---|
838 | cp = line+1; |
---|
839 | i = 0; |
---|
840 | while (*cp >= '0' && *cp <= '9') |
---|
841 | i = i * 10 + (*cp++ - '0'); |
---|
842 | fdev = i; |
---|
843 | cp++; |
---|
844 | i = 0; |
---|
845 | while (*cp >= '0' && *cp <= '9') |
---|
846 | i = i * 10 + (*cp++ - '0'); |
---|
847 | fino = i; |
---|
848 | continue; |
---|
849 | } |
---|
850 | if (line[0] >= 'a' && line[0] <= 'z' && line[0] != 'q') { |
---|
851 | strncpy(last, line, sizeof(last)); |
---|
852 | last[sizeof(last) - 1] = '\0'; |
---|
853 | while (i = getline(cfp)) |
---|
854 | if (strcmp(last, line)) |
---|
855 | break; |
---|
856 | switch (sendfile('\3', last+1)) { |
---|
857 | case OK: |
---|
858 | if (i) |
---|
859 | goto again; |
---|
860 | break; |
---|
861 | case REPRINT: |
---|
862 | (void) fclose(cfp); |
---|
863 | cfp = NULL; |
---|
864 | return(REPRINT); |
---|
865 | case ACCESS: |
---|
866 | #ifdef ZEPHYR |
---|
867 | sendmail(logname, ACCESS); |
---|
868 | #else |
---|
869 | sendzephyr(logname, ACCESS); |
---|
870 | #endif ZEPHYR |
---|
871 | case ERROR: |
---|
872 | err = ERROR; |
---|
873 | } |
---|
874 | break; |
---|
875 | } |
---|
876 | } |
---|
877 | if (err == OK && sendfile('\2', file) > 0) { |
---|
878 | (void) fclose(cfp); |
---|
879 | cfp = NULL; |
---|
880 | return(REPRINT); |
---|
881 | } |
---|
882 | /* |
---|
883 | * pass 2 |
---|
884 | */ |
---|
885 | fseek(cfp, 0L, 0); |
---|
886 | while (getline(cfp)) |
---|
887 | if (line[0] == 'U') |
---|
888 | (void) spool_unlink(line+1, 'd', 1); |
---|
889 | /* |
---|
890 | * clean-up in case another control file exists |
---|
891 | */ |
---|
892 | (void) fclose(cfp); |
---|
893 | cfp = NULL; |
---|
894 | (void) spool_unlink(file, 'c', 1); |
---|
895 | return(err); |
---|
896 | } |
---|
897 | |
---|
898 | /* |
---|
899 | * Send a data file to the remote machine and spool it. |
---|
900 | * Return positive if we should try resending. |
---|
901 | */ |
---|
902 | sendfile(type, file) |
---|
903 | char type, *file; |
---|
904 | { |
---|
905 | register int f, i, amt; |
---|
906 | struct stat stb; |
---|
907 | char buf[BUFSIZ]; |
---|
908 | int sizerr, resp; |
---|
909 | |
---|
910 | if (lstat(file, &stb) < 0 || (f = open(file, O_RDONLY)) < 0) |
---|
911 | return(ERROR); |
---|
912 | /* |
---|
913 | * Check to see if data file is a symbolic link. If so, it should |
---|
914 | * still point to the same file or someone is trying to print something |
---|
915 | * he shouldn't. |
---|
916 | */ |
---|
917 | if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(f, &stb) == 0 && |
---|
918 | (stb.st_dev != fdev || stb.st_ino != fino)) |
---|
919 | return(ACCESS); |
---|
920 | (void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file); |
---|
921 | amt = strlen(buf); |
---|
922 | for (i = 0; ; i++) { |
---|
923 | if (write(pfd, buf, amt) != amt || |
---|
924 | (resp = response()) < 0 || resp == '\1') { |
---|
925 | (void) close(f); |
---|
926 | return(REPRINT); |
---|
927 | } else if (resp == '\0') |
---|
928 | break; |
---|
929 | if (i == 0) |
---|
930 | status("no space on remote; waiting for queue to drain"); |
---|
931 | if (i == 10) |
---|
932 | syslog(LOG_ALERT, "%s: can't send to %s; queue full", |
---|
933 | printer, RM); |
---|
934 | sleep(5 * 60); |
---|
935 | } |
---|
936 | if (i) |
---|
937 | status("sending to %s", RM); |
---|
938 | sizerr = 0; |
---|
939 | for (i = 0; i < stb.st_size; i += BUFSIZ) { |
---|
940 | amt = BUFSIZ; |
---|
941 | if (i + amt > stb.st_size) |
---|
942 | amt = stb.st_size - i; |
---|
943 | if (sizerr == 0 && read(f, buf, amt) != amt) |
---|
944 | sizerr = 1; |
---|
945 | if (write(pfd, buf, amt) != amt) { |
---|
946 | (void) close(f); |
---|
947 | return(REPRINT); |
---|
948 | } |
---|
949 | } |
---|
950 | (void) close(f); |
---|
951 | if (sizerr) { |
---|
952 | syslog(LOG_INFO, "%s: %s: changed size", printer, file); |
---|
953 | /* tell recvjob to ignore this file */ |
---|
954 | (void) write(pfd, "\1", 1); |
---|
955 | return(ERROR); |
---|
956 | } |
---|
957 | if (write(pfd, "", 1) != 1 || response()) |
---|
958 | return(REPRINT); |
---|
959 | return(OK); |
---|
960 | } |
---|
961 | |
---|
962 | /* |
---|
963 | * Check to make sure there have been no errors and that both programs |
---|
964 | * are in sync with eachother. |
---|
965 | * Return non-zero if the connection was lost. |
---|
966 | */ |
---|
967 | response() |
---|
968 | { |
---|
969 | char resp; |
---|
970 | |
---|
971 | if (read(pfd, &resp, 1) != 1) { |
---|
972 | syslog(LOG_INFO, "%s: lost connection", printer); |
---|
973 | return(-1); |
---|
974 | } |
---|
975 | return(resp); |
---|
976 | } |
---|
977 | |
---|
978 | /* |
---|
979 | * Banner printing stuff |
---|
980 | */ |
---|
981 | banner(name1, name2) |
---|
982 | char *name1, *name2; |
---|
983 | { |
---|
984 | time_t tvec; |
---|
985 | extern char *ctime(); |
---|
986 | |
---|
987 | time(&tvec); |
---|
988 | if (!SF && !tof) |
---|
989 | (void) write(ofd, FF, strlen(FF)); |
---|
990 | if (SB) { /* short banner only */ |
---|
991 | if (class[0]) { |
---|
992 | (void) write(ofd, class, strlen(class)); |
---|
993 | (void) write(ofd, ":", 1); |
---|
994 | } |
---|
995 | (void) write(ofd, name1, strlen(name1)); |
---|
996 | (void) write(ofd, " Job: ", 7); |
---|
997 | (void) write(ofd, name2, strlen(name2)); |
---|
998 | (void) write(ofd, " Date: ", 8); |
---|
999 | (void) write(ofd, ctime(&tvec), 24); |
---|
1000 | (void) write(ofd, "\n", 1); |
---|
1001 | } else { /* normal banner */ |
---|
1002 | (void) write(ofd, "\n\n\n", 3); |
---|
1003 | scan_out(ofd, name1, '\0'); |
---|
1004 | (void) write(ofd, "\n\n", 2); |
---|
1005 | scan_out(ofd, name2, '\0'); |
---|
1006 | if (class[0]) { |
---|
1007 | register char *cp; |
---|
1008 | (void) write(ofd,"\n\n\n",3); |
---|
1009 | /* Take out domain names, if any */ |
---|
1010 | if (cp = strchr(class, '.')) *cp = '\0'; |
---|
1011 | scan_out(ofd, class, '\0'); |
---|
1012 | } |
---|
1013 | (void) write(ofd, "\n\n\n\n\t\t\t\tJob: ", 17); |
---|
1014 | (void) write(ofd, name2, strlen(name2)); |
---|
1015 | |
---|
1016 | (void) write(ofd, "\n\t\t\t\tUser: ", 14); |
---|
1017 | if (logname[0]) (void) write (ofd, logname, strlen(logname)); |
---|
1018 | else (void) write(ofd, name1, strlen(name1)); |
---|
1019 | |
---|
1020 | if (class[0] || fromhost[0]) { |
---|
1021 | (void) write (ofd, "@", 1); |
---|
1022 | if (fromhost[0]) { |
---|
1023 | (void) write (ofd, fromhost, strlen(fromhost)); |
---|
1024 | } |
---|
1025 | else { |
---|
1026 | (void) write (ofd, class, strlen(class)); |
---|
1027 | } |
---|
1028 | } |
---|
1029 | |
---|
1030 | (void) write(ofd, "\n\t\t\t\tDate: ", 14); |
---|
1031 | (void) write(ofd, ctime(&tvec), 24); |
---|
1032 | |
---|
1033 | if (printer != (char *) NULL && *printer != '\0') { |
---|
1034 | (void) write (ofd, "\n\t\t\t\tPrinter: ", 14); |
---|
1035 | (void) write (ofd, printer, strlen(printer)); |
---|
1036 | if (host != (char *) NULL && *host != '\0') { |
---|
1037 | (void) write (ofd, " (on ", 5); |
---|
1038 | (void) write (ofd, host, strlen(host)); |
---|
1039 | (void) write (ofd, ")", 1); |
---|
1040 | } |
---|
1041 | } |
---|
1042 | |
---|
1043 | (void) write(ofd, "\n", 1); |
---|
1044 | } |
---|
1045 | if (!SF) |
---|
1046 | (void) write(ofd, FF, strlen(FF)); |
---|
1047 | tof = 1; |
---|
1048 | } |
---|
1049 | |
---|
1050 | char * |
---|
1051 | scnline(key, p, c) |
---|
1052 | register char key, *p; |
---|
1053 | char c; |
---|
1054 | { |
---|
1055 | register int scnwidth; |
---|
1056 | |
---|
1057 | for (scnwidth = WIDTH; --scnwidth;) { |
---|
1058 | key <<= 1; |
---|
1059 | *p++ = key & 0200 ? c : BACKGND; |
---|
1060 | } |
---|
1061 | return (p); |
---|
1062 | } |
---|
1063 | |
---|
1064 | #define TRC(q) (((q)-' ')&0177) |
---|
1065 | |
---|
1066 | scan_out(scfd, scsp, dlm) |
---|
1067 | int scfd; |
---|
1068 | char *scsp, dlm; |
---|
1069 | { |
---|
1070 | register char *strp; |
---|
1071 | register nchrs, j; |
---|
1072 | char outbuf[LINELEN+1], *sp, c, cc; |
---|
1073 | int d, scnhgt; |
---|
1074 | extern char scnkey[][HEIGHT]; /* in lpdchar.c */ |
---|
1075 | |
---|
1076 | for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) { |
---|
1077 | strp = &outbuf[0]; |
---|
1078 | sp = scsp; |
---|
1079 | for (nchrs = 0; ; ) { |
---|
1080 | d = dropit(c = TRC(cc = *sp++)); |
---|
1081 | if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d)) |
---|
1082 | for (j = WIDTH; --j;) |
---|
1083 | *strp++ = BACKGND; |
---|
1084 | else |
---|
1085 | strp = scnline(scnkey[c][scnhgt-1-d], strp, cc); |
---|
1086 | if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1) |
---|
1087 | break; |
---|
1088 | *strp++ = BACKGND; |
---|
1089 | *strp++ = BACKGND; |
---|
1090 | } |
---|
1091 | while (*--strp == BACKGND && strp >= outbuf) |
---|
1092 | ; |
---|
1093 | strp++; |
---|
1094 | *strp++ = '\n'; |
---|
1095 | (void) write(scfd, outbuf, strp-outbuf); |
---|
1096 | } |
---|
1097 | } |
---|
1098 | |
---|
1099 | dropit(c) |
---|
1100 | char c; |
---|
1101 | { |
---|
1102 | switch(c) { |
---|
1103 | |
---|
1104 | case TRC('_'): |
---|
1105 | case TRC(';'): |
---|
1106 | case TRC(','): |
---|
1107 | case TRC('g'): |
---|
1108 | case TRC('j'): |
---|
1109 | case TRC('p'): |
---|
1110 | case TRC('q'): |
---|
1111 | case TRC('y'): |
---|
1112 | return (DROP); |
---|
1113 | |
---|
1114 | default: |
---|
1115 | return (0); |
---|
1116 | } |
---|
1117 | } |
---|
1118 | |
---|
1119 | /* |
---|
1120 | * sendmail --- |
---|
1121 | * tell people about job completion |
---|
1122 | */ |
---|
1123 | sendmail(user, bombed) |
---|
1124 | char *user; |
---|
1125 | int bombed; |
---|
1126 | { |
---|
1127 | register int i; |
---|
1128 | int p[2], s; |
---|
1129 | register char *cp; |
---|
1130 | char buf[MAXHOSTNAMELEN + 100]; |
---|
1131 | struct stat stb; |
---|
1132 | FILE *fp; |
---|
1133 | #ifdef ALLOW_MAIL |
---|
1134 | pipe(p); |
---|
1135 | if ((s = dofork(DORETURN)) == 0) { /* child */ |
---|
1136 | dup2(p[0], 0); |
---|
1137 | for (i = 3; i < NOFILE; i++) |
---|
1138 | (void) close(i); |
---|
1139 | if ((cp = strrchr(MAIL, '/')) != NULL) |
---|
1140 | cp++; |
---|
1141 | else |
---|
1142 | cp = MAIL; |
---|
1143 | sprintf(buf, "%s@%s", user, fromhost); |
---|
1144 | execl(MAIL, cp, buf, 0); |
---|
1145 | exit(0); |
---|
1146 | } else if (s > 0) { /* parent */ |
---|
1147 | dup2(p[1], 1); |
---|
1148 | printf("To: %s@%s\n", user, fromhost); |
---|
1149 | printf("Subject: printer job\n\n"); |
---|
1150 | printf("Your printer job "); |
---|
1151 | if (*jobname) |
---|
1152 | printf("(%s) ", jobname); |
---|
1153 | switch (bombed) { |
---|
1154 | case OK: |
---|
1155 | printf("\ncompleted successfully\n"); |
---|
1156 | break; |
---|
1157 | default: |
---|
1158 | case FATALERR: |
---|
1159 | printf("\ncould not be printed\n"); |
---|
1160 | break; |
---|
1161 | case NOACCT: |
---|
1162 | printf("\ncould not be printed without an account on %s\n", host); |
---|
1163 | break; |
---|
1164 | case FILTERERR: |
---|
1165 | if (stat(tpfile, &stb) < 0 || stb.st_size == 0 || |
---|
1166 | (fp = fopen(tpfile, "r")) == NULL) { |
---|
1167 | printf("\nwas printed but had some errors\n"); |
---|
1168 | break; |
---|
1169 | } |
---|
1170 | printf("\nwas printed but had the following errors:\n"); |
---|
1171 | while ((i = getc(fp)) != EOF) |
---|
1172 | putchar(i); |
---|
1173 | (void) fclose(fp); |
---|
1174 | break; |
---|
1175 | case ACCESS: |
---|
1176 | printf("\nwas not printed because it was not linked to the original file\n"); |
---|
1177 | } |
---|
1178 | fflush(stdout); |
---|
1179 | (void) close(1); |
---|
1180 | } |
---|
1181 | (void) close(p[0]); |
---|
1182 | (void) close(p[1]); |
---|
1183 | wait(&s); |
---|
1184 | #endif |
---|
1185 | } |
---|
1186 | |
---|
1187 | #ifdef ZEPHYR |
---|
1188 | sendzephyr(user, bombed) |
---|
1189 | char *user; |
---|
1190 | int bombed; |
---|
1191 | { |
---|
1192 | notice.z_kind=UNACKED; |
---|
1193 | notice.z_port=0; |
---|
1194 | notice.z_class=ZCLASS; |
---|
1195 | notice.z_class_inst=ZINSTANCE; |
---|
1196 | notice.z_opcode=""; |
---|
1197 | notice.z_sender=ZSENDER; |
---|
1198 | strncpy(zrecipient,logname,sizeof(zrecipient)); |
---|
1199 | zrecipient[sizeof(zrecipient) - 1] = '\0'; |
---|
1200 | notice.z_recipient=zrecipient; |
---|
1201 | notice.z_default_format=ZDEFAULTFORMAT; |
---|
1202 | notice.z_num_other_fields=0; |
---|
1203 | |
---|
1204 | if(*jobname) |
---|
1205 | sprintf(zmessagetext,"Printer status for %s:\n\nJob name: %s\n%s", |
---|
1206 | printer,jobname,zerrtext[bombed+4]); |
---|
1207 | else |
---|
1208 | sprintf(zmessagetext,"Printer status for %s:\n\n%s", |
---|
1209 | printer,zerrtext[bombed+4]); |
---|
1210 | zmessage[0]="Printer Daemon"; |
---|
1211 | zmessage[1]=zmessagetext; |
---|
1212 | zmessage[2]=printer; |
---|
1213 | zmessage[3]=line+1; |
---|
1214 | zmessage[4]=zerrtext[bombed+4]; |
---|
1215 | zmessage[5]=zerrtoken[bombed+4]; |
---|
1216 | |
---|
1217 | if (zerrno=ZSendList(¬ice,zmessage,6,ZNOAUTH)) |
---|
1218 | syslog(LOG_ERR,"Error sending zephyr notification: zerrno=%d", |
---|
1219 | zerrno); |
---|
1220 | } |
---|
1221 | #endif ZEPHYR |
---|
1222 | |
---|
1223 | |
---|
1224 | /* |
---|
1225 | * dofork - fork with retries on failure |
---|
1226 | */ |
---|
1227 | dofork(action) |
---|
1228 | int action; |
---|
1229 | { |
---|
1230 | register int i, pid; |
---|
1231 | |
---|
1232 | for (i = 0; i < 20; i++) { |
---|
1233 | if ((pid = fork()) < 0) { |
---|
1234 | sleep((unsigned)(i*i)); |
---|
1235 | continue; |
---|
1236 | } |
---|
1237 | /* |
---|
1238 | * Child should run as daemon instead of root |
---|
1239 | */ |
---|
1240 | if (pid == 0) |
---|
1241 | setuid(DU); |
---|
1242 | return(pid); |
---|
1243 | } |
---|
1244 | syslog(LOG_ERR, "can't fork"); |
---|
1245 | |
---|
1246 | switch (action) { |
---|
1247 | case DORETURN: |
---|
1248 | return (-1); |
---|
1249 | default: |
---|
1250 | syslog(LOG_ERR, "bad action (%d) to dofork", action); |
---|
1251 | /*FALL THRU*/ |
---|
1252 | case DOABORT: |
---|
1253 | exit(1); |
---|
1254 | } |
---|
1255 | /*NOTREACHED*/ |
---|
1256 | } |
---|
1257 | |
---|
1258 | /* |
---|
1259 | * Kill child processes to abort current job. |
---|
1260 | */ |
---|
1261 | void |
---|
1262 | abortpr() |
---|
1263 | { |
---|
1264 | void hard_kill(); |
---|
1265 | |
---|
1266 | /* Drop the lock on the control file, if necessary */ |
---|
1267 | if (cfp) |
---|
1268 | (void) fclose(cfp); |
---|
1269 | /* Drop lock on lock file as well */ |
---|
1270 | if (lfd > 0) |
---|
1271 | (void) close(lfd); |
---|
1272 | (void) UNLINK(tpfile); |
---|
1273 | kill(0, SIGINT); |
---|
1274 | if (ofilter > 0) |
---|
1275 | kill(ofilter, SIGCONT); |
---|
1276 | signal(SIGALRM, hard_kill); |
---|
1277 | alarm(30); |
---|
1278 | while (wait(NULL) > 0) |
---|
1279 | ; |
---|
1280 | exit(0); |
---|
1281 | } |
---|
1282 | void |
---|
1283 | hard_kill() |
---|
1284 | { |
---|
1285 | kill(0, SIGKILL); |
---|
1286 | } |
---|
1287 | |
---|
1288 | init() |
---|
1289 | { |
---|
1290 | int status; |
---|
1291 | |
---|
1292 | #ifdef HESIOD |
---|
1293 | if ((status = pgetent(line, printer)) <= 0) { |
---|
1294 | if (pralias(alibuf, printer)) |
---|
1295 | printer = alibuf; |
---|
1296 | if ((status = hpgetent(line, printer)) < 1) |
---|
1297 | fatal("unknown printer"); |
---|
1298 | } |
---|
1299 | #else |
---|
1300 | if ((status = pgetent(line, printer)) < 0) { |
---|
1301 | fatal("can't open printer description file"); |
---|
1302 | } else if (status == 0) |
---|
1303 | fatal("unknown printer"); |
---|
1304 | #endif HESIOD |
---|
1305 | if ((LP = pgetstr("lp", &bp)) == NULL) |
---|
1306 | LP = DEFDEVLP; |
---|
1307 | if ((RP = pgetstr("rp", &bp)) == NULL) |
---|
1308 | RP = DEFLP; |
---|
1309 | if ((LO = pgetstr("lo", &bp)) == NULL) |
---|
1310 | LO = DEFLOCK; |
---|
1311 | if ((ST = pgetstr("st", &bp)) == NULL) |
---|
1312 | ST = DEFSTAT; |
---|
1313 | if ((LF = pgetstr("lf", &bp)) == NULL) |
---|
1314 | LF = DEFLOGF; |
---|
1315 | if ((SD = pgetstr("sd", &bp)) == NULL) |
---|
1316 | SD = DEFSPOOL; |
---|
1317 | if ((DU = pgetnum("du")) < 0) |
---|
1318 | DU = DEFUID; |
---|
1319 | if ((FF = pgetstr("ff", &bp)) == NULL) |
---|
1320 | FF = DEFFF; |
---|
1321 | if ((PW = pgetnum("pw")) < 0) |
---|
1322 | PW = DEFWIDTH; |
---|
1323 | sprintf(&width[2], "%d", PW); |
---|
1324 | if ((PL = pgetnum("pl")) < 0) |
---|
1325 | PL = DEFLENGTH; |
---|
1326 | sprintf(&length[2], "%d", PL); |
---|
1327 | #ifdef PQUOTA |
---|
1328 | if ((CP = pgetnum("pc")) < 0) |
---|
1329 | CP = DEFPC; |
---|
1330 | sprintf(&cost[2], "%d", CP); |
---|
1331 | #endif |
---|
1332 | if ((PX = pgetnum("px")) < 0) |
---|
1333 | PX = 0; |
---|
1334 | sprintf(&pxwidth[2], "%d", PX); |
---|
1335 | if ((PY = pgetnum("py")) < 0) |
---|
1336 | PY = 0; |
---|
1337 | sprintf(&pxlength[2], "%d", PY); |
---|
1338 | RM = pgetstr("rm", &bp); |
---|
1339 | |
---|
1340 | /* |
---|
1341 | * Figure out whether the local machine is the same as the remote |
---|
1342 | * machine entry (if it exists). If not, then ignore the local |
---|
1343 | * queue information. |
---|
1344 | */ |
---|
1345 | |
---|
1346 | if (RM != (char *) NULL) { |
---|
1347 | |
---|
1348 | char name[MAXHOSTNAMELEN + 1]; |
---|
1349 | struct hostent *hp; |
---|
1350 | |
---|
1351 | /* get the name of the local host */ |
---|
1352 | gethostname (name, sizeof(name) - 1); |
---|
1353 | name[sizeof(name)-1] = '\0'; |
---|
1354 | |
---|
1355 | /* get the network standard name of the local host */ |
---|
1356 | hp = gethostbyname (name); |
---|
1357 | if (hp == (struct hostent *) NULL) { |
---|
1358 | printf ("unable to get hostname for local machine %s\n", |
---|
1359 | name); |
---|
1360 | } else { |
---|
1361 | strncpy (name, hp->h_name, sizeof(name)); |
---|
1362 | name[sizeof(name) - 1] = '\0'; |
---|
1363 | |
---|
1364 | /* get the network standard name of RM */ |
---|
1365 | hp = gethostbyname (RM); |
---|
1366 | if (hp == (struct hostent *) NULL) { |
---|
1367 | printf ("unable to get hostname for remote machine %s\n", |
---|
1368 | RM); |
---|
1369 | } |
---|
1370 | /* if printer is not on local machine, |
---|
1371 | ignore LP and SD */ |
---|
1372 | else if (strcasecmp(name, hp->h_name) != 0) { |
---|
1373 | if (lflag) syslog(LOG_INFO, "printer is remote; ignoring LP"); |
---|
1374 | LP = ""; |
---|
1375 | SD = DEFSPOOL; |
---|
1376 | } |
---|
1377 | } |
---|
1378 | |
---|
1379 | } |
---|
1380 | localcheck_done: |
---|
1381 | |
---|
1382 | AF = pgetstr("af", &bp); |
---|
1383 | OF = pgetstr("of", &bp); |
---|
1384 | IF = pgetstr("if", &bp); |
---|
1385 | RF = pgetstr("rf", &bp); |
---|
1386 | TF = pgetstr("tf", &bp); |
---|
1387 | NF = pgetstr("nf", &bp); |
---|
1388 | DF = pgetstr("df", &bp); |
---|
1389 | GF = pgetstr("gf", &bp); |
---|
1390 | VF = pgetstr("vf", &bp); |
---|
1391 | CF = pgetstr("cf", &bp); |
---|
1392 | TR = pgetstr("tr", &bp); |
---|
1393 | MS = pgetstr("ms", &bp); |
---|
1394 | RS = pgetflag("rs"); |
---|
1395 | SF = pgetflag("sf"); |
---|
1396 | SH = pgetflag("sh"); |
---|
1397 | SB = pgetflag("sb"); |
---|
1398 | HL = pgetflag("hl"); |
---|
1399 | RW = pgetflag("rw"); |
---|
1400 | BR = pgetnum("br"); |
---|
1401 | if ((FC = pgetnum("fc")) < 0) |
---|
1402 | FC = 0; |
---|
1403 | if ((FS = pgetnum("fs")) < 0) |
---|
1404 | FS = 0; |
---|
1405 | if ((XC = pgetnum("xc")) < 0) |
---|
1406 | XC = 0; |
---|
1407 | if ((XS = pgetnum("xs")) < 0) |
---|
1408 | XS = 0; |
---|
1409 | tof = !pgetflag("fo"); |
---|
1410 | } |
---|
1411 | |
---|
1412 | /* |
---|
1413 | * Acquire line printer or remote connection. |
---|
1414 | */ |
---|
1415 | openpr() |
---|
1416 | { |
---|
1417 | register int i, n; |
---|
1418 | int resp; |
---|
1419 | if (lflag)syslog(LOG_INFO, "Opening printer (LP = \"%s\")", LP); |
---|
1420 | |
---|
1421 | if (*LP) { |
---|
1422 | for (i = 1; ; i = i < 32 ? i << 1 : i) { |
---|
1423 | if (LP[0] == '@') { |
---|
1424 | pfd = tcp_conn(&LP[1]); |
---|
1425 | network = 1; |
---|
1426 | } else { |
---|
1427 | pfd = open(LP, RW ? O_RDWR : O_WRONLY); |
---|
1428 | network = 0; |
---|
1429 | } |
---|
1430 | if (lflag) syslog(LOG_INFO, "LP opened."); |
---|
1431 | if (pfd >= 0) |
---|
1432 | break; |
---|
1433 | if (errno == ENOENT) { |
---|
1434 | syslog(LOG_ERR, "%s: %m", LP); |
---|
1435 | exit(1); |
---|
1436 | } |
---|
1437 | else syslog(LOG_ERR, "%s: %m", LP); |
---|
1438 | if (i == 1) |
---|
1439 | status("waiting for %s (%s) to become ready (offline ?)", printer, LP); |
---|
1440 | sleep(i); |
---|
1441 | } |
---|
1442 | if (isatty(pfd)) { |
---|
1443 | setty(); |
---|
1444 | #if defined(POSIX) && !defined(ultrix) |
---|
1445 | if (MS) |
---|
1446 | setms (); |
---|
1447 | #endif |
---|
1448 | } |
---|
1449 | |
---|
1450 | status("%s is ready and printing", printer); |
---|
1451 | /* |
---|
1452 | * Start up an output filter, if needed. |
---|
1453 | */ |
---|
1454 | if (OF) { |
---|
1455 | int p[2]; |
---|
1456 | char *cp; |
---|
1457 | if (lflag) syslog(LOG_INFO, "Starting filter on %s", LP); |
---|
1458 | |
---|
1459 | pipe(p); |
---|
1460 | if ((ofilter = dofork(DOABORT)) == 0) { /* child */ |
---|
1461 | dup2(p[0], 0); /* pipe is std in */ |
---|
1462 | dup2(pfd, 1); /* printer is std out */ |
---|
1463 | for (i = 3; i < NOFILE; i++) |
---|
1464 | (void) close(i); |
---|
1465 | if ((cp = strrchr(OF, '/')) == NULL) |
---|
1466 | cp = OF; |
---|
1467 | else |
---|
1468 | cp++; |
---|
1469 | execl(OF, cp, width, length, |
---|
1470 | "-P", printer, |
---|
1471 | 0); |
---|
1472 | syslog(LOG_ERR, "%s: %s: %m", printer, OF); |
---|
1473 | exit(1); |
---|
1474 | } |
---|
1475 | (void) close(p[0]); /* close input side */ |
---|
1476 | ofd = p[1]; /* use pipe for output */ |
---|
1477 | } else { |
---|
1478 | ofd = pfd; |
---|
1479 | ofilter = 0; |
---|
1480 | } |
---|
1481 | |
---|
1482 | } else if (RM != NULL) { |
---|
1483 | if (lflag) syslog(LOG_INFO, "Connecting to %s..", RM); |
---|
1484 | for (i = 1; ; i = i < 256 ? i << 1 : i) { |
---|
1485 | resp = -1; |
---|
1486 | pfd = getport(RM); |
---|
1487 | if (pfd >= 0) { |
---|
1488 | (void) sprintf(line, "\2%s\n", RP); |
---|
1489 | n = strlen(line); |
---|
1490 | if (write(pfd, line, n) == n && |
---|
1491 | (resp = response()) == '\0') |
---|
1492 | break; |
---|
1493 | (void) close(pfd); |
---|
1494 | } |
---|
1495 | if (i == 1) { |
---|
1496 | if (resp < 0) |
---|
1497 | status("waiting for %s to come up", RM); |
---|
1498 | else { |
---|
1499 | status("waiting for queue to be enabled on %s", RM); |
---|
1500 | i = 256; |
---|
1501 | } |
---|
1502 | } |
---|
1503 | sleep(i); |
---|
1504 | } |
---|
1505 | if (lflag) syslog(LOG_INFO, "Sending to %s..", RM); |
---|
1506 | status("sending to %s", RM); |
---|
1507 | remote = 1; |
---|
1508 | ofd = pfd; |
---|
1509 | ofilter = 0; |
---|
1510 | } else { |
---|
1511 | syslog(LOG_ERR, "%s: no line printer device or host name", |
---|
1512 | printer); |
---|
1513 | exit(1); |
---|
1514 | } |
---|
1515 | } |
---|
1516 | |
---|
1517 | struct bauds { |
---|
1518 | int baud; |
---|
1519 | int speed; |
---|
1520 | } bauds[] = { |
---|
1521 | 50, B50, |
---|
1522 | 75, B75, |
---|
1523 | 110, B110, |
---|
1524 | 134, B134, |
---|
1525 | 150, B150, |
---|
1526 | 200, B200, |
---|
1527 | 300, B300, |
---|
1528 | 600, B600, |
---|
1529 | 1200, B1200, |
---|
1530 | 1800, B1800, |
---|
1531 | 2400, B2400, |
---|
1532 | 4800, B4800, |
---|
1533 | 9600, B9600, |
---|
1534 | 19200, EXTA, |
---|
1535 | 38400, EXTB, |
---|
1536 | 0, 0 |
---|
1537 | }; |
---|
1538 | |
---|
1539 | /* |
---|
1540 | * setup tty lines. |
---|
1541 | */ |
---|
1542 | setty() |
---|
1543 | { |
---|
1544 | #if defined(ultrix) || !defined(POSIX) |
---|
1545 | struct sgttyb ttybuf; |
---|
1546 | #else |
---|
1547 | struct termios ttybuf; |
---|
1548 | #endif |
---|
1549 | register struct bauds *bp; |
---|
1550 | #if defined(ultrix) || !defined(POSIX) |
---|
1551 | /* I cannot determine if under AUX you can open a line exclusively */ |
---|
1552 | if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) { |
---|
1553 | syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer); |
---|
1554 | exit(1); |
---|
1555 | } |
---|
1556 | if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) { |
---|
1557 | syslog(LOG_ERR, "%s: ioctl(TIOCGETP): %m", printer); |
---|
1558 | exit(1); |
---|
1559 | } |
---|
1560 | #else |
---|
1561 | if (tcgetattr(pfd, &ttybuf) < 0) { |
---|
1562 | syslog(LOG_ERR, "%s: tcgetattr: %m", printer); |
---|
1563 | exit(1); |
---|
1564 | } |
---|
1565 | /* put line in RAW mode for POSIX if printcap does not say how */ |
---|
1566 | if (! MS) { |
---|
1567 | ttybuf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); |
---|
1568 | ttybuf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); |
---|
1569 | ttybuf.c_cflag &= ~(CSIZE | PARENB); |
---|
1570 | ttybuf.c_cflag |= CS8; |
---|
1571 | ttybuf.c_oflag &= ~(OPOST); |
---|
1572 | ttybuf.c_cc[VMIN] = 1; |
---|
1573 | ttybuf.c_cc[VTIME] = 0; |
---|
1574 | } |
---|
1575 | #endif |
---|
1576 | if (BR > 0) { |
---|
1577 | for (bp = bauds; bp->baud; bp++) |
---|
1578 | if (BR == bp->baud) |
---|
1579 | break; |
---|
1580 | if (!bp->baud) { |
---|
1581 | syslog(LOG_ERR, "%s: illegal baud rate %d", printer, BR); |
---|
1582 | exit(1); |
---|
1583 | } |
---|
1584 | #if defined(ultrix) || !defined(POSIX) |
---|
1585 | |
---|
1586 | ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed; |
---|
1587 | #else |
---|
1588 | #ifdef SOLARIS |
---|
1589 | cfsetospeed(&ttybuf, bp->speed); |
---|
1590 | cfsetispeed(&ttybuf, bp->speed); |
---|
1591 | if (tcsetattr(pfd, TCSADRAIN, &ttybuf) < 0) { |
---|
1592 | syslog(LOG_INFO, "SETATTR failed.."); |
---|
1593 | syslog(LOG_ERR, "%s: tcsetattr(TCSNOW): %m", printer); |
---|
1594 | exit(1); |
---|
1595 | } |
---|
1596 | #else /* AIX */ |
---|
1597 | cfgetospeed(&ttybuf); |
---|
1598 | cfsetospeed(&ttybuf, (speed_t)bp->speed); |
---|
1599 | cfgetispeed(&ttybuf); |
---|
1600 | cfsetispeed(&ttybuf, (speed_t)bp->speed); |
---|
1601 | if (tcsetattr(pfd, TCSADRAIN, &ttybuf) < 0) { |
---|
1602 | syslog(LOG_INFO, "SETATTR failed.."); |
---|
1603 | syslog(LOG_ERR, "%s: tcsetattr(TCSNOW): %m", printer); |
---|
1604 | exit(1); |
---|
1605 | } |
---|
1606 | #endif |
---|
1607 | #endif |
---|
1608 | } |
---|
1609 | #if defined(ultrix) || !defined(POSIX) |
---|
1610 | ttybuf.sg_flags &= ~FC; |
---|
1611 | ttybuf.sg_flags |= FS; |
---|
1612 | if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) { |
---|
1613 | syslog(LOG_INFO, "SETP failed.."); |
---|
1614 | syslog(LOG_ERR, "%s: ioctl(TIOCSETP): %m", printer); |
---|
1615 | exit(1); |
---|
1616 | } |
---|
1617 | /* AUX does not appear to have old/new line disciplines that |
---|
1618 | do anything */ |
---|
1619 | if (XC || XS) { |
---|
1620 | int ldisc = NTTYDISC; |
---|
1621 | |
---|
1622 | if (ioctl(pfd, TIOCSETD, &ldisc) < 0) { |
---|
1623 | syslog(LOG_ERR, "%s: ioctl(TIOCSETD): %m", printer); |
---|
1624 | exit(1); |
---|
1625 | } |
---|
1626 | } |
---|
1627 | /* For AUX, XC and XS handled above */ |
---|
1628 | if (XC) { |
---|
1629 | if (ioctl(pfd, TIOCLBIC, &XC) < 0) { |
---|
1630 | syslog(LOG_ERR, "%s: ioctl(TIOCLBIC): %m", printer); |
---|
1631 | exit(1); |
---|
1632 | } |
---|
1633 | } |
---|
1634 | |
---|
1635 | if (XS) { |
---|
1636 | if (ioctl(pfd, TIOCLBIS, &XS) < 0) { |
---|
1637 | syslog(LOG_ERR, "%s: ioctl(TIOCLBIS): %m", printer); |
---|
1638 | exit(1); |
---|
1639 | } |
---|
1640 | } |
---|
1641 | #endif |
---|
1642 | } |
---|
1643 | |
---|
1644 | /*VARARGS1*/ |
---|
1645 | status(msg, a1, a2, a3) |
---|
1646 | char *msg; |
---|
1647 | { |
---|
1648 | register int fd; |
---|
1649 | char buf[BUFSIZ]; |
---|
1650 | |
---|
1651 | umask(0); |
---|
1652 | fd = open(ST, O_WRONLY|O_CREAT, 0664); |
---|
1653 | if (fd < 0 || flock(fd, LOCK_EX) < 0) { |
---|
1654 | syslog(LOG_ERR, "%s: %s: %m", printer, ST); |
---|
1655 | exit(1); |
---|
1656 | } |
---|
1657 | ftruncate(fd, 0); |
---|
1658 | sprintf(buf, msg, a1, a2, a3); |
---|
1659 | strcat(buf, "\n"); |
---|
1660 | (void) write(fd, buf, strlen(buf)); |
---|
1661 | (void) close(fd); |
---|
1662 | } |
---|