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