2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
33 * @(#)rmjob.c 8.2 (Berkeley) 4/28/95
34 * $FreeBSD: src/usr.sbin/lpr/common_source/rmjob.c,v 1.12.2.5 2001/06/25 01:00:56 gad Exp $
35 * $DragonFly: src/usr.sbin/lpr/common_source/rmjob.c,v 1.4 2004/12/18 22:48:03 swildner Exp $
38 #include <sys/param.h>
48 #define psignal foil_gcc_psignal
49 #define sys_siglist foil_gcc_siglist
56 #include "pathnames.h"
59 * rmjob - remove the specified jobs from the queue.
63 * Stuff for handling lprm specifications
65 static char root
[] = "root";
66 static int all
= 0; /* eliminate all files (root only) */
67 static int cur_daemon
; /* daemon's pid */
68 static char current
[7+MAXHOSTNAMELEN
]; /* active control file name */
70 extern uid_t uid
, euid
; /* real and effective user id's */
72 static void alarmhandler(int _signo
);
73 static void do_unlink(char *_file
);
76 rmjob(const char *printer
)
80 struct dirent
**files
;
82 struct printer myprinter
, *pp
= &myprinter
;
85 if ((i
= getprintcap(printer
, pp
)) < 0)
86 fatal(pp
, "getprintcap: %s", pcaperr(i
));
87 if ((cp
= checkremote(pp
))) {
88 printf("Warning: %s\n", cp
);
93 * If the format was `lprm -' and the user isn't the super-user,
94 * then fake things to look like he said `lprm user'.
98 all
= 1; /* all files in local queue */
104 if (!strcmp(person
, "-all")) {
105 if (from_host
== local_host
)
106 fatal(pp
, "The login name \"-all\" is reserved");
107 all
= 1; /* all those from 'from_host' */
112 if (chdir(pp
->spool_dir
) < 0)
113 fatal(pp
, "cannot chdir to spool directory");
114 if ((nitems
= scandir(".", &files
, iscf
, NULL
)) < 0)
115 fatal(pp
, "cannot access spool directory");
120 * Check for an active printer daemon (in which case we
121 * kill it if it is reading our file) then remove stuff
122 * (after which we have to restart the daemon).
124 if (lockchk(pp
, pp
->lock_file
) && chk(current
)) {
126 assasinated
= kill(cur_daemon
, SIGINT
) == 0;
129 fatal(pp
, "cannot kill printer daemon");
134 for (i
= 0; i
< nitems
; i
++)
135 process(pp
, files
[i
]->d_name
);
139 * Restart the printer daemon if it was killed
141 if (assasinated
&& !startdaemon(pp
))
142 fatal(pp
, "cannot restart printer daemon\n");
147 * Process a lock file: collect the pid of the active
148 * daemon and the file name of the active spool entry.
149 * Return boolean indicating existence of a lock file.
152 lockchk(struct printer
*pp
, char *slockf
)
158 if ((fp
= fopen(slockf
, "r")) == NULL
) {
160 fatal(pp
, "%s: %s", slockf
, strerror(errno
));
167 return(0); /* no daemon present */
169 cur_daemon
= atoi(line
);
170 if (kill(cur_daemon
, 0) < 0 && errno
!= EPERM
) {
172 return(0); /* no daemon present */
174 for (i
= 1; (n
= fread(current
, sizeof(char), sizeof(current
), fp
)) <= 0; i
++) {
187 * Process a control file.
190 process(const struct printer
*pp
, char *file
)
197 if ((cfp
= fopen(file
, "r")) == NULL
)
198 fatal(pp
, "cannot open %s", file
);
200 while (getline(cfp
)) {
202 case 'U': /* unlink associated files */
203 if (strchr(line
+1, '/') || strncmp(line
+1, "df", 2))
213 do_unlink(char *file
)
217 if (from_host
!= local_host
)
218 printf("%s: ", local_host
);
222 printf(ret
? "cannot dequeue %s\n" : "%s dequeued\n", file
);
226 * Do the dirty work in checking
236 * Check for valid cf file name (mostly checking current).
238 if (strlen(file
) < 7 || file
[0] != 'c' || file
[1] != 'f')
241 if (all
&& (from_host
== local_host
|| !strcmp(from_host
, file
+6)))
245 * get the owner's name from the control file.
248 if ((cfp
= fopen(file
, "r")) == NULL
)
251 while (getline(cfp
)) {
259 if (users
== 0 && requests
== 0)
260 return(!strcmp(file
, current
) && isowner(line
+1, file
));
262 * Check the request list
264 for (n
= 0, cp
= file
+3; isdigit(*cp
); )
265 n
= n
* 10 + (*cp
++ - '0');
266 for (r
= requ
; r
< &requ
[requests
]; r
++)
267 if (*r
== n
&& isowner(line
+1, file
))
270 * Check to see if it's in the user list
272 for (u
= user
; u
< &user
[users
]; u
++)
273 if (!strcmp(*u
, line
+1) && isowner(line
+1, file
))
279 * If root is removing a file on the local machine, allow it.
280 * If root is removing a file from a remote machine, only allow
281 * files sent from the remote machine to be removed.
282 * Normal users can only remove the file from where it was sent.
285 isowner(char *owner
, char *file
)
287 if (!strcmp(person
, root
) && (from_host
== local_host
||
288 !strcmp(from_host
, file
+6)))
290 if (!strcmp(person
, owner
) && !strcmp(from_host
, file
+6))
292 if (from_host
!= local_host
)
293 printf("%s: ", local_host
);
294 printf("%s: Permission denied\n", file
);
299 * Check to see if we are sending files to a remote machine. If we are,
300 * then try removing files on the remote machine.
303 rmremote(const struct printer
*pp
)
305 int i
, elem
, firstreq
, niov
, rem
, totlen
;
307 void (*savealrm
)(int);
311 return; /* not sending to a remote machine */
314 * Flush stdout so the user can see what has been deleted
315 * while we wait (possibly) for the connection.
321 * 4 == "\5" + remote_queue + " " + person
322 * 2 * users == " " + user[i] for each user
323 * requests == asprintf results for each request
325 * Although laborious, doing it this way makes it possible for
326 * us to process requests of indeterminate length without
327 * applying an arbitrary limit. Arbitrary Limits Are Bad (tm).
330 niov
= 4 + 2 * users
+ requests
+ 1;
332 niov
= 4 + requests
+ 1;
333 iov
= malloc(niov
* sizeof *iov
);
335 fatal(pp
, "out of memory in rmremote()");
336 iov
[0].iov_base
= "\5";
337 iov
[1].iov_base
= pp
->remote_queue
;
338 iov
[2].iov_base
= " ";
339 iov
[3].iov_base
= all
? "-all" : person
;
341 for (i
= 0; i
< users
; i
++) {
342 iov
[elem
].iov_base
= " ";
343 iov
[elem
+ 1].iov_base
= user
[i
];
347 for (i
= 0; i
< requests
; i
++) {
348 asprintf(&iov
[elem
].iov_base
, " %d", requ
[i
]);
349 if (iov
[elem
].iov_base
== 0)
350 fatal(pp
, "out of memory in rmremote()");
353 iov
[elem
++].iov_base
= "\n";
354 for (totlen
= i
= 0; i
< niov
; i
++)
355 totlen
+= (iov
[i
].iov_len
= strlen(iov
[i
].iov_base
));
357 savealrm
= signal(SIGALRM
, alarmhandler
);
358 alarm(pp
->conn_timeout
);
359 rem
= getport(pp
, pp
->remote_host
, 0);
360 signal(SIGALRM
, savealrm
);
362 if (from_host
!= local_host
)
363 printf("%s: ", local_host
);
364 printf("connection to %s is down\n", pp
->remote_host
);
366 if (writev(rem
, iov
, niov
) != totlen
)
367 fatal(pp
, "Lost connection");
368 while ((i
= read(rem
, buf
, sizeof(buf
))) > 0)
369 fwrite(buf
, 1, i
, stdout
);
372 for (i
= 0; i
< requests
; i
++)
373 free(iov
[firstreq
+ i
].iov_base
);
378 * Return 1 if the filename begins with 'cf'
381 iscf(struct dirent
*d
)
383 return(d
->d_name
[0] == 'c' && d
->d_name
[1] == 'f');
387 alarmhandler(int signo __unused
)
389 /* the signal is ignored */
390 /* (the '__unused' is just to avoid a compile-time warning) */