rmjob.c revision 1.1 1 /*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 #ifndef lint
35 static char sccsid[] = "@(#)rmjob.c 5.7 (Berkeley) 6/1/90";
36 #endif /* not lint */
37
38 /*
39 * rmjob - remove the specified jobs from the queue.
40 */
41
42 #include "lp.h"
43 #include "pathnames.h"
44
45 /*
46 * Stuff for handling lprm specifications
47 */
48 extern char *user[]; /* users to process */
49 extern int users; /* # of users in user array */
50 extern int requ[]; /* job number of spool entries */
51 extern int requests; /* # of spool requests */
52 extern char *person; /* name of person doing lprm */
53
54 char root[] = "root";
55 int all = 0; /* eliminate all files (root only) */
56 int cur_daemon; /* daemon's pid */
57 char current[40]; /* active control file name */
58
59 int iscf();
60
61 rmjob()
62 {
63 register int i, nitems;
64 int assasinated = 0;
65 struct direct **files;
66 char *cp;
67
68 if ((i = pgetent(line, printer)) < 0)
69 fatal("cannot open printer description file");
70 else if (i == 0)
71 fatal("unknown printer");
72 if ((SD = pgetstr("sd", &bp)) == NULL)
73 SD = _PATH_DEFSPOOL;
74 if ((LO = pgetstr("lo", &bp)) == NULL)
75 LO = DEFLOCK;
76 if ((LP = pgetstr("lp", &bp)) == NULL)
77 LP = _PATH_DEFDEVLP;
78 if ((RP = pgetstr("rp", &bp)) == NULL)
79 RP = DEFLP;
80 RM = pgetstr("rm", &bp);
81 if (cp = checkremote())
82 printf("Warning: %s\n", cp);
83
84 /*
85 * If the format was `lprm -' and the user isn't the super-user,
86 * then fake things to look like he said `lprm user'.
87 */
88 if (users < 0) {
89 if (getuid() == 0)
90 all = 1; /* all files in local queue */
91 else {
92 user[0] = person;
93 users = 1;
94 }
95 }
96 if (!strcmp(person, "-all")) {
97 if (from == host)
98 fatal("The login name \"-all\" is reserved");
99 all = 1; /* all those from 'from' */
100 person = root;
101 }
102
103 if (chdir(SD) < 0)
104 fatal("cannot chdir to spool directory");
105 if ((nitems = scandir(".", &files, iscf, NULL)) < 0)
106 fatal("cannot access spool directory");
107
108 if (nitems) {
109 /*
110 * Check for an active printer daemon (in which case we
111 * kill it if it is reading our file) then remove stuff
112 * (after which we have to restart the daemon).
113 */
114 if (lockchk(LO) && chk(current)) {
115 assasinated = kill(cur_daemon, SIGINT) == 0;
116 if (!assasinated)
117 fatal("cannot kill printer daemon");
118 }
119 /*
120 * process the files
121 */
122 for (i = 0; i < nitems; i++)
123 process(files[i]->d_name);
124 }
125 rmremote();
126 /*
127 * Restart the printer daemon if it was killed
128 */
129 if (assasinated && !startdaemon(printer))
130 fatal("cannot restart printer daemon\n");
131 exit(0);
132 }
133
134 /*
135 * Process a lock file: collect the pid of the active
136 * daemon and the file name of the active spool entry.
137 * Return boolean indicating existence of a lock file.
138 */
139 lockchk(s)
140 char *s;
141 {
142 register FILE *fp;
143 register int i, n;
144
145 if ((fp = fopen(s, "r")) == NULL)
146 if (errno == EACCES)
147 fatal("can't access lock file");
148 else
149 return(0);
150 if (!getline(fp)) {
151 (void) fclose(fp);
152 return(0); /* no daemon present */
153 }
154 cur_daemon = atoi(line);
155 if (kill(cur_daemon, 0) < 0) {
156 (void) fclose(fp);
157 return(0); /* no daemon present */
158 }
159 for (i = 1; (n = fread(current, sizeof(char), sizeof(current), fp)) <= 0; i++) {
160 if (i > 5) {
161 n = 1;
162 break;
163 }
164 sleep(i);
165 }
166 current[n-1] = '\0';
167 (void) fclose(fp);
168 return(1);
169 }
170
171 /*
172 * Process a control file.
173 */
174 process(file)
175 char *file;
176 {
177 FILE *cfp;
178
179 if (!chk(file))
180 return;
181 if ((cfp = fopen(file, "r")) == NULL)
182 fatal("cannot open %s", file);
183 while (getline(cfp)) {
184 switch (line[0]) {
185 case 'U': /* unlink associated files */
186 if (from != host)
187 printf("%s: ", host);
188 printf(unlink(line+1) ? "cannot dequeue %s\n" :
189 "%s dequeued\n", line+1);
190 }
191 }
192 (void) fclose(cfp);
193 if (from != host)
194 printf("%s: ", host);
195 printf(unlink(file) ? "cannot dequeue %s\n" : "%s dequeued\n", file);
196 }
197
198 /*
199 * Do the dirty work in checking
200 */
201 chk(file)
202 char *file;
203 {
204 register int *r, n;
205 register char **u, *cp;
206 FILE *cfp;
207
208 /*
209 * Check for valid cf file name (mostly checking current).
210 */
211 if (strlen(file) < 7 || file[0] != 'c' || file[1] != 'f')
212 return(0);
213
214 if (all && (from == host || !strcmp(from, file+6)))
215 return(1);
216
217 /*
218 * get the owner's name from the control file.
219 */
220 if ((cfp = fopen(file, "r")) == NULL)
221 return(0);
222 while (getline(cfp)) {
223 if (line[0] == 'P')
224 break;
225 }
226 (void) fclose(cfp);
227 if (line[0] != 'P')
228 return(0);
229
230 if (users == 0 && requests == 0)
231 return(!strcmp(file, current) && isowner(line+1, file));
232 /*
233 * Check the request list
234 */
235 for (n = 0, cp = file+3; isdigit(*cp); )
236 n = n * 10 + (*cp++ - '0');
237 for (r = requ; r < &requ[requests]; r++)
238 if (*r == n && isowner(line+1, file))
239 return(1);
240 /*
241 * Check to see if it's in the user list
242 */
243 for (u = user; u < &user[users]; u++)
244 if (!strcmp(*u, line+1) && isowner(line+1, file))
245 return(1);
246 return(0);
247 }
248
249 /*
250 * If root is removing a file on the local machine, allow it.
251 * If root is removing a file from a remote machine, only allow
252 * files sent from the remote machine to be removed.
253 * Normal users can only remove the file from where it was sent.
254 */
255 isowner(owner, file)
256 char *owner, *file;
257 {
258 if (!strcmp(person, root) && (from == host || !strcmp(from, file+6)))
259 return(1);
260 if (!strcmp(person, owner) && !strcmp(from, file+6))
261 return(1);
262 if (from != host)
263 printf("%s: ", host);
264 printf("%s: Permission denied\n", file);
265 return(0);
266 }
267
268 /*
269 * Check to see if we are sending files to a remote machine. If we are,
270 * then try removing files on the remote machine.
271 */
272 rmremote()
273 {
274 register char *cp;
275 register int i, rem;
276 char buf[BUFSIZ];
277
278 if (!sendtorem)
279 return; /* not sending to a remote machine */
280
281 /*
282 * Flush stdout so the user can see what has been deleted
283 * while we wait (possibly) for the connection.
284 */
285 fflush(stdout);
286
287 sprintf(buf, "\5%s %s", RP, all ? "-all" : person);
288 cp = buf;
289 for (i = 0; i < users; i++) {
290 cp += strlen(cp);
291 *cp++ = ' ';
292 strcpy(cp, user[i]);
293 }
294 for (i = 0; i < requests; i++) {
295 cp += strlen(cp);
296 (void) sprintf(cp, " %d", requ[i]);
297 }
298 strcat(cp, "\n");
299 rem = getport(RM);
300 if (rem < 0) {
301 if (from != host)
302 printf("%s: ", host);
303 printf("connection to %s is down\n", RM);
304 } else {
305 i = strlen(buf);
306 if (write(rem, buf, i) != i)
307 fatal("Lost connection");
308 while ((i = read(rem, buf, sizeof(buf))) > 0)
309 (void) fwrite(buf, 1, i, stdout);
310 (void) close(rem);
311 }
312 }
313
314 /*
315 * Return 1 if the filename begins with 'cf'
316 */
317 iscf(d)
318 struct direct *d;
319 {
320 return(d->d_name[0] == 'c' && d->d_name[1] == 'f');
321 }
322