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
main(int argc,char ** argv)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
usage(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