Deleted Added
full compact
lpr.c (241015) lpr.c (241852)
1/*
2 * Copyright (c) 1983, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.

--- 36 unchanged lines hidden (view full) ---

45
46#if 0
47#ifndef lint
48static char sccsid[] = "@(#)lpr.c 8.4 (Berkeley) 4/28/95";
49#endif /* not lint */
50#endif
51
52#include "lp.cdefs.h" /* A cross-platform version of <sys/cdefs.h> */
1/*
2 * Copyright (c) 1983, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.

--- 36 unchanged lines hidden (view full) ---

45
46#if 0
47#ifndef lint
48static char sccsid[] = "@(#)lpr.c 8.4 (Berkeley) 4/28/95";
49#endif /* not lint */
50#endif
51
52#include "lp.cdefs.h" /* A cross-platform version of <sys/cdefs.h> */
53__FBSDID("$FreeBSD: head/usr.sbin/lpr/lpr/lpr.c 241015 2012-09-27 23:31:19Z mdf $");
53__FBSDID("$FreeBSD: head/usr.sbin/lpr/lpr/lpr.c 241852 2012-10-22 03:31:22Z eadler $");
54
55/*
56 * lpr -- off line print
57 *
58 * Allows multiple printers and printers on remote machines by
59 * using information from a printer data base.
60 */
61

--- 78 unchanged lines hidden (view full) ---

140 int ret, didlink;
141 struct stat stb;
142 struct stat statb1, statb2;
143 struct printer myprinter, *pp = &myprinter;
144
145 printer = NULL;
146 euid = geteuid();
147 uid = getuid();
54
55/*
56 * lpr -- off line print
57 *
58 * Allows multiple printers and printers on remote machines by
59 * using information from a printer data base.
60 */
61

--- 78 unchanged lines hidden (view full) ---

140 int ret, didlink;
141 struct stat stb;
142 struct stat statb1, statb2;
143 struct printer myprinter, *pp = &myprinter;
144
145 printer = NULL;
146 euid = geteuid();
147 uid = getuid();
148 seteuid(uid);
148 PRIV_END
149 if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
150 signal(SIGHUP, cleanup);
151 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
152 signal(SIGINT, cleanup);
153 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
154 signal(SIGQUIT, cleanup);
155 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
156 signal(SIGTERM, cleanup);

--- 164 unchanged lines hidden (view full) ---

321 lock_file_name(pp, buf, sizeof buf);
322 if (userid && stat(buf, &stb) == 0 && (stb.st_mode & LFM_QUEUE_DIS))
323 errx(1, "Printer queue is disabled");
324 /*
325 * Initialize the control file.
326 */
327 mktemps(pp);
328 tfd = nfile(tfname);
149 if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
150 signal(SIGHUP, cleanup);
151 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
152 signal(SIGINT, cleanup);
153 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
154 signal(SIGQUIT, cleanup);
155 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
156 signal(SIGTERM, cleanup);

--- 164 unchanged lines hidden (view full) ---

321 lock_file_name(pp, buf, sizeof buf);
322 if (userid && stat(buf, &stb) == 0 && (stb.st_mode & LFM_QUEUE_DIS))
323 errx(1, "Printer queue is disabled");
324 /*
325 * Initialize the control file.
326 */
327 mktemps(pp);
328 tfd = nfile(tfname);
329 seteuid(euid);
329 PRIV_START
330 (void) fchown(tfd, pp->daemon_user, -1);
331 /* owned by daemon for protection */
330 (void) fchown(tfd, pp->daemon_user, -1);
331 /* owned by daemon for protection */
332 seteuid(uid);
332 PRIV_END
333 card('H', local_host);
334 card('P', lpr_username);
335 card('C', class);
336 if (hdr && !pp->no_header) {
337 if (jobname == NULL) {
338 if (argc == 0)
339 jobname = "stdin";
340 else

--- 69 unchanged lines hidden (view full) ---

410 /*
411 * The user wants the file removed after it is copied
412 * to the spool area, so see if the file can be moved
413 * instead of copy/unlink'ed. This is much faster and
414 * uses less spool space than copying the file. This
415 * can be very significant when running services like
416 * samba, pcnfs, CAP, et al.
417 */
333 card('H', local_host);
334 card('P', lpr_username);
335 card('C', class);
336 if (hdr && !pp->no_header) {
337 if (jobname == NULL) {
338 if (argc == 0)
339 jobname = "stdin";
340 else

--- 69 unchanged lines hidden (view full) ---

410 /*
411 * The user wants the file removed after it is copied
412 * to the spool area, so see if the file can be moved
413 * instead of copy/unlink'ed. This is much faster and
414 * uses less spool space than copying the file. This
415 * can be very significant when running services like
416 * samba, pcnfs, CAP, et al.
417 */
418 seteuid(euid);
418 PRIV_START
419 didlink = 0;
420 /*
421 * There are several things to check to avoid any
422 * security issues. Some of these are redundant
423 * under BSD's, but are necessary when lpr is built
424 * under some other OS's (which I do do...)
425 */
426 if (lstat(arg, &statb1) < 0)

--- 21 unchanged lines hidden (view full) ---

448 if (statb2.st_nlink > 2)
449 goto nohardlink;
450 /*
451 * If we can access and remove the original file
452 * without special setuid-ness then this method is
453 * safe. Otherwise, abandon the move and fall back
454 * to the (usual) copy method.
455 */
419 didlink = 0;
420 /*
421 * There are several things to check to avoid any
422 * security issues. Some of these are redundant
423 * under BSD's, but are necessary when lpr is built
424 * under some other OS's (which I do do...)
425 */
426 if (lstat(arg, &statb1) < 0)

--- 21 unchanged lines hidden (view full) ---

448 if (statb2.st_nlink > 2)
449 goto nohardlink;
450 /*
451 * If we can access and remove the original file
452 * without special setuid-ness then this method is
453 * safe. Otherwise, abandon the move and fall back
454 * to the (usual) copy method.
455 */
456 seteuid(uid);
456 PRIV_END
457 ret = access(dfname, R_OK);
458 if (ret == 0)
459 ret = unlink(arg);
457 ret = access(dfname, R_OK);
458 if (ret == 0)
459 ret = unlink(arg);
460 seteuid(euid);
460 PRIV_START
461 if (ret != 0)
462 goto nohardlink;
463 /*
464 * Unlink of user file was successful. Change the
465 * owner and permissions, add entries to the control
466 * file, and skip the file copying step.
467 */
468 chown(dfname, pp->daemon_user, getegid());
469 chmod(dfname, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
461 if (ret != 0)
462 goto nohardlink;
463 /*
464 * Unlink of user file was successful. Change the
465 * owner and permissions, add entries to the control
466 * file, and skip the file copying step.
467 */
468 chown(dfname, pp->daemon_user, getegid());
469 chmod(dfname, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
470 seteuid(uid);
470 PRIV_END
471 if (format == 'p')
472 card('T', title ? title : arg);
473 for (i = 0; i < ncopies; i++)
474 card(format, &dfname[inchar-2]);
475 card('U', &dfname[inchar-2]);
476 card('N', arg);
477 nact++;
478 continue;
479 nohardlink:
480 if (didlink)
481 unlink(dfname);
471 if (format == 'p')
472 card('T', title ? title : arg);
473 for (i = 0; i < ncopies; i++)
474 card(format, &dfname[inchar-2]);
475 card('U', &dfname[inchar-2]);
476 card('N', arg);
477 nact++;
478 continue;
479 nohardlink:
480 if (didlink)
481 unlink(dfname);
482 seteuid(uid); /* restore old uid */
482 PRIV_END /* restore old uid */
483 } /* end: if (f) */
484
485 if ((i = open(arg, O_RDONLY)) < 0) {
486 printf("%s: cannot open %s\n", progname, arg);
487 } else {
488 copy(pp, i, arg);
489 (void) close(i);
490 if (f && unlink(arg) < 0)
491 printf("%s: %s: not removed\n", progname, arg);
492 }
493 }
494
495 if (nact) {
496 (void) close(tfd);
497 tfname[inchar]--;
498 /*
499 * Touch the control file to fix position in the queue.
500 */
483 } /* end: if (f) */
484
485 if ((i = open(arg, O_RDONLY)) < 0) {
486 printf("%s: cannot open %s\n", progname, arg);
487 } else {
488 copy(pp, i, arg);
489 (void) close(i);
490 if (f && unlink(arg) < 0)
491 printf("%s: %s: not removed\n", progname, arg);
492 }
493 }
494
495 if (nact) {
496 (void) close(tfd);
497 tfname[inchar]--;
498 /*
499 * Touch the control file to fix position in the queue.
500 */
501 seteuid(euid);
501 PRIV_START
502 if ((tfd = open(tfname, O_RDWR)) >= 0) {
503 char touch_c;
504
505 if (read(tfd, &touch_c, 1) == 1 &&
506 lseek(tfd, (off_t)0, 0) == 0 &&
507 write(tfd, &touch_c, 1) != 1) {
508 printf("%s: cannot touch %s\n", progname,
509 tfname);
510 tfname[inchar]++;
511 cleanup(0);
512 }
513 (void) close(tfd);
514 }
515 if (link(tfname, cfname) < 0) {
516 printf("%s: cannot rename %s\n", progname, cfname);
517 tfname[inchar]++;
518 cleanup(0);
519 }
520 unlink(tfname);
502 if ((tfd = open(tfname, O_RDWR)) >= 0) {
503 char touch_c;
504
505 if (read(tfd, &touch_c, 1) == 1 &&
506 lseek(tfd, (off_t)0, 0) == 0 &&
507 write(tfd, &touch_c, 1) != 1) {
508 printf("%s: cannot touch %s\n", progname,
509 tfname);
510 tfname[inchar]++;
511 cleanup(0);
512 }
513 (void) close(tfd);
514 }
515 if (link(tfname, cfname) < 0) {
516 printf("%s: cannot rename %s\n", progname, cfname);
517 tfname[inchar]++;
518 cleanup(0);
519 }
520 unlink(tfname);
521 seteuid(uid);
521 PRIV_END
522 if (qflag) /* just q things up */
523 exit(0);
524 if (!startdaemon(pp))
525 printf("jobs queued, but cannot start daemon.\n");
526 exit(0);
527 }
528 cleanup(0);
529 return (1);

--- 69 unchanged lines hidden (view full) ---

599 }
600 }
601 break;
602 }
603 strncat(buf, "/", sizeof(buf) - strlen(buf) - 1);
604 strncat(buf, file, sizeof(buf) - strlen(buf) - 1);
605 file = buf;
606 }
522 if (qflag) /* just q things up */
523 exit(0);
524 if (!startdaemon(pp))
525 printf("jobs queued, but cannot start daemon.\n");
526 exit(0);
527 }
528 cleanup(0);
529 return (1);

--- 69 unchanged lines hidden (view full) ---

599 }
600 }
601 break;
602 }
603 strncat(buf, "/", sizeof(buf) - strlen(buf) - 1);
604 strncat(buf, file, sizeof(buf) - strlen(buf) - 1);
605 file = buf;
606 }
607 seteuid(euid);
607 PRIV_START
608 ret = symlink(file, dfname);
608 ret = symlink(file, dfname);
609 seteuid(uid);
609 PRIV_END
610 return(ret ? NULL : file);
611}
612
613/*
614 * Put a line into the control file.
615 */
616static void
617card(int c, const char *p2)

--- 15 unchanged lines hidden (view full) ---

633 * Create a new file in the spool directory.
634 */
635static int
636nfile(char *n)
637{
638 register int f;
639 int oldumask = umask(0); /* should block signals */
640
610 return(ret ? NULL : file);
611}
612
613/*
614 * Put a line into the control file.
615 */
616static void
617card(int c, const char *p2)

--- 15 unchanged lines hidden (view full) ---

633 * Create a new file in the spool directory.
634 */
635static int
636nfile(char *n)
637{
638 register int f;
639 int oldumask = umask(0); /* should block signals */
640
641 seteuid(euid);
641 PRIV_START
642 f = open(n, O_WRONLY | O_EXCL | O_CREAT, FILMOD);
643 (void) umask(oldumask);
644 if (f < 0) {
645 printf("%s: cannot create %s\n", progname, n);
646 cleanup(0);
647 }
648 if (fchown(f, userid, -1) < 0) {
649 printf("%s: cannot chown %s\n", progname, n);
650 cleanup(0); /* cleanup does exit */
651 }
642 f = open(n, O_WRONLY | O_EXCL | O_CREAT, FILMOD);
643 (void) umask(oldumask);
644 if (f < 0) {
645 printf("%s: cannot create %s\n", progname, n);
646 cleanup(0);
647 }
648 if (fchown(f, userid, -1) < 0) {
649 printf("%s: cannot chown %s\n", progname, n);
650 cleanup(0); /* cleanup does exit */
651 }
652 seteuid(uid);
652 PRIV_END
653 if (++n[inchar] > 'z') {
654 if (++n[inchar-2] == 't') {
655 printf("too many files - break up the job\n");
656 cleanup(0);
657 }
658 n[inchar] = 'A';
659 } else if (n[inchar] == '[')
660 n[inchar] = 'a';

--- 8 unchanged lines hidden (view full) ---

669{
670 register int i;
671
672 signal(SIGHUP, SIG_IGN);
673 signal(SIGINT, SIG_IGN);
674 signal(SIGQUIT, SIG_IGN);
675 signal(SIGTERM, SIG_IGN);
676 i = inchar;
653 if (++n[inchar] > 'z') {
654 if (++n[inchar-2] == 't') {
655 printf("too many files - break up the job\n");
656 cleanup(0);
657 }
658 n[inchar] = 'A';
659 } else if (n[inchar] == '[')
660 n[inchar] = 'a';

--- 8 unchanged lines hidden (view full) ---

669{
670 register int i;
671
672 signal(SIGHUP, SIG_IGN);
673 signal(SIGINT, SIG_IGN);
674 signal(SIGQUIT, SIG_IGN);
675 signal(SIGTERM, SIG_IGN);
676 i = inchar;
677 seteuid(euid);
677 PRIV_START
678 if (tfname)
679 do
680 unlink(tfname);
681 while (tfname[i]-- != 'A');
682 if (cfname)
683 do
684 unlink(cfname);
685 while (cfname[i]-- != 'A');

--- 155 unchanged lines hidden (view full) ---

841static void
842mktemps(const struct printer *pp)
843{
844 register int len, fd, n;
845 register char *cp;
846 char buf[BUFSIZ];
847
848 (void) snprintf(buf, sizeof(buf), "%s/.seq", pp->spool_dir);
678 if (tfname)
679 do
680 unlink(tfname);
681 while (tfname[i]-- != 'A');
682 if (cfname)
683 do
684 unlink(cfname);
685 while (cfname[i]-- != 'A');

--- 155 unchanged lines hidden (view full) ---

841static void
842mktemps(const struct printer *pp)
843{
844 register int len, fd, n;
845 register char *cp;
846 char buf[BUFSIZ];
847
848 (void) snprintf(buf, sizeof(buf), "%s/.seq", pp->spool_dir);
849 seteuid(euid);
849 PRIV_START
850 if ((fd = open(buf, O_RDWR|O_CREAT, 0664)) < 0) {
851 printf("%s: cannot create %s\n", progname, buf);
852 exit(1);
853 }
854 if (flock(fd, LOCK_EX)) {
855 printf("%s: cannot lock %s\n", progname, buf);
856 exit(1);
857 }
850 if ((fd = open(buf, O_RDWR|O_CREAT, 0664)) < 0) {
851 printf("%s: cannot create %s\n", progname, buf);
852 exit(1);
853 }
854 if (flock(fd, LOCK_EX)) {
855 printf("%s: cannot lock %s\n", progname, buf);
856 exit(1);
857 }
858 seteuid(uid);
858 PRIV_END
859 n = 0;
860 if ((len = read(fd, buf, sizeof(buf))) > 0) {
861 for (cp = buf; len--; ) {
862 if (*cp < '0' || *cp > '9')
863 break;
864 n = n * 10 + (*cp++ - '0');
865 }
866 }

--- 26 unchanged lines hidden ---
859 n = 0;
860 if ((len = read(fd, buf, sizeof(buf))) > 0) {
861 for (cp = buf; len--; ) {
862 if (*cp < '0' || *cp > '9')
863 break;
864 n = n * 10 + (*cp++ - '0');
865 }
866 }

--- 26 unchanged lines hidden ---