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