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