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