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