summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorgad <gad@FreeBSD.org>2004-12-31 00:36:28 +0000
committergad <gad@FreeBSD.org>2004-12-31 00:36:28 +0000
commit6a6737d3e1d2c73186dbd83388444f40910039b4 (patch)
tree5a13f7ae5fa47be23af1a8eeccb26ef7de7d4fb5 /usr.sbin
parente1d1aaa012c9d5a1a1ab782daafff83fbba24197 (diff)
downloadFreeBSD-src-6a6737d3e1d2c73186dbd83388444f40910039b4.zip
FreeBSD-src-6a6737d3e1d2c73186dbd83388444f40910039b4.tar.gz
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
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/lpr/common_source/common.c55
-rw-r--r--usr.sbin/lpr/common_source/displayq.c15
-rw-r--r--usr.sbin/lpr/common_source/lp.h2
-rw-r--r--usr.sbin/lpr/common_source/matchjobs.c19
-rw-r--r--usr.sbin/lpr/common_source/rmjob.c25
5 files changed, 79 insertions, 37 deletions
diff --git a/usr.sbin/lpr/common_source/common.c b/usr.sbin/lpr/common_source/common.c
index d2ffb6a..d28ac1f 100644
--- a/usr.sbin/lpr/common_source/common.c
+++ b/usr.sbin/lpr/common_source/common.c
@@ -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>
@@ -73,6 +74,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.
* Returns 0 at EOF or the number of characters read.
@@ -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)
diff --git a/usr.sbin/lpr/common_source/displayq.c b/usr.sbin/lpr/common_source/displayq.c
index cdac70c..6c03621 100644
--- a/usr.sbin/lpr/common_source/displayq.c
+++ b/usr.sbin/lpr/common_source/displayq.c
@@ -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);
}
diff --git a/usr.sbin/lpr/common_source/lp.h b/usr.sbin/lpr/common_source/lp.h
index fea03b9..891ed2f 100644
--- a/usr.sbin/lpr/common_source/lp.h
+++ b/usr.sbin/lpr/common_source/lp.h
@@ -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);
diff --git a/usr.sbin/lpr/common_source/matchjobs.c b/usr.sbin/lpr/common_source/matchjobs.c
index eeeb0d4..de572f8 100644
--- a/usr.sbin/lpr/common_source/matchjobs.c
+++ b/usr.sbin/lpr/common_source/matchjobs.c
@@ -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;
diff --git a/usr.sbin/lpr/common_source/rmjob.c b/usr.sbin/lpr/common_source/rmjob.c
index 589117a..d6fd614 100644
--- a/usr.sbin/lpr/common_source/rmjob.c
+++ b/usr.sbin/lpr/common_source/rmjob.c
@@ -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);
OpenPOWER on IntegriCloud