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