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.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * @(#) Copyright (c) 1983, 1989, 1993 The Regents of the University of California. All rights reserved.
40 * @(#)from: lpr.c 8.4 (Berkeley) 4/28/95
41 * $FreeBSD: src/usr.sbin/lpr/lpr/lpr.c,v 1.32.2.11 2002/04/28 23:40:23 gad Exp $
42 * $DragonFly: src/usr.sbin/lpr/lpr/lpr.c,v 1.5 2005/08/08 18:58:56 joerg Exp $
46 * lpr -- off line print
48 * Allows multiple printers and printers on remote machines by
49 * using information from a printer data base.
52 #include <sys/param.h>
55 #include <netinet/in.h> /* N_BADMAG uses ntohl() */
74 #include "pathnames.h"
76 static char *cfname
; /* daemon control files, linked from tf's */
77 static char *class = local_host
; /* class title on header page */
78 static char *dfname
; /* data files */
79 static char *fonts
[4]; /* troff font names */
80 static char format
= 'f'; /* format char for printing files */
81 static int hdr
= 1; /* print header or not (default is yes) */
82 static int iflag
; /* indentation wanted */
83 static int inchar
; /* location to increment char in file names */
84 static int indent
; /* amount to indent */
85 static const char *jobname
; /* job name on header page */
86 static int mailflg
; /* send mail */
87 static int nact
; /* number of jobs to act on */
88 static int ncopies
= 1; /* # of copies to make */
89 static char *lpr_username
; /* person sending the print job(s) */
90 static int qflag
; /* q job, but don't exec daemon */
91 static int rflag
; /* remove files upon completion */
92 static int sflag
; /* symbolic link flag */
93 static int tfd
; /* control file descriptor */
94 static char *tfname
; /* tmp copy of cf before linking */
95 static char *title
; /* pr'ing title */
96 static char *locale
; /* pr'ing locale */
97 static int userid
; /* user id */
98 static char *Uflag
; /* user name specified with -U flag */
99 static char *width
; /* width for versatec printing */
100 static char *Zflag
; /* extra filter options for LPRng servers */
102 static struct stat statb
;
104 static void card(int _c
, const char *_p2
);
105 static int checkwriteperm(const char *_file
, const char *_directory
);
106 static void chkprinter(const char *_ptrname
, struct printer
*_pp
);
107 static void cleanup(int _signo
);
108 static void copy(const struct printer
*_pp
, int _f
, const char _n
[]);
109 static char *itoa(int _i
);
110 static const char *linked(const char *_file
);
111 int main(int _argc
, char *_argv
[]);
112 static char *lmktemp(const struct printer
*_pp
, const char *_id
,
114 static void mktemps(const struct printer
*_pp
);
115 static int nfile(char *_n
);
116 static int test(const char *_file
);
117 static void usage(void);
122 main(int argc
, char *argv
[])
126 const char *arg
, *cp
, *printer
;
132 struct stat statb1
, statb2
;
133 struct printer myprinter
, *pp
= &myprinter
;
139 if (signal(SIGHUP
, SIG_IGN
) != SIG_IGN
)
140 signal(SIGHUP
, cleanup
);
141 if (signal(SIGINT
, SIG_IGN
) != SIG_IGN
)
142 signal(SIGINT
, cleanup
);
143 if (signal(SIGQUIT
, SIG_IGN
) != SIG_IGN
)
144 signal(SIGQUIT
, cleanup
);
145 if (signal(SIGTERM
, SIG_IGN
) != SIG_IGN
)
146 signal(SIGTERM
, cleanup
);
149 gethostname(local_host
, sizeof(local_host
));
150 openlog("lpd", 0, LOG_LPR
);
153 while ((c
= getopt(argc
, argv
,
154 ":#:1:2:3:4:C:J:L:P:T:U:Z:cdfghi:lnmprstvw:"))
157 case '#': /* n copies */
158 i
= strtol(optarg
, &p
, 10);
160 errx(1, "Bad argument to -#, number expected");
165 case '1': /* troff fonts */
169 fonts
[optopt
- '1'] = optarg
;
172 case 'C': /* classification spec */
177 case 'J': /* job name */
182 case 'P': /* specifiy printer name */
186 case 'L': /* pr's locale */
190 case 'T': /* pr's title line */
194 case 'U': /* user name */
203 case 'c': /* print cifplot output */
204 case 'd': /* print tex output (dvi files) */
205 case 'g': /* print graph(1G) output */
206 case 'l': /* literal output */
207 case 'n': /* print ditroff output */
208 case 't': /* print troff output (cat files) */
209 case 'p': /* print using ``pr'' */
210 case 'v': /* print vplot output */
214 case 'f': /* print fortran output */
218 case 'h': /* nulifiy header page */
222 case 'i': /* indent output */
224 indent
= strtol(optarg
, &p
, 10);
226 errx(1, "Bad argument to -i, number expected");
229 case 'm': /* send mail when done */
233 case 'q': /* just queue job */
237 case 'r': /* remove file when done */
241 case 's': /* try to link files */
245 case 'w': /* versatec page width */
249 case ':': /* catch "missing argument" error */
251 iflag
++; /* -i without args is valid */
264 if (printer
== NULL
&& (printer
= getenv("PRINTER")) == NULL
)
266 chkprinter(printer
, pp
);
267 if (pp
->no_copies
&& ncopies
> 1)
268 errx(1, "multiple copies are not allowed");
269 if (pp
->max_copies
> 0 && ncopies
> pp
->max_copies
)
270 errx(1, "only %ld copies are allowed", pp
->max_copies
);
272 * Get the identity of the person doing the lpr using the same
273 * algorithm as lprm. Actually, not quite -- lprm will override
274 * the login name with "root" if the user is running as root;
275 * the daemon actually checks for the string "root" in its
276 * permission checking. Sigh.
280 if (userid
!= 0 && userid
!= pp
->daemon_user
)
281 errx(1, "only privileged users may use the `-U' flag");
282 lpr_username
= Uflag
; /* -U person doing 'lpr' */
284 lpr_username
= getlogin(); /* person doing 'lpr' */
285 if (userid
!= pp
->daemon_user
|| lpr_username
== 0) {
286 if ((pw
= getpwuid(userid
)) == NULL
)
287 errx(1, "Who are you?");
288 lpr_username
= pw
->pw_name
;
293 * Check for restricted group access.
295 if (pp
->restrict_grp
!= NULL
&& userid
!= pp
->daemon_user
) {
296 if ((gptr
= getgrnam(pp
->restrict_grp
)) == NULL
)
297 errx(1, "Restricted group specified incorrectly");
298 if (gptr
->gr_gid
!= getgid()) {
299 while (*gptr
->gr_mem
!= NULL
) {
300 if ((strcmp(lpr_username
, *gptr
->gr_mem
)) == 0)
304 if (*gptr
->gr_mem
== NULL
)
305 errx(1, "Not a member of the restricted group");
309 * Check to make sure queuing is enabled if userid is not root.
311 lock_file_name(pp
, buf
, sizeof buf
);
312 if (userid
&& stat(buf
, &stb
) == 0 && (stb
.st_mode
& LFM_QUEUE_DIS
))
313 errx(1, "Printer queue is disabled");
315 * Initialize the control file.
320 fchown(tfd
, pp
->daemon_user
, -1);
321 /* owned by daemon for protection */
323 card('H', local_host
);
324 card('P', lpr_username
);
326 if (hdr
&& !pp
->no_header
) {
327 if (jobname
== NULL
) {
331 jobname
= ((arg
= strrchr(argv
[0], '/'))
332 ? arg
+ 1 : argv
[0]);
335 card('L', lpr_username
);
337 if (format
!= 'p' && Zflag
!= 0)
340 card('I', itoa(indent
));
342 card('M', lpr_username
);
343 if (format
== 't' || format
== 'n' || format
== 'd')
344 for (i
= 0; i
< 4; i
++)
345 if (fonts
[i
] != NULL
)
346 card('1'+i
, fonts
[i
]);
351 * Our use of `Z' here is incompatible with LPRng's
352 * use. We assume that the only use of our existing
353 * `Z' card is as shown for `p' format (pr) files.
360 else if ((s
= setlocale(LC_TIME
, "")) != NULL
)
365 * Read the files and spool them.
369 else while (argc
--) {
370 if (argv
[0][0] == '-' && argv
[0][1] == '\0') {
376 if ((f
= test(arg
= *argv
++)) < 0)
377 continue; /* file unreasonable */
379 if (sflag
&& (cp
= linked(arg
)) != NULL
) {
380 snprintf(buf
, sizeof(buf
), "%d %"PRId64
, statb
.st_dev
,
381 (uint64_t)statb
.st_ino
);
384 card('T', title
? title
: arg
);
385 for (i
= 0; i
< ncopies
; i
++)
386 card(format
, &dfname
[inchar
-2]);
387 card('U', &dfname
[inchar
-2]);
396 printf("%s: %s: not linked, copying instead\n",
401 * The user wants the file removed after it is copied
402 * to the spool area, so see if the file can be moved
403 * instead of copy/unlink'ed. This is much faster and
404 * uses less spool space than copying the file. This
405 * can be very significant when running services like
406 * samba, pcnfs, CAP, et al.
411 * There are several things to check to avoid any
412 * security issues. Some of these are redundant
413 * under BSD's, but are necessary when lpr is built
414 * under some other OS's (which I do do...)
416 if (lstat(arg
, &statb1
) < 0)
418 if (S_ISLNK(statb1
.st_mode
))
420 if (link(arg
, dfname
) != 0)
424 * Make sure the user hasn't tried to trick us via
425 * any race conditions
427 if (lstat(dfname
, &statb2
) < 0)
429 if (statb1
.st_dev
!= statb2
.st_dev
)
431 if (statb1
.st_ino
!= statb2
.st_ino
)
434 * Skip if the file already had multiple hard links,
435 * because changing the owner and access-bits would
436 * change ALL versions of the file
438 if (statb2
.st_nlink
> 2)
441 * If we can access and remove the original file
442 * without special setuid-ness then this method is
443 * safe. Otherwise, abandon the move and fall back
444 * to the (usual) copy method.
447 ret
= access(dfname
, R_OK
);
454 * Unlink of user file was successful. Change the
455 * owner and permissions, add entries to the control
456 * file, and skip the file copying step.
458 chown(dfname
, pp
->daemon_user
, getegid());
459 chmod(dfname
, S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
);
462 card('T', title
? title
: arg
);
463 for (i
= 0; i
< ncopies
; i
++)
464 card(format
, &dfname
[inchar
-2]);
465 card('U', &dfname
[inchar
-2]);
472 seteuid(uid
); /* restore old uid */
475 if ((i
= open(arg
, O_RDONLY
)) < 0) {
476 printf("%s: cannot open %s\n", progname
, arg
);
480 if (f
&& unlink(arg
) < 0)
481 printf("%s: %s: not removed\n", progname
, arg
);
489 * Touch the control file to fix position in the queue.
492 if ((tfd
= open(tfname
, O_RDWR
)) >= 0) {
495 if (read(tfd
, &touch_c
, 1) == 1 &&
496 lseek(tfd
, (off_t
)0, 0) == 0 &&
497 write(tfd
, &touch_c
, 1) != 1) {
498 printf("%s: cannot touch %s\n", progname
,
505 if (link(tfname
, cfname
) < 0) {
506 printf("%s: cannot rename %s\n", progname
, cfname
);
512 if (qflag
) /* just q things up */
514 if (!startdaemon(pp
))
515 printf("jobs queued, but cannot start daemon.\n");
524 * Create the file n and copy from file descriptor f.
527 copy(const struct printer
*pp
, int f
, const char n
[])
533 card('T', title
? title
: n
);
534 for (i
= 0; i
< ncopies
; i
++)
535 card(format
, &dfname
[inchar
-2]);
536 card('U', &dfname
[inchar
-2]);
540 while ((i
= read(f
, buf
, BUFSIZ
)) > 0) {
541 if (write(fd
, buf
, i
) != i
) {
542 printf("%s: %s: temp file write error\n", progname
, n
);
549 if (pp
->max_blocks
> 0 && nr
> pp
->max_blocks
) {
550 printf("%s: %s: copy file is too large\n",
558 printf("%s: %s: empty input file\n", progname
,
565 * Try and link the file to dfname. Return a pointer to the full
566 * path name if successful.
569 linked(const char *file
)
572 static char buf
[MAXPATHLEN
];
576 if (getcwd(buf
, sizeof(buf
)) == NULL
)
578 while (file
[0] == '.') {
584 if (file
[2] == '/') {
585 if ((cp
= strrchr(buf
, '/')) != NULL
)
593 strncat(buf
, "/", sizeof(buf
) - strlen(buf
) - 1);
594 strncat(buf
, file
, sizeof(buf
) - strlen(buf
) - 1);
598 ret
= symlink(file
, dfname
);
600 return(ret
? NULL
: file
);
604 * Put a line into the control file.
607 card(int c
, const char *p2
)
614 while ((c
= *p2
++) != '\0' && len
< sizeof(buf
)) {
615 *p1
++ = (c
== '\n') ? ' ' : c
;
619 write(tfd
, buf
, len
);
623 * Create a new file in the spool directory.
629 int oldumask
= umask(0); /* should block signals */
632 f
= open(n
, O_WRONLY
| O_EXCL
| O_CREAT
, FILMOD
);
635 printf("%s: cannot create %s\n", progname
, n
);
638 if (fchown(f
, userid
, -1) < 0) {
639 printf("%s: cannot chown %s\n", progname
, n
);
640 cleanup(0); /* cleanup does exit */
643 if (++n
[inchar
] > 'z') {
644 if (++n
[inchar
-2] == 't') {
645 printf("too many files - break up the job\n");
649 } else if (n
[inchar
] == '[')
655 * Cleanup after interrupts and errors.
658 cleanup(int signo __unused
)
662 signal(SIGHUP
, SIG_IGN
);
663 signal(SIGINT
, SIG_IGN
);
664 signal(SIGQUIT
, SIG_IGN
);
665 signal(SIGTERM
, SIG_IGN
);
671 while (tfname
[i
]-- != 'A');
675 while (cfname
[i
]-- != 'A');
680 while (dfname
[i
]-- != 'A');
682 } while (dfname
[i
-2]-- != 'd');
687 * Test to see if this is a printable file.
688 * Return -1 if it is not, 0 if its printable, and 1 if
689 * we should remove it after printing.
692 test(const char *file
)
699 if (access(file
, 4) < 0) {
700 printf("%s: cannot access %s\n", progname
, file
);
703 if (stat(file
, &statb
) < 0) {
704 printf("%s: cannot stat %s\n", progname
, file
);
707 if ((statb
.st_mode
& S_IFMT
) == S_IFDIR
) {
708 printf("%s: %s is a directory\n", progname
, file
);
711 if (statb
.st_size
== 0) {
712 printf("%s: %s is an empty file\n", progname
, file
);
715 if ((fd
= open(file
, O_RDONLY
)) < 0) {
716 printf("%s: cannot open %s\n", progname
, file
);
720 * XXX Shall we add a similar test for ELF?
722 if (read(fd
, &execb
, sizeof(execb
)) == sizeof(execb
) &&
724 printf("%s: %s is an executable program", progname
, file
);
730 * aside: note that 'cp' is technically a 'const char *'
731 * (because it points into 'file'), even though strrchr
732 * returns a value of type 'char *'.
734 if ((cp
= strrchr(file
, '/')) == NULL
) {
735 if (checkwriteperm(file
,".") == 0)
739 fd
= checkwriteperm(file
,"/");
741 /* strlcpy will change the '/' to '\0' */
742 dlen
= cp
- file
+ 1;
743 dirpath
= malloc(dlen
);
744 strlcpy(dirpath
, file
, dlen
);
745 fd
= checkwriteperm(file
, dirpath
);
751 printf("%s: %s: is not removable by you\n", progname
, file
);
756 printf(" and is unprintable\n");
762 checkwriteperm(const char *file
, const char *directory
)
765 if (access(directory
, W_OK
) == 0) {
766 stat(directory
, &stats
);
767 if (stats
.st_mode
& S_ISVTX
) {
769 if(stats
.st_uid
== userid
) {
778 * itoa - integer to string conversion
783 static char b
[10] = "########";
794 * Perform lookup for printer name or abbreviation --
797 chkprinter(const char *ptrname
, struct printer
*pp
)
802 status
= getprintcap(ptrname
, pp
);
806 errx(1, "%s: %s", ptrname
, pcaperr(status
));
807 case PCAPERR_NOTFOUND
:
808 errx(1, "%s: unknown printer", ptrname
);
810 warnx("%s: unresolved tc= reference(s)", ptrname
);
815 * Tell the user what we wanna get.
820 fprintf(stderr
, "%s\n",
821 "usage: lpr [-Pprinter] [-#num] [-C class] [-J job] [-T title] [-U user]\n"
822 "\t[-Z daemon-options] [-i[numcols]] [-i[numcols]] [-1234 font]\n"
823 "\t[-L locale] [-wnum] [-cdfghlnmprstv] [name ...]");
829 * Make the temp files.
832 mktemps(const struct printer
*pp
)
838 snprintf(buf
, sizeof(buf
), "%s/.seq", pp
->spool_dir
);
840 if ((fd
= open(buf
, O_RDWR
|O_CREAT
, 0661)) < 0) {
841 printf("%s: cannot create %s\n", progname
, buf
);
844 if (flock(fd
, LOCK_EX
)) {
845 printf("%s: cannot lock %s\n", progname
, buf
);
850 if ((len
= read(fd
, buf
, sizeof(buf
))) > 0) {
851 for (cp
= buf
; len
--; ) {
852 if (*cp
< '0' || *cp
> '9')
854 n
= n
* 10 + (*cp
++ - '0');
857 len
= strlen(pp
->spool_dir
) + strlen(local_host
) + 8;
858 tfname
= lmktemp(pp
, "tf", n
, len
);
859 cfname
= lmktemp(pp
, "cf", n
, len
);
860 dfname
= lmktemp(pp
, "df", n
, len
);
861 inchar
= strlen(pp
->spool_dir
) + 3;
863 lseek(fd
, (off_t
)0, 0);
864 snprintf(buf
, sizeof(buf
), "%03d\n", n
);
865 write(fd
, buf
, strlen(buf
));
866 close(fd
); /* unlocks as well */
870 * Make a temp file name.
873 lmktemp(const struct printer
*pp
, const char *id
, int num
, int len
)
877 if ((s
= malloc(len
)) == NULL
)
878 errx(1, "out of memory");
879 snprintf(s
, len
, "%s/%sA%03d%s", pp
->spool_dir
, id
, num
, local_host
);