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