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