1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the University of 17 * California, Berkeley and its contributors. 18 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #ifndef lint 36 static const char copyright[] = 37 "@(#) Copyright (c) 1983, 1993\n\ 38 The Regents of the University of California. All rights reserved.\n"; 39 #endif /* not lint */ 40 41 #if 0 42 #ifndef lint 43 static char sccsid[] = "@(#)printjob.c 8.7 (Berkeley) 5/10/95"; 44 #endif /* not lint */ 45 #endif 46 47 #include "lp.cdefs.h" /* A cross-platform version of <sys/cdefs.h> */ 48 __FBSDID("$FreeBSD$"); 49 50 /* 51 * printjob -- print jobs in the queue. 52 * 53 * NOTE: the lock file is used to pass information to lpq and lprm. 54 * it does not need to be removed because file locks are dynamic. 55 */ 56 57 #include <sys/param.h> 58 #include <sys/wait.h> 59 #include <sys/stat.h> 60 #include <sys/types.h> 61 62 #include <pwd.h> 63 #include <unistd.h> 64 #include <signal.h> 65 #include <syslog.h> 66 #include <fcntl.h> 67 #include <dirent.h> 68 #include <errno.h> 69 #include <stdio.h> 70 #include <string.h> 71 #include <stdlib.h> 72 #include <sys/ioctl.h> 73 #include <termios.h> 74 #include <time.h> 75 #include "lp.h" 76 #include "lp.local.h" 77 #include "pathnames.h" 78 #include "extern.h" 79 80 #define DORETURN 0 /* dofork should return "can't fork" error */ 81 #define DOABORT 1 /* dofork should just die if fork() fails */ 82 83 /* 84 * The buffer size to use when reading/writing spool files. 85 */ 86 #define SPL_BUFSIZ BUFSIZ 87 88 /* 89 * Error tokens 90 */ 91 #define REPRINT -2 92 #define ERROR -1 93 #define OK 0 94 #define FATALERR 1 95 #define NOACCT 2 96 #define FILTERERR 3 97 #define ACCESS 4 98 99 static dev_t fdev; /* device of file pointed to by symlink */ 100 static ino_t fino; /* inode of file pointed to by symlink */ 101 static FILE *cfp; /* control file */ 102 static pid_t of_pid; /* process id of output filter, if any */ 103 static int child; /* id of any filters */ 104 static int job_dfcnt; /* count of datafiles in current user job */ 105 static int lfd; /* lock file descriptor */ 106 static int ofd; /* output filter file descriptor */ 107 static int tfd = -1; /* output filter temp file output */ 108 static int pfd; /* prstatic inter file descriptor */ 109 static int prchild; /* id of pr process */ 110 static char title[80]; /* ``pr'' title */ 111 static char locale[80]; /* ``pr'' locale */ 112 113 /* these two are set from pp->daemon_user, but only if they are needed */ 114 static char *daemon_uname; /* set from pwd->pw_name */ 115 static int daemon_defgid; 116 117 static char class[32]; /* classification field */ 118 static char origin_host[MAXHOSTNAMELEN]; /* user's host machine */ 119 /* indentation size in static characters */ 120 static char indent[10] = "-i0"; 121 static char jobname[100]; /* job or file name */ 122 static char length[10] = "-l"; /* page length in lines */ 123 static char logname[32]; /* user's login name */ 124 static char pxlength[10] = "-y"; /* page length in pixels */ 125 static char pxwidth[10] = "-x"; /* page width in pixels */ 126 /* tempstderr is the filename used to catch stderr from exec-ing filters */ 127 static char tempstderr[] = "errs.XXXXXXX"; 128 static char width[10] = "-w"; /* page width in static characters */ 129 #define TFILENAME "fltXXXXXX" 130 static char tfile[] = TFILENAME; /* file name for filter output */ 131 132 static void abortpr(int _signo); 133 static void alarmhandler(int _signo); 134 static void banner(struct printer *_pp, char *_name1, char *_name2); 135 static int dofork(const struct printer *_pp, int _action); 136 static int dropit(int _c); 137 static int execfilter(struct printer *_pp, char *_f_cmd, char **_f_av, 138 int _infd, int _outfd); 139 static void init(struct printer *_pp); 140 static void openpr(const struct printer *_pp); 141 static void opennet(const struct printer *_pp); 142 static void opentty(const struct printer *_pp); 143 static void openrem(const struct printer *pp); 144 static int print(struct printer *_pp, int _format, char *_file); 145 static int printit(struct printer *_pp, char *_file); 146 static void pstatus(const struct printer *_pp, const char *_msg, ...) 147 __printflike(2, 3); 148 static char response(const struct printer *_pp); 149 static void scan_out(struct printer *_pp, int _scfd, char *_scsp, 150 int _dlm); 151 static char *scnline(int _key, char *_p, int _c); 152 static int sendfile(struct printer *_pp, int _type, char *_file, 153 char _format, int _copyreq); 154 static int sendit(struct printer *_pp, char *_file); 155 static void sendmail(struct printer *_pp, char *_userid, int _bombed); 156 static void setty(const struct printer *_pp); 157 static void wait4data(struct printer *_pp, const char *_dfile); 158 159 void 160 printjob(struct printer *pp) 161 { 162 struct stat stb; 163 register struct jobqueue *q, **qp; 164 struct jobqueue **queue; 165 register int i, nitems; 166 off_t pidoff; 167 pid_t printpid; 168 int errcnt, jobcount, tempfd; 169 170 jobcount = 0; 171 init(pp); /* set up capabilities */ 172 (void) write(STDOUT_FILENO, "", 1); /* ack that daemon is started */ 173 (void) close(STDERR_FILENO); /* set up log file */ 174 if (open(pp->log_file, O_WRONLY|O_APPEND, LOG_FILE_MODE) < 0) { 175 syslog(LOG_ERR, "%s: open(%s): %m", pp->printer, 176 pp->log_file); 177 (void) open(_PATH_DEVNULL, O_WRONLY); 178 } 179 setgid(getegid()); 180 printpid = getpid(); /* for use with lprm */ 181 setpgrp(0, printpid); 182 183 /* 184 * At initial lpd startup, printjob may be called with various 185 * signal handlers in effect. After that initial startup, any 186 * calls to printjob will have a *different* set of signal-handlers 187 * in effect. Make sure all handlers are the ones we want. 188 */ 189 signal(SIGCHLD, SIG_DFL); 190 signal(SIGHUP, abortpr); 191 signal(SIGINT, abortpr); 192 signal(SIGQUIT, abortpr); 193 signal(SIGTERM, abortpr); 194 195 /* 196 * uses short form file names 197 */ 198 if (chdir(pp->spool_dir) < 0) { 199 syslog(LOG_ERR, "%s: chdir(%s): %m", pp->printer, 200 pp->spool_dir); 201 exit(1); 202 } 203 if (stat(pp->lock_file, &stb) == 0 && (stb.st_mode & LFM_PRINT_DIS)) 204 exit(0); /* printing disabled */ 205 umask(S_IWOTH); 206 lfd = open(pp->lock_file, O_WRONLY|O_CREAT|O_EXLOCK|O_NONBLOCK, 207 LOCK_FILE_MODE); 208 if (lfd < 0) { 209 if (errno == EWOULDBLOCK) /* active daemon present */ 210 exit(0); 211 syslog(LOG_ERR, "%s: open(%s): %m", pp->printer, 212 pp->lock_file); 213 exit(1); 214 } 215 /* turn off non-blocking mode (was turned on for lock effects only) */ 216 if (fcntl(lfd, F_SETFL, 0) < 0) { 217 syslog(LOG_ERR, "%s: fcntl(%s): %m", pp->printer, 218 pp->lock_file); 219 exit(1); 220 } 221 ftruncate(lfd, 0); 222 /* 223 * write process id for others to know 224 */ 225 sprintf(line, "%u\n", printpid); 226 pidoff = i = strlen(line); 227 if (write(lfd, line, i) != i) { 228 syslog(LOG_ERR, "%s: write(%s): %m", pp->printer, 229 pp->lock_file); 230 exit(1); 231 } 232 /* 233 * search the spool directory for work and sort by queue order. 234 */ 235 if ((nitems = getq(pp, &queue)) < 0) { 236 syslog(LOG_ERR, "%s: can't scan %s", pp->printer, 237 pp->spool_dir); 238 exit(1); 239 } 240 if (nitems == 0) /* no work to do */ 241 exit(0); 242 if (stb.st_mode & LFM_RESET_QUE) { /* reset queue flag */ 243 if (fchmod(lfd, stb.st_mode & ~LFM_RESET_QUE) < 0) 244 syslog(LOG_ERR, "%s: fchmod(%s): %m", pp->printer, 245 pp->lock_file); 246 } 247 248 /* create a file which will be used to hold stderr from filters */ 249 if ((tempfd = mkstemp(tempstderr)) == -1) { 250 syslog(LOG_ERR, "%s: mkstemp(%s): %m", pp->printer, 251 tempstderr); 252 exit(1); 253 } 254 if ((i = fchmod(tempfd, 0664)) == -1) { 255 syslog(LOG_ERR, "%s: fchmod(%s): %m", pp->printer, 256 tempstderr); 257 exit(1); 258 } 259 /* lpd doesn't need it to be open, it just needs it to exist */ 260 close(tempfd); 261 262 openpr(pp); /* open printer or remote */ 263 again: 264 /* 265 * we found something to do now do it -- 266 * write the name of the current control file into the lock file 267 * so the spool queue program can tell what we're working on 268 */ 269 for (qp = queue; nitems--; free((char *) q)) { 270 q = *qp++; 271 if (stat(q->job_cfname, &stb) < 0) 272 continue; 273 errcnt = 0; 274 restart: 275 (void) lseek(lfd, pidoff, 0); 276 (void) snprintf(line, sizeof(line), "%s\n", q->job_cfname); 277 i = strlen(line); 278 if (write(lfd, line, i) != i) 279 syslog(LOG_ERR, "%s: write(%s): %m", pp->printer, 280 pp->lock_file); 281 if (!pp->remote) 282 i = printit(pp, q->job_cfname); 283 else 284 i = sendit(pp, q->job_cfname); 285 /* 286 * Check to see if we are supposed to stop printing or 287 * if we are to rebuild the queue. 288 */ 289 if (fstat(lfd, &stb) == 0) { 290 /* stop printing before starting next job? */ 291 if (stb.st_mode & LFM_PRINT_DIS) 292 goto done; 293 /* rebuild queue (after lpc topq) */ 294 if (stb.st_mode & LFM_RESET_QUE) { 295 for (free(q); nitems--; free(q)) 296 q = *qp++; 297 if (fchmod(lfd, stb.st_mode & ~LFM_RESET_QUE) 298 < 0) 299 syslog(LOG_WARNING, 300 "%s: fchmod(%s): %m", 301 pp->printer, pp->lock_file); 302 break; 303 } 304 } 305 if (i == OK) /* all files of this job printed */ 306 jobcount++; 307 else if (i == REPRINT && ++errcnt < 5) { 308 /* try reprinting the job */ 309 syslog(LOG_INFO, "restarting %s", pp->printer); 310 if (of_pid > 0) { 311 kill(of_pid, SIGCONT); /* to be sure */ 312 (void) close(ofd); 313 while ((i = wait(NULL)) > 0 && i != of_pid) 314 ; 315 if (i < 0) 316 syslog(LOG_WARNING, "%s: after kill(of=%d), wait() returned: %m", 317 pp->printer, of_pid); 318 of_pid = 0; 319 } 320 (void) close(pfd); /* close printer */ 321 if (ftruncate(lfd, pidoff) < 0) 322 syslog(LOG_WARNING, "%s: ftruncate(%s): %m", 323 pp->printer, pp->lock_file); 324 openpr(pp); /* try to reopen printer */ 325 goto restart; 326 } else { 327 syslog(LOG_WARNING, "%s: job could not be %s (%s)", 328 pp->printer, 329 pp->remote ? "sent to remote host" : "printed", 330 q->job_cfname); 331 if (i == REPRINT) { 332 /* ensure we don't attempt this job again */ 333 (void) unlink(q->job_cfname); 334 q->job_cfname[0] = 'd'; 335 (void) unlink(q->job_cfname); 336 if (logname[0]) 337 sendmail(pp, logname, FATALERR); 338 } 339 } 340 } 341 free(queue); 342 /* 343 * search the spool directory for more work. 344 */ 345 if ((nitems = getq(pp, &queue)) < 0) { 346 syslog(LOG_ERR, "%s: can't scan %s", pp->printer, 347 pp->spool_dir); 348 exit(1); 349 } 350 if (nitems == 0) { /* no more work to do */ 351 done: 352 if (jobcount > 0) { /* jobs actually printed */ 353 if (!pp->no_formfeed && !pp->tof) 354 (void) write(ofd, pp->form_feed, 355 strlen(pp->form_feed)); 356 if (pp->trailer != NULL) /* output trailer */ 357 (void) write(ofd, pp->trailer, 358 strlen(pp->trailer)); 359 } 360 (void) close(ofd); 361 (void) wait(NULL); 362 (void) unlink(tempstderr); 363 exit(0); 364 } 365 goto again; 366 } 367 368 char fonts[4][50]; /* fonts for troff */ 369 370 char ifonts[4][40] = { 371 _PATH_VFONTR, 372 _PATH_VFONTI, 373 _PATH_VFONTB, 374 _PATH_VFONTS, 375 }; 376 377 /* 378 * The remaining part is the reading of the control file (cf) 379 * and performing the various actions. 380 */ 381 static int 382 printit(struct printer *pp, char *file) 383 { 384 register int i; 385 char *cp; 386 int bombed, didignorehdr; 387 388 bombed = OK; 389 didignorehdr = 0; 390 /* 391 * open control file; ignore if no longer there. 392 */ 393 if ((cfp = fopen(file, "r")) == NULL) { 394 syslog(LOG_INFO, "%s: fopen(%s): %m", pp->printer, file); 395 return (OK); 396 } 397 /* 398 * Reset troff fonts. 399 */ 400 for (i = 0; i < 4; i++) 401 strcpy(fonts[i], ifonts[i]); 402 sprintf(&width[2], "%ld", pp->page_width); 403 strcpy(indent+2, "0"); 404 405 /* initialize job-specific count of datafiles processed */ 406 job_dfcnt = 0; 407 408 /* 409 * read the control file for work to do 410 * 411 * file format -- first character in the line is a command 412 * rest of the line is the argument. 413 * valid commands are: 414 * 415 * S -- "stat info" for symbolic link protection 416 * J -- "job name" on banner page 417 * C -- "class name" on banner page 418 * L -- "literal" user's name to print on banner 419 * T -- "title" for pr 420 * H -- "host name" of machine where lpr was done 421 * P -- "person" user's login name 422 * I -- "indent" amount to indent output 423 * R -- laser dpi "resolution" 424 * f -- "file name" name of text file to print 425 * l -- "file name" text file with control chars 426 * o -- "file name" postscript file, according to 427 * the RFC. Here it is treated like an 'f'. 428 * p -- "file name" text file to print with pr(1) 429 * t -- "file name" troff(1) file to print 430 * n -- "file name" ditroff(1) file to print 431 * d -- "file name" dvi file to print 432 * g -- "file name" plot(1G) file to print 433 * v -- "file name" plain raster file to print 434 * c -- "file name" cifplot file to print 435 * 1 -- "R font file" for troff 436 * 2 -- "I font file" for troff 437 * 3 -- "B font file" for troff 438 * 4 -- "S font file" for troff 439 * N -- "name" of file (used by lpq) 440 * U -- "unlink" name of file to remove 441 * (after we print it. (Pass 2 only)). 442 * M -- "mail" to user when done printing 443 * Z -- "locale" for pr 444 * 445 * getline reads a line and expands tabs to blanks 446 */ 447 448 /* pass 1 */ 449 450 while (getline(cfp)) 451 switch (line[0]) { 452 case 'H': 453 strlcpy(origin_host, line + 1, sizeof(origin_host)); 454 if (class[0] == '\0') { 455 strlcpy(class, line+1, sizeof(class)); 456 } 457 continue; 458 459 case 'P': 460 strlcpy(logname, line + 1, sizeof(logname)); 461 if (pp->restricted) { /* restricted */ 462 if (getpwnam(logname) == NULL) { 463 bombed = NOACCT; 464 sendmail(pp, line+1, bombed); 465 goto pass2; 466 } 467 } 468 continue; 469 470 case 'S': 471 cp = line+1; 472 i = 0; 473 while (*cp >= '0' && *cp <= '9') 474 i = i * 10 + (*cp++ - '0'); 475 fdev = i; 476 cp++; 477 i = 0; 478 while (*cp >= '0' && *cp <= '9') 479 i = i * 10 + (*cp++ - '0'); 480 fino = i; 481 continue; 482 483 case 'J': 484 if (line[1] != '\0') { 485 strlcpy(jobname, line + 1, sizeof(jobname)); 486 } else 487 strcpy(jobname, " "); 488 continue; 489 490 case 'C': 491 if (line[1] != '\0') 492 strlcpy(class, line + 1, sizeof(class)); 493 else if (class[0] == '\0') { 494 /* XXX - why call gethostname instead of 495 * just strlcpy'ing local_host? */ 496 gethostname(class, sizeof(class)); 497 class[sizeof(class) - 1] = '\0'; 498 } 499 continue; 500 501 case 'T': /* header title for pr */ 502 strlcpy(title, line + 1, sizeof(title)); 503 continue; 504 505 case 'L': /* identification line */ 506 if (!pp->no_header && !pp->header_last) 507 banner(pp, line+1, jobname); 508 continue; 509 510 case '1': /* troff fonts */ 511 case '2': 512 case '3': 513 case '4': 514 if (line[1] != '\0') { 515 strlcpy(fonts[line[0]-'1'], line + 1, 516 (size_t)50); 517 } 518 continue; 519 520 case 'W': /* page width */ 521 strlcpy(width+2, line + 1, sizeof(width) - 2); 522 continue; 523 524 case 'I': /* indent amount */ 525 strlcpy(indent+2, line + 1, sizeof(indent) - 2); 526 continue; 527 528 case 'Z': /* locale for pr */ 529 strlcpy(locale, line + 1, sizeof(locale)); 530 continue; 531 532 default: /* some file to print */ 533 /* only lowercase cmd-codes include a file-to-print */ 534 if ((line[0] < 'a') || (line[0] > 'z')) { 535 /* ignore any other lines */ 536 if (lflag <= 1) 537 continue; 538 if (!didignorehdr) { 539 syslog(LOG_INFO, "%s: in %s :", 540 pp->printer, file); 541 didignorehdr = 1; 542 } 543 syslog(LOG_INFO, "%s: ignoring line: '%c' %s", 544 pp->printer, line[0], &line[1]); 545 continue; 546 } 547 i = print(pp, line[0], line+1); 548 switch (i) { 549 case ERROR: 550 if (bombed == OK) 551 bombed = FATALERR; 552 break; 553 case REPRINT: 554 (void) fclose(cfp); 555 return (REPRINT); 556 case FILTERERR: 557 case ACCESS: 558 bombed = i; 559 sendmail(pp, logname, bombed); 560 } 561 title[0] = '\0'; 562 continue; 563 564 case 'N': 565 case 'U': 566 case 'M': 567 case 'R': 568 continue; 569 } 570 571 /* pass 2 */ 572 573 pass2: 574 fseek(cfp, 0L, 0); 575 while (getline(cfp)) 576 switch (line[0]) { 577 case 'L': /* identification line */ 578 if (!pp->no_header && pp->header_last) 579 banner(pp, line+1, jobname); 580 continue; 581 582 case 'M': 583 if (bombed < NOACCT) /* already sent if >= NOACCT */ 584 sendmail(pp, line+1, bombed); 585 continue; 586 587 case 'U': 588 if (strchr(line+1, '/')) 589 continue; 590 (void) unlink(line+1); 591 } 592 /* 593 * clean-up in case another control file exists 594 */ 595 (void) fclose(cfp); 596 (void) unlink(file); 597 return (bombed == OK ? OK : ERROR); 598 } 599 600 /* 601 * Print a file. 602 * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}. 603 * Return -1 if a non-recoverable error occured, 604 * 2 if the filter detected some errors (but printed the job anyway), 605 * 1 if we should try to reprint this job and 606 * 0 if all is well. 607 * Note: all filters take stdin as the file, stdout as the printer, 608 * stderr as the log file, and must not ignore SIGINT. 609 */ 610 static int 611 print(struct printer *pp, int format, char *file) 612 { 613 register int n, i; 614 register char *prog; 615 int fi, fo; 616 FILE *fp; 617 char *av[15], buf[SPL_BUFSIZ]; 618 pid_t wpid; 619 int p[2], retcode, stopped, wstatus, wstatus_set; 620 struct stat stb; 621 622 /* Make sure the entire data file has arrived. */ 623 wait4data(pp, file); 624 625 if (lstat(file, &stb) < 0 || (fi = open(file, O_RDONLY)) < 0) { 626 syslog(LOG_INFO, "%s: unable to open %s ('%c' line)", 627 pp->printer, file, format); 628 return (ERROR); 629 } 630 /* 631 * Check to see if data file is a symbolic link. If so, it should 632 * still point to the same file or someone is trying to print 633 * something he shouldn't. 634 */ 635 if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(fi, &stb) == 0 && 636 (stb.st_dev != fdev || stb.st_ino != fino)) 637 return (ACCESS); 638 639 job_dfcnt++; /* increment datafile counter for this job */ 640 stopped = 0; /* output filter is not stopped */ 641 642 /* everything seems OK, start it up */ 643 if (!pp->no_formfeed && !pp->tof) { /* start on a fresh page */ 644 (void) write(ofd, pp->form_feed, strlen(pp->form_feed)); 645 pp->tof = 1; 646 } 647 if (pp->filters[LPF_INPUT] == NULL 648 && (format == 'f' || format == 'l' || format == 'o')) { 649 pp->tof = 0; 650 while ((n = read(fi, buf, SPL_BUFSIZ)) > 0) 651 if (write(ofd, buf, n) != n) { 652 (void) close(fi); 653 return (REPRINT); 654 } 655 (void) close(fi); 656 return (OK); 657 } 658 switch (format) { 659 case 'p': /* print file using 'pr' */ 660 if (pp->filters[LPF_INPUT] == NULL) { /* use output filter */ 661 prog = _PATH_PR; 662 i = 0; 663 av[i++] = "pr"; 664 av[i++] = width; 665 av[i++] = length; 666 av[i++] = "-h"; 667 av[i++] = *title ? title : " "; 668 av[i++] = "-L"; 669 av[i++] = *locale ? locale : "C"; 670 av[i++] = "-F"; 671 av[i] = 0; 672 fo = ofd; 673 goto start; 674 } 675 pipe(p); 676 if ((prchild = dofork(pp, DORETURN)) == 0) { /* child */ 677 dup2(fi, STDIN_FILENO); /* file is stdin */ 678 dup2(p[1], STDOUT_FILENO); /* pipe is stdout */ 679 closelog(); 680 closeallfds(3); 681 execl(_PATH_PR, "pr", width, length, 682 "-h", *title ? title : " ", 683 "-L", *locale ? locale : "C", 684 "-F", (char *)0); 685 syslog(LOG_ERR, "cannot execl %s", _PATH_PR); 686 exit(2); 687 } 688 (void) close(p[1]); /* close output side */ 689 (void) close(fi); 690 if (prchild < 0) { 691 prchild = 0; 692 (void) close(p[0]); 693 return (ERROR); 694 } 695 fi = p[0]; /* use pipe for input */ 696 case 'f': /* print plain text file */ 697 prog = pp->filters[LPF_INPUT]; 698 av[1] = width; 699 av[2] = length; 700 av[3] = indent; 701 n = 4; 702 break; 703 case 'o': /* print postscript file */ 704 /* 705 * Treat this as a "plain file with control characters", and 706 * assume the standard LPF_INPUT filter will recognize that 707 * the data is postscript and know what to do with it. These 708 * 'o'-file requests could come from MacOS 10.1 systems. 709 * (later versions of MacOS 10 will explicitly use 'l') 710 * A postscript file can contain binary data, which is why 'l' 711 * is somewhat more appropriate than 'f'. 712 */ 713 /* FALLTHROUGH */ 714 case 'l': /* like 'f' but pass control characters */ 715 prog = pp->filters[LPF_INPUT]; 716 av[1] = "-c"; 717 av[2] = width; 718 av[3] = length; 719 av[4] = indent; 720 n = 5; 721 break; 722 case 'r': /* print a fortran text file */ 723 prog = pp->filters[LPF_FORTRAN]; 724 av[1] = width; 725 av[2] = length; 726 n = 3; 727 break; 728 case 't': /* print troff output */ 729 case 'n': /* print ditroff output */ 730 case 'd': /* print tex output */ 731 (void) unlink(".railmag"); 732 if ((fo = creat(".railmag", FILMOD)) < 0) { 733 syslog(LOG_ERR, "%s: cannot create .railmag", 734 pp->printer); 735 (void) unlink(".railmag"); 736 } else { 737 for (n = 0; n < 4; n++) { 738 if (fonts[n][0] != '/') 739 (void) write(fo, _PATH_VFONT, 740 sizeof(_PATH_VFONT) - 1); 741 (void) write(fo, fonts[n], strlen(fonts[n])); 742 (void) write(fo, "\n", 1); 743 } 744 (void) close(fo); 745 } 746 prog = (format == 't') ? pp->filters[LPF_TROFF] 747 : ((format == 'n') ? pp->filters[LPF_DITROFF] 748 : pp->filters[LPF_DVI]); 749 av[1] = pxwidth; 750 av[2] = pxlength; 751 n = 3; 752 break; 753 case 'c': /* print cifplot output */ 754 prog = pp->filters[LPF_CIFPLOT]; 755 av[1] = pxwidth; 756 av[2] = pxlength; 757 n = 3; 758 break; 759 case 'g': /* print plot(1G) output */ 760 prog = pp->filters[LPF_GRAPH]; 761 av[1] = pxwidth; 762 av[2] = pxlength; 763 n = 3; 764 break; 765 case 'v': /* print raster output */ 766 prog = pp->filters[LPF_RASTER]; 767 av[1] = pxwidth; 768 av[2] = pxlength; 769 n = 3; 770 break; 771 default: 772 (void) close(fi); 773 syslog(LOG_ERR, "%s: illegal format character '%c'", 774 pp->printer, format); 775 return (ERROR); 776 } 777 if (prog == NULL) { 778 (void) close(fi); 779 syslog(LOG_ERR, 780 "%s: no filter found in printcap for format character '%c'", 781 pp->printer, format); 782 return (ERROR); 783 } 784 if ((av[0] = strrchr(prog, '/')) != NULL) 785 av[0]++; 786 else 787 av[0] = prog; 788 av[n++] = "-n"; 789 av[n++] = logname; 790 av[n++] = "-h"; 791 av[n++] = origin_host; 792 av[n++] = pp->acct_file; 793 av[n] = 0; 794 fo = pfd; 795 if (of_pid > 0) { /* stop output filter */ 796 write(ofd, "\031\1", 2); 797 while ((wpid = 798 wait3(&wstatus, WUNTRACED, 0)) > 0 && wpid != of_pid) 799 ; 800 if (wpid < 0) 801 syslog(LOG_WARNING, 802 "%s: after stopping 'of', wait3() returned: %m", 803 pp->printer); 804 else if (!WIFSTOPPED(wstatus)) { 805 (void) close(fi); 806 syslog(LOG_WARNING, "%s: output filter died " 807 "(pid=%d retcode=%d termsig=%d)", 808 pp->printer, of_pid, WEXITSTATUS(wstatus), 809 WTERMSIG(wstatus)); 810 return (REPRINT); 811 } 812 stopped++; 813 } 814 start: 815 if ((child = dofork(pp, DORETURN)) == 0) { /* child */ 816 dup2(fi, STDIN_FILENO); 817 dup2(fo, STDOUT_FILENO); 818 /* setup stderr for the filter (child process) 819 * so it goes to our temporary errors file */ 820 n = open(tempstderr, O_WRONLY|O_TRUNC, 0664); 821 if (n >= 0) 822 dup2(n, STDERR_FILENO); 823 closelog(); 824 closeallfds(3); 825 execv(prog, av); 826 syslog(LOG_ERR, "%s: cannot execv(%s): %m", pp->printer, 827 prog); 828 exit(2); 829 } 830 (void) close(fi); 831 wstatus_set = 0; 832 if (child < 0) 833 retcode = 100; 834 else { 835 while ((wpid = wait(&wstatus)) > 0 && wpid != child) 836 ; 837 if (wpid < 0) { 838 retcode = 100; 839 syslog(LOG_WARNING, 840 "%s: after execv(%s), wait() returned: %m", 841 pp->printer, prog); 842 } else { 843 wstatus_set = 1; 844 retcode = WEXITSTATUS(wstatus); 845 } 846 } 847 child = 0; 848 prchild = 0; 849 if (stopped) { /* restart output filter */ 850 if (kill(of_pid, SIGCONT) < 0) { 851 syslog(LOG_ERR, "cannot restart output filter"); 852 exit(1); 853 } 854 } 855 pp->tof = 0; 856 857 /* Copy the filter's output to "lf" logfile */ 858 if ((fp = fopen(tempstderr, "r"))) { 859 while (fgets(buf, sizeof(buf), fp)) 860 fputs(buf, stderr); 861 fclose(fp); 862 } 863 864 if (wstatus_set && !WIFEXITED(wstatus)) { 865 syslog(LOG_WARNING, "%s: filter '%c' terminated (termsig=%d)", 866 pp->printer, format, WTERMSIG(wstatus)); 867 return (ERROR); 868 } 869 switch (retcode) { 870 case 0: 871 pp->tof = 1; 872 return (OK); 873 case 1: 874 return (REPRINT); 875 case 2: 876 return (ERROR); 877 default: 878 syslog(LOG_WARNING, "%s: filter '%c' exited (retcode=%d)", 879 pp->printer, format, retcode); 880 return (FILTERERR); 881 } 882 } 883 884 /* 885 * Send the daemon control file (cf) and any data files. 886 * Return -1 if a non-recoverable error occured, 1 if a recoverable error and 887 * 0 if all is well. 888 */ 889 static int 890 sendit(struct printer *pp, char *file) 891 { 892 int dfcopies, err, i; 893 char *cp, last[sizeof(line)]; 894 895 /* 896 * open control file 897 */ 898 if ((cfp = fopen(file, "r")) == NULL) 899 return (OK); 900 901 /* initialize job-specific count of datafiles processed */ 902 job_dfcnt = 0; 903 904 /* 905 * read the control file for work to do 906 * 907 * file format -- first character in the line is a command 908 * rest of the line is the argument. 909 * commands of interest are: 910 * 911 * a-z -- "file name" name of file to print 912 * U -- "unlink" name of file to remove 913 * (after we print it. (Pass 2 only)). 914 */ 915 916 /* 917 * pass 1 918 */ 919 err = OK; 920 while (getline(cfp)) { 921 again: 922 if (line[0] == 'S') { 923 cp = line+1; 924 i = 0; 925 while (*cp >= '0' && *cp <= '9') 926 i = i * 10 + (*cp++ - '0'); 927 fdev = i; 928 cp++; 929 i = 0; 930 while (*cp >= '0' && *cp <= '9') 931 i = i * 10 + (*cp++ - '0'); 932 fino = i; 933 } else if (line[0] == 'H') { 934 strlcpy(origin_host, line + 1, sizeof(origin_host)); 935 if (class[0] == '\0') { 936 strlcpy(class, line + 1, sizeof(class)); 937 } 938 } else if (line[0] == 'P') { 939 strlcpy(logname, line + 1, sizeof(logname)); 940 if (pp->restricted) { /* restricted */ 941 if (getpwnam(logname) == NULL) { 942 sendmail(pp, line+1, NOACCT); 943 err = ERROR; 944 break; 945 } 946 } 947 } else if (line[0] == 'I') { 948 strlcpy(indent+2, line + 1, sizeof(indent) - 2); 949 } else if (line[0] >= 'a' && line[0] <= 'z') { 950 dfcopies = 1; 951 strcpy(last, line); 952 while ((i = getline(cfp)) != 0) { 953 if (strcmp(last, line) != 0) 954 break; 955 dfcopies++; 956 } 957 switch (sendfile(pp, '\3', last+1, *last, dfcopies)) { 958 case OK: 959 if (i) 960 goto again; 961 break; 962 case REPRINT: 963 (void) fclose(cfp); 964 return (REPRINT); 965 case ACCESS: 966 sendmail(pp, logname, ACCESS); 967 case ERROR: 968 err = ERROR; 969 } 970 break; 971 } 972 } 973 if (err == OK && sendfile(pp, '\2', file, '\0', 1) > 0) { 974 (void) fclose(cfp); 975 return (REPRINT); 976 } 977 /* 978 * pass 2 979 */ 980 fseek(cfp, 0L, 0); 981 while (getline(cfp)) 982 if (line[0] == 'U' && !strchr(line+1, '/')) 983 (void) unlink(line+1); 984 /* 985 * clean-up in case another control file exists 986 */ 987 (void) fclose(cfp); 988 (void) unlink(file); 989 return (err); 990 } 991 992 /* 993 * Send a data file to the remote machine and spool it. 994 * Return positive if we should try resending. 995 */ 996 static int 997 sendfile(struct printer *pp, int type, char *file, char format, int copyreq) 998 { 999 int i, amt; 1000 struct stat stb; 1001 char *av[15], *filtcmd; 1002 char buf[SPL_BUFSIZ], opt_c[4], opt_h[4], opt_n[4]; 1003 int copycnt, filtstat, narg, resp, sfd, sfres, sizerr, statrc; 1004 1005 /* Make sure the entire data file has arrived. */ 1006 wait4data(pp, file); 1007 1008 statrc = lstat(file, &stb); 1009 if (statrc < 0) { 1010 syslog(LOG_ERR, "%s: error from lstat(%s): %m", 1011 pp->printer, file); 1012 return (ERROR); 1013 } 1014 sfd = open(file, O_RDONLY); 1015 if (sfd < 0) { 1016 syslog(LOG_ERR, "%s: error from open(%s,O_RDONLY): %m", 1017 pp->printer, file); 1018 return (ERROR); 1019 } 1020 /* 1021 * Check to see if data file is a symbolic link. If so, it should 1022 * still point to the same file or someone is trying to print something 1023 * he shouldn't. 1024 */ 1025 if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(sfd, &stb) == 0 && 1026 (stb.st_dev != fdev || stb.st_ino != fino)) { 1027 close(sfd); 1028 return (ACCESS); 1029 } 1030 1031 /* Everything seems OK for reading the file, now to send it */ 1032 filtcmd = NULL; 1033 sizerr = 0; 1034 tfd = -1; 1035 if (type == '\3') { 1036 /* 1037 * Type == 3 means this is a datafile, not a control file. 1038 * Increment the counter of data-files in this job, and 1039 * then check for input or output filters (which are only 1040 * applied to datafiles, not control files). 1041 */ 1042 job_dfcnt++; 1043 1044 /* 1045 * Note that here we are filtering datafiles, one at a time, 1046 * as they are sent to the remote machine. Here, the *only* 1047 * difference between an input filter (`if=') and an output 1048 * filter (`of=') is the argument list that the filter is 1049 * started up with. Here, the output filter is executed 1050 * for each individual file as it is sent. This is not the 1051 * same as local print queues, where the output filter is 1052 * started up once, and then all jobs are passed thru that 1053 * single invocation of the output filter. 1054 * 1055 * Also note that a queue for a remote-machine can have an 1056 * input filter or an output filter, but not both. 1057 */ 1058 if (pp->filters[LPF_INPUT]) { 1059 filtcmd = pp->filters[LPF_INPUT]; 1060 av[0] = filtcmd; 1061 narg = 0; 1062 strcpy(opt_c, "-c"); 1063 strcpy(opt_h, "-h"); 1064 strcpy(opt_n, "-n"); 1065 if (format == 'l') 1066 av[++narg] = opt_c; 1067 av[++narg] = width; 1068 av[++narg] = length; 1069 av[++narg] = indent; 1070 av[++narg] = opt_n; 1071 av[++narg] = logname; 1072 av[++narg] = opt_h; 1073 av[++narg] = origin_host; 1074 av[++narg] = pp->acct_file; 1075 av[++narg] = NULL; 1076 } else if (pp->filters[LPF_OUTPUT]) { 1077 filtcmd = pp->filters[LPF_OUTPUT]; 1078 av[0] = filtcmd; 1079 narg = 0; 1080 av[++narg] = width; 1081 av[++narg] = length; 1082 av[++narg] = NULL; 1083 } 1084 } 1085 if (filtcmd) { 1086 /* 1087 * If there is an input or output filter, we have to run 1088 * the datafile thru that filter and store the result as 1089 * a temporary spool file, because the protocol requires 1090 * that we send the remote host the file-size before we 1091 * start to send any of the data. 1092 */ 1093 strcpy(tfile, TFILENAME); 1094 tfd = mkstemp(tfile); 1095 if (tfd == -1) { 1096 syslog(LOG_ERR, "%s: mkstemp(%s): %m", pp->printer, 1097 TFILENAME); 1098 sfres = ERROR; 1099 goto return_sfres; 1100 } 1101 filtstat = execfilter(pp, filtcmd, av, sfd, tfd); 1102 1103 /* process the return-code from the filter */ 1104 switch (filtstat) { 1105 case 0: 1106 break; 1107 case 1: 1108 sfres = REPRINT; 1109 goto return_sfres; 1110 case 2: 1111 sfres = ERROR; 1112 goto return_sfres; 1113 default: 1114 syslog(LOG_WARNING, 1115 "%s: filter '%c' exited (retcode=%d)", 1116 pp->printer, format, filtstat); 1117 sfres = FILTERERR; 1118 goto return_sfres; 1119 } 1120 statrc = fstat(tfd, &stb); /* to find size of tfile */ 1121 if (statrc < 0) { 1122 syslog(LOG_ERR, 1123 "%s: error processing 'if', fstat(%s): %m", 1124 pp->printer, tfile); 1125 sfres = ERROR; 1126 goto return_sfres; 1127 } 1128 close(sfd); 1129 sfd = tfd; 1130 lseek(sfd, 0, SEEK_SET); 1131 } 1132 1133 copycnt = 0; 1134 sendagain: 1135 copycnt++; 1136 1137 if (copycnt < 2) 1138 (void) sprintf(buf, "%c%qd %s\n", type, stb.st_size, file); 1139 else 1140 (void) sprintf(buf, "%c%qd %s_c%d\n", type, stb.st_size, 1141 file, copycnt); 1142 amt = strlen(buf); 1143 for (i = 0; ; i++) { 1144 if (write(pfd, buf, amt) != amt || 1145 (resp = response(pp)) < 0 || resp == '\1') { 1146 sfres = REPRINT; 1147 goto return_sfres; 1148 } else if (resp == '\0') 1149 break; 1150 if (i == 0) 1151 pstatus(pp, 1152 "no space on remote; waiting for queue to drain"); 1153 if (i == 10) 1154 syslog(LOG_ALERT, "%s: can't send to %s; queue full", 1155 pp->printer, pp->remote_host); 1156 sleep(5 * 60); 1157 } 1158 if (i) 1159 pstatus(pp, "sending to %s", pp->remote_host); 1160 /* 1161 * XXX - we should change trstat_init()/trstat_write() to include 1162 * the copycnt in the statistics record it may write. 1163 */ 1164 if (type == '\3') 1165 trstat_init(pp, file, job_dfcnt); 1166 for (i = 0; i < stb.st_size; i += SPL_BUFSIZ) { 1167 amt = SPL_BUFSIZ; 1168 if (i + amt > stb.st_size) 1169 amt = stb.st_size - i; 1170 if (sizerr == 0 && read(sfd, buf, amt) != amt) 1171 sizerr = 1; 1172 if (write(pfd, buf, amt) != amt) { 1173 sfres = REPRINT; 1174 goto return_sfres; 1175 } 1176 } 1177 1178 if (sizerr) { 1179 syslog(LOG_INFO, "%s: %s: changed size", pp->printer, file); 1180 /* tell recvjob to ignore this file */ 1181 (void) write(pfd, "\1", 1); 1182 sfres = ERROR; 1183 goto return_sfres; 1184 } 1185 if (write(pfd, "", 1) != 1 || response(pp)) { 1186 sfres = REPRINT; 1187 goto return_sfres; 1188 } 1189 if (type == '\3') { 1190 trstat_write(pp, TR_SENDING, stb.st_size, logname, 1191 pp->remote_host, origin_host); 1192 /* 1193 * Usually we only need to send one copy of a datafile, 1194 * because the control-file will simply print the same 1195 * file multiple times. However, some printers ignore 1196 * the control file, and simply print each data file as 1197 * it arrives. For such "remote hosts", we need to 1198 * transfer the same data file multiple times. Such a 1199 * a host is indicated by adding 'rc' to the printcap 1200 * entry. 1201 * XXX - Right now this ONLY works for remote hosts which 1202 * do ignore the name of the data file, because 1203 * this sends the file multiple times with slight 1204 * changes to the filename. To do this right would 1205 * require that we also rewrite the control file 1206 * to match those filenames. 1207 */ 1208 if (pp->resend_copies && (copycnt < copyreq)) { 1209 lseek(sfd, 0, SEEK_SET); 1210 goto sendagain; 1211 } 1212 } 1213 sfres = OK; 1214 1215 return_sfres: 1216 (void)close(sfd); 1217 if (tfd != -1) { 1218 /* 1219 * If tfd is set, then it is the same value as sfd, and 1220 * therefore it is already closed at this point. All 1221 * we need to do is remove the temporary file. 1222 */ 1223 tfd = -1; 1224 unlink(tfile); 1225 } 1226 return (sfres); 1227 } 1228 1229 /* 1230 * Some print servers send the control-file first, and then start sending the 1231 * matching data file(s). That is not the correct order. If some queue is 1232 * already printing an active job, then when that job is finished the queue 1233 * may proceed to the control file of any incoming print job. This turns 1234 * into a race between the process which is receiving the data file, and the 1235 * process which is actively printing the very same file. When the remote 1236 * server sends files in the wrong order, it is even possible that a queue 1237 * will start to print a data file before the file has been created! 1238 * 1239 * So before we start to print() or send() a data file, we call this routine 1240 * to make sure the data file is not still changing in size. Note that this 1241 * problem will only happen for jobs arriving from a remote host, and that 1242 * the process which has decided to print this job (and is thus making this 1243 * check) is *not* the process which is receiving the job. 1244 * 1245 * A second benefit of this is that any incoming job is guaranteed to appear 1246 * in a queue listing for at least a few seconds after it has arrived. Some 1247 * lpr implementations get confused if they send a job and it disappears 1248 * from the queue before they can check on it. 1249 */ 1250 #define MAXWAIT_ARRIVE 16 /* max to wait for the file to *exist* */ 1251 #define MAXWAIT_4DATA (20*60) /* max to wait for it to stop changing */ 1252 #define MINWAIT_4DATA 4 /* This value must be >= 1 */ 1253 #define DEBUG_MINWAIT 1 1254 static void 1255 wait4data(struct printer *pp, const char *dfile) 1256 { 1257 const char *cp; 1258 int statres; 1259 size_t dlen, hlen; 1260 time_t amtslept, checktime; 1261 struct stat statdf; 1262 1263 /* Skip these checks if the print job is from the local host. */ 1264 dlen = strlen(dfile); 1265 hlen = strlen(local_host); 1266 if (dlen > hlen) { 1267 cp = dfile + dlen - hlen; 1268 if (strcmp(cp, local_host) == 0) 1269 return; 1270 } 1271 1272 /* 1273 * If this data file does not exist, then wait up to MAXWAIT_ARRIVE 1274 * seconds for it to arrive. 1275 */ 1276 amtslept = 0; 1277 statres = stat(dfile, &statdf); 1278 while (statres < 0 && amtslept < MAXWAIT_ARRIVE) { 1279 if (amtslept == 0) 1280 pstatus(pp, "Waiting for data file from remote host"); 1281 amtslept += MINWAIT_4DATA - sleep(MINWAIT_4DATA); 1282 statres = stat(dfile, &statdf); 1283 } 1284 if (statres < 0) { 1285 /* The file still does not exist, so just give up on it. */ 1286 syslog(LOG_WARNING, "%s: wait4data() abandoned wait for %s", 1287 pp->printer, dfile); 1288 return; 1289 } 1290 1291 /* 1292 * The file exists, so keep waiting until the data file has not 1293 * changed for some reasonable amount of time. 1294 */ 1295 while (statres == 0 && amtslept < MAXWAIT_4DATA) { 1296 checktime = time(NULL) - MINWAIT_4DATA; 1297 if (statdf.st_mtime <= checktime) 1298 break; 1299 if (amtslept == 0) 1300 pstatus(pp, "Waiting for data file from remote host"); 1301 amtslept += MINWAIT_4DATA - sleep(MINWAIT_4DATA); 1302 statres = stat(dfile, &statdf); 1303 } 1304 1305 if (statres != 0) 1306 syslog(LOG_WARNING, "%s: %s disappeared during wait4data()", 1307 pp->printer, dfile); 1308 else if (amtslept > MAXWAIT_4DATA) 1309 syslog(LOG_WARNING, 1310 "%s: %s still changing after %lu secs in wait4data()", 1311 pp->printer, dfile, (unsigned long)amtslept); 1312 #if DEBUG_MINWAIT 1313 else if (amtslept > MINWAIT_4DATA) 1314 syslog(LOG_INFO, "%s: slept %lu secs in wait4data(%s)", 1315 pp->printer, (unsigned long)amtslept, dfile); 1316 #endif 1317 } 1318 #undef MAXWAIT_ARRIVE 1319 #undef MAXWAIT_4DATA 1320 #undef MINWAIT_4DATA 1321 1322 /* 1323 * This routine is called to execute one of the filters as was 1324 * specified in a printcap entry. While the child-process will read 1325 * all of 'infd', it is up to the caller to close that file descriptor 1326 * in the parent process. 1327 */ 1328 static int 1329 execfilter(struct printer *pp, char *f_cmd, char *f_av[], int infd, int outfd) 1330 { 1331 pid_t fpid, wpid; 1332 int errfd, retcode, wstatus; 1333 FILE *errfp; 1334 char buf[BUFSIZ], *slash; 1335 1336 fpid = dofork(pp, DORETURN); 1337 if (fpid != 0) { 1338 /* 1339 * This is the parent process, which just waits for the child 1340 * to complete and then returns the result. Note that it is 1341 * the child process which reads the input stream. 1342 */ 1343 if (fpid < 0) 1344 retcode = 100; 1345 else { 1346 while ((wpid = wait(&wstatus)) > 0 && 1347 wpid != fpid) 1348 ; 1349 if (wpid < 0) { 1350 retcode = 100; 1351 syslog(LOG_WARNING, 1352 "%s: after execv(%s), wait() returned: %m", 1353 pp->printer, f_cmd); 1354 } else 1355 retcode = WEXITSTATUS(wstatus); 1356 } 1357 1358 /* 1359 * Copy everything the filter wrote to stderr from our 1360 * temporary errors file to the "lf=" logfile. 1361 */ 1362 errfp = fopen(tempstderr, "r"); 1363 if (errfp) { 1364 while (fgets(buf, sizeof(buf), errfp)) 1365 fputs(buf, stderr); 1366 fclose(errfp); 1367 } 1368 1369 return (retcode); 1370 } 1371 1372 /* 1373 * This is the child process, which is the one that executes the 1374 * given filter. 1375 */ 1376 /* 1377 * If the first parameter has any slashes in it, then change it 1378 * to point to the first character after the last slash. 1379 */ 1380 slash = strrchr(f_av[0], '/'); 1381 if (slash != NULL) 1382 f_av[0] = slash + 1; 1383 /* 1384 * XXX - in the future, this should setup an explicit list of 1385 * environment variables and use execve()! 1386 */ 1387 1388 /* 1389 * Setup stdin, stdout, and stderr as we want them when the filter 1390 * is running. Stderr is setup so it points to a temporary errors 1391 * file, and the parent process will copy that temporary file to 1392 * the real logfile after the filter completes. 1393 */ 1394 dup2(infd, STDIN_FILENO); 1395 dup2(outfd, STDOUT_FILENO); 1396 errfd = open(tempstderr, O_WRONLY|O_TRUNC, 0664); 1397 if (errfd >= 0) 1398 dup2(errfd, STDERR_FILENO); 1399 closelog(); 1400 closeallfds(3); 1401 execv(f_cmd, f_av); 1402 syslog(LOG_ERR, "%s: cannot execv(%s): %m", pp->printer, f_cmd); 1403 exit(2); 1404 /* NOTREACHED */ 1405 } 1406 1407 /* 1408 * Check to make sure there have been no errors and that both programs 1409 * are in sync with eachother. 1410 * Return non-zero if the connection was lost. 1411 */ 1412 static char 1413 response(const struct printer *pp) 1414 { 1415 char resp; 1416 1417 if (read(pfd, &resp, 1) != 1) { 1418 syslog(LOG_INFO, "%s: lost connection", pp->printer); 1419 return (-1); 1420 } 1421 return (resp); 1422 } 1423 1424 /* 1425 * Banner printing stuff 1426 */ 1427 static void 1428 banner(struct printer *pp, char *name1, char *name2) 1429 { 1430 time_t tvec; 1431 1432 time(&tvec); 1433 if (!pp->no_formfeed && !pp->tof) 1434 (void) write(ofd, pp->form_feed, strlen(pp->form_feed)); 1435 if (pp->short_banner) { /* short banner only */ 1436 if (class[0]) { 1437 (void) write(ofd, class, strlen(class)); 1438 (void) write(ofd, ":", 1); 1439 } 1440 (void) write(ofd, name1, strlen(name1)); 1441 (void) write(ofd, " Job: ", 7); 1442 (void) write(ofd, name2, strlen(name2)); 1443 (void) write(ofd, " Date: ", 8); 1444 (void) write(ofd, ctime(&tvec), 24); 1445 (void) write(ofd, "\n", 1); 1446 } else { /* normal banner */ 1447 (void) write(ofd, "\n\n\n", 3); 1448 scan_out(pp, ofd, name1, '\0'); 1449 (void) write(ofd, "\n\n", 2); 1450 scan_out(pp, ofd, name2, '\0'); 1451 if (class[0]) { 1452 (void) write(ofd,"\n\n\n",3); 1453 scan_out(pp, ofd, class, '\0'); 1454 } 1455 (void) write(ofd, "\n\n\n\n\t\t\t\t\tJob: ", 15); 1456 (void) write(ofd, name2, strlen(name2)); 1457 (void) write(ofd, "\n\t\t\t\t\tDate: ", 12); 1458 (void) write(ofd, ctime(&tvec), 24); 1459 (void) write(ofd, "\n", 1); 1460 } 1461 if (!pp->no_formfeed) 1462 (void) write(ofd, pp->form_feed, strlen(pp->form_feed)); 1463 pp->tof = 1; 1464 } 1465 1466 static char * 1467 scnline(int key, char *p, int c) 1468 { 1469 register int scnwidth; 1470 1471 for (scnwidth = WIDTH; --scnwidth;) { 1472 key <<= 1; 1473 *p++ = key & 0200 ? c : BACKGND; 1474 } 1475 return (p); 1476 } 1477 1478 #define TRC(q) (((q)-' ')&0177) 1479 1480 static void 1481 scan_out(struct printer *pp, int scfd, char *scsp, int dlm) 1482 { 1483 register char *strp; 1484 register int nchrs, j; 1485 char outbuf[LINELEN+1], *sp, c, cc; 1486 int d, scnhgt; 1487 1488 for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) { 1489 strp = &outbuf[0]; 1490 sp = scsp; 1491 for (nchrs = 0; ; ) { 1492 d = dropit(c = TRC(cc = *sp++)); 1493 if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d)) 1494 for (j = WIDTH; --j;) 1495 *strp++ = BACKGND; 1496 else 1497 strp = scnline(scnkey[(int)c][scnhgt-1-d], strp, cc); 1498 if (*sp == dlm || *sp == '\0' || 1499 nchrs++ >= pp->page_width/(WIDTH+1)-1) 1500 break; 1501 *strp++ = BACKGND; 1502 *strp++ = BACKGND; 1503 } 1504 while (*--strp == BACKGND && strp >= outbuf) 1505 ; 1506 strp++; 1507 *strp++ = '\n'; 1508 (void) write(scfd, outbuf, strp-outbuf); 1509 } 1510 } 1511 1512 static int 1513 dropit(int c) 1514 { 1515 switch(c) { 1516 1517 case TRC('_'): 1518 case TRC(';'): 1519 case TRC(','): 1520 case TRC('g'): 1521 case TRC('j'): 1522 case TRC('p'): 1523 case TRC('q'): 1524 case TRC('y'): 1525 return (DROP); 1526 1527 default: 1528 return (0); 1529 } 1530 } 1531 1532 /* 1533 * sendmail --- 1534 * tell people about job completion 1535 */ 1536 static void 1537 sendmail(struct printer *pp, char *userid, int bombed) 1538 { 1539 register int i; 1540 int p[2], s; 1541 register const char *cp; 1542 struct stat stb; 1543 FILE *fp; 1544 1545 pipe(p); 1546 if ((s = dofork(pp, DORETURN)) == 0) { /* child */ 1547 dup2(p[0], STDIN_FILENO); 1548 closelog(); 1549 closeallfds(3); 1550 if ((cp = strrchr(_PATH_SENDMAIL, '/')) != NULL) 1551 cp++; 1552 else 1553 cp = _PATH_SENDMAIL; 1554 execl(_PATH_SENDMAIL, cp, "-t", (char *)0); 1555 _exit(0); 1556 } else if (s > 0) { /* parent */ 1557 dup2(p[1], STDOUT_FILENO); 1558 printf("To: %s@%s\n", userid, origin_host); 1559 printf("Subject: %s printer job \"%s\"\n", pp->printer, 1560 *jobname ? jobname : "<unknown>"); 1561 printf("Reply-To: root@%s\n\n", local_host); 1562 printf("Your printer job "); 1563 if (*jobname) 1564 printf("(%s) ", jobname); 1565 1566 switch (bombed) { 1567 case OK: 1568 cp = "OK"; 1569 printf("\ncompleted successfully\n"); 1570 break; 1571 default: 1572 case FATALERR: 1573 cp = "FATALERR"; 1574 printf("\ncould not be printed\n"); 1575 break; 1576 case NOACCT: 1577 cp = "NOACCT"; 1578 printf("\ncould not be printed without an account on %s\n", 1579 local_host); 1580 break; 1581 case FILTERERR: 1582 cp = "FILTERERR"; 1583 if (stat(tempstderr, &stb) < 0 || stb.st_size == 0 1584 || (fp = fopen(tempstderr, "r")) == NULL) { 1585 printf("\nhad some errors and may not have printed\n"); 1586 break; 1587 } 1588 printf("\nhad the following errors and may not have printed:\n"); 1589 while ((i = getc(fp)) != EOF) 1590 putchar(i); 1591 (void) fclose(fp); 1592 break; 1593 case ACCESS: 1594 cp = "ACCESS"; 1595 printf("\nwas not printed because it was not linked to the original file\n"); 1596 } 1597 fflush(stdout); 1598 (void) close(STDOUT_FILENO); 1599 } else { 1600 syslog(LOG_WARNING, "unable to send mail to %s: %m", userid); 1601 return; 1602 } 1603 (void) close(p[0]); 1604 (void) close(p[1]); 1605 wait(NULL); 1606 syslog(LOG_INFO, "mail sent to user %s about job %s on printer %s (%s)", 1607 userid, *jobname ? jobname : "<unknown>", pp->printer, cp); 1608 } 1609 1610 /* 1611 * dofork - fork with retries on failure 1612 */ 1613 static int 1614 dofork(const struct printer *pp, int action) 1615 { 1616 pid_t forkpid; 1617 int i, fail; 1618 struct passwd *pwd; 1619 1620 forkpid = -1; 1621 if (daemon_uname == NULL) { 1622 pwd = getpwuid(pp->daemon_user); 1623 if (pwd == NULL) { 1624 syslog(LOG_ERR, "%s: Can't lookup default daemon uid (%ld) in password file", 1625 pp->printer, pp->daemon_user); 1626 goto error_ret; 1627 } 1628 daemon_uname = strdup(pwd->pw_name); 1629 daemon_defgid = pwd->pw_gid; 1630 } 1631 1632 for (i = 0; i < 20; i++) { 1633 forkpid = fork(); 1634 if (forkpid < 0) { 1635 sleep((unsigned)(i*i)); 1636 continue; 1637 } 1638 /* 1639 * Child should run as daemon instead of root 1640 */ 1641 if (forkpid == 0) { 1642 errno = 0; 1643 fail = initgroups(daemon_uname, daemon_defgid); 1644 if (fail) { 1645 syslog(LOG_ERR, "%s: initgroups(%s,%u): %m", 1646 pp->printer, daemon_uname, daemon_defgid); 1647 break; 1648 } 1649 fail = setgid(daemon_defgid); 1650 if (fail) { 1651 syslog(LOG_ERR, "%s: setgid(%u): %m", 1652 pp->printer, daemon_defgid); 1653 break; 1654 } 1655 fail = setuid(pp->daemon_user); 1656 if (fail) { 1657 syslog(LOG_ERR, "%s: setuid(%ld): %m", 1658 pp->printer, pp->daemon_user); 1659 break; 1660 } 1661 } 1662 return (forkpid); 1663 } 1664 1665 /* 1666 * An error occurred. If the error is in the child process, then 1667 * this routine MUST always exit(). DORETURN only effects how 1668 * errors should be handled in the parent process. 1669 */ 1670 error_ret: 1671 if (forkpid == 0) { 1672 syslog(LOG_ERR, "%s: dofork(): aborting child process...", 1673 pp->printer); 1674 exit(1); 1675 } 1676 syslog(LOG_ERR, "%s: dofork(): failure in fork", pp->printer); 1677 1678 sleep(1); /* throttle errors, as a safety measure */ 1679 switch (action) { 1680 case DORETURN: 1681 return (-1); 1682 default: 1683 syslog(LOG_ERR, "bad action (%d) to dofork", action); 1684 /* FALLTHROUGH */ 1685 case DOABORT: 1686 exit(1); 1687 } 1688 /*NOTREACHED*/ 1689 } 1690 1691 /* 1692 * Kill child processes to abort current job. 1693 */ 1694 static void 1695 abortpr(int signo __unused) 1696 { 1697 1698 (void) unlink(tempstderr); 1699 kill(0, SIGINT); 1700 if (of_pid > 0) 1701 kill(of_pid, SIGCONT); 1702 while (wait(NULL) > 0) 1703 ; 1704 if (of_pid > 0 && tfd != -1) 1705 unlink(tfile); 1706 exit(0); 1707 } 1708 1709 static void 1710 init(struct printer *pp) 1711 { 1712 char *s; 1713 1714 sprintf(&width[2], "%ld", pp->page_width); 1715 sprintf(&length[2], "%ld", pp->page_length); 1716 sprintf(&pxwidth[2], "%ld", pp->page_pwidth); 1717 sprintf(&pxlength[2], "%ld", pp->page_plength); 1718 if ((s = checkremote(pp)) != 0) { 1719 syslog(LOG_WARNING, "%s", s); 1720 free(s); 1721 } 1722 } 1723 1724 void 1725 startprinting(const char *printer) 1726 { 1727 struct printer myprinter, *pp = &myprinter; 1728 int status; 1729 1730 init_printer(pp); 1731 status = getprintcap(printer, pp); 1732 switch(status) { 1733 case PCAPERR_OSERR: 1734 syslog(LOG_ERR, "can't open printer description file: %m"); 1735 exit(1); 1736 case PCAPERR_NOTFOUND: 1737 syslog(LOG_ERR, "unknown printer: %s", printer); 1738 exit(1); 1739 case PCAPERR_TCLOOP: 1740 fatal(pp, "potential reference loop detected in printcap file"); 1741 default: 1742 break; 1743 } 1744 printjob(pp); 1745 } 1746 1747 /* 1748 * Acquire line printer or remote connection. 1749 */ 1750 static void 1751 openpr(const struct printer *pp) 1752 { 1753 int p[2]; 1754 char *cp; 1755 1756 if (pp->remote) { 1757 openrem(pp); 1758 /* 1759 * Lpd does support the setting of 'of=' filters for 1760 * jobs going to remote machines, but that does not 1761 * have the same meaning as 'of=' does when handling 1762 * local print queues. For remote machines, all 'of=' 1763 * filter processing is handled in sendfile(), and that 1764 * does not use these global "output filter" variables. 1765 */ 1766 ofd = -1; 1767 of_pid = 0; 1768 return; 1769 } else if (*pp->lp) { 1770 if ((cp = strchr(pp->lp, '@')) != NULL) 1771 opennet(pp); 1772 else 1773 opentty(pp); 1774 } else { 1775 syslog(LOG_ERR, "%s: no line printer device or host name", 1776 pp->printer); 1777 exit(1); 1778 } 1779 1780 /* 1781 * Start up an output filter, if needed. 1782 */ 1783 if (pp->filters[LPF_OUTPUT] && !pp->filters[LPF_INPUT] && !of_pid) { 1784 pipe(p); 1785 if (pp->remote) { 1786 strcpy(tfile, TFILENAME); 1787 tfd = mkstemp(tfile); 1788 } 1789 if ((of_pid = dofork(pp, DOABORT)) == 0) { /* child */ 1790 dup2(p[0], STDIN_FILENO); /* pipe is std in */ 1791 /* tfile/printer is stdout */ 1792 dup2(pp->remote ? tfd : pfd, STDOUT_FILENO); 1793 closelog(); 1794 closeallfds(3); 1795 if ((cp = strrchr(pp->filters[LPF_OUTPUT], '/')) == NULL) 1796 cp = pp->filters[LPF_OUTPUT]; 1797 else 1798 cp++; 1799 execl(pp->filters[LPF_OUTPUT], cp, width, length, 1800 (char *)0); 1801 syslog(LOG_ERR, "%s: execl(%s): %m", pp->printer, 1802 pp->filters[LPF_OUTPUT]); 1803 exit(1); 1804 } 1805 (void) close(p[0]); /* close input side */ 1806 ofd = p[1]; /* use pipe for output */ 1807 } else { 1808 ofd = pfd; 1809 of_pid = 0; 1810 } 1811 } 1812 1813 /* 1814 * Printer connected directly to the network 1815 * or to a terminal server on the net 1816 */ 1817 static void 1818 opennet(const struct printer *pp) 1819 { 1820 register int i; 1821 int resp; 1822 u_long port; 1823 char *ep; 1824 void (*savealrm)(int); 1825 1826 port = strtoul(pp->lp, &ep, 0); 1827 if (*ep != '@' || port > 65535) { 1828 syslog(LOG_ERR, "%s: bad port number: %s", pp->printer, 1829 pp->lp); 1830 exit(1); 1831 } 1832 ep++; 1833 1834 for (i = 1; ; i = i < 256 ? i << 1 : i) { 1835 resp = -1; 1836 savealrm = signal(SIGALRM, alarmhandler); 1837 alarm(pp->conn_timeout); 1838 pfd = getport(pp, ep, port); 1839 alarm(0); 1840 (void)signal(SIGALRM, savealrm); 1841 if (pfd < 0 && errno == ECONNREFUSED) 1842 resp = 1; 1843 else if (pfd >= 0) { 1844 /* 1845 * need to delay a bit for rs232 lines 1846 * to stabilize in case printer is 1847 * connected via a terminal server 1848 */ 1849 delay(500); 1850 break; 1851 } 1852 if (i == 1) { 1853 if (resp < 0) 1854 pstatus(pp, "waiting for %s to come up", 1855 pp->lp); 1856 else 1857 pstatus(pp, 1858 "waiting for access to printer on %s", 1859 pp->lp); 1860 } 1861 sleep(i); 1862 } 1863 pstatus(pp, "sending to %s port %lu", ep, port); 1864 } 1865 1866 /* 1867 * Printer is connected to an RS232 port on this host 1868 */ 1869 static void 1870 opentty(const struct printer *pp) 1871 { 1872 register int i; 1873 1874 for (i = 1; ; i = i < 32 ? i << 1 : i) { 1875 pfd = open(pp->lp, pp->rw ? O_RDWR : O_WRONLY); 1876 if (pfd >= 0) { 1877 delay(500); 1878 break; 1879 } 1880 if (errno == ENOENT) { 1881 syslog(LOG_ERR, "%s: %m", pp->lp); 1882 exit(1); 1883 } 1884 if (i == 1) 1885 pstatus(pp, 1886 "waiting for %s to become ready (offline?)", 1887 pp->printer); 1888 sleep(i); 1889 } 1890 if (isatty(pfd)) 1891 setty(pp); 1892 pstatus(pp, "%s is ready and printing", pp->printer); 1893 } 1894 1895 /* 1896 * Printer is on a remote host 1897 */ 1898 static void 1899 openrem(const struct printer *pp) 1900 { 1901 register int i; 1902 int resp; 1903 void (*savealrm)(int); 1904 1905 for (i = 1; ; i = i < 256 ? i << 1 : i) { 1906 resp = -1; 1907 savealrm = signal(SIGALRM, alarmhandler); 1908 alarm(pp->conn_timeout); 1909 pfd = getport(pp, pp->remote_host, 0); 1910 alarm(0); 1911 (void)signal(SIGALRM, savealrm); 1912 if (pfd >= 0) { 1913 if ((writel(pfd, "\2", pp->remote_queue, "\n", 1914 (char *)0) 1915 == 2 + strlen(pp->remote_queue)) 1916 && (resp = response(pp)) == 0) 1917 break; 1918 (void) close(pfd); 1919 } 1920 if (i == 1) { 1921 if (resp < 0) 1922 pstatus(pp, "waiting for %s to come up", 1923 pp->remote_host); 1924 else { 1925 pstatus(pp, 1926 "waiting for queue to be enabled on %s", 1927 pp->remote_host); 1928 i = 256; 1929 } 1930 } 1931 sleep(i); 1932 } 1933 pstatus(pp, "sending to %s", pp->remote_host); 1934 } 1935 1936 /* 1937 * setup tty lines. 1938 */ 1939 static void 1940 setty(const struct printer *pp) 1941 { 1942 struct termios ttybuf; 1943 1944 if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) { 1945 syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", pp->printer); 1946 exit(1); 1947 } 1948 if (tcgetattr(pfd, &ttybuf) < 0) { 1949 syslog(LOG_ERR, "%s: tcgetattr: %m", pp->printer); 1950 exit(1); 1951 } 1952 if (pp->baud_rate > 0) 1953 cfsetspeed(&ttybuf, pp->baud_rate); 1954 if (pp->mode_set) { 1955 char *s = strdup(pp->mode_set), *tmp; 1956 1957 while ((tmp = strsep(&s, ",")) != NULL) { 1958 (void) msearch(tmp, &ttybuf); 1959 } 1960 } 1961 if (pp->mode_set != 0 || pp->baud_rate > 0) { 1962 if (tcsetattr(pfd, TCSAFLUSH, &ttybuf) == -1) { 1963 syslog(LOG_ERR, "%s: tcsetattr: %m", pp->printer); 1964 } 1965 } 1966 } 1967 1968 #include <stdarg.h> 1969 1970 static void 1971 pstatus(const struct printer *pp, const char *msg, ...) 1972 { 1973 int fd; 1974 char *buf; 1975 va_list ap; 1976 va_start(ap, msg); 1977 1978 umask(S_IWOTH); 1979 fd = open(pp->status_file, O_WRONLY|O_CREAT|O_EXLOCK, STAT_FILE_MODE); 1980 if (fd < 0) { 1981 syslog(LOG_ERR, "%s: open(%s): %m", pp->printer, 1982 pp->status_file); 1983 exit(1); 1984 } 1985 ftruncate(fd, 0); 1986 vasprintf(&buf, msg, ap); 1987 va_end(ap); 1988 writel(fd, buf, "\n", (char *)0); 1989 close(fd); 1990 free(buf); 1991 } 1992 1993 void 1994 alarmhandler(int signo __unused) 1995 { 1996 /* the signal is ignored */ 1997 /* (the '__unused' is just to avoid a compile-time warning) */ 1998 } 1999