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