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