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