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