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