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