xref: /openbsd/usr.sbin/lpr/lprm/lprm.c (revision 76d0caae)
1 /*	$OpenBSD: lprm.c,v 1.21 2015/01/16 06:40:18 deraadt Exp $	*/
2 /*	$$NetBSD: lprm.c,v 1.9 1999/08/16 03:12:32 simonb Exp $	*/
3 
4 /*
5  * Copyright (c) 1983, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 /*
35  * lprm - remove the current user's spool entry
36  *
37  * lprm [-] [[job #] [user] ...]
38  *
39  * Using information in the lock file, lprm will kill the
40  * currently active daemon (if necessary), remove the associated files,
41  * and startup a new daemon.  Privileged users may remove anyone's spool
42  * entries, otherwise one can only remove their own.
43  */
44 
45 
46 #include <ctype.h>
47 #include <signal.h>
48 #include <dirent.h>
49 #include <err.h>
50 #include <errno.h>
51 #include <pwd.h>
52 #include <stdlib.h>
53 #include <stdio.h>
54 #include <string.h>
55 #include <syslog.h>
56 #include <unistd.h>
57 #include <limits.h>
58 
59 #include "lp.h"
60 #include "lp.local.h"
61 
62 /*
63  * Stuff for handling job specifications
64  */
65 char	*person;		/* name of person doing lprm */
66 int	 requ[MAXREQUESTS];	/* job number of spool entries */
67 int	 requests;		/* # of spool requests */
68 char	*user[MAXUSERS];	/* users to process */
69 int	 users;			/* # of users in user array */
70 volatile sig_atomic_t gotintr;	/* set when we receive SIGINT */
71 static char luser[LOGIN_NAME_MAX];	/* buffer for person */
72 
73 static __dead void usage(void);
74 
75 int
76 main(int argc, char **argv)
77 {
78 	struct passwd *pw;
79 	char *cp;
80 	long l;
81 	int ch;
82 
83 	/*
84 	 * Simulate setuid daemon w/ PRIV_END called.
85 	 * We don't want lpr to actually be setuid daemon since that
86 	 * requires that the lpr binary be owned by user daemon, which
87 	 * is potentially unsafe.
88 	 */
89 	if ((pw = getpwuid(DEFUID)) == NULL)
90 		errx(1, "daemon uid (%u) not in password file", DEFUID);
91 	effective_uid = pw->pw_uid;
92 	real_uid = getuid();
93 	effective_gid = pw->pw_gid;
94 	real_gid = getgid();
95 	setresgid(real_gid, real_gid, effective_gid);
96 	setresuid(real_uid, real_uid, effective_uid);
97 
98 	gethostname(host, sizeof(host));
99 	openlog("lprm", 0, LOG_LPR);
100 	if ((pw = getpwuid(real_uid)) == NULL)
101 		fatal("Who are you?");
102 	if (strlen(pw->pw_name) >= sizeof(luser))
103 		fatal("Your name is too long");
104 	strlcpy(luser, pw->pw_name, sizeof(luser));
105 	person = luser;
106 	while ((ch = getopt(argc, argv, "P:w:-")) != -1) {
107 		switch (ch) {
108 		case '-':
109 			users = -1;
110 			break;
111 		case 'P':
112 			printer = optarg;
113 			break;
114 		case 'w':
115 			l = strtol(optarg, &cp, 10);
116 			if (*cp != '\0' || l < 0 || l >= INT_MAX)
117 				errx(1, "wait time must be positive integer: %s",
118 				    optarg);
119 			wait_time = (u_int)l;
120 			if (wait_time < 30)
121 				warnx("warning: wait time less than 30 seconds");
122 			break;
123 		default:
124 			usage();
125 		}
126 	}
127 	argc -= optind;
128 	argv += optind;
129 
130 	if (printer == NULL && (printer = getenv("PRINTER")) == NULL)
131 		printer = DEFLP;
132 	if (users < 0 && argc != 0)
133 		usage();
134 	while (argc > 0) {
135 		if (isdigit((unsigned char)*argv[0])) {
136 			if (requests >= MAXREQUESTS)
137 				fatal("Too many requests");
138 			requ[requests++] = atoi(argv[0]);
139 		} else {
140 			if (users >= MAXUSERS)
141 				fatal("Too many users");
142 			user[users++] = argv[0];
143 		}
144 		argc--;
145 		argv++;
146 	}
147 
148 	rmjob();
149 	exit(0);
150 }
151 
152 static __dead void
153 usage(void)
154 {
155 	extern char *__progname;
156 
157 	fprintf(stderr, "usage: %s [-] [-Pprinter] [[job# ...] [user ...]]\n",
158 	    __progname);
159 	exit(2);
160 }
161