Fix so all parts of lpd, lpc, lpq, and lprm will use the same algorithm
for calculating the job number for a job based on the control-file name. We might receive cf-files named by other implementations of lpr, where the job number shown by lpq would not match the job number that other commands expected for the same name. This also uses a newer algorithm for determining a job number, to avoid problems caused when a control-file is named using an IP address, instead of the hostname. This also moved the declaration if isowner() from lp.h to rmjob.c. When I went to change the parameters, I noticed that rmjob.c was the only source file which uses it. MFC after: 2 weeks
This commit is contained in:
parent
fff3e23824
commit
c547dbe854
@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@ -72,6 +73,13 @@ extern uid_t uid, euid;
|
||||
|
||||
static int compar(const void *_p1, const void *_p2);
|
||||
|
||||
/*
|
||||
* isdigit() takes a parameter of 'int', but expect values in the range
|
||||
* of unsigned char. Define a wrapper which takes a value of type 'char',
|
||||
* whether signed or unsigned, and ensure it ends up in the right range.
|
||||
*/
|
||||
#define isdigitch(Anychar) isdigit((u_char)(Anychar))
|
||||
|
||||
/*
|
||||
* Getline reads a line from the control file cfp, removes tabs, converts
|
||||
* new-line to null and leaves it in line.
|
||||
@ -207,6 +215,53 @@ compar(const void *p1, const void *p2)
|
||||
return (strcmp(qe1->job_cfname, qe2->job_cfname));
|
||||
}
|
||||
|
||||
/*
|
||||
* A simple routine to determine the job number for a print job based on
|
||||
* the name of its control file. The algorithm used here may look odd, but
|
||||
* the main issue is that all parts of `lpd', `lpc', `lpq' & `lprm' must be
|
||||
* using the same algorithm, whatever that algorithm may be. If the caller
|
||||
* provides a non-null value for ''hostpp', then this returns a pointer to
|
||||
* the start of the hostname (or IP address?) as found in the filename.
|
||||
*
|
||||
* Algorithm: The standard `cf' file has the job number start in position 4,
|
||||
* but some implementations have that as an extra file-sequence letter, and
|
||||
* start the job number in position 5. The job number is usually three bytes,
|
||||
* but may be as many as five. Confusing matters still more, some Windows
|
||||
* print servers will append an IP address to the job number, instead of
|
||||
* the expected hostname. So, if the job number ends with a '.', then
|
||||
* assume the correct jobnum value is the first three digits.
|
||||
*/
|
||||
int
|
||||
calc_jobnum(const char *cfname, const char **hostpp)
|
||||
{
|
||||
int jnum;
|
||||
const char *cp, *numstr, *hoststr;
|
||||
|
||||
numstr = cfname + 3;
|
||||
if (!isdigitch(*numstr))
|
||||
numstr++;
|
||||
jnum = 0;
|
||||
for (cp = numstr; (cp < numstr + 5) && isdigitch(*cp); cp++)
|
||||
jnum = jnum * 10 + (*cp - '0');
|
||||
hoststr = cp;
|
||||
|
||||
/*
|
||||
* If the filename was built with an IP number instead of a hostname,
|
||||
* then recalculate using only the first three digits found.
|
||||
*/
|
||||
while(isdigitch(*cp))
|
||||
cp++;
|
||||
if (*cp == '.') {
|
||||
jnum = 0;
|
||||
for (cp = numstr; (cp < numstr + 3) && isdigitch(*cp); cp++)
|
||||
jnum = jnum * 10 + (*cp - '0');
|
||||
hoststr = cp;
|
||||
}
|
||||
if (hostpp != NULL)
|
||||
*hostpp = hoststr;
|
||||
return (jnum);
|
||||
}
|
||||
|
||||
/* sleep n milliseconds */
|
||||
void
|
||||
delay(int millisec)
|
||||
|
@ -286,7 +286,7 @@ header(void)
|
||||
void
|
||||
inform(const struct printer *pp, char *cf)
|
||||
{
|
||||
register int copycnt;
|
||||
int copycnt, jnum;
|
||||
char savedname[MAXPATHLEN+1];
|
||||
FILE *cfp;
|
||||
|
||||
@ -318,6 +318,7 @@ inform(const struct printer *pp, char *cf)
|
||||
copycnt = 0;
|
||||
file[0] = '\0';
|
||||
savedname[0] = '\0';
|
||||
jnum = calc_jobnum(cf, NULL);
|
||||
while (getline(cfp)) {
|
||||
switch (line[0]) {
|
||||
case 'P': /* Was this file specified in the user's list? */
|
||||
@ -335,7 +336,7 @@ inform(const struct printer *pp, char *cf)
|
||||
col = 0;
|
||||
prank(rank);
|
||||
blankfill(OWNCOL);
|
||||
printf("%-10s %-3d ", line+1, atoi(cf+3));
|
||||
printf("%-10s %-3d ", line+1, jnum);
|
||||
col += 16;
|
||||
first = 1;
|
||||
}
|
||||
@ -383,8 +384,9 @@ inform(const struct printer *pp, char *cf)
|
||||
int
|
||||
inlist(char *uname, char *cfile)
|
||||
{
|
||||
register int *r, n;
|
||||
register char **u, *cp;
|
||||
int *r, jnum;
|
||||
char **u;
|
||||
const char *cfhost;
|
||||
|
||||
if (users == 0 && requests == 0)
|
||||
return(1);
|
||||
@ -397,10 +399,9 @@ inlist(char *uname, char *cfile)
|
||||
/*
|
||||
* Check the request list
|
||||
*/
|
||||
for (n = 0, cp = cfile+3; isdigit(*cp); )
|
||||
n = n * 10 + (*cp++ - '0');
|
||||
jnum = calc_jobnum(cfile, &cfhost);
|
||||
for (r = requ; r < &requ[requests]; r++)
|
||||
if (*r == n && !strcmp(cp, from_host))
|
||||
if (*r == jnum && !strcmp(cfhost, from_host))
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
@ -259,6 +259,7 @@ __BEGIN_DECLS
|
||||
struct dirent;
|
||||
|
||||
void blankfill(int _tocol);
|
||||
int calc_jobnum(const char *_cfname, const char **_hostpp);
|
||||
char *checkremote(struct printer *_pp);
|
||||
int chk(char *_file);
|
||||
void closeallfds(int _start);
|
||||
@ -280,7 +281,6 @@ void init_printer(struct printer *_pp);
|
||||
void init_request(struct request *_rp);
|
||||
int inlist(char *_uname, char *_cfile);
|
||||
int iscf(struct dirent *_d);
|
||||
int isowner(char *_owner, char *_file);
|
||||
void ldump(const char *_nfile, const char *_datafile, int _copies);
|
||||
void lastprinter(void);
|
||||
int lockchk(struct printer *_pp, char *_slockf);
|
||||
|
@ -401,7 +401,7 @@ static int
|
||||
match_jobspec(struct jobqueue *jq, struct jobspec *jspec)
|
||||
{
|
||||
struct cjobinfo *cfinf;
|
||||
char *cp, *cf_numstr, *cf_hoststr;
|
||||
const char *cf_hoststr;
|
||||
int jnum, match;
|
||||
|
||||
#if DEBUG_SCANJS
|
||||
@ -418,22 +418,7 @@ match_jobspec(struct jobqueue *jq, struct jobspec *jspec)
|
||||
if (jq->job_matched)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* The standard `cf' file has the job number start in position 4,
|
||||
* but some implementations have that as an extra file-sequence
|
||||
* letter, and start the job number in position 5. The job
|
||||
* number is usually three bytes, but may be as many as five.
|
||||
*
|
||||
* XXX - All this nonsense should really be handled in a single
|
||||
* place, like getq()...
|
||||
*/
|
||||
cf_numstr = jq->job_cfname + 3;
|
||||
if (!isdigitch(*cf_numstr))
|
||||
cf_numstr++;
|
||||
jnum = 0;
|
||||
for (cp = cf_numstr; (cp < cf_numstr + 5) && isdigitch(*cp); cp++)
|
||||
jnum = jnum * 10 + (*cp - '0');
|
||||
cf_hoststr = cp;
|
||||
jnum = calc_jobnum(jq->job_cfname, &cf_hoststr);
|
||||
cfinf = NULL;
|
||||
match = 0; /* assume the job will not match */
|
||||
jspec->matcheduser = NULL;
|
||||
|
@ -76,6 +76,7 @@ extern uid_t uid, euid; /* real and effective user id's */
|
||||
|
||||
static void alarmhandler(int _signo);
|
||||
static void do_unlink(char *_file);
|
||||
static int isowner(char *_owner, char *_file, const char *_cfhost);
|
||||
|
||||
void
|
||||
rmjob(const char *printer)
|
||||
@ -233,8 +234,9 @@ do_unlink(char *file)
|
||||
int
|
||||
chk(char *file)
|
||||
{
|
||||
register int *r, n;
|
||||
register char **u, *cp;
|
||||
int *r, jnum;
|
||||
char **u;
|
||||
const char *cfhost;
|
||||
FILE *cfp;
|
||||
|
||||
/*
|
||||
@ -243,7 +245,8 @@ chk(char *file)
|
||||
if (strlen(file) < 7 || file[0] != 'c' || file[1] != 'f')
|
||||
return(0);
|
||||
|
||||
if (all && (from_host == local_host || !strcmp(from_host, file+6)))
|
||||
jnum = calc_jobnum(file, &cfhost);
|
||||
if (all && (from_host == local_host || !strcmp(from_host, cfhost)))
|
||||
return(1);
|
||||
|
||||
/*
|
||||
@ -262,20 +265,18 @@ chk(char *file)
|
||||
return(0);
|
||||
|
||||
if (users == 0 && requests == 0)
|
||||
return(!strcmp(file, current) && isowner(line+1, file));
|
||||
return(!strcmp(file, current) && isowner(line+1, file, cfhost));
|
||||
/*
|
||||
* Check the request list
|
||||
*/
|
||||
for (n = 0, cp = file+3; isdigit(*cp); )
|
||||
n = n * 10 + (*cp++ - '0');
|
||||
for (r = requ; r < &requ[requests]; r++)
|
||||
if (*r == n && isowner(line+1, file))
|
||||
if (*r == jnum && isowner(line+1, file, cfhost))
|
||||
return(1);
|
||||
/*
|
||||
* Check to see if it's in the user list
|
||||
*/
|
||||
for (u = user; u < &user[users]; u++)
|
||||
if (!strcmp(*u, line+1) && isowner(line+1, file))
|
||||
if (!strcmp(*u, line+1) && isowner(line+1, file, cfhost))
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
@ -286,13 +287,13 @@ chk(char *file)
|
||||
* files sent from the remote machine to be removed.
|
||||
* Normal users can only remove the file from where it was sent.
|
||||
*/
|
||||
int
|
||||
isowner(char *owner, char *file)
|
||||
static int
|
||||
isowner(char *owner, char *file, const char *cfhost)
|
||||
{
|
||||
if (!strcmp(person, root) && (from_host == local_host ||
|
||||
!strcmp(from_host, file+6)))
|
||||
!strcmp(from_host, cfhost)))
|
||||
return (1);
|
||||
if (!strcmp(person, owner) && !strcmp(from_host, file+6))
|
||||
if (!strcmp(person, owner) && !strcmp(from_host, cfhost))
|
||||
return (1);
|
||||
if (from_host != local_host)
|
||||
printf("%s: ", local_host);
|
||||
|
Loading…
x
Reference in New Issue
Block a user