122439Sdist /*
261840Sbostic * Copyright (c) 1983, 1993
361840Sbostic * The Regents of the University of California. All rights reserved.
434203Sbostic *
556243Selan * %sccs.include.redist.c%
622439Sdist */
722439Sdist
813955Ssam #ifndef lint
9*69009Stef static char sccsid[] = "@(#)rmjob.c 8.2 (Berkeley) 04/28/95";
1034203Sbostic #endif /* not lint */
1113955Ssam
1255470Sbostic #include <sys/param.h>
1312112Sralph
1455470Sbostic #include <signal.h>
1555470Sbostic #include <errno.h>
1655470Sbostic #include <dirent.h>
1755470Sbostic #include <unistd.h>
1855470Sbostic #include <stdlib.h>
1955470Sbostic #include <stdio.h>
2055470Sbostic #include <string.h>
2155470Sbostic #include <ctype.h>
2212112Sralph #include "lp.h"
2355470Sbostic #include "lp.local.h"
2437968Sbostic #include "pathnames.h"
2512112Sralph
2612112Sralph /*
2755470Sbostic * rmjob - remove the specified jobs from the queue.
2855470Sbostic */
2955470Sbostic
3055470Sbostic /*
3112112Sralph * Stuff for handling lprm specifications
3212112Sralph */
3312112Sralph extern char *user[]; /* users to process */
3412112Sralph extern int users; /* # of users in user array */
3512112Sralph extern int requ[]; /* job number of spool entries */
3612112Sralph extern int requests; /* # of spool requests */
3712877Sralph extern char *person; /* name of person doing lprm */
3812112Sralph
3956120Selan static char root[] = "root";
4056120Selan static int all = 0; /* eliminate all files (root only) */
4156120Selan static int cur_daemon; /* daemon's pid */
4256120Selan static char current[40]; /* active control file name */
4312112Sralph
4455470Sbostic void
rmjob()4512112Sralph rmjob()
4612112Sralph {
4712112Sralph register int i, nitems;
4812112Sralph int assasinated = 0;
4955470Sbostic struct dirent **files;
5038736Stef char *cp;
5112112Sralph
5256120Selan if ((i = cgetent(&bp, printcapdb, printer)) == -2)
5356120Selan fatal("can't open printer description file");
5456120Selan else if (i == -1)
5512112Sralph fatal("unknown printer");
5656120Selan else if (i == -3)
5756120Selan fatal("potential reference loop detected in printcap file");
5856120Selan if (cgetstr(bp, "lp", &LP) < 0)
5956120Selan LP = _PATH_DEFDEVLP;
6056120Selan if (cgetstr(bp, "rp", &RP) < 0)
6156120Selan RP = DEFLP;
6256120Selan if (cgetstr(bp, "sd", &SD) < 0)
6337968Sbostic SD = _PATH_DEFSPOOL;
6456120Selan if (cgetstr(bp,"lo", &LO) < 0)
6512112Sralph LO = DEFLOCK;
6656120Selan cgetstr(bp, "rm", &RM);
6738736Stef if (cp = checkremote())
6838736Stef printf("Warning: %s\n", cp);
6912112Sralph
7012112Sralph /*
7112112Sralph * If the format was `lprm -' and the user isn't the super-user,
7212112Sralph * then fake things to look like he said `lprm user'.
7312112Sralph */
7412112Sralph if (users < 0) {
7512112Sralph if (getuid() == 0)
7612112Sralph all = 1; /* all files in local queue */
7712112Sralph else {
7812112Sralph user[0] = person;
7912112Sralph users = 1;
8012112Sralph }
8112112Sralph }
8212112Sralph if (!strcmp(person, "-all")) {
8312112Sralph if (from == host)
8412112Sralph fatal("The login name \"-all\" is reserved");
8512112Sralph all = 1; /* all those from 'from' */
8612112Sralph person = root;
8712112Sralph }
8812112Sralph
8912112Sralph if (chdir(SD) < 0)
9012112Sralph fatal("cannot chdir to spool directory");
9112112Sralph if ((nitems = scandir(".", &files, iscf, NULL)) < 0)
9212112Sralph fatal("cannot access spool directory");
9312112Sralph
9412112Sralph if (nitems) {
9512112Sralph /*
9612112Sralph * Check for an active printer daemon (in which case we
9712112Sralph * kill it if it is reading our file) then remove stuff
9812112Sralph * (after which we have to restart the daemon).
9912112Sralph */
10012112Sralph if (lockchk(LO) && chk(current)) {
10112112Sralph assasinated = kill(cur_daemon, SIGINT) == 0;
10212112Sralph if (!assasinated)
10312112Sralph fatal("cannot kill printer daemon");
10412112Sralph }
10512112Sralph /*
10612112Sralph * process the files
10712112Sralph */
10812112Sralph for (i = 0; i < nitems; i++)
10912112Sralph process(files[i]->d_name);
11012112Sralph }
11138736Stef rmremote();
11212112Sralph /*
11312112Sralph * Restart the printer daemon if it was killed
11412112Sralph */
11515828Sralph if (assasinated && !startdaemon(printer))
11612112Sralph fatal("cannot restart printer daemon\n");
11712112Sralph exit(0);
11812112Sralph }
11912112Sralph
12012112Sralph /*
12112112Sralph * Process a lock file: collect the pid of the active
12212112Sralph * daemon and the file name of the active spool entry.
12312112Sralph * Return boolean indicating existence of a lock file.
12412112Sralph */
12555470Sbostic int
lockchk(s)12612112Sralph lockchk(s)
12712112Sralph char *s;
12812112Sralph {
12912112Sralph register FILE *fp;
13012112Sralph register int i, n;
13112112Sralph
13212112Sralph if ((fp = fopen(s, "r")) == NULL)
13312112Sralph if (errno == EACCES)
13412112Sralph fatal("can't access lock file");
13512112Sralph else
13612112Sralph return(0);
13713443Sralph if (!getline(fp)) {
13812112Sralph (void) fclose(fp);
13912112Sralph return(0); /* no daemon present */
14012112Sralph }
14112112Sralph cur_daemon = atoi(line);
14213443Sralph if (kill(cur_daemon, 0) < 0) {
14313443Sralph (void) fclose(fp);
14413443Sralph return(0); /* no daemon present */
14513443Sralph }
14612112Sralph for (i = 1; (n = fread(current, sizeof(char), sizeof(current), fp)) <= 0; i++) {
14712527Sralph if (i > 5) {
14812112Sralph n = 1;
14912112Sralph break;
15012112Sralph }
15112112Sralph sleep(i);
15212112Sralph }
15312112Sralph current[n-1] = '\0';
15412112Sralph (void) fclose(fp);
15512112Sralph return(1);
15612112Sralph }
15712112Sralph
15812112Sralph /*
15912112Sralph * Process a control file.
16012112Sralph */
16155470Sbostic void
process(file)16212112Sralph process(file)
16312112Sralph char *file;
16412112Sralph {
16512112Sralph FILE *cfp;
16612112Sralph
16712112Sralph if (!chk(file))
16812112Sralph return;
16912112Sralph if ((cfp = fopen(file, "r")) == NULL)
17012112Sralph fatal("cannot open %s", file);
17116759Sralph while (getline(cfp)) {
17212112Sralph switch (line[0]) {
17312112Sralph case 'U': /* unlink associated files */
17412112Sralph if (from != host)
17512112Sralph printf("%s: ", host);
17612112Sralph printf(unlink(line+1) ? "cannot dequeue %s\n" :
17712112Sralph "%s dequeued\n", line+1);
17812112Sralph }
17912112Sralph }
18012112Sralph (void) fclose(cfp);
18112112Sralph if (from != host)
18212112Sralph printf("%s: ", host);
18312112Sralph printf(unlink(file) ? "cannot dequeue %s\n" : "%s dequeued\n", file);
18412112Sralph }
18512112Sralph
18612112Sralph /*
18712112Sralph * Do the dirty work in checking
18812112Sralph */
18955470Sbostic int
chk(file)19012112Sralph chk(file)
19112112Sralph char *file;
19212112Sralph {
19312112Sralph register int *r, n;
19412112Sralph register char **u, *cp;
19512112Sralph FILE *cfp;
19612112Sralph
19715543Sralph /*
19815543Sralph * Check for valid cf file name (mostly checking current).
19915543Sralph */
20015543Sralph if (strlen(file) < 7 || file[0] != 'c' || file[1] != 'f')
20115543Sralph return(0);
20215543Sralph
20312112Sralph if (all && (from == host || !strcmp(from, file+6)))
20412112Sralph return(1);
20512112Sralph
20612112Sralph /*
20712112Sralph * get the owner's name from the control file.
20812112Sralph */
20912112Sralph if ((cfp = fopen(file, "r")) == NULL)
21012112Sralph return(0);
21112112Sralph while (getline(cfp)) {
21212112Sralph if (line[0] == 'P')
21312112Sralph break;
21412112Sralph }
21512112Sralph (void) fclose(cfp);
21612112Sralph if (line[0] != 'P')
21712112Sralph return(0);
21812112Sralph
21912112Sralph if (users == 0 && requests == 0)
22012112Sralph return(!strcmp(file, current) && isowner(line+1, file));
22112112Sralph /*
22212112Sralph * Check the request list
22312112Sralph */
22412112Sralph for (n = 0, cp = file+3; isdigit(*cp); )
22512112Sralph n = n * 10 + (*cp++ - '0');
22612112Sralph for (r = requ; r < &requ[requests]; r++)
22712112Sralph if (*r == n && isowner(line+1, file))
22812112Sralph return(1);
22912112Sralph /*
23012112Sralph * Check to see if it's in the user list
23112112Sralph */
23212112Sralph for (u = user; u < &user[users]; u++)
23312112Sralph if (!strcmp(*u, line+1) && isowner(line+1, file))
23412112Sralph return(1);
23512112Sralph return(0);
23612112Sralph }
23712112Sralph
23812112Sralph /*
23912112Sralph * If root is removing a file on the local machine, allow it.
24012433Sralph * If root is removing a file from a remote machine, only allow
24112433Sralph * files sent from the remote machine to be removed.
24212112Sralph * Normal users can only remove the file from where it was sent.
24312112Sralph */
24455470Sbostic int
isowner(owner,file)24512112Sralph isowner(owner, file)
24612112Sralph char *owner, *file;
24712112Sralph {
24812433Sralph if (!strcmp(person, root) && (from == host || !strcmp(from, file+6)))
24912433Sralph return(1);
25012433Sralph if (!strcmp(person, owner) && !strcmp(from, file+6))
25112433Sralph return(1);
25212433Sralph if (from != host)
25312433Sralph printf("%s: ", host);
25412433Sralph printf("%s: Permission denied\n", file);
25512433Sralph return(0);
25612112Sralph }
25712112Sralph
25812112Sralph /*
25912112Sralph * Check to see if we are sending files to a remote machine. If we are,
26012112Sralph * then try removing files on the remote machine.
26112112Sralph */
26255470Sbostic void
rmremote()26338736Stef rmremote()
26412112Sralph {
26512112Sralph register char *cp;
26612112Sralph register int i, rem;
26712112Sralph char buf[BUFSIZ];
26812112Sralph
269*69009Stef if (!remote)
27012112Sralph return; /* not sending to a remote machine */
27112112Sralph
27212433Sralph /*
27312433Sralph * Flush stdout so the user can see what has been deleted
27412433Sralph * while we wait (possibly) for the connection.
27512433Sralph */
27612433Sralph fflush(stdout);
27712433Sralph
27855470Sbostic (void)snprintf(buf, sizeof(buf), "\5%s %s", RP, all ? "-all" : person);
27912112Sralph cp = buf;
28012112Sralph for (i = 0; i < users; i++) {
28112112Sralph cp += strlen(cp);
28212112Sralph *cp++ = ' ';
28312112Sralph strcpy(cp, user[i]);
28412112Sralph }
28512112Sralph for (i = 0; i < requests; i++) {
28612112Sralph cp += strlen(cp);
28712112Sralph (void) sprintf(cp, " %d", requ[i]);
28812112Sralph }
28912112Sralph strcat(cp, "\n");
290*69009Stef rem = getport(RM, 0);
29112112Sralph if (rem < 0) {
29212112Sralph if (from != host)
29312112Sralph printf("%s: ", host);
29412112Sralph printf("connection to %s is down\n", RM);
29512112Sralph } else {
29612112Sralph i = strlen(buf);
29712112Sralph if (write(rem, buf, i) != i)
29812112Sralph fatal("Lost connection");
29912112Sralph while ((i = read(rem, buf, sizeof(buf))) > 0)
30012112Sralph (void) fwrite(buf, 1, i, stdout);
30112112Sralph (void) close(rem);
30212112Sralph }
30312112Sralph }
30412112Sralph
30512112Sralph /*
30612112Sralph * Return 1 if the filename begins with 'cf'
30712112Sralph */
30855470Sbostic int
iscf(d)30912112Sralph iscf(d)
31055470Sbostic struct dirent *d;
31112112Sralph {
31212112Sralph return(d->d_name[0] == 'c' && d->d_name[1] == 'f');
31312112Sralph }
314