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