rmjob.c revision 30407
11553Srgrimes/* 21553Srgrimes * Copyright (c) 1983, 1993 31553Srgrimes * The Regents of the University of California. All rights reserved. 41553Srgrimes * 51553Srgrimes * Redistribution and use in source and binary forms, with or without 61553Srgrimes * modification, are permitted provided that the following conditions 71553Srgrimes * are met: 81553Srgrimes * 1. Redistributions of source code must retain the above copyright 91553Srgrimes * notice, this list of conditions and the following disclaimer. 101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111553Srgrimes * notice, this list of conditions and the following disclaimer in the 121553Srgrimes * documentation and/or other materials provided with the distribution. 131553Srgrimes * 3. All advertising materials mentioning features or use of this software 141553Srgrimes * must display the following acknowledgement: 151553Srgrimes * This product includes software developed by the University of 161553Srgrimes * California, Berkeley and its contributors. 171553Srgrimes * 4. Neither the name of the University nor the names of its contributors 181553Srgrimes * may be used to endorse or promote products derived from this software 191553Srgrimes * without specific prior written permission. 201553Srgrimes * 211553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311553Srgrimes * SUCH DAMAGE. 321553Srgrimes */ 331553Srgrimes 341553Srgrimes#ifndef lint 3529780Scharnier#if 0 3615648Sjoergstatic char sccsid[] = "@(#)rmjob.c 8.2 (Berkeley) 4/28/95"; 3729780Scharnier#endif 3829780Scharnierstatic const char rcsid[] = 3930407Sjoerg "$Id: rmjob.c,v 1.9 1997/09/24 06:47:31 charnier Exp $"; 401553Srgrimes#endif /* not lint */ 411553Srgrimes 421553Srgrimes#include <sys/param.h> 431553Srgrimes 441553Srgrimes#include <signal.h> 451553Srgrimes#include <errno.h> 461553Srgrimes#include <dirent.h> 471553Srgrimes#include <unistd.h> 481553Srgrimes#include <stdlib.h> 491553Srgrimes#include <stdio.h> 501553Srgrimes#include <string.h> 511553Srgrimes#include <ctype.h> 521553Srgrimes#include "lp.h" 531553Srgrimes#include "lp.local.h" 541553Srgrimes#include "pathnames.h" 551553Srgrimes 561553Srgrimes/* 571553Srgrimes * rmjob - remove the specified jobs from the queue. 581553Srgrimes */ 591553Srgrimes 601553Srgrimes/* 611553Srgrimes * Stuff for handling lprm specifications 621553Srgrimes */ 631553Srgrimesstatic char root[] = "root"; 641553Srgrimesstatic int all = 0; /* eliminate all files (root only) */ 651553Srgrimesstatic int cur_daemon; /* daemon's pid */ 661553Srgrimesstatic char current[40]; /* active control file name */ 671553Srgrimes 6827618Simpextern uid_t uid, euid; /* real and effective user id's */ 6927618Simp 7030407Sjoergstatic void alarmhandler __P((int)); 7127618Simpstatic void do_unlink __P((char *)); 7227618Simp 731553Srgrimesvoid 741553Srgrimesrmjob() 751553Srgrimes{ 761553Srgrimes register int i, nitems; 771553Srgrimes int assasinated = 0; 781553Srgrimes struct dirent **files; 791553Srgrimes char *cp; 801553Srgrimes 811553Srgrimes if ((i = cgetent(&bp, printcapdb, printer)) == -2) 821553Srgrimes fatal("can't open printer description file"); 831553Srgrimes else if (i == -1) 841553Srgrimes fatal("unknown printer"); 851553Srgrimes else if (i == -3) 861553Srgrimes fatal("potential reference loop detected in printcap file"); 871553Srgrimes if (cgetstr(bp, "lp", &LP) < 0) 881553Srgrimes LP = _PATH_DEFDEVLP; 891553Srgrimes if (cgetstr(bp, "rp", &RP) < 0) 901553Srgrimes RP = DEFLP; 911553Srgrimes if (cgetstr(bp, "sd", &SD) < 0) 921553Srgrimes SD = _PATH_DEFSPOOL; 931553Srgrimes if (cgetstr(bp,"lo", &LO) < 0) 941553Srgrimes LO = DEFLOCK; 9530407Sjoerg if (cgetnum(bp, "ct", &CT) < 0) 9630407Sjoerg CT = DEFTIMEOUT; 971553Srgrimes cgetstr(bp, "rm", &RM); 9827748Simp if ((cp = checkremote())) 991553Srgrimes printf("Warning: %s\n", cp); 1001553Srgrimes 1011553Srgrimes /* 1021553Srgrimes * If the format was `lprm -' and the user isn't the super-user, 1031553Srgrimes * then fake things to look like he said `lprm user'. 1041553Srgrimes */ 1051553Srgrimes if (users < 0) { 1061553Srgrimes if (getuid() == 0) 1071553Srgrimes all = 1; /* all files in local queue */ 1081553Srgrimes else { 1091553Srgrimes user[0] = person; 1101553Srgrimes users = 1; 1111553Srgrimes } 1121553Srgrimes } 1131553Srgrimes if (!strcmp(person, "-all")) { 1141553Srgrimes if (from == host) 1151553Srgrimes fatal("The login name \"-all\" is reserved"); 1161553Srgrimes all = 1; /* all those from 'from' */ 1171553Srgrimes person = root; 1181553Srgrimes } 1191553Srgrimes 12027618Simp seteuid(euid); 1211553Srgrimes if (chdir(SD) < 0) 1221553Srgrimes fatal("cannot chdir to spool directory"); 1231553Srgrimes if ((nitems = scandir(".", &files, iscf, NULL)) < 0) 1241553Srgrimes fatal("cannot access spool directory"); 12527618Simp seteuid(uid); 1261553Srgrimes 1271553Srgrimes if (nitems) { 1281553Srgrimes /* 1291553Srgrimes * Check for an active printer daemon (in which case we 1301553Srgrimes * kill it if it is reading our file) then remove stuff 1311553Srgrimes * (after which we have to restart the daemon). 1321553Srgrimes */ 1331553Srgrimes if (lockchk(LO) && chk(current)) { 13427618Simp seteuid(euid); 1351553Srgrimes assasinated = kill(cur_daemon, SIGINT) == 0; 13627618Simp seteuid(uid); 1371553Srgrimes if (!assasinated) 1381553Srgrimes fatal("cannot kill printer daemon"); 1391553Srgrimes } 1401553Srgrimes /* 1411553Srgrimes * process the files 1421553Srgrimes */ 1431553Srgrimes for (i = 0; i < nitems; i++) 1441553Srgrimes process(files[i]->d_name); 1451553Srgrimes } 1461553Srgrimes rmremote(); 1471553Srgrimes /* 1481553Srgrimes * Restart the printer daemon if it was killed 1491553Srgrimes */ 1501553Srgrimes if (assasinated && !startdaemon(printer)) 1511553Srgrimes fatal("cannot restart printer daemon\n"); 1521553Srgrimes exit(0); 1531553Srgrimes} 1541553Srgrimes 1551553Srgrimes/* 1561553Srgrimes * Process a lock file: collect the pid of the active 1571553Srgrimes * daemon and the file name of the active spool entry. 1581553Srgrimes * Return boolean indicating existence of a lock file. 1591553Srgrimes */ 1601553Srgrimesint 1611553Srgrimeslockchk(s) 1621553Srgrimes char *s; 1631553Srgrimes{ 1641553Srgrimes register FILE *fp; 1651553Srgrimes register int i, n; 1661553Srgrimes 16727618Simp seteuid(euid); 16827618Simp if ((fp = fopen(s, "r")) == NULL) { 1691553Srgrimes if (errno == EACCES) 1701553Srgrimes fatal("can't access lock file"); 1711553Srgrimes else 1721553Srgrimes return(0); 17327618Simp } 17427618Simp seteuid(uid); 1751553Srgrimes if (!getline(fp)) { 1761553Srgrimes (void) fclose(fp); 1771553Srgrimes return(0); /* no daemon present */ 1781553Srgrimes } 1791553Srgrimes cur_daemon = atoi(line); 18027618Simp if (kill(cur_daemon, 0) < 0 && errno != EPERM) { 1811553Srgrimes (void) fclose(fp); 1821553Srgrimes return(0); /* no daemon present */ 1831553Srgrimes } 1841553Srgrimes for (i = 1; (n = fread(current, sizeof(char), sizeof(current), fp)) <= 0; i++) { 1851553Srgrimes if (i > 5) { 1861553Srgrimes n = 1; 1871553Srgrimes break; 1881553Srgrimes } 1891553Srgrimes sleep(i); 1901553Srgrimes } 1911553Srgrimes current[n-1] = '\0'; 1921553Srgrimes (void) fclose(fp); 1931553Srgrimes return(1); 1941553Srgrimes} 1951553Srgrimes 1961553Srgrimes/* 1971553Srgrimes * Process a control file. 1981553Srgrimes */ 1991553Srgrimesvoid 2001553Srgrimesprocess(file) 2011553Srgrimes char *file; 2021553Srgrimes{ 2031553Srgrimes FILE *cfp; 2041553Srgrimes 2051553Srgrimes if (!chk(file)) 2061553Srgrimes return; 20727618Simp seteuid(euid); 2081553Srgrimes if ((cfp = fopen(file, "r")) == NULL) 2091553Srgrimes fatal("cannot open %s", file); 21027618Simp seteuid(uid); 2111553Srgrimes while (getline(cfp)) { 2121553Srgrimes switch (line[0]) { 2131553Srgrimes case 'U': /* unlink associated files */ 21427509Simp if (strchr(line+1, '/') || strncmp(line+1, "df", 2)) 21527509Simp break; 2161553Srgrimes if (from != host) 2171553Srgrimes printf("%s: ", host); 21827618Simp do_unlink(line+1); 2191553Srgrimes } 2201553Srgrimes } 2211553Srgrimes (void) fclose(cfp); 22227618Simp do_unlink(file); 22327618Simp} 22427618Simp 22527618Simpstatic void 22627618Simpdo_unlink(file) 22727618Simp char *file; 22827618Simp{ 22927618Simp int ret; 23027618Simp 2311553Srgrimes if (from != host) 2321553Srgrimes printf("%s: ", host); 23327618Simp seteuid(euid); 23427618Simp ret = unlink(file); 23527618Simp seteuid(uid); 23627618Simp printf(ret ? "cannot dequeue %s\n" : "%s dequeued\n", file); 2371553Srgrimes} 2381553Srgrimes 2391553Srgrimes/* 2401553Srgrimes * Do the dirty work in checking 2411553Srgrimes */ 2421553Srgrimesint 2431553Srgrimeschk(file) 2441553Srgrimes char *file; 2451553Srgrimes{ 2461553Srgrimes register int *r, n; 2471553Srgrimes register char **u, *cp; 2481553Srgrimes FILE *cfp; 2491553Srgrimes 2501553Srgrimes /* 2511553Srgrimes * Check for valid cf file name (mostly checking current). 2521553Srgrimes */ 2531553Srgrimes if (strlen(file) < 7 || file[0] != 'c' || file[1] != 'f') 2541553Srgrimes return(0); 2551553Srgrimes 2561553Srgrimes if (all && (from == host || !strcmp(from, file+6))) 2571553Srgrimes return(1); 2581553Srgrimes 2591553Srgrimes /* 2601553Srgrimes * get the owner's name from the control file. 2611553Srgrimes */ 26227618Simp seteuid(euid); 2631553Srgrimes if ((cfp = fopen(file, "r")) == NULL) 2641553Srgrimes return(0); 26527618Simp seteuid(uid); 2661553Srgrimes while (getline(cfp)) { 2671553Srgrimes if (line[0] == 'P') 2681553Srgrimes break; 2691553Srgrimes } 2701553Srgrimes (void) fclose(cfp); 2711553Srgrimes if (line[0] != 'P') 2721553Srgrimes return(0); 2731553Srgrimes 2741553Srgrimes if (users == 0 && requests == 0) 2751553Srgrimes return(!strcmp(file, current) && isowner(line+1, file)); 2761553Srgrimes /* 2771553Srgrimes * Check the request list 2781553Srgrimes */ 2791553Srgrimes for (n = 0, cp = file+3; isdigit(*cp); ) 2801553Srgrimes n = n * 10 + (*cp++ - '0'); 2811553Srgrimes for (r = requ; r < &requ[requests]; r++) 2821553Srgrimes if (*r == n && isowner(line+1, file)) 2831553Srgrimes return(1); 2841553Srgrimes /* 2851553Srgrimes * Check to see if it's in the user list 2861553Srgrimes */ 2871553Srgrimes for (u = user; u < &user[users]; u++) 2881553Srgrimes if (!strcmp(*u, line+1) && isowner(line+1, file)) 2891553Srgrimes return(1); 2901553Srgrimes return(0); 2911553Srgrimes} 2921553Srgrimes 2931553Srgrimes/* 2941553Srgrimes * If root is removing a file on the local machine, allow it. 2951553Srgrimes * If root is removing a file from a remote machine, only allow 2961553Srgrimes * files sent from the remote machine to be removed. 2971553Srgrimes * Normal users can only remove the file from where it was sent. 2981553Srgrimes */ 2991553Srgrimesint 3001553Srgrimesisowner(owner, file) 3011553Srgrimes char *owner, *file; 3021553Srgrimes{ 3031553Srgrimes if (!strcmp(person, root) && (from == host || !strcmp(from, file+6))) 3041553Srgrimes return(1); 3051553Srgrimes if (!strcmp(person, owner) && !strcmp(from, file+6)) 3061553Srgrimes return(1); 3071553Srgrimes if (from != host) 3081553Srgrimes printf("%s: ", host); 3091553Srgrimes printf("%s: Permission denied\n", file); 3101553Srgrimes return(0); 3111553Srgrimes} 3121553Srgrimes 3131553Srgrimes/* 3141553Srgrimes * Check to see if we are sending files to a remote machine. If we are, 3151553Srgrimes * then try removing files on the remote machine. 3161553Srgrimes */ 3171553Srgrimesvoid 3181553Srgrimesrmremote() 3191553Srgrimes{ 3201553Srgrimes register char *cp; 3211553Srgrimes register int i, rem; 3221553Srgrimes char buf[BUFSIZ]; 32330407Sjoerg void (*savealrm)(int); 3241553Srgrimes 32515648Sjoerg if (!remote) 3261553Srgrimes return; /* not sending to a remote machine */ 3271553Srgrimes 3281553Srgrimes /* 3291553Srgrimes * Flush stdout so the user can see what has been deleted 3301553Srgrimes * while we wait (possibly) for the connection. 3311553Srgrimes */ 3321553Srgrimes fflush(stdout); 3331553Srgrimes 3341553Srgrimes (void)snprintf(buf, sizeof(buf), "\5%s %s", RP, all ? "-all" : person); 3351553Srgrimes cp = buf; 33627748Simp for (i = 0; i < users && cp-buf+1+strlen(user[i]) < sizeof(buf); i++) { 3371553Srgrimes cp += strlen(cp); 3381553Srgrimes *cp++ = ' '; 3391553Srgrimes strcpy(cp, user[i]); 3401553Srgrimes } 34127757Simp for (i = 0; i < requests && cp-buf+10 < sizeof(buf) - 1; i++) { 3421553Srgrimes cp += strlen(cp); 3431553Srgrimes (void) sprintf(cp, " %d", requ[i]); 3441553Srgrimes } 3451553Srgrimes strcat(cp, "\n"); 34630407Sjoerg savealrm = signal(SIGALRM, alarmhandler); 34730407Sjoerg alarm(CT); 34815648Sjoerg rem = getport(RM, 0); 34930407Sjoerg (void)signal(SIGALRM, savealrm); 3501553Srgrimes if (rem < 0) { 3511553Srgrimes if (from != host) 3521553Srgrimes printf("%s: ", host); 3531553Srgrimes printf("connection to %s is down\n", RM); 3541553Srgrimes } else { 3551553Srgrimes i = strlen(buf); 3561553Srgrimes if (write(rem, buf, i) != i) 3571553Srgrimes fatal("Lost connection"); 3581553Srgrimes while ((i = read(rem, buf, sizeof(buf))) > 0) 3591553Srgrimes (void) fwrite(buf, 1, i, stdout); 3601553Srgrimes (void) close(rem); 3611553Srgrimes } 3621553Srgrimes} 3631553Srgrimes 3641553Srgrimes/* 3651553Srgrimes * Return 1 if the filename begins with 'cf' 3661553Srgrimes */ 3671553Srgrimesint 3681553Srgrimesiscf(d) 3691553Srgrimes struct dirent *d; 3701553Srgrimes{ 3711553Srgrimes return(d->d_name[0] == 'c' && d->d_name[1] == 'f'); 3721553Srgrimes} 37330407Sjoerg 37430407Sjoergvoid 37530407Sjoergalarmhandler(signo) 37630407Sjoerg{ 37730407Sjoerg /* ignored */ 37830407Sjoerg} 379