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