rmjob.c revision 15648
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 3515648Sjoergstatic char sccsid[] = "@(#)rmjob.c 8.2 (Berkeley) 4/28/95"; 361553Srgrimes#endif /* not lint */ 371553Srgrimes 381553Srgrimes#include <sys/param.h> 391553Srgrimes 401553Srgrimes#include <signal.h> 411553Srgrimes#include <errno.h> 421553Srgrimes#include <dirent.h> 431553Srgrimes#include <unistd.h> 441553Srgrimes#include <stdlib.h> 451553Srgrimes#include <stdio.h> 461553Srgrimes#include <string.h> 471553Srgrimes#include <ctype.h> 481553Srgrimes#include "lp.h" 491553Srgrimes#include "lp.local.h" 501553Srgrimes#include "pathnames.h" 511553Srgrimes 521553Srgrimes/* 531553Srgrimes * rmjob - remove the specified jobs from the queue. 541553Srgrimes */ 551553Srgrimes 561553Srgrimes/* 571553Srgrimes * Stuff for handling lprm specifications 581553Srgrimes */ 591553Srgrimesextern char *user[]; /* users to process */ 601553Srgrimesextern int users; /* # of users in user array */ 611553Srgrimesextern int requ[]; /* job number of spool entries */ 621553Srgrimesextern int requests; /* # of spool requests */ 631553Srgrimesextern char *person; /* name of person doing lprm */ 641553Srgrimes 651553Srgrimesstatic char root[] = "root"; 661553Srgrimesstatic int all = 0; /* eliminate all files (root only) */ 671553Srgrimesstatic int cur_daemon; /* daemon's pid */ 681553Srgrimesstatic char current[40]; /* active control file name */ 691553Srgrimes 701553Srgrimesvoid 711553Srgrimesrmjob() 721553Srgrimes{ 731553Srgrimes register int i, nitems; 741553Srgrimes int assasinated = 0; 751553Srgrimes struct dirent **files; 761553Srgrimes char *cp; 771553Srgrimes 781553Srgrimes if ((i = cgetent(&bp, printcapdb, printer)) == -2) 791553Srgrimes fatal("can't open printer description file"); 801553Srgrimes else if (i == -1) 811553Srgrimes fatal("unknown printer"); 821553Srgrimes else if (i == -3) 831553Srgrimes fatal("potential reference loop detected in printcap file"); 841553Srgrimes if (cgetstr(bp, "lp", &LP) < 0) 851553Srgrimes LP = _PATH_DEFDEVLP; 861553Srgrimes if (cgetstr(bp, "rp", &RP) < 0) 871553Srgrimes RP = DEFLP; 881553Srgrimes if (cgetstr(bp, "sd", &SD) < 0) 891553Srgrimes SD = _PATH_DEFSPOOL; 901553Srgrimes if (cgetstr(bp,"lo", &LO) < 0) 911553Srgrimes LO = DEFLOCK; 921553Srgrimes cgetstr(bp, "rm", &RM); 931553Srgrimes if (cp = checkremote()) 941553Srgrimes printf("Warning: %s\n", cp); 951553Srgrimes 961553Srgrimes /* 971553Srgrimes * If the format was `lprm -' and the user isn't the super-user, 981553Srgrimes * then fake things to look like he said `lprm user'. 991553Srgrimes */ 1001553Srgrimes if (users < 0) { 1011553Srgrimes if (getuid() == 0) 1021553Srgrimes all = 1; /* all files in local queue */ 1031553Srgrimes else { 1041553Srgrimes user[0] = person; 1051553Srgrimes users = 1; 1061553Srgrimes } 1071553Srgrimes } 1081553Srgrimes if (!strcmp(person, "-all")) { 1091553Srgrimes if (from == host) 1101553Srgrimes fatal("The login name \"-all\" is reserved"); 1111553Srgrimes all = 1; /* all those from 'from' */ 1121553Srgrimes person = root; 1131553Srgrimes } 1141553Srgrimes 1151553Srgrimes if (chdir(SD) < 0) 1161553Srgrimes fatal("cannot chdir to spool directory"); 1171553Srgrimes if ((nitems = scandir(".", &files, iscf, NULL)) < 0) 1181553Srgrimes fatal("cannot access spool directory"); 1191553Srgrimes 1201553Srgrimes if (nitems) { 1211553Srgrimes /* 1221553Srgrimes * Check for an active printer daemon (in which case we 1231553Srgrimes * kill it if it is reading our file) then remove stuff 1241553Srgrimes * (after which we have to restart the daemon). 1251553Srgrimes */ 1261553Srgrimes if (lockchk(LO) && chk(current)) { 1271553Srgrimes assasinated = kill(cur_daemon, SIGINT) == 0; 1281553Srgrimes if (!assasinated) 1291553Srgrimes fatal("cannot kill printer daemon"); 1301553Srgrimes } 1311553Srgrimes /* 1321553Srgrimes * process the files 1331553Srgrimes */ 1341553Srgrimes for (i = 0; i < nitems; i++) 1351553Srgrimes process(files[i]->d_name); 1361553Srgrimes } 1371553Srgrimes rmremote(); 1381553Srgrimes /* 1391553Srgrimes * Restart the printer daemon if it was killed 1401553Srgrimes */ 1411553Srgrimes if (assasinated && !startdaemon(printer)) 1421553Srgrimes fatal("cannot restart printer daemon\n"); 1431553Srgrimes exit(0); 1441553Srgrimes} 1451553Srgrimes 1461553Srgrimes/* 1471553Srgrimes * Process a lock file: collect the pid of the active 1481553Srgrimes * daemon and the file name of the active spool entry. 1491553Srgrimes * Return boolean indicating existence of a lock file. 1501553Srgrimes */ 1511553Srgrimesint 1521553Srgrimeslockchk(s) 1531553Srgrimes char *s; 1541553Srgrimes{ 1551553Srgrimes register FILE *fp; 1561553Srgrimes register int i, n; 1571553Srgrimes 1581553Srgrimes if ((fp = fopen(s, "r")) == NULL) 1591553Srgrimes if (errno == EACCES) 1601553Srgrimes fatal("can't access lock file"); 1611553Srgrimes else 1621553Srgrimes return(0); 1631553Srgrimes if (!getline(fp)) { 1641553Srgrimes (void) fclose(fp); 1651553Srgrimes return(0); /* no daemon present */ 1661553Srgrimes } 1671553Srgrimes cur_daemon = atoi(line); 1681553Srgrimes if (kill(cur_daemon, 0) < 0) { 1691553Srgrimes (void) fclose(fp); 1701553Srgrimes return(0); /* no daemon present */ 1711553Srgrimes } 1721553Srgrimes for (i = 1; (n = fread(current, sizeof(char), sizeof(current), fp)) <= 0; i++) { 1731553Srgrimes if (i > 5) { 1741553Srgrimes n = 1; 1751553Srgrimes break; 1761553Srgrimes } 1771553Srgrimes sleep(i); 1781553Srgrimes } 1791553Srgrimes current[n-1] = '\0'; 1801553Srgrimes (void) fclose(fp); 1811553Srgrimes return(1); 1821553Srgrimes} 1831553Srgrimes 1841553Srgrimes/* 1851553Srgrimes * Process a control file. 1861553Srgrimes */ 1871553Srgrimesvoid 1881553Srgrimesprocess(file) 1891553Srgrimes char *file; 1901553Srgrimes{ 1911553Srgrimes FILE *cfp; 1921553Srgrimes 1931553Srgrimes if (!chk(file)) 1941553Srgrimes return; 1951553Srgrimes if ((cfp = fopen(file, "r")) == NULL) 1961553Srgrimes fatal("cannot open %s", file); 1971553Srgrimes while (getline(cfp)) { 1981553Srgrimes switch (line[0]) { 1991553Srgrimes case 'U': /* unlink associated files */ 2001553Srgrimes if (from != host) 2011553Srgrimes printf("%s: ", host); 2021553Srgrimes printf(unlink(line+1) ? "cannot dequeue %s\n" : 2031553Srgrimes "%s dequeued\n", line+1); 2041553Srgrimes } 2051553Srgrimes } 2061553Srgrimes (void) fclose(cfp); 2071553Srgrimes if (from != host) 2081553Srgrimes printf("%s: ", host); 2091553Srgrimes printf(unlink(file) ? "cannot dequeue %s\n" : "%s dequeued\n", file); 2101553Srgrimes} 2111553Srgrimes 2121553Srgrimes/* 2131553Srgrimes * Do the dirty work in checking 2141553Srgrimes */ 2151553Srgrimesint 2161553Srgrimeschk(file) 2171553Srgrimes char *file; 2181553Srgrimes{ 2191553Srgrimes register int *r, n; 2201553Srgrimes register char **u, *cp; 2211553Srgrimes FILE *cfp; 2221553Srgrimes 2231553Srgrimes /* 2241553Srgrimes * Check for valid cf file name (mostly checking current). 2251553Srgrimes */ 2261553Srgrimes if (strlen(file) < 7 || file[0] != 'c' || file[1] != 'f') 2271553Srgrimes return(0); 2281553Srgrimes 2291553Srgrimes if (all && (from == host || !strcmp(from, file+6))) 2301553Srgrimes return(1); 2311553Srgrimes 2321553Srgrimes /* 2331553Srgrimes * get the owner's name from the control file. 2341553Srgrimes */ 2351553Srgrimes if ((cfp = fopen(file, "r")) == NULL) 2361553Srgrimes return(0); 2371553Srgrimes while (getline(cfp)) { 2381553Srgrimes if (line[0] == 'P') 2391553Srgrimes break; 2401553Srgrimes } 2411553Srgrimes (void) fclose(cfp); 2421553Srgrimes if (line[0] != 'P') 2431553Srgrimes return(0); 2441553Srgrimes 2451553Srgrimes if (users == 0 && requests == 0) 2461553Srgrimes return(!strcmp(file, current) && isowner(line+1, file)); 2471553Srgrimes /* 2481553Srgrimes * Check the request list 2491553Srgrimes */ 2501553Srgrimes for (n = 0, cp = file+3; isdigit(*cp); ) 2511553Srgrimes n = n * 10 + (*cp++ - '0'); 2521553Srgrimes for (r = requ; r < &requ[requests]; r++) 2531553Srgrimes if (*r == n && isowner(line+1, file)) 2541553Srgrimes return(1); 2551553Srgrimes /* 2561553Srgrimes * Check to see if it's in the user list 2571553Srgrimes */ 2581553Srgrimes for (u = user; u < &user[users]; u++) 2591553Srgrimes if (!strcmp(*u, line+1) && isowner(line+1, file)) 2601553Srgrimes return(1); 2611553Srgrimes return(0); 2621553Srgrimes} 2631553Srgrimes 2641553Srgrimes/* 2651553Srgrimes * If root is removing a file on the local machine, allow it. 2661553Srgrimes * If root is removing a file from a remote machine, only allow 2671553Srgrimes * files sent from the remote machine to be removed. 2681553Srgrimes * Normal users can only remove the file from where it was sent. 2691553Srgrimes */ 2701553Srgrimesint 2711553Srgrimesisowner(owner, file) 2721553Srgrimes char *owner, *file; 2731553Srgrimes{ 2741553Srgrimes if (!strcmp(person, root) && (from == host || !strcmp(from, file+6))) 2751553Srgrimes return(1); 2761553Srgrimes if (!strcmp(person, owner) && !strcmp(from, file+6)) 2771553Srgrimes return(1); 2781553Srgrimes if (from != host) 2791553Srgrimes printf("%s: ", host); 2801553Srgrimes printf("%s: Permission denied\n", file); 2811553Srgrimes return(0); 2821553Srgrimes} 2831553Srgrimes 2841553Srgrimes/* 2851553Srgrimes * Check to see if we are sending files to a remote machine. If we are, 2861553Srgrimes * then try removing files on the remote machine. 2871553Srgrimes */ 2881553Srgrimesvoid 2891553Srgrimesrmremote() 2901553Srgrimes{ 2911553Srgrimes register char *cp; 2921553Srgrimes register int i, rem; 2931553Srgrimes char buf[BUFSIZ]; 2941553Srgrimes 29515648Sjoerg if (!remote) 2961553Srgrimes return; /* not sending to a remote machine */ 2971553Srgrimes 2981553Srgrimes /* 2991553Srgrimes * Flush stdout so the user can see what has been deleted 3001553Srgrimes * while we wait (possibly) for the connection. 3011553Srgrimes */ 3021553Srgrimes fflush(stdout); 3031553Srgrimes 3041553Srgrimes (void)snprintf(buf, sizeof(buf), "\5%s %s", RP, all ? "-all" : person); 3051553Srgrimes cp = buf; 3061553Srgrimes for (i = 0; i < users; i++) { 3071553Srgrimes cp += strlen(cp); 3081553Srgrimes *cp++ = ' '; 3091553Srgrimes strcpy(cp, user[i]); 3101553Srgrimes } 3111553Srgrimes for (i = 0; i < requests; i++) { 3121553Srgrimes cp += strlen(cp); 3131553Srgrimes (void) sprintf(cp, " %d", requ[i]); 3141553Srgrimes } 3151553Srgrimes strcat(cp, "\n"); 31615648Sjoerg rem = getport(RM, 0); 3171553Srgrimes if (rem < 0) { 3181553Srgrimes if (from != host) 3191553Srgrimes printf("%s: ", host); 3201553Srgrimes printf("connection to %s is down\n", RM); 3211553Srgrimes } else { 3221553Srgrimes i = strlen(buf); 3231553Srgrimes if (write(rem, buf, i) != i) 3241553Srgrimes fatal("Lost connection"); 3251553Srgrimes while ((i = read(rem, buf, sizeof(buf))) > 0) 3261553Srgrimes (void) fwrite(buf, 1, i, stdout); 3271553Srgrimes (void) close(rem); 3281553Srgrimes } 3291553Srgrimes} 3301553Srgrimes 3311553Srgrimes/* 3321553Srgrimes * Return 1 if the filename begins with 'cf' 3331553Srgrimes */ 3341553Srgrimesint 3351553Srgrimesiscf(d) 3361553Srgrimes struct dirent *d; 3371553Srgrimes{ 3381553Srgrimes return(d->d_name[0] == 'c' && d->d_name[1] == 'f'); 3391553Srgrimes} 340