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